diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000000000..41062f958e4544 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,61 @@ +{ + "root": true, + "env": { + "browser": true, + "node": true, + "es2018": true + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "extends": [ + "mdcs", + "plugin:compat/recommended" + ], + "plugins": [ + "html", + "import" + ], + "settings": { + "polyfills": [ + "WebGL2RenderingContext" + ] + }, + "globals": { + "__THREE_DEVTOOLS__": "readonly", + "potpack": "readonly", + "fflate": "readonly", + "Stats": "readonly", + "XRWebGLBinding": "readonly", + "XRWebGLLayer": "readonly", + "GPUShaderStage": "readonly", + "GPUBufferUsage": "readonly", + "GPUTextureUsage": "readonly", + "GPUTexture": "readonly", + "GPUMapMode": "readonly", + "QUnit": "readonly", + "Ammo": "readonly", + "XRRigidTransform": "readonly", + "XRMediaBinding": "readonly", + "CodeMirror": "readonly", + "esprima": "readonly", + "jsonlint": "readonly" + }, + "rules": { + "no-throw-literal": [ + "error" + ], + "quotes": [ + "error", + "single" + ], + "prefer-const": [ + "error", + { + "destructuring": "any", + "ignoreReadBeforeAssign": false + } + ] + } +} diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000000000..59306918fe3901 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,16 @@ +{ + "extends": [ + "config:base", + ":disableDependencyDashboard" + ], + "timezone": "Asia/Tokyo", + "schedule": ["after 1am and before 7am every monday"], + "packageRules": [ + { + "matchDepTypes": ["devDependencies"], + "matchUpdateTypes": ["patch", "minor", "pin", "digest"], + "groupName": "devDependencies (non-major)", + "automerge": true + } + ] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8bac271f4951b..9146c9936daa21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,80 +17,85 @@ permissions: jobs: lint: - name: "Lint testing" + name: Lint testing runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: 'npm' - - name: Install packages + - name: Install dependencies run: npm ci - name: === Lint testing === run: npm run lint unit: - name: "Unit testing" + name: Unit testing runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: 'npm' - - name: Install packages + - name: Install dependencies run: npm ci - - name: Build - run: npm run build - name: === Unit testing === run: npm run test-unit e2e: - name: "E2E testing" + name: E2E testing runs-on: ${{ matrix.os }} + timeout-minutes: 20 strategy: fail-fast: false matrix: - os: [ windows-latest, ubuntu-latest ] - CI: [ 0, 1, 2, 3, 4, 5, 6, 7 ] + os: [ windows-latest, ubuntu-latest, macos-latest ] + CI: [ 0, 1, 2, 3 ] env: CI: ${{ matrix.CI }} - FORCE_COLOR: 1 steps: - name: Git checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: 'npm' - - name: Install packages + - name: Install dependencies run: npm ci - name: Build run: npm run build - name: === E2E testing === run: npm run test-e2e + - name: Upload output screenshots + uses: actions/upload-artifact@v3 + if: always() + with: + name: Output screenshots + path: test/e2e/output-screenshots + if-no-files-found: ignore e2e-cov: - name: "Examples ready for release" + name: Examples ready for release runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: 'npm' - - name: Install packages + - name: Install dependencies run: npm ci - name: === Examples ready for release === diff --git a/.github/workflows/read-size.yml b/.github/workflows/read-size.yml new file mode 100644 index 00000000000000..16173259cd0efe --- /dev/null +++ b/.github/workflows/read-size.yml @@ -0,0 +1,52 @@ +name: Read size + +on: + pull_request: + paths: + - 'src/**' + - 'package.json' + - 'utils/build/**' + +# This workflow runs in a read-only environment. We can safely checkout +# the PR code here. +# Reference: +# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ +permissions: + contents: read + +jobs: + read-size: + name: Tree-shaking + runs-on: ubuntu-latest + steps: + - name: Git checkout + uses: actions/checkout@v3 + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Build + run: npm run build + - name: === Test tree-shaking === + run: npm run test-treeshake + - name: Read bundle sizes + id: read-size + run: | + FILESIZE=$(stat --format=%s build/three.module.min.js) + gzip -k build/three.module.min.js + FILESIZE_GZIP=$(stat --format=%s build/three.module.min.js.gz) + TREESHAKEN=$(stat --format=%s test/treeshake/index.bundle.min.js) + gzip -k test/treeshake/index.bundle.min.js + TREESHAKEN_GZIP=$(stat --format=%s test/treeshake/index.bundle.min.js.gz) + PR=${{ github.event.pull_request.number }} + + # write the output in a json file to upload it as artifact + node -pe "JSON.stringify({ filesize: $FILESIZE, gzip: $FILESIZE_GZIP, treeshaken: $TREESHAKEN, treeshakenGzip: $TREESHAKEN_GZIP, pr: $PR })" > sizes.json + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: sizes + path: sizes.json diff --git a/.github/workflows/report-size.yml b/.github/workflows/report-size.yml new file mode 100644 index 00000000000000..a1a6782b96f7ca --- /dev/null +++ b/.github/workflows/report-size.yml @@ -0,0 +1,156 @@ +name: Report size + +on: + workflow_run: + workflows: ["Read size"] + types: + - completed + +# This workflow needs to be run with "pull-requests: write" permissions to +# be able to comment on the pull request. We can't checkout the PR code +# in this workflow. +# Reference: +# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ +permissions: + pull-requests: write + +jobs: + report-size: + name: Comment on PR + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' + steps: + - name: Log GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + + # Using actions/download-artifact doesn't work here + # https://github.com/actions/download-artifact/issues/60 + - name: Download artifact + uses: actions/github-script@v6 + id: download-artifact + with: + result-encoding: string + script: | + const fs = require('fs/promises'); + + const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + const matchArtifact = artifacts.data.artifacts.find((artifact) => artifact.name === 'sizes'); + const download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + + await fs.writeFile('sizes.zip', Buffer.from(download.data)); + await exec.exec('unzip sizes.zip'); + const json = await fs.readFile('sizes.json', 'utf8'); + return json; + + # This runs on the base branch of the PR, meaning "dev" + - name: Git checkout + uses: actions/checkout@v3 + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Build + run: npm run build + - name: === Test tree-shaking === + run: npm run test-treeshake + - name: Read sizes + id: read-size + run: | + FILESIZE_BASE=$(stat --format=%s build/three.module.min.js) + gzip -k build/three.module.min.js + FILESIZE_BASE_GZIP=$(stat --format=%s build/three.module.min.js.gz) + TREESHAKEN_BASE=$(stat --format=%s test/treeshake/index.bundle.min.js) + gzip -k test/treeshake/index.bundle.min.js + TREESHAKEN_BASE_GZIP=$(stat --format=%s test/treeshake/index.bundle.min.js.gz) + + # log to console + echo "FILESIZE_BASE=$FILESIZE_BASE" + echo "FILESIZE_BASE_GZIP=$FILESIZE_BASE_GZIP" + echo "TREESHAKEN_BASE=$TREESHAKEN_BASE" + echo "TREESHAKEN_BASE_GZIP=$TREESHAKEN_BASE_GZIP" + + echo "FILESIZE_BASE=$FILESIZE_BASE" >> $GITHUB_OUTPUT + echo "FILESIZE_BASE_GZIP=$FILESIZE_BASE_GZIP" >> $GITHUB_OUTPUT + echo "TREESHAKEN_BASE=$TREESHAKEN_BASE" >> $GITHUB_OUTPUT + echo "TREESHAKEN_BASE_GZIP=$TREESHAKEN_BASE_GZIP" >> $GITHUB_OUTPUT + + - name: Format sizes + id: format + # It's important these are passed as env variables. + # https://securitylab.github.com/research/github-actions-untrusted-input/ + env: + FILESIZE: ${{ fromJSON(steps.download-artifact.outputs.result).filesize }} + FILESIZE_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).gzip }} + FILESIZE_BASE: ${{ steps.read-size.outputs.FILESIZE_BASE }} + FILESIZE_BASE_GZIP: ${{ steps.read-size.outputs.FILESIZE_BASE_GZIP }} + TREESHAKEN: ${{ fromJSON(steps.download-artifact.outputs.result).treeshaken }} + TREESHAKEN_GZIP: ${{ fromJSON(steps.download-artifact.outputs.result).treeshakenGzip }} + TREESHAKEN_BASE: ${{ steps.read-size.outputs.TREESHAKEN_BASE }} + TREESHAKEN_BASE_GZIP: ${{ steps.read-size.outputs.TREESHAKEN_BASE_GZIP }} + run: | + FILESIZE_FORM=$(node ./test/treeshake/utils/format-size.js "$FILESIZE") + FILESIZE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$FILESIZE_GZIP") + FILESIZE_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$FILESIZE_BASE") + FILESIZE_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$FILESIZE_BASE_GZIP") + FILESIZE_DIFF=$(node ./test/treeshake/utils/format-diff.js "$FILESIZE" "$FILESIZE_BASE") + TREESHAKEN_FORM=$(node ./test/treeshake/utils/format-size.js "$TREESHAKEN") + TREESHAKEN_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$TREESHAKEN_GZIP") + TREESHAKEN_BASE_FORM=$(node ./test/treeshake/utils/format-size.js "$TREESHAKEN_BASE") + TREESHAKEN_BASE_GZIP_FORM=$(node ./test/treeshake/utils/format-size.js "$TREESHAKEN_BASE_GZIP") + TREESHAKEN_DIFF=$(node ./test/treeshake/utils/format-diff.js "$TREESHAKEN" "$TREESHAKEN_BASE") + + echo "FILESIZE=$FILESIZE_FORM" >> $GITHUB_OUTPUT + echo "FILESIZE_GZIP=$FILESIZE_GZIP_FORM" >> $GITHUB_OUTPUT + echo "FILESIZE_BASE=$FILESIZE_BASE_FORM" >> $GITHUB_OUTPUT + echo "FILESIZE_BASE_GZIP=$FILESIZE_BASE_GZIP_FORM" >> $GITHUB_OUTPUT + echo "FILESIZE_DIFF=$FILESIZE_DIFF" >> $GITHUB_OUTPUT + echo "TREESHAKEN=$TREESHAKEN_FORM" >> $GITHUB_OUTPUT + echo "TREESHAKEN_GZIP=$TREESHAKEN_GZIP_FORM" >> $GITHUB_OUTPUT + echo "TREESHAKEN_BASE=$TREESHAKEN_BASE_FORM" >> $GITHUB_OUTPUT + echo "TREESHAKEN_BASE_GZIP=$TREESHAKEN_BASE_GZIP_FORM" >> $GITHUB_OUTPUT + echo "TREESHAKEN_DIFF=$TREESHAKEN_DIFF" >> $GITHUB_OUTPUT + + - name: Find existing comment + uses: peter-evans/find-comment@v2 + id: find-comment + with: + issue-number: ${{ fromJSON(steps.download-artifact.outputs.result).pr }} + comment-author: 'github-actions[bot]' + body-includes: Bundle size + - name: Comment on PR + uses: peter-evans/create-or-update-comment@v3 + with: + issue-number: ${{ fromJSON(steps.download-artifact.outputs.result).pr }} + comment-id: ${{ steps.find-comment.outputs.comment-id }} + edit-mode: replace + body: | + ### 📦 Bundle size + + _Full ESM build, minified and gzipped._ + + | Filesize `${{ github.ref_name }}` | Filesize PR | Diff | + |----------|---------|------| + | ${{ steps.format.outputs.FILESIZE_BASE }} (${{ steps.format.outputs.FILESIZE_BASE_GZIP }}) | ${{ steps.format.outputs.FILESIZE }} (${{ steps.format.outputs.FILESIZE_GZIP }}) | ${{ steps.format.outputs.FILESIZE_DIFF }} | + + ### 🌳 Bundle size after tree-shaking + + _Minimal build including a renderer, camera, empty scene, and dependencies._ + + | Filesize `${{ github.ref_name }}` | Filesize PR | Diff | + |----------|---------|------| + | ${{ steps.format.outputs.TREESHAKEN_BASE }} (${{ steps.format.outputs.TREESHAKEN_BASE_GZIP }}) | ${{ steps.format.outputs.TREESHAKEN }} (${{ steps.format.outputs.TREESHAKEN_GZIP }}) | ${{ steps.format.outputs.TREESHAKEN_DIFF }} | diff --git a/.gitignore b/.gitignore index 6895a6a437988c..50df59a8212b6c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,6 @@ test/treeshake/index.bundle.min.js test/treeshake/index-src.bundle.min.js test/treeshake/stats.html test/e2e/chromium +test/e2e/output-screenshots **/node_modules \ No newline at end of file diff --git a/build/three.cjs b/build/three.cjs index 559a30276c06c5..81031f23d5751c 100644 --- a/build/three.cjs +++ b/build/three.cjs @@ -5,7 +5,8 @@ */ 'use strict'; -const REVISION = '150dev'; +const REVISION = '153dev'; + const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; const CullFaceNone = 0; @@ -146,7 +147,9 @@ const AdditiveAnimationBlendMode = 2501; const TrianglesDrawMode = 0; const TriangleStripDrawMode = 1; const TriangleFanDrawMode = 2; +/** @deprecated Use LinearSRGBColorSpace or NoColorSpace in three.js r152+. */ const LinearEncoding = 3000; +/** @deprecated Use SRGBColorSpace in three.js r152+. */ const sRGBEncoding = 3001; const BasicDepthPacking = 3200; const RGBADepthPacking = 3201; @@ -157,6 +160,7 @@ const ObjectSpaceNormalMap = 1; const NoColorSpace = ''; const SRGBColorSpace = 'srgb'; const LinearSRGBColorSpace = 'srgb-linear'; +const DisplayP3ColorSpace = 'display-p3'; const ZeroStencilOp = 0; const KeepStencilOp = 7680; @@ -176,6 +180,15 @@ const NotEqualStencilFunc = 517; const GreaterEqualStencilFunc = 518; const AlwaysStencilFunc = 519; +const NeverCompare = 512; +const LessCompare = 513; +const EqualCompare = 514; +const LessEqualCompare = 515; +const GreaterCompare = 516; +const NotEqualCompare = 517; +const GreaterEqualCompare = 518; +const AlwaysCompare = 519; + const StaticDrawUsage = 35044; const DynamicDrawUsage = 35048; const StreamDrawUsage = 35040; @@ -513,6 +526,10 @@ function denormalize( value, array ) { return value; + case Uint32Array: + + return value / 4294967295.0; + case Uint16Array: return value / 65535.0; @@ -521,6 +538,10 @@ function denormalize( value, array ) { return value / 255.0; + case Int32Array: + + return Math.max( value / 2147483647.0, - 1.0 ); + case Int16Array: return Math.max( value / 32767.0, - 1.0 ); @@ -545,6 +566,10 @@ function normalize( value, array ) { return value; + case Uint32Array: + + return Math.round( value * 4294967295.0 ); + case Uint16Array: return Math.round( value * 65535.0 ); @@ -553,6 +578,10 @@ function normalize( value, array ) { return Math.round( value * 255.0 ); + case Int32Array: + + return Math.round( value * 2147483647.0 ); + case Int16Array: return Math.round( value * 32767.0 ); @@ -569,33 +598,32 @@ function normalize( value, array ) { } -var MathUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, +const MathUtils = { DEG2RAD: DEG2RAD, RAD2DEG: RAD2DEG, - ceilPowerOfTwo: ceilPowerOfTwo, + generateUUID: generateUUID, clamp: clamp, - damp: damp, - degToRad: degToRad, - denormalize: denormalize, euclideanModulo: euclideanModulo, - floorPowerOfTwo: floorPowerOfTwo, - generateUUID: generateUUID, + mapLinear: mapLinear, inverseLerp: inverseLerp, - isPowerOfTwo: isPowerOfTwo, lerp: lerp, - mapLinear: mapLinear, - normalize: normalize, + damp: damp, pingpong: pingpong, - radToDeg: radToDeg, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, randFloat: randFloat, randFloatSpread: randFloatSpread, - randInt: randInt, seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, setQuaternionFromProperEuler: setQuaternionFromProperEuler, - smootherstep: smootherstep, - smoothstep: smoothstep -}); + normalize: normalize, + denormalize: denormalize +}; class Vector2 { @@ -952,6 +980,20 @@ class Vector2 { } + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; + + const theta = this.dot( v ) / denominator; + + // clamp, to handle numerical problems + + return Math.acos( clamp( theta, - 1, 1 ) ); + + } + distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); @@ -1062,7 +1104,7 @@ class Vector2 { class Matrix3 { - constructor() { + constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { Matrix3.prototype.isMatrix3 = true; @@ -1074,6 +1116,12 @@ class Matrix3 { ]; + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); + + } + } set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { @@ -1323,13 +1371,27 @@ class Matrix3 { makeTranslation( x, y ) { - this.set( + if ( x.isVector2 ) { - 1, 0, x, - 0, 1, y, - 0, 0, 1 + this.set( - ); + 1, 0, x.x, + 0, 1, x.y, + 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, x, + 0, 1, y, + 0, 0, 1 + + ); + + } return this; @@ -1465,6 +1527,18 @@ function createElementNS( name ) { } +const _cache = {}; + +function warnOnce( message ) { + + if ( message in _cache ) return; + + _cache[ message ] = true; + + console.warn( message ); + +} + function SRGBToLinear( c ) { return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); @@ -1477,16 +1551,77 @@ function LinearToSRGB( c ) { } -// JavaScript RGB-to-RGB transforms, defined as -// FN[InputColorSpace][OutputColorSpace] callback functions. -const FN = { - [ SRGBColorSpace ]: { [ LinearSRGBColorSpace ]: SRGBToLinear }, - [ LinearSRGBColorSpace ]: { [ SRGBColorSpace ]: LinearToSRGB }, +/** + * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + +const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().fromArray( [ + 0.8224621, 0.0331941, 0.0170827, + 0.1775380, 0.9668058, 0.0723974, + - 0.0000001, 0.0000001, 0.9105199 +] ); + +const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().fromArray( [ + 1.2249401, - 0.0420569, - 0.0196376, + - 0.2249404, 1.0420571, - 0.0786361, + 0.0000001, 0.0000000, 1.0982735 +] ); + +function DisplayP3ToLinearSRGB( color ) { + + // Display P3 uses the sRGB transfer functions + return color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ); + +} + +function LinearSRGBToDisplayP3( color ) { + + // Display P3 uses the sRGB transfer functions + return color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(); + +} + +// Conversions from to Linear-sRGB reference space. +const TO_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertSRGBToLinear(), + [ DisplayP3ColorSpace ]: DisplayP3ToLinearSRGB, +}; + +// Conversions to from Linear-sRGB reference space. +const FROM_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertLinearToSRGB(), + [ DisplayP3ColorSpace ]: LinearSRGBToDisplayP3, }; const ColorManagement = { - legacyMode: true, + enabled: true, + + get legacyMode() { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + return ! this.enabled; + + }, + + set legacyMode( legacyMode ) { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + this.enabled = ! legacyMode; + + }, get workingColorSpace() { @@ -1502,25 +1637,22 @@ const ColorManagement = { convert: function ( color, sourceColorSpace, targetColorSpace ) { - if ( this.legacyMode || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { return color; } - if ( FN[ sourceColorSpace ] && FN[ sourceColorSpace ][ targetColorSpace ] !== undefined ) { - - const fn = FN[ sourceColorSpace ][ targetColorSpace ]; + const sourceToLinear = TO_LINEAR[ sourceColorSpace ]; + const targetFromLinear = FROM_LINEAR[ targetColorSpace ]; - color.r = fn( color.r ); - color.g = fn( color.g ); - color.b = fn( color.b ); + if ( sourceToLinear === undefined || targetFromLinear === undefined ) { - return color; + throw new Error( `Unsupported color space conversion, "${ sourceColorSpace }" to "${ targetColorSpace }".` ); } - throw new Error( 'Unsupported color space conversion.' ); + return targetFromLinear( sourceToLinear( color ) ); }, @@ -1538,3211 +1670,2658 @@ const ColorManagement = { }; -const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, - 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, - 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, - 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, - 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, - 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, - 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, - 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, - 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, - 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, - 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, - 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, - 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, - 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, - 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, - 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, - 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, - 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, - 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, - 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, - 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, - 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, - 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, - 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - -const _rgb$1 = { r: 0, g: 0, b: 0 }; -const _hslA = { h: 0, s: 0, l: 0 }; -const _hslB = { h: 0, s: 0, l: 0 }; - -function hue2rgb( p, q, t ) { - - if ( t < 0 ) t += 1; - if ( t > 1 ) t -= 1; - if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; - if ( t < 1 / 2 ) return q; - if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); - return p; - -} - -function toComponents( source, target ) { - - target.r = source.r; - target.g = source.g; - target.b = source.b; - - return target; +let _canvas; -} +class ImageUtils { -class Color { + static getDataURL( image ) { - constructor( r, g, b ) { + if ( /^data:/i.test( image.src ) ) { - this.isColor = true; + return image.src; - this.r = 1; - this.g = 1; - this.b = 1; + } - if ( g === undefined && b === undefined ) { + if ( typeof HTMLCanvasElement === 'undefined' ) { - // r is THREE.Color, hex or string - return this.set( r ); + return image.src; } - return this.setRGB( r, g, b ); - - } + let canvas; - set( value ) { + if ( image instanceof HTMLCanvasElement ) { - if ( value && value.isColor ) { + canvas = image; - this.copy( value ); + } else { - } else if ( typeof value === 'number' ) { + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); - this.setHex( value ); + _canvas.width = image.width; + _canvas.height = image.height; - } else if ( typeof value === 'string' ) { + const context = _canvas.getContext( '2d' ); - this.setStyle( value ); + if ( image instanceof ImageData ) { - } + context.putImageData( image, 0, 0 ); - return this; + } else { - } + context.drawImage( image, 0, 0, image.width, image.height ); - setScalar( scalar ) { + } - this.r = scalar; - this.g = scalar; - this.b = scalar; + canvas = _canvas; - return this; + } - } + if ( canvas.width > 2048 || canvas.height > 2048 ) { - setHex( hex, colorSpace = SRGBColorSpace ) { + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); - hex = Math.floor( hex ); + return canvas.toDataURL( 'image/jpeg', 0.6 ); - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + return canvas.toDataURL( 'image/png' ); - return this; + } } - setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { - - this.r = r; - this.g = g; - this.b = b; + static sRGBToLinear( image ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - return this; + const canvas = createElementNS( 'canvas' ); - } + canvas.width = image.width; + canvas.height = image.height; - setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); - // h,s,l ranges are in 0.0 - 1.0 - h = euclideanModulo( h, 1 ); - s = clamp( s, 0, 1 ); - l = clamp( l, 0, 1 ); + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; - if ( s === 0 ) { + for ( let i = 0; i < data.length; i ++ ) { - this.r = this.g = this.b = l; + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; - } else { + } - const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - const q = ( 2 * l ) - p; + context.putImageData( imageData, 0, 0 ); - this.r = hue2rgb( q, p, h + 1 / 3 ); - this.g = hue2rgb( q, p, h ); - this.b = hue2rgb( q, p, h - 1 / 3 ); + return canvas; - } + } else if ( image.data ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + const data = image.data.slice( 0 ); - return this; + for ( let i = 0; i < data.length; i ++ ) { - } + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { - setStyle( style, colorSpace = SRGBColorSpace ) { + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); - function handleAlpha( string ) { + } else { - if ( string === undefined ) return; + // assuming float - if ( parseFloat( string ) < 1 ) { + data[ i ] = SRGBToLinear( data[ i ] ); - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + } } - } + return { + data: data, + width: image.width, + height: image.height + }; + } else { - let m; + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; - if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) { + } - // rgb / hsl + } - let color; - const name = m[ 1 ]; - const components = m[ 2 ]; +} - switch ( name ) { +let sourceId = 0; - case 'rgb': - case 'rgba': +class Source { - if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + constructor( data = null ) { - // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; + this.isSource = true; - ColorManagement.toWorkingColorSpace( this, colorSpace ); + Object.defineProperty( this, 'id', { value: sourceId ++ } ); - handleAlpha( color[ 4 ] ); + this.uuid = generateUUID(); - return this; + this.data = data; - } + this.version = 0; - if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + } - // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; + set needsUpdate( value ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + if ( value === true ) this.version ++; - handleAlpha( color[ 4 ] ); + } - return this; + toJSON( meta ) { - } + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - break; + if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { - case 'hsl': - case 'hsla': + return meta.images[ this.uuid ]; - if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + } - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - const h = parseFloat( color[ 1 ] ) / 360; - const s = parseFloat( color[ 2 ] ) / 100; - const l = parseFloat( color[ 3 ] ) / 100; + const output = { + uuid: this.uuid, + url: '' + }; - handleAlpha( color[ 4 ] ); + const data = this.data; - return this.setHSL( h, s, l, colorSpace ); + if ( data !== null ) { - } + let url; - break; + if ( Array.isArray( data ) ) { - } + // cube texture - } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { + url = []; - // hex color + for ( let i = 0, l = data.length; i < l; i ++ ) { - const hex = m[ 1 ]; - const size = hex.length; + if ( data[ i ].isDataTexture ) { - if ( size === 3 ) { + url.push( serializeImage( data[ i ].image ) ); - // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + url.push( serializeImage( data[ i ] ) ); - return this; + } - } else if ( size === 6 ) { + } - // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + // texture - return this; + url = serializeImage( data ); } + output.url = url; + } - if ( style && style.length > 0 ) { + if ( ! isRootObject ) { - return this.setColorName( style, colorSpace ); + meta.images[ this.uuid ] = output; } - return this; + return output; } - setColorName( style, colorSpace = SRGBColorSpace ) { +} - // color keywords - const hex = _colorKeywords[ style.toLowerCase() ]; +function serializeImage( image ) { - if ( hex !== undefined ) { + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - // red - this.setHex( hex, colorSpace ); + // default images + + return ImageUtils.getDataURL( image ); + + } else { + + if ( image.data ) { + + // images of DataTexture + + return { + data: Array.from( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; } else { - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; } - return this; - } - clone() { +} - return new this.constructor( this.r, this.g, this.b ); +let textureId = 0; - } +class Texture extends EventDispatcher { - copy( color ) { + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { - this.r = color.r; - this.g = color.g; - this.b = color.b; + super(); - return this; + this.isTexture = true; - } + Object.defineProperty( this, 'id', { value: textureId ++ } ); - copySRGBToLinear( color ) { + this.uuid = generateUUID(); - this.r = SRGBToLinear( color.r ); - this.g = SRGBToLinear( color.g ); - this.b = SRGBToLinear( color.b ); + this.name = ''; - return this; + this.source = new Source( image ); + this.mipmaps = []; - } + this.mapping = mapping; + this.channel = 0; - copyLinearToSRGB( color ) { + this.wrapS = wrapS; + this.wrapT = wrapT; - this.r = LinearToSRGB( color.r ); - this.g = LinearToSRGB( color.g ); - this.b = LinearToSRGB( color.b ); + this.magFilter = magFilter; + this.minFilter = minFilter; - return this; + this.anisotropy = anisotropy; - } + this.format = format; + this.internalFormat = null; + this.type = type; - convertSRGBToLinear() { + this.offset = new Vector2( 0, 0 ); + this.repeat = new Vector2( 1, 1 ); + this.center = new Vector2( 0, 0 ); + this.rotation = 0; - this.copySRGBToLinear( this ); + this.matrixAutoUpdate = true; + this.matrix = new Matrix3(); - return this; + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - } + if ( typeof colorSpace === 'string' ) { - convertLinearToSRGB() { + this.colorSpace = colorSpace; - this.copyLinearToSRGB( this ); + } else { // @deprecated, r152 - return this; + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace; - } + } - getHex( colorSpace = SRGBColorSpace ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + this.userData = {}; + + this.version = 0; + this.onUpdate = null; - return clamp( _rgb$1.r * 255, 0, 255 ) << 16 ^ clamp( _rgb$1.g * 255, 0, 255 ) << 8 ^ clamp( _rgb$1.b * 255, 0, 255 ) << 0; + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) } - getHexString( colorSpace = SRGBColorSpace ) { + get image() { - return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); + return this.source.data; } - getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { + set image( value = null ) { - // h,s,l ranges are in 0.0 - 1.0 + this.source.data = value; - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + } - const r = _rgb$1.r, g = _rgb$1.g, b = _rgb$1.b; + updateMatrix() { - const max = Math.max( r, g, b ); - const min = Math.min( r, g, b ); + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); - let hue, saturation; - const lightness = ( min + max ) / 2.0; + } - if ( min === max ) { + clone() { - hue = 0; - saturation = 0; + return new this.constructor().copy( this ); - } else { + } - const delta = max - min; + copy( source ) { - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + this.name = source.name; - switch ( max ) { + this.source = source.source; + this.mipmaps = source.mipmaps.slice( 0 ); - case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; - case g: hue = ( b - r ) / delta + 2; break; - case b: hue = ( r - g ) / delta + 4; break; + this.mapping = source.mapping; + this.channel = source.channel; - } + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; - hue /= 6; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; - } + this.anisotropy = source.anisotropy; - target.h = hue; - target.s = saturation; - target.l = lightness; + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; - return target; + this.offset.copy( source.offset ); + this.repeat.copy( source.repeat ); + this.center.copy( source.center ); + this.rotation = source.rotation; - } + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy( source.matrix ); - getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.colorSpace = source.colorSpace; - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - target.r = _rgb$1.r; - target.g = _rgb$1.g; - target.b = _rgb$1.b; + this.needsUpdate = true; - return target; + return this; } - getStyle( colorSpace = SRGBColorSpace ) { + toJSON( meta ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - if ( colorSpace !== SRGBColorSpace ) { + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). - return `color(${ colorSpace } ${ _rgb$1.r } ${ _rgb$1.g } ${ _rgb$1.b })`; + return meta.textures[ this.uuid ]; } - return `rgb(${( _rgb$1.r * 255 ) | 0},${( _rgb$1.g * 255 ) | 0},${( _rgb$1.b * 255 ) | 0})`; + const output = { - } + metadata: { + version: 4.6, + type: 'Texture', + generator: 'Texture.toJSON' + }, - offsetHSL( h, s, l ) { + uuid: this.uuid, + name: this.name, - this.getHSL( _hslA ); + image: this.source.toJSON( meta ).uuid, - _hslA.h += h; _hslA.s += s; _hslA.l += l; + mapping: this.mapping, + channel: this.channel, - this.setHSL( _hslA.h, _hslA.s, _hslA.l ); + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, - return this; + wrap: [ this.wrapS, this.wrapT ], - } + format: this.format, + internalFormat: this.internalFormat, + type: this.type, + colorSpace: this.colorSpace, - add( color ) { + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, - this.r += color.r; - this.g += color.g; - this.b += color.b; + flipY: this.flipY, - return this; + generateMipmaps: this.generateMipmaps, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment - } + }; - addColors( color1, color2 ) { + if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; + if ( ! isRootObject ) { - return this; + meta.textures[ this.uuid ] = output; - } + } - addScalar( s ) { + return output; - this.r += s; - this.g += s; - this.b += s; + } - return this; + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); } - sub( color ) { + transformUv( uv ) { - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); + if ( this.mapping !== UVMapping ) return uv; - return this; + uv.applyMatrix3( this.matrix ); - } + if ( uv.x < 0 || uv.x > 1 ) { - multiply( color ) { + switch ( this.wrapS ) { - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; + case RepeatWrapping: - return this; + uv.x = uv.x - Math.floor( uv.x ); + break; - } + case ClampToEdgeWrapping: - multiplyScalar( s ) { + uv.x = uv.x < 0 ? 0 : 1; + break; - this.r *= s; - this.g *= s; - this.b *= s; + case MirroredRepeatWrapping: - return this; + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { - } + uv.x = Math.ceil( uv.x ) - uv.x; - lerp( color, alpha ) { + } else { - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; + uv.x = uv.x - Math.floor( uv.x ); - return this; + } - } + break; - lerpColors( color1, color2, alpha ) { + } - this.r = color1.r + ( color2.r - color1.r ) * alpha; - this.g = color1.g + ( color2.g - color1.g ) * alpha; - this.b = color1.b + ( color2.b - color1.b ) * alpha; + } - return this; + if ( uv.y < 0 || uv.y > 1 ) { - } + switch ( this.wrapT ) { - lerpHSL( color, alpha ) { + case RepeatWrapping: - this.getHSL( _hslA ); - color.getHSL( _hslB ); + uv.y = uv.y - Math.floor( uv.y ); + break; - const h = lerp( _hslA.h, _hslB.h, alpha ); - const s = lerp( _hslA.s, _hslB.s, alpha ); - const l = lerp( _hslA.l, _hslB.l, alpha ); + case ClampToEdgeWrapping: - this.setHSL( h, s, l ); + uv.y = uv.y < 0 ? 0 : 1; + break; - return this; + case MirroredRepeatWrapping: - } + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - equals( c ) { + uv.y = Math.ceil( uv.y ) - uv.y; - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + } else { - } + uv.y = uv.y - Math.floor( uv.y ); - fromArray( array, offset = 0 ) { + } - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; + break; - return this; + } - } + } - toArray( array = [], offset = 0 ) { + if ( this.flipY ) { - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; + uv.y = 1 - uv.y; - return array; + } + + return uv; } - fromBufferAttribute( attribute, index ) { + set needsUpdate( value ) { - this.r = attribute.getX( index ); - this.g = attribute.getY( index ); - this.b = attribute.getZ( index ); + if ( value === true ) { - return this; + this.version ++; + this.source.needsUpdate = true; + + } } - toJSON() { + get encoding() { // @deprecated, r152 - return this.getHex(); + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; } - *[ Symbol.iterator ]() { + set encoding( encoding ) { // @deprecated, r152 - yield this.r; - yield this.g; - yield this.b; + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; } } -Color.NAMES = _colorKeywords; - -let _canvas; +Texture.DEFAULT_IMAGE = null; +Texture.DEFAULT_MAPPING = UVMapping; +Texture.DEFAULT_ANISOTROPY = 1; -class ImageUtils { +class Vector4 { - static getDataURL( image ) { + constructor( x = 0, y = 0, z = 0, w = 1 ) { - if ( /^data:/i.test( image.src ) ) { + Vector4.prototype.isVector4 = true; - return image.src; + this.x = x; + this.y = y; + this.z = z; + this.w = w; - } + } - if ( typeof HTMLCanvasElement == 'undefined' ) { + get width() { - return image.src; + return this.z; - } + } - let canvas; + set width( value ) { - if ( image instanceof HTMLCanvasElement ) { + this.z = value; - canvas = image; + } - } else { + get height() { - if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); + return this.w; - _canvas.width = image.width; - _canvas.height = image.height; + } - const context = _canvas.getContext( '2d' ); + set height( value ) { - if ( image instanceof ImageData ) { + this.w = value; - context.putImageData( image, 0, 0 ); + } - } else { + set( x, y, z, w ) { - context.drawImage( image, 0, 0, image.width, image.height ); + this.x = x; + this.y = y; + this.z = z; + this.w = w; - } + return this; - canvas = _canvas; + } - } + setScalar( scalar ) { - if ( canvas.width > 2048 || canvas.height > 2048 ) { + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; - console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); + return this; - return canvas.toDataURL( 'image/jpeg', 0.6 ); + } - } else { + setX( x ) { - return canvas.toDataURL( 'image/png' ); + this.x = x; - } + return this; } - static sRGBToLinear( image ) { + setY( y ) { - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + this.y = y; - const canvas = createElementNS( 'canvas' ); + return this; - canvas.width = image.width; - canvas.height = image.height; + } - const context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, image.width, image.height ); + setZ( z ) { - const imageData = context.getImageData( 0, 0, image.width, image.height ); - const data = imageData.data; + this.z = z; - for ( let i = 0; i < data.length; i ++ ) { + return this; - data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; + } - } + setW( w ) { - context.putImageData( imageData, 0, 0 ); + this.w = w; - return canvas; + return this; - } else if ( image.data ) { + } - const data = image.data.slice( 0 ); + setComponent( index, value ) { - for ( let i = 0; i < data.length; i ++ ) { + switch ( index ) { - if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + case 3: this.w = value; break; + default: throw new Error( 'index is out of range: ' + index ); - data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); + } - } else { + return this; - // assuming float + } - data[ i ] = SRGBToLinear( data[ i ] ); + getComponent( index ) { - } + switch ( index ) { - } + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + case 3: return this.w; + default: throw new Error( 'index is out of range: ' + index ); - return { - data: data, - width: image.width, - height: image.height - }; + } - } else { + } - console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); - return image; + clone() { - } + return new this.constructor( this.x, this.y, this.z, this.w ); } -} + copy( v ) { -class Source { + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; - constructor( data = null ) { + return this; - this.isSource = true; + } - this.uuid = generateUUID(); + add( v ) { - this.data = data; + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; - this.version = 0; + return this; } - set needsUpdate( value ) { + addScalar( s ) { - if ( value === true ) this.version ++; + this.x += s; + this.y += s; + this.z += s; + this.w += s; + + return this; } - toJSON( meta ) { + addVectors( a, b ) { - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; + this.w = a.w + b.w; - if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { + return this; - return meta.images[ this.uuid ]; + } - } + addScaledVector( v, s ) { - const output = { - uuid: this.uuid, - url: '' - }; + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; - const data = this.data; + return this; - if ( data !== null ) { + } - let url; + sub( v ) { - if ( Array.isArray( data ) ) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; - // cube texture + return this; - url = []; + } - for ( let i = 0, l = data.length; i < l; i ++ ) { + subScalar( s ) { - if ( data[ i ].isDataTexture ) { + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; - url.push( serializeImage( data[ i ].image ) ); + return this; - } else { + } - url.push( serializeImage( data[ i ] ) ); + subVectors( a, b ) { - } + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + this.w = a.w - b.w; - } + return this; - } else { + } - // texture + multiply( v ) { - url = serializeImage( data ); + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + this.w *= v.w; - } + return this; - output.url = url; + } - } + multiplyScalar( scalar ) { - if ( ! isRootObject ) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; - meta.images[ this.uuid ] = output; + return this; - } + } - return output; + applyMatrix4( m ) { + + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; + this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + + return this; } -} + divideScalar( scalar ) { -function serializeImage( image ) { + return this.multiplyScalar( 1 / scalar ); - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + } - // default images + setAxisAngleFromQuaternion( q ) { - return ImageUtils.getDataURL( image ); + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - } else { + // q is assumed to be normalized - if ( image.data ) { + this.w = 2 * Math.acos( q.w ); - // images of DataTexture + const s = Math.sqrt( 1 - q.w * q.w ); - return { - data: Array.from( image.data ), - width: image.width, - height: image.height, - type: image.data.constructor.name - }; + if ( s < 0.0001 ) { + + this.x = 1; + this.y = 0; + this.z = 0; } else { - console.warn( 'THREE.Texture: Unable to serialize Texture.' ); - return {}; + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; } + return this; + } -} + setAxisAngleFromRotationMatrix( m ) { -let textureId = 0; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm -class Texture extends EventDispatcher { + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, encoding = LinearEncoding ) { + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - super(); + te = m.elements, - this.isTexture = true; + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; - Object.defineProperty( this, 'id', { value: textureId ++ } ); + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { - this.uuid = generateUUID(); + // singularity found + // first check for identity matrix which must have +1 for all terms + // in leading diagonal and zero in other terms - this.name = ''; + if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && + ( Math.abs( m13 + m31 ) < epsilon2 ) && + ( Math.abs( m23 + m32 ) < epsilon2 ) && + ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { - this.source = new Source( image ); - this.mipmaps = []; + // this singularity is identity matrix so angle = 0 - this.mapping = mapping; + this.set( 1, 0, 0, 0 ); - this.wrapS = wrapS; - this.wrapT = wrapT; + return this; // zero angle, arbitrary axis - this.magFilter = magFilter; - this.minFilter = minFilter; + } - this.anisotropy = anisotropy; + // otherwise this singularity is angle = 180 - this.format = format; - this.internalFormat = null; - this.type = type; + angle = Math.PI; - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); - this.center = new Vector2( 0, 0 ); - this.rotation = 0; - - this.matrixAutoUpdate = true; - this.matrix = new Matrix3(); - - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + const xx = ( m11 + 1 ) / 2; + const yy = ( m22 + 1 ) / 2; + const zz = ( m33 + 1 ) / 2; + const xy = ( m12 + m21 ) / 4; + const xz = ( m13 + m31 ) / 4; + const yz = ( m23 + m32 ) / 4; - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding; + if ( ( xx > yy ) && ( xx > zz ) ) { - this.userData = {}; + // m11 is the largest diagonal term - this.version = 0; - this.onUpdate = null; + if ( xx < epsilon ) { - this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not - this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) + x = 0; + y = 0.707106781; + z = 0.707106781; - } + } else { - get image() { + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; - return this.source.data; + } - } + } else if ( yy > zz ) { - set image( value ) { + // m22 is the largest diagonal term - this.source.data = value; + if ( yy < epsilon ) { - } + x = 0.707106781; + y = 0; + z = 0.707106781; - updateMatrix() { + } else { - this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; - } + } - clone() { + } else { - return new this.constructor().copy( this ); + // m33 is the largest diagonal term so base result on this - } + if ( zz < epsilon ) { - copy( source ) { + x = 0.707106781; + y = 0.707106781; + z = 0; - this.name = source.name; + } else { - this.source = source.source; - this.mipmaps = source.mipmaps.slice( 0 ); + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; - this.mapping = source.mapping; + } - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + } - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + this.set( x, y, z, angle ); - this.anisotropy = source.anisotropy; + return this; // return 180 deg rotation - this.format = source.format; - this.internalFormat = source.internalFormat; - this.type = source.type; + } - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; + // as we have reached here there are no singularities so we can handle normally - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + if ( Math.abs( s ) < 0.001 ) s = 1; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case - this.needsUpdate = true; + this.x = ( m32 - m23 ) / s; + this.y = ( m13 - m31 ) / s; + this.z = ( m21 - m12 ) / s; + this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); return this; } - toJSON( meta ) { - - const isRootObject = ( meta === undefined || typeof meta === 'string' ); - - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - - return meta.textures[ this.uuid ]; - - } - - const output = { - - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + min( v ) { - uuid: this.uuid, - name: this.name, + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); + this.w = Math.min( this.w, v.w ); - image: this.source.toJSON( meta ).uuid, + return this; - mapping: this.mapping, + } - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, + max( v ) { - wrap: [ this.wrapS, this.wrapT ], + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); + this.w = Math.max( this.w, v.w ); - format: this.format, - type: this.type, - encoding: this.encoding, + return this; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + } - flipY: this.flipY, + clamp( min, max ) { - generateMipmaps: this.generateMipmaps, - premultiplyAlpha: this.premultiplyAlpha, - unpackAlignment: this.unpackAlignment + // assumes min < max, componentwise - }; + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); - if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; + return this; - if ( ! isRootObject ) { + } - meta.textures[ this.uuid ] = output; + clampScalar( minVal, maxVal ) { - } + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); + this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); - return output; + return this; } - dispose() { + clampLength( min, max ) { - this.dispatchEvent( { type: 'dispose' } ); + const length = this.length(); + + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); } - transformUv( uv ) { + floor() { - if ( this.mapping !== UVMapping ) return uv; + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); + this.w = Math.floor( this.w ); - uv.applyMatrix3( this.matrix ); + return this; - if ( uv.x < 0 || uv.x > 1 ) { + } - switch ( this.wrapS ) { + ceil() { - case RepeatWrapping: + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); + this.w = Math.ceil( this.w ); - uv.x = uv.x - Math.floor( uv.x ); - break; + return this; - case ClampToEdgeWrapping: + } - uv.x = uv.x < 0 ? 0 : 1; - break; + round() { - case MirroredRepeatWrapping: + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + this.w = Math.round( this.w ); - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + return this; - uv.x = Math.ceil( uv.x ) - uv.x; + } - } else { + roundToZero() { - uv.x = uv.x - Math.floor( uv.x ); + this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); + this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); + this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); + this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); - } + return this; - break; + } - } + negate() { - } + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + this.w = - this.w; - if ( uv.y < 0 || uv.y > 1 ) { + return this; - switch ( this.wrapT ) { + } - case RepeatWrapping: + dot( v ) { - uv.y = uv.y - Math.floor( uv.y ); - break; + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - case ClampToEdgeWrapping: + } - uv.y = uv.y < 0 ? 0 : 1; - break; + lengthSq() { - case MirroredRepeatWrapping: + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + } - uv.y = Math.ceil( uv.y ) - uv.y; + length() { - } else { + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - uv.y = uv.y - Math.floor( uv.y ); + } - } + manhattanLength() { - break; + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - } + } - } + normalize() { - if ( this.flipY ) { + return this.divideScalar( this.length() || 1 ); - uv.y = 1 - uv.y; + } - } + setLength( length ) { - return uv; + return this.normalize().multiplyScalar( length ); } - set needsUpdate( value ) { - - if ( value === true ) { + lerp( v, alpha ) { - this.version ++; - this.source.needsUpdate = true; + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; + this.w += ( v.w - this.w ) * alpha; - } + return this; } -} - -Texture.DEFAULT_IMAGE = null; -Texture.DEFAULT_MAPPING = UVMapping; -Texture.DEFAULT_ANISOTROPY = 1; - -class Vector4 { - - constructor( x = 0, y = 0, z = 0, w = 1 ) { + lerpVectors( v1, v2, alpha ) { - Vector4.prototype.isVector4 = true; + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; + this.w = v1.w + ( v2.w - v1.w ) * alpha; - this.x = x; - this.y = y; - this.z = z; - this.w = w; + return this; } - get width() { + equals( v ) { - return this.z; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); } - set width( value ) { - - this.z = value; - - } + fromArray( array, offset = 0 ) { - get height() { + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; - return this.w; + return this; } - set height( value ) { + toArray( array = [], offset = 0 ) { - this.w = value; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; + + return array; } - set( x, y, z, w ) { + fromBufferAttribute( attribute, index ) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); return this; } - setScalar( scalar ) { + random() { - this.x = scalar; - this.y = scalar; - this.z = scalar; - this.w = scalar; + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); return this; } - setX( x ) { - - this.x = x; + *[ Symbol.iterator ]() { - return this; + yield this.x; + yield this.y; + yield this.z; + yield this.w; } - setY( y ) { +} - this.y = y; +/* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers +*/ +class WebGLRenderTarget extends EventDispatcher { - return this; + constructor( width = 1, height = 1, options = {} ) { - } + super(); - setZ( z ) { + this.isWebGLRenderTarget = true; - this.z = z; + this.width = width; + this.height = height; + this.depth = 1; - return this; + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - } + this.viewport = new Vector4( 0, 0, width, height ); - setW( w ) { + const image = { width: width, height: height, depth: 1 }; - this.w = w; + if ( options.encoding !== undefined ) { - return this; + // @deprecated, r152 + warnOnce( 'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; - } + } - setComponent( index, value ) { + this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); + this.texture.isRenderTargetTexture = true; - switch ( index ) { + this.texture.flipY = false; + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - case 3: this.w = value; break; - default: throw new Error( 'index is out of range: ' + index ); + this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; - } + this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - return this; + this.samples = options.samples !== undefined ? options.samples : 0; } - getComponent( index ) { + setSize( width, height, depth = 1 ) { - switch ( index ) { + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - case 3: return this.w; - default: throw new Error( 'index is out of range: ' + index ); + this.width = width; + this.height = height; + this.depth = depth; + + this.texture.image.width = width; + this.texture.image.height = height; + this.texture.image.depth = depth; + + this.dispose(); } + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); + } clone() { - return new this.constructor( this.x, this.y, this.z, this.w ); + return new this.constructor().copy( this ); } - copy( v ) { + copy( source ) { - this.x = v.x; - this.y = v.y; - this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - return this; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - } + this.viewport.copy( source.viewport ); - add( v ) { + this.texture = source.texture.clone(); + this.texture.isRenderTargetTexture = true; - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; + // ensure image object is not shared, see #20328 - return this; + const image = Object.assign( {}, source.texture.image ); + this.texture.source = new Source( image ); - } + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - addScalar( s ) { + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - this.x += s; - this.y += s; - this.z += s; - this.w += s; + this.samples = source.samples; return this; } - addVectors( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - this.w = a.w + b.w; + dispose() { - return this; + this.dispatchEvent( { type: 'dispose' } ); } - addScaledVector( v, s ) { +} - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - this.w += v.w * s; +class DataArrayTexture extends Texture { - return this; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - } + super( null ); - sub( v ) { + this.isDataArrayTexture = true; - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; + this.image = { data, width, height, depth }; - return this; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - } + this.wrapR = ClampToEdgeWrapping; - subScalar( s ) { + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - this.x -= s; - this.y -= s; - this.z -= s; - this.w -= s; + } - return this; +} - } +class WebGLArrayRenderTarget extends WebGLRenderTarget { - subVectors( a, b ) { + constructor( width = 1, height = 1, depth = 1 ) { - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - this.w = a.w - b.w; + super( width, height ); - return this; + this.isWebGLArrayRenderTarget = true; + + this.depth = depth; + + this.texture = new DataArrayTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; } - multiply( v ) { +} - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - this.w *= v.w; +class Data3DTexture extends Texture { - return this; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - } + // We're going to add .setXXX() methods for setting properties later. + // Users can still set in DataTexture3D directly. + // + // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // texture.anisotropy = 16; + // + // See #14839 - multiplyScalar( scalar ) { + super( null ); - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + this.isData3DTexture = true; - return this; + this.image = { data, width, height, depth }; + + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + + this.wrapR = ClampToEdgeWrapping; + + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; } - applyMatrix4( m ) { +} - const x = this.x, y = this.y, z = this.z, w = this.w; - const e = m.elements; +class WebGL3DRenderTarget extends WebGLRenderTarget { - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; - this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + constructor( width = 1, height = 1, depth = 1 ) { - return this; + super( width, height ); - } + this.isWebGL3DRenderTarget = true; - divideScalar( scalar ) { + this.depth = depth; - return this.multiplyScalar( 1 / scalar ); + this.texture = new Data3DTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; } - setAxisAngleFromQuaternion( q ) { +} - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm +class WebGLMultipleRenderTargets extends WebGLRenderTarget { - // q is assumed to be normalized + constructor( width = 1, height = 1, count = 1, options = {} ) { - this.w = 2 * Math.acos( q.w ); + super( width, height, options ); - const s = Math.sqrt( 1 - q.w * q.w ); + this.isWebGLMultipleRenderTargets = true; - if ( s < 0.0001 ) { + const texture = this.texture; - this.x = 1; - this.y = 0; - this.z = 0; + this.texture = []; - } else { + for ( let i = 0; i < count; i ++ ) { - this.x = q.x / s; - this.y = q.y / s; - this.z = q.z / s; + this.texture[ i ] = texture.clone(); + this.texture[ i ].isRenderTargetTexture = true; } - return this; - } - setAxisAngleFromRotationMatrix( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + setSize( width, height, depth = 1 ) { - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - let angle, x, y, z; // variables for result - const epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + this.width = width; + this.height = height; + this.depth = depth; - te = m.elements, + for ( let i = 0, il = this.texture.length; i < il; i ++ ) { - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; + this.texture[ i ].image.width = width; + this.texture[ i ].image.height = height; + this.texture[ i ].image.depth = depth; - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { + } - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + this.dispose(); - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + } - // this singularity is identity matrix so angle = 0 + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - this.set( 1, 0, 0, 0 ); + return this; - return this; // zero angle, arbitrary axis + } - } + copy( source ) { - // otherwise this singularity is angle = 180 + this.dispose(); - angle = Math.PI; + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - const xx = ( m11 + 1 ) / 2; - const yy = ( m22 + 1 ) / 2; - const zz = ( m33 + 1 ) / 2; - const xy = ( m12 + m21 ) / 4; - const xz = ( m13 + m31 ) / 4; - const yz = ( m23 + m32 ) / 4; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - if ( ( xx > yy ) && ( xx > zz ) ) { + this.viewport.copy( source.viewport ); - // m11 is the largest diagonal term + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - if ( xx < epsilon ) { + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - x = 0; - y = 0.707106781; - z = 0.707106781; + this.texture.length = 0; - } else { + for ( let i = 0, il = source.texture.length; i < il; i ++ ) { - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + this.texture[ i ] = source.texture[ i ].clone(); + this.texture[ i ].isRenderTargetTexture = true; - } + } - } else if ( yy > zz ) { + return this; - // m22 is the largest diagonal term + } - if ( yy < epsilon ) { +} - x = 0.707106781; - y = 0; - z = 0.707106781; +class Quaternion { - } else { + constructor( x = 0, y = 0, z = 0, w = 1 ) { - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + this.isQuaternion = true; - } + this._x = x; + this._y = y; + this._z = z; + this._w = w; - } else { + } - // m33 is the largest diagonal term so base result on this + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - if ( zz < epsilon ) { + // fuzz-free, array-based Quaternion SLERP operation - x = 0.707106781; - y = 0.707106781; - z = 0; + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; - } else { + const x1 = src1[ srcOffset1 + 0 ], + y1 = src1[ srcOffset1 + 1 ], + z1 = src1[ srcOffset1 + 2 ], + w1 = src1[ srcOffset1 + 3 ]; - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + if ( t === 0 ) { - } + dst[ dstOffset + 0 ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; + return; - } + } - this.set( x, y, z, angle ); + if ( t === 1 ) { - return this; // return 180 deg rotation + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; } - // as we have reached here there are no singularities so we can handle normally + if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { - let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + let s = 1 - t; + const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + dir = ( cos >= 0 ? 1 : - 1 ), + sqrSin = 1 - cos * cos; - if ( Math.abs( s ) < 0.001 ) s = 1; + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; - return this; + } - } + const tDir = t * dir; - min( v ) { + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - this.w = Math.min( this.w, v.w ); + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { - return this; + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - } + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; - max( v ) { + } - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - this.w = Math.max( this.w, v.w ); + } - return this; + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; } - clamp( min, max ) { + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { - // assumes min < max, componentwise + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; - return this; + dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; + dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; + dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; + dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; - } + return dst; - clampScalar( minVal, maxVal ) { + } - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); + get x() { - return this; + return this._x; } - clampLength( min, max ) { - - const length = this.length(); + set x( value ) { - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + this._x = value; + this._onChangeCallback(); } - floor() { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); + get y() { - return this; + return this._y; } - ceil() { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); + set y( value ) { - return this; + this._y = value; + this._onChangeCallback(); } - round() { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - this.w = Math.round( this.w ); + get z() { - return this; + return this._z; } - roundToZero() { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); + set z( value ) { - return this; + this._z = value; + this._onChangeCallback(); } - negate() { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - this.w = - this.w; + get w() { - return this; + return this._w; } - dot( v ) { + set w( value ) { - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + this._w = value; + this._onChangeCallback(); } - lengthSq() { - - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + set( x, y, z, w ) { - } + this._x = x; + this._y = y; + this._z = z; + this._w = w; - length() { + this._onChangeCallback(); - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); + return this; } - manhattanLength() { + clone() { - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + return new this.constructor( this._x, this._y, this._z, this._w ); } - normalize() { + copy( quaternion ) { - return this.divideScalar( this.length() || 1 ); + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; + + this._onChangeCallback(); + + return this; } - setLength( length ) { + setFromEuler( euler, update ) { - return this.normalize().multiplyScalar( length ); + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - } + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m - lerp( v, alpha ) { + const cos = Math.cos; + const sin = Math.sin; - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - this.w += ( v.w - this.w ) * alpha; + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); - return this; + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); - } + switch ( order ) { - lerpVectors( v1, v2, alpha ) { + case 'XYZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; - this.w = v1.w + ( v2.w - v1.w ) * alpha; + case 'YXZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - return this; + case 'ZXY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - } + case 'ZYX': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - equals( v ) { + case 'YZX': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); + case 'XZY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - } + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); - fromArray( array, offset = 0 ) { + } - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; + if ( update !== false ) this._onChangeCallback(); return this; } - toArray( array = [], offset = 0 ) { + setFromAxisAngle( axis, angle ) { - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - return array; + // assumes axis is normalized - } + const halfAngle = angle / 2, s = Math.sin( halfAngle ); - fromBufferAttribute( attribute, index ) { + this._x = axis.x * s; + this._y = axis.y * s; + this._z = axis.z * s; + this._w = Math.cos( halfAngle ); - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); + this._onChangeCallback(); return this; } - random() { - - this.x = Math.random(); - this.y = Math.random(); - this.z = Math.random(); - this.w = Math.random(); + setFromRotationMatrix( m ) { - return this; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - } + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - *[ Symbol.iterator ]() { + const te = m.elements, - yield this.x; - yield this.y; - yield this.z; - yield this.w; + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], - } + trace = m11 + m22 + m33; -} + if ( trace > 0 ) { -/* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers -*/ -class WebGLRenderTarget extends EventDispatcher { + const s = 0.5 / Math.sqrt( trace + 1.0 ); - constructor( width = 1, height = 1, options = {} ) { + this._w = 0.25 / s; + this._x = ( m32 - m23 ) * s; + this._y = ( m13 - m31 ) * s; + this._z = ( m21 - m12 ) * s; - super(); + } else if ( m11 > m22 && m11 > m33 ) { - this.isWebGLRenderTarget = true; + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - this.width = width; - this.height = height; - this.depth = 1; + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; + } else if ( m22 > m33 ) { - this.viewport = new Vector4( 0, 0, width, height ); + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - const image = { width: width, height: height, depth: 1 }; + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; - this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - this.texture.isRenderTargetTexture = true; + } else { - this.texture.flipY = false; - this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; - this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; - this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; + const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; + this._w = ( m21 - m12 ) / s; + this._x = ( m13 + m31 ) / s; + this._y = ( m23 + m32 ) / s; + this._z = 0.25 * s; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; + } - this.samples = options.samples !== undefined ? options.samples : 0; + this._onChangeCallback(); + + return this; } - setSize( width, height, depth = 1 ) { + setFromUnitVectors( vFrom, vTo ) { - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + // assumes direction vectors vFrom and vTo are normalized - this.width = width; - this.height = height; - this.depth = depth; + let r = vFrom.dot( vTo ) + 1; - this.texture.image.width = width; - this.texture.image.height = height; - this.texture.image.depth = depth; + if ( r < Number.EPSILON ) { - this.dispose(); + // vFrom and vTo point in opposite directions - } + r = 0; - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - } + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; - clone() { + } else { - return new this.constructor().copy( this ); + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; - } + } - copy( source ) { + } else { - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 - this.viewport.copy( source.viewport ); + this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; + this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; + this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; + this._w = r; - this.texture = source.texture.clone(); - this.texture.isRenderTargetTexture = true; + } - // ensure image object is not shared, see #20328 + return this.normalize(); - const image = Object.assign( {}, source.texture.image ); - this.texture.source = new Source( image ); + } - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; + angleTo( q ) { - if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); - this.samples = source.samples; + } + + rotateTowards( q, step ) { + + const angle = this.angleTo( q ); + + if ( angle === 0 ) return this; + + const t = Math.min( 1, step / angle ); + + this.slerp( q, t ); return this; } - dispose() { + identity() { - this.dispatchEvent( { type: 'dispose' } ); + return this.set( 0, 0, 0, 1 ); } -} - -class DataArrayTexture extends Texture { + invert() { - constructor( data = null, width = 1, height = 1, depth = 1 ) { + // quaternion is assumed to have unit length - super( null ); + return this.conjugate(); - this.isDataArrayTexture = true; + } - this.image = { data, width, height, depth }; + conjugate() { - this.magFilter = NearestFilter; - this.minFilter = NearestFilter; + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; - this.wrapR = ClampToEdgeWrapping; + this._onChangeCallback(); - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; } -} + dot( v ) { -class WebGLArrayRenderTarget extends WebGLRenderTarget { + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - constructor( width = 1, height = 1, depth = 1 ) { + } - super( width, height ); + lengthSq() { - this.isWebGLArrayRenderTarget = true; + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; - this.depth = depth; + } - this.texture = new DataArrayTexture( null, width, height, depth ); + length() { - this.texture.isRenderTargetTexture = true; + return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); } -} + normalize() { -class Data3DTexture extends Texture { + let l = this.length(); - constructor( data = null, width = 1, height = 1, depth = 1 ) { + if ( l === 0 ) { - // We're going to add .setXXX() methods for setting properties later. - // Users can still set in DataTexture3D directly. - // - // const texture = new THREE.DataTexture3D( data, width, height, depth ); - // texture.anisotropy = 16; - // - // See #14839 + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; - super( null ); + } else { - this.isData3DTexture = true; + l = 1 / l; - this.image = { data, width, height, depth }; + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; - this.magFilter = NearestFilter; - this.minFilter = NearestFilter; + } - this.wrapR = ClampToEdgeWrapping; + this._onChangeCallback(); - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; } -} - -class WebGL3DRenderTarget extends WebGLRenderTarget { - - constructor( width = 1, height = 1, depth = 1 ) { - - super( width, height ); + multiply( q ) { - this.isWebGL3DRenderTarget = true; + return this.multiplyQuaternions( this, q ); - this.depth = depth; + } - this.texture = new Data3DTexture( null, width, height, depth ); + premultiply( q ) { - this.texture.isRenderTargetTexture = true; + return this.multiplyQuaternions( q, this ); } -} - -class WebGLMultipleRenderTargets extends WebGLRenderTarget { + multiplyQuaternions( a, b ) { - constructor( width = 1, height = 1, count = 1, options = {} ) { + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - super( width, height, options ); + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - this.isWebGLMultipleRenderTargets = true; + this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - const texture = this.texture; + this._onChangeCallback(); - this.texture = []; + return this; - for ( let i = 0; i < count; i ++ ) { + } - this.texture[ i ] = texture.clone(); - this.texture[ i ].isRenderTargetTexture = true; + slerp( qb, t ) { - } + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); - } + const x = this._x, y = this._y, z = this._z, w = this._w; - setSize( width, height, depth = 1 ) { + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - this.width = width; - this.height = height; - this.depth = depth; + if ( cosHalfTheta < 0 ) { - for ( let i = 0, il = this.texture.length; i < il; i ++ ) { + this._w = - qb._w; + this._x = - qb._x; + this._y = - qb._y; + this._z = - qb._z; - this.texture[ i ].image.width = width; - this.texture[ i ].image.height = height; - this.texture[ i ].image.depth = depth; + cosHalfTheta = - cosHalfTheta; - } + } else { - this.dispose(); + this.copy( qb ); } - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + if ( cosHalfTheta >= 1.0 ) { - return this; + this._w = w; + this._x = x; + this._y = y; + this._z = z; - } + return this; - copy( source ) { + } - this.dispose(); + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + if ( sqrSinHalfTheta <= Number.EPSILON ) { - this.viewport.set( 0, 0, this.width, this.height ); - this.scissor.set( 0, 0, this.width, this.height ); + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; + this.normalize(); + this._onChangeCallback(); - if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); + return this; - this.texture.length = 0; + } - for ( let i = 0, il = source.texture.length; i < il; i ++ ) { + const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); + const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); + const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, + ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - this.texture[ i ] = source.texture[ i ].clone(); - this.texture[ i ].isRenderTargetTexture = true; + this._w = ( w * ratioA + this._w * ratioB ); + this._x = ( x * ratioA + this._x * ratioB ); + this._y = ( y * ratioA + this._y * ratioB ); + this._z = ( z * ratioA + this._z * ratioB ); - } + this._onChangeCallback(); return this; } -} + slerpQuaternions( qa, qb, t ) { -class Quaternion { + return this.copy( qa ).slerp( qb, t ); - constructor( x = 0, y = 0, z = 0, w = 1 ) { + } - this.isQuaternion = true; + random() { - this._x = x; - this._y = y; - this._z = z; - this._w = w; + // Derived from http://planning.cs.uiuc.edu/node198.html + // Note, this source uses w, x, y, z ordering, + // so we swap the order below. - } + const u1 = Math.random(); + const sqrt1u1 = Math.sqrt( 1 - u1 ); + const sqrtu1 = Math.sqrt( u1 ); - static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + const u2 = 2 * Math.PI * Math.random(); - // fuzz-free, array-based Quaternion SLERP operation + const u3 = 2 * Math.PI * Math.random(); - let x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ]; + return this.set( + sqrt1u1 * Math.cos( u2 ), + sqrtu1 * Math.sin( u3 ), + sqrtu1 * Math.cos( u3 ), + sqrt1u1 * Math.sin( u2 ), + ); - const x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; + } - if ( t === 0 ) { + equals( quaternion ) { - dst[ dstOffset + 0 ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - return; + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - } + } - if ( t === 1 ) { + fromArray( array, offset = 0 ) { - dst[ dstOffset + 0 ] = x1; - dst[ dstOffset + 1 ] = y1; - dst[ dstOffset + 2 ] = z1; - dst[ dstOffset + 3 ] = w1; - return; + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; - } + this._onChangeCallback(); - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + return this; - let s = 1 - t; - const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; + } - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { + toArray( array = [], offset = 0 ) { - const sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + return array; - } + } - const tDir = t * dir; + fromBufferAttribute( attribute, index ) { - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + return this; - const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + } - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; + toJSON() { - } + return this.toArray(); - } + } - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; + _onChange( callback ) { - } + this._onChangeCallback = callback; - static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { + return this; - const x0 = src0[ srcOffset0 ]; - const y0 = src0[ srcOffset0 + 1 ]; - const z0 = src0[ srcOffset0 + 2 ]; - const w0 = src0[ srcOffset0 + 3 ]; + } - const x1 = src1[ srcOffset1 ]; - const y1 = src1[ srcOffset1 + 1 ]; - const z1 = src1[ srcOffset1 + 2 ]; - const w1 = src1[ srcOffset1 + 3 ]; + _onChangeCallback() {} - dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; - dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; - dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; - dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + *[ Symbol.iterator ]() { - return dst; + yield this._x; + yield this._y; + yield this._z; + yield this._w; } - get x() { +} - return this._x; +class Vector3 { - } + constructor( x = 0, y = 0, z = 0 ) { - set x( value ) { + Vector3.prototype.isVector3 = true; - this._x = value; - this._onChangeCallback(); + this.x = x; + this.y = y; + this.z = z; } - get y() { - - return this._y; + set( x, y, z ) { - } + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) - set y( value ) { + this.x = x; + this.y = y; + this.z = z; - this._y = value; - this._onChangeCallback(); + return this; } - get z() { + setScalar( scalar ) { - return this._z; + this.x = scalar; + this.y = scalar; + this.z = scalar; + + return this; } - set z( value ) { + setX( x ) { - this._z = value; - this._onChangeCallback(); + this.x = x; + + return this; } - get w() { + setY( y ) { - return this._w; + this.y = y; + + return this; } - set w( value ) { + setZ( z ) { - this._w = value; - this._onChangeCallback(); + this.z = z; + + return this; } - set( x, y, z, w ) { + setComponent( index, value ) { - this._x = x; - this._y = y; - this._z = z; - this._w = w; - - this._onChangeCallback(); - - return this; + switch ( index ) { - } + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + default: throw new Error( 'index is out of range: ' + index ); - clone() { + } - return new this.constructor( this._x, this._y, this._z, this._w ); + return this; } - copy( quaternion ) { + getComponent( index ) { - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; + switch ( index ) { - this._onChangeCallback(); + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + default: throw new Error( 'index is out of range: ' + index ); - return this; + } } - setFromEuler( euler, update ) { - - const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m - - const cos = Math.cos; - const sin = Math.sin; + clone() { - const c1 = cos( x / 2 ); - const c2 = cos( y / 2 ); - const c3 = cos( z / 2 ); + return new this.constructor( this.x, this.y, this.z ); - const s1 = sin( x / 2 ); - const s2 = sin( y / 2 ); - const s3 = sin( z / 2 ); + } - switch ( order ) { + copy( v ) { - case 'XYZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + this.x = v.x; + this.y = v.y; + this.z = v.z; - case 'YXZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this; - case 'ZXY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + } - case 'ZYX': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + add( v ) { - case 'YZX': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + this.x += v.x; + this.y += v.y; + this.z += v.z; - case 'XZY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this; - default: - console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); + } - } + addScalar( s ) { - if ( update !== false ) this._onChangeCallback(); + this.x += s; + this.y += s; + this.z += s; return this; } - setFromAxisAngle( axis, angle ) { + addVectors( a, b ) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; - // assumes axis is normalized + return this; - const halfAngle = angle / 2, s = Math.sin( halfAngle ); + } - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); + addScaledVector( v, s ) { - this._onChangeCallback(); + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; return this; } - setFromRotationMatrix( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + sub( v ) { - const te = m.elements, + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], + return this; - trace = m11 + m22 + m33; + } - if ( trace > 0 ) { + subScalar( s ) { - const s = 0.5 / Math.sqrt( trace + 1.0 ); + this.x -= s; + this.y -= s; + this.z -= s; - this._w = 0.25 / s; - this._x = ( m32 - m23 ) * s; - this._y = ( m13 - m31 ) * s; - this._z = ( m21 - m12 ) * s; + return this; - } else if ( m11 > m22 && m11 > m33 ) { + } - const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); + subVectors( a, b ) { - this._w = ( m32 - m23 ) / s; - this._x = 0.25 * s; - this._y = ( m12 + m21 ) / s; - this._z = ( m13 + m31 ) / s; + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; - } else if ( m22 > m33 ) { + return this; - const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + } - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; + multiply( v ) { - } else { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; - const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + return this; - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; + } - } + multiplyScalar( scalar ) { - this._onChangeCallback(); + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; return this; } - setFromUnitVectors( vFrom, vTo ) { - - // assumes direction vectors vFrom and vTo are normalized - - let r = vFrom.dot( vTo ) + 1; + multiplyVectors( a, b ) { - if ( r < Number.EPSILON ) { + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; - // vFrom and vTo point in opposite directions + return this; - r = 0; + } - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + applyEuler( euler ) { - this._x = - vFrom.y; - this._y = vFrom.x; - this._z = 0; - this._w = r; + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - } else { + } - this._x = 0; - this._y = - vFrom.z; - this._z = vFrom.y; - this._w = r; + applyAxisAngle( axis, angle ) { - } + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - } else { + } - // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 + applyMatrix3( m ) { - this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; - this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; - this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; - this._w = r; + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - } + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; + this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - return this.normalize(); + return this; } - angleTo( q ) { + applyNormalMatrix( m ) { - return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); + return this.applyMatrix3( m ).normalize(); } - rotateTowards( q, step ) { - - const angle = this.angleTo( q ); + applyMatrix4( m ) { - if ( angle === 0 ) return this; + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - const t = Math.min( 1, step / angle ); + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - this.slerp( q, t ); + this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; + this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; + this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; return this; } - identity() { - - return this.set( 0, 0, 0, 1 ); + applyQuaternion( q ) { - } + const x = this.x, y = this.y, z = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - invert() { + // calculate quat * vector - // quaternion is assumed to have unit length + const ix = qw * x + qy * z - qz * y; + const iy = qw * y + qz * x - qx * z; + const iz = qw * z + qx * y - qy * x; + const iw = - qx * x - qy * y - qz * z; - return this.conjugate(); + // calculate result * inverse quat - } + this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; + this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; + this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - conjugate() { + return this; - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; + } - this._onChangeCallback(); + project( camera ) { - return this; + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); } - dot( v ) { + unproject( camera ) { - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); } - lengthSq() { + transformDirection( m ) { - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction - } + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - length() { + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); + return this.normalize(); } - normalize() { + divide( v ) { - let l = this.length(); + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; - if ( l === 0 ) { + return this; - this._x = 0; - this._y = 0; - this._z = 0; - this._w = 1; + } - } else { + divideScalar( scalar ) { - l = 1 / l; + return this.multiplyScalar( 1 / scalar ); - this._x = this._x * l; - this._y = this._y * l; - this._z = this._z * l; - this._w = this._w * l; + } - } + min( v ) { - this._onChangeCallback(); + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); return this; } - multiply( q ) { + max( v ) { - return this.multiplyQuaternions( this, q ); + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); - } + return this; - premultiply( q ) { + } - return this.multiplyQuaternions( q, this ); + clamp( min, max ) { - } + // assumes min < max, componentwise - multiplyQuaternions( a, b ) { + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm + return this; - const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; + } - this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + clampScalar( minVal, maxVal ) { - this._onChangeCallback(); + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); return this; } - slerp( qb, t ) { - - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - const x = this._x, y = this._y, z = this._z, w = this._w; + clampLength( min, max ) { - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ + const length = this.length(); - let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - if ( cosHalfTheta < 0 ) { + } - this._w = - qb._w; - this._x = - qb._x; - this._y = - qb._y; - this._z = - qb._z; + floor() { - cosHalfTheta = - cosHalfTheta; + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); - } else { + return this; - this.copy( qb ); + } - } + ceil() { - if ( cosHalfTheta >= 1.0 ) { + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); - this._w = w; - this._x = x; - this._y = y; - this._z = z; + return this; - return this; + } - } + round() { - const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); - if ( sqrSinHalfTheta <= Number.EPSILON ) { + return this; - const s = 1 - t; - this._w = s * w + t * this._w; - this._x = s * x + t * this._x; - this._y = s * y + t * this._y; - this._z = s * z + t * this._z; + } - this.normalize(); - this._onChangeCallback(); + roundToZero() { - return this; + this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); + this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); + this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - } + return this; - const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); - const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; + } - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); + negate() { - this._onChangeCallback(); + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; return this; } - slerpQuaternions( qa, qb, t ) { + dot( v ) { - return this.copy( qa ).slerp( qb, t ); + return this.x * v.x + this.y * v.y + this.z * v.z; } - random() { + // TODO lengthSquared? - // Derived from http://planning.cs.uiuc.edu/node198.html - // Note, this source uses w, x, y, z ordering, - // so we swap the order below. + lengthSq() { - const u1 = Math.random(); - const sqrt1u1 = Math.sqrt( 1 - u1 ); - const sqrtu1 = Math.sqrt( u1 ); + return this.x * this.x + this.y * this.y + this.z * this.z; - const u2 = 2 * Math.PI * Math.random(); + } - const u3 = 2 * Math.PI * Math.random(); + length() { - return this.set( - sqrt1u1 * Math.cos( u2 ), - sqrtu1 * Math.sin( u3 ), - sqrtu1 * Math.cos( u3 ), - sqrt1u1 * Math.sin( u2 ), - ); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); } - equals( quaternion ) { + manhattanLength() { - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); } - fromArray( array, offset = 0 ) { - - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; - - this._onChangeCallback(); + normalize() { - return this; + return this.divideScalar( this.length() || 1 ); } - toArray( array = [], offset = 0 ) { - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; + setLength( length ) { - return array; + return this.normalize().multiplyScalar( length ); } - fromBufferAttribute( attribute, index ) { + lerp( v, alpha ) { - this._x = attribute.getX( index ); - this._y = attribute.getY( index ); - this._z = attribute.getZ( index ); - this._w = attribute.getW( index ); + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; return this; } - _onChange( callback ) { + lerpVectors( v1, v2, alpha ) { - this._onChangeCallback = callback; + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; return this; } - _onChangeCallback() {} - - *[ Symbol.iterator ]() { + cross( v ) { - yield this._x; - yield this._y; - yield this._z; - yield this._w; + return this.crossVectors( this, v ); } -} - -class Vector3 { - - constructor( x = 0, y = 0, z = 0 ) { - - Vector3.prototype.isVector3 = true; - - this.x = x; - this.y = y; - this.z = z; - - } - - set( x, y, z ) { - - if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) - - this.x = x; - this.y = y; - this.z = z; - - return this; - - } - - setScalar( scalar ) { - - this.x = scalar; - this.y = scalar; - this.z = scalar; - - return this; - - } - - setX( x ) { - - this.x = x; - - return this; - - } - - setY( y ) { - - this.y = y; - - return this; - - } - - setZ( z ) { - - this.z = z; - - return this; - - } - - setComponent( index, value ) { - - switch ( index ) { - - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - default: throw new Error( 'index is out of range: ' + index ); - - } - - return this; - - } - - getComponent( index ) { - - switch ( index ) { - - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - default: throw new Error( 'index is out of range: ' + index ); - - } - - } - - clone() { - - return new this.constructor( this.x, this.y, this.z ); - - } - - copy( v ) { - - this.x = v.x; - this.y = v.y; - this.z = v.z; - - return this; - - } - - add( v ) { - - this.x += v.x; - this.y += v.y; - this.z += v.z; - - return this; - - } - - addScalar( s ) { - - this.x += s; - this.y += s; - this.z += s; - - return this; - - } - - addVectors( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - - return this; - - } - - addScaledVector( v, s ) { - - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - - return this; - - } - - sub( v ) { - - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - - return this; - - } - - subScalar( s ) { - - this.x -= s; - this.y -= s; - this.z -= s; - - return this; - - } - - subVectors( a, b ) { - - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - - return this; - - } - - multiply( v ) { - - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - - return this; - - } - - multiplyScalar( scalar ) { - - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - - return this; - - } - - multiplyVectors( a, b ) { - - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; - - return this; - - } - - applyEuler( euler ) { - - return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - - } - - applyAxisAngle( axis, angle ) { - - return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - - } - - applyMatrix3( m ) { - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; - this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - - return this; - - } - - applyNormalMatrix( m ) { - - return this.applyMatrix3( m ).normalize(); - - } - - applyMatrix4( m ) { - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - - this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; - this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; - this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; - - return this; - - } - - applyQuaternion( q ) { - - const x = this.x, y = this.y, z = this.z; - const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vector - - const ix = qw * x + qy * z - qz * y; - const iy = qw * y + qz * x - qx * z; - const iz = qw * z + qx * y - qy * x; - const iw = - qx * x - qy * y - qz * z; - - // calculate result * inverse quat - - this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; - this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; - this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - - return this; - - } - - project( camera ) { - - return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - - } - - unproject( camera ) { - - return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); - - } - - transformDirection( m ) { - - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - - return this.normalize(); - - } - - divide( v ) { - - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; - - return this; - - } - - divideScalar( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - } - - min( v ) { - - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - - return this; - - } - - max( v ) { - - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - - return this; - - } - - clamp( min, max ) { - - // assumes min < max, componentwise - - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - - return this; - - } - - clampScalar( minVal, maxVal ) { - - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - - return this; - - } - - clampLength( min, max ) { - - const length = this.length(); - - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - - } - - floor() { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - - return this; - - } - - ceil() { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - - return this; - - } - - round() { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - - return this; - - } - - roundToZero() { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - - return this; - - } - - negate() { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - - return this; - - } - - dot( v ) { - - return this.x * v.x + this.y * v.y + this.z * v.z; - - } - - // TODO lengthSquared? - - lengthSq() { - - return this.x * this.x + this.y * this.y + this.z * this.z; - - } - - length() { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - - } - - manhattanLength() { - - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); - - } - - normalize() { - - return this.divideScalar( this.length() || 1 ); - - } - - setLength( length ) { - - return this.normalize().multiplyScalar( length ); - - } - - lerp( v, alpha ) { - - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - - return this; - - } - - lerpVectors( v1, v2, alpha ) { - - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; - - return this; - - } - - cross( v ) { - - return this.crossVectors( this, v ); - - } - - crossVectors( a, b ) { + crossVectors( a, b ) { const ax = a.x, ay = a.y, az = a.z; const bx = b.x, by = b.y, bz = b.z; @@ -4769,9 +4348,9 @@ class Vector3 { projectOnPlane( planeNormal ) { - _vector$c.copy( this ).projectOnVector( planeNormal ); + _vector$b.copy( this ).projectOnVector( planeNormal ); - return this.sub( _vector$c ); + return this.sub( _vector$b ); } @@ -4780,7 +4359,7 @@ class Vector3 { // reflect incident vector off plane orthogonal to normal // normal is assumed to have unit length - return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + return this.sub( _vector$b.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); } @@ -4900,6 +4479,16 @@ class Vector3 { } + setFromColor( c ) { + + this.x = c.r; + this.y = c.g; + this.z = c.b; + + return this; + + } + equals( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); @@ -4972,7 +4561,7 @@ class Vector3 { } -const _vector$c = /*@__PURE__*/ new Vector3(); +const _vector$b = /*@__PURE__*/ new Vector3(); const _quaternion$4 = /*@__PURE__*/ new Quaternion(); class Box3 { @@ -4997,66 +4586,28 @@ class Box3 { setFromArray( array ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = array.length; i < l; i += 3 ) { - - const x = array[ i ]; - const y = array[ i + 1 ]; - const z = array[ i + 2 ]; + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = array.length; i < il; i += 3 ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector$a.fromArray( array, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } setFromBufferAttribute( attribute ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = attribute.count; i < l; i ++ ) { - - const x = attribute.getX( i ); - const y = attribute.getY( i ); - const z = attribute.getZ( i ); + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = attribute.count; i < il; i ++ ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector$a.fromBufferAttribute( attribute, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } @@ -5077,7 +4628,7 @@ class Box3 { setFromCenterAndSize( center, size ) { - const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); + const halfSize = _vector$a.copy( size ).multiplyScalar( 0.5 ); this.min.copy( center ).sub( halfSize ); this.max.copy( center ).add( halfSize ); @@ -5172,46 +4723,63 @@ class Box3 { object.updateWorldMatrix( false, false ); - const geometry = object.geometry; + if ( object.boundingBox !== undefined ) { - if ( geometry !== undefined ) { + if ( object.boundingBox === null ) { - if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) { + object.computeBoundingBox(); - const position = geometry.attributes.position; - for ( let i = 0, l = position.count; i < l; i ++ ) { + } - _vector$b.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); - this.expandByPoint( _vector$b ); + _box$3.copy( object.boundingBox ); + _box$3.applyMatrix4( object.matrixWorld ); - } + this.union( _box$3 ); - } else { + } else { - if ( geometry.boundingBox === null ) { + const geometry = object.geometry; - geometry.computeBoundingBox(); + if ( geometry !== undefined ) { - } + if ( precise && geometry.attributes !== undefined && geometry.attributes.position !== undefined ) { - _box$3.copy( geometry.boundingBox ); - _box$3.applyMatrix4( object.matrixWorld ); + const position = geometry.attributes.position; + for ( let i = 0, l = position.count; i < l; i ++ ) { - this.union( _box$3 ); + _vector$a.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector$a ); - } + } - } + } else { - const children = object.children; + if ( geometry.boundingBox === null ) { - for ( let i = 0, l = children.length; i < l; i ++ ) { + geometry.computeBoundingBox(); - this.expandByObject( children[ i ], precise ); + } - } + _box$3.copy( geometry.boundingBox ); + _box$3.applyMatrix4( object.matrixWorld ); - return this; + this.union( _box$3 ); + + } + + } + + } + + const children = object.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + this.expandByObject( children[ i ], precise ); + + } + + return this; } @@ -5256,10 +4824,10 @@ class Box3 { intersectsSphere( sphere ) { // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, _vector$b ); + this.clampPoint( sphere.center, _vector$a ); // If that point is inside the sphere, the AABB and sphere intersect. - return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); + return _vector$a.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); } @@ -5371,17 +4939,23 @@ class Box3 { distanceToPoint( point ) { - const clampedPoint = _vector$b.copy( point ).clamp( this.min, this.max ); - - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector$a ).distanceTo( point ); } getBoundingSphere( target ) { - this.getCenter( target.center ); + if ( this.isEmpty() ) { + + target.makeEmpty(); + + } else { + + this.getCenter( target.center ); - target.radius = this.getSize( _vector$b ).length() * 0.5; + target.radius = this.getSize( _vector$a ).length() * 0.5; + + } return target; @@ -5457,7 +5031,7 @@ const _points = [ /*@__PURE__*/ new Vector3() ]; -const _vector$b = /*@__PURE__*/ new Vector3(); +const _vector$a = /*@__PURE__*/ new Vector3(); const _box$3 = /*@__PURE__*/ new Box3(); @@ -5743,7 +5317,7 @@ class Sphere { } -const _vector$a = /*@__PURE__*/ new Vector3(); +const _vector$9 = /*@__PURE__*/ new Vector3(); const _segCenter = /*@__PURE__*/ new Vector3(); const _segDir = /*@__PURE__*/ new Vector3(); const _diff = /*@__PURE__*/ new Vector3(); @@ -5781,7 +5355,7 @@ class Ray { at( t, target ) { - return target.copy( this.direction ).multiplyScalar( t ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, t ); } @@ -5795,7 +5369,7 @@ class Ray { recast( t ) { - this.origin.copy( this.at( t, _vector$a ) ); + this.origin.copy( this.at( t, _vector$9 ) ); return this; @@ -5813,7 +5387,7 @@ class Ray { } - return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); } @@ -5825,7 +5399,7 @@ class Ray { distanceSqToPoint( point ) { - const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); + const directionDistance = _vector$9.subVectors( point, this.origin ).dot( this.direction ); // point behind the ray @@ -5835,9 +5409,9 @@ class Ray { } - _vector$a.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + _vector$9.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - return _vector$a.distanceToSquared( point ); + return _vector$9.distanceToSquared( point ); } @@ -5946,13 +5520,13 @@ class Ray { if ( optionalPointOnRay ) { - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); } if ( optionalPointOnSegment ) { - optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter ); + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); } @@ -5962,9 +5536,9 @@ class Ray { intersectSphere( sphere, target ) { - _vector$a.subVectors( sphere.center, this.origin ); - const tca = _vector$a.dot( this.direction ); - const d2 = _vector$a.dot( _vector$a ) - tca * tca; + _vector$9.subVectors( sphere.center, this.origin ); + const tca = _vector$9.dot( this.direction ); + const d2 = _vector$9.dot( _vector$9 ) - tca * tca; const radius2 = sphere.radius * sphere.radius; if ( d2 > radius2 ) return null; @@ -5977,8 +5551,8 @@ class Ray { // t1 = second intersect point - exit point on back of sphere const t1 = tca + thc; - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; // test to see if t0 is behind the ray: // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, @@ -6131,7 +5705,7 @@ class Ray { intersectsBox( box ) { - return this.intersectBox( box, _vector$a ) !== null; + return this.intersectBox( box, _vector$9 ) !== null; } @@ -6235,7 +5809,7 @@ class Ray { class Matrix4 { - constructor() { + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { Matrix4.prototype.isMatrix4 = true; @@ -6248,6 +5822,12 @@ class Matrix4 { ]; + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); + + } + } set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { @@ -6787,14 +6367,29 @@ class Matrix4 { makeTranslation( x, y, z ) { - this.set( + if ( x.isVector3 ) { - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + this.set( - ); + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 + + ); + + } return this; @@ -7090,7 +6685,7 @@ const _x = /*@__PURE__*/ new Vector3(); const _y = /*@__PURE__*/ new Vector3(); const _z = /*@__PURE__*/ new Vector3(); -const _matrix$1 = /*@__PURE__*/ new Matrix4(); +const _matrix = /*@__PURE__*/ new Matrix4(); const _quaternion$3 = /*@__PURE__*/ new Quaternion(); class Euler { @@ -7325,9 +6920,9 @@ class Euler { setFromQuaternion( q, order, update ) { - _matrix$1.makeRotationFromQuaternion( q ); + _matrix.makeRotationFromQuaternion( q ); - return this.setFromRotationMatrix( _matrix$1, order, update ); + return this.setFromRotationMatrix( _matrix, order, update ); } @@ -8144,7 +7739,7 @@ class Object3D extends EventDispatcher { }; output.metadata = { - version: 4.5, + version: 4.6, type: 'Object', generator: 'Object3D.toJSON' }; @@ -8168,6 +7763,7 @@ class Object3D extends EventDispatcher { object.layers = this.layers.mask; object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; @@ -8395,6 +7991,8 @@ class Object3D extends EventDispatcher { this.frustumCulled = source.frustumCulled; this.renderOrder = source.renderOrder; + this.animations = source.animations; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); if ( recursive === true ) { @@ -8430,6 +8028,8 @@ const _vap = /*@__PURE__*/ new Vector3(); const _vbp = /*@__PURE__*/ new Vector3(); const _vcp = /*@__PURE__*/ new Vector3(); +let warnedGetUV = false; + class Triangle { constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { @@ -8499,14 +8099,28 @@ class Triangle { } - static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { + static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { // @deprecated, r151 + + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return this.getInterpolation( point, p1, p2, p3, uv1, uv2, uv3, target ); + + } + + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { this.getBarycoord( point, p1, p2, p3, _v3$1 ); - target.set( 0, 0 ); - target.addScaledVector( uv1, _v3$1.x ); - target.addScaledVector( uv2, _v3$1.y ); - target.addScaledVector( uv3, _v3$1.z ); + target.setScalar( 0 ); + target.addScaledVector( v1, _v3$1.x ); + target.addScaledVector( v2, _v3$1.y ); + target.addScaledVector( v3, _v3$1.z ); return target; @@ -8601,9 +8215,23 @@ class Triangle { } - getUV( point, uv1, uv2, uv3, target ) { + getUV( point, uv1, uv2, uv3, target ) { // @deprecated, r151 - return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return Triangle.getInterpolation( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + + } + + getInterpolation( point, v1, v2, v3, target ) { + + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); } @@ -8714,497 +8342,1128 @@ class Triangle { } -let materialId = 0; +let materialId = 0; + +class Material extends EventDispatcher { + + constructor() { + + super(); + + this.isMaterial = true; + + Object.defineProperty( this, 'id', { value: materialId ++ } ); + + this.uuid = generateUUID(); + + this.name = ''; + this.type = 'Material'; + + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; + + this.opacity = 1; + this.transparent = false; + + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; + + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; + + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; + + this.shadowSide = null; + + this.colorWrite = true; + + this.precision = null; // override the renderer's default precision for this material + + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; + + this.dithering = false; + + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.forceSinglePass = false; + + this.visible = true; + + this.toneMapped = true; + + this.userData = {}; + + this.version = 0; + + this._alphaTest = 0; + + } + + get alphaTest() { + + return this._alphaTest; + + } + + set alphaTest( value ) { + + if ( this._alphaTest > 0 !== value > 0 ) { + + this.version ++; + + } + + this._alphaTest = value; + + } + + onBuild( /* shaderobject, renderer */ ) {} + + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + + onBeforeCompile( /* shaderobject, renderer */ ) {} + + customProgramCacheKey() { + + return this.onBeforeCompile.toString(); + + } + + setValues( values ) { + + if ( values === undefined ) return; + + for ( const key in values ) { + + const newValue = values[ key ]; + + if ( newValue === undefined ) { + + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + continue; + + } + + const currentValue = this[ key ]; + + if ( currentValue === undefined ) { + + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + continue; + + } + + if ( currentValue && currentValue.isColor ) { + + currentValue.set( newValue ); + + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + + currentValue.copy( newValue ); + + } else { + + this[ key ] = newValue; + + } + + } + + } + + toJSON( meta ) { + + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( isRootObject ) { + + meta = { + textures: {}, + images: {} + }; + + } + + const data = { + metadata: { + version: 4.6, + type: 'Material', + generator: 'Material.toJSON' + } + }; + + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; + + if ( this.name !== '' ) data.name = this.name; + + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; + + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + + } + + if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; + if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; + if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; + + if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { + + data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; + + } + + if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { + + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; + + } + + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; + + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { + + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; + + } + + if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; + if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; + if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + + if ( this.lightMap && this.lightMap.isTexture ) { + + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; + + } + + if ( this.aoMap && this.aoMap.isTexture ) { + + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; + + } + + if ( this.bumpMap && this.bumpMap.isTexture ) { + + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; + + } + + if ( this.normalMap && this.normalMap.isTexture ) { + + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); + + } + + if ( this.displacementMap && this.displacementMap.isTexture ) { + + data.displacementMap = this.displacementMap.toJSON( meta ).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; + + } + + if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; + if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + + if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; + if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; + if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; + if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + + if ( this.envMap && this.envMap.isTexture ) { + + data.envMap = this.envMap.toJSON( meta ).uuid; + + if ( this.combine !== undefined ) data.combine = this.combine; + + } + + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + + if ( this.gradientMap && this.gradientMap.isTexture ) { + + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + + } + + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors ) data.vertexColors = true; + + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.transparent === true ) data.transparent = this.transparent; + + data.depthFunc = this.depthFunc; + data.depthTest = this.depthTest; + data.depthWrite = this.depthWrite; + data.colorWrite = this.colorWrite; + + data.stencilWrite = this.stencilWrite; + data.stencilWriteMask = this.stencilWriteMask; + data.stencilFunc = this.stencilFunc; + data.stencilRef = this.stencilRef; + data.stencilFuncMask = this.stencilFuncMask; + data.stencilFail = this.stencilFail; + data.stencilZFail = this.stencilZFail; + data.stencilZPass = this.stencilZPass; + + // rotation (SpriteMaterial) + if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; + + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + + if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; + + if ( this.dithering === true ) data.dithering = true; + + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; + if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass; + + if ( this.wireframe === true ) data.wireframe = this.wireframe; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + + if ( this.flatShading === true ) data.flatShading = this.flatShading; + + if ( this.visible === false ) data.visible = false; + + if ( this.toneMapped === false ) data.toneMapped = false; + + if ( this.fog === false ) data.fog = false; + + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + + // TODO: Copied from Object3D.toJSON + + function extractFromCache( cache ) { + + const values = []; + + for ( const key in cache ) { + + const data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + + return values; + + } + + if ( isRootObject ) { + + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; + + } + + return data; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + this.name = source.name; + + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; + + this.opacity = source.opacity; + this.transparent = source.transparent; + + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; + + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; + + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; + + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; + + if ( srcPlanes !== null ) { + + const n = srcPlanes.length; + dstPlanes = new Array( n ); + + for ( let i = 0; i !== n; ++ i ) { + + dstPlanes[ i ] = srcPlanes[ i ].clone(); + + } + + } + + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; + + this.shadowSide = source.shadowSide; + + this.colorWrite = source.colorWrite; + + this.precision = source.precision; + + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; + + this.dithering = source.dithering; + + this.alphaTest = source.alphaTest; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.forceSinglePass = source.forceSinglePass; + + this.visible = source.visible; + + this.toneMapped = source.toneMapped; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + + return this; + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + +} + +const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, + 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, + 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, + 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, + 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, + 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, + 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, + 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, + 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, + 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, + 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, + 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, + 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, + 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, + 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, + 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, + 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, + 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, + 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, + 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, + 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, + 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, + 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; + +const _hslA = { h: 0, s: 0, l: 0 }; +const _hslB = { h: 0, s: 0, l: 0 }; + +function hue2rgb( p, q, t ) { + + if ( t < 0 ) t += 1; + if ( t > 1 ) t -= 1; + if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; + if ( t < 1 / 2 ) return q; + if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); + return p; + +} + +class Color { + + constructor( r, g, b ) { + + this.isColor = true; + + this.r = 1; + this.g = 1; + this.b = 1; + + return this.set( r, g, b ); + + } + + set( r, g, b ) { + + if ( g === undefined && b === undefined ) { + + // r is THREE.Color, hex or string + + const value = r; + + if ( value && value.isColor ) { + + this.copy( value ); + + } else if ( typeof value === 'number' ) { + + this.setHex( value ); + + } else if ( typeof value === 'string' ) { + + this.setStyle( value ); + + } + + } else { + + this.setRGB( r, g, b ); + + } + + return this; + + } + + setScalar( scalar ) { + + this.r = scalar; + this.g = scalar; + this.b = scalar; + + return this; + + } + + setHex( hex, colorSpace = SRGBColorSpace ) { + + hex = Math.floor( hex ); + + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { + + this.r = r; + this.g = g; + this.b = b; + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { + + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); + + if ( s === 0 ) { + + this.r = this.g = this.b = l; + + } else { + + const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); + const q = ( 2 * l ) - p; + + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); + + } + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setStyle( style, colorSpace = SRGBColorSpace ) { + + function handleAlpha( string ) { + + if ( string === undefined ) return; + + if ( parseFloat( string ) < 1 ) { + + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + + } + + } + + + let m; + + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { -class Material extends EventDispatcher { + // rgb / hsl - constructor() { + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; - super(); + switch ( name ) { - this.isMaterial = true; + case 'rgb': + case 'rgba': - Object.defineProperty( this, 'id', { value: materialId ++ } ); + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.uuid = generateUUID(); + // rgb(255,0,0) rgba(255,0,0,0.5) - this.name = ''; - this.type = 'Material'; + handleAlpha( color[ 4 ] ); - this.blending = NormalBlending; - this.side = FrontSide; - this.vertexColors = false; + return this.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); - this.opacity = 1; - this.transparent = false; + } - this.blendSrc = SrcAlphaFactor; - this.blendDst = OneMinusSrcAlphaFactor; - this.blendEquation = AddEquation; - this.blendSrcAlpha = null; - this.blendDstAlpha = null; - this.blendEquationAlpha = null; + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.depthFunc = LessEqualDepth; - this.depthTest = true; - this.depthWrite = true; + // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.stencilWriteMask = 0xff; - this.stencilFunc = AlwaysStencilFunc; - this.stencilRef = 0; - this.stencilFuncMask = 0xff; - this.stencilFail = KeepStencilOp; - this.stencilZFail = KeepStencilOp; - this.stencilZPass = KeepStencilOp; - this.stencilWrite = false; + handleAlpha( color[ 4 ] ); - this.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); - this.shadowSide = null; + } - this.colorWrite = true; + break; - this.precision = null; // override the renderer's default precision for this material + case 'hsl': + case 'hsla': - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.dithering = false; + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - this.alphaToCoverage = false; - this.premultipliedAlpha = false; - this.forceSinglePass = false; + handleAlpha( color[ 4 ] ); - this.visible = true; + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); - this.toneMapped = true; + } - this.userData = {}; + break; - this.version = 0; + default: - this._alphaTest = 0; + console.warn( 'THREE.Color: Unknown color model ' + style ); - } + } - get alphaTest() { + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { - return this._alphaTest; + // hex color - } + const hex = m[ 1 ]; + const size = hex.length; - set alphaTest( value ) { + if ( size === 3 ) { - if ( this._alphaTest > 0 !== value > 0 ) { + // #ff0 + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); - this.version ++; + } else if ( size === 6 ) { - } + // #ff0000 + return this.setHex( parseInt( hex, 16 ), colorSpace ); - this._alphaTest = value; + } else { - } + console.warn( 'THREE.Color: Invalid hex color ' + style ); - onBuild( /* shaderobject, renderer */ ) {} + } - onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + } else if ( style && style.length > 0 ) { - onBeforeCompile( /* shaderobject, renderer */ ) {} + return this.setColorName( style, colorSpace ); - customProgramCacheKey() { + } - return this.onBeforeCompile.toString(); + return this; } - setValues( values ) { + setColorName( style, colorSpace = SRGBColorSpace ) { - if ( values === undefined ) return; + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; - for ( const key in values ) { + if ( hex !== undefined ) { - const newValue = values[ key ]; + // red + this.setHex( hex, colorSpace ); - if ( newValue === undefined ) { + } else { - console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' ); - continue; + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); - } + } - const currentValue = this[ key ]; + return this; - if ( currentValue === undefined ) { + } - console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' ); - continue; + clone() { - } + return new this.constructor( this.r, this.g, this.b ); - if ( currentValue && currentValue.isColor ) { + } - currentValue.set( newValue ); + copy( color ) { - } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + this.r = color.r; + this.g = color.g; + this.b = color.b; - currentValue.copy( newValue ); + return this; - } else { + } - this[ key ] = newValue; + copySRGBToLinear( color ) { - } + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); - } + return this; } - toJSON( meta ) { + copyLinearToSRGB( color ) { - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); - if ( isRootObject ) { + return this; - meta = { - textures: {}, - images: {} - }; + } - } + convertSRGBToLinear() { - const data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' - } - }; + this.copySRGBToLinear( this ); - // standard Material serialization - data.uuid = this.uuid; - data.type = this.type; + return this; - if ( this.name !== '' ) data.name = this.name; + } - if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + convertLinearToSRGB() { - if ( this.roughness !== undefined ) data.roughness = this.roughness; - if ( this.metalness !== undefined ) data.metalness = this.metalness; + this.copyLinearToSRGB( this ); - if ( this.sheen !== undefined ) data.sheen = this.sheen; - if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); - if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; - if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); - if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + return this; - if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); - if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; - if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); - if ( this.shininess !== undefined ) data.shininess = this.shininess; - if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; - if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + } - if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + getHex( colorSpace = SRGBColorSpace ) { - data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - } + return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color.b * 255, 0, 255 ) ); - if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + } - data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + getHexString( colorSpace = SRGBColorSpace ) { - } + return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); - if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + } - data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; - data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { - } + // h,s,l ranges are in 0.0 - 1.0 - if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; - if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; - if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { + const r = _color.r, g = _color.g, b = _color.b; - data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); - } + let hue, saturation; + const lightness = ( min + max ) / 2.0; - if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { + if ( min === max ) { - data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; + hue = 0; + saturation = 0; - } + } else { - if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; - if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; - if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + const delta = max - min; - if ( this.lightMap && this.lightMap.isTexture ) { + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - data.lightMap = this.lightMap.toJSON( meta ).uuid; - data.lightMapIntensity = this.lightMapIntensity; + switch ( max ) { - } + case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; + case g: hue = ( b - r ) / delta + 2; break; + case b: hue = ( r - g ) / delta + 4; break; - if ( this.aoMap && this.aoMap.isTexture ) { + } - data.aoMap = this.aoMap.toJSON( meta ).uuid; - data.aoMapIntensity = this.aoMapIntensity; + hue /= 6; } - if ( this.bumpMap && this.bumpMap.isTexture ) { - - data.bumpMap = this.bumpMap.toJSON( meta ).uuid; - data.bumpScale = this.bumpScale; + target.h = hue; + target.s = saturation; + target.l = lightness; - } + return target; - if ( this.normalMap && this.normalMap.isTexture ) { + } - data.normalMap = this.normalMap.toJSON( meta ).uuid; - data.normalMapType = this.normalMapType; - data.normalScale = this.normalScale.toArray(); + getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { - } + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.displacementMap && this.displacementMap.isTexture ) { + target.r = _color.r; + target.g = _color.g; + target.b = _color.b; - data.displacementMap = this.displacementMap.toJSON( meta ).uuid; - data.displacementScale = this.displacementScale; - data.displacementBias = this.displacementBias; + return target; - } + } - if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; - if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + getStyle( colorSpace = SRGBColorSpace ) { - if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; - if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; - if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; - if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.envMap && this.envMap.isTexture ) { + const r = _color.r, g = _color.g, b = _color.b; - data.envMap = this.envMap.toJSON( meta ).uuid; + if ( colorSpace !== SRGBColorSpace ) { - if ( this.combine !== undefined ) data.combine = this.combine; + // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; } - if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; - if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; - if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; - if ( this.gradientMap && this.gradientMap.isTexture ) { + } - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + offsetHSL( h, s, l ) { - } + this.getHSL( _hslA ); - if ( this.transmission !== undefined ) data.transmission = this.transmission; - if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; - if ( this.thickness !== undefined ) data.thickness = this.thickness; - if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; - if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; - if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + _hslA.h += h; _hslA.s += s; _hslA.l += l; - if ( this.size !== undefined ) data.size = this.size; - if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; - if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + this.setHSL( _hslA.h, _hslA.s, _hslA.l ); - if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.side !== FrontSide ) data.side = this.side; - if ( this.vertexColors ) data.vertexColors = true; + return this; - if ( this.opacity < 1 ) data.opacity = this.opacity; - if ( this.transparent === true ) data.transparent = this.transparent; + } - data.depthFunc = this.depthFunc; - data.depthTest = this.depthTest; - data.depthWrite = this.depthWrite; - data.colorWrite = this.colorWrite; + add( color ) { - data.stencilWrite = this.stencilWrite; - data.stencilWriteMask = this.stencilWriteMask; - data.stencilFunc = this.stencilFunc; - data.stencilRef = this.stencilRef; - data.stencilFuncMask = this.stencilFuncMask; - data.stencilFail = this.stencilFail; - data.stencilZFail = this.stencilZFail; - data.stencilZPass = this.stencilZPass; + this.r += color.r; + this.g += color.g; + this.b += color.b; - // rotation (SpriteMaterial) - if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; + return this; - if ( this.polygonOffset === true ) data.polygonOffset = true; - if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; - if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + } - if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; - if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; - if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; - if ( this.scale !== undefined ) data.scale = this.scale; + addColors( color1, color2 ) { - if ( this.dithering === true ) data.dithering = true; + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; - if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; - if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; - if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; - if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass; + return this; - if ( this.wireframe === true ) data.wireframe = this.wireframe; - if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; - if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; - if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + } - if ( this.flatShading === true ) data.flatShading = this.flatShading; + addScalar( s ) { - if ( this.visible === false ) data.visible = false; + this.r += s; + this.g += s; + this.b += s; - if ( this.toneMapped === false ) data.toneMapped = false; + return this; - if ( this.fog === false ) data.fog = false; + } - if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + sub( color ) { - // TODO: Copied from Object3D.toJSON + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); - function extractFromCache( cache ) { + return this; - const values = []; + } - for ( const key in cache ) { + multiply( color ) { - const data = cache[ key ]; - delete data.metadata; - values.push( data ); + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; - } + return this; - return values; + } - } + multiplyScalar( s ) { - if ( isRootObject ) { + this.r *= s; + this.g *= s; + this.b *= s; - const textures = extractFromCache( meta.textures ); - const images = extractFromCache( meta.images ); + return this; - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; + } - } + lerp( color, alpha ) { - return data; + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; + + return this; } - clone() { + lerpColors( color1, color2, alpha ) { - return new this.constructor().copy( this ); + this.r = color1.r + ( color2.r - color1.r ) * alpha; + this.g = color1.g + ( color2.g - color1.g ) * alpha; + this.b = color1.b + ( color2.b - color1.b ) * alpha; + + return this; } - copy( source ) { + lerpHSL( color, alpha ) { - this.name = source.name; + this.getHSL( _hslA ); + color.getHSL( _hslB ); - this.blending = source.blending; - this.side = source.side; - this.vertexColors = source.vertexColors; + const h = lerp( _hslA.h, _hslB.h, alpha ); + const s = lerp( _hslA.s, _hslB.s, alpha ); + const l = lerp( _hslA.l, _hslB.l, alpha ); - this.opacity = source.opacity; - this.transparent = source.transparent; + this.setHSL( h, s, l ); - this.blendSrc = source.blendSrc; - this.blendDst = source.blendDst; - this.blendEquation = source.blendEquation; - this.blendSrcAlpha = source.blendSrcAlpha; - this.blendDstAlpha = source.blendDstAlpha; - this.blendEquationAlpha = source.blendEquationAlpha; + return this; - this.depthFunc = source.depthFunc; - this.depthTest = source.depthTest; - this.depthWrite = source.depthWrite; + } - this.stencilWriteMask = source.stencilWriteMask; - this.stencilFunc = source.stencilFunc; - this.stencilRef = source.stencilRef; - this.stencilFuncMask = source.stencilFuncMask; - this.stencilFail = source.stencilFail; - this.stencilZFail = source.stencilZFail; - this.stencilZPass = source.stencilZPass; - this.stencilWrite = source.stencilWrite; + setFromVector3( v ) { - const srcPlanes = source.clippingPlanes; - let dstPlanes = null; + this.r = v.x; + this.g = v.y; + this.b = v.z; - if ( srcPlanes !== null ) { + return this; - const n = srcPlanes.length; - dstPlanes = new Array( n ); + } - for ( let i = 0; i !== n; ++ i ) { + applyMatrix3( m ) { - dstPlanes[ i ] = srcPlanes[ i ].clone(); + const r = this.r, g = this.g, b = this.b; + const e = m.elements; - } + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; - } + return this; - this.clippingPlanes = dstPlanes; - this.clipIntersection = source.clipIntersection; - this.clipShadows = source.clipShadows; + } - this.shadowSide = source.shadowSide; + equals( c ) { - this.colorWrite = source.colorWrite; + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); - this.precision = source.precision; + } - this.polygonOffset = source.polygonOffset; - this.polygonOffsetFactor = source.polygonOffsetFactor; - this.polygonOffsetUnits = source.polygonOffsetUnits; + fromArray( array, offset = 0 ) { - this.dithering = source.dithering; + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; - this.alphaTest = source.alphaTest; - this.alphaToCoverage = source.alphaToCoverage; - this.premultipliedAlpha = source.premultipliedAlpha; - this.forceSinglePass = source.forceSinglePass; + return this; - this.visible = source.visible; + } - this.toneMapped = source.toneMapped; + toArray( array = [], offset = 0 ) { - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); return this; } - dispose() { + toJSON() { - this.dispatchEvent( { type: 'dispose' } ); + return this.getHex(); } - set needsUpdate( value ) { + *[ Symbol.iterator ]() { - if ( value === true ) this.version ++; + yield this.r; + yield this.g; + yield this.b; } } +const _color = /*@__PURE__*/ new Color(); + +Color.NAMES = _colorKeywords; + class MeshBasicMaterial extends Material { constructor( parameters ) { @@ -9281,7 +9540,176 @@ class MeshBasicMaterial extends Material { } -const _vector$9 = /*@__PURE__*/ new Vector3(); +// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + +const _tables = /*@__PURE__*/ _generateTables(); + +function _generateTables() { + + // float32 to float16 helpers + + const buffer = new ArrayBuffer( 4 ); + const floatView = new Float32Array( buffer ); + const uint32View = new Uint32Array( buffer ); + + const baseTable = new Uint32Array( 512 ); + const shiftTable = new Uint32Array( 512 ); + + for ( let i = 0; i < 256; ++ i ) { + + const e = i - 127; + + // very small number (0, -0) + + if ( e < - 27 ) { + + baseTable[ i ] = 0x0000; + baseTable[ i | 0x100 ] = 0x8000; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // small number (denorm) + + } else if ( e < - 14 ) { + + baseTable[ i ] = 0x0400 >> ( - e - 14 ); + baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; + shiftTable[ i ] = - e - 1; + shiftTable[ i | 0x100 ] = - e - 1; + + // normal number + + } else if ( e <= 15 ) { + + baseTable[ i ] = ( e + 15 ) << 10; + baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + // large number (Infinity, -Infinity) + + } else if ( e < 128 ) { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // stay (NaN, Infinity, -Infinity) + + } else { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + } + + } + + // float16 to float32 helpers + + const mantissaTable = new Uint32Array( 2048 ); + const exponentTable = new Uint32Array( 64 ); + const offsetTable = new Uint32Array( 64 ); + + for ( let i = 1; i < 1024; ++ i ) { + + let m = i << 13; // zero pad mantissa bits + let e = 0; // zero exponent + + // normalized + while ( ( m & 0x00800000 ) === 0 ) { + + m <<= 1; + e -= 0x00800000; // decrement exponent + + } + + m &= ~ 0x00800000; // clear leading 1 bit + e += 0x38800000; // adjust bias + + mantissaTable[ i ] = m | e; + + } + + for ( let i = 1024; i < 2048; ++ i ) { + + mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); + + } + + for ( let i = 1; i < 31; ++ i ) { + + exponentTable[ i ] = i << 23; + + } + + exponentTable[ 31 ] = 0x47800000; + exponentTable[ 32 ] = 0x80000000; + + for ( let i = 33; i < 63; ++ i ) { + + exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); + + } + + exponentTable[ 63 ] = 0xc7800000; + + for ( let i = 1; i < 64; ++ i ) { + + if ( i !== 32 ) { + + offsetTable[ i ] = 1024; + + } + + } + + return { + floatView: floatView, + uint32View: uint32View, + baseTable: baseTable, + shiftTable: shiftTable, + mantissaTable: mantissaTable, + exponentTable: exponentTable, + offsetTable: offsetTable + }; + +} + +// float32 to float16 + +function toHalfFloat( val ) { + + if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); + + val = clamp( val, - 65504, 65504 ); + + _tables.floatView[ 0 ] = val; + const f = _tables.uint32View[ 0 ]; + const e = ( f >> 23 ) & 0x1ff; + return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); + +} + +// float16 to float32 + +function fromHalfFloat( val ) { + + const m = val >> 10; + _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; + return _tables.floatView[ 0 ]; + +} + +const DataUtils = { + toHalfFloat: toHalfFloat, + fromHalfFloat: fromHalfFloat, +}; + +const _vector$8 = /*@__PURE__*/ new Vector3(); const _vector2$1 = /*@__PURE__*/ new Vector2(); class BufferAttribute { @@ -9380,10 +9808,10 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); - _vector$9.applyMatrix3( m ); + _vector$8.fromBufferAttribute( this, i ); + _vector$8.applyMatrix3( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9397,11 +9825,11 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.applyMatrix4( m ); + _vector$8.applyMatrix4( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9413,11 +9841,11 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.applyNormalMatrix( m ); + _vector$8.applyNormalMatrix( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9429,11 +9857,11 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.transformDirection( m ); + _vector$8.transformDirection( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9621,27 +10049,25 @@ class BufferAttribute { } - // @deprecated - - copyColorsArray() { + copyColorsArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyColorsArray() was removed in r144.' ); } - copyVector2sArray() { + copyVector2sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector2sArray() was removed in r144.' ); } - copyVector3sArray() { + copyVector3sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector3sArray() was removed in r144.' ); } - copyVector4sArray() { + copyVector4sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector4sArray() was removed in r144.' ); @@ -9657,6 +10083,18 @@ class Int8BufferAttribute extends BufferAttribute { super( new Int8Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9667,6 +10105,18 @@ class Uint8BufferAttribute extends BufferAttribute { super( new Uint8Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9687,6 +10137,18 @@ class Int16BufferAttribute extends BufferAttribute { super( new Int16Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9697,6 +10159,18 @@ class Uint16BufferAttribute extends BufferAttribute { super( new Uint16Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9731,6 +10205,146 @@ class Float16BufferAttribute extends BufferAttribute { } + getX( index ) { + + let x = fromHalfFloat( this.array[ index * this.itemSize ] ); + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; + + } + + setX( index, x ) { + + if ( this.normalized ) x = normalize( x, this.array ); + + this.array[ index * this.itemSize ] = toHalfFloat( x ); + + return this; + + } + + getY( index ) { + + let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; + + } + + setY( index, y ) { + + if ( this.normalized ) y = normalize( y, this.array ); + + this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); + + return this; + + } + + getZ( index ) { + + let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; + + } + + setZ( index, z ) { + + if ( this.normalized ) z = normalize( z, this.array ); + + this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); + + return this; + + } + + getW( index ) { + + let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; + + } + + setW( index, w ) { + + if ( this.normalized ) w = normalize( w, this.array ); + + this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); + + return this; + + } + + setXY( index, x, y ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + + return this; + + } + + setXYZ( index, x, y, z ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + + return this; + + } + + setXYZW( index, x, y, z, w ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + this.array[ index + 3 ] = toHalfFloat( w ); + + return this; + + } + } @@ -9761,7 +10375,7 @@ const _obj = /*@__PURE__*/ new Object3D(); const _offset = /*@__PURE__*/ new Vector3(); const _box$1 = /*@__PURE__*/ new Box3(); const _boxMorphTargets = /*@__PURE__*/ new Box3(); -const _vector$8 = /*@__PURE__*/ new Vector3(); +const _vector$7 = /*@__PURE__*/ new Vector3(); class BufferGeometry extends EventDispatcher { @@ -10070,11 +10684,11 @@ class BufferGeometry extends EventDispatcher { if ( this.morphTargetsRelative ) { - _vector$8.addVectors( this.boundingBox.min, _box$1.min ); - this.boundingBox.expandByPoint( _vector$8 ); + _vector$7.addVectors( this.boundingBox.min, _box$1.min ); + this.boundingBox.expandByPoint( _vector$7 ); - _vector$8.addVectors( this.boundingBox.max, _box$1.max ); - this.boundingBox.expandByPoint( _vector$8 ); + _vector$7.addVectors( this.boundingBox.max, _box$1.max ); + this.boundingBox.expandByPoint( _vector$7 ); } else { @@ -10141,11 +10755,11 @@ class BufferGeometry extends EventDispatcher { if ( this.morphTargetsRelative ) { - _vector$8.addVectors( _box$1.min, _boxMorphTargets.min ); - _box$1.expandByPoint( _vector$8 ); + _vector$7.addVectors( _box$1.min, _boxMorphTargets.min ); + _box$1.expandByPoint( _vector$7 ); - _vector$8.addVectors( _box$1.max, _boxMorphTargets.max ); - _box$1.expandByPoint( _vector$8 ); + _vector$7.addVectors( _box$1.max, _boxMorphTargets.max ); + _box$1.expandByPoint( _vector$7 ); } else { @@ -10167,9 +10781,9 @@ class BufferGeometry extends EventDispatcher { for ( let i = 0, il = position.count; i < il; i ++ ) { - _vector$8.fromBufferAttribute( position, i ); + _vector$7.fromBufferAttribute( position, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) ); } @@ -10184,16 +10798,16 @@ class BufferGeometry extends EventDispatcher { for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { - _vector$8.fromBufferAttribute( morphAttribute, j ); + _vector$7.fromBufferAttribute( morphAttribute, j ); if ( morphTargetsRelative ) { _offset.fromBufferAttribute( position, j ); - _vector$8.add( _offset ); + _vector$7.add( _offset ); } - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) ); } @@ -10470,11 +11084,9 @@ class BufferGeometry extends EventDispatcher { } - // @deprecated since r144 - - merge() { + merge() { // @deprecated, r144 - console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeBufferGeometries() instead.' ); + console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeGeometries() instead.' ); return this; } @@ -10485,11 +11097,11 @@ class BufferGeometry extends EventDispatcher { for ( let i = 0, il = normals.count; i < il; i ++ ) { - _vector$8.fromBufferAttribute( normals, i ); + _vector$7.fromBufferAttribute( normals, i ); - _vector$8.normalize(); + _vector$7.normalize(); - normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); + normals.setXYZ( i, _vector$7.x, _vector$7.y, _vector$7.z ); } @@ -10601,7 +11213,7 @@ class BufferGeometry extends EventDispatcher { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'BufferGeometry', generator: 'BufferGeometry.toJSON' } @@ -10817,10 +11429,6 @@ class BufferGeometry extends EventDispatcher { this.userData = source.userData; - // geometry generator parameters - - if ( source.parameters !== undefined ) this.parameters = Object.assign( {}, source.parameters ); - return this; } @@ -10833,9 +11441,10 @@ class BufferGeometry extends EventDispatcher { } -const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); -const _ray$2 = /*@__PURE__*/ new Ray(); -const _sphere$3 = /*@__PURE__*/ new Sphere(); +const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); +const _ray$3 = /*@__PURE__*/ new Ray(); +const _sphere$5 = /*@__PURE__*/ new Sphere(); +const _sphereHitAt = /*@__PURE__*/ new Vector3(); const _vA$1 = /*@__PURE__*/ new Vector3(); const _vB$1 = /*@__PURE__*/ new Vector3(); @@ -10848,6 +11457,10 @@ const _uvA$1 = /*@__PURE__*/ new Vector2(); const _uvB$1 = /*@__PURE__*/ new Vector2(); const _uvC$1 = /*@__PURE__*/ new Vector2(); +const _normalA = /*@__PURE__*/ new Vector3(); +const _normalB = /*@__PURE__*/ new Vector3(); +const _normalC = /*@__PURE__*/ new Vector3(); + const _intersectionPoint = /*@__PURE__*/ new Vector3(); const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); @@ -10962,12 +11575,6 @@ class Mesh extends Object3D { } - if ( this.isSkinnedMesh ) { - - this.boneTransform( index, target ); - - } - return target; } @@ -10980,34 +11587,56 @@ class Mesh extends Object3D { if ( material === undefined ) return; - // Checking boundingSphere distance to ray + // test with bounding sphere in world space if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - _sphere$3.copy( geometry.boundingSphere ); - _sphere$3.applyMatrix4( matrixWorld ); + _sphere$5.copy( geometry.boundingSphere ); + _sphere$5.applyMatrix4( matrixWorld ); - if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; + // check distance from ray origin to bounding sphere - // + _ray$3.copy( raycaster.ray ).recast( raycaster.near ); - _inverseMatrix$2.copy( matrixWorld ).invert(); - _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); + if ( _sphere$5.containsPoint( _ray$3.origin ) === false ) { + + if ( _ray$3.intersectSphere( _sphere$5, _sphereHitAt ) === null ) return; + + if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; + + } + + // convert ray to local space of mesh + + _inverseMatrix$3.copy( matrixWorld ).invert(); + _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); - // Check boundingBox before continuing + // test with bounding box in local space if ( geometry.boundingBox !== null ) { - if ( _ray$2.intersectsBox( geometry.boundingBox ) === false ) return; + if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; } + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$3 ); + + } + + _computeIntersections( raycaster, intersects, rayLocalSpace ) { + let intersection; + const geometry = this.geometry; + const material = this.material; + const index = geometry.index; const position = geometry.attributes.position; const uv = geometry.attributes.uv; - const uv2 = geometry.attributes.uv2; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; const groups = geometry.groups; const drawRange = geometry.drawRange; @@ -11031,7 +11660,7 @@ class Mesh extends Object3D { const b = index.getX( j + 1 ); const c = index.getX( j + 2 ); - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11056,7 +11685,7 @@ class Mesh extends Object3D { const b = index.getX( i + 1 ); const c = index.getX( i + 2 ); - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11089,7 +11718,7 @@ class Mesh extends Object3D { const b = j + 1; const c = j + 2; - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11114,7 +11743,7 @@ class Mesh extends Object3D { const b = i + 1; const c = i + 2; - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11164,7 +11793,7 @@ function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point } -function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, uv2, a, b, c ) { +function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { object.getVertexPosition( a, _vA$1 ); object.getVertexPosition( b, _vB$1 ); @@ -11180,17 +11809,34 @@ function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, _uvB$1.fromBufferAttribute( uv, b ); _uvC$1.fromBufferAttribute( uv, c ); - intersection.uv = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); } - if ( uv2 ) { + if ( uv1 ) { - _uvA$1.fromBufferAttribute( uv2, a ); - _uvB$1.fromBufferAttribute( uv2, b ); - _uvC$1.fromBufferAttribute( uv2, c ); + _uvA$1.fromBufferAttribute( uv1, a ); + _uvB$1.fromBufferAttribute( uv1, b ); + _uvC$1.fromBufferAttribute( uv1, c ); - intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv2 = intersection.uv1; // @deprecated, r152 + + } + + if ( normal ) { + + _normalA.fromBufferAttribute( normal, a ); + _normalB.fromBufferAttribute( normal, b ); + _normalC.fromBufferAttribute( normal, c ); + + intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); + + if ( intersection.normal.dot( ray.direction ) > 0 ) { + + intersection.normal.multiplyScalar( - 1 ); + + } } @@ -11369,6 +12015,16 @@ class BoxGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); @@ -11398,7 +12054,16 @@ function cloneUniforms( src ) { property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion ) ) { - dst[ u ][ p ] = property.clone(); + if ( property.isRenderTargetTexture ) { + + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; + + } else { + + dst[ u ][ p ] = property.clone(); + + } } else if ( Array.isArray( property ) ) { @@ -11457,7 +12122,7 @@ function getUnlitUniformColorSpace( renderer ) { if ( renderer.getRenderTarget() === null ) { // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 - return renderer.outputEncoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; + return renderer.outputColorSpace; } @@ -11499,6 +12164,8 @@ class ShaderMaterial extends Material { this.lights = false; // set to use scene lights this.clipping = false; // set to use user-defined clipping planes + this.forceSinglePass = true; + this.extensions = { derivatives: false, // set to use derivatives fragDepth: false, // set to use fragment depth values @@ -11511,7 +12178,7 @@ class ShaderMaterial extends Material { this.defaultAttributeValues = { 'color': [ 1, 1, 1 ], 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] + 'uv1': [ 0, 0 ] }; this.index0AttributeName = undefined; @@ -11632,6 +12299,9 @@ class ShaderMaterial extends Material { data.vertexShader = this.vertexShader; data.fragmentShader = this.fragmentShader; + data.lights = this.lights; + data.clipping = this.clipping; + const extensions = {}; for ( const key in this.extensions ) { @@ -12045,12 +12715,12 @@ class CubeCamera extends Object3D { class CubeTexture extends Texture { - constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { images = images !== undefined ? images : []; mapping = mapping !== undefined ? mapping : CubeReflectionMapping; - super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCubeTexture = true; @@ -12083,7 +12753,15 @@ class WebGLCubeRenderTarget extends WebGLRenderTarget { const image = { width: size, height: size, depth: 1 }; const images = [ image, image, image, image, image, image ]; - this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( options.encoding !== undefined ) { + + // @deprecated, r152 + warnOnce( 'THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; + + } + + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, @@ -12103,7 +12781,7 @@ class WebGLCubeRenderTarget extends WebGLRenderTarget { fromEquirectangularTexture( renderer, texture ) { this.texture.type = texture.type; - this.texture.encoding = texture.encoding; + this.texture.colorSpace = texture.colorSpace; this.texture.generateMipmaps = texture.generateMipmaps; this.texture.minFilter = texture.minFilter; @@ -12308,7 +12986,7 @@ class Plane { projectPoint( point, target ) { - return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); } @@ -12340,7 +13018,7 @@ class Plane { } - return target.copy( direction ).multiplyScalar( t ).add( line.start ); + return target.copy( line.start ).addScaledVector( direction, t ); } @@ -12409,8 +13087,8 @@ class Plane { } -const _sphere$2 = /*@__PURE__*/ new Sphere(); -const _vector$7 = /*@__PURE__*/ new Vector3(); +const _sphere$4 = /*@__PURE__*/ new Sphere(); +const _vector$6 = /*@__PURE__*/ new Vector3(); class Frustum { @@ -12471,23 +13149,33 @@ class Frustum { intersectsObject( object ) { - const geometry = object.geometry; + if ( object.boundingSphere !== undefined ) { - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + + _sphere$4.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } else { - _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + const geometry = object.geometry; + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere$4.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } - return this.intersectsSphere( _sphere$2 ); + return this.intersectsSphere( _sphere$4 ); } intersectsSprite( sprite ) { - _sphere$2.center.set( 0, 0, 0 ); - _sphere$2.radius = 0.7071067811865476; - _sphere$2.applyMatrix4( sprite.matrixWorld ); + _sphere$4.center.set( 0, 0, 0 ); + _sphere$4.radius = 0.7071067811865476; + _sphere$4.applyMatrix4( sprite.matrixWorld ); - return this.intersectsSphere( _sphere$2 ); + return this.intersectsSphere( _sphere$4 ); } @@ -12523,11 +13211,11 @@ class Frustum { // corner at max distance - _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; - _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; - _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; + _vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x; + _vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y; + _vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z; - if ( plane.distanceToPoint( _vector$7 ) < 0 ) { + if ( plane.distanceToPoint( _vector$6 ) < 0 ) { return false; @@ -12886,6 +13574,16 @@ class PlaneGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); @@ -12894,7 +13592,7 @@ class PlaneGeometry extends BufferGeometry { } -var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif"; +var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; @@ -12902,7 +13600,7 @@ var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTes var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; -var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; +var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; @@ -12910,11 +13608,11 @@ var begin_vertex = "vec3 transformed = vec3( position );"; var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; -var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\n\tvec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif"; +var bsdfs = "float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated"; var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif"; -var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; +var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif"; @@ -12932,7 +13630,7 @@ var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\ var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif"; -var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}"; +var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; @@ -12940,9 +13638,9 @@ var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_I var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; -var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif"; +var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; -var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; +var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; @@ -12970,7 +13668,7 @@ var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying flo var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}"; -var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; +var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; @@ -12978,9 +13676,9 @@ var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert"; -var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; +var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; -var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, worldNormal );\n\t\t\t#endif\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\t#else\n\t\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec );\n\t\t\t#endif\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif"; +var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; @@ -12990,13 +13688,13 @@ var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; -var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; +var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tanisotropyV /= material.anisotropy;\n\tmaterial.anisotropy = saturate( material.anisotropy );\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x - tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x + tbn[ 0 ] * anisotropyV.y;\n#endif"; -var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; +var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; -var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && ( defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE ) )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; +var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometry.viewDir, geometry.normal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; @@ -13008,15 +13706,15 @@ var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_ var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif"; -var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; +var map_fragment = "#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, vMapUv );\n#endif"; var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; -var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; +var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; -var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; +var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; -var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; +var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; @@ -13028,9 +13726,9 @@ var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTar var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif"; -var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;"; +var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal, vNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 geometryNormal = normal;"; -var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; +var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; @@ -13038,19 +13736,19 @@ var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif"; -var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif"; +var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif"; var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif"; -var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif"; +var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif"; -var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif"; +var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif"; var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; -var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; +var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; -var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}"; +var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; @@ -13060,13 +13758,13 @@ var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_F var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif"; -var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; +var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; -var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; +var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; -var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; +var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; @@ -13080,35 +13778,29 @@ var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif"; -var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; +var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; -var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; - -var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif"; - -var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; - -var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif"; +var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; -var uv_pars_vertex = "#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif"; +var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; -var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; +var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; -var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; +var uv_pars_fragment = "#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; -var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif"; +var uv_pars_vertex = "#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; -var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif"; +var uv_vertex = "#ifdef USE_UV\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif"; var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; -const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; +const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; const vertex$g = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; @@ -13130,49 +13822,45 @@ const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; -const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; +const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; -const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; +const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; -const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; -<<<<<<< HEAD -const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -======= +const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; -const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; ->>>>>>> mrdoob-dev +const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; +const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; -const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; const fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$2 = "#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$2 = "#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; +const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"; @@ -13281,9 +13969,6 @@ const ShaderChunk = { uv_pars_fragment: uv_pars_fragment, uv_pars_vertex: uv_pars_vertex, uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, worldpos_vertex: worldpos_vertex, background_vert: vertex$h, @@ -13334,10 +14019,11 @@ const UniformsLib = { opacity: { value: 1.0 }, map: { value: null }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() }, - uv2Transform: { value: /*@__PURE__*/ new Matrix3() }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } }, @@ -13345,6 +14031,7 @@ const UniformsLib = { specularmap: { specularMap: { value: null }, + specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -13361,26 +14048,23 @@ const UniformsLib = { aomap: { aoMap: { value: null }, - aoMapIntensity: { value: 1 } + aoMapIntensity: { value: 1 }, + aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, lightmap: { lightMap: { value: null }, - lightMapIntensity: { value: 1 } - - }, - - emissivemap: { - - emissiveMap: { value: null } + lightMapIntensity: { value: 1 }, + lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, bumpmap: { bumpMap: { value: null }, + bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, bumpScale: { value: 1 } }, @@ -13388,6 +14072,7 @@ const UniformsLib = { normalmap: { normalMap: { value: null }, + normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } }, @@ -13395,20 +14080,30 @@ const UniformsLib = { displacementmap: { displacementMap: { value: null }, + displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, displacementScale: { value: 1 }, displacementBias: { value: 0 } }, - roughnessmap: { + emissivemap: { - roughnessMap: { value: null } + emissiveMap: { value: null }, + emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, metalnessmap: { - metalnessMap: { value: null } + metalnessMap: { value: null }, + metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } + + }, + + roughnessmap: { + + roughnessMap: { value: null }, + roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -13515,6 +14210,7 @@ const UniformsLib = { scale: { value: 1.0 }, map: { value: null }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaTest: { value: 0 }, uvTransform: { value: /*@__PURE__*/ new Matrix3() } @@ -13527,9 +14223,10 @@ const UniformsLib = { center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, rotation: { value: 0.0 }, map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, - alphaTest: { value: 0 }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() } + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } } @@ -13835,33 +14532,47 @@ ShaderLib.physical = { { clearcoat: { value: 0 }, clearcoatMap: { value: null }, + clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalMap: { value: null }, + clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, clearcoatRoughness: { value: 0 }, clearcoatRoughnessMap: { value: null }, - clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, - clearcoatNormalMap: { value: null }, + clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescence: { value: 0 }, iridescenceMap: { value: null }, + iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescenceIOR: { value: 1.3 }, iridescenceThicknessMinimum: { value: 100 }, iridescenceThicknessMaximum: { value: 400 }, iridescenceThicknessMap: { value: null }, + iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheen: { value: 0 }, sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, sheenColorMap: { value: null }, + sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheenRoughness: { value: 1 }, sheenRoughnessMap: { value: null }, + sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmission: { value: 0 }, transmissionMap: { value: null }, + transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, transmissionSamplerMap: { value: null }, thickness: { value: 0 }, thicknessMap: { value: null }, + thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, attenuationDistance: { value: 0 }, attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, - specularIntensity: { value: 1 }, - specularIntensityMap: { value: null }, specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, specularColorMap: { value: null }, + specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, + anisotropyMap: { value: null }, + anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, } ] ), @@ -13896,26 +14607,35 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, } - // Ignore background in AR - // TODO: Reconsider this. + if ( background === null ) { - const xr = renderer.xr; - const session = xr.getSession && xr.getSession(); + setClear( clearColor, clearAlpha ); - if ( session && session.environmentBlendMode === 'additive' ) { + } else if ( background && background.isColor ) { - background = null; + setClear( background, 1 ); + forceClear = true; } - if ( background === null ) { + const xr = renderer.xr; + const environmentBlendMode = xr.getEnvironmentBlendMode(); - setClear( clearColor, clearAlpha ); + switch ( environmentBlendMode ) { - } else if ( background && background.isColor ) { + case 'opaque': + forceClear = true; + break; - setClear( background, 1 ); - forceClear = true; + case 'additive': + state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); + forceClear = true; + break; + + case 'alpha-blend': + state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); + forceClear = true; + break; } @@ -13971,7 +14691,7 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - boxMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + boxMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( currentBackground !== background || currentBackgroundVersion !== background.version || @@ -14027,7 +14747,7 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, planeMesh.material.uniforms.t2D.value = background; planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - planeMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + planeMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( background.matrixAutoUpdate === true ) { @@ -14414,9 +15134,9 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { } - function vertexAttribPointer( index, size, type, normalized, stride, offset ) { + function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { - if ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT ) ) { + if ( integer === true ) { gl.vertexAttribIPointer( index, size, type, stride, offset ); @@ -14474,6 +15194,10 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { const type = attribute.type; const bytesPerElement = attribute.bytesPerElement; + // check for integer attributes (WebGL 2 only) + + const integer = ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ) ); + if ( geometryAttribute.isInterleavedBufferAttribute ) { const data = geometryAttribute.data; @@ -14514,7 +15238,8 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { type, normalized, stride * bytesPerElement, - ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement + ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, + integer ); } @@ -14555,7 +15280,8 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { type, normalized, size * bytesPerElement, - ( size / programAttribute.locationSize ) * i * bytesPerElement + ( size / programAttribute.locationSize ) * i * bytesPerElement, + integer ); } @@ -14831,7 +15557,7 @@ function WebGLCapabilities( gl, extensions, parameters ) { } - const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; + const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl.constructor.name === 'WebGL2RenderingContext'; let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; const maxPrecision = getMaxPrecision( precision ); @@ -15368,28 +16094,11 @@ class PMREMGenerator { */ fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { -<<<<<<< HEAD - - fromScene(scene, sigma = 0, near = 0.1, far = 100, cubeUVRenderTarget = null, pingPongRenderTarget = null) { - _oldTarget = this._renderer.getRenderTarget(); - - if (!cubeUVRenderTarget) { - cubeUVRenderTarget = this._allocateTargets(); - } - - if (pingPongRenderTarget) { - this._pingPongRenderTarget = pingPongRenderTarget; - } - - this._setSize(256); - -======= _oldTarget = this._renderer.getRenderTarget(); this._setSize( 256 ); const cubeUVRenderTarget = this._allocateTargets(); ->>>>>>> mrdoob-dev cubeUVRenderTarget.depthBuffer = true; this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); @@ -15407,50 +16116,6 @@ class PMREMGenerator { } -<<<<<<< HEAD - prepareForRenderTarget(cubeUVRenderTarget, pingPongRenderTarget = null, cubeSize = 256) { - this._setSize(cubeSize); - - const { - _lodMax - } = this; - ({ - sizeLods: this._sizeLods, - lodPlanes: this._lodPlanes, - sigmas: this._sigmas - } = _createPlanes(_lodMax)); - const width = 3 * Math.max(this._cubeSize, 16 * 7); - const height = 4 * this._cubeSize; - this._blurMaterial = _getBlurShader(_lodMax, width, height); - cubeUVRenderTarget.setSize(width, height); - - if (pingPongRenderTarget) { - pingPongRenderTarget.setSize(width, height); - } - } - - fromSceneToRenderTarget(scene, cubeUVRenderTarget, pingPongRenderTarget, sigma = 0, near = 0.1, far = 100) { - _oldTarget = this._renderer.getRenderTarget(); - this._pingPongRenderTarget = pingPongRenderTarget; - - this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget); - - if (sigma > 0) { - this._blur(cubeUVRenderTarget, 0, 0, sigma); - } - - this._applyPMREM(cubeUVRenderTarget); - - this._renderer.setRenderTarget(_oldTarget); - - cubeUVRenderTarget.scissorTest = false; - - _setViewport(cubeUVRenderTarget, 0, 0, cubeUVRenderTarget.width, cubeUVRenderTarget.height); - - return cubeUVRenderTarget; - } -======= ->>>>>>> mrdoob-dev /** * Generates a PMREM from an equirectangular texture, which can be either LDR * or HDR. The ideal input image size is 1k (1024 x 512), @@ -15582,7 +16247,7 @@ class PMREMGenerator { generateMipmaps: false, type: HalfFloatType, format: RGBAFormat, - encoding: LinearEncoding, + colorSpace: LinearSRGBColorSpace, depthBuffer: false }; @@ -16174,16 +16839,6 @@ function _getCommonVertexShader() { varying vec3 vOutputDirection; - mat3 getRotationMatrix(vec3 axis, float angle) { - axis = normalize(axis); - float s = sin(angle); - float c = cos(angle); - float oc = 1.0 - c; - - return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, - oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); - } // RH coordinate system; PMREM face-indexing convention vec3 getDirection( vec2 uv, float face ) { @@ -16219,8 +16874,7 @@ function _getCommonVertexShader() { direction.z *= -1.0; // ( u, v, -1 ) neg z } - mat3 rotationMatrix = getRotationMatrix(vec3(1.0, 0.0, 0.0), 1.57); - direction = rotationMatrix * direction; + return direction; } @@ -16476,6 +17130,18 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { } + for ( const name in geometry.morphAttributes ) { + + const array = geometry.morphAttributes[ name ]; + + for ( let i = 0, l = array.length; i < l; i ++ ) { + + attributes.remove( array[ i ] ); + + } + + } + geometry.removeEventListener( 'dispose', onGeometryDispose ); delete geometries[ geometry.id ]; @@ -16765,7 +17431,6 @@ function WebGLInfo( gl ) { function reset() { - render.frame ++; render.calls = 0; render.triangles = 0; render.points = 0; @@ -16811,7 +17476,7 @@ function WebGLMorphtargets( gl, capabilities, textures ) { } - function update( object, geometry, material, program ) { + function update( object, geometry, program ) { const objectInfluences = object.morphTargetInfluences; @@ -17190,6 +17855,7 @@ function WebGLObjects( gl, geometries, attributes, info ) { * */ + const emptyTexture = /*@__PURE__*/ new Texture(); const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); @@ -17721,12 +18387,6 @@ function setValueT3D1( gl, v, textures ) { gl.uniform1i( this.addr, unit ); cache[ 0 ] = unit; -<<<<<<< HEAD - for (let i = from; i < to; i++) { - const line = i + 1; - lines2.push(`${line === errorLine ? '>' : ' '} ${line}: ${lines[i]}`); -======= ->>>>>>> mrdoob-dev } textures.setTexture3D( v || empty3dTexture, unit ); @@ -17759,16 +18419,6 @@ function setValueT2DArray1( gl, v, textures ) { gl.uniform1i( this.addr, unit ); cache[ 0 ] = unit; -<<<<<<< HEAD - if (errorMatches) { - // --enable-privileged-webgl-extension - // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - const errorLine = parseInt(errorMatches[1]); - return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource(gl.getShaderSource(shader), errorLine); - } else { - return errors; -======= ->>>>>>> mrdoob-dev } textures.setTexture2DArray( v || emptyArrayTexture, unit ); @@ -17925,61 +18575,11 @@ function setValueV1uiArray( gl, v ) { } -<<<<<<< HEAD - if (prefixFragment.length > 0) { - prefixFragment += '\n'; - } - } else { - prefixVertex = [generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.skinning ? '#define USE_SKINNING' : '', parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', parameters.morphColors && parameters.isWebGL2 ? '#define USE_MORPHCOLORS' : '', parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE' : '', parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', '#ifdef USE_INSTANCING', ' attribute mat4 instanceMatrix;', '#endif', '#ifdef USE_INSTANCING_COLOR', ' attribute vec3 instanceColor;', '#endif', 'attribute vec3 position;', 'attribute vec3 normal;', 'attribute vec2 uv;', '#ifdef USE_TANGENT', ' attribute vec4 tangent;', '#endif', '#if defined( USE_COLOR_ALPHA )', ' attribute vec4 color;', '#elif defined( USE_COLOR )', ' attribute vec3 color;', '#endif', '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )', ' attribute vec3 morphTarget0;', ' attribute vec3 morphTarget1;', ' attribute vec3 morphTarget2;', ' attribute vec3 morphTarget3;', ' #ifdef USE_MORPHNORMALS', ' attribute vec3 morphNormal0;', ' attribute vec3 morphNormal1;', ' attribute vec3 morphNormal2;', ' attribute vec3 morphNormal3;', ' #else', ' attribute vec3 morphTarget4;', ' attribute vec3 morphTarget5;', ' attribute vec3 morphTarget6;', ' attribute vec3 morphTarget7;', ' #endif', '#endif', '#ifdef USE_SKINNING', ' attribute vec4 skinIndex;', ' attribute vec4 skinWeight;', '#endif', '\n'].filter(filterEmptyLine).join('\n'); - prefixFragment = [customExtensions, generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapTypeDefine : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.envMap ? '#define ' + envMapBlendingDefine : '', envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '', envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '', envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.iridescence ? '#define USE_IRIDESCENCE' : '', parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', parameters.toneMapping !== NoToneMapping ? '#define TONE_MAPPING' : '', parameters.toneMapping !== NoToneMapping ? ShaderChunk['tonemapping_pars_fragment'] : '', // this code is required here because it is used by the toneMapping() function defined below - parameters.toneMapping !== NoToneMapping ? getToneMappingFunction('toneMapping', parameters.toneMapping) : '', parameters.dithering ? '#define DITHERING' : '', parameters.opaque ? '#define OPAQUE' : '', ShaderChunk['encodings_pars_fragment'], // this code is required here because it is used by the various encoding/decoding function defined below - getTexelEncodingFunction('linearToOutputTexel', parameters.outputEncoding), parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', '\n'].filter(filterEmptyLine).join('\n'); - } - - if (renderer.onShaderBeforeResolve) { - const ret = renderer.onShaderBeforeResolve(vertexShader, fragmentShader, parameters); - vertexShader = ret.vertexShader; - fragmentShader = ret.fragmentShader; - } - - vertexShader = resolveIncludes(vertexShader); - vertexShader = replaceLightNums(vertexShader, parameters); - vertexShader = replaceClippingPlaneNums(vertexShader, parameters); - fragmentShader = resolveIncludes(fragmentShader); - fragmentShader = replaceLightNums(fragmentShader, parameters); - fragmentShader = replaceClippingPlaneNums(fragmentShader, parameters); - vertexShader = unrollLoops(vertexShader); - fragmentShader = unrollLoops(fragmentShader); - - if (parameters.isWebGL2 && parameters.isRawShaderMaterial !== true) { - // GLSL 3.0 conversion for built-in materials and ShaderMaterial - versionString = '#version 300 es\n'; - prefixVertex = ['precision mediump sampler2DArray;', '#define attribute in', '#define varying out', '#define texture2D texture'].join('\n') + '\n' + prefixVertex; - prefixFragment = ['#define varying in', parameters.glslVersion === GLSL3 ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', parameters.glslVersion === GLSL3 ? '' : '#define gl_FragColor pc_fragColor', '#define gl_FragDepthEXT gl_FragDepth', '#define texture2D texture', '#define textureCube texture', '#define texture2DProj textureProj', '#define texture2DLodEXT textureLod', '#define texture2DProjLodEXT textureProjLod', '#define textureCubeLodEXT textureLod', '#define texture2DGradEXT textureGrad', '#define texture2DProjGradEXT textureProjGrad', '#define textureCubeGradEXT textureGrad'].join('\n') + '\n' + prefixFragment; - } - - let vertexGlsl = versionString + prefixVertex + vertexShader; - let fragmentGlsl = versionString + prefixFragment + fragmentShader; - - if (renderer.onShaderBeforeCompile) { - const ret = renderer.onShaderBeforeCompile(vertexGlsl, fragmentGlsl, parameters); - vertexGlsl = ret.vertexShader; - fragmentGlsl = ret.fragmentShader; - } // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); - - - const glVertexShader = WebGLShader(gl, gl.VERTEX_SHADER, vertexGlsl); - const glFragmentShader = WebGLShader(gl, gl.FRAGMENT_SHADER, fragmentGlsl); - gl.attachShader(program, glVertexShader); - gl.attachShader(program, glFragmentShader); // Force a particular attribute to index 0. -======= // Array of unsigned integer vectors (from flat array) function setValueV2uiArray( gl, v ) { gl.uniform2uiv( this.addr, v ); ->>>>>>> mrdoob-dev } @@ -18090,115 +18690,6 @@ function setValueT2DArrayArray( gl, v, textures ) { textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); -<<<<<<< HEAD - const currentRenderTarget = renderer.getRenderTarget(); - const useAlphaTest = material.alphaTest > 0; - const useClearcoat = material.clearcoat > 0; - const useIridescence = material.iridescence > 0; - const parameters = { - isWebGL2: isWebGL2, - shaderID: shaderID, - shaderName: material.type, - vertexShader: vertexShader, - fragmentShader: fragmentShader, - defines: material.defines, - customVertexShaderID: customVertexShaderID, - customFragmentShaderID: customFragmentShaderID, - isRawShaderMaterial: material.isRawShaderMaterial === true, - glslVersion: material.glslVersion, - precision: precision, - instancing: object.isInstancedMesh === true, - instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, - supportsVertexTextures: vertexTextures, - outputEncoding: currentRenderTarget === null ? renderer.outputEncoding : currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding, - map: !!material.map, - matcap: !!material.matcap, - envMap: !!envMap, - envMapMode: envMap && envMap.mapping, - envMapCubeUVHeight: envMapCubeUVHeight, - lightMap: !!material.lightMap, - aoMap: !!material.aoMap, - emissiveMap: !!material.emissiveMap, - bumpMap: !!material.bumpMap, - normalMap: !!material.normalMap, - objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, - tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, - decodeVideoTexture: !!material.map && material.map.isVideoTexture === true && material.map.encoding === sRGBEncoding, - clearcoat: useClearcoat, - clearcoatMap: useClearcoat && !!material.clearcoatMap, - clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap, - clearcoatNormalMap: useClearcoat && !!material.clearcoatNormalMap, - iridescence: useIridescence, - iridescenceMap: useIridescence && !!material.iridescenceMap, - iridescenceThicknessMap: useIridescence && !!material.iridescenceThicknessMap, - displacementMap: !!material.displacementMap, - roughnessMap: !!material.roughnessMap, - metalnessMap: !!material.metalnessMap, - specularMap: !!material.specularMap, - specularIntensityMap: !!material.specularIntensityMap, - specularColorMap: !!material.specularColorMap, - opaque: material.transparent === false && material.blending === NormalBlending, - alphaMap: !!material.alphaMap, - alphaTest: useAlphaTest, - gradientMap: !!material.gradientMap, - sheen: material.sheen > 0, - sheenColorMap: !!material.sheenColorMap, - sheenRoughnessMap: !!material.sheenRoughnessMap, - transmission: material.transmission > 0, - transmissionMap: !!material.transmissionMap, - thicknessMap: !!material.thicknessMap, - combine: material.combine, - vertexTangents: !!material.normalMap && !!geometry.attributes.tangent, - vertexColors: material.vertexColors, - vertexAlphas: material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4, - vertexUvs: !!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatMap || !!material.clearcoatRoughnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || !!material.displacementMap || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || !!material.sheenColorMap || !!material.sheenRoughnessMap, - uvsVertexOnly: !(!!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || material.transmission > 0 || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || material.sheen > 0 || !!material.sheenColorMap || !!material.sheenRoughnessMap) && !!material.displacementMap, - fog: !!fog, - useFog: material.fog === true, - fogExp2: fog && fog.isFogExp2, - flatShading: !!material.flatShading, - sizeAttenuation: material.sizeAttenuation, - logarithmicDepthBuffer: logarithmicDepthBuffer, - skinning: object.isSkinnedMesh === true, - morphTargets: geometry.morphAttributes.position !== undefined, - morphNormals: geometry.morphAttributes.normal !== undefined, - morphColors: geometry.morphAttributes.color !== undefined, - morphTargetsCount: morphTargetsCount, - morphTextureStride: morphTextureStride, - numDirLights: lights.directional.length, - numPointLights: lights.point.length, - numSpotLights: lights.spot.length, - numRectAreaLights: lights.rectArea.length, - numHemiLights: lights.hemi.length, - numDirLightShadows: lights.directionalShadowMap.length, - numPointLightShadows: lights.pointShadowMap.length, - numSpotLightShadows: lights.spotShadowMap.length, - numClippingPlanes: clipping.numPlanes, - numClipIntersection: clipping.numIntersection, - dithering: material.dithering, - shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, - shadowMapType: renderer.shadowMap.type, - toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, - premultipliedAlpha: material.premultipliedAlpha, - doubleSided: material.side === DoubleSide, - flipSided: material.side === BackSide, - useDepthPacking: !!material.depthPacking, - depthPacking: material.depthPacking || 0, - index0AttributeName: material.index0AttributeName, - extensionDerivatives: material.extensions && material.extensions.derivatives, - extensionFragDepth: material.extensions && material.extensions.fragDepth, - extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, - extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, - rendererExtensionFragDepth: isWebGL2 || extensions.has('EXT_frag_depth'), - rendererExtensionDrawBuffers: isWebGL2 || extensions.has('WEBGL_draw_buffers'), - rendererExtensionShaderTextureLod: isWebGL2 || extensions.has('EXT_shader_texture_lod'), - customProgramCacheKey: material.customProgramCacheKey(), - extraProgramCacheKey: renderer.extraProgramCacheKey - }; - return parameters; -======= ->>>>>>> mrdoob-dev } } @@ -18208,18 +18699,7 @@ function setValueT2DArrayArray( gl, v, textures ) { function getPureArraySetter( type ) { -<<<<<<< HEAD - array.push(parameters.customProgramCacheKey); - - if (renderer.extraProgramCacheKey) { - array.push(renderer.extraProgramCacheKey); - } - - return array.join(); - } -======= switch ( type ) { ->>>>>>> mrdoob-dev case 0x1406: return setValueV1fArray; // FLOAT case 0x8b50: return setValueV2fArray; // _VEC2 @@ -18505,16 +18985,16 @@ function handleSource( string, errorLine ) { } -function getEncodingComponents( encoding ) { +function getEncodingComponents( colorSpace ) { - switch ( encoding ) { + switch ( colorSpace ) { - case LinearEncoding: + case LinearSRGBColorSpace: return [ 'Linear', '( value )' ]; - case sRGBEncoding: + case SRGBColorSpace: return [ 'sRGB', '( value )' ]; default: - console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding ); + console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); return [ 'Linear', '( value )' ]; } @@ -18545,9 +19025,9 @@ function getShaderErrors( gl, shader, type ) { } -function getTexelEncodingFunction( functionName, encoding ) { +function getTexelEncodingFunction( functionName, colorSpace ) { - const components = getEncodingComponents( encoding ); + const components = getEncodingComponents( colorSpace ); return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; } @@ -18591,7 +19071,7 @@ function getToneMappingFunction( functionName, toneMapping ) { function generateExtensions( parameters ) { const chunks = [ - ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', + ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.normalMapTangentSpace || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '', ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '', ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : '' @@ -18899,6 +19379,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { prefixVertex = [ + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -18912,6 +19395,10 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { prefixFragment = [ customExtensions, + + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -18928,6 +19415,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, @@ -18935,21 +19423,22 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', - - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', @@ -18958,11 +19447,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -18972,14 +19459,52 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', + + // + + parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', + parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', + parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', + parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', + parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', + parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', + parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', + parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', + + parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', + parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', + + parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', + + parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', + parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', + parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', + + parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', + parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', + + parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', + parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', + + parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', + parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', + parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', + + parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', + parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', + + // parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', @@ -18999,6 +19524,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -19026,6 +19553,24 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { 'attribute vec3 normal;', 'attribute vec2 uv;', + '#ifdef USE_UV1', + + ' attribute vec2 uv1;', + + '#endif', + + '#ifdef USE_UV2', + + ' attribute vec2 uv2;', + + '#endif', + + '#ifdef USE_UV3', + + ' attribute vec2 uv3;', + + '#endif', + '#ifdef USE_TANGENT', ' attribute vec4 tangent;', @@ -19084,12 +19629,13 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', @@ -19102,11 +19648,14 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', @@ -19118,8 +19667,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -19127,20 +19677,21 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', - parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', @@ -19154,7 +19705,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', - parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -19171,7 +19722,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.opaque ? '#define OPAQUE' : '', ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below - getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ), + getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', @@ -19264,16 +19815,26 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { runnable = false; - const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); - const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + if ( typeof renderer.debug.onShaderError === 'function' ) { - console.error( - 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + - 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + - 'Program Info Log: ' + programLog + '\n' + - vertexErrors + '\n' + - fragmentErrors - ); + renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); + + } else { + + // default error reporting + + const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); + + } } else if ( programLog !== '' ) { @@ -19367,6 +19928,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { // + this.type = parameters.shaderType; this.name = parameters.shaderName; this.id = programIdCount ++; this.cacheKey = cacheKey; @@ -19508,9 +20070,10 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const _customShaders = new WebGLShaderCache(); const programs = []; - const isWebGL2 = capabilities.isWebGL2; + const IS_WEBGL2 = capabilities.isWebGL2; const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; - const vertexTextures = capabilities.vertexTextures; + const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; + let precision = capabilities.precision; const shaderIDs = { @@ -19531,6 +20094,14 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities SpriteMaterial: 'sprite' }; + function getChannel( value ) { + + if ( value === 0 ) return 'uv'; + + return `uv${ value }`; + + } + function getParameters( material, lights, shadows, scene, object ) { const fog = scene.fog; @@ -19594,16 +20165,65 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const currentRenderTarget = renderer.getRenderTarget(); - const useAlphaTest = material.alphaTest > 0; - const useClearcoat = material.clearcoat > 0; - const useIridescence = material.iridescence > 0; + const IS_INSTANCEDMESH = object.isInstancedMesh === true; + + const HAS_MAP = !! material.map; + const HAS_MATCAP = !! material.matcap; + const HAS_ENVMAP = !! envMap; + const HAS_AOMAP = !! material.aoMap; + const HAS_LIGHTMAP = !! material.lightMap; + const HAS_BUMPMAP = !! material.bumpMap; + const HAS_NORMALMAP = !! material.normalMap; + const HAS_DISPLACEMENTMAP = !! material.displacementMap; + const HAS_EMISSIVEMAP = !! material.emissiveMap; + + const HAS_METALNESSMAP = !! material.metalnessMap; + const HAS_ROUGHNESSMAP = !! material.roughnessMap; + + const HAS_ANISOTROPY = material.anisotropy > 0; + const HAS_CLEARCOAT = material.clearcoat > 0; + const HAS_IRIDESCENCE = material.iridescence > 0; + const HAS_SHEEN = material.sheen > 0; + const HAS_TRANSMISSION = material.transmission > 0; + + const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; + + const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; + const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; + const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; + + const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; + const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; + + const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; + const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; + + const HAS_SPECULARMAP = !! material.specularMap; + const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; + const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; + + const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; + const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; + + const HAS_GRADIENTMAP = !! material.gradientMap; + + const HAS_ALPHAMAP = !! material.alphaMap; + + const HAS_ALPHATEST = material.alphaTest > 0; + + const HAS_EXTENSIONS = !! material.extensions; + + const HAS_ATTRIBUTE_UV1 = !! geometry.attributes.uv1; + const HAS_ATTRIBUTE_UV2 = !! geometry.attributes.uv2; + const HAS_ATTRIBUTE_UV3 = !! geometry.attributes.uv3; const parameters = { - isWebGL2: isWebGL2, + isWebGL2: IS_WEBGL2, shaderID: shaderID, - shaderName: material.type, + shaderType: material.type, + shaderName: material.name, vertexShader: vertexShader, fragmentShader: fragmentShader, @@ -19617,72 +20237,115 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities precision: precision, - instancing: object.isInstancedMesh === true, - instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + instancing: IS_INSTANCEDMESH, + instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, + + supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, + outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), - supportsVertexTextures: vertexTextures, - outputEncoding: ( currentRenderTarget === null ) ? renderer.outputEncoding : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding ), - map: !! material.map, - matcap: !! material.matcap, - envMap: !! envMap, - envMapMode: envMap && envMap.mapping, + map: HAS_MAP, + matcap: HAS_MATCAP, + envMap: HAS_ENVMAP, + envMapMode: HAS_ENVMAP && envMap.mapping, envMapCubeUVHeight: envMapCubeUVHeight, - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, - tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, - - decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ), - - clearcoat: useClearcoat, - clearcoatMap: useClearcoat && !! material.clearcoatMap, - clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap, - clearcoatNormalMap: useClearcoat && !! material.clearcoatNormalMap, - - iridescence: useIridescence, - iridescenceMap: useIridescence && !! material.iridescenceMap, - iridescenceThicknessMap: useIridescence && !! material.iridescenceThicknessMap, - - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - specularIntensityMap: !! material.specularIntensityMap, - specularColorMap: !! material.specularColorMap, + aoMap: HAS_AOMAP, + lightMap: HAS_LIGHTMAP, + bumpMap: HAS_BUMPMAP, + normalMap: HAS_NORMALMAP, + displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + emissiveMap: HAS_EMISSIVEMAP, - opaque: material.transparent === false && material.blending === NormalBlending, + normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, + normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, + + metalnessMap: HAS_METALNESSMAP, + roughnessMap: HAS_ROUGHNESSMAP, - alphaMap: !! material.alphaMap, - alphaTest: useAlphaTest, + anisotropy: HAS_ANISOTROPY, + anisotropyMap: HAS_ANISOTROPYMAP, - gradientMap: !! material.gradientMap, + clearcoat: HAS_CLEARCOAT, + clearcoatMap: HAS_CLEARCOATMAP, + clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, + clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, - sheen: material.sheen > 0, - sheenColorMap: !! material.sheenColorMap, - sheenRoughnessMap: !! material.sheenRoughnessMap, + iridescence: HAS_IRIDESCENCE, + iridescenceMap: HAS_IRIDESCENCEMAP, + iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, - transmission: material.transmission > 0, - transmissionMap: !! material.transmissionMap, - thicknessMap: !! material.thicknessMap, + sheen: HAS_SHEEN, + sheenColorMap: HAS_SHEEN_COLORMAP, + sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, + + specularMap: HAS_SPECULARMAP, + specularColorMap: HAS_SPECULAR_COLORMAP, + specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, + + transmission: HAS_TRANSMISSION, + transmissionMap: HAS_TRANSMISSIONMAP, + thicknessMap: HAS_THICKNESSMAP, + + gradientMap: HAS_GRADIENTMAP, + + opaque: material.transparent === false && material.blending === NormalBlending, + + alphaMap: HAS_ALPHAMAP, + alphaTest: HAS_ALPHATEST, combine: material.combine, - vertexTangents: ( !! material.normalMap && !! geometry.attributes.tangent ), + // + + mapUv: HAS_MAP && getChannel( material.map.channel ), + aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), + lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), + bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), + normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), + displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), + emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), + + metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), + roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), + + anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), + + clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), + clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), + clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), + + iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), + iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), + + sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), + sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), + + specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), + specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), + specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), + + transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), + thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), + + alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), + + // + + vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), vertexColors: material.vertexColors, vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, - vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || !! material.displacementMap || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheenColorMap || !! material.sheenRoughnessMap, - uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || material.transmission > 0 || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || material.sheen > 0 || !! material.sheenColorMap || !! material.sheenRoughnessMap ) && !! material.displacementMap, + vertexUv1s: HAS_ATTRIBUTE_UV1, + vertexUv2s: HAS_ATTRIBUTE_UV2, + vertexUv3s: HAS_ATTRIBUTE_UV3, + + pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), fog: !! fog, useFog: material.fog === true, fogExp2: ( fog && fog.isFogExp2 ), - flatShading: !! material.flatShading, + flatShading: material.flatShading === true, - sizeAttenuation: material.sizeAttenuation, + sizeAttenuation: material.sizeAttenuation === true, logarithmicDepthBuffer: logarithmicDepthBuffer, skinning: object.isSkinnedMesh === true, @@ -19714,26 +20377,26 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities shadowMapType: renderer.shadowMap.type, toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, + useLegacyLights: renderer.useLegacyLights, premultipliedAlpha: material.premultipliedAlpha, doubleSided: material.side === DoubleSide, flipSided: material.side === BackSide, - useDepthPacking: !! material.depthPacking, + useDepthPacking: material.depthPacking >= 0, depthPacking: material.depthPacking || 0, index0AttributeName: material.index0AttributeName, - extensionDerivatives: material.extensions && material.extensions.derivatives, - extensionFragDepth: material.extensions && material.extensions.fragDepth, - extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, - extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, + extensionDerivatives: HAS_EXTENSIONS && material.extensions.derivatives === true, + extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true, + extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true, + extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true, - rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ), - rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ), - rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ), + rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ), + rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ), + rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ), customProgramCacheKey: material.customProgramCacheKey() @@ -19773,7 +20436,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities getProgramCacheKeyParameters( array, parameters ); getProgramCacheKeyBooleans( array, parameters ); - array.push( renderer.outputEncoding ); + array.push( renderer.outputColorSpace ); } @@ -19786,11 +20449,33 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities function getProgramCacheKeyParameters( array, parameters ) { array.push( parameters.precision ); - array.push( parameters.outputEncoding ); + array.push( parameters.outputColorSpace ); array.push( parameters.envMapMode ); array.push( parameters.envMapCubeUVHeight ); + array.push( parameters.mapUv ); + array.push( parameters.alphaMapUv ); + array.push( parameters.lightMapUv ); + array.push( parameters.aoMapUv ); + array.push( parameters.bumpMapUv ); + array.push( parameters.normalMapUv ); + array.push( parameters.displacementMapUv ); + array.push( parameters.emissiveMapUv ); + array.push( parameters.metalnessMapUv ); + array.push( parameters.roughnessMapUv ); + array.push( parameters.anisotropyMapUv ); + array.push( parameters.clearcoatMapUv ); + array.push( parameters.clearcoatNormalMapUv ); + array.push( parameters.clearcoatRoughnessMapUv ); + array.push( parameters.iridescenceMapUv ); + array.push( parameters.iridescenceThicknessMapUv ); + array.push( parameters.sheenColorMapUv ); + array.push( parameters.sheenRoughnessMapUv ); + array.push( parameters.specularMapUv ); + array.push( parameters.specularColorMapUv ); + array.push( parameters.specularIntensityMapUv ); + array.push( parameters.transmissionMapUv ); + array.push( parameters.thicknessMapUv ); array.push( parameters.combine ); - array.push( parameters.vertexUvs ); array.push( parameters.fogExp2 ); array.push( parameters.sizeAttenuation ); array.push( parameters.morphTargetsCount ); @@ -19825,64 +20510,34 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 2 ); if ( parameters.instancingColor ) _programLayers.enable( 3 ); - if ( parameters.map ) - _programLayers.enable( 4 ); if ( parameters.matcap ) - _programLayers.enable( 5 ); + _programLayers.enable( 4 ); if ( parameters.envMap ) + _programLayers.enable( 5 ); + if ( parameters.normalMapObjectSpace ) _programLayers.enable( 6 ); - if ( parameters.lightMap ) + if ( parameters.normalMapTangentSpace ) _programLayers.enable( 7 ); - if ( parameters.aoMap ) + if ( parameters.clearcoat ) _programLayers.enable( 8 ); - if ( parameters.emissiveMap ) + if ( parameters.iridescence ) _programLayers.enable( 9 ); - if ( parameters.bumpMap ) + if ( parameters.alphaTest ) _programLayers.enable( 10 ); - if ( parameters.normalMap ) + if ( parameters.vertexColors ) _programLayers.enable( 11 ); - if ( parameters.objectSpaceNormalMap ) + if ( parameters.vertexAlphas ) _programLayers.enable( 12 ); - if ( parameters.tangentSpaceNormalMap ) + if ( parameters.vertexUv1s ) _programLayers.enable( 13 ); - if ( parameters.clearcoat ) + if ( parameters.vertexUv2s ) _programLayers.enable( 14 ); - if ( parameters.clearcoatMap ) + if ( parameters.vertexUv3s ) _programLayers.enable( 15 ); - if ( parameters.clearcoatRoughnessMap ) + if ( parameters.vertexTangents ) _programLayers.enable( 16 ); - if ( parameters.clearcoatNormalMap ) + if ( parameters.anisotropy ) _programLayers.enable( 17 ); - if ( parameters.iridescence ) - _programLayers.enable( 18 ); - if ( parameters.iridescenceMap ) - _programLayers.enable( 19 ); - if ( parameters.iridescenceThicknessMap ) - _programLayers.enable( 20 ); - if ( parameters.displacementMap ) - _programLayers.enable( 21 ); - if ( parameters.specularMap ) - _programLayers.enable( 22 ); - if ( parameters.roughnessMap ) - _programLayers.enable( 23 ); - if ( parameters.metalnessMap ) - _programLayers.enable( 24 ); - if ( parameters.gradientMap ) - _programLayers.enable( 25 ); - if ( parameters.alphaMap ) - _programLayers.enable( 26 ); - if ( parameters.alphaTest ) - _programLayers.enable( 27 ); - if ( parameters.vertexColors ) - _programLayers.enable( 28 ); - if ( parameters.vertexAlphas ) - _programLayers.enable( 29 ); - if ( parameters.vertexUvs ) - _programLayers.enable( 30 ); - if ( parameters.vertexTangents ) - _programLayers.enable( 31 ); - if ( parameters.uvsVertexOnly ) - _programLayers.enable( 32 ); array.push( _programLayers.mask ); _programLayers.disableAll(); @@ -19907,7 +20562,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 8 ); if ( parameters.shadowMapEnabled ) _programLayers.enable( 9 ); - if ( parameters.physicallyCorrectLights ) + if ( parameters.useLegacyLights ) _programLayers.enable( 10 ); if ( parameters.doubleSided ) _programLayers.enable( 11 ); @@ -19917,26 +20572,14 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 13 ); if ( parameters.dithering ) _programLayers.enable( 14 ); - if ( parameters.specularIntensityMap ) + if ( parameters.transmission ) _programLayers.enable( 15 ); - if ( parameters.specularColorMap ) + if ( parameters.sheen ) _programLayers.enable( 16 ); - if ( parameters.transmission ) + if ( parameters.opaque ) _programLayers.enable( 17 ); - if ( parameters.transmissionMap ) + if ( parameters.pointsUvs ) _programLayers.enable( 18 ); - if ( parameters.thicknessMap ) - _programLayers.enable( 19 ); - if ( parameters.sheen ) - _programLayers.enable( 20 ); - if ( parameters.sheenColorMap ) - _programLayers.enable( 21 ); - if ( parameters.sheenRoughnessMap ) - _programLayers.enable( 22 ); - if ( parameters.decodeVideoTexture ) - _programLayers.enable( 23 ); - if ( parameters.opaque ) - _programLayers.enable( 24 ); array.push( _programLayers.mask ); @@ -20392,22 +21035,7 @@ function UniformsCache() { } -<<<<<<< HEAD - let camera = cameras[i]; - - if (camera === undefined) { - camera = new PerspectiveCamera(); - camera.layers.enable(i); - camera.viewport = new Vector4(); - cameras[i] = camera; - } - - camera.matrix.fromArray(view.transform.matrix); - camera.projectionMatrix.fromArray(view.projectionMatrix); - camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height); -======= function ShadowUniformsCache() { ->>>>>>> mrdoob-dev const lights = {}; @@ -20530,7 +21158,7 @@ function WebGLLights( extensions, capabilities ) { const matrix4 = new Matrix4(); const matrix42 = new Matrix4(); - function setup( lights, physicallyCorrectLights ) { + function setup( lights, useLegacyLights ) { let r = 0, g = 0, b = 0; @@ -20552,7 +21180,7 @@ function WebGLLights( extensions, capabilities ) { lights.sort( shadowCastingAndTexturingLightsFirst ); // artist-friendly light intensity scaling factor - const scaleFactor = ( physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1; for ( let i = 0, l = lights.length; i < l; i ++ ) { @@ -20920,9 +21548,9 @@ function WebGLRenderState( extensions, capabilities ) { } - function setupLights( physicallyCorrectLights ) { + function setupLights( useLegacyLights ) { - lights.setup( lightsArray, physicallyCorrectLights ); + lights.setup( lightsArray, useLegacyLights ); } @@ -21057,10 +21685,6 @@ class MeshDistanceMaterial extends Material { this.type = 'MeshDistanceMaterial'; - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; - this.map = null; this.alphaMap = null; @@ -21077,10 +21701,6 @@ class MeshDistanceMaterial extends Material { super.copy( source ); - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; - this.map = source.map; this.alphaMap = source.alphaMap; @@ -21154,6 +21774,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { this.needsUpdate = false; this.type = PCFShadowMap; + let _previousType = this.type; this.render = function ( lights, scene, camera ) { @@ -21174,6 +21795,11 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { _state.buffers.depth.setTest( true ); _state.setScissorTest( false ); + // check for shadow map type changes + + const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); + const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); + // render depth map for ( let i = 0, il = lights.length; i < il; i ++ ) { @@ -21218,10 +21844,16 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } - if ( shadow.map === null ) { + if ( shadow.map === null || toVSM === true || fromVSM === true ) { const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; + if ( shadow.map !== null ) { + + shadow.map.dispose(); + + } + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); shadow.map.texture.name = light.name + '.shadowMap'; @@ -21232,49 +21864,11 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { _renderer.setRenderTarget( shadow.map ); _renderer.clear(); -<<<<<<< HEAD - function updateCommonMaterialProperties(material, parameters) { - const materialProperties = properties.get(material); - materialProperties.outputEncoding = parameters.outputEncoding; - materialProperties.instancing = parameters.instancing; - materialProperties.skinning = parameters.skinning; - materialProperties.morphTargets = parameters.morphTargets; - materialProperties.morphNormals = parameters.morphNormals; - materialProperties.morphColors = parameters.morphColors; - materialProperties.morphTargetsCount = parameters.morphTargetsCount; - materialProperties.numClippingPlanes = parameters.numClippingPlanes; - materialProperties.numIntersection = parameters.numClipIntersection; - materialProperties.vertexAlphas = parameters.vertexAlphas; - materialProperties.vertexTangents = parameters.vertexTangents; - materialProperties.toneMapping = parameters.toneMapping; - materialProperties.extraProgramCacheKey = parameters.extraProgramCacheKey; - } -======= const viewportCount = shadow.getViewportCount(); ->>>>>>> mrdoob-dev for ( let vp = 0; vp < viewportCount; vp ++ ) { -<<<<<<< HEAD - textures.resetTextureUnits(); - const fog = scene.fog; - const environment = material.isMeshStandardMaterial ? scene.environment : null; - const encoding = _currentRenderTarget === null ? _this.outputEncoding : _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding; - const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment); - const vertexAlphas = material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4; - const vertexTangents = !!material.normalMap && !!geometry.attributes.tangent; - const morphTargets = !!geometry.morphAttributes.position; - const morphNormals = !!geometry.morphAttributes.normal; - const morphColors = !!geometry.morphAttributes.color; - const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = morphAttribute !== undefined ? morphAttribute.length : 0; - const materialProperties = properties.get(material); - const lights = currentRenderState.state.lights; - const extraProgramCacheKey = _this.extraProgramCacheKey; -======= const viewport = shadow.getViewport( vp ); ->>>>>>> mrdoob-dev _viewport.set( _viewportSize.x * viewport.x, @@ -21297,50 +21891,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { -<<<<<<< HEAD - if (material.version === materialProperties.__version) { - if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) { - needsProgramChange = true; - } else if (materialProperties.outputEncoding !== encoding) { - needsProgramChange = true; - } else if (object.isInstancedMesh && materialProperties.instancing === false) { - needsProgramChange = true; - } else if (!object.isInstancedMesh && materialProperties.instancing === true) { - needsProgramChange = true; - } else if (object.isSkinnedMesh && materialProperties.skinning === false) { - needsProgramChange = true; - } else if (!object.isSkinnedMesh && materialProperties.skinning === true) { - needsProgramChange = true; - } else if (materialProperties.envMap !== envMap) { - needsProgramChange = true; - } else if (material.fog === true && materialProperties.fog !== fog) { - needsProgramChange = true; - } else if (materialProperties.numClippingPlanes !== undefined && (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)) { - needsProgramChange = true; - } else if (materialProperties.vertexAlphas !== vertexAlphas) { - needsProgramChange = true; - } else if (materialProperties.vertexTangents !== vertexTangents) { - needsProgramChange = true; - } else if (materialProperties.morphTargets !== morphTargets) { - needsProgramChange = true; - } else if (materialProperties.morphNormals !== morphNormals) { - needsProgramChange = true; - } else if (materialProperties.morphColors !== morphColors) { - needsProgramChange = true; - } else if (materialProperties.toneMapping !== toneMapping) { - needsProgramChange = true; - } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) { - needsProgramChange = true; - } else if (extraProgramCacheKey !== materialProperties.extraProgramCacheKey) { - needsProgramChange = true; - } - } else { - needsProgramChange = true; - materialProperties.__version = material.version; - } // -======= VSMPass( shadow, camera ); ->>>>>>> mrdoob-dev } @@ -21348,6 +21899,8 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } + _previousType = this.type; + scope.needsUpdate = false; _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); @@ -21394,7 +21947,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } - function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) { + function getDepthMaterial( object, material, light, type ) { let result = null; @@ -21472,9 +22025,8 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { - result.referencePosition.setFromMatrixPosition( light.matrixWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; + const materialProperties = _renderer.properties.get( result ); + materialProperties.light = light; } @@ -21508,7 +22060,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { if ( groupMaterial && groupMaterial.visible ) { - const depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); @@ -21518,7 +22070,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } else if ( material.visible ) { - const depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, material, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); @@ -21901,7 +22453,7 @@ function WebGLState( gl, extensions, capabilities ) { const currentScissor = new Vector4().fromArray( scissorParam ); const currentViewport = new Vector4().fromArray( viewportParam ); - function createTexture( type, target, count ) { + function createTexture( type, target, count, dimensions ) { const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. const texture = gl.createTexture(); @@ -21912,7 +22464,15 @@ function WebGLState( gl, extensions, capabilities ) { for ( let i = 0; i < count; i ++ ) { - gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + if ( isWebGL2 && ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) ) { + + gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } else { + + gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } } @@ -21924,6 +22484,13 @@ function WebGLState( gl, extensions, capabilities ) { emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); + if ( isWebGL2 ) { + + emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); + emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); + + } + // init colorBuffer.setClear( 0, 0, 0, 1 ); @@ -22960,7 +23527,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, encoding, forceLinearEncoding = false ) { + function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { if ( isWebGL2 === false ) return glFormat; @@ -22994,7 +23561,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; - if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( encoding === sRGBEncoding && forceLinearEncoding === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( colorSpace === SRGBColorSpace && forceLinearTransfer === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; @@ -23251,7 +23818,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, array.push( texture.premultiplyAlpha ); array.push( texture.flipY ); array.push( texture.unpackAlignment ); - array.push( texture.encoding ); + array.push( texture.colorSpace ); return array.join(); @@ -23351,6 +23918,17 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR }; + const compareToGL = { + [ NeverCompare ]: _gl.NEVER, + [ AlwaysCompare ]: _gl.ALWAYS, + [ LessCompare ]: _gl.LESS, + [ LessEqualCompare ]: _gl.LEQUAL, + [ EqualCompare ]: _gl.EQUAL, + [ GreaterEqualCompare ]: _gl.GEQUAL, + [ GreaterCompare ]: _gl.GREATER, + [ NotEqualCompare ]: _gl.NOTEQUAL + }; + function setTextureParameters( textureType, texture, supportsMips ) { if ( supportsMips ) { @@ -23395,6 +23973,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + if ( texture.compareFunction ) { + + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); + + } + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); @@ -23523,10 +24108,10 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, image = verifyColorSpace( texture, image ); const supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ); + glFormat = utils.convert( texture.format, texture.colorSpace ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); setTextureParameters( textureType, texture, supportsMips ); @@ -23955,9 +24540,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const image = cubeImage[ 0 ], supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ), + glFormat = utils.convert( texture.format, texture.colorSpace ), glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); @@ -24124,9 +24709,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) { - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const renderTargetProperties = properties.get( renderTarget ); if ( ! renderTargetProperties.__hasExternalTextures ) { @@ -24236,9 +24821,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const texture = textures[ i ]; - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const samples = getRenderTargetSamples( renderTarget ); if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { @@ -24471,9 +25056,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, renderTarget.isXRRenderTarget === true ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); const samples = getRenderTargetSamples( renderTarget ); _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); @@ -24745,17 +25330,17 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, function verifyColorSpace( texture, image ) { - const encoding = texture.encoding; + const colorSpace = texture.colorSpace; const format = texture.format; const type = texture.type; - if ( texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat ) return image; + if ( texture.isCompressedTexture === true || texture.format === _SRGBAFormat ) return image; - if ( encoding !== LinearEncoding ) { + if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { // sRGB - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { if ( isWebGL2 === false ) { @@ -24792,7 +25377,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding ); + console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); } @@ -24825,7 +25410,7 @@ function WebGLUtils( gl, extensions, capabilities ) { const isWebGL2 = capabilities.isWebGL2; - function convert( p, encoding = null ) { + function convert( p, colorSpace = NoColorSpace ) { let extension; @@ -24895,7 +25480,7 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); @@ -24980,8 +25565,8 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; - if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + if ( p === RGB_ETC2_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; } else { @@ -25003,20 +25588,20 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; - if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; - if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; - if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; - if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; - if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; - if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; - if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; - if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; - if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; - if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; - if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; - if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; - if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; + if ( p === RGBA_ASTC_4x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; } else { @@ -25034,7 +25619,7 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + if ( p === RGBA_BPTC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; } else { @@ -25291,6 +25876,7 @@ class WebXRController { joint.matrix.fromArray( jointPose.transform.matrix ); joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); + joint.matrixWorldNeedsUpdate = true; joint.jointRadius = jointPose.radius; } @@ -25339,6 +25925,7 @@ class WebXRController { grip.matrix.fromArray( gripPose.transform.matrix ); grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + grip.matrixWorldNeedsUpdate = true; if ( gripPose.linearVelocity ) { @@ -25383,6 +25970,7 @@ class WebXRController { targetRay.matrix.fromArray( inputPose.transform.matrix ); targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + targetRay.matrixWorldNeedsUpdate = true; if ( inputPose.linearVelocity ) { @@ -25485,9 +26073,31 @@ class DepthTexture extends Texture { this.flipY = false; this.generateMipmaps = false; + this.compareFunction = null; + } + copy( source ) { + + super.copy( source ); + + this.compareFunction = source.compareFunction; + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; + + return data; + + } + } class WebXRManager extends EventDispatcher { @@ -25499,6 +26109,7 @@ class WebXRManager extends EventDispatcher { const scope = this; let session = null; + let framebufferScaleFactor = 1.0; let referenceSpace = null; @@ -25519,11 +26130,10 @@ class WebXRManager extends EventDispatcher { const controllers = []; const controllerInputSources = []; - const planes = new Set(); - const planesLastChangedTimes = new Map(); - // + let userCamera = null; + const cameraL = new PerspectiveCamera(); cameraL.layers.enable( 1 ); cameraL.viewport = new Vector4(); @@ -25534,20 +26144,28 @@ class WebXRManager extends EventDispatcher { const cameras = [ cameraL, cameraR ]; - const cameraVR = new ArrayCamera(); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + const cameraXR = new ArrayCamera(); + cameraXR.layers.enable( 1 ); + cameraXR.layers.enable( 2 ); let _currentDepthNear = null; let _currentDepthFar = null; // - this.cameraAutoUpdate = true; + this.cameraAutoUpdate = true; // @deprecated, r153 this.enabled = false; this.isPresenting = false; + this.getCamera = function () {}; // @deprecated, r153 + + this.setUserCamera = function ( value ) { + + userCamera = value; + + }; + this.getController = function ( index ) { let controller = controllers[ index ]; @@ -25609,6 +26227,7 @@ class WebXRManager extends EventDispatcher { if ( controller !== undefined ) { + controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); controller.dispatchEvent( { type: event.type, data: event.inputSource } ); } @@ -25748,7 +26367,7 @@ class WebXRManager extends EventDispatcher { const layerInit = { antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true, - alpha: attributes.alpha, + alpha: true, depth: attributes.depth, stencil: attributes.stencil, framebufferScaleFactor: framebufferScaleFactor @@ -25764,7 +26383,7 @@ class WebXRManager extends EventDispatcher { { format: RGBAFormat, type: UnsignedByteType, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, stencilBuffer: attributes.stencil } ); @@ -25803,7 +26422,7 @@ class WebXRManager extends EventDispatcher { type: UnsignedByteType, depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), stencilBuffer: attributes.stencil, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, samples: attributes.antialias ? 4 : 0 } ); @@ -25830,6 +26449,16 @@ class WebXRManager extends EventDispatcher { }; + this.getEnvironmentBlendMode = function () { + + if ( session !== null ) { + + return session.environmentBlendMode; + + } + + }; + function onInputSourcesChange( event ) { // Notify disconnected @@ -25953,6 +26582,7 @@ class WebXRManager extends EventDispatcher { const bottom2 = bottomFov * far / far2 * near2; camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); } @@ -25972,31 +26602,37 @@ class WebXRManager extends EventDispatcher { } - this.updateCamera = function ( camera ) { + this.updateCameraXR = function ( camera ) { - if ( session === null ) return; + if ( session === null ) return camera; - cameraVR.near = cameraR.near = cameraL.near = camera.near; - cameraVR.far = cameraR.far = cameraL.far = camera.far; + if ( userCamera ) { - if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { + camera = userCamera; + + } + + cameraXR.near = cameraR.near = cameraL.near = camera.near; + cameraXR.far = cameraR.far = cameraL.far = camera.far; + + if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { // Note that the new renderState won't apply until the next frame. See #18320 session.updateRenderState( { - depthNear: cameraVR.near, - depthFar: cameraVR.far + depthNear: cameraXR.near, + depthFar: cameraXR.far } ); - _currentDepthNear = cameraVR.near; - _currentDepthFar = cameraVR.far; + _currentDepthNear = cameraXR.near; + _currentDepthFar = cameraXR.far; } const parent = camera.parent; - const cameras = cameraVR.cameras; + const cameras = cameraXR.cameras; - updateCamera( cameraVR, parent ); + updateCamera( cameraXR, parent ); for ( let i = 0; i < cameras.length; i ++ ) { @@ -26004,42 +26640,70 @@ class WebXRManager extends EventDispatcher { } - cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale ); + // update projection matrix for proper view frustum culling - // update user camera and its children + if ( cameras.length === 2 ) { - camera.matrix.copy( cameraVR.matrix ); - camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + setProjectionFromUnion( cameraXR, cameraL, cameraR ); - const children = camera.children; + } else { - for ( let i = 0, l = children.length; i < l; i ++ ) { + // assume single camera setup (AR) - children[ i ].updateMatrixWorld( true ); + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); } - // update projection matrix for proper view frustum culling + // update user camera and its children - if ( cameras.length === 2 ) { + if ( userCamera ) { + + updateUserCamera( cameraXR, parent ); - setProjectionFromUnion( cameraVR, cameraL, cameraR ); + } + + return cameraXR; + + }; + + function updateUserCamera( cameraXR, parent ) { + + const camera = userCamera; + + if ( parent === null ) { + + camera.matrix.copy( cameraXR.matrixWorld ); } else { - // assume single camera setup (AR) + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); + + } + + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); + + const children = camera.children; - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].updateMatrixWorld( true ); } - }; + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); - this.getCamera = function () { + if ( camera.isPerspectiveCamera ) { - return cameraVR; + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; - }; + } + + } this.getFoveation = function () { @@ -26074,12 +26738,6 @@ class WebXRManager extends EventDispatcher { }; - this.getPlanes = function () { - - return planes; - - }; - // Animation Loop let onAnimationFrameCallback = null; @@ -26100,14 +26758,14 @@ class WebXRManager extends EventDispatcher { } - let cameraVRNeedsUpdate = false; + let cameraXRNeedsUpdate = false; - // check if it's necessary to rebuild cameraVR's camera list + // check if it's necessary to rebuild cameraXR's camera list - if ( views.length !== cameraVR.cameras.length ) { + if ( views.length !== cameraXR.cameras.length ) { - cameraVR.cameras.length = 0; - cameraVRNeedsUpdate = true; + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; } @@ -26152,18 +26810,21 @@ class WebXRManager extends EventDispatcher { } camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); if ( i === 0 ) { - cameraVR.matrix.copy( camera.matrix ); + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); } - if ( cameraVRNeedsUpdate === true ) { + if ( cameraXRNeedsUpdate === true ) { - cameraVR.cameras.push( camera ); + cameraXR.cameras.push( camera ); } @@ -26190,60 +26851,7 @@ class WebXRManager extends EventDispatcher { if ( frame.detectedPlanes ) { - scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } ); - - let planesToRemove = null; - - for ( const plane of planes ) { - - if ( ! frame.detectedPlanes.has( plane ) ) { - - if ( planesToRemove === null ) { - - planesToRemove = []; - - } - - planesToRemove.push( plane ); - - } - - } - - if ( planesToRemove !== null ) { - - for ( const plane of planesToRemove ) { - - planes.delete( plane ); - planesLastChangedTimes.delete( plane ); - scope.dispatchEvent( { type: 'planeremoved', data: plane } ); - - } - - } - - for ( const plane of frame.detectedPlanes ) { - - if ( ! planes.has( plane ) ) { - - planes.add( plane ); - planesLastChangedTimes.set( plane, frame.lastChangedTime ); - scope.dispatchEvent( { type: 'planeadded', data: plane } ); - - } else { - - const lastKnownTime = planesLastChangedTimes.get( plane ); - - if ( plane.lastChangedTime > lastKnownTime ) { - - planesLastChangedTimes.set( plane, plane.lastChangedTime ); - scope.dispatchEvent( { type: 'planechanged', data: plane } ); - - } - - } - - } + scope.dispatchEvent( { type: 'planesdetected', data: frame } ); } @@ -26269,6 +26877,18 @@ class WebXRManager extends EventDispatcher { function WebGLMaterials( renderer, properties ) { + function refreshTransformUniform( map, uniform ) { + + if ( map.matrixAutoUpdate === true ) { + + map.updateMatrix(); + + } + + uniform.value.copy( map.matrix ); + + } + function refreshFogUniforms( uniforms, fog ) { fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); @@ -26386,25 +27006,56 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.bumpMap ) { uniforms.bumpMap.value = material.bumpMap; + + refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); + uniforms.bumpScale.value = material.bumpScale; - if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; + + if ( material.side === BackSide ) { + + uniforms.bumpScale.value *= - 1; + + } + + } + + if ( material.normalMap ) { + + uniforms.normalMap.value = material.normalMap; + + refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); + + uniforms.normalScale.value.copy( material.normalScale ); + + if ( material.side === BackSide ) { + + uniforms.normalScale.value.negate(); + + } } if ( material.displacementMap ) { uniforms.displacementMap.value = material.displacementMap; + + refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); + uniforms.displacementScale.value = material.displacementScale; uniforms.displacementBias.value = material.displacementBias; @@ -26414,13 +27065,7 @@ function WebGLMaterials( renderer, properties ) { uniforms.emissiveMap.value = material.emissiveMap; - } - - if ( material.normalMap ) { - - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); - if ( material.side === BackSide ) uniforms.normalScale.value.negate(); + refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); } @@ -26428,6 +27073,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.specularMap.value = material.specularMap; + refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26455,10 +27102,12 @@ function WebGLMaterials( renderer, properties ) { uniforms.lightMap.value = material.lightMap; // artist-friendly light intensity scaling factor - const scaleFactor = ( renderer.physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( renderer.useLegacyLights === true ) ? Math.PI : 1; uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; + refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); + } if ( material.aoMap ) { @@ -26466,175 +27115,27 @@ function WebGLMaterials( renderer, properties ) { uniforms.aoMap.value = material.aoMap; uniforms.aoMapIntensity.value = material.aoMapIntensity; - } - - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. displacementMap map - // 4. normal map - // 5. bump map - // 6. roughnessMap map - // 7. metalnessMap map - // 8. alphaMap map - // 9. emissiveMap map - // 10. clearcoat map - // 11. clearcoat normal map - // 12. clearcoat roughnessMap map - // 13. iridescence map - // 14. iridescence thickness map - // 15. specular intensity map - // 16. specular tint map - // 17. transmission map - // 18. thickness map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.specularMap ) { - - uvScaleMap = material.specularMap; - - } else if ( material.displacementMap ) { - - uvScaleMap = material.displacementMap; - - } else if ( material.normalMap ) { - - uvScaleMap = material.normalMap; - - } else if ( material.bumpMap ) { - - uvScaleMap = material.bumpMap; - - } else if ( material.roughnessMap ) { - - uvScaleMap = material.roughnessMap; - - } else if ( material.metalnessMap ) { - - uvScaleMap = material.metalnessMap; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } else if ( material.emissiveMap ) { - - uvScaleMap = material.emissiveMap; - - } else if ( material.clearcoatMap ) { - - uvScaleMap = material.clearcoatMap; - - } else if ( material.clearcoatNormalMap ) { - - uvScaleMap = material.clearcoatNormalMap; - - } else if ( material.clearcoatRoughnessMap ) { - - uvScaleMap = material.clearcoatRoughnessMap; - - } else if ( material.iridescenceMap ) { - - uvScaleMap = material.iridescenceMap; - - } else if ( material.iridescenceThicknessMap ) { - - uvScaleMap = material.iridescenceThicknessMap; - - } else if ( material.specularIntensityMap ) { - - uvScaleMap = material.specularIntensityMap; - - } else if ( material.specularColorMap ) { - - uvScaleMap = material.specularColorMap; - - } else if ( material.transmissionMap ) { - - uvScaleMap = material.transmissionMap; - - } else if ( material.thicknessMap ) { - - uvScaleMap = material.thicknessMap; - - } else if ( material.sheenColorMap ) { - - uvScaleMap = material.sheenColorMap; - - } else if ( material.sheenRoughnessMap ) { - - uvScaleMap = material.sheenRoughnessMap; + refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); } - if ( uvScaleMap !== undefined ) { - - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { - - uvScaleMap = uvScaleMap.texture; - - } - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - - // uv repeat and offset setting priorities for uv2 - // 1. ao map - // 2. light map - - let uv2ScaleMap; - - if ( material.aoMap ) { - - uv2ScaleMap = material.aoMap; - - } else if ( material.lightMap ) { - - uv2ScaleMap = material.lightMap; - - } - - if ( uv2ScaleMap !== undefined ) { - - // backwards compatibility - if ( uv2ScaleMap.isWebGLRenderTarget ) { - - uv2ScaleMap = uv2ScaleMap.texture; + } - } + function refreshUniformsLine( uniforms, material ) { - if ( uv2ScaleMap.matrixAutoUpdate === true ) { + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - uv2ScaleMap.updateMatrix(); + if ( material.map ) { - } + uniforms.map.value = material.map; - uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix ); + refreshTransformUniform( material.map, uniforms.mapTransform ); } } - function refreshUniformsLine( uniforms, material ) { - - uniforms.diffuse.value.copy( material.color ); - uniforms.opacity.value = material.opacity; - - } - function refreshUniformsDash( uniforms, material ) { uniforms.dashSize.value = material.dashSize; @@ -26654,12 +27155,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.uvTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26668,34 +27173,6 @@ function WebGLMaterials( renderer, properties ) { } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsSprites( uniforms, material ) { @@ -26708,12 +27185,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26722,34 +27203,6 @@ function WebGLMaterials( renderer, properties ) { } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsPhong( uniforms, material ) { @@ -26771,18 +27224,23 @@ function WebGLMaterials( renderer, properties ) { function refreshUniformsStandard( uniforms, material ) { - uniforms.roughness.value = material.roughness; uniforms.metalness.value = material.metalness; - if ( material.roughnessMap ) { + if ( material.metalnessMap ) { - uniforms.roughnessMap.value = material.roughnessMap; + uniforms.metalnessMap.value = material.metalnessMap; + + refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); } - if ( material.metalnessMap ) { + uniforms.roughness.value = material.roughness; - uniforms.metalnessMap.value = material.metalnessMap; + if ( material.roughnessMap ) { + + uniforms.roughnessMap.value = material.roughnessMap; + + refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); } @@ -26811,12 +27269,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.sheenColorMap.value = material.sheenColorMap; + refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); + } if ( material.sheenRoughnessMap ) { uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; + refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); + } } @@ -26830,19 +27292,26 @@ function WebGLMaterials( renderer, properties ) { uniforms.clearcoatMap.value = material.clearcoatMap; + refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); + } if ( material.clearcoatRoughnessMap ) { uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; + refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); + } if ( material.clearcoatNormalMap ) { - uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; + refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); + + uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); + if ( material.side === BackSide ) { uniforms.clearcoatNormalScale.value.negate(); @@ -26864,12 +27333,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.iridescenceMap.value = material.iridescenceMap; + refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); + } if ( material.iridescenceThicknessMap ) { uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; + refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); + } } @@ -26884,6 +27357,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.transmissionMap.value = material.transmissionMap; + refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); + } uniforms.thickness.value = material.thickness; @@ -26892,6 +27367,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.thicknessMap.value = material.thicknessMap; + refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); + } uniforms.attenuationDistance.value = material.attenuationDistance; @@ -26899,19 +27376,37 @@ function WebGLMaterials( renderer, properties ) { } - uniforms.specularIntensity.value = material.specularIntensity; - uniforms.specularColor.value.copy( material.specularColor ); + if ( material.anisotropy > 0 ) { - if ( material.specularIntensityMap ) { + uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - uniforms.specularIntensityMap.value = material.specularIntensityMap; + if ( material.anisotropyMap ) { + + uniforms.anisotropyMap.value = material.anisotropyMap; + + refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); + + } } + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy( material.specularColor ); + if ( material.specularColorMap ) { uniforms.specularColorMap.value = material.specularColorMap; + refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); + + } + + if ( material.specularIntensityMap ) { + + uniforms.specularIntensityMap.value = material.specularIntensityMap; + + refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); + } } @@ -26928,9 +27423,11 @@ function WebGLMaterials( renderer, properties ) { function refreshUniformsDistance( uniforms, material ) { - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; + const light = properties.get( material ).light; + + uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); + uniforms.nearDistance.value = light.shadow.camera.near; + uniforms.farDistance.value = light.shadow.camera.far; } @@ -27360,2199 +27857,2374 @@ function createCanvasElement() { } -function WebGLRenderer( parameters = {} ) { +class WebGLRenderer { - this.isWebGLRenderer = true; + constructor( parameters = {} ) { - const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(), - _context = parameters.context !== undefined ? parameters.context : null, + const { + canvas = createCanvasElement(), + context = null, + depth = true, + stencil = true, + alpha = false, + antialias = false, + premultipliedAlpha = true, + preserveDrawingBuffer = false, + powerPreference = 'default', + failIfMajorPerformanceCaveat = false, + } = parameters; - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, - _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', - _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; + this.isWebGLRenderer = true; - let _alpha; + let _alpha; - if ( _context !== null ) { + if ( context !== null ) { - _alpha = _context.getContextAttributes().alpha; + _alpha = context.getContextAttributes().alpha; - } else { + } else { - _alpha = parameters.alpha !== undefined ? parameters.alpha : false; + _alpha = alpha; - } + } - let currentRenderList = null; - let currentRenderState = null; + const uintClearColor = new Uint32Array( 4 ); + const intClearColor = new Int32Array( 4 ); - // render() can be called from within a callback triggered by another render. - // We track this so that the nested render call gets its list and state isolated from the parent render call. + let currentRenderList = null; + let currentRenderState = null; - const renderListStack = []; - const renderStateStack = []; + // render() can be called from within a callback triggered by another render. + // We track this so that the nested render call gets its list and state isolated from the parent render call. - // public properties + const renderListStack = []; + const renderStateStack = []; - this.domElement = _canvas; + // public properties - // Debug configuration container - this.debug = { + this.domElement = canvas; - /** - * Enables error checking and reporting when shader programs are being compiled - * @type {boolean} - */ - checkShaderErrors: true - }; + // Debug configuration container + this.debug = { - // clearing + /** + * Enables error checking and reporting when shader programs are being compiled + * @type {boolean} + */ + checkShaderErrors: true, + /** + * Callback for custom error reporting. + * @type {?Function} + */ + onShaderError: null + }; - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; + // clearing - // scene graph + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; - this.sortObjects = true; + // scene graph - // user-defined clipping + this.sortObjects = true; - this.clippingPlanes = []; - this.localClippingEnabled = false; + // user-defined clipping - // physically based shading + this.clippingPlanes = []; + this.localClippingEnabled = false; - this.outputEncoding = LinearEncoding; + // physically based shading - // physical lights + this.outputColorSpace = SRGBColorSpace; - this.physicallyCorrectLights = false; + // physical lights - // tone mapping + this.useLegacyLights = true; - this.toneMapping = NoToneMapping; - this.toneMappingExposure = 1.0; + // tone mapping - // internal properties + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; - const _this = this; + // internal properties - let _isContextLost = false; + const _this = this; - // internal state cache + let _isContextLost = false; - let _currentActiveCubeFace = 0; - let _currentActiveMipmapLevel = 0; - let _currentRenderTarget = null; - let _currentMaterialId = - 1; + // internal state cache - let _currentCamera = null; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = - 1; - const _currentViewport = new Vector4(); - const _currentScissor = new Vector4(); - let _currentScissorTest = null; + let _currentCamera = null; - // + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; - let _width = _canvas.width; - let _height = _canvas.height; + const _currentClearColor = new Color( 0x000000 ); + let _currentClearAlpha = 0; - let _pixelRatio = 1; - let _opaqueSort = null; - let _transparentSort = null; + // - const _viewport = new Vector4( 0, 0, _width, _height ); - const _scissor = new Vector4( 0, 0, _width, _height ); - let _scissorTest = false; + let _width = canvas.width; + let _height = canvas.height; - // frustum + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; - const _frustum = new Frustum(); + const _viewport = new Vector4( 0, 0, _width, _height ); + const _scissor = new Vector4( 0, 0, _width, _height ); + let _scissorTest = false; - // clipping + // frustum - let _clippingEnabled = false; - let _localClippingEnabled = false; + const _frustum = new Frustum(); - // transmission + // clipping - let _transmissionRenderTarget = null; + let _clippingEnabled = false; + let _localClippingEnabled = false; - // camera matrices cache + // transmission - const _projScreenMatrix = new Matrix4(); + let _transmissionRenderTarget = null; - const _vector2 = new Vector2(); - const _vector3 = new Vector3(); + // camera matrices cache - const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; + const _projScreenMatrix = new Matrix4(); - function getTargetPixelRatio() { + const _vector2 = new Vector2(); + const _vector3 = new Vector3(); - return _currentRenderTarget === null ? _pixelRatio : 1; + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; - } + function getTargetPixelRatio() { + + return _currentRenderTarget === null ? _pixelRatio : 1; + + } - // initialize + // initialize - let _gl = _context; + let _gl = context; - function getContext( contextNames, contextAttributes ) { + function getContext( contextNames, contextAttributes ) { - for ( let i = 0; i < contextNames.length; i ++ ) { + for ( let i = 0; i < contextNames.length; i ++ ) { - const contextName = contextNames[ i ]; - const context = _canvas.getContext( contextName, contextAttributes ); - if ( context !== null ) return context; + const contextName = contextNames[ i ]; + const context = canvas.getContext( contextName, contextAttributes ); + if ( context !== null ) return context; + + } + + return null; } - return null; + try { - } + const contextAttributes = { + alpha: true, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + powerPreference, + failIfMajorPerformanceCaveat, + }; - try { + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); - const contextAttributes = { - alpha: true, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer, - powerPreference: _powerPreference, - failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat - }; + // event listeners must be registered before WebGL context is created, see #12753 + canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + + if ( _gl === null ) { - // OffscreenCanvas does not have setAttribute, see #22811 - if ( 'setAttribute' in _canvas ) _canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); + const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; - // event listeners must be registered before WebGL context is created, see #12753 - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + if ( _this.isWebGL1Renderer === true ) { - if ( _gl === null ) { + contextNames.shift(); - const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; + } - if ( _this.isWebGL1Renderer === true ) { + _gl = getContext( contextNames, contextAttributes ); - contextNames.shift(); + if ( _gl === null ) { + + if ( getContext( contextNames ) ) { + + throw new Error( 'Error creating WebGL context with your selected attributes.' ); + + } else { + + throw new Error( 'Error creating WebGL context.' ); + + } + + } } - _gl = getContext( contextNames, contextAttributes ); + if ( _gl instanceof WebGLRenderingContext ) { // @deprecated, r153 - if ( _gl === null ) { + console.warn( 'THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.' ); - if ( getContext( contextNames ) ) { + } - throw new Error( 'Error creating WebGL context with your selected attributes.' ); + // Some experimental-webgl implementations do not have getShaderPrecisionFormat - } else { + if ( _gl.getShaderPrecisionFormat === undefined ) { - throw new Error( 'Error creating WebGL context.' ); + _gl.getShaderPrecisionFormat = function () { - } + return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + + }; } + } catch ( error ) { + + console.error( 'THREE.WebGLRenderer: ' + error.message ); + throw error; + } - // Some experimental-webgl implementations do not have getShaderPrecisionFormat + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; - if ( _gl.getShaderPrecisionFormat === undefined ) { + let background, morphtargets, bufferRenderer, indexedBufferRenderer; - _gl.getShaderPrecisionFormat = function () { + let utils, bindingStates, uniformsGroups; - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + function initGLContext() { - }; + extensions = new WebGLExtensions( _gl ); + + capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + + extensions.init( capabilities ); + + utils = new WebGLUtils( _gl, extensions, capabilities ); + + state = new WebGLState( _gl, extensions, capabilities ); + + info = new WebGLInfo( _gl ); + properties = new WebGLProperties(); + textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); + cubemaps = new WebGLCubeMaps( _this ); + cubeuvmaps = new WebGLCubeUVMaps( _this ); + attributes = new WebGLAttributes( _gl, capabilities ); + bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); + geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); + objects = new WebGLObjects( _gl, geometries, attributes, info ); + morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); + clipping = new WebGLClipping( properties ); + programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); + materials = new WebGLMaterials( _this, properties ); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates( extensions, capabilities ); + background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + shadowMap = new WebGLShadowMap( _this, objects, capabilities ); + uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); + + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); + + info.programs = programCache.programs; + + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.shadowMap = shadowMap; + _this.state = state; + _this.info = info; } - } catch ( error ) { + initGLContext(); - console.error( 'THREE.WebGLRenderer: ' + error.message ); - throw error; + // xr - } + const xr = new WebXRManager( _this, _gl ); - let extensions, capabilities, state, info; - let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; - let programCache, materials, renderLists, renderStates, clipping, shadowMap; + this.xr = xr; - let background, morphtargets, bufferRenderer, indexedBufferRenderer; + // API - let utils, bindingStates, uniformsGroups; + this.getContext = function () { - function initGLContext() { + return _gl; - extensions = new WebGLExtensions( _gl ); + }; - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + this.getContextAttributes = function () { - extensions.init( capabilities ); + return _gl.getContextAttributes(); - utils = new WebGLUtils( _gl, extensions, capabilities ); + }; - state = new WebGLState( _gl, extensions, capabilities ); + this.forceContextLoss = function () { - info = new WebGLInfo( _gl ); - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); - cubemaps = new WebGLCubeMaps( _this ); - cubeuvmaps = new WebGLCubeUVMaps( _this ); - attributes = new WebGLAttributes( _gl, capabilities ); - bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); - geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); - objects = new WebGLObjects( _gl, geometries, attributes, info ); - morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); - clipping = new WebGLClipping( properties ); - programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); - materials = new WebGLMaterials( _this, properties ); - renderLists = new WebGLRenderLists(); - renderStates = new WebGLRenderStates( extensions, capabilities ); - background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, _premultipliedAlpha ); - shadowMap = new WebGLShadowMap( _this, objects, capabilities ); - uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.loseContext(); - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); + }; - info.programs = programCache.programs; + this.forceContextRestore = function () { - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.shadowMap = shadowMap; - _this.state = state; - _this.info = info; + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); - } + }; + + this.getPixelRatio = function () { + + return _pixelRatio; + + }; + + this.setPixelRatio = function ( value ) { + + if ( value === undefined ) return; + + _pixelRatio = value; + + this.setSize( _width, _height, false ); + + }; + + this.getSize = function ( target ) { + + return target.set( _width, _height ); + + }; + + this.setSize = function ( width, height, updateStyle = true ) { + + if ( xr.isPresenting ) { + + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; - initGLContext(); + } + + _width = width; + _height = height; + + canvas.width = Math.floor( width * _pixelRatio ); + canvas.height = Math.floor( height * _pixelRatio ); + + if ( updateStyle === true ) { + + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; + + } + + this.setViewport( 0, 0, width, height ); + + }; + + this.getDrawingBufferSize = function ( target ) { + + return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + + }; + + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + + _width = width; + _height = height; + + _pixelRatio = pixelRatio; + + canvas.width = Math.floor( width * pixelRatio ); + canvas.height = Math.floor( height * pixelRatio ); + + this.setViewport( 0, 0, width, height ); + + }; + + this.getCurrentViewport = function ( target ) { + + return target.copy( _currentViewport ); + + }; + + this.getViewport = function ( target ) { + + return target.copy( _viewport ); + + }; + + this.setViewport = function ( x, y, width, height ) { + + if ( x.isVector4 ) { + + _viewport.set( x.x, x.y, x.z, x.w ); + + } else { - // xr + _viewport.set( x, y, width, height ); - const xr = new WebXRManager( _this, _gl ); + } - this.xr = xr; + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); - // API + }; - this.getContext = function () { + this.getScissor = function ( target ) { - return _gl; + return target.copy( _scissor ); - }; + }; - this.getContextAttributes = function () { + this.setScissor = function ( x, y, width, height ) { - return _gl.getContextAttributes(); + if ( x.isVector4 ) { - }; + _scissor.set( x.x, x.y, x.z, x.w ); - this.forceContextLoss = function () { + } else { - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.loseContext(); + _scissor.set( x, y, width, height ); - }; + } - this.forceContextRestore = function () { + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.restoreContext(); + }; - }; + this.getScissorTest = function () { - this.getPixelRatio = function () { + return _scissorTest; - return _pixelRatio; + }; - }; + this.setScissorTest = function ( boolean ) { - this.setPixelRatio = function ( value ) { + state.setScissorTest( _scissorTest = boolean ); - if ( value === undefined ) return; + }; - _pixelRatio = value; + this.setOpaqueSort = function ( method ) { - this.setSize( _width, _height, false ); + _opaqueSort = method; - }; + }; - this.getSize = function ( target ) { + this.setTransparentSort = function ( method ) { - return target.set( _width, _height ); + _transparentSort = method; - }; + }; - this.setSize = function ( width, height, updateStyle ) { + // Clearing - if ( xr.isPresenting ) { + this.getClearColor = function ( target ) { - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; + return target.copy( background.getClearColor() ); - } + }; - _width = width; - _height = height; + this.setClearColor = function () { - _canvas.width = Math.floor( width * _pixelRatio ); - _canvas.height = Math.floor( height * _pixelRatio ); + background.setClearColor.apply( background, arguments ); - if ( updateStyle !== false ) { + }; - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; + this.getClearAlpha = function () { - } + return background.getClearAlpha(); - this.setViewport( 0, 0, width, height ); + }; - }; + this.setClearAlpha = function () { - this.getDrawingBufferSize = function ( target ) { + background.setClearAlpha.apply( background, arguments ); - return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + }; - }; + this.clear = function ( color = true, depth = true, stencil = true ) { - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + let bits = 0; - _width = width; - _height = height; + if ( color ) { - _pixelRatio = pixelRatio; + // check if we're trying to clear an integer target + let isIntegerFormat = false; + if ( _currentRenderTarget !== null ) { - _canvas.width = Math.floor( width * pixelRatio ); - _canvas.height = Math.floor( height * pixelRatio ); + const targetFormat = _currentRenderTarget.texture.format; + isIntegerFormat = targetFormat === RGBAIntegerFormat || + targetFormat === RGIntegerFormat || + targetFormat === RedIntegerFormat; - this.setViewport( 0, 0, width, height ); + } - }; + // use the appropriate clear functions to clear the target if it's a signed + // or unsigned integer target + if ( isIntegerFormat ) { - this.getCurrentViewport = function ( target ) { + const targetType = _currentRenderTarget.texture.type; + const isUnsignedType = targetType === UnsignedByteType || + targetType === UnsignedIntType || + targetType === UnsignedShortType || + targetType === UnsignedInt248Type || + targetType === UnsignedShort4444Type || + targetType === UnsignedShort5551Type; - return target.copy( _currentViewport ); + const clearColor = background.getClearColor(); + const a = background.getClearAlpha(); + const r = clearColor.r; + const g = clearColor.g; + const b = clearColor.b; - }; + const __webglFramebuffer = properties.get( _currentRenderTarget ).__webglFramebuffer; - this.getViewport = function ( target ) { + if ( isUnsignedType ) { - return target.copy( _viewport ); + uintClearColor[ 0 ] = r; + uintClearColor[ 1 ] = g; + uintClearColor[ 2 ] = b; + uintClearColor[ 3 ] = a; + _gl.clearBufferuiv( _gl.COLOR, __webglFramebuffer, uintClearColor ); - }; + } else { - this.setViewport = function ( x, y, width, height ) { + intClearColor[ 0 ] = r; + intClearColor[ 1 ] = g; + intClearColor[ 2 ] = b; + intClearColor[ 3 ] = a; + _gl.clearBufferiv( _gl.COLOR, __webglFramebuffer, intClearColor ); - if ( x.isVector4 ) { + } - _viewport.set( x.x, x.y, x.z, x.w ); + } else { - } else { + bits |= _gl.COLOR_BUFFER_BIT; - _viewport.set( x, y, width, height ); + } - } + } - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); + if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( stencil ) bits |= _gl.STENCIL_BUFFER_BIT; - }; + _gl.clear( bits ); - this.getScissor = function ( target ) { + }; - return target.copy( _scissor ); + this.clearColor = function () { - }; + this.clear( true, false, false ); - this.setScissor = function ( x, y, width, height ) { + }; - if ( x.isVector4 ) { + this.clearDepth = function () { - _scissor.set( x.x, x.y, x.z, x.w ); + this.clear( false, true, false ); - } else { + }; - _scissor.set( x, y, width, height ); + this.clearStencil = function () { - } + this.clear( false, false, true ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); + }; - }; + // - this.getScissorTest = function () { + this.dispose = function () { - return _scissorTest; + canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - }; + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); - this.setScissorTest = function ( boolean ) { + xr.dispose(); - state.setScissorTest( _scissorTest = boolean ); + xr.removeEventListener( 'sessionstart', onXRSessionStart ); + xr.removeEventListener( 'sessionend', onXRSessionEnd ); - }; + if ( _transmissionRenderTarget ) { - this.setOpaqueSort = function ( method ) { + _transmissionRenderTarget.dispose(); + _transmissionRenderTarget = null; - _opaqueSort = method; + } - }; + animation.stop(); - this.setTransparentSort = function ( method ) { + }; - _transparentSort = method; + // Events - }; + function onContextLost( event ) { - // Clearing + event.preventDefault(); - this.getClearColor = function ( target ) { + console.log( 'THREE.WebGLRenderer: Context Lost.' ); - return target.copy( background.getClearColor() ); + _isContextLost = true; - }; + } - this.setClearColor = function () { + function onContextRestore( /* event */ ) { - background.setClearColor.apply( background, arguments ); + console.log( 'THREE.WebGLRenderer: Context Restored.' ); - }; + _isContextLost = false; - this.getClearAlpha = function () { + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; - return background.getClearAlpha(); + initGLContext(); - }; + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; - this.setClearAlpha = function () { + } - background.setClearAlpha.apply( background, arguments ); + function onContextCreationError( event ) { - }; + console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); - this.clear = function ( color = true, depth = true, stencil = true ) { + } - let bits = 0; + function onMaterialDispose( event ) { - if ( color ) bits |= _gl.COLOR_BUFFER_BIT; - if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; - if ( stencil ) bits |= _gl.STENCIL_BUFFER_BIT; + const material = event.target; - _gl.clear( bits ); + material.removeEventListener( 'dispose', onMaterialDispose ); - }; + deallocateMaterial( material ); - this.clearColor = function () { + } - this.clear( true, false, false ); + // Buffer deallocation - }; + function deallocateMaterial( material ) { - this.clearDepth = function () { + releaseMaterialProgramReferences( material ); - this.clear( false, true, false ); + properties.remove( material ); - }; + } - this.clearStencil = function () { - this.clear( false, false, true ); + function releaseMaterialProgramReferences( material ) { - }; + const programs = properties.get( material ).programs; - // + if ( programs !== undefined ) { - this.dispose = function () { + programs.forEach( function ( program ) { - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + programCache.releaseProgram( program ); - renderLists.dispose(); - renderStates.dispose(); - properties.dispose(); - cubemaps.dispose(); - cubeuvmaps.dispose(); - objects.dispose(); - bindingStates.dispose(); - uniformsGroups.dispose(); - programCache.dispose(); + } ); - xr.dispose(); + if ( material.isShaderMaterial ) { - xr.removeEventListener( 'sessionstart', onXRSessionStart ); - xr.removeEventListener( 'sessionend', onXRSessionEnd ); + programCache.releaseShaderCache( material ); - if ( _transmissionRenderTarget ) { + } - _transmissionRenderTarget.dispose(); - _transmissionRenderTarget = null; + } } - animation.stop(); + // Buffer rendering - }; + this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { - // Events + if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) - function onContextLost( event ) { + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); - event.preventDefault(); + const program = setProgram( camera, scene, geometry, material, object ); - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + state.setMaterial( material, frontFaceCW ); - _isContextLost = true; + // - } + let index = geometry.index; + let rangeFactor = 1; - function onContextRestore( /* event */ ) { + if ( material.wireframe === true ) { - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + index = geometries.getWireframeAttribute( geometry ); + rangeFactor = 2; - _isContextLost = false; + } - const infoAutoReset = info.autoReset; - const shadowMapEnabled = shadowMap.enabled; - const shadowMapAutoUpdate = shadowMap.autoUpdate; - const shadowMapNeedsUpdate = shadowMap.needsUpdate; - const shadowMapType = shadowMap.type; + // - initGLContext(); + const drawRange = geometry.drawRange; + const position = geometry.attributes.position; - info.autoReset = infoAutoReset; - shadowMap.enabled = shadowMapEnabled; - shadowMap.autoUpdate = shadowMapAutoUpdate; - shadowMap.needsUpdate = shadowMapNeedsUpdate; - shadowMap.type = shadowMapType; + let drawStart = drawRange.start * rangeFactor; + let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; - } + if ( group !== null ) { - function onContextCreationError( event ) { + drawStart = Math.max( drawStart, group.start * rangeFactor ); + drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); - console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); + } - } + if ( index !== null ) { - function onMaterialDispose( event ) { + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, index.count ); - const material = event.target; + } else if ( position !== undefined && position !== null ) { - material.removeEventListener( 'dispose', onMaterialDispose ); + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, position.count ); - deallocateMaterial( material ); + } - } + const drawCount = drawEnd - drawStart; - // Buffer deallocation + if ( drawCount < 0 || drawCount === Infinity ) return; - function deallocateMaterial( material ) { + // - releaseMaterialProgramReferences( material ); + bindingStates.setup( object, material, program, geometry, index ); - properties.remove( material ); + let attribute; + let renderer = bufferRenderer; - } + if ( index !== null ) { + attribute = attributes.get( index ); - function releaseMaterialProgramReferences( material ) { + renderer = indexedBufferRenderer; + renderer.setIndex( attribute ); - const programs = properties.get( material ).programs; + } - if ( programs !== undefined ) { + // - programs.forEach( function ( program ) { + if ( object.isMesh ) { - programCache.releaseProgram( program ); + if ( material.wireframe === true ) { - } ); + state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); + renderer.setMode( _gl.LINES ); - if ( material.isShaderMaterial ) { + } else { - programCache.releaseShaderCache( material ); + renderer.setMode( _gl.TRIANGLES ); - } + } - } + } else if ( object.isLine ) { - } + let lineWidth = material.linewidth; - // Buffer rendering + if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { + state.setLineWidth( lineWidth * getTargetPixelRatio() ); - if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) + if ( object.isLineSegments ) { - const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + renderer.setMode( _gl.LINES ); - const program = setProgram( camera, scene, geometry, material, object ); + } else if ( object.isLineLoop ) { - state.setMaterial( material, frontFaceCW ); + renderer.setMode( _gl.LINE_LOOP ); - // + } else { - let index = geometry.index; - let rangeFactor = 1; + renderer.setMode( _gl.LINE_STRIP ); - if ( material.wireframe === true ) { + } - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; + } else if ( object.isPoints ) { - } + renderer.setMode( _gl.POINTS ); - // + } else if ( object.isSprite ) { - const drawRange = geometry.drawRange; - const position = geometry.attributes.position; + renderer.setMode( _gl.TRIANGLES ); - let drawStart = drawRange.start * rangeFactor; - let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; + } - if ( group !== null ) { + if ( object.isInstancedMesh ) { - drawStart = Math.max( drawStart, group.start * rangeFactor ); - drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); + renderer.renderInstances( drawStart, drawCount, object.count ); - } + } else if ( geometry.isInstancedBufferGeometry ) { - if ( index !== null ) { + const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; + const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, index.count ); + renderer.renderInstances( drawStart, drawCount, instanceCount ); - } else if ( position !== undefined && position !== null ) { + } else { - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, position.count ); + renderer.render( drawStart, drawCount ); - } + } - const drawCount = drawEnd - drawStart; + }; - if ( drawCount < 0 || drawCount === Infinity ) return; + // Compile - // + this.compile = function ( scene, camera ) { - bindingStates.setup( object, material, program, geometry, index ); + function prepare( material, scene, object ) { - let attribute; - let renderer = bufferRenderer; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - if ( index !== null ) { + material.side = BackSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - attribute = attributes.get( index ); + material.side = FrontSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); + material.side = DoubleSide; - } + } else { - // + getProgram( material, scene, object ); - if ( object.isMesh ) { + } - if ( material.wireframe === true ) { + } - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( _gl.LINES ); + currentRenderState = renderStates.get( scene ); + currentRenderState.init(); - } else { + renderStateStack.push( currentRenderState ); - renderer.setMode( _gl.TRIANGLES ); + scene.traverseVisible( function ( object ) { - } + if ( object.isLight && object.layers.test( camera.layers ) ) { - } else if ( object.isLine ) { + currentRenderState.pushLight( object ); - let lineWidth = material.linewidth; + if ( object.castShadow ) { - if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material + currentRenderState.pushShadow( object ); - state.setLineWidth( lineWidth * getTargetPixelRatio() ); + } - if ( object.isLineSegments ) { + } - renderer.setMode( _gl.LINES ); + } ); - } else if ( object.isLineLoop ) { + currentRenderState.setupLights( _this.useLegacyLights ); - renderer.setMode( _gl.LINE_LOOP ); + scene.traverse( function ( object ) { - } else { + const material = object.material; - renderer.setMode( _gl.LINE_STRIP ); + if ( material ) { - } + if ( Array.isArray( material ) ) { - } else if ( object.isPoints ) { + for ( let i = 0; i < material.length; i ++ ) { - renderer.setMode( _gl.POINTS ); + const material2 = material[ i ]; - } else if ( object.isSprite ) { + prepare( material2, scene, object ); - renderer.setMode( _gl.TRIANGLES ); + } - } + } else { - if ( object.isInstancedMesh ) { + prepare( material, scene, object ); - renderer.renderInstances( drawStart, drawCount, object.count ); + } - } else if ( geometry.isInstancedBufferGeometry ) { + } - const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; - const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); + } ); - renderer.renderInstances( drawStart, drawCount, instanceCount ); + renderStateStack.pop(); + currentRenderState = null; - } else { + }; - renderer.render( drawStart, drawCount ); + // Animation Loop - } + let onAnimationFrameCallback = null; - }; + function onAnimationFrame( time ) { - // Compile + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); - this.compile = function ( scene, camera ) { + } - function prepare( material, scene, object ) { + function onXRSessionStart() { - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + animation.stop(); - material.side = BackSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + } - material.side = FrontSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + function onXRSessionEnd() { - material.side = DoubleSide; + animation.start(); - } else { + } - getProgram( material, scene, object ); + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); - } + if ( typeof self !== 'undefined' ) animation.setContext( self ); - } + this.setAnimationLoop = function ( callback ) { - currentRenderState = renderStates.get( scene ); - currentRenderState.init(); + onAnimationFrameCallback = callback; + xr.setAnimationLoop( callback ); - renderStateStack.push( currentRenderState ); + ( callback === null ) ? animation.stop() : animation.start(); - scene.traverseVisible( function ( object ) { + }; - if ( object.isLight && object.layers.test( camera.layers ) ) { + xr.addEventListener( 'sessionstart', onXRSessionStart ); + xr.addEventListener( 'sessionend', onXRSessionEnd ); - currentRenderState.pushLight( object ); + // Rendering - if ( object.castShadow ) { + this.render = function ( scene, camera ) { - currentRenderState.pushShadow( object ); + if ( camera !== undefined && camera.isCamera !== true ) { - } + console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + return; } - } ); + if ( _isContextLost === true ) return; - currentRenderState.setupLights( _this.physicallyCorrectLights ); + // update scene graph - scene.traverse( function ( object ) { + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); - const material = object.material; + // update camera matrices and frustum - if ( material ) { + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - if ( Array.isArray( material ) ) { + if ( xr.enabled === true && xr.isPresenting === true ) { - for ( let i = 0; i < material.length; i ++ ) { + camera = xr.updateCameraXR( camera ); // use XR camera for rendering - const material2 = material[ i ]; + } - prepare( material2, scene, object ); + // + if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); - } + currentRenderState = renderStates.get( scene, renderStateStack.length ); + currentRenderState.init(); - } else { + renderStateStack.push( currentRenderState ); - prepare( material, scene, object ); + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix ); - } + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); - } + currentRenderList = renderLists.get( scene, renderListStack.length ); + currentRenderList.init(); - } ); + renderListStack.push( currentRenderList ); - renderStateStack.pop(); - currentRenderState = null; + projectObject( scene, camera, 0, _this.sortObjects ); - }; + currentRenderList.finish(); - // Animation Loop + if ( _this.sortObjects === true ) { - let onAnimationFrameCallback = null; + currentRenderList.sort( _opaqueSort, _transparentSort ); - function onAnimationFrame( time ) { + } - if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); + // - } + if ( _clippingEnabled === true ) clipping.beginShadows(); - function onXRSessionStart() { + const shadowsArray = currentRenderState.state.shadowsArray; - animation.stop(); + shadowMap.render( shadowsArray, scene, camera ); - } + if ( _clippingEnabled === true ) clipping.endShadows(); - function onXRSessionEnd() { + // - animation.start(); + if ( this.info.autoReset === true ) this.info.reset(); - } + this.info.render.frame ++; - const animation = new WebGLAnimation(); - animation.setAnimationLoop( onAnimationFrame ); + // - if ( typeof self !== 'undefined' ) animation.setContext( self ); + background.render( currentRenderList, scene ); - this.setAnimationLoop = function ( callback ) { + // render scene - onAnimationFrameCallback = callback; - xr.setAnimationLoop( callback ); + currentRenderState.setupLights( _this.useLegacyLights ); - ( callback === null ) ? animation.stop() : animation.start(); + if ( camera.isArrayCamera ) { - }; + const cameras = camera.cameras; - xr.addEventListener( 'sessionstart', onXRSessionStart ); - xr.addEventListener( 'sessionend', onXRSessionEnd ); + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - // Rendering + const camera2 = cameras[ i ]; - this.render = function ( scene, camera ) { + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - if ( camera !== undefined && camera.isCamera !== true ) { + } - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; + } else { - } + renderScene( currentRenderList, scene, camera ); - if ( _isContextLost === true ) return; + } - // update scene graph + // - if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); + if ( _currentRenderTarget !== null ) { - // update camera matrices and frustum + // resolve multisample renderbuffers to a single-sample texture if necessary - if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); + textures.updateMultisampleRenderTarget( _currentRenderTarget ); - if ( xr.enabled === true && xr.isPresenting === true ) { + // Generate mipmap if we're using any kind of mipmap filtering - if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); + textures.updateRenderTargetMipmap( _currentRenderTarget ); - camera = xr.getCamera(); // use XR camera for rendering + } - } + // - // - if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); + if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); - currentRenderState = renderStates.get( scene, renderStateStack.length ); - currentRenderState.init(); + // _gl.finish(); - renderStateStack.push( currentRenderState ); + bindingStates.resetDefaultState(); + _currentMaterialId = - 1; + _currentCamera = null; - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromProjectionMatrix( _projScreenMatrix ); + renderStateStack.pop(); - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); + if ( renderStateStack.length > 0 ) { - currentRenderList = renderLists.get( scene, renderListStack.length ); - currentRenderList.init(); + currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; - renderListStack.push( currentRenderList ); + } else { - projectObject( scene, camera, 0, _this.sortObjects ); + currentRenderState = null; - currentRenderList.finish(); + } - if ( _this.sortObjects === true ) { + renderListStack.pop(); - currentRenderList.sort( _opaqueSort, _transparentSort ); + if ( renderListStack.length > 0 ) { - } + currentRenderList = renderListStack[ renderListStack.length - 1 ]; - // + } else { - if ( _clippingEnabled === true ) clipping.beginShadows(); + currentRenderList = null; - const shadowsArray = currentRenderState.state.shadowsArray; + } - shadowMap.render( shadowsArray, scene, camera ); + }; - if ( _clippingEnabled === true ) clipping.endShadows(); + function projectObject( object, camera, groupOrder, sortObjects ) { - // + if ( object.visible === false ) return; - if ( this.info.autoReset === true ) this.info.reset(); + const visible = object.layers.test( camera.layers ); - // + if ( visible ) { - background.render( currentRenderList, scene ); + if ( object.isGroup ) { - // render scene + groupOrder = object.renderOrder; - currentRenderState.setupLights( _this.physicallyCorrectLights ); + } else if ( object.isLOD ) { - if ( camera.isArrayCamera ) { + if ( object.autoUpdate === true ) object.update( camera ); - const cameras = camera.cameras; + } else if ( object.isLight ) { - for ( let i = 0, l = cameras.length; i < l; i ++ ) { + currentRenderState.pushLight( object ); - const camera2 = cameras[ i ]; + if ( object.castShadow ) { - renderScene( currentRenderList, scene, camera2, camera2.viewport ); + currentRenderState.pushShadow( object ); - } + } - } else { + } else if ( object.isSprite ) { - renderScene( currentRenderList, scene, camera ); + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - } + if ( sortObjects ) { - // + _vector3.setFromMatrixPosition( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - if ( _currentRenderTarget !== null ) { + } - // resolve multisample renderbuffers to a single-sample texture if necessary + const geometry = objects.update( object ); + const material = object.material; - textures.updateMultisampleRenderTarget( _currentRenderTarget ); + if ( material.visible ) { - // Generate mipmap if we're using any kind of mipmap filtering + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); - textures.updateRenderTargetMipmap( _currentRenderTarget ); + } - } + } - // + } else if ( object.isMesh || object.isLine || object.isPoints ) { - if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - // _gl.finish(); + if ( object.isSkinnedMesh ) { - bindingStates.resetDefaultState(); - _currentMaterialId = - 1; - _currentCamera = null; + // update skeleton only once in a frame - renderStateStack.pop(); + if ( object.skeleton.frame !== info.render.frame ) { - if ( renderStateStack.length > 0 ) { + object.skeleton.update(); + object.skeleton.frame = info.render.frame; - currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; + } - } else { + } - currentRenderState = null; + const geometry = objects.update( object ); + const material = object.material; - } + if ( sortObjects ) { - renderListStack.pop(); + if ( object.boundingSphere !== undefined ) { - if ( renderListStack.length > 0 ) { + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + _vector3.copy( object.boundingSphere.center ); - currentRenderList = renderListStack[ renderListStack.length - 1 ]; + } else { - } else { + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _vector3.copy( geometry.boundingSphere.center ); - currentRenderList = null; + } - } + _vector3 + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - }; + } - function projectObject( object, camera, groupOrder, sortObjects ) { + if ( Array.isArray( material ) ) { - if ( object.visible === false ) return; + const groups = geometry.groups; - const visible = object.layers.test( camera.layers ); + for ( let i = 0, l = groups.length; i < l; i ++ ) { - if ( visible ) { + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - if ( object.isGroup ) { + if ( groupMaterial && groupMaterial.visible ) { - groupOrder = object.renderOrder; + currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); - } else if ( object.isLOD ) { + } - if ( object.autoUpdate === true ) object.update( camera ); + } - } else if ( object.isLight ) { + } else if ( material.visible ) { - currentRenderState.pushLight( object ); + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); - if ( object.castShadow ) { + } - currentRenderState.pushShadow( object ); + } } - } else if ( object.isSprite ) { + } - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + const children = object.children; - if ( sortObjects ) { + for ( let i = 0, l = children.length; i < l; i ++ ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + projectObject( children[ i ], camera, groupOrder, sortObjects ); - } + } - const geometry = objects.update( object ); - const material = object.material; + } - if ( material.visible ) { + function renderScene( currentRenderList, scene, camera, viewport ) { - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; + const transparentObjects = currentRenderList.transparent; - } + currentRenderState.setupLightsView( camera ); - } + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - } else if ( object.isMesh || object.isLine || object.isPoints ) { + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - if ( object.isSkinnedMesh ) { + if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); - // update skeleton only once in a frame + if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); + if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); + if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); - if ( object.skeleton.frame !== info.render.frame ) { + // Ensure depth buffer writing is enabled so it can be cleared on next render - object.skeleton.update(); - object.skeleton.frame = info.render.frame; + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); - } + state.setPolygonOffset( false ); - } + } - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { - if ( sortObjects ) { + const isWebGL2 = capabilities.isWebGL2; - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + if ( _transmissionRenderTarget === null ) { - } + _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { + generateMipmaps: true, + type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: ( isWebGL2 && antialias === true ) ? 4 : 0 + } ); - const geometry = objects.update( object ); - const material = object.material; + // debug - if ( Array.isArray( material ) ) { + /* + const geometry = new PlaneGeometry(); + const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); - const groups = geometry.groups; + const mesh = new Mesh( geometry, material ); + scene.add( mesh ); + */ - for ( let i = 0, l = groups.length; i < l; i ++ ) { + } - const group = groups[ i ]; - const groupMaterial = material[ group.materialIndex ]; + _this.getDrawingBufferSize( _vector2 ); - if ( groupMaterial && groupMaterial.visible ) { + if ( isWebGL2 ) { - currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); + _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); - } + } else { - } + _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); - } else if ( material.visible ) { + } - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + // - } + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget( _transmissionRenderTarget ); - } + _this.getClearColor( _currentClearColor ); + _currentClearAlpha = _this.getClearAlpha(); + if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); - } + _this.clear(); - } + // Turn off the features which can affect the frag color for opaque objects pass. + // Otherwise they are applied twice in opaque objects pass and transmission objects pass. + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; - const children = object.children; + renderObjects( opaqueObjects, scene, camera ); - for ( let i = 0, l = children.length; i < l; i ++ ) { + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - projectObject( children[ i ], camera, groupOrder, sortObjects ); + let renderTargetNeedsUpdate = false; - } + for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { - } + const renderItem = transmissiveObjects[ i ]; - function renderScene( currentRenderList, scene, camera, viewport ) { + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = renderItem.material; + const group = renderItem.group; - const opaqueObjects = currentRenderList.opaque; - const transmissiveObjects = currentRenderList.transmissive; - const transparentObjects = currentRenderList.transparent; + if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { - currentRenderState.setupLightsView( camera ); + const currentSide = material.side; - if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); + material.side = BackSide; + material.needsUpdate = true; - if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, scene, camera ); + renderObject( object, scene, camera, geometry, material, group ); - if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); + material.side = currentSide; + material.needsUpdate = true; - if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); - if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); - if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); + renderTargetNeedsUpdate = true; - // Ensure depth buffer writing is enabled so it can be cleared on next render + } - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); + } - state.setPolygonOffset( false ); + if ( renderTargetNeedsUpdate === true ) { - } + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - function renderTransmissionPass( opaqueObjects, scene, camera ) { + } - const isWebGL2 = capabilities.isWebGL2; + _this.setRenderTarget( currentRenderTarget ); - if ( _transmissionRenderTarget === null ) { + _this.setClearColor( _currentClearColor, _currentClearAlpha ); - _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { - generateMipmaps: true, - type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, - minFilter: LinearMipmapLinearFilter, - samples: ( isWebGL2 && _antialias === true ) ? 4 : 0 - } ); + _this.toneMapping = currentToneMapping; } - _this.getDrawingBufferSize( _vector2 ); - - if ( isWebGL2 ) { + function renderObjects( renderList, scene, camera ) { - _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - } else { + for ( let i = 0, l = renderList.length; i < l; i ++ ) { - _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); + const renderItem = renderList[ i ]; - } + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = overrideMaterial === null ? renderItem.material : overrideMaterial; + const group = renderItem.group; - // + if ( object.layers.test( camera.layers ) ) { - const currentRenderTarget = _this.getRenderTarget(); - _this.setRenderTarget( _transmissionRenderTarget ); - _this.clear(); + renderObject( object, scene, camera, geometry, material, group ); - // Turn off the features which can affect the frag color for opaque objects pass. - // Otherwise they are applied twice in opaque objects pass and transmission objects pass. - const currentToneMapping = _this.toneMapping; - _this.toneMapping = NoToneMapping; + } - renderObjects( opaqueObjects, scene, camera ); + } - _this.toneMapping = currentToneMapping; + } - textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); - textures.updateRenderTargetMipmap( _transmissionRenderTarget ); + function renderObject( object, scene, camera, geometry, material, group ) { - _this.setRenderTarget( currentRenderTarget ); + object.onBeforeRender( _this, scene, camera, geometry, material, group ); - } + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - function renderObjects( renderList, scene, camera ) { + material.onBeforeRender( _this, scene, camera, geometry, object, group ); - const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - for ( let i = 0, l = renderList.length; i < l; i ++ ) { + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - const renderItem = renderList[ i ]; + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - const object = renderItem.object; - const geometry = renderItem.geometry; - const material = overrideMaterial === null ? renderItem.material : overrideMaterial; - const group = renderItem.group; + material.side = DoubleSide; - if ( object.layers.test( camera.layers ) ) { + } else { - renderObject( object, scene, camera, geometry, material, group ); + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); } + object.onAfterRender( _this, scene, camera, geometry, material, group ); + } - } + function getProgram( material, scene, object ) { - function renderObject( object, scene, camera, geometry, material, group ) { + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + const materialProperties = properties.get( material ); - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; - material.onBeforeRender( _this, scene, camera, geometry, object, group ); + const lightsStateVersion = lights.state.version; - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); + const programCacheKey = programCache.getProgramCacheKey( parameters ); - material.side = BackSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + let programs = materialProperties.programs; - material.side = FrontSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - material.side = DoubleSide; + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); - } else { + if ( programs === undefined ) { - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + // new material - } + material.addEventListener( 'dispose', onMaterialDispose ); - object.onAfterRender( _this, scene, camera, geometry, material, group ); + programs = new Map(); + materialProperties.programs = programs; - } + } - function getProgram( material, scene, object ) { + let program = programs.get( programCacheKey ); - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + if ( program !== undefined ) { - const materialProperties = properties.get( material ); + // early out if program and light state is identical + + if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { + + updateCommonMaterialProperties( material, parameters ); - const lights = currentRenderState.state.lights; - const shadowsArray = currentRenderState.state.shadowsArray; + return program; - const lightsStateVersion = lights.state.version; + } - const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); - const programCacheKey = programCache.getProgramCacheKey( parameters ); + } else { - let programs = materialProperties.programs; + parameters.uniforms = programCache.getUniforms( material ); - // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change + material.onBuild( object, parameters, _this ); - materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; - materialProperties.fog = scene.fog; - materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + material.onBeforeCompile( parameters, _this ); - if ( programs === undefined ) { + program = programCache.acquireProgram( parameters, programCacheKey ); + programs.set( programCacheKey, program ); - // new material + materialProperties.uniforms = parameters.uniforms; - material.addEventListener( 'dispose', onMaterialDispose ); + } - programs = new Map(); - materialProperties.programs = programs; + const uniforms = materialProperties.uniforms; - } + if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { - let program = programs.get( programCacheKey ); + uniforms.clippingPlanes = clipping.uniform; - if ( program !== undefined ) { + } - // early out if program and light state is identical + updateCommonMaterialProperties( material, parameters ); - if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { + // store the light setup it was created for - updateCommonMaterialProperties( material, parameters ); + materialProperties.needsLights = materialNeedsLights( material ); + materialProperties.lightsStateVersion = lightsStateVersion; - return program; + if ( materialProperties.needsLights ) { - } + // wire up the material to this renderer's lighting state - } else { + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.lightProbe.value = lights.state.probe; + uniforms.directionalLights.value = lights.state.directional; + uniforms.directionalLightShadows.value = lights.state.directionalShadow; + uniforms.spotLights.value = lights.state.spot; + uniforms.spotLightShadows.value = lights.state.spotShadow; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.ltc_1.value = lights.state.rectAreaLTC1; + uniforms.ltc_2.value = lights.state.rectAreaLTC2; + uniforms.pointLights.value = lights.state.point; + uniforms.pointLightShadows.value = lights.state.pointShadow; + uniforms.hemisphereLights.value = lights.state.hemi; - parameters.uniforms = programCache.getUniforms( material ); + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; + uniforms.spotLightMap.value = lights.state.spotLightMap; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + // TODO (abelnation): add area lights shadow info to uniforms - material.onBuild( object, parameters, _this ); + } - material.onBeforeCompile( parameters, _this ); + const progUniforms = program.getUniforms(); + const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); - program = programCache.acquireProgram( parameters, programCacheKey ); - programs.set( programCacheKey, program ); + materialProperties.currentProgram = program; + materialProperties.uniformsList = uniformsList; - materialProperties.uniforms = parameters.uniforms; + return program; } - const uniforms = materialProperties.uniforms; + function updateCommonMaterialProperties( material, parameters ) { - if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { + const materialProperties = properties.get( material ); - uniforms.clippingPlanes = clipping.uniform; + materialProperties.outputColorSpace = parameters.outputColorSpace; + materialProperties.instancing = parameters.instancing; + materialProperties.skinning = parameters.skinning; + materialProperties.morphTargets = parameters.morphTargets; + materialProperties.morphNormals = parameters.morphNormals; + materialProperties.morphColors = parameters.morphColors; + materialProperties.morphTargetsCount = parameters.morphTargetsCount; + materialProperties.numClippingPlanes = parameters.numClippingPlanes; + materialProperties.numIntersection = parameters.numClipIntersection; + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } - updateCommonMaterialProperties( material, parameters ); + function setProgram( camera, scene, geometry, material, object ) { - // store the light setup it was created for + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - materialProperties.needsLights = materialNeedsLights( material ); - materialProperties.lightsStateVersion = lightsStateVersion; + textures.resetTextureUnits(); - if ( materialProperties.needsLights ) { + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); + const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); + const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; + const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); + const morphTargets = !! geometry.morphAttributes.position; + const morphNormals = !! geometry.morphAttributes.normal; + const morphColors = !! geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; - // wire up the material to this renderer's lighting state + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.lightProbe.value = lights.state.probe; - uniforms.directionalLights.value = lights.state.directional; - uniforms.directionalLightShadows.value = lights.state.directionalShadow; - uniforms.spotLights.value = lights.state.spot; - uniforms.spotLightShadows.value = lights.state.spotShadow; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.ltc_1.value = lights.state.rectAreaLTC1; - uniforms.ltc_2.value = lights.state.rectAreaLTC2; - uniforms.pointLights.value = lights.state.point; - uniforms.pointLightShadows.value = lights.state.pointShadow; - uniforms.hemisphereLights.value = lights.state.hemi; + const materialProperties = properties.get( material ); + const lights = currentRenderState.state.lights; - uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; - uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; - uniforms.spotShadowMap.value = lights.state.spotShadowMap; - uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; - uniforms.spotLightMap.value = lights.state.spotLightMap; - uniforms.pointShadowMap.value = lights.state.pointShadowMap; - uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; - // TODO (abelnation): add area lights shadow info to uniforms + if ( _clippingEnabled === true ) { - } + if ( _localClippingEnabled === true || camera !== _currentCamera ) { - const progUniforms = program.getUniforms(); - const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); + const useCache = + camera === _currentCamera && + material.id === _currentMaterialId; - materialProperties.currentProgram = program; - materialProperties.uniformsList = uniformsList; + // we might want to call this function with some ClippingGroup + // object instead of the material, once it becomes feasible + // (#8465, #8379) + clipping.setState( material, camera, useCache ); - return program; + } - } + } - function updateCommonMaterialProperties( material, parameters ) { + // - const materialProperties = properties.get( material ); + let needsProgramChange = false; - materialProperties.outputEncoding = parameters.outputEncoding; - materialProperties.instancing = parameters.instancing; - materialProperties.skinning = parameters.skinning; - materialProperties.morphTargets = parameters.morphTargets; - materialProperties.morphNormals = parameters.morphNormals; - materialProperties.morphColors = parameters.morphColors; - materialProperties.morphTargetsCount = parameters.morphTargetsCount; - materialProperties.numClippingPlanes = parameters.numClippingPlanes; - materialProperties.numIntersection = parameters.numClipIntersection; - materialProperties.vertexAlphas = parameters.vertexAlphas; - materialProperties.vertexTangents = parameters.vertexTangents; - materialProperties.toneMapping = parameters.toneMapping; + if ( material.version === materialProperties.__version ) { - } + if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { - function setProgram( camera, scene, geometry, material, object ) { + needsProgramChange = true; - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + } else if ( materialProperties.outputColorSpace !== colorSpace ) { - textures.resetTextureUnits(); + needsProgramChange = true; - const fog = scene.fog; - const environment = material.isMeshStandardMaterial ? scene.environment : null; - const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding ); - const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); - const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; - const vertexTangents = !! material.normalMap && !! geometry.attributes.tangent; - const morphTargets = !! geometry.morphAttributes.position; - const morphNormals = !! geometry.morphAttributes.normal; - const morphColors = !! geometry.morphAttributes.color; - const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; + } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + needsProgramChange = true; - const materialProperties = properties.get( material ); - const lights = currentRenderState.state.lights; + } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { - if ( _clippingEnabled === true ) { + needsProgramChange = true; - if ( _localClippingEnabled === true || camera !== _currentCamera ) { + } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { - const useCache = - camera === _currentCamera && - material.id === _currentMaterialId; + needsProgramChange = true; - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - clipping.setState( material, camera, useCache ); + } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { - } + needsProgramChange = true; - } + } else if ( materialProperties.envMap !== envMap ) { - // + needsProgramChange = true; - let needsProgramChange = false; + } else if ( material.fog === true && materialProperties.fog !== fog ) { - if ( material.version === materialProperties.__version ) { + needsProgramChange = true; - if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { + } else if ( materialProperties.numClippingPlanes !== undefined && + ( materialProperties.numClippingPlanes !== clipping.numPlanes || + materialProperties.numIntersection !== clipping.numIntersection ) ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( materialProperties.outputEncoding !== encoding ) { + } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { + } else if ( materialProperties.vertexTangents !== vertexTangents ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { + } else if ( materialProperties.morphTargets !== morphTargets ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { + } else if ( materialProperties.morphNormals !== morphNormals ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { + } else if ( materialProperties.morphColors !== morphColors ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( materialProperties.envMap !== envMap ) { + } else if ( materialProperties.toneMapping !== toneMapping ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( material.fog === true && materialProperties.fog !== fog ) { + } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== clipping.numPlanes || - materialProperties.numIntersection !== clipping.numIntersection ) ) { + } + + } else { needsProgramChange = true; + materialProperties.__version = material.version; - } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { + } - needsProgramChange = true; + // - } else if ( materialProperties.vertexTangents !== vertexTangents ) { + let program = materialProperties.currentProgram; - needsProgramChange = true; + if ( needsProgramChange === true ) { - } else if ( materialProperties.morphTargets !== morphTargets ) { + program = getProgram( material, scene, object ); - needsProgramChange = true; + } - } else if ( materialProperties.morphNormals !== morphNormals ) { + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; - needsProgramChange = true; + const p_uniforms = program.getUniforms(), + m_uniforms = materialProperties.uniforms; - } else if ( materialProperties.morphColors !== morphColors ) { + if ( state.useProgram( program.program ) ) { - needsProgramChange = true; + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; - } else if ( materialProperties.toneMapping !== toneMapping ) { + } - needsProgramChange = true; + if ( material.id !== _currentMaterialId ) { - } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { + _currentMaterialId = material.id; - needsProgramChange = true; + refreshMaterial = true; } - } else { + if ( refreshProgram || _currentCamera !== camera ) { - needsProgramChange = true; - materialProperties.__version = material.version; + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); - } + if ( capabilities.logarithmicDepthBuffer ) { - // + p_uniforms.setValue( _gl, 'logDepthBufFC', + 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + + } - let program = materialProperties.currentProgram; + if ( _currentCamera !== camera ) { - if ( needsProgramChange === true ) { + _currentCamera = camera; - program = getProgram( material, scene, object ); + // lighting uniforms depend on the camera so enforce an update + // now, in case this material supports lights - or later, when + // the next material that does gets activated: - } + refreshMaterial = true; // set to true on material change + refreshLights = true; // remains set until update done - let refreshProgram = false; - let refreshMaterial = false; - let refreshLights = false; + } - const p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.uniforms; + // load material specific uniforms + // (shader material also gets them for the sake of genericity) - if ( state.useProgram( program.program ) ) { + if ( material.isShaderMaterial || + material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshStandardMaterial || + material.envMap ) { - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; + const uCamPos = p_uniforms.map.cameraPosition; - } + if ( uCamPos !== undefined ) { - if ( material.id !== _currentMaterialId ) { + uCamPos.setValue( _gl, + _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + + } - _currentMaterialId = material.id; + } - refreshMaterial = true; + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial ) { - } + p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); - if ( refreshProgram || _currentCamera !== camera ) { + } - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial || + material.isShadowMaterial || + object.isSkinnedMesh ) { - if ( capabilities.logarithmicDepthBuffer ) { + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + } } - if ( _currentCamera !== camera ) { + // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures + // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures - _currentCamera = camera; + if ( object.isSkinnedMesh ) { - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: + p_uniforms.setOptional( _gl, object, 'bindMatrix' ); + p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done + const skeleton = object.skeleton; - } + if ( skeleton ) { + + if ( capabilities.floatVertexTextures ) { - // load material specific uniforms - // (shader material also gets them for the sake of genericity) + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshStandardMaterial || - material.envMap ) { + p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); + p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); - const uCamPos = p_uniforms.map.cameraPosition; + } else { - if ( uCamPos !== undefined ) { + console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + } } } - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial ) { + const morphAttributes = geometry.morphAttributes; - p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); + if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { + + morphtargets.update( object, geometry, program ); } - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.isShadowMaterial || - object.isSkinnedMesh ) { + if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); } - } + // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 - // skinning and morph target uniforms must be set even if material didn't change - // auto-setting of texture unit for bone and morph texture must go before other textures - // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures + if ( material.isMeshGouraudMaterial && material.envMap !== null ) { - if ( object.isSkinnedMesh ) { + m_uniforms.envMap.value = envMap; - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); + m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - const skeleton = object.skeleton; + } - if ( skeleton ) { + if ( refreshMaterial ) { - if ( capabilities.floatVertexTextures ) { + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); + if ( materialProperties.needsLights ) { - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); + // the current material requires lighting info - } else { + // note: all lighting uniforms are always set correctly + // they simply reference the renderer's state for their + // values + // + // use the current material's .needsUpdate flags to set + // the GL state when required - console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); + markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); } - } - - } - - const morphAttributes = geometry.morphAttributes; + // refresh uniforms common to several materials - if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { + if ( fog && material.fog === true ) { - morphtargets.update( object, geometry, material, program ); + materials.refreshFogUniforms( m_uniforms, fog ); - } + } - if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { + materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); - materialProperties.receiveShadow = object.receiveShadow; - p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - } + } - // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 + if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { - if ( material.isMeshGouraudMaterial && material.envMap !== null ) { + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + material.uniformsNeedUpdate = false; - m_uniforms.envMap.value = envMap; + } - m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; + if ( material.isSpriteMaterial ) { - } + p_uniforms.setValue( _gl, 'center', object.center ); - if ( refreshMaterial ) { + } - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); + // common matrices - if ( materialProperties.needsLights ) { + p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); + p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - // the current material requires lighting info + // UBOs - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); + const groups = material.uniformsGroups; - } + for ( let i = 0, l = groups.length; i < l; i ++ ) { - // refresh uniforms common to several materials + if ( capabilities.isWebGL2 ) { - if ( fog && material.fog === true ) { + const group = groups[ i ]; - materials.refreshFogUniforms( m_uniforms, fog ); + uniformsGroups.update( group, program ); + uniformsGroups.bind( group, program ); - } + } else { - materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); + console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + } - } + } - if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { + } - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - material.uniformsNeedUpdate = false; + return program; } - if ( material.isSpriteMaterial ) { - - p_uniforms.setValue( _gl, 'center', object.center ); + // If uniforms are marked as clean, they don't need to be loaded to the GPU. - } + function markUniformsLightsNeedsUpdate( uniforms, value ) { - // common matrices + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + uniforms.directionalLights.needsUpdate = value; + uniforms.directionalLightShadows.needsUpdate = value; + uniforms.pointLights.needsUpdate = value; + uniforms.pointLightShadows.needsUpdate = value; + uniforms.spotLights.needsUpdate = value; + uniforms.spotLightShadows.needsUpdate = value; + uniforms.rectAreaLights.needsUpdate = value; + uniforms.hemisphereLights.needsUpdate = value; - // UBOs + } - if ( material.isShaderMaterial || material.isRawShaderMaterial ) { + function materialNeedsLights( material ) { - const groups = material.uniformsGroups; + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + material.isMeshStandardMaterial || material.isShadowMaterial || + ( material.isShaderMaterial && material.lights === true ); - for ( let i = 0, l = groups.length; i < l; i ++ ) { + } - if ( capabilities.isWebGL2 ) { + this.getActiveCubeFace = function () { - const group = groups[ i ]; + return _currentActiveCubeFace; - uniformsGroups.update( group, program ); - uniformsGroups.bind( group, program ); + }; - } else { + this.getActiveMipmapLevel = function () { - console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); + return _currentActiveMipmapLevel; - } + }; - } + this.getRenderTarget = function () { - } + return _currentRenderTarget; - return program; + }; - } + this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { - // If uniforms are marked as clean, they don't need to be loaded to the GPU. + properties.get( renderTarget.texture ).__webglTexture = colorTexture; + properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; - function markUniformsLightsNeedsUpdate( uniforms, value ) { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; - uniforms.ambientLightColor.needsUpdate = value; - uniforms.lightProbe.needsUpdate = value; + if ( renderTargetProperties.__hasExternalTextures ) { - uniforms.directionalLights.needsUpdate = value; - uniforms.directionalLightShadows.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.pointLightShadows.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.spotLightShadows.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; - } + if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { - function materialNeedsLights( material ) { + // The multisample_render_to_texture extension doesn't work properly if there + // are midframe flushes and an external depth buffer. Disable use of the extension. + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { - return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || - material.isMeshStandardMaterial || material.isShadowMaterial || - ( material.isShaderMaterial && material.lights === true ); + console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); + renderTargetProperties.__useRenderToTexture = false; - } + } - this.getActiveCubeFace = function () { + } - return _currentActiveCubeFace; + } - }; + }; - this.getActiveMipmapLevel = function () { + this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { - return _currentActiveMipmapLevel; + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; - }; + }; - this.getRenderTarget = function () { + this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { - return _currentRenderTarget; + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; - }; + let useDefaultFramebuffer = true; + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; - this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { + if ( renderTarget ) { - properties.get( renderTarget.texture ).__webglTexture = colorTexture; - properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; + const renderTargetProperties = properties.get( renderTarget ); - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__hasExternalTextures = true; + if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { - if ( renderTargetProperties.__hasExternalTextures ) { + // We need to make sure to rebind the framebuffer. + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); + useDefaultFramebuffer = false; - renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; + } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { - if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { + textures.setupRenderTarget( renderTarget ); - // The multisample_render_to_texture extension doesn't work properly if there - // are midframe flushes and an external depth buffer. Disable use of the extension. - if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { + } else if ( renderTargetProperties.__hasExternalTextures ) { - console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); - renderTargetProperties.__useRenderToTexture = false; + // Color and depth texture must be rebound in order for the swapchain to update. + textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); } - } - - } - - }; + const texture = renderTarget.texture; - this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { + if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__webglFramebuffer = defaultFramebuffer; - renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; + isRenderTarget3D = true; - }; + } - this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { + const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - _currentRenderTarget = renderTarget; - _currentActiveCubeFace = activeCubeFace; - _currentActiveMipmapLevel = activeMipmapLevel; + if ( renderTarget.isWebGLCubeRenderTarget ) { - let useDefaultFramebuffer = true; - let framebuffer = null; - let isCube = false; - let isRenderTarget3D = false; + framebuffer = __webglFramebuffer[ activeCubeFace ]; + isCube = true; - if ( renderTarget ) { + } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { - const renderTargetProperties = properties.get( renderTarget ); + framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; - if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { + } else { - // We need to make sure to rebind the framebuffer. - state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - useDefaultFramebuffer = false; + framebuffer = __webglFramebuffer; - } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { + } - textures.setupRenderTarget( renderTarget ); + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; - } else if ( renderTargetProperties.__hasExternalTextures ) { + } else { - // Color and depth texture must be rebound in order for the swapchain to update. - textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); + _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); + _currentScissorTest = _scissorTest; } - const texture = renderTarget.texture; + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { - isRenderTarget3D = true; + state.drawBuffers( renderTarget, framebuffer ); } - const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); - if ( renderTarget.isWebGLCubeRenderTarget ) { + if ( isCube ) { - framebuffer = __webglFramebuffer[ activeCubeFace ]; - isCube = true; + const textureProperties = properties.get( renderTarget.texture ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); - } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { + } else if ( isRenderTarget3D ) { - framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; + const textureProperties = properties.get( renderTarget.texture ); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); - } else { + } - framebuffer = __webglFramebuffer; + _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings - } + }; - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; + this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - } else { + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); - _currentScissorTest = _scissorTest; + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; - } + } - const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - state.drawBuffers( renderTarget, framebuffer ); + framebuffer = framebuffer[ activeCubeFaceIndex ]; - } + } - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); + if ( framebuffer ) { - if ( isCube ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - const textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); + try { - } else if ( isRenderTarget3D ) { + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - const textureProperties = properties.get( renderTarget.texture ); - const layer = activeCubeFace || 0; - _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { - } + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + return; - _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings + } - }; + const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) + ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox + ! halfFloatSupportedByExt ) { - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + return; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; + } - } + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - let framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - framebuffer = framebuffer[ activeCubeFaceIndex ]; + } - } + } finally { - if ( framebuffer ) { + // restore framebuffer of current render target if necessary - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - try { + } - const texture = renderTarget.texture; - const textureFormat = texture.format; - const textureType = texture.type; + } - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + }; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; + this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { - } + const levelScale = Math.pow( 2, - level ); + const width = Math.floor( texture.image.width * levelScale ); + const height = Math.floor( texture.image.height * levelScale ); - const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); + textures.setTexture2D( texture, 0 ); - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! halfFloatSupportedByExt ) { + _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; + state.unbindTexture(); - } + }; - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + const width = srcTexture.image.width; + const height = srcTexture.image.height; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); + textures.setTexture2D( dstTexture, 0 ); - } + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - } finally { + if ( srcTexture.isDataTexture ) { - // restore framebuffer of current render target if necessary + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); - const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + } else { - } + if ( srcTexture.isCompressedTexture ) { - } + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); - }; + } else { - this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); - const levelScale = Math.pow( 2, - level ); - const width = Math.floor( texture.image.width * levelScale ); - const height = Math.floor( texture.image.height * levelScale ); + } - textures.setTexture2D( texture, 0 ); + } - _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); - state.unbindTexture(); + state.unbindTexture(); - }; + }; - this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { + this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { - const width = srcTexture.image.width; - const height = srcTexture.image.height; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); + if ( _this.isWebGL1Renderer ) { - textures.setTexture2D( dstTexture, 0 ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); + return; - // As another texture upload may have changed pixelStorei - // parameters, make sure they are correct for the dstTexture - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + } - if ( srcTexture.isDataTexture ) { + const width = sourceBox.max.x - sourceBox.min.x + 1; + const height = sourceBox.max.y - sourceBox.min.y + 1; + const depth = sourceBox.max.z - sourceBox.min.z + 1; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; - _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); + if ( dstTexture.isData3DTexture ) { - } else { + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; - if ( srcTexture.isCompressedTexture ) { + } else if ( dstTexture.isDataArrayTexture ) { - _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; } else { - _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; } - } - - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - state.unbindTexture(); + const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - }; + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; - this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); - if ( _this.isWebGL1Renderer ) { + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); - return; + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); - } + } else { - const width = sourceBox.max.x - sourceBox.min.x + 1; - const height = sourceBox.max.y - sourceBox.min.y + 1; - const depth = sourceBox.max.z - sourceBox.min.z + 1; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); - let glTarget; + if ( srcTexture.isCompressedArrayTexture ) { - if ( dstTexture.isData3DTexture ) { + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); + _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); - textures.setTexture3D( dstTexture, 0 ); - glTarget = _gl.TEXTURE_3D; + } else { - } else if ( dstTexture.isDataArrayTexture ) { + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); - textures.setTexture2DArray( dstTexture, 0 ); - glTarget = _gl.TEXTURE_2D_ARRAY; + } - } else { + } - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); - return; + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); - } + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + state.unbindTexture(); - const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); - const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); - const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); - const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); - const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); + }; - const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; + this.initTexture = function ( texture ) { - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); + if ( texture.isCubeTexture ) { - if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { + textures.setTextureCube( texture, 0 ); - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); + } else if ( texture.isData3DTexture ) { - } else { + textures.setTexture3D( texture, 0 ); - if ( srcTexture.isCompressedArrayTexture ) { + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); - _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); + textures.setTexture2DArray( texture, 0 ); } else { - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); + textures.setTexture2D( texture, 0 ); } - } - - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); - - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); + state.unbindTexture(); - state.unbindTexture(); + }; - }; + this.resetState = function () { - this.initTexture = function ( texture ) { + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; - if ( texture.isCubeTexture ) { + state.reset(); + bindingStates.reset(); - textures.setTextureCube( texture, 0 ); + }; - } else if ( texture.isData3DTexture ) { + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - textures.setTexture3D( texture, 0 ); + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); - } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + } - textures.setTexture2DArray( texture, 0 ); + } - } else { + get physicallyCorrectLights() { // @deprecated, r150 - textures.setTexture2D( texture, 0 ); + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + return ! this.useLegacyLights; - } + } - state.unbindTexture(); + set physicallyCorrectLights( value ) { // @deprecated, r150 - }; + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + this.useLegacyLights = ! value; - this.resetState = function () { + } - _currentActiveCubeFace = 0; - _currentActiveMipmapLevel = 0; - _currentRenderTarget = null; + get outputEncoding() { // @deprecated, r152 - state.reset(); - bindingStates.reset(); + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + return this.outputColorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; - }; + } - if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + set outputEncoding( encoding ) { // @deprecated, r152 - __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + this.outputColorSpace = encoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; } @@ -29685,16 +30357,14 @@ class Scene extends Object3D { } - // @deprecated - - get autoUpdate() { + get autoUpdate() { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); return this.matrixWorldAutoUpdate; } - set autoUpdate( value ) { + set autoUpdate( value ) { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); this.matrixWorldAutoUpdate = value; @@ -29844,7 +30514,7 @@ class InterleavedBuffer { } -const _vector$6 = /*@__PURE__*/ new Vector3(); +const _vector$5 = /*@__PURE__*/ new Vector3(); class InterleavedBufferAttribute { @@ -29884,11 +30554,11 @@ class InterleavedBufferAttribute { for ( let i = 0, l = this.data.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.applyMatrix4( m ); + _vector$5.applyMatrix4( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -29900,11 +30570,11 @@ class InterleavedBufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.applyNormalMatrix( m ); + _vector$5.applyNormalMatrix( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -29916,11 +30586,11 @@ class InterleavedBufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.transformDirection( m ); + _vector$5.transformDirection( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -30340,7 +31010,7 @@ class Sprite extends Object3D { distance: distance, point: _intersectPoint.clone(), - uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), + uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), face: null, object: this @@ -30603,8 +31273,13 @@ const _basePosition = /*@__PURE__*/ new Vector3(); const _skinIndex = /*@__PURE__*/ new Vector4(); const _skinWeight = /*@__PURE__*/ new Vector4(); -const _vector$5 = /*@__PURE__*/ new Vector3(); -const _matrix = /*@__PURE__*/ new Matrix4(); +const _vector3 = /*@__PURE__*/ new Vector3(); +const _matrix4 = /*@__PURE__*/ new Matrix4(); +const _vertex = /*@__PURE__*/ new Vector3(); + +const _sphere$3 = /*@__PURE__*/ new Sphere(); +const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _ray$2 = /*@__PURE__*/ new Ray(); class SkinnedMesh extends Mesh { @@ -30620,6 +31295,57 @@ class SkinnedMesh extends Mesh { this.bindMatrix = new Matrix4(); this.bindMatrixInverse = new Matrix4(); + this.boundingBox = null; + this.boundingSphere = null; + + } + + computeBoundingBox() { + + const geometry = this.geometry; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + this.boundingBox.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + this.boundingSphere.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); + + } + } copy( source, recursive ) { @@ -30632,10 +31358,58 @@ class SkinnedMesh extends Mesh { this.skeleton = source.skeleton; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } + raycast( raycaster, intersects ) { + + const material = this.material; + const matrixWorld = this.matrixWorld; + + if ( material === undefined ) return; + + // test with bounding sphere in world space + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$3.copy( this.boundingSphere ); + _sphere$3.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; + + // convert ray to local space of skinned mesh + + _inverseMatrix$2.copy( matrixWorld ).invert(); + _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); + + // test with bounding box in local space + + if ( this.boundingBox !== null ) { + + if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; + + } + + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$2 ); + + } + + getVertexPosition( index, target ) { + + super.getVertexPosition( index, target ); + + this.applyBoneTransform( index, target ); + + return target; + + } + bind( skeleton, bindMatrix ) { this.skeleton = skeleton; @@ -30709,7 +31483,7 @@ class SkinnedMesh extends Mesh { } - boneTransform( index, target ) { + applyBoneTransform( index, vector ) { const skeleton = this.skeleton; const geometry = this.geometry; @@ -30717,9 +31491,9 @@ class SkinnedMesh extends Mesh { _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - _basePosition.copy( target ).applyMatrix4( this.bindMatrix ); + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); - target.set( 0, 0, 0 ); + vector.set( 0, 0, 0 ); for ( let i = 0; i < 4; i ++ ) { @@ -30729,18 +31503,26 @@ class SkinnedMesh extends Mesh { const boneIndex = _skinIndex.getComponent( i ); - _matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - target.addScaledVector( _vector$5.copy( _basePosition ).applyMatrix4( _matrix ), weight ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); } } - return target.applyMatrix4( this.bindMatrixInverse ); + return vector.applyMatrix4( this.bindMatrixInverse ); } + boneTransform( index, vector ) { // @deprecated, r151 + + console.warn( 'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' ); + return this.applyBoneTransform( index, vector ); + + } + + } class Bone extends Object3D { @@ -30759,9 +31541,9 @@ class Bone extends Object3D { class DataTexture extends Texture { - constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding ) { + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isDataTexture = true; @@ -31017,7 +31799,7 @@ class Skeleton { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Skeleton', generator: 'Skeleton.toJSON' }, @@ -31087,8 +31869,10 @@ const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); const _instanceIntersects = []; +const _box3 = /*@__PURE__*/ new Box3(); const _identity = /*@__PURE__*/ new Matrix4(); const _mesh = /*@__PURE__*/ new Mesh(); +const _sphere$2 = /*@__PURE__*/ new Sphere(); class InstancedMesh extends Mesh { @@ -31103,7 +31887,8 @@ class InstancedMesh extends Mesh { this.count = count; - this.frustumCulled = false; + this.boundingBox = null; + this.boundingSphere = null; for ( let i = 0; i < count; i ++ ) { @@ -31113,6 +31898,68 @@ class InstancedMesh extends Mesh { } + computeBoundingBox() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + this.boundingBox.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingBox.union( _box3 ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + if ( geometry.boundingSphere === null ) { + + geometry.computeBoundingSphere(); + + } + + this.boundingSphere.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingSphere.union( _sphere$2 ); + + } + + } + copy( source, recursive ) { super.copy( source, recursive ); @@ -31123,6 +31970,9 @@ class InstancedMesh extends Mesh { this.count = source.count; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } @@ -31149,6 +31999,17 @@ class InstancedMesh extends Mesh { if ( _mesh.material === undefined ) return; + // test with bounding sphere first + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$2.copy( this.boundingSphere ); + _sphere$2.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return; + + // now test each instance + for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { // calculate the world matrix for each instance @@ -31222,6 +32083,8 @@ class LineBasicMaterial extends Material { this.color = new Color( 0xffffff ); + this.map = null; + this.linewidth = 1; this.linecap = 'round'; this.linejoin = 'round'; @@ -31239,6 +32102,8 @@ class LineBasicMaterial extends Material { this.color.copy( source.color ); + this.map = source.map; + this.linewidth = source.linewidth; this.linecap = source.linecap; this.linejoin = source.linejoin; @@ -31783,14 +32648,12 @@ class VideoTexture extends Texture { class FramebufferTexture extends Texture { - constructor( width, height, format ) { + constructor( width, height ) { super( { width, height } ); this.isFramebufferTexture = true; - this.format = format; - this.magFilter = NearestFilter; this.minFilter = NearestFilter; @@ -31804,9 +32667,9 @@ class FramebufferTexture extends Texture { class CompressedTexture extends Texture { - constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCompressedTexture = true; @@ -32241,7 +33104,7 @@ class Curve { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Curve', generator: 'Curve.toJSON' } @@ -32947,13 +33810,15 @@ class LineCurve extends Curve { } - getTangent( t, optionalTarget ) { + getTangent( t, optionalTarget = new Vector2() ) { - const tangent = optionalTarget || new Vector2(); + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); - tangent.copy( this.v2 ).sub( this.v1 ).normalize(); + } - return tangent; + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); } @@ -33030,6 +33895,19 @@ class LineCurve3 extends Curve { return this.getPoint( u, optionalTarget ); } + + getTangent( t, optionalTarget = new Vector3() ) { + + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); + + } + + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); + + } + copy( source ) { super.copy( source ); @@ -33904,6 +34782,16 @@ class LatheGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); @@ -34017,6 +34905,16 @@ class CircleGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); @@ -34286,6 +35184,16 @@ class CylinderGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); @@ -34617,6 +35525,16 @@ class PolyhedronGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); @@ -34820,6 +35738,16 @@ class EdgesGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } class Shape extends Path { @@ -35818,6 +36746,7 @@ function addContour( vertices, contour ) { * } */ + class ExtrudeGeometry extends BufferGeometry { constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) { @@ -35960,7 +36889,7 @@ class ExtrudeGeometry extends BufferGeometry { if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); - return vec.clone().multiplyScalar( size ).add( pt ); + return pt.clone().addScaledVector( vec, size ); } @@ -36467,6 +37396,16 @@ class ExtrudeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -36765,6 +37704,16 @@ class RingGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); @@ -36899,6 +37848,16 @@ class ShapeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -36999,11 +37958,11 @@ class SphereGeometry extends BufferGeometry { let uOffset = 0; - if ( iy == 0 && thetaStart == 0 ) { + if ( iy === 0 && thetaStart === 0 ) { uOffset = 0.5 / widthSegments; - } else if ( iy == heightSegments && thetaEnd == Math.PI ) { + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { uOffset = - 0.5 / widthSegments; @@ -37065,6 +38024,16 @@ class SphereGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); @@ -37201,6 +38170,16 @@ class TorusGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); @@ -37353,6 +38332,16 @@ class TorusKnotGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); @@ -37520,6 +38509,16 @@ class TubeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -37656,6 +38655,16 @@ class WireframeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } function isUniqueEdge( start, end, edges ) { @@ -37884,6 +38893,9 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { this.type = 'MeshPhysicalMaterial'; + this.anisotropyRotation = 0; + this.anisotropyMap = null; + this.clearcoatMap = null; this.clearcoatRoughness = 0.0; this.clearcoatRoughnessMap = null; @@ -37927,30 +38939,31 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { this.specularColor = new Color( 1, 1, 1 ); this.specularColorMap = null; - this._sheen = 0.0; + this._anisotropy = 0; this._clearcoat = 0; this._iridescence = 0; + this._sheen = 0.0; this._transmission = 0; this.setValues( parameters ); } - get sheen() { + get anisotropy() { - return this._sheen; + return this._anisotropy; } - set sheen( value ) { + set anisotropy( value ) { - if ( this._sheen > 0 !== value > 0 ) { + if ( this._anisotropy > 0 !== value > 0 ) { this.version ++; } - this._sheen = value; + this._anisotropy = value; } @@ -37990,6 +39003,24 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { } + get sheen() { + + return this._sheen; + + } + + set sheen( value ) { + + if ( this._sheen > 0 !== value > 0 ) { + + this.version ++; + + } + + this._sheen = value; + + } + get transmission() { return this._transmission; @@ -38019,6 +39050,10 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { }; + this.anisotropy = source.anisotropy; + this.anisotropyRotation = source.anisotropyRotation; + this.anisotropyMap = source.anisotropyMap; + this.clearcoat = source.clearcoat; this.clearcoatMap = source.clearcoatMap; this.clearcoatRoughness = source.clearcoatRoughness; @@ -38890,17 +39925,16 @@ function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targe } -var AnimationUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, +const AnimationUtils = { arraySlice: arraySlice, convertArray: convertArray, - flattenJSON: flattenJSON, - getKeyframeOrder: getKeyframeOrder, isTypedArray: isTypedArray, - makeClipAdditive: makeClipAdditive, + getKeyframeOrder: getKeyframeOrder, sortedArray: sortedArray, - subclip: subclip -}); + flattenJSON: flattenJSON, + subclip: subclip, + makeClipAdditive: makeClipAdditive +}; /** * Abstract base class of interpolants over parametric samples. @@ -41251,7 +42285,11 @@ class DataTextureLoader extends Loader { texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - if ( texData.encoding !== undefined ) { + if ( texData.colorSpace !== undefined ) { + + texture.colorSpace = texData.colorSpace; + + } else if ( texData.encoding !== undefined ) { // @deprecated, r152 texture.encoding = texData.encoding; @@ -42300,6 +43338,8 @@ class MaterialLoader extends Loader { if ( json.thickness !== undefined ) material.thickness = json.thickness; if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); + if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; + if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; if ( json.fog !== undefined ) material.fog = json.fog; if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; if ( json.blending !== undefined ) material.blending = json.blending; @@ -42428,6 +43468,9 @@ class MaterialLoader extends Loader { } + if ( json.lights !== undefined ) material.lights = json.lights; + if ( json.clipping !== undefined ) material.clipping = json.clipping; + // for PointsMaterial if ( json.size !== undefined ) material.size = json.size; @@ -42500,6 +43543,8 @@ class MaterialLoader extends Loader { if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); + if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); + if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); @@ -43101,7 +44146,7 @@ class ObjectLoader extends Loader { geometry.uuid = data.uuid; if ( data.name !== undefined ) geometry.name = data.name; - if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData; + if ( data.userData !== undefined ) geometry.userData = data.userData; geometries[ data.uuid ] = geometry; @@ -43443,6 +44488,7 @@ class ObjectLoader extends Loader { if ( data.name !== undefined ) texture.name = data.name; if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); + if ( data.channel !== undefined ) texture.channel = data.channel; if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); @@ -43457,8 +44503,10 @@ class ObjectLoader extends Loader { } if ( data.format !== undefined ) texture.format = data.format; + if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; if ( data.type !== undefined ) texture.type = data.type; - if ( data.encoding !== undefined ) texture.encoding = data.encoding; + if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; + if ( data.encoding !== undefined ) texture.encoding = data.encoding; // @deprecated, r152 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); @@ -43469,6 +44517,7 @@ class ObjectLoader extends Loader { if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; + if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; if ( data.userData !== undefined ) texture.userData = data.userData; @@ -43767,6 +44816,8 @@ class ObjectLoader extends Loader { } + if ( data.up !== undefined ) object.up.fromArray( data.up ); + if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; @@ -44038,25 +45089,31 @@ class AudioLoader extends Loader { onLoad( audioBuffer ); - } ); + }, handleError ); } catch ( e ) { - if ( onError ) { + handleError( e ); - onError( e ); + } - } else { + }, onProgress, onError ); - console.error( e ); + function handleError( e ) { - } + if ( onError ) { - scope.manager.itemError( url ); + onError( e ); + + } else { + + console.error( e ); } - }, onProgress, onError ); + scope.manager.itemError( url ); + + } } @@ -48157,6 +49214,7 @@ function intersectObject( object, raycaster, intersects, recursive ) { * The azimuthal angle (theta) is measured from the positive z-axis. */ + class Spherical { constructor( radius = 1, phi = 0, theta = 0 ) { @@ -48453,8 +49511,7 @@ class Box2 { distanceToPoint( point ) { - const clampedPoint = _vector$4.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector$4 ).distanceTo( point ); } @@ -48463,6 +49520,8 @@ class Box2 { this.min.max( box.min ); this.max.min( box.max ); + if ( this.isEmpty() ) this.makeEmpty(); + return this; } @@ -50106,179 +51165,7 @@ class ShapePath { } -// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - -const _tables = /*@__PURE__*/ _generateTables(); - -function _generateTables() { - - // float32 to float16 helpers - - const buffer = new ArrayBuffer( 4 ); - const floatView = new Float32Array( buffer ); - const uint32View = new Uint32Array( buffer ); - - const baseTable = new Uint32Array( 512 ); - const shiftTable = new Uint32Array( 512 ); - - for ( let i = 0; i < 256; ++ i ) { - - const e = i - 127; - - // very small number (0, -0) - - if ( e < - 27 ) { - - baseTable[ i ] = 0x0000; - baseTable[ i | 0x100 ] = 0x8000; - shiftTable[ i ] = 24; - shiftTable[ i | 0x100 ] = 24; - - // small number (denorm) - - } else if ( e < - 14 ) { - - baseTable[ i ] = 0x0400 >> ( - e - 14 ); - baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; - shiftTable[ i ] = - e - 1; - shiftTable[ i | 0x100 ] = - e - 1; - - // normal number - - } else if ( e <= 15 ) { - - baseTable[ i ] = ( e + 15 ) << 10; - baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; - shiftTable[ i ] = 13; - shiftTable[ i | 0x100 ] = 13; - - // large number (Infinity, -Infinity) - - } else if ( e < 128 ) { - - baseTable[ i ] = 0x7c00; - baseTable[ i | 0x100 ] = 0xfc00; - shiftTable[ i ] = 24; - shiftTable[ i | 0x100 ] = 24; - - // stay (NaN, Infinity, -Infinity) - - } else { - - baseTable[ i ] = 0x7c00; - baseTable[ i | 0x100 ] = 0xfc00; - shiftTable[ i ] = 13; - shiftTable[ i | 0x100 ] = 13; - - } - - } - - // float16 to float32 helpers - - const mantissaTable = new Uint32Array( 2048 ); - const exponentTable = new Uint32Array( 64 ); - const offsetTable = new Uint32Array( 64 ); - - for ( let i = 1; i < 1024; ++ i ) { - - let m = i << 13; // zero pad mantissa bits - let e = 0; // zero exponent - - // normalized - while ( ( m & 0x00800000 ) === 0 ) { - - m <<= 1; - e -= 0x00800000; // decrement exponent - - } - - m &= ~ 0x00800000; // clear leading 1 bit - e += 0x38800000; // adjust bias - - mantissaTable[ i ] = m | e; - - } - - for ( let i = 1024; i < 2048; ++ i ) { - - mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); - - } - - for ( let i = 1; i < 31; ++ i ) { - - exponentTable[ i ] = i << 23; - - } - - exponentTable[ 31 ] = 0x47800000; - exponentTable[ 32 ] = 0x80000000; - - for ( let i = 33; i < 63; ++ i ) { - - exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); - - } - - exponentTable[ 63 ] = 0xc7800000; - - for ( let i = 1; i < 64; ++ i ) { - - if ( i !== 32 ) { - - offsetTable[ i ] = 1024; - - } - - } - - return { - floatView: floatView, - uint32View: uint32View, - baseTable: baseTable, - shiftTable: shiftTable, - mantissaTable: mantissaTable, - exponentTable: exponentTable, - offsetTable: offsetTable - }; - -} - -// float32 to float16 - -function toHalfFloat( val ) { - - if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); - - val = clamp( val, - 65504, 65504 ); - - _tables.floatView[ 0 ] = val; - const f = _tables.uint32View[ 0 ]; - const e = ( f >> 23 ) & 0x1ff; - return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); - -} - -// float16 to float32 - -function fromHalfFloat( val ) { - - const m = val >> 10; - _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; - return _tables.floatView[ 0 ]; - -} - -var DataUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, - fromHalfFloat: fromHalfFloat, - toHalfFloat: toHalfFloat -}); - -// r144 - -class BoxBufferGeometry extends BoxGeometry { +class BoxBufferGeometry extends BoxGeometry { // @deprecated, r144 constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) { @@ -50290,9 +51177,7 @@ class BoxBufferGeometry extends BoxGeometry { } -// r144 - -class CapsuleBufferGeometry extends CapsuleGeometry { +class CapsuleBufferGeometry extends CapsuleGeometry { // @deprecated, r144 constructor( radius, length, capSegments, radialSegments ) { @@ -50303,9 +51188,7 @@ class CapsuleBufferGeometry extends CapsuleGeometry { } -// r144 - -class CircleBufferGeometry extends CircleGeometry { +class CircleBufferGeometry extends CircleGeometry { // @deprecated, r144 constructor( radius, segments, thetaStart, thetaLength ) { @@ -50316,9 +51199,7 @@ class CircleBufferGeometry extends CircleGeometry { } -// r144 - -class ConeBufferGeometry extends ConeGeometry { +class ConeBufferGeometry extends ConeGeometry { // @deprecated, r144 constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -50329,9 +51210,7 @@ class ConeBufferGeometry extends ConeGeometry { } -// r144 - -class CylinderBufferGeometry extends CylinderGeometry { +class CylinderBufferGeometry extends CylinderGeometry { // @deprecated, r144 constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -50342,9 +51221,7 @@ class CylinderBufferGeometry extends CylinderGeometry { } -// r144 - -class DodecahedronBufferGeometry extends DodecahedronGeometry { +class DodecahedronBufferGeometry extends DodecahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50355,9 +51232,7 @@ class DodecahedronBufferGeometry extends DodecahedronGeometry { } -// r144 - -class ExtrudeBufferGeometry extends ExtrudeGeometry { +class ExtrudeBufferGeometry extends ExtrudeGeometry { // @deprecated, r144 constructor( shapes, options ) { @@ -50368,9 +51243,7 @@ class ExtrudeBufferGeometry extends ExtrudeGeometry { } -// r144 - -class IcosahedronBufferGeometry extends IcosahedronGeometry { +class IcosahedronBufferGeometry extends IcosahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50381,9 +51254,7 @@ class IcosahedronBufferGeometry extends IcosahedronGeometry { } -// r144 - -class LatheBufferGeometry extends LatheGeometry { +class LatheBufferGeometry extends LatheGeometry { // @deprecated, r144 constructor( points, segments, phiStart, phiLength ) { @@ -50394,9 +51265,7 @@ class LatheBufferGeometry extends LatheGeometry { } -// r144 - -class OctahedronBufferGeometry extends OctahedronGeometry { +class OctahedronBufferGeometry extends OctahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50407,9 +51276,7 @@ class OctahedronBufferGeometry extends OctahedronGeometry { } -// r144 - -class PlaneBufferGeometry extends PlaneGeometry { +class PlaneBufferGeometry extends PlaneGeometry { // @deprecated, r144 constructor( width, height, widthSegments, heightSegments ) { @@ -50420,9 +51287,7 @@ class PlaneBufferGeometry extends PlaneGeometry { } -// r144 - -class PolyhedronBufferGeometry extends PolyhedronGeometry { +class PolyhedronBufferGeometry extends PolyhedronGeometry { // @deprecated, r144 constructor( vertices, indices, radius, detail ) { @@ -50433,9 +51298,7 @@ class PolyhedronBufferGeometry extends PolyhedronGeometry { } -// r144 - -class RingBufferGeometry extends RingGeometry { +class RingBufferGeometry extends RingGeometry { // @deprecated, r144 constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { @@ -50446,9 +51309,7 @@ class RingBufferGeometry extends RingGeometry { } -// r144 - -class ShapeBufferGeometry extends ShapeGeometry { +class ShapeBufferGeometry extends ShapeGeometry { // @deprecated, r144 constructor( shapes, curveSegments ) { @@ -50459,9 +51320,7 @@ class ShapeBufferGeometry extends ShapeGeometry { } -// r144 - -class SphereBufferGeometry extends SphereGeometry { +class SphereBufferGeometry extends SphereGeometry { // @deprecated, r144 constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { @@ -50472,9 +51331,7 @@ class SphereBufferGeometry extends SphereGeometry { } -// r144 - -class TetrahedronBufferGeometry extends TetrahedronGeometry { +class TetrahedronBufferGeometry extends TetrahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50485,9 +51342,7 @@ class TetrahedronBufferGeometry extends TetrahedronGeometry { } -// r144 - -class TorusBufferGeometry extends TorusGeometry { +class TorusBufferGeometry extends TorusGeometry { // @deprecated, r144 constructor( radius, tube, radialSegments, tubularSegments, arc ) { @@ -50498,9 +51353,7 @@ class TorusBufferGeometry extends TorusGeometry { } -// r144 - -class TorusKnotBufferGeometry extends TorusKnotGeometry { +class TorusKnotBufferGeometry extends TorusKnotGeometry { // @deprecated, r144 constructor( radius, tube, tubularSegments, radialSegments, p, q ) { @@ -50511,9 +51364,7 @@ class TorusKnotBufferGeometry extends TorusKnotGeometry { } -// r144 - -class TubeBufferGeometry extends TubeGeometry { +class TubeBufferGeometry extends TubeGeometry { // @deprecated, r144 constructor( path, tubularSegments, radius, radialSegments, closed ) { @@ -50552,10 +51403,12 @@ exports.AddOperation = AddOperation; exports.AdditiveAnimationBlendMode = AdditiveAnimationBlendMode; exports.AdditiveBlending = AdditiveBlending; exports.AlphaFormat = AlphaFormat; +exports.AlwaysCompare = AlwaysCompare; exports.AlwaysDepth = AlwaysDepth; exports.AlwaysStencilFunc = AlwaysStencilFunc; exports.AmbientLight = AmbientLight; exports.AmbientLightProbe = AmbientLightProbe; +exports.AnimationAction = AnimationAction; exports.AnimationClip = AnimationClip; exports.AnimationLoader = AnimationLoader; exports.AnimationMixer = AnimationMixer; @@ -50639,6 +51492,7 @@ exports.DepthTexture = DepthTexture; exports.DirectionalLight = DirectionalLight; exports.DirectionalLightHelper = DirectionalLightHelper; exports.DiscreteInterpolant = DiscreteInterpolant; +exports.DisplayP3ColorSpace = DisplayP3ColorSpace; exports.DodecahedronBufferGeometry = DodecahedronBufferGeometry; exports.DodecahedronGeometry = DodecahedronGeometry; exports.DoubleSide = DoubleSide; @@ -50649,6 +51503,7 @@ exports.DynamicDrawUsage = DynamicDrawUsage; exports.DynamicReadUsage = DynamicReadUsage; exports.EdgesGeometry = EdgesGeometry; exports.EllipseCurve = EllipseCurve; +exports.EqualCompare = EqualCompare; exports.EqualDepth = EqualDepth; exports.EqualStencilFunc = EqualStencilFunc; exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping; @@ -50670,7 +51525,9 @@ exports.Frustum = Frustum; exports.GLBufferAttribute = GLBufferAttribute; exports.GLSL1 = GLSL1; exports.GLSL3 = GLSL3; +exports.GreaterCompare = GreaterCompare; exports.GreaterDepth = GreaterDepth; +exports.GreaterEqualCompare = GreaterEqualCompare; exports.GreaterEqualDepth = GreaterEqualDepth; exports.GreaterEqualStencilFunc = GreaterEqualStencilFunc; exports.GreaterStencilFunc = GreaterStencilFunc; @@ -50708,7 +51565,9 @@ exports.LOD = LOD; exports.LatheBufferGeometry = LatheBufferGeometry; exports.LatheGeometry = LatheGeometry; exports.Layers = Layers; +exports.LessCompare = LessCompare; exports.LessDepth = LessDepth; +exports.LessEqualCompare = LessEqualCompare; exports.LessEqualDepth = LessEqualDepth; exports.LessEqualStencilFunc = LessEqualStencilFunc; exports.LessStencilFunc = LessStencilFunc; @@ -50767,6 +51626,7 @@ exports.NearestMipMapLinearFilter = NearestMipMapLinearFilter; exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter; exports.NearestMipmapLinearFilter = NearestMipmapLinearFilter; exports.NearestMipmapNearestFilter = NearestMipmapNearestFilter; +exports.NeverCompare = NeverCompare; exports.NeverDepth = NeverDepth; exports.NeverStencilFunc = NeverStencilFunc; exports.NoBlending = NoBlending; @@ -50774,6 +51634,7 @@ exports.NoColorSpace = NoColorSpace; exports.NoToneMapping = NoToneMapping; exports.NormalAnimationBlendMode = NormalAnimationBlendMode; exports.NormalBlending = NormalBlending; +exports.NotEqualCompare = NotEqualCompare; exports.NotEqualDepth = NotEqualDepth; exports.NotEqualStencilFunc = NotEqualStencilFunc; exports.NumberKeyframeTrack = NumberKeyframeTrack; diff --git a/build/three.js b/build/three.js index 7f359b9694e128..11f807fc5755bf 100644 --- a/build/three.js +++ b/build/three.js @@ -1,3 +1,4 @@ +console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated with r150+, and will be removed with r160. Please use ES Modules or alternatives: https://threejs.org/docs/index.html#manual/en/introduction/Installation' ); /** * @license * Copyright 2010-2023 Three.js Authors @@ -9,7 +10,8 @@ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.THREE = {})); })(this, (function (exports) { 'use strict'; - const REVISION = '150dev'; + const REVISION = '153dev'; + const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; const CullFaceNone = 0; @@ -150,7 +152,9 @@ const TrianglesDrawMode = 0; const TriangleStripDrawMode = 1; const TriangleFanDrawMode = 2; + /** @deprecated Use LinearSRGBColorSpace or NoColorSpace in three.js r152+. */ const LinearEncoding = 3000; + /** @deprecated Use SRGBColorSpace in three.js r152+. */ const sRGBEncoding = 3001; const BasicDepthPacking = 3200; const RGBADepthPacking = 3201; @@ -161,6 +165,7 @@ const NoColorSpace = ''; const SRGBColorSpace = 'srgb'; const LinearSRGBColorSpace = 'srgb-linear'; + const DisplayP3ColorSpace = 'display-p3'; const ZeroStencilOp = 0; const KeepStencilOp = 7680; @@ -180,6 +185,15 @@ const GreaterEqualStencilFunc = 518; const AlwaysStencilFunc = 519; + const NeverCompare = 512; + const LessCompare = 513; + const EqualCompare = 514; + const LessEqualCompare = 515; + const GreaterCompare = 516; + const NotEqualCompare = 517; + const GreaterEqualCompare = 518; + const AlwaysCompare = 519; + const StaticDrawUsage = 35044; const DynamicDrawUsage = 35048; const StreamDrawUsage = 35040; @@ -517,6 +531,10 @@ return value; + case Uint32Array: + + return value / 4294967295.0; + case Uint16Array: return value / 65535.0; @@ -525,6 +543,10 @@ return value / 255.0; + case Int32Array: + + return Math.max( value / 2147483647.0, - 1.0 ); + case Int16Array: return Math.max( value / 32767.0, - 1.0 ); @@ -549,6 +571,10 @@ return value; + case Uint32Array: + + return Math.round( value * 4294967295.0 ); + case Uint16Array: return Math.round( value * 65535.0 ); @@ -557,6 +583,10 @@ return Math.round( value * 255.0 ); + case Int32Array: + + return Math.round( value * 2147483647.0 ); + case Int16Array: return Math.round( value * 32767.0 ); @@ -573,33 +603,32 @@ } - var MathUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, + const MathUtils = { DEG2RAD: DEG2RAD, RAD2DEG: RAD2DEG, - ceilPowerOfTwo: ceilPowerOfTwo, + generateUUID: generateUUID, clamp: clamp, - damp: damp, - degToRad: degToRad, - denormalize: denormalize, euclideanModulo: euclideanModulo, - floorPowerOfTwo: floorPowerOfTwo, - generateUUID: generateUUID, + mapLinear: mapLinear, inverseLerp: inverseLerp, - isPowerOfTwo: isPowerOfTwo, lerp: lerp, - mapLinear: mapLinear, - normalize: normalize, + damp: damp, pingpong: pingpong, - radToDeg: radToDeg, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, randFloat: randFloat, randFloatSpread: randFloatSpread, - randInt: randInt, seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, setQuaternionFromProperEuler: setQuaternionFromProperEuler, - smootherstep: smootherstep, - smoothstep: smoothstep - }); + normalize: normalize, + denormalize: denormalize + }; class Vector2 { @@ -956,6 +985,20 @@ } + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; + + const theta = this.dot( v ) / denominator; + + // clamp, to handle numerical problems + + return Math.acos( clamp( theta, - 1, 1 ) ); + + } + distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); @@ -1066,7 +1109,7 @@ class Matrix3 { - constructor() { + constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { Matrix3.prototype.isMatrix3 = true; @@ -1078,6 +1121,12 @@ ]; + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); + + } + } set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { @@ -1327,13 +1376,27 @@ makeTranslation( x, y ) { - this.set( + if ( x.isVector2 ) { - 1, 0, x, - 0, 1, y, - 0, 0, 1 + this.set( - ); + 1, 0, x.x, + 0, 1, x.y, + 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, x, + 0, 1, y, + 0, 0, 1 + + ); + + } return this; @@ -1469,6 +1532,18 @@ } + const _cache = {}; + + function warnOnce( message ) { + + if ( message in _cache ) return; + + _cache[ message ] = true; + + console.warn( message ); + + } + function SRGBToLinear( c ) { return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); @@ -1481,16 +1556,77 @@ } - // JavaScript RGB-to-RGB transforms, defined as - // FN[InputColorSpace][OutputColorSpace] callback functions. - const FN = { - [ SRGBColorSpace ]: { [ LinearSRGBColorSpace ]: SRGBToLinear }, - [ LinearSRGBColorSpace ]: { [ SRGBColorSpace ]: LinearToSRGB }, + /** + * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + + const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().fromArray( [ + 0.8224621, 0.0331941, 0.0170827, + 0.1775380, 0.9668058, 0.0723974, + - 0.0000001, 0.0000001, 0.9105199 + ] ); + + const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().fromArray( [ + 1.2249401, - 0.0420569, - 0.0196376, + - 0.2249404, 1.0420571, - 0.0786361, + 0.0000001, 0.0000000, 1.0982735 + ] ); + + function DisplayP3ToLinearSRGB( color ) { + + // Display P3 uses the sRGB transfer functions + return color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ); + + } + + function LinearSRGBToDisplayP3( color ) { + + // Display P3 uses the sRGB transfer functions + return color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(); + + } + + // Conversions from to Linear-sRGB reference space. + const TO_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertSRGBToLinear(), + [ DisplayP3ColorSpace ]: DisplayP3ToLinearSRGB, + }; + + // Conversions to from Linear-sRGB reference space. + const FROM_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertLinearToSRGB(), + [ DisplayP3ColorSpace ]: LinearSRGBToDisplayP3, }; const ColorManagement = { - legacyMode: true, + enabled: true, + + get legacyMode() { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + return ! this.enabled; + + }, + + set legacyMode( legacyMode ) { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + this.enabled = ! legacyMode; + + }, get workingColorSpace() { @@ -1506,25 +1642,22 @@ convert: function ( color, sourceColorSpace, targetColorSpace ) { - if ( this.legacyMode || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { return color; } - if ( FN[ sourceColorSpace ] && FN[ sourceColorSpace ][ targetColorSpace ] !== undefined ) { - - const fn = FN[ sourceColorSpace ][ targetColorSpace ]; + const sourceToLinear = TO_LINEAR[ sourceColorSpace ]; + const targetFromLinear = FROM_LINEAR[ targetColorSpace ]; - color.r = fn( color.r ); - color.g = fn( color.g ); - color.b = fn( color.b ); + if ( sourceToLinear === undefined || targetFromLinear === undefined ) { - return color; + throw new Error( `Unsupported color space conversion, "${ sourceColorSpace }" to "${ targetColorSpace }".` ); } - throw new Error( 'Unsupported color space conversion.' ); + return targetFromLinear( sourceToLinear( color ) ); }, @@ -1542,3211 +1675,2658 @@ }; - const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, - 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, - 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, - 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, - 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, - 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, - 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, - 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, - 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, - 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, - 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, - 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, - 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, - 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, - 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, - 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, - 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, - 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, - 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, - 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, - 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, - 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, - 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, - 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - - const _rgb$1 = { r: 0, g: 0, b: 0 }; - const _hslA = { h: 0, s: 0, l: 0 }; - const _hslB = { h: 0, s: 0, l: 0 }; - - function hue2rgb( p, q, t ) { - - if ( t < 0 ) t += 1; - if ( t > 1 ) t -= 1; - if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; - if ( t < 1 / 2 ) return q; - if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); - return p; - - } - - function toComponents( source, target ) { - - target.r = source.r; - target.g = source.g; - target.b = source.b; - - return target; + let _canvas; - } + class ImageUtils { - class Color { + static getDataURL( image ) { - constructor( r, g, b ) { + if ( /^data:/i.test( image.src ) ) { - this.isColor = true; + return image.src; - this.r = 1; - this.g = 1; - this.b = 1; + } - if ( g === undefined && b === undefined ) { + if ( typeof HTMLCanvasElement === 'undefined' ) { - // r is THREE.Color, hex or string - return this.set( r ); + return image.src; } - return this.setRGB( r, g, b ); - - } + let canvas; - set( value ) { + if ( image instanceof HTMLCanvasElement ) { - if ( value && value.isColor ) { + canvas = image; - this.copy( value ); + } else { - } else if ( typeof value === 'number' ) { + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); - this.setHex( value ); + _canvas.width = image.width; + _canvas.height = image.height; - } else if ( typeof value === 'string' ) { + const context = _canvas.getContext( '2d' ); - this.setStyle( value ); + if ( image instanceof ImageData ) { - } + context.putImageData( image, 0, 0 ); - return this; + } else { - } + context.drawImage( image, 0, 0, image.width, image.height ); - setScalar( scalar ) { + } - this.r = scalar; - this.g = scalar; - this.b = scalar; + canvas = _canvas; - return this; + } - } + if ( canvas.width > 2048 || canvas.height > 2048 ) { - setHex( hex, colorSpace = SRGBColorSpace ) { + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); - hex = Math.floor( hex ); + return canvas.toDataURL( 'image/jpeg', 0.6 ); - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + return canvas.toDataURL( 'image/png' ); - return this; + } } - setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { - - this.r = r; - this.g = g; - this.b = b; + static sRGBToLinear( image ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - return this; + const canvas = createElementNS( 'canvas' ); - } + canvas.width = image.width; + canvas.height = image.height; - setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); - // h,s,l ranges are in 0.0 - 1.0 - h = euclideanModulo( h, 1 ); - s = clamp( s, 0, 1 ); - l = clamp( l, 0, 1 ); + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; - if ( s === 0 ) { + for ( let i = 0; i < data.length; i ++ ) { - this.r = this.g = this.b = l; + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; - } else { + } - const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - const q = ( 2 * l ) - p; + context.putImageData( imageData, 0, 0 ); - this.r = hue2rgb( q, p, h + 1 / 3 ); - this.g = hue2rgb( q, p, h ); - this.b = hue2rgb( q, p, h - 1 / 3 ); + return canvas; - } + } else if ( image.data ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + const data = image.data.slice( 0 ); - return this; + for ( let i = 0; i < data.length; i ++ ) { - } + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { - setStyle( style, colorSpace = SRGBColorSpace ) { + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); - function handleAlpha( string ) { + } else { - if ( string === undefined ) return; + // assuming float - if ( parseFloat( string ) < 1 ) { + data[ i ] = SRGBToLinear( data[ i ] ); - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + } } - } + return { + data: data, + width: image.width, + height: image.height + }; + } else { - let m; + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; - if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) { + } - // rgb / hsl + } - let color; - const name = m[ 1 ]; - const components = m[ 2 ]; + } - switch ( name ) { + let sourceId = 0; - case 'rgb': - case 'rgba': + class Source { - if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + constructor( data = null ) { - // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; + this.isSource = true; - ColorManagement.toWorkingColorSpace( this, colorSpace ); + Object.defineProperty( this, 'id', { value: sourceId ++ } ); - handleAlpha( color[ 4 ] ); + this.uuid = generateUUID(); - return this; + this.data = data; - } + this.version = 0; - if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + } - // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; + set needsUpdate( value ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + if ( value === true ) this.version ++; - handleAlpha( color[ 4 ] ); + } - return this; + toJSON( meta ) { - } + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - break; + if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { - case 'hsl': - case 'hsla': + return meta.images[ this.uuid ]; - if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + } - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - const h = parseFloat( color[ 1 ] ) / 360; - const s = parseFloat( color[ 2 ] ) / 100; - const l = parseFloat( color[ 3 ] ) / 100; + const output = { + uuid: this.uuid, + url: '' + }; - handleAlpha( color[ 4 ] ); + const data = this.data; - return this.setHSL( h, s, l, colorSpace ); + if ( data !== null ) { - } + let url; - break; + if ( Array.isArray( data ) ) { - } + // cube texture - } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { + url = []; - // hex color + for ( let i = 0, l = data.length; i < l; i ++ ) { - const hex = m[ 1 ]; - const size = hex.length; + if ( data[ i ].isDataTexture ) { - if ( size === 3 ) { + url.push( serializeImage( data[ i ].image ) ); - // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + url.push( serializeImage( data[ i ] ) ); - return this; + } - } else if ( size === 6 ) { + } - // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + // texture - return this; + url = serializeImage( data ); } + output.url = url; + } - if ( style && style.length > 0 ) { + if ( ! isRootObject ) { - return this.setColorName( style, colorSpace ); + meta.images[ this.uuid ] = output; } - return this; + return output; } - setColorName( style, colorSpace = SRGBColorSpace ) { + } - // color keywords - const hex = _colorKeywords[ style.toLowerCase() ]; + function serializeImage( image ) { - if ( hex !== undefined ) { + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - // red - this.setHex( hex, colorSpace ); + // default images + + return ImageUtils.getDataURL( image ); + + } else { + + if ( image.data ) { + + // images of DataTexture + + return { + data: Array.from( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; } else { - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; } - return this; - } - clone() { + } - return new this.constructor( this.r, this.g, this.b ); + let textureId = 0; - } + class Texture extends EventDispatcher { - copy( color ) { + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { - this.r = color.r; - this.g = color.g; - this.b = color.b; + super(); - return this; + this.isTexture = true; - } + Object.defineProperty( this, 'id', { value: textureId ++ } ); - copySRGBToLinear( color ) { + this.uuid = generateUUID(); - this.r = SRGBToLinear( color.r ); - this.g = SRGBToLinear( color.g ); - this.b = SRGBToLinear( color.b ); + this.name = ''; - return this; + this.source = new Source( image ); + this.mipmaps = []; - } + this.mapping = mapping; + this.channel = 0; - copyLinearToSRGB( color ) { + this.wrapS = wrapS; + this.wrapT = wrapT; - this.r = LinearToSRGB( color.r ); - this.g = LinearToSRGB( color.g ); - this.b = LinearToSRGB( color.b ); + this.magFilter = magFilter; + this.minFilter = minFilter; - return this; + this.anisotropy = anisotropy; - } + this.format = format; + this.internalFormat = null; + this.type = type; - convertSRGBToLinear() { + this.offset = new Vector2( 0, 0 ); + this.repeat = new Vector2( 1, 1 ); + this.center = new Vector2( 0, 0 ); + this.rotation = 0; - this.copySRGBToLinear( this ); + this.matrixAutoUpdate = true; + this.matrix = new Matrix3(); - return this; + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - } + if ( typeof colorSpace === 'string' ) { - convertLinearToSRGB() { + this.colorSpace = colorSpace; - this.copyLinearToSRGB( this ); + } else { // @deprecated, r152 - return this; + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace; - } + } - getHex( colorSpace = SRGBColorSpace ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + this.userData = {}; + + this.version = 0; + this.onUpdate = null; - return clamp( _rgb$1.r * 255, 0, 255 ) << 16 ^ clamp( _rgb$1.g * 255, 0, 255 ) << 8 ^ clamp( _rgb$1.b * 255, 0, 255 ) << 0; + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) } - getHexString( colorSpace = SRGBColorSpace ) { + get image() { - return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); + return this.source.data; } - getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { + set image( value = null ) { - // h,s,l ranges are in 0.0 - 1.0 + this.source.data = value; - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + } - const r = _rgb$1.r, g = _rgb$1.g, b = _rgb$1.b; + updateMatrix() { - const max = Math.max( r, g, b ); - const min = Math.min( r, g, b ); + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); - let hue, saturation; - const lightness = ( min + max ) / 2.0; + } - if ( min === max ) { + clone() { - hue = 0; - saturation = 0; + return new this.constructor().copy( this ); - } else { + } - const delta = max - min; + copy( source ) { - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + this.name = source.name; - switch ( max ) { + this.source = source.source; + this.mipmaps = source.mipmaps.slice( 0 ); - case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; - case g: hue = ( b - r ) / delta + 2; break; - case b: hue = ( r - g ) / delta + 4; break; + this.mapping = source.mapping; + this.channel = source.channel; - } + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; - hue /= 6; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; - } + this.anisotropy = source.anisotropy; - target.h = hue; - target.s = saturation; - target.l = lightness; + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; - return target; + this.offset.copy( source.offset ); + this.repeat.copy( source.repeat ); + this.center.copy( source.center ); + this.rotation = source.rotation; - } + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy( source.matrix ); - getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.colorSpace = source.colorSpace; - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - target.r = _rgb$1.r; - target.g = _rgb$1.g; - target.b = _rgb$1.b; + this.needsUpdate = true; - return target; + return this; } - getStyle( colorSpace = SRGBColorSpace ) { + toJSON( meta ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - if ( colorSpace !== SRGBColorSpace ) { + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). - return `color(${ colorSpace } ${ _rgb$1.r } ${ _rgb$1.g } ${ _rgb$1.b })`; + return meta.textures[ this.uuid ]; } - return `rgb(${( _rgb$1.r * 255 ) | 0},${( _rgb$1.g * 255 ) | 0},${( _rgb$1.b * 255 ) | 0})`; + const output = { - } + metadata: { + version: 4.6, + type: 'Texture', + generator: 'Texture.toJSON' + }, - offsetHSL( h, s, l ) { + uuid: this.uuid, + name: this.name, - this.getHSL( _hslA ); + image: this.source.toJSON( meta ).uuid, - _hslA.h += h; _hslA.s += s; _hslA.l += l; + mapping: this.mapping, + channel: this.channel, - this.setHSL( _hslA.h, _hslA.s, _hslA.l ); + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, - return this; + wrap: [ this.wrapS, this.wrapT ], - } + format: this.format, + internalFormat: this.internalFormat, + type: this.type, + colorSpace: this.colorSpace, - add( color ) { + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, - this.r += color.r; - this.g += color.g; - this.b += color.b; + flipY: this.flipY, - return this; + generateMipmaps: this.generateMipmaps, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment - } + }; - addColors( color1, color2 ) { + if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; + if ( ! isRootObject ) { - return this; + meta.textures[ this.uuid ] = output; - } + } - addScalar( s ) { + return output; - this.r += s; - this.g += s; - this.b += s; + } - return this; + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); } - sub( color ) { + transformUv( uv ) { - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); + if ( this.mapping !== UVMapping ) return uv; - return this; + uv.applyMatrix3( this.matrix ); - } + if ( uv.x < 0 || uv.x > 1 ) { - multiply( color ) { + switch ( this.wrapS ) { - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; + case RepeatWrapping: - return this; + uv.x = uv.x - Math.floor( uv.x ); + break; - } + case ClampToEdgeWrapping: - multiplyScalar( s ) { + uv.x = uv.x < 0 ? 0 : 1; + break; - this.r *= s; - this.g *= s; - this.b *= s; + case MirroredRepeatWrapping: - return this; + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { - } + uv.x = Math.ceil( uv.x ) - uv.x; - lerp( color, alpha ) { + } else { - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; + uv.x = uv.x - Math.floor( uv.x ); - return this; + } - } + break; - lerpColors( color1, color2, alpha ) { + } - this.r = color1.r + ( color2.r - color1.r ) * alpha; - this.g = color1.g + ( color2.g - color1.g ) * alpha; - this.b = color1.b + ( color2.b - color1.b ) * alpha; + } - return this; + if ( uv.y < 0 || uv.y > 1 ) { - } + switch ( this.wrapT ) { - lerpHSL( color, alpha ) { + case RepeatWrapping: - this.getHSL( _hslA ); - color.getHSL( _hslB ); + uv.y = uv.y - Math.floor( uv.y ); + break; - const h = lerp( _hslA.h, _hslB.h, alpha ); - const s = lerp( _hslA.s, _hslB.s, alpha ); - const l = lerp( _hslA.l, _hslB.l, alpha ); + case ClampToEdgeWrapping: - this.setHSL( h, s, l ); + uv.y = uv.y < 0 ? 0 : 1; + break; - return this; + case MirroredRepeatWrapping: - } + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - equals( c ) { + uv.y = Math.ceil( uv.y ) - uv.y; - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + } else { - } + uv.y = uv.y - Math.floor( uv.y ); - fromArray( array, offset = 0 ) { + } - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; + break; - return this; + } - } + } - toArray( array = [], offset = 0 ) { + if ( this.flipY ) { - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; + uv.y = 1 - uv.y; - return array; + } + + return uv; } - fromBufferAttribute( attribute, index ) { + set needsUpdate( value ) { - this.r = attribute.getX( index ); - this.g = attribute.getY( index ); - this.b = attribute.getZ( index ); + if ( value === true ) { - return this; + this.version ++; + this.source.needsUpdate = true; + + } } - toJSON() { + get encoding() { // @deprecated, r152 - return this.getHex(); + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; } - *[ Symbol.iterator ]() { + set encoding( encoding ) { // @deprecated, r152 - yield this.r; - yield this.g; - yield this.b; + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; } } - Color.NAMES = _colorKeywords; - - let _canvas; + Texture.DEFAULT_IMAGE = null; + Texture.DEFAULT_MAPPING = UVMapping; + Texture.DEFAULT_ANISOTROPY = 1; - class ImageUtils { + class Vector4 { - static getDataURL( image ) { + constructor( x = 0, y = 0, z = 0, w = 1 ) { - if ( /^data:/i.test( image.src ) ) { + Vector4.prototype.isVector4 = true; - return image.src; + this.x = x; + this.y = y; + this.z = z; + this.w = w; - } + } - if ( typeof HTMLCanvasElement == 'undefined' ) { + get width() { - return image.src; + return this.z; - } + } - let canvas; + set width( value ) { - if ( image instanceof HTMLCanvasElement ) { + this.z = value; - canvas = image; + } - } else { + get height() { - if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); + return this.w; - _canvas.width = image.width; - _canvas.height = image.height; + } - const context = _canvas.getContext( '2d' ); + set height( value ) { - if ( image instanceof ImageData ) { + this.w = value; - context.putImageData( image, 0, 0 ); + } - } else { + set( x, y, z, w ) { - context.drawImage( image, 0, 0, image.width, image.height ); + this.x = x; + this.y = y; + this.z = z; + this.w = w; - } + return this; - canvas = _canvas; + } - } + setScalar( scalar ) { - if ( canvas.width > 2048 || canvas.height > 2048 ) { + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; - console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); + return this; - return canvas.toDataURL( 'image/jpeg', 0.6 ); + } - } else { + setX( x ) { - return canvas.toDataURL( 'image/png' ); + this.x = x; - } + return this; } - static sRGBToLinear( image ) { + setY( y ) { - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + this.y = y; - const canvas = createElementNS( 'canvas' ); + return this; - canvas.width = image.width; - canvas.height = image.height; + } - const context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, image.width, image.height ); + setZ( z ) { - const imageData = context.getImageData( 0, 0, image.width, image.height ); - const data = imageData.data; + this.z = z; - for ( let i = 0; i < data.length; i ++ ) { + return this; - data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; + } - } + setW( w ) { - context.putImageData( imageData, 0, 0 ); + this.w = w; - return canvas; + return this; - } else if ( image.data ) { + } - const data = image.data.slice( 0 ); + setComponent( index, value ) { - for ( let i = 0; i < data.length; i ++ ) { + switch ( index ) { - if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + case 3: this.w = value; break; + default: throw new Error( 'index is out of range: ' + index ); - data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); + } - } else { + return this; - // assuming float + } - data[ i ] = SRGBToLinear( data[ i ] ); + getComponent( index ) { - } + switch ( index ) { - } + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + case 3: return this.w; + default: throw new Error( 'index is out of range: ' + index ); - return { - data: data, - width: image.width, - height: image.height - }; + } - } else { + } - console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); - return image; + clone() { - } + return new this.constructor( this.x, this.y, this.z, this.w ); } - } + copy( v ) { - class Source { + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; - constructor( data = null ) { + return this; - this.isSource = true; + } - this.uuid = generateUUID(); + add( v ) { - this.data = data; + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; - this.version = 0; + return this; } - set needsUpdate( value ) { + addScalar( s ) { - if ( value === true ) this.version ++; + this.x += s; + this.y += s; + this.z += s; + this.w += s; + + return this; } - toJSON( meta ) { + addVectors( a, b ) { - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; + this.w = a.w + b.w; - if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { + return this; - return meta.images[ this.uuid ]; + } - } + addScaledVector( v, s ) { - const output = { - uuid: this.uuid, - url: '' - }; + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; - const data = this.data; + return this; - if ( data !== null ) { + } - let url; + sub( v ) { - if ( Array.isArray( data ) ) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; - // cube texture + return this; - url = []; + } - for ( let i = 0, l = data.length; i < l; i ++ ) { + subScalar( s ) { - if ( data[ i ].isDataTexture ) { + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; - url.push( serializeImage( data[ i ].image ) ); + return this; - } else { + } - url.push( serializeImage( data[ i ] ) ); + subVectors( a, b ) { - } + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + this.w = a.w - b.w; - } + return this; - } else { + } - // texture + multiply( v ) { - url = serializeImage( data ); + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + this.w *= v.w; - } + return this; - output.url = url; + } - } + multiplyScalar( scalar ) { - if ( ! isRootObject ) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; - meta.images[ this.uuid ] = output; + return this; - } + } - return output; + applyMatrix4( m ) { + + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; + this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + + return this; } - } + divideScalar( scalar ) { - function serializeImage( image ) { + return this.multiplyScalar( 1 / scalar ); - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + } - // default images + setAxisAngleFromQuaternion( q ) { - return ImageUtils.getDataURL( image ); + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - } else { + // q is assumed to be normalized - if ( image.data ) { + this.w = 2 * Math.acos( q.w ); - // images of DataTexture + const s = Math.sqrt( 1 - q.w * q.w ); - return { - data: Array.from( image.data ), - width: image.width, - height: image.height, - type: image.data.constructor.name - }; + if ( s < 0.0001 ) { + + this.x = 1; + this.y = 0; + this.z = 0; } else { - console.warn( 'THREE.Texture: Unable to serialize Texture.' ); - return {}; + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; } + return this; + } - } + setAxisAngleFromRotationMatrix( m ) { - let textureId = 0; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - class Texture extends EventDispatcher { + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, encoding = LinearEncoding ) { + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - super(); + te = m.elements, - this.isTexture = true; + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; - Object.defineProperty( this, 'id', { value: textureId ++ } ); + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { - this.uuid = generateUUID(); + // singularity found + // first check for identity matrix which must have +1 for all terms + // in leading diagonal and zero in other terms - this.name = ''; + if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && + ( Math.abs( m13 + m31 ) < epsilon2 ) && + ( Math.abs( m23 + m32 ) < epsilon2 ) && + ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { - this.source = new Source( image ); - this.mipmaps = []; + // this singularity is identity matrix so angle = 0 - this.mapping = mapping; + this.set( 1, 0, 0, 0 ); - this.wrapS = wrapS; - this.wrapT = wrapT; + return this; // zero angle, arbitrary axis - this.magFilter = magFilter; - this.minFilter = minFilter; + } - this.anisotropy = anisotropy; + // otherwise this singularity is angle = 180 - this.format = format; - this.internalFormat = null; - this.type = type; + angle = Math.PI; - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); - this.center = new Vector2( 0, 0 ); - this.rotation = 0; - - this.matrixAutoUpdate = true; - this.matrix = new Matrix3(); - - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + const xx = ( m11 + 1 ) / 2; + const yy = ( m22 + 1 ) / 2; + const zz = ( m33 + 1 ) / 2; + const xy = ( m12 + m21 ) / 4; + const xz = ( m13 + m31 ) / 4; + const yz = ( m23 + m32 ) / 4; - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding; + if ( ( xx > yy ) && ( xx > zz ) ) { - this.userData = {}; + // m11 is the largest diagonal term - this.version = 0; - this.onUpdate = null; + if ( xx < epsilon ) { - this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not - this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) + x = 0; + y = 0.707106781; + z = 0.707106781; - } + } else { - get image() { + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; - return this.source.data; + } - } + } else if ( yy > zz ) { - set image( value ) { + // m22 is the largest diagonal term - this.source.data = value; + if ( yy < epsilon ) { - } + x = 0.707106781; + y = 0; + z = 0.707106781; - updateMatrix() { + } else { - this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; - } + } - clone() { + } else { - return new this.constructor().copy( this ); + // m33 is the largest diagonal term so base result on this - } + if ( zz < epsilon ) { - copy( source ) { + x = 0.707106781; + y = 0.707106781; + z = 0; - this.name = source.name; + } else { - this.source = source.source; - this.mipmaps = source.mipmaps.slice( 0 ); + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; - this.mapping = source.mapping; + } - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + } - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + this.set( x, y, z, angle ); - this.anisotropy = source.anisotropy; + return this; // return 180 deg rotation - this.format = source.format; - this.internalFormat = source.internalFormat; - this.type = source.type; + } - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; + // as we have reached here there are no singularities so we can handle normally - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + if ( Math.abs( s ) < 0.001 ) s = 1; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case - this.needsUpdate = true; + this.x = ( m32 - m23 ) / s; + this.y = ( m13 - m31 ) / s; + this.z = ( m21 - m12 ) / s; + this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); return this; } - toJSON( meta ) { - - const isRootObject = ( meta === undefined || typeof meta === 'string' ); - - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - - return meta.textures[ this.uuid ]; - - } - - const output = { - - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + min( v ) { - uuid: this.uuid, - name: this.name, + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); + this.w = Math.min( this.w, v.w ); - image: this.source.toJSON( meta ).uuid, + return this; - mapping: this.mapping, + } - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, + max( v ) { - wrap: [ this.wrapS, this.wrapT ], + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); + this.w = Math.max( this.w, v.w ); - format: this.format, - type: this.type, - encoding: this.encoding, + return this; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + } - flipY: this.flipY, + clamp( min, max ) { - generateMipmaps: this.generateMipmaps, - premultiplyAlpha: this.premultiplyAlpha, - unpackAlignment: this.unpackAlignment + // assumes min < max, componentwise - }; + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); - if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; + return this; - if ( ! isRootObject ) { + } - meta.textures[ this.uuid ] = output; + clampScalar( minVal, maxVal ) { - } + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); + this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); - return output; + return this; } - dispose() { + clampLength( min, max ) { - this.dispatchEvent( { type: 'dispose' } ); + const length = this.length(); + + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); } - transformUv( uv ) { + floor() { - if ( this.mapping !== UVMapping ) return uv; + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); + this.w = Math.floor( this.w ); - uv.applyMatrix3( this.matrix ); + return this; - if ( uv.x < 0 || uv.x > 1 ) { + } - switch ( this.wrapS ) { + ceil() { - case RepeatWrapping: + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); + this.w = Math.ceil( this.w ); - uv.x = uv.x - Math.floor( uv.x ); - break; + return this; - case ClampToEdgeWrapping: + } - uv.x = uv.x < 0 ? 0 : 1; - break; + round() { - case MirroredRepeatWrapping: + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + this.w = Math.round( this.w ); - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + return this; - uv.x = Math.ceil( uv.x ) - uv.x; + } - } else { + roundToZero() { - uv.x = uv.x - Math.floor( uv.x ); + this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); + this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); + this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); + this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); - } + return this; - break; + } - } + negate() { - } + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + this.w = - this.w; - if ( uv.y < 0 || uv.y > 1 ) { + return this; - switch ( this.wrapT ) { + } - case RepeatWrapping: + dot( v ) { - uv.y = uv.y - Math.floor( uv.y ); - break; + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - case ClampToEdgeWrapping: + } - uv.y = uv.y < 0 ? 0 : 1; - break; + lengthSq() { - case MirroredRepeatWrapping: + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + } - uv.y = Math.ceil( uv.y ) - uv.y; + length() { - } else { + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - uv.y = uv.y - Math.floor( uv.y ); + } - } + manhattanLength() { - break; + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - } + } - } + normalize() { - if ( this.flipY ) { + return this.divideScalar( this.length() || 1 ); - uv.y = 1 - uv.y; + } - } + setLength( length ) { - return uv; + return this.normalize().multiplyScalar( length ); } - set needsUpdate( value ) { - - if ( value === true ) { + lerp( v, alpha ) { - this.version ++; - this.source.needsUpdate = true; + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; + this.w += ( v.w - this.w ) * alpha; - } + return this; } - } - - Texture.DEFAULT_IMAGE = null; - Texture.DEFAULT_MAPPING = UVMapping; - Texture.DEFAULT_ANISOTROPY = 1; - - class Vector4 { - - constructor( x = 0, y = 0, z = 0, w = 1 ) { + lerpVectors( v1, v2, alpha ) { - Vector4.prototype.isVector4 = true; + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; + this.w = v1.w + ( v2.w - v1.w ) * alpha; - this.x = x; - this.y = y; - this.z = z; - this.w = w; + return this; } - get width() { + equals( v ) { - return this.z; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); } - set width( value ) { - - this.z = value; - - } + fromArray( array, offset = 0 ) { - get height() { + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; - return this.w; + return this; } - set height( value ) { + toArray( array = [], offset = 0 ) { - this.w = value; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; + + return array; } - set( x, y, z, w ) { + fromBufferAttribute( attribute, index ) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); return this; } - setScalar( scalar ) { + random() { - this.x = scalar; - this.y = scalar; - this.z = scalar; - this.w = scalar; + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); return this; } - setX( x ) { - - this.x = x; + *[ Symbol.iterator ]() { - return this; + yield this.x; + yield this.y; + yield this.z; + yield this.w; } - setY( y ) { + } - this.y = y; + /* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers + */ + class WebGLRenderTarget extends EventDispatcher { - return this; + constructor( width = 1, height = 1, options = {} ) { - } + super(); - setZ( z ) { + this.isWebGLRenderTarget = true; - this.z = z; + this.width = width; + this.height = height; + this.depth = 1; - return this; + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - } + this.viewport = new Vector4( 0, 0, width, height ); - setW( w ) { + const image = { width: width, height: height, depth: 1 }; - this.w = w; + if ( options.encoding !== undefined ) { - return this; + // @deprecated, r152 + warnOnce( 'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; - } + } - setComponent( index, value ) { + this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); + this.texture.isRenderTargetTexture = true; - switch ( index ) { + this.texture.flipY = false; + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - case 3: this.w = value; break; - default: throw new Error( 'index is out of range: ' + index ); + this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; - } + this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - return this; + this.samples = options.samples !== undefined ? options.samples : 0; } - getComponent( index ) { + setSize( width, height, depth = 1 ) { - switch ( index ) { + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - case 3: return this.w; - default: throw new Error( 'index is out of range: ' + index ); + this.width = width; + this.height = height; + this.depth = depth; + + this.texture.image.width = width; + this.texture.image.height = height; + this.texture.image.depth = depth; + + this.dispose(); } + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); + } clone() { - return new this.constructor( this.x, this.y, this.z, this.w ); + return new this.constructor().copy( this ); } - copy( v ) { + copy( source ) { - this.x = v.x; - this.y = v.y; - this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - return this; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - } + this.viewport.copy( source.viewport ); - add( v ) { + this.texture = source.texture.clone(); + this.texture.isRenderTargetTexture = true; - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; + // ensure image object is not shared, see #20328 - return this; + const image = Object.assign( {}, source.texture.image ); + this.texture.source = new Source( image ); - } + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - addScalar( s ) { + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - this.x += s; - this.y += s; - this.z += s; - this.w += s; + this.samples = source.samples; return this; } - addVectors( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - this.w = a.w + b.w; + dispose() { - return this; + this.dispatchEvent( { type: 'dispose' } ); } - addScaledVector( v, s ) { + } - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - this.w += v.w * s; + class DataArrayTexture extends Texture { - return this; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - } + super( null ); - sub( v ) { + this.isDataArrayTexture = true; - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; + this.image = { data, width, height, depth }; - return this; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - } + this.wrapR = ClampToEdgeWrapping; - subScalar( s ) { + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - this.x -= s; - this.y -= s; - this.z -= s; - this.w -= s; + } - return this; + } - } + class WebGLArrayRenderTarget extends WebGLRenderTarget { - subVectors( a, b ) { + constructor( width = 1, height = 1, depth = 1 ) { - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - this.w = a.w - b.w; + super( width, height ); - return this; + this.isWebGLArrayRenderTarget = true; + + this.depth = depth; + + this.texture = new DataArrayTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; } - multiply( v ) { + } - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - this.w *= v.w; + class Data3DTexture extends Texture { - return this; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - } + // We're going to add .setXXX() methods for setting properties later. + // Users can still set in DataTexture3D directly. + // + // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // texture.anisotropy = 16; + // + // See #14839 - multiplyScalar( scalar ) { + super( null ); - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + this.isData3DTexture = true; - return this; + this.image = { data, width, height, depth }; + + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + + this.wrapR = ClampToEdgeWrapping; + + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; } - applyMatrix4( m ) { + } - const x = this.x, y = this.y, z = this.z, w = this.w; - const e = m.elements; + class WebGL3DRenderTarget extends WebGLRenderTarget { - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; - this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + constructor( width = 1, height = 1, depth = 1 ) { - return this; + super( width, height ); - } + this.isWebGL3DRenderTarget = true; - divideScalar( scalar ) { + this.depth = depth; - return this.multiplyScalar( 1 / scalar ); + this.texture = new Data3DTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; } - setAxisAngleFromQuaternion( q ) { + } - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm + class WebGLMultipleRenderTargets extends WebGLRenderTarget { - // q is assumed to be normalized + constructor( width = 1, height = 1, count = 1, options = {} ) { - this.w = 2 * Math.acos( q.w ); + super( width, height, options ); - const s = Math.sqrt( 1 - q.w * q.w ); + this.isWebGLMultipleRenderTargets = true; - if ( s < 0.0001 ) { + const texture = this.texture; - this.x = 1; - this.y = 0; - this.z = 0; + this.texture = []; - } else { + for ( let i = 0; i < count; i ++ ) { - this.x = q.x / s; - this.y = q.y / s; - this.z = q.z / s; + this.texture[ i ] = texture.clone(); + this.texture[ i ].isRenderTargetTexture = true; } - return this; - } - setAxisAngleFromRotationMatrix( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + setSize( width, height, depth = 1 ) { - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - let angle, x, y, z; // variables for result - const epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + this.width = width; + this.height = height; + this.depth = depth; - te = m.elements, + for ( let i = 0, il = this.texture.length; i < il; i ++ ) { - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; + this.texture[ i ].image.width = width; + this.texture[ i ].image.height = height; + this.texture[ i ].image.depth = depth; - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { + } - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + this.dispose(); - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + } - // this singularity is identity matrix so angle = 0 + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - this.set( 1, 0, 0, 0 ); + return this; - return this; // zero angle, arbitrary axis + } - } + copy( source ) { - // otherwise this singularity is angle = 180 + this.dispose(); - angle = Math.PI; + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - const xx = ( m11 + 1 ) / 2; - const yy = ( m22 + 1 ) / 2; - const zz = ( m33 + 1 ) / 2; - const xy = ( m12 + m21 ) / 4; - const xz = ( m13 + m31 ) / 4; - const yz = ( m23 + m32 ) / 4; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - if ( ( xx > yy ) && ( xx > zz ) ) { + this.viewport.copy( source.viewport ); - // m11 is the largest diagonal term + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - if ( xx < epsilon ) { + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - x = 0; - y = 0.707106781; - z = 0.707106781; + this.texture.length = 0; - } else { + for ( let i = 0, il = source.texture.length; i < il; i ++ ) { - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + this.texture[ i ] = source.texture[ i ].clone(); + this.texture[ i ].isRenderTargetTexture = true; - } + } - } else if ( yy > zz ) { + return this; - // m22 is the largest diagonal term + } - if ( yy < epsilon ) { + } - x = 0.707106781; - y = 0; - z = 0.707106781; + class Quaternion { - } else { + constructor( x = 0, y = 0, z = 0, w = 1 ) { - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + this.isQuaternion = true; - } + this._x = x; + this._y = y; + this._z = z; + this._w = w; - } else { + } - // m33 is the largest diagonal term so base result on this + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - if ( zz < epsilon ) { + // fuzz-free, array-based Quaternion SLERP operation - x = 0.707106781; - y = 0.707106781; - z = 0; + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; - } else { + const x1 = src1[ srcOffset1 + 0 ], + y1 = src1[ srcOffset1 + 1 ], + z1 = src1[ srcOffset1 + 2 ], + w1 = src1[ srcOffset1 + 3 ]; - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + if ( t === 0 ) { - } + dst[ dstOffset + 0 ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; + return; - } + } - this.set( x, y, z, angle ); + if ( t === 1 ) { - return this; // return 180 deg rotation + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; } - // as we have reached here there are no singularities so we can handle normally + if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { - let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + let s = 1 - t; + const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + dir = ( cos >= 0 ? 1 : - 1 ), + sqrSin = 1 - cos * cos; - if ( Math.abs( s ) < 0.001 ) s = 1; + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; - return this; + } - } + const tDir = t * dir; - min( v ) { + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - this.w = Math.min( this.w, v.w ); + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { - return this; + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - } + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; - max( v ) { + } - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - this.w = Math.max( this.w, v.w ); + } - return this; + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; } - clamp( min, max ) { + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { - // assumes min < max, componentwise + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; - return this; + dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; + dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; + dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; + dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; - } + return dst; - clampScalar( minVal, maxVal ) { + } - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); + get x() { - return this; + return this._x; } - clampLength( min, max ) { - - const length = this.length(); + set x( value ) { - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + this._x = value; + this._onChangeCallback(); } - floor() { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); + get y() { - return this; + return this._y; } - ceil() { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); + set y( value ) { - return this; + this._y = value; + this._onChangeCallback(); } - round() { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - this.w = Math.round( this.w ); + get z() { - return this; + return this._z; } - roundToZero() { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); + set z( value ) { - return this; + this._z = value; + this._onChangeCallback(); } - negate() { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - this.w = - this.w; + get w() { - return this; + return this._w; } - dot( v ) { + set w( value ) { - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + this._w = value; + this._onChangeCallback(); } - lengthSq() { - - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + set( x, y, z, w ) { - } + this._x = x; + this._y = y; + this._z = z; + this._w = w; - length() { + this._onChangeCallback(); - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); + return this; } - manhattanLength() { + clone() { - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + return new this.constructor( this._x, this._y, this._z, this._w ); } - normalize() { + copy( quaternion ) { - return this.divideScalar( this.length() || 1 ); + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; + + this._onChangeCallback(); + + return this; } - setLength( length ) { + setFromEuler( euler, update ) { - return this.normalize().multiplyScalar( length ); + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - } + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m - lerp( v, alpha ) { + const cos = Math.cos; + const sin = Math.sin; - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - this.w += ( v.w - this.w ) * alpha; + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); - return this; + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); - } + switch ( order ) { - lerpVectors( v1, v2, alpha ) { + case 'XYZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; - this.w = v1.w + ( v2.w - v1.w ) * alpha; + case 'YXZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - return this; + case 'ZXY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - } + case 'ZYX': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - equals( v ) { + case 'YZX': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); + case 'XZY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - } + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); - fromArray( array, offset = 0 ) { + } - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; + if ( update !== false ) this._onChangeCallback(); return this; } - toArray( array = [], offset = 0 ) { + setFromAxisAngle( axis, angle ) { - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - return array; + // assumes axis is normalized - } + const halfAngle = angle / 2, s = Math.sin( halfAngle ); - fromBufferAttribute( attribute, index ) { + this._x = axis.x * s; + this._y = axis.y * s; + this._z = axis.z * s; + this._w = Math.cos( halfAngle ); - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); + this._onChangeCallback(); return this; } - random() { - - this.x = Math.random(); - this.y = Math.random(); - this.z = Math.random(); - this.w = Math.random(); + setFromRotationMatrix( m ) { - return this; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - } + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - *[ Symbol.iterator ]() { + const te = m.elements, - yield this.x; - yield this.y; - yield this.z; - yield this.w; + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], - } + trace = m11 + m22 + m33; - } + if ( trace > 0 ) { - /* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers - */ - class WebGLRenderTarget extends EventDispatcher { + const s = 0.5 / Math.sqrt( trace + 1.0 ); - constructor( width = 1, height = 1, options = {} ) { + this._w = 0.25 / s; + this._x = ( m32 - m23 ) * s; + this._y = ( m13 - m31 ) * s; + this._z = ( m21 - m12 ) * s; - super(); + } else if ( m11 > m22 && m11 > m33 ) { - this.isWebGLRenderTarget = true; + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - this.width = width; - this.height = height; - this.depth = 1; + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; + } else if ( m22 > m33 ) { - this.viewport = new Vector4( 0, 0, width, height ); + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - const image = { width: width, height: height, depth: 1 }; + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; - this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - this.texture.isRenderTargetTexture = true; + } else { - this.texture.flipY = false; - this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; - this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; - this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; + const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; + this._w = ( m21 - m12 ) / s; + this._x = ( m13 + m31 ) / s; + this._y = ( m23 + m32 ) / s; + this._z = 0.25 * s; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; + } - this.samples = options.samples !== undefined ? options.samples : 0; + this._onChangeCallback(); + + return this; } - setSize( width, height, depth = 1 ) { + setFromUnitVectors( vFrom, vTo ) { - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + // assumes direction vectors vFrom and vTo are normalized - this.width = width; - this.height = height; - this.depth = depth; + let r = vFrom.dot( vTo ) + 1; - this.texture.image.width = width; - this.texture.image.height = height; - this.texture.image.depth = depth; + if ( r < Number.EPSILON ) { - this.dispose(); + // vFrom and vTo point in opposite directions - } + r = 0; - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - } + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; - clone() { + } else { - return new this.constructor().copy( this ); + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; - } + } - copy( source ) { + } else { - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 - this.viewport.copy( source.viewport ); + this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; + this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; + this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; + this._w = r; - this.texture = source.texture.clone(); - this.texture.isRenderTargetTexture = true; + } - // ensure image object is not shared, see #20328 + return this.normalize(); - const image = Object.assign( {}, source.texture.image ); - this.texture.source = new Source( image ); + } - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; + angleTo( q ) { - if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); - this.samples = source.samples; + } + + rotateTowards( q, step ) { + + const angle = this.angleTo( q ); + + if ( angle === 0 ) return this; + + const t = Math.min( 1, step / angle ); + + this.slerp( q, t ); return this; } - dispose() { + identity() { - this.dispatchEvent( { type: 'dispose' } ); + return this.set( 0, 0, 0, 1 ); } - } - - class DataArrayTexture extends Texture { + invert() { - constructor( data = null, width = 1, height = 1, depth = 1 ) { + // quaternion is assumed to have unit length - super( null ); + return this.conjugate(); - this.isDataArrayTexture = true; + } - this.image = { data, width, height, depth }; + conjugate() { - this.magFilter = NearestFilter; - this.minFilter = NearestFilter; + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; - this.wrapR = ClampToEdgeWrapping; + this._onChangeCallback(); - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; } - } + dot( v ) { - class WebGLArrayRenderTarget extends WebGLRenderTarget { + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - constructor( width = 1, height = 1, depth = 1 ) { + } - super( width, height ); + lengthSq() { - this.isWebGLArrayRenderTarget = true; + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; - this.depth = depth; + } - this.texture = new DataArrayTexture( null, width, height, depth ); + length() { - this.texture.isRenderTargetTexture = true; + return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); } - } + normalize() { - class Data3DTexture extends Texture { + let l = this.length(); - constructor( data = null, width = 1, height = 1, depth = 1 ) { + if ( l === 0 ) { - // We're going to add .setXXX() methods for setting properties later. - // Users can still set in DataTexture3D directly. - // - // const texture = new THREE.DataTexture3D( data, width, height, depth ); - // texture.anisotropy = 16; - // - // See #14839 + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; - super( null ); + } else { - this.isData3DTexture = true; + l = 1 / l; - this.image = { data, width, height, depth }; + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; - this.magFilter = NearestFilter; - this.minFilter = NearestFilter; + } - this.wrapR = ClampToEdgeWrapping; + this._onChangeCallback(); - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; } - } - - class WebGL3DRenderTarget extends WebGLRenderTarget { - - constructor( width = 1, height = 1, depth = 1 ) { - - super( width, height ); + multiply( q ) { - this.isWebGL3DRenderTarget = true; + return this.multiplyQuaternions( this, q ); - this.depth = depth; + } - this.texture = new Data3DTexture( null, width, height, depth ); + premultiply( q ) { - this.texture.isRenderTargetTexture = true; + return this.multiplyQuaternions( q, this ); } - } - - class WebGLMultipleRenderTargets extends WebGLRenderTarget { + multiplyQuaternions( a, b ) { - constructor( width = 1, height = 1, count = 1, options = {} ) { + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - super( width, height, options ); + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - this.isWebGLMultipleRenderTargets = true; + this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - const texture = this.texture; + this._onChangeCallback(); - this.texture = []; + return this; - for ( let i = 0; i < count; i ++ ) { + } - this.texture[ i ] = texture.clone(); - this.texture[ i ].isRenderTargetTexture = true; + slerp( qb, t ) { - } + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); - } + const x = this._x, y = this._y, z = this._z, w = this._w; - setSize( width, height, depth = 1 ) { + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - this.width = width; - this.height = height; - this.depth = depth; + if ( cosHalfTheta < 0 ) { - for ( let i = 0, il = this.texture.length; i < il; i ++ ) { + this._w = - qb._w; + this._x = - qb._x; + this._y = - qb._y; + this._z = - qb._z; - this.texture[ i ].image.width = width; - this.texture[ i ].image.height = height; - this.texture[ i ].image.depth = depth; + cosHalfTheta = - cosHalfTheta; - } + } else { - this.dispose(); + this.copy( qb ); } - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + if ( cosHalfTheta >= 1.0 ) { - return this; + this._w = w; + this._x = x; + this._y = y; + this._z = z; - } + return this; - copy( source ) { + } - this.dispose(); + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + if ( sqrSinHalfTheta <= Number.EPSILON ) { - this.viewport.set( 0, 0, this.width, this.height ); - this.scissor.set( 0, 0, this.width, this.height ); + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; + this.normalize(); + this._onChangeCallback(); - if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); + return this; - this.texture.length = 0; + } - for ( let i = 0, il = source.texture.length; i < il; i ++ ) { + const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); + const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); + const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, + ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - this.texture[ i ] = source.texture[ i ].clone(); - this.texture[ i ].isRenderTargetTexture = true; + this._w = ( w * ratioA + this._w * ratioB ); + this._x = ( x * ratioA + this._x * ratioB ); + this._y = ( y * ratioA + this._y * ratioB ); + this._z = ( z * ratioA + this._z * ratioB ); - } + this._onChangeCallback(); return this; } - } + slerpQuaternions( qa, qb, t ) { - class Quaternion { + return this.copy( qa ).slerp( qb, t ); - constructor( x = 0, y = 0, z = 0, w = 1 ) { + } - this.isQuaternion = true; + random() { - this._x = x; - this._y = y; - this._z = z; - this._w = w; + // Derived from http://planning.cs.uiuc.edu/node198.html + // Note, this source uses w, x, y, z ordering, + // so we swap the order below. - } + const u1 = Math.random(); + const sqrt1u1 = Math.sqrt( 1 - u1 ); + const sqrtu1 = Math.sqrt( u1 ); - static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + const u2 = 2 * Math.PI * Math.random(); - // fuzz-free, array-based Quaternion SLERP operation + const u3 = 2 * Math.PI * Math.random(); - let x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ]; + return this.set( + sqrt1u1 * Math.cos( u2 ), + sqrtu1 * Math.sin( u3 ), + sqrtu1 * Math.cos( u3 ), + sqrt1u1 * Math.sin( u2 ), + ); - const x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; + } - if ( t === 0 ) { + equals( quaternion ) { - dst[ dstOffset + 0 ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - return; + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - } + } - if ( t === 1 ) { + fromArray( array, offset = 0 ) { - dst[ dstOffset + 0 ] = x1; - dst[ dstOffset + 1 ] = y1; - dst[ dstOffset + 2 ] = z1; - dst[ dstOffset + 3 ] = w1; - return; + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; - } + this._onChangeCallback(); - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + return this; - let s = 1 - t; - const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; + } - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { + toArray( array = [], offset = 0 ) { - const sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + return array; - } + } - const tDir = t * dir; + fromBufferAttribute( attribute, index ) { - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + return this; - const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + } - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; + toJSON() { - } + return this.toArray(); - } + } - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; + _onChange( callback ) { - } + this._onChangeCallback = callback; - static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { + return this; - const x0 = src0[ srcOffset0 ]; - const y0 = src0[ srcOffset0 + 1 ]; - const z0 = src0[ srcOffset0 + 2 ]; - const w0 = src0[ srcOffset0 + 3 ]; + } - const x1 = src1[ srcOffset1 ]; - const y1 = src1[ srcOffset1 + 1 ]; - const z1 = src1[ srcOffset1 + 2 ]; - const w1 = src1[ srcOffset1 + 3 ]; + _onChangeCallback() {} - dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; - dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; - dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; - dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + *[ Symbol.iterator ]() { - return dst; + yield this._x; + yield this._y; + yield this._z; + yield this._w; } - get x() { + } - return this._x; + class Vector3 { - } + constructor( x = 0, y = 0, z = 0 ) { - set x( value ) { + Vector3.prototype.isVector3 = true; - this._x = value; - this._onChangeCallback(); + this.x = x; + this.y = y; + this.z = z; } - get y() { - - return this._y; + set( x, y, z ) { - } + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) - set y( value ) { + this.x = x; + this.y = y; + this.z = z; - this._y = value; - this._onChangeCallback(); + return this; } - get z() { + setScalar( scalar ) { - return this._z; + this.x = scalar; + this.y = scalar; + this.z = scalar; + + return this; } - set z( value ) { + setX( x ) { - this._z = value; - this._onChangeCallback(); + this.x = x; + + return this; } - get w() { + setY( y ) { - return this._w; + this.y = y; + + return this; } - set w( value ) { + setZ( z ) { - this._w = value; - this._onChangeCallback(); + this.z = z; + + return this; } - set( x, y, z, w ) { + setComponent( index, value ) { - this._x = x; - this._y = y; - this._z = z; - this._w = w; - - this._onChangeCallback(); - - return this; + switch ( index ) { - } + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + default: throw new Error( 'index is out of range: ' + index ); - clone() { + } - return new this.constructor( this._x, this._y, this._z, this._w ); + return this; } - copy( quaternion ) { + getComponent( index ) { - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; + switch ( index ) { - this._onChangeCallback(); + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + default: throw new Error( 'index is out of range: ' + index ); - return this; + } } - setFromEuler( euler, update ) { - - const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m - - const cos = Math.cos; - const sin = Math.sin; + clone() { - const c1 = cos( x / 2 ); - const c2 = cos( y / 2 ); - const c3 = cos( z / 2 ); + return new this.constructor( this.x, this.y, this.z ); - const s1 = sin( x / 2 ); - const s2 = sin( y / 2 ); - const s3 = sin( z / 2 ); + } - switch ( order ) { + copy( v ) { - case 'XYZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + this.x = v.x; + this.y = v.y; + this.z = v.z; - case 'YXZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this; - case 'ZXY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + } - case 'ZYX': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + add( v ) { - case 'YZX': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + this.x += v.x; + this.y += v.y; + this.z += v.z; - case 'XZY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this; - default: - console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); + } - } + addScalar( s ) { - if ( update !== false ) this._onChangeCallback(); + this.x += s; + this.y += s; + this.z += s; return this; } - setFromAxisAngle( axis, angle ) { + addVectors( a, b ) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; - // assumes axis is normalized + return this; - const halfAngle = angle / 2, s = Math.sin( halfAngle ); + } - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); + addScaledVector( v, s ) { - this._onChangeCallback(); + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; return this; } - setFromRotationMatrix( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + sub( v ) { - const te = m.elements, + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], + return this; - trace = m11 + m22 + m33; + } - if ( trace > 0 ) { + subScalar( s ) { - const s = 0.5 / Math.sqrt( trace + 1.0 ); + this.x -= s; + this.y -= s; + this.z -= s; - this._w = 0.25 / s; - this._x = ( m32 - m23 ) * s; - this._y = ( m13 - m31 ) * s; - this._z = ( m21 - m12 ) * s; + return this; - } else if ( m11 > m22 && m11 > m33 ) { + } - const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); + subVectors( a, b ) { - this._w = ( m32 - m23 ) / s; - this._x = 0.25 * s; - this._y = ( m12 + m21 ) / s; - this._z = ( m13 + m31 ) / s; + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; - } else if ( m22 > m33 ) { + return this; - const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + } - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; + multiply( v ) { - } else { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; - const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + return this; - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; + } - } + multiplyScalar( scalar ) { - this._onChangeCallback(); + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; return this; } - setFromUnitVectors( vFrom, vTo ) { - - // assumes direction vectors vFrom and vTo are normalized - - let r = vFrom.dot( vTo ) + 1; + multiplyVectors( a, b ) { - if ( r < Number.EPSILON ) { + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; - // vFrom and vTo point in opposite directions + return this; - r = 0; + } - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + applyEuler( euler ) { - this._x = - vFrom.y; - this._y = vFrom.x; - this._z = 0; - this._w = r; + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - } else { + } - this._x = 0; - this._y = - vFrom.z; - this._z = vFrom.y; - this._w = r; + applyAxisAngle( axis, angle ) { - } + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - } else { + } - // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 + applyMatrix3( m ) { - this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; - this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; - this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; - this._w = r; + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - } + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; + this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - return this.normalize(); + return this; } - angleTo( q ) { + applyNormalMatrix( m ) { - return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); + return this.applyMatrix3( m ).normalize(); } - rotateTowards( q, step ) { - - const angle = this.angleTo( q ); + applyMatrix4( m ) { - if ( angle === 0 ) return this; + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - const t = Math.min( 1, step / angle ); + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - this.slerp( q, t ); + this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; + this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; + this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; return this; } - identity() { - - return this.set( 0, 0, 0, 1 ); + applyQuaternion( q ) { - } + const x = this.x, y = this.y, z = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - invert() { + // calculate quat * vector - // quaternion is assumed to have unit length + const ix = qw * x + qy * z - qz * y; + const iy = qw * y + qz * x - qx * z; + const iz = qw * z + qx * y - qy * x; + const iw = - qx * x - qy * y - qz * z; - return this.conjugate(); + // calculate result * inverse quat - } + this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; + this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; + this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - conjugate() { + return this; - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; + } - this._onChangeCallback(); + project( camera ) { - return this; + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); } - dot( v ) { + unproject( camera ) { - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); } - lengthSq() { + transformDirection( m ) { - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction - } + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - length() { + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); + return this.normalize(); } - normalize() { + divide( v ) { - let l = this.length(); + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; - if ( l === 0 ) { + return this; - this._x = 0; - this._y = 0; - this._z = 0; - this._w = 1; + } - } else { + divideScalar( scalar ) { - l = 1 / l; + return this.multiplyScalar( 1 / scalar ); - this._x = this._x * l; - this._y = this._y * l; - this._z = this._z * l; - this._w = this._w * l; + } - } + min( v ) { - this._onChangeCallback(); + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); return this; } - multiply( q ) { + max( v ) { - return this.multiplyQuaternions( this, q ); + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); - } + return this; - premultiply( q ) { + } - return this.multiplyQuaternions( q, this ); + clamp( min, max ) { - } + // assumes min < max, componentwise - multiplyQuaternions( a, b ) { + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm + return this; - const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; + } - this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + clampScalar( minVal, maxVal ) { - this._onChangeCallback(); + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); return this; } - slerp( qb, t ) { - - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - const x = this._x, y = this._y, z = this._z, w = this._w; + clampLength( min, max ) { - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ + const length = this.length(); - let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - if ( cosHalfTheta < 0 ) { + } - this._w = - qb._w; - this._x = - qb._x; - this._y = - qb._y; - this._z = - qb._z; + floor() { - cosHalfTheta = - cosHalfTheta; + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); - } else { + return this; - this.copy( qb ); + } - } + ceil() { - if ( cosHalfTheta >= 1.0 ) { + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); - this._w = w; - this._x = x; - this._y = y; - this._z = z; + return this; - return this; + } - } + round() { - const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); - if ( sqrSinHalfTheta <= Number.EPSILON ) { + return this; - const s = 1 - t; - this._w = s * w + t * this._w; - this._x = s * x + t * this._x; - this._y = s * y + t * this._y; - this._z = s * z + t * this._z; + } - this.normalize(); - this._onChangeCallback(); + roundToZero() { - return this; + this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); + this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); + this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - } + return this; - const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); - const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; + } - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); + negate() { - this._onChangeCallback(); + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; return this; } - slerpQuaternions( qa, qb, t ) { + dot( v ) { - return this.copy( qa ).slerp( qb, t ); + return this.x * v.x + this.y * v.y + this.z * v.z; } - random() { + // TODO lengthSquared? - // Derived from http://planning.cs.uiuc.edu/node198.html - // Note, this source uses w, x, y, z ordering, - // so we swap the order below. + lengthSq() { - const u1 = Math.random(); - const sqrt1u1 = Math.sqrt( 1 - u1 ); - const sqrtu1 = Math.sqrt( u1 ); + return this.x * this.x + this.y * this.y + this.z * this.z; - const u2 = 2 * Math.PI * Math.random(); + } - const u3 = 2 * Math.PI * Math.random(); + length() { - return this.set( - sqrt1u1 * Math.cos( u2 ), - sqrtu1 * Math.sin( u3 ), - sqrtu1 * Math.cos( u3 ), - sqrt1u1 * Math.sin( u2 ), - ); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); } - equals( quaternion ) { + manhattanLength() { - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); } - fromArray( array, offset = 0 ) { - - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; - - this._onChangeCallback(); + normalize() { - return this; + return this.divideScalar( this.length() || 1 ); } - toArray( array = [], offset = 0 ) { - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; + setLength( length ) { - return array; + return this.normalize().multiplyScalar( length ); } - fromBufferAttribute( attribute, index ) { + lerp( v, alpha ) { - this._x = attribute.getX( index ); - this._y = attribute.getY( index ); - this._z = attribute.getZ( index ); - this._w = attribute.getW( index ); + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; return this; } - _onChange( callback ) { + lerpVectors( v1, v2, alpha ) { - this._onChangeCallback = callback; + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; return this; } - _onChangeCallback() {} - - *[ Symbol.iterator ]() { + cross( v ) { - yield this._x; - yield this._y; - yield this._z; - yield this._w; + return this.crossVectors( this, v ); } - } - - class Vector3 { - - constructor( x = 0, y = 0, z = 0 ) { - - Vector3.prototype.isVector3 = true; - - this.x = x; - this.y = y; - this.z = z; - - } - - set( x, y, z ) { - - if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) - - this.x = x; - this.y = y; - this.z = z; - - return this; - - } - - setScalar( scalar ) { - - this.x = scalar; - this.y = scalar; - this.z = scalar; - - return this; - - } - - setX( x ) { - - this.x = x; - - return this; - - } - - setY( y ) { - - this.y = y; - - return this; - - } - - setZ( z ) { - - this.z = z; - - return this; - - } - - setComponent( index, value ) { - - switch ( index ) { - - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - default: throw new Error( 'index is out of range: ' + index ); - - } - - return this; - - } - - getComponent( index ) { - - switch ( index ) { - - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - default: throw new Error( 'index is out of range: ' + index ); - - } - - } - - clone() { - - return new this.constructor( this.x, this.y, this.z ); - - } - - copy( v ) { - - this.x = v.x; - this.y = v.y; - this.z = v.z; - - return this; - - } - - add( v ) { - - this.x += v.x; - this.y += v.y; - this.z += v.z; - - return this; - - } - - addScalar( s ) { - - this.x += s; - this.y += s; - this.z += s; - - return this; - - } - - addVectors( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - - return this; - - } - - addScaledVector( v, s ) { - - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - - return this; - - } - - sub( v ) { - - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - - return this; - - } - - subScalar( s ) { - - this.x -= s; - this.y -= s; - this.z -= s; - - return this; - - } - - subVectors( a, b ) { - - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - - return this; - - } - - multiply( v ) { - - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - - return this; - - } - - multiplyScalar( scalar ) { - - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - - return this; - - } - - multiplyVectors( a, b ) { - - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; - - return this; - - } - - applyEuler( euler ) { - - return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - - } - - applyAxisAngle( axis, angle ) { - - return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - - } - - applyMatrix3( m ) { - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; - this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - - return this; - - } - - applyNormalMatrix( m ) { - - return this.applyMatrix3( m ).normalize(); - - } - - applyMatrix4( m ) { - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - - this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; - this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; - this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; - - return this; - - } - - applyQuaternion( q ) { - - const x = this.x, y = this.y, z = this.z; - const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vector - - const ix = qw * x + qy * z - qz * y; - const iy = qw * y + qz * x - qx * z; - const iz = qw * z + qx * y - qy * x; - const iw = - qx * x - qy * y - qz * z; - - // calculate result * inverse quat - - this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; - this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; - this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - - return this; - - } - - project( camera ) { - - return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - - } - - unproject( camera ) { - - return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); - - } - - transformDirection( m ) { - - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - - return this.normalize(); - - } - - divide( v ) { - - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; - - return this; - - } - - divideScalar( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - } - - min( v ) { - - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - - return this; - - } - - max( v ) { - - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - - return this; - - } - - clamp( min, max ) { - - // assumes min < max, componentwise - - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - - return this; - - } - - clampScalar( minVal, maxVal ) { - - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - - return this; - - } - - clampLength( min, max ) { - - const length = this.length(); - - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - - } - - floor() { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - - return this; - - } - - ceil() { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - - return this; - - } - - round() { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - - return this; - - } - - roundToZero() { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - - return this; - - } - - negate() { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - - return this; - - } - - dot( v ) { - - return this.x * v.x + this.y * v.y + this.z * v.z; - - } - - // TODO lengthSquared? - - lengthSq() { - - return this.x * this.x + this.y * this.y + this.z * this.z; - - } - - length() { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - - } - - manhattanLength() { - - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); - - } - - normalize() { - - return this.divideScalar( this.length() || 1 ); - - } - - setLength( length ) { - - return this.normalize().multiplyScalar( length ); - - } - - lerp( v, alpha ) { - - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - - return this; - - } - - lerpVectors( v1, v2, alpha ) { - - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; - - return this; - - } - - cross( v ) { - - return this.crossVectors( this, v ); - - } - - crossVectors( a, b ) { + crossVectors( a, b ) { const ax = a.x, ay = a.y, az = a.z; const bx = b.x, by = b.y, bz = b.z; @@ -4773,9 +4353,9 @@ projectOnPlane( planeNormal ) { - _vector$c.copy( this ).projectOnVector( planeNormal ); + _vector$b.copy( this ).projectOnVector( planeNormal ); - return this.sub( _vector$c ); + return this.sub( _vector$b ); } @@ -4784,7 +4364,7 @@ // reflect incident vector off plane orthogonal to normal // normal is assumed to have unit length - return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + return this.sub( _vector$b.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); } @@ -4904,6 +4484,16 @@ } + setFromColor( c ) { + + this.x = c.r; + this.y = c.g; + this.z = c.b; + + return this; + + } + equals( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); @@ -4976,7 +4566,7 @@ } - const _vector$c = /*@__PURE__*/ new Vector3(); + const _vector$b = /*@__PURE__*/ new Vector3(); const _quaternion$4 = /*@__PURE__*/ new Quaternion(); class Box3 { @@ -5001,66 +4591,28 @@ setFromArray( array ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = array.length; i < l; i += 3 ) { - - const x = array[ i ]; - const y = array[ i + 1 ]; - const z = array[ i + 2 ]; + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = array.length; i < il; i += 3 ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector$a.fromArray( array, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } setFromBufferAttribute( attribute ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = attribute.count; i < l; i ++ ) { - - const x = attribute.getX( i ); - const y = attribute.getY( i ); - const z = attribute.getZ( i ); + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = attribute.count; i < il; i ++ ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector$a.fromBufferAttribute( attribute, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } @@ -5081,7 +4633,7 @@ setFromCenterAndSize( center, size ) { - const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); + const halfSize = _vector$a.copy( size ).multiplyScalar( 0.5 ); this.min.copy( center ).sub( halfSize ); this.max.copy( center ).add( halfSize ); @@ -5176,46 +4728,63 @@ object.updateWorldMatrix( false, false ); - const geometry = object.geometry; + if ( object.boundingBox !== undefined ) { - if ( geometry !== undefined ) { + if ( object.boundingBox === null ) { - if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) { + object.computeBoundingBox(); - const position = geometry.attributes.position; - for ( let i = 0, l = position.count; i < l; i ++ ) { + } - _vector$b.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); - this.expandByPoint( _vector$b ); + _box$3.copy( object.boundingBox ); + _box$3.applyMatrix4( object.matrixWorld ); - } + this.union( _box$3 ); - } else { + } else { - if ( geometry.boundingBox === null ) { + const geometry = object.geometry; - geometry.computeBoundingBox(); + if ( geometry !== undefined ) { - } + if ( precise && geometry.attributes !== undefined && geometry.attributes.position !== undefined ) { - _box$3.copy( geometry.boundingBox ); - _box$3.applyMatrix4( object.matrixWorld ); + const position = geometry.attributes.position; + for ( let i = 0, l = position.count; i < l; i ++ ) { - this.union( _box$3 ); + _vector$a.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector$a ); - } + } - } + } else { - const children = object.children; + if ( geometry.boundingBox === null ) { - for ( let i = 0, l = children.length; i < l; i ++ ) { + geometry.computeBoundingBox(); - this.expandByObject( children[ i ], precise ); + } - } + _box$3.copy( geometry.boundingBox ); + _box$3.applyMatrix4( object.matrixWorld ); - return this; + this.union( _box$3 ); + + } + + } + + } + + const children = object.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + this.expandByObject( children[ i ], precise ); + + } + + return this; } @@ -5260,10 +4829,10 @@ intersectsSphere( sphere ) { // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, _vector$b ); + this.clampPoint( sphere.center, _vector$a ); // If that point is inside the sphere, the AABB and sphere intersect. - return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); + return _vector$a.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); } @@ -5375,17 +4944,23 @@ distanceToPoint( point ) { - const clampedPoint = _vector$b.copy( point ).clamp( this.min, this.max ); - - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector$a ).distanceTo( point ); } getBoundingSphere( target ) { - this.getCenter( target.center ); + if ( this.isEmpty() ) { + + target.makeEmpty(); + + } else { + + this.getCenter( target.center ); - target.radius = this.getSize( _vector$b ).length() * 0.5; + target.radius = this.getSize( _vector$a ).length() * 0.5; + + } return target; @@ -5461,7 +5036,7 @@ /*@__PURE__*/ new Vector3() ]; - const _vector$b = /*@__PURE__*/ new Vector3(); + const _vector$a = /*@__PURE__*/ new Vector3(); const _box$3 = /*@__PURE__*/ new Box3(); @@ -5747,7 +5322,7 @@ } - const _vector$a = /*@__PURE__*/ new Vector3(); + const _vector$9 = /*@__PURE__*/ new Vector3(); const _segCenter = /*@__PURE__*/ new Vector3(); const _segDir = /*@__PURE__*/ new Vector3(); const _diff = /*@__PURE__*/ new Vector3(); @@ -5785,7 +5360,7 @@ at( t, target ) { - return target.copy( this.direction ).multiplyScalar( t ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, t ); } @@ -5799,7 +5374,7 @@ recast( t ) { - this.origin.copy( this.at( t, _vector$a ) ); + this.origin.copy( this.at( t, _vector$9 ) ); return this; @@ -5817,7 +5392,7 @@ } - return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); } @@ -5829,7 +5404,7 @@ distanceSqToPoint( point ) { - const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); + const directionDistance = _vector$9.subVectors( point, this.origin ).dot( this.direction ); // point behind the ray @@ -5839,9 +5414,9 @@ } - _vector$a.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + _vector$9.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - return _vector$a.distanceToSquared( point ); + return _vector$9.distanceToSquared( point ); } @@ -5950,13 +5525,13 @@ if ( optionalPointOnRay ) { - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); } if ( optionalPointOnSegment ) { - optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter ); + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); } @@ -5966,9 +5541,9 @@ intersectSphere( sphere, target ) { - _vector$a.subVectors( sphere.center, this.origin ); - const tca = _vector$a.dot( this.direction ); - const d2 = _vector$a.dot( _vector$a ) - tca * tca; + _vector$9.subVectors( sphere.center, this.origin ); + const tca = _vector$9.dot( this.direction ); + const d2 = _vector$9.dot( _vector$9 ) - tca * tca; const radius2 = sphere.radius * sphere.radius; if ( d2 > radius2 ) return null; @@ -5981,8 +5556,8 @@ // t1 = second intersect point - exit point on back of sphere const t1 = tca + thc; - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; // test to see if t0 is behind the ray: // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, @@ -6135,7 +5710,7 @@ intersectsBox( box ) { - return this.intersectBox( box, _vector$a ) !== null; + return this.intersectBox( box, _vector$9 ) !== null; } @@ -6239,7 +5814,7 @@ class Matrix4 { - constructor() { + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { Matrix4.prototype.isMatrix4 = true; @@ -6252,6 +5827,12 @@ ]; + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); + + } + } set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { @@ -6791,14 +6372,29 @@ makeTranslation( x, y, z ) { - this.set( + if ( x.isVector3 ) { - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + this.set( - ); + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 + + ); + + } return this; @@ -7094,7 +6690,7 @@ const _y = /*@__PURE__*/ new Vector3(); const _z = /*@__PURE__*/ new Vector3(); - const _matrix$1 = /*@__PURE__*/ new Matrix4(); + const _matrix = /*@__PURE__*/ new Matrix4(); const _quaternion$3 = /*@__PURE__*/ new Quaternion(); class Euler { @@ -7329,9 +6925,9 @@ setFromQuaternion( q, order, update ) { - _matrix$1.makeRotationFromQuaternion( q ); + _matrix.makeRotationFromQuaternion( q ); - return this.setFromRotationMatrix( _matrix$1, order, update ); + return this.setFromRotationMatrix( _matrix, order, update ); } @@ -8148,7 +7744,7 @@ }; output.metadata = { - version: 4.5, + version: 4.6, type: 'Object', generator: 'Object3D.toJSON' }; @@ -8172,6 +7768,7 @@ object.layers = this.layers.mask; object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; @@ -8399,6 +7996,8 @@ this.frustumCulled = source.frustumCulled; this.renderOrder = source.renderOrder; + this.animations = source.animations; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); if ( recursive === true ) { @@ -8434,6 +8033,8 @@ const _vbp = /*@__PURE__*/ new Vector3(); const _vcp = /*@__PURE__*/ new Vector3(); + let warnedGetUV = false; + class Triangle { constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { @@ -8503,14 +8104,28 @@ } - static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { + static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { // @deprecated, r151 + + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return this.getInterpolation( point, p1, p2, p3, uv1, uv2, uv3, target ); + + } + + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { this.getBarycoord( point, p1, p2, p3, _v3$1 ); - target.set( 0, 0 ); - target.addScaledVector( uv1, _v3$1.x ); - target.addScaledVector( uv2, _v3$1.y ); - target.addScaledVector( uv3, _v3$1.z ); + target.setScalar( 0 ); + target.addScaledVector( v1, _v3$1.x ); + target.addScaledVector( v2, _v3$1.y ); + target.addScaledVector( v3, _v3$1.z ); return target; @@ -8605,9 +8220,23 @@ } - getUV( point, uv1, uv2, uv3, target ) { + getUV( point, uv1, uv2, uv3, target ) { // @deprecated, r151 - return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return Triangle.getInterpolation( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + + } + + getInterpolation( point, v1, v2, v3, target ) { + + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); } @@ -8718,505 +8347,1128 @@ } - let materialId = 0; + let materialId = 0; + + class Material extends EventDispatcher { + + constructor() { + + super(); + + this.isMaterial = true; + + Object.defineProperty( this, 'id', { value: materialId ++ } ); + + this.uuid = generateUUID(); + + this.name = ''; + this.type = 'Material'; + + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; + + this.opacity = 1; + this.transparent = false; + + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; + + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; + + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; + + this.shadowSide = null; + + this.colorWrite = true; + + this.precision = null; // override the renderer's default precision for this material + + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; + + this.dithering = false; + + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.forceSinglePass = false; + + this.visible = true; + + this.toneMapped = true; + + this.userData = {}; + + this.version = 0; + + this._alphaTest = 0; + + } + + get alphaTest() { + + return this._alphaTest; + + } + + set alphaTest( value ) { + + if ( this._alphaTest > 0 !== value > 0 ) { + + this.version ++; + + } + + this._alphaTest = value; + + } + + onBuild( /* shaderobject, renderer */ ) {} + + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + + onBeforeCompile( /* shaderobject, renderer */ ) {} + + customProgramCacheKey() { + + return this.onBeforeCompile.toString(); + + } + + setValues( values ) { + + if ( values === undefined ) return; + + for ( const key in values ) { + + const newValue = values[ key ]; + + if ( newValue === undefined ) { + + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + continue; + + } + + const currentValue = this[ key ]; + + if ( currentValue === undefined ) { + + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + continue; + + } + + if ( currentValue && currentValue.isColor ) { + + currentValue.set( newValue ); + + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + + currentValue.copy( newValue ); + + } else { + + this[ key ] = newValue; + + } + + } + + } + + toJSON( meta ) { + + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( isRootObject ) { + + meta = { + textures: {}, + images: {} + }; + + } + + const data = { + metadata: { + version: 4.6, + type: 'Material', + generator: 'Material.toJSON' + } + }; + + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; + + if ( this.name !== '' ) data.name = this.name; + + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; + + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + + } + + if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; + if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; + if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; + + if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { + + data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; + + } + + if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { + + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; + + } + + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; + + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { + + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; + + } + + if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; + if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; + if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + + if ( this.lightMap && this.lightMap.isTexture ) { + + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; + + } + + if ( this.aoMap && this.aoMap.isTexture ) { + + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; + + } + + if ( this.bumpMap && this.bumpMap.isTexture ) { + + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; + + } + + if ( this.normalMap && this.normalMap.isTexture ) { + + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); + + } + + if ( this.displacementMap && this.displacementMap.isTexture ) { + + data.displacementMap = this.displacementMap.toJSON( meta ).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; + + } + + if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; + if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + + if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; + if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; + if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; + if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + + if ( this.envMap && this.envMap.isTexture ) { + + data.envMap = this.envMap.toJSON( meta ).uuid; + + if ( this.combine !== undefined ) data.combine = this.combine; + + } + + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + + if ( this.gradientMap && this.gradientMap.isTexture ) { + + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + + } + + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors ) data.vertexColors = true; + + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.transparent === true ) data.transparent = this.transparent; + + data.depthFunc = this.depthFunc; + data.depthTest = this.depthTest; + data.depthWrite = this.depthWrite; + data.colorWrite = this.colorWrite; + + data.stencilWrite = this.stencilWrite; + data.stencilWriteMask = this.stencilWriteMask; + data.stencilFunc = this.stencilFunc; + data.stencilRef = this.stencilRef; + data.stencilFuncMask = this.stencilFuncMask; + data.stencilFail = this.stencilFail; + data.stencilZFail = this.stencilZFail; + data.stencilZPass = this.stencilZPass; + + // rotation (SpriteMaterial) + if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; + + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + + if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; + + if ( this.dithering === true ) data.dithering = true; + + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; + if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass; + + if ( this.wireframe === true ) data.wireframe = this.wireframe; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + + if ( this.flatShading === true ) data.flatShading = this.flatShading; + + if ( this.visible === false ) data.visible = false; + + if ( this.toneMapped === false ) data.toneMapped = false; + + if ( this.fog === false ) data.fog = false; + + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + + // TODO: Copied from Object3D.toJSON + + function extractFromCache( cache ) { + + const values = []; + + for ( const key in cache ) { + + const data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + + return values; + + } + + if ( isRootObject ) { + + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; + + } + + return data; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + this.name = source.name; + + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; + + this.opacity = source.opacity; + this.transparent = source.transparent; + + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; + + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; + + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; + + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; + + if ( srcPlanes !== null ) { + + const n = srcPlanes.length; + dstPlanes = new Array( n ); + + for ( let i = 0; i !== n; ++ i ) { + + dstPlanes[ i ] = srcPlanes[ i ].clone(); + + } + + } + + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; + + this.shadowSide = source.shadowSide; + + this.colorWrite = source.colorWrite; + + this.precision = source.precision; + + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; + + this.dithering = source.dithering; + + this.alphaTest = source.alphaTest; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.forceSinglePass = source.forceSinglePass; + + this.visible = source.visible; + + this.toneMapped = source.toneMapped; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + + return this; + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + } + + const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, + 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, + 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, + 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, + 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, + 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, + 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, + 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, + 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, + 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, + 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, + 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, + 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, + 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, + 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, + 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, + 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, + 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, + 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, + 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, + 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, + 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, + 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; + + const _hslA = { h: 0, s: 0, l: 0 }; + const _hslB = { h: 0, s: 0, l: 0 }; + + function hue2rgb( p, q, t ) { + + if ( t < 0 ) t += 1; + if ( t > 1 ) t -= 1; + if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; + if ( t < 1 / 2 ) return q; + if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); + return p; + + } + + class Color { + + constructor( r, g, b ) { + + this.isColor = true; + + this.r = 1; + this.g = 1; + this.b = 1; + + return this.set( r, g, b ); + + } + + set( r, g, b ) { + + if ( g === undefined && b === undefined ) { + + // r is THREE.Color, hex or string + + const value = r; + + if ( value && value.isColor ) { + + this.copy( value ); + + } else if ( typeof value === 'number' ) { + + this.setHex( value ); + + } else if ( typeof value === 'string' ) { + + this.setStyle( value ); + + } + + } else { + + this.setRGB( r, g, b ); + + } + + return this; + + } + + setScalar( scalar ) { + + this.r = scalar; + this.g = scalar; + this.b = scalar; + + return this; + + } + + setHex( hex, colorSpace = SRGBColorSpace ) { + + hex = Math.floor( hex ); + + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { + + this.r = r; + this.g = g; + this.b = b; + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { + + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); + + if ( s === 0 ) { + + this.r = this.g = this.b = l; + + } else { + + const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); + const q = ( 2 * l ) - p; + + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); + + } + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setStyle( style, colorSpace = SRGBColorSpace ) { + + function handleAlpha( string ) { + + if ( string === undefined ) return; + + if ( parseFloat( string ) < 1 ) { + + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + + } + + } + + + let m; + + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { - class Material extends EventDispatcher { + // rgb / hsl - constructor() { + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; - super(); + switch ( name ) { - this.isMaterial = true; + case 'rgb': + case 'rgba': - Object.defineProperty( this, 'id', { value: materialId ++ } ); + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.uuid = generateUUID(); + // rgb(255,0,0) rgba(255,0,0,0.5) - this.name = ''; - this.type = 'Material'; + handleAlpha( color[ 4 ] ); - this.blending = NormalBlending; - this.side = FrontSide; - this.vertexColors = false; + return this.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); - this.opacity = 1; - this.transparent = false; + } - this.blendSrc = SrcAlphaFactor; - this.blendDst = OneMinusSrcAlphaFactor; - this.blendEquation = AddEquation; - this.blendSrcAlpha = null; - this.blendDstAlpha = null; - this.blendEquationAlpha = null; + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.depthFunc = LessEqualDepth; - this.depthTest = true; - this.depthWrite = true; + // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.stencilWriteMask = 0xff; - this.stencilFunc = AlwaysStencilFunc; - this.stencilRef = 0; - this.stencilFuncMask = 0xff; - this.stencilFail = KeepStencilOp; - this.stencilZFail = KeepStencilOp; - this.stencilZPass = KeepStencilOp; - this.stencilWrite = false; + handleAlpha( color[ 4 ] ); - this.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); - this.shadowSide = null; + } - this.colorWrite = true; + break; - this.precision = null; // override the renderer's default precision for this material + case 'hsl': + case 'hsla': - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.dithering = false; + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - this.alphaToCoverage = false; - this.premultipliedAlpha = false; - this.forceSinglePass = false; + handleAlpha( color[ 4 ] ); - this.visible = true; + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); - this.toneMapped = true; + } - this.userData = {}; + break; - this.version = 0; + default: - this._alphaTest = 0; + console.warn( 'THREE.Color: Unknown color model ' + style ); - } + } - get alphaTest() { + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { - return this._alphaTest; + // hex color - } + const hex = m[ 1 ]; + const size = hex.length; - set alphaTest( value ) { + if ( size === 3 ) { - if ( this._alphaTest > 0 !== value > 0 ) { + // #ff0 + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); - this.version ++; + } else if ( size === 6 ) { - } + // #ff0000 + return this.setHex( parseInt( hex, 16 ), colorSpace ); - this._alphaTest = value; + } else { - } + console.warn( 'THREE.Color: Invalid hex color ' + style ); - onBuild( /* shaderobject, renderer */ ) {} + } - onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + } else if ( style && style.length > 0 ) { - onBeforeCompile( /* shaderobject, renderer */ ) {} + return this.setColorName( style, colorSpace ); - customProgramCacheKey() { + } - return this.onBeforeCompile.toString(); + return this; } - setValues( values ) { + setColorName( style, colorSpace = SRGBColorSpace ) { - if ( values === undefined ) return; + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; - for ( const key in values ) { + if ( hex !== undefined ) { - const newValue = values[ key ]; + // red + this.setHex( hex, colorSpace ); - if ( newValue === undefined ) { + } else { - console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' ); - continue; + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); - } + } - const currentValue = this[ key ]; + return this; - if ( currentValue === undefined ) { + } - console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' ); - continue; + clone() { - } + return new this.constructor( this.r, this.g, this.b ); - if ( currentValue && currentValue.isColor ) { + } - currentValue.set( newValue ); + copy( color ) { - } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + this.r = color.r; + this.g = color.g; + this.b = color.b; - currentValue.copy( newValue ); + return this; - } else { + } - this[ key ] = newValue; + copySRGBToLinear( color ) { - } + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); - } + return this; } - toJSON( meta ) { + copyLinearToSRGB( color ) { - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); - if ( isRootObject ) { + return this; - meta = { - textures: {}, - images: {} - }; + } - } + convertSRGBToLinear() { - const data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' - } - }; + this.copySRGBToLinear( this ); - // standard Material serialization - data.uuid = this.uuid; - data.type = this.type; + return this; - if ( this.name !== '' ) data.name = this.name; + } - if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + convertLinearToSRGB() { - if ( this.roughness !== undefined ) data.roughness = this.roughness; - if ( this.metalness !== undefined ) data.metalness = this.metalness; + this.copyLinearToSRGB( this ); - if ( this.sheen !== undefined ) data.sheen = this.sheen; - if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); - if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; - if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); - if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + return this; - if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); - if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; - if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); - if ( this.shininess !== undefined ) data.shininess = this.shininess; - if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; - if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + } - if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + getHex( colorSpace = SRGBColorSpace ) { - data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - } + return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color.b * 255, 0, 255 ) ); - if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + } - data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + getHexString( colorSpace = SRGBColorSpace ) { - } + return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); - if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + } - data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; - data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { - } + // h,s,l ranges are in 0.0 - 1.0 - if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; - if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; - if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { + const r = _color.r, g = _color.g, b = _color.b; - data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); - } + let hue, saturation; + const lightness = ( min + max ) / 2.0; - if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { + if ( min === max ) { - data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; + hue = 0; + saturation = 0; - } + } else { - if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; - if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; - if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + const delta = max - min; - if ( this.lightMap && this.lightMap.isTexture ) { + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - data.lightMap = this.lightMap.toJSON( meta ).uuid; - data.lightMapIntensity = this.lightMapIntensity; + switch ( max ) { - } + case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; + case g: hue = ( b - r ) / delta + 2; break; + case b: hue = ( r - g ) / delta + 4; break; - if ( this.aoMap && this.aoMap.isTexture ) { + } - data.aoMap = this.aoMap.toJSON( meta ).uuid; - data.aoMapIntensity = this.aoMapIntensity; + hue /= 6; } - if ( this.bumpMap && this.bumpMap.isTexture ) { - - data.bumpMap = this.bumpMap.toJSON( meta ).uuid; - data.bumpScale = this.bumpScale; + target.h = hue; + target.s = saturation; + target.l = lightness; - } + return target; - if ( this.normalMap && this.normalMap.isTexture ) { + } - data.normalMap = this.normalMap.toJSON( meta ).uuid; - data.normalMapType = this.normalMapType; - data.normalScale = this.normalScale.toArray(); + getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { - } + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.displacementMap && this.displacementMap.isTexture ) { + target.r = _color.r; + target.g = _color.g; + target.b = _color.b; - data.displacementMap = this.displacementMap.toJSON( meta ).uuid; - data.displacementScale = this.displacementScale; - data.displacementBias = this.displacementBias; + return target; - } + } - if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; - if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + getStyle( colorSpace = SRGBColorSpace ) { - if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; - if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; - if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; - if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.envMap && this.envMap.isTexture ) { + const r = _color.r, g = _color.g, b = _color.b; - data.envMap = this.envMap.toJSON( meta ).uuid; + if ( colorSpace !== SRGBColorSpace ) { - if ( this.combine !== undefined ) data.combine = this.combine; + // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; } - if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; - if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; - if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; - if ( this.gradientMap && this.gradientMap.isTexture ) { + } - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + offsetHSL( h, s, l ) { - } + this.getHSL( _hslA ); - if ( this.transmission !== undefined ) data.transmission = this.transmission; - if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; - if ( this.thickness !== undefined ) data.thickness = this.thickness; - if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; - if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; - if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + _hslA.h += h; _hslA.s += s; _hslA.l += l; - if ( this.size !== undefined ) data.size = this.size; - if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; - if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + this.setHSL( _hslA.h, _hslA.s, _hslA.l ); - if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.side !== FrontSide ) data.side = this.side; - if ( this.vertexColors ) data.vertexColors = true; + return this; - if ( this.opacity < 1 ) data.opacity = this.opacity; - if ( this.transparent === true ) data.transparent = this.transparent; + } - data.depthFunc = this.depthFunc; - data.depthTest = this.depthTest; - data.depthWrite = this.depthWrite; - data.colorWrite = this.colorWrite; + add( color ) { - data.stencilWrite = this.stencilWrite; - data.stencilWriteMask = this.stencilWriteMask; - data.stencilFunc = this.stencilFunc; - data.stencilRef = this.stencilRef; - data.stencilFuncMask = this.stencilFuncMask; - data.stencilFail = this.stencilFail; - data.stencilZFail = this.stencilZFail; - data.stencilZPass = this.stencilZPass; + this.r += color.r; + this.g += color.g; + this.b += color.b; - // rotation (SpriteMaterial) - if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; + return this; - if ( this.polygonOffset === true ) data.polygonOffset = true; - if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; - if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + } - if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; - if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; - if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; - if ( this.scale !== undefined ) data.scale = this.scale; + addColors( color1, color2 ) { - if ( this.dithering === true ) data.dithering = true; + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; - if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; - if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; - if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; - if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass; + return this; - if ( this.wireframe === true ) data.wireframe = this.wireframe; - if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; - if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; - if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + } - if ( this.flatShading === true ) data.flatShading = this.flatShading; + addScalar( s ) { - if ( this.visible === false ) data.visible = false; + this.r += s; + this.g += s; + this.b += s; - if ( this.toneMapped === false ) data.toneMapped = false; + return this; - if ( this.fog === false ) data.fog = false; + } - if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + sub( color ) { - // TODO: Copied from Object3D.toJSON + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); - function extractFromCache( cache ) { + return this; - const values = []; + } - for ( const key in cache ) { + multiply( color ) { - const data = cache[ key ]; - delete data.metadata; - values.push( data ); + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; - } + return this; - return values; + } - } + multiplyScalar( s ) { - if ( isRootObject ) { + this.r *= s; + this.g *= s; + this.b *= s; - const textures = extractFromCache( meta.textures ); - const images = extractFromCache( meta.images ); + return this; -<<<<<<< HEAD - var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, worldNormal );\n\t\t\t#endif\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\t#else\n\t\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec );\n\t\t\t#endif\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif"; -======= - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; ->>>>>>> mrdoob-dev + } - } + lerp( color, alpha ) { - return data; + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; + + return this; } - clone() { + lerpColors( color1, color2, alpha ) { - return new this.constructor().copy( this ); + this.r = color1.r + ( color2.r - color1.r ) * alpha; + this.g = color1.g + ( color2.g - color1.g ) * alpha; + this.b = color1.b + ( color2.b - color1.b ) * alpha; + + return this; } - copy( source ) { + lerpHSL( color, alpha ) { -<<<<<<< HEAD - var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && ( defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE ) )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; -======= - this.name = source.name; ->>>>>>> mrdoob-dev + this.getHSL( _hslA ); + color.getHSL( _hslB ); - this.blending = source.blending; - this.side = source.side; - this.vertexColors = source.vertexColors; + const h = lerp( _hslA.h, _hslB.h, alpha ); + const s = lerp( _hslA.s, _hslB.s, alpha ); + const l = lerp( _hslA.l, _hslB.l, alpha ); - this.opacity = source.opacity; - this.transparent = source.transparent; + this.setHSL( h, s, l ); - this.blendSrc = source.blendSrc; - this.blendDst = source.blendDst; - this.blendEquation = source.blendEquation; - this.blendSrcAlpha = source.blendSrcAlpha; - this.blendDstAlpha = source.blendDstAlpha; - this.blendEquationAlpha = source.blendEquationAlpha; + return this; - this.depthFunc = source.depthFunc; - this.depthTest = source.depthTest; - this.depthWrite = source.depthWrite; + } - this.stencilWriteMask = source.stencilWriteMask; - this.stencilFunc = source.stencilFunc; - this.stencilRef = source.stencilRef; - this.stencilFuncMask = source.stencilFuncMask; - this.stencilFail = source.stencilFail; - this.stencilZFail = source.stencilZFail; - this.stencilZPass = source.stencilZPass; - this.stencilWrite = source.stencilWrite; + setFromVector3( v ) { - const srcPlanes = source.clippingPlanes; - let dstPlanes = null; + this.r = v.x; + this.g = v.y; + this.b = v.z; - if ( srcPlanes !== null ) { + return this; - const n = srcPlanes.length; - dstPlanes = new Array( n ); + } - for ( let i = 0; i !== n; ++ i ) { + applyMatrix3( m ) { - dstPlanes[ i ] = srcPlanes[ i ].clone(); + const r = this.r, g = this.g, b = this.b; + const e = m.elements; - } + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; - } + return this; - this.clippingPlanes = dstPlanes; - this.clipIntersection = source.clipIntersection; - this.clipShadows = source.clipShadows; + } - this.shadowSide = source.shadowSide; + equals( c ) { - this.colorWrite = source.colorWrite; + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); - this.precision = source.precision; + } - this.polygonOffset = source.polygonOffset; - this.polygonOffsetFactor = source.polygonOffsetFactor; - this.polygonOffsetUnits = source.polygonOffsetUnits; + fromArray( array, offset = 0 ) { - this.dithering = source.dithering; + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; - this.alphaTest = source.alphaTest; - this.alphaToCoverage = source.alphaToCoverage; - this.premultipliedAlpha = source.premultipliedAlpha; - this.forceSinglePass = source.forceSinglePass; + return this; - this.visible = source.visible; + } - this.toneMapped = source.toneMapped; + toArray( array = [], offset = 0 ) { - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); return this; } - dispose() { + toJSON() { - this.dispatchEvent( { type: 'dispose' } ); + return this.getHex(); } - set needsUpdate( value ) { + *[ Symbol.iterator ]() { - if ( value === true ) this.version ++; + yield this.r; + yield this.g; + yield this.b; } } + const _color = /*@__PURE__*/ new Color(); + + Color.NAMES = _colorKeywords; + class MeshBasicMaterial extends Material { constructor( parameters ) { @@ -9293,7 +9545,176 @@ } - const _vector$9 = /*@__PURE__*/ new Vector3(); + // Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + + const _tables = /*@__PURE__*/ _generateTables(); + + function _generateTables() { + + // float32 to float16 helpers + + const buffer = new ArrayBuffer( 4 ); + const floatView = new Float32Array( buffer ); + const uint32View = new Uint32Array( buffer ); + + const baseTable = new Uint32Array( 512 ); + const shiftTable = new Uint32Array( 512 ); + + for ( let i = 0; i < 256; ++ i ) { + + const e = i - 127; + + // very small number (0, -0) + + if ( e < - 27 ) { + + baseTable[ i ] = 0x0000; + baseTable[ i | 0x100 ] = 0x8000; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // small number (denorm) + + } else if ( e < - 14 ) { + + baseTable[ i ] = 0x0400 >> ( - e - 14 ); + baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; + shiftTable[ i ] = - e - 1; + shiftTable[ i | 0x100 ] = - e - 1; + + // normal number + + } else if ( e <= 15 ) { + + baseTable[ i ] = ( e + 15 ) << 10; + baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + // large number (Infinity, -Infinity) + + } else if ( e < 128 ) { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // stay (NaN, Infinity, -Infinity) + + } else { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + } + + } + + // float16 to float32 helpers + + const mantissaTable = new Uint32Array( 2048 ); + const exponentTable = new Uint32Array( 64 ); + const offsetTable = new Uint32Array( 64 ); + + for ( let i = 1; i < 1024; ++ i ) { + + let m = i << 13; // zero pad mantissa bits + let e = 0; // zero exponent + + // normalized + while ( ( m & 0x00800000 ) === 0 ) { + + m <<= 1; + e -= 0x00800000; // decrement exponent + + } + + m &= ~ 0x00800000; // clear leading 1 bit + e += 0x38800000; // adjust bias + + mantissaTable[ i ] = m | e; + + } + + for ( let i = 1024; i < 2048; ++ i ) { + + mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); + + } + + for ( let i = 1; i < 31; ++ i ) { + + exponentTable[ i ] = i << 23; + + } + + exponentTable[ 31 ] = 0x47800000; + exponentTable[ 32 ] = 0x80000000; + + for ( let i = 33; i < 63; ++ i ) { + + exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); + + } + + exponentTable[ 63 ] = 0xc7800000; + + for ( let i = 1; i < 64; ++ i ) { + + if ( i !== 32 ) { + + offsetTable[ i ] = 1024; + + } + + } + + return { + floatView: floatView, + uint32View: uint32View, + baseTable: baseTable, + shiftTable: shiftTable, + mantissaTable: mantissaTable, + exponentTable: exponentTable, + offsetTable: offsetTable + }; + + } + + // float32 to float16 + + function toHalfFloat( val ) { + + if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); + + val = clamp( val, - 65504, 65504 ); + + _tables.floatView[ 0 ] = val; + const f = _tables.uint32View[ 0 ]; + const e = ( f >> 23 ) & 0x1ff; + return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); + + } + + // float16 to float32 + + function fromHalfFloat( val ) { + + const m = val >> 10; + _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; + return _tables.floatView[ 0 ]; + + } + + const DataUtils = { + toHalfFloat: toHalfFloat, + fromHalfFloat: fromHalfFloat, + }; + + const _vector$8 = /*@__PURE__*/ new Vector3(); const _vector2$1 = /*@__PURE__*/ new Vector2(); class BufferAttribute { @@ -9302,12 +9723,7 @@ if ( Array.isArray( array ) ) { -<<<<<<< HEAD - const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; - const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -======= throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); ->>>>>>> mrdoob-dev } @@ -9397,10 +9813,10 @@ for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); - _vector$9.applyMatrix3( m ); + _vector$8.fromBufferAttribute( this, i ); + _vector$8.applyMatrix3( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9414,11 +9830,11 @@ for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.applyMatrix4( m ); + _vector$8.applyMatrix4( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9430,11 +9846,11 @@ for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.applyNormalMatrix( m ); + _vector$8.applyNormalMatrix( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9446,11 +9862,11 @@ for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.transformDirection( m ); + _vector$8.transformDirection( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9638,27 +10054,25 @@ } - // @deprecated - - copyColorsArray() { + copyColorsArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyColorsArray() was removed in r144.' ); } - copyVector2sArray() { + copyVector2sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector2sArray() was removed in r144.' ); } - copyVector3sArray() { + copyVector3sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector3sArray() was removed in r144.' ); } - copyVector4sArray() { + copyVector4sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector4sArray() was removed in r144.' ); @@ -9674,6 +10088,18 @@ super( new Int8Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9684,6 +10110,18 @@ super( new Uint8Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9704,6 +10142,18 @@ super( new Int16Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9714,6 +10164,18 @@ super( new Uint16Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9748,6 +10210,146 @@ } + getX( index ) { + + let x = fromHalfFloat( this.array[ index * this.itemSize ] ); + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; + + } + + setX( index, x ) { + + if ( this.normalized ) x = normalize( x, this.array ); + + this.array[ index * this.itemSize ] = toHalfFloat( x ); + + return this; + + } + + getY( index ) { + + let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; + + } + + setY( index, y ) { + + if ( this.normalized ) y = normalize( y, this.array ); + + this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); + + return this; + + } + + getZ( index ) { + + let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; + + } + + setZ( index, z ) { + + if ( this.normalized ) z = normalize( z, this.array ); + + this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); + + return this; + + } + + getW( index ) { + + let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; + + } + + setW( index, w ) { + + if ( this.normalized ) w = normalize( w, this.array ); + + this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); + + return this; + + } + + setXY( index, x, y ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + + return this; + + } + + setXYZ( index, x, y, z ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + + return this; + + } + + setXYZW( index, x, y, z, w ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + this.array[ index + 3 ] = toHalfFloat( w ); + + return this; + + } + } @@ -9771,20 +10373,6 @@ } -<<<<<<< HEAD - fromScene(scene, sigma = 0, near = 0.1, far = 100, cubeUVRenderTarget = null, pingPongRenderTarget = null) { - _oldTarget = this._renderer.getRenderTarget(); - - if (!cubeUVRenderTarget) { - cubeUVRenderTarget = this._allocateTargets(); - } - - if (pingPongRenderTarget) { - this._pingPongRenderTarget = pingPongRenderTarget; - } - - this._setSize(256); -======= let _id$1 = 0; const _m1 = /*@__PURE__*/ new Matrix4(); @@ -9792,10 +10380,9 @@ const _offset = /*@__PURE__*/ new Vector3(); const _box$1 = /*@__PURE__*/ new Box3(); const _boxMorphTargets = /*@__PURE__*/ new Box3(); - const _vector$8 = /*@__PURE__*/ new Vector3(); + const _vector$7 = /*@__PURE__*/ new Vector3(); class BufferGeometry extends EventDispatcher { ->>>>>>> mrdoob-dev constructor() { @@ -9807,60 +10394,8 @@ this.uuid = generateUUID(); -<<<<<<< HEAD - return cubeUVRenderTarget; - } - - prepareForRenderTarget(cubeUVRenderTarget, pingPongRenderTarget = null, cubeSize = 256) { - this._setSize(cubeSize); - - const { - _lodMax - } = this; - ({ - sizeLods: this._sizeLods, - lodPlanes: this._lodPlanes, - sigmas: this._sigmas - } = _createPlanes(_lodMax)); - const width = 3 * Math.max(this._cubeSize, 16 * 7); - const height = 4 * this._cubeSize; - this._blurMaterial = _getBlurShader(_lodMax, width, height); - cubeUVRenderTarget.setSize(width, height); - - if (pingPongRenderTarget) { - pingPongRenderTarget.setSize(width, height); - } - } - - fromSceneToRenderTarget(scene, cubeUVRenderTarget, pingPongRenderTarget, sigma = 0, near = 0.1, far = 100) { - _oldTarget = this._renderer.getRenderTarget(); - this._pingPongRenderTarget = pingPongRenderTarget; - - this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget); - - if (sigma > 0) { - this._blur(cubeUVRenderTarget, 0, 0, sigma); - } - - this._applyPMREM(cubeUVRenderTarget); - - this._renderer.setRenderTarget(_oldTarget); - - cubeUVRenderTarget.scissorTest = false; - - _setViewport(cubeUVRenderTarget, 0, 0, cubeUVRenderTarget.width, cubeUVRenderTarget.height); - - return cubeUVRenderTarget; - } - /** - * Generates a PMREM from an equirectangular texture, which can be either LDR - * or HDR. The ideal input image size is 1k (1024 x 512), - * as this matches best with the 256 x 256 cubemap output. - */ -======= this.name = ''; this.type = 'BufferGeometry'; ->>>>>>> mrdoob-dev this.index = null; this.attributes = {}; @@ -10107,22 +10642,7 @@ const point = points[ i ]; position.push( point.x, point.y, point.z || 0 ); -<<<<<<< HEAD - mat3 getRotationMatrix(vec3 axis, float angle) { - axis = normalize(axis); - float s = sin(angle); - float c = cos(angle); - float oc = 1.0 - c; - - return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, - oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); - } - // RH coordinate system; PMREM face-indexing convention - vec3 getDirection( vec2 uv, float face ) { -======= } ->>>>>>> mrdoob-dev this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); @@ -10156,16 +10676,9 @@ if ( position !== undefined ) { -<<<<<<< HEAD - } - mat3 rotationMatrix = getRotationMatrix(vec3(1.0, 0.0, 0.0), 1.57); - direction = rotationMatrix * direction; - return direction; -======= this.boundingBox.setFromBufferAttribute( position ); // process morph attributes if present ->>>>>>> mrdoob-dev if ( morphAttributesPosition ) { @@ -10176,11 +10689,11 @@ if ( this.morphTargetsRelative ) { - _vector$8.addVectors( this.boundingBox.min, _box$1.min ); - this.boundingBox.expandByPoint( _vector$8 ); + _vector$7.addVectors( this.boundingBox.min, _box$1.min ); + this.boundingBox.expandByPoint( _vector$7 ); - _vector$8.addVectors( this.boundingBox.max, _box$1.max ); - this.boundingBox.expandByPoint( _vector$8 ); + _vector$7.addVectors( this.boundingBox.max, _box$1.max ); + this.boundingBox.expandByPoint( _vector$7 ); } else { @@ -10247,11 +10760,11 @@ if ( this.morphTargetsRelative ) { - _vector$8.addVectors( _box$1.min, _boxMorphTargets.min ); - _box$1.expandByPoint( _vector$8 ); + _vector$7.addVectors( _box$1.min, _boxMorphTargets.min ); + _box$1.expandByPoint( _vector$7 ); - _vector$8.addVectors( _box$1.max, _boxMorphTargets.max ); - _box$1.expandByPoint( _vector$8 ); + _vector$7.addVectors( _box$1.max, _boxMorphTargets.max ); + _box$1.expandByPoint( _vector$7 ); } else { @@ -10273,9 +10786,9 @@ for ( let i = 0, il = position.count; i < il; i ++ ) { - _vector$8.fromBufferAttribute( position, i ); + _vector$7.fromBufferAttribute( position, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) ); } @@ -10290,16 +10803,16 @@ for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { - _vector$8.fromBufferAttribute( morphAttribute, j ); + _vector$7.fromBufferAttribute( morphAttribute, j ); if ( morphTargetsRelative ) { _offset.fromBufferAttribute( position, j ); - _vector$8.add( _offset ); + _vector$7.add( _offset ); } - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) ); } @@ -10576,11 +11089,9 @@ } - // @deprecated since r144 - - merge() { + merge() { // @deprecated, r144 - console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeBufferGeometries() instead.' ); + console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeGeometries() instead.' ); return this; } @@ -10591,11 +11102,11 @@ for ( let i = 0, il = normals.count; i < il; i ++ ) { - _vector$8.fromBufferAttribute( normals, i ); + _vector$7.fromBufferAttribute( normals, i ); - _vector$8.normalize(); + _vector$7.normalize(); - normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); + normals.setXYZ( i, _vector$7.x, _vector$7.y, _vector$7.z ); } @@ -10707,7 +11218,7 @@ const data = { metadata: { - version: 4.5, + version: 4.6, type: 'BufferGeometry', generator: 'BufferGeometry.toJSON' } @@ -10923,10 +11434,6 @@ this.userData = source.userData; - // geometry generator parameters - - if ( source.parameters !== undefined ) this.parameters = Object.assign( {}, source.parameters ); - return this; } @@ -10939,9 +11446,10 @@ } - const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); - const _ray$2 = /*@__PURE__*/ new Ray(); - const _sphere$3 = /*@__PURE__*/ new Sphere(); + const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); + const _ray$3 = /*@__PURE__*/ new Ray(); + const _sphere$5 = /*@__PURE__*/ new Sphere(); + const _sphereHitAt = /*@__PURE__*/ new Vector3(); const _vA$1 = /*@__PURE__*/ new Vector3(); const _vB$1 = /*@__PURE__*/ new Vector3(); @@ -10950,16 +11458,13 @@ const _tempA = /*@__PURE__*/ new Vector3(); const _morphA = /*@__PURE__*/ new Vector3(); -<<<<<<< HEAD - for (let i = from; i < to; i++) { - const line = i + 1; - lines2.push(`${line === errorLine ? '>' : ' '} ${line}: ${lines[i]}`); - } -======= const _uvA$1 = /*@__PURE__*/ new Vector2(); const _uvB$1 = /*@__PURE__*/ new Vector2(); const _uvC$1 = /*@__PURE__*/ new Vector2(); ->>>>>>> mrdoob-dev + + const _normalA = /*@__PURE__*/ new Vector3(); + const _normalB = /*@__PURE__*/ new Vector3(); + const _normalC = /*@__PURE__*/ new Vector3(); const _intersectionPoint = /*@__PURE__*/ new Vector3(); const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); @@ -10972,19 +11477,7 @@ this.isMesh = true; -<<<<<<< HEAD - if (errorMatches) { - // --enable-privileged-webgl-extension - // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - const errorLine = parseInt(errorMatches[1]); - return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource(gl.getShaderSource(shader), errorLine); - } else { - return errors; - } - } -======= this.type = 'Mesh'; ->>>>>>> mrdoob-dev this.geometry = geometry; this.material = material; @@ -11087,12 +11580,6 @@ } - if ( this.isSkinnedMesh ) { - - this.boneTransform( index, target ); - - } - return target; } @@ -11105,83 +11592,58 @@ if ( material === undefined ) return; - // Checking boundingSphere distance to ray + // test with bounding sphere in world space if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - _sphere$3.copy( geometry.boundingSphere ); - _sphere$3.applyMatrix4( matrixWorld ); - - if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; + _sphere$5.copy( geometry.boundingSphere ); + _sphere$5.applyMatrix4( matrixWorld ); - // + // check distance from ray origin to bounding sphere - _inverseMatrix$2.copy( matrixWorld ).invert(); - _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); + _ray$3.copy( raycaster.ray ).recast( raycaster.near ); - // Check boundingBox before continuing + if ( _sphere$5.containsPoint( _ray$3.origin ) === false ) { - if ( geometry.boundingBox !== null ) { + if ( _ray$3.intersectSphere( _sphere$5, _sphereHitAt ) === null ) return; - if ( _ray$2.intersectsBox( geometry.boundingBox ) === false ) return; + if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; } -<<<<<<< HEAD - } else { - prefixVertex = [generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.skinning ? '#define USE_SKINNING' : '', parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', parameters.morphColors && parameters.isWebGL2 ? '#define USE_MORPHCOLORS' : '', parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE' : '', parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', '#ifdef USE_INSTANCING', ' attribute mat4 instanceMatrix;', '#endif', '#ifdef USE_INSTANCING_COLOR', ' attribute vec3 instanceColor;', '#endif', 'attribute vec3 position;', 'attribute vec3 normal;', 'attribute vec2 uv;', '#ifdef USE_TANGENT', ' attribute vec4 tangent;', '#endif', '#if defined( USE_COLOR_ALPHA )', ' attribute vec4 color;', '#elif defined( USE_COLOR )', ' attribute vec3 color;', '#endif', '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )', ' attribute vec3 morphTarget0;', ' attribute vec3 morphTarget1;', ' attribute vec3 morphTarget2;', ' attribute vec3 morphTarget3;', ' #ifdef USE_MORPHNORMALS', ' attribute vec3 morphNormal0;', ' attribute vec3 morphNormal1;', ' attribute vec3 morphNormal2;', ' attribute vec3 morphNormal3;', ' #else', ' attribute vec3 morphTarget4;', ' attribute vec3 morphTarget5;', ' attribute vec3 morphTarget6;', ' attribute vec3 morphTarget7;', ' #endif', '#endif', '#ifdef USE_SKINNING', ' attribute vec4 skinIndex;', ' attribute vec4 skinWeight;', '#endif', '\n'].filter(filterEmptyLine).join('\n'); - prefixFragment = [customExtensions, generatePrecision(parameters), '#define SHADER_NAME ' + parameters.shaderName, customDefines, parameters.useFog && parameters.fog ? '#define USE_FOG' : '', parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapTypeDefine : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.envMap ? '#define ' + envMapBlendingDefine : '', envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '', envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '', envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '', parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', parameters.iridescence ? '#define USE_IRIDESCENCE' : '', parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUvs ? '#define USE_UV' : '', parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', 'uniform bool isOrthographic;', parameters.toneMapping !== NoToneMapping ? '#define TONE_MAPPING' : '', parameters.toneMapping !== NoToneMapping ? ShaderChunk['tonemapping_pars_fragment'] : '', // this code is required here because it is used by the toneMapping() function defined below - parameters.toneMapping !== NoToneMapping ? getToneMappingFunction('toneMapping', parameters.toneMapping) : '', parameters.dithering ? '#define DITHERING' : '', parameters.opaque ? '#define OPAQUE' : '', ShaderChunk['encodings_pars_fragment'], // this code is required here because it is used by the various encoding/decoding function defined below - getTexelEncodingFunction('linearToOutputTexel', parameters.outputEncoding), parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', '\n'].filter(filterEmptyLine).join('\n'); - } - if (renderer.onShaderBeforeResolve) { - const ret = renderer.onShaderBeforeResolve(vertexShader, fragmentShader, parameters); - vertexShader = ret.vertexShader; - fragmentShader = ret.fragmentShader; - } + // convert ray to local space of mesh - vertexShader = resolveIncludes(vertexShader); - vertexShader = replaceLightNums(vertexShader, parameters); - vertexShader = replaceClippingPlaneNums(vertexShader, parameters); - fragmentShader = resolveIncludes(fragmentShader); - fragmentShader = replaceLightNums(fragmentShader, parameters); - fragmentShader = replaceClippingPlaneNums(fragmentShader, parameters); - vertexShader = unrollLoops(vertexShader); - fragmentShader = unrollLoops(fragmentShader); + _inverseMatrix$3.copy( matrixWorld ).invert(); + _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); - if (parameters.isWebGL2 && parameters.isRawShaderMaterial !== true) { - // GLSL 3.0 conversion for built-in materials and ShaderMaterial - versionString = '#version 300 es\n'; - prefixVertex = ['precision mediump sampler2DArray;', '#define attribute in', '#define varying out', '#define texture2D texture'].join('\n') + '\n' + prefixVertex; - prefixFragment = ['#define varying in', parameters.glslVersion === GLSL3 ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', parameters.glslVersion === GLSL3 ? '' : '#define gl_FragColor pc_fragColor', '#define gl_FragDepthEXT gl_FragDepth', '#define texture2D texture', '#define textureCube texture', '#define texture2DProj textureProj', '#define texture2DLodEXT textureLod', '#define texture2DProjLodEXT textureProjLod', '#define textureCubeLodEXT textureLod', '#define texture2DGradEXT textureGrad', '#define texture2DProjGradEXT textureProjGrad', '#define textureCubeGradEXT textureGrad'].join('\n') + '\n' + prefixFragment; - } + // test with bounding box in local space - let vertexGlsl = versionString + prefixVertex + vertexShader; - let fragmentGlsl = versionString + prefixFragment + fragmentShader; + if ( geometry.boundingBox !== null ) { - if (renderer.onShaderBeforeCompile) { - const ret = renderer.onShaderBeforeCompile(vertexGlsl, fragmentGlsl, parameters); - vertexGlsl = ret.vertexShader; - fragmentGlsl = ret.fragmentShader; - } // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); + if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; + } - const glVertexShader = WebGLShader(gl, gl.VERTEX_SHADER, vertexGlsl); - const glFragmentShader = WebGLShader(gl, gl.FRAGMENT_SHADER, fragmentGlsl); - gl.attachShader(program, glVertexShader); - gl.attachShader(program, glFragmentShader); // Force a particular attribute to index 0. -======= + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$3 ); + + } + + _computeIntersections( raycaster, intersects, rayLocalSpace ) { let intersection; + const geometry = this.geometry; + const material = this.material; + const index = geometry.index; const position = geometry.attributes.position; const uv = geometry.attributes.uv; - const uv2 = geometry.attributes.uv2; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; const groups = geometry.groups; const drawRange = geometry.drawRange; ->>>>>>> mrdoob-dev if ( index !== null ) { @@ -11203,7 +11665,7 @@ const b = index.getX( j + 1 ); const c = index.getX( j + 2 ); - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11228,7 +11690,7 @@ const b = index.getX( i + 1 ); const c = index.getX( i + 2 ); - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11261,7 +11723,7 @@ const b = j + 1; const c = j + 2; - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11286,7 +11748,7 @@ const b = i + 1; const c = i + 2; - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11326,117 +11788,7 @@ const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); -<<<<<<< HEAD - const currentRenderTarget = renderer.getRenderTarget(); - const useAlphaTest = material.alphaTest > 0; - const useClearcoat = material.clearcoat > 0; - const useIridescence = material.iridescence > 0; - const parameters = { - isWebGL2: isWebGL2, - shaderID: shaderID, - shaderName: material.type, - vertexShader: vertexShader, - fragmentShader: fragmentShader, - defines: material.defines, - customVertexShaderID: customVertexShaderID, - customFragmentShaderID: customFragmentShaderID, - isRawShaderMaterial: material.isRawShaderMaterial === true, - glslVersion: material.glslVersion, - precision: precision, - instancing: object.isInstancedMesh === true, - instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, - supportsVertexTextures: vertexTextures, - outputEncoding: currentRenderTarget === null ? renderer.outputEncoding : currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding, - map: !!material.map, - matcap: !!material.matcap, - envMap: !!envMap, - envMapMode: envMap && envMap.mapping, - envMapCubeUVHeight: envMapCubeUVHeight, - lightMap: !!material.lightMap, - aoMap: !!material.aoMap, - emissiveMap: !!material.emissiveMap, - bumpMap: !!material.bumpMap, - normalMap: !!material.normalMap, - objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, - tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, - decodeVideoTexture: !!material.map && material.map.isVideoTexture === true && material.map.encoding === sRGBEncoding, - clearcoat: useClearcoat, - clearcoatMap: useClearcoat && !!material.clearcoatMap, - clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap, - clearcoatNormalMap: useClearcoat && !!material.clearcoatNormalMap, - iridescence: useIridescence, - iridescenceMap: useIridescence && !!material.iridescenceMap, - iridescenceThicknessMap: useIridescence && !!material.iridescenceThicknessMap, - displacementMap: !!material.displacementMap, - roughnessMap: !!material.roughnessMap, - metalnessMap: !!material.metalnessMap, - specularMap: !!material.specularMap, - specularIntensityMap: !!material.specularIntensityMap, - specularColorMap: !!material.specularColorMap, - opaque: material.transparent === false && material.blending === NormalBlending, - alphaMap: !!material.alphaMap, - alphaTest: useAlphaTest, - gradientMap: !!material.gradientMap, - sheen: material.sheen > 0, - sheenColorMap: !!material.sheenColorMap, - sheenRoughnessMap: !!material.sheenRoughnessMap, - transmission: material.transmission > 0, - transmissionMap: !!material.transmissionMap, - thicknessMap: !!material.thicknessMap, - combine: material.combine, - vertexTangents: !!material.normalMap && !!geometry.attributes.tangent, - vertexColors: material.vertexColors, - vertexAlphas: material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4, - vertexUvs: !!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatMap || !!material.clearcoatRoughnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || !!material.displacementMap || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || !!material.sheenColorMap || !!material.sheenRoughnessMap, - uvsVertexOnly: !(!!material.map || !!material.bumpMap || !!material.normalMap || !!material.specularMap || !!material.alphaMap || !!material.emissiveMap || !!material.roughnessMap || !!material.metalnessMap || !!material.clearcoatNormalMap || !!material.iridescenceMap || !!material.iridescenceThicknessMap || material.transmission > 0 || !!material.transmissionMap || !!material.thicknessMap || !!material.specularIntensityMap || !!material.specularColorMap || material.sheen > 0 || !!material.sheenColorMap || !!material.sheenRoughnessMap) && !!material.displacementMap, - fog: !!fog, - useFog: material.fog === true, - fogExp2: fog && fog.isFogExp2, - flatShading: !!material.flatShading, - sizeAttenuation: material.sizeAttenuation, - logarithmicDepthBuffer: logarithmicDepthBuffer, - skinning: object.isSkinnedMesh === true, - morphTargets: geometry.morphAttributes.position !== undefined, - morphNormals: geometry.morphAttributes.normal !== undefined, - morphColors: geometry.morphAttributes.color !== undefined, - morphTargetsCount: morphTargetsCount, - morphTextureStride: morphTextureStride, - numDirLights: lights.directional.length, - numPointLights: lights.point.length, - numSpotLights: lights.spot.length, - numRectAreaLights: lights.rectArea.length, - numHemiLights: lights.hemi.length, - numDirLightShadows: lights.directionalShadowMap.length, - numPointLightShadows: lights.pointShadowMap.length, - numSpotLightShadows: lights.spotShadowMap.length, - numClippingPlanes: clipping.numPlanes, - numClipIntersection: clipping.numIntersection, - dithering: material.dithering, - shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, - shadowMapType: renderer.shadowMap.type, - toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, - premultipliedAlpha: material.premultipliedAlpha, - doubleSided: material.side === DoubleSide, - flipSided: material.side === BackSide, - useDepthPacking: !!material.depthPacking, - depthPacking: material.depthPacking || 0, - index0AttributeName: material.index0AttributeName, - extensionDerivatives: material.extensions && material.extensions.derivatives, - extensionFragDepth: material.extensions && material.extensions.fragDepth, - extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, - extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, - rendererExtensionFragDepth: isWebGL2 || extensions.has('EXT_frag_depth'), - rendererExtensionDrawBuffers: isWebGL2 || extensions.has('WEBGL_draw_buffers'), - rendererExtensionShaderTextureLod: isWebGL2 || extensions.has('EXT_shader_texture_lod'), - customProgramCacheKey: material.customProgramCacheKey(), - extraProgramCacheKey: renderer.extraProgramCacheKey - }; - return parameters; - } -======= if ( distance < raycaster.near || distance > raycaster.far ) return null; ->>>>>>> mrdoob-dev return { distance: distance, @@ -11446,24 +11798,13 @@ } - function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, uv2, a, b, c ) { + function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { object.getVertexPosition( a, _vA$1 ); object.getVertexPosition( b, _vB$1 ); object.getVertexPosition( c, _vC$1 ); -<<<<<<< HEAD - array.push(parameters.customProgramCacheKey); - - if (renderer.extraProgramCacheKey) { - array.push(renderer.extraProgramCacheKey); - } - - return array.join(); - } -======= const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); ->>>>>>> mrdoob-dev if ( intersection ) { @@ -11473,17 +11814,34 @@ _uvB$1.fromBufferAttribute( uv, b ); _uvC$1.fromBufferAttribute( uv, c ); - intersection.uv = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); } - if ( uv2 ) { + if ( uv1 ) { - _uvA$1.fromBufferAttribute( uv2, a ); - _uvB$1.fromBufferAttribute( uv2, b ); - _uvC$1.fromBufferAttribute( uv2, c ); + _uvA$1.fromBufferAttribute( uv1, a ); + _uvB$1.fromBufferAttribute( uv1, b ); + _uvC$1.fromBufferAttribute( uv1, c ); - intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv2 = intersection.uv1; // @deprecated, r152 + + } + + if ( normal ) { + + _normalA.fromBufferAttribute( normal, a ); + _normalB.fromBufferAttribute( normal, b ); + _normalC.fromBufferAttribute( normal, c ); + + intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); + + if ( intersection.normal.dot( ray.direction ) > 0 ) { + + intersection.normal.multiplyScalar( - 1 ); + + } } @@ -11662,6 +12020,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); @@ -11691,7 +12059,16 @@ property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion ) ) { - dst[ u ][ p ] = property.clone(); + if ( property.isRenderTargetTexture ) { + + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; + + } else { + + dst[ u ][ p ] = property.clone(); + + } } else if ( Array.isArray( property ) ) { @@ -11750,7 +12127,7 @@ if ( renderer.getRenderTarget() === null ) { // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 - return renderer.outputEncoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; + return renderer.outputColorSpace; } @@ -11792,6 +12169,8 @@ this.lights = false; // set to use scene lights this.clipping = false; // set to use user-defined clipping planes + this.forceSinglePass = true; + this.extensions = { derivatives: false, // set to use derivatives fragDepth: false, // set to use fragment depth values @@ -11804,7 +12183,7 @@ this.defaultAttributeValues = { 'color': [ 1, 1, 1 ], 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] + 'uv1': [ 0, 0 ] }; this.index0AttributeName = undefined; @@ -11925,6 +12304,9 @@ data.vertexShader = this.vertexShader; data.fragmentShader = this.fragmentShader; + data.lights = this.lights; + data.clipping = this.clipping; + const extensions = {}; for ( const key in this.extensions ) { @@ -12338,12 +12720,12 @@ class CubeTexture extends Texture { - constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { images = images !== undefined ? images : []; mapping = mapping !== undefined ? mapping : CubeReflectionMapping; - super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCubeTexture = true; @@ -12376,7 +12758,15 @@ const image = { width: size, height: size, depth: 1 }; const images = [ image, image, image, image, image, image ]; - this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( options.encoding !== undefined ) { + + // @deprecated, r152 + warnOnce( 'THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; + + } + + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, @@ -12396,7 +12786,7 @@ fromEquirectangularTexture( renderer, texture ) { this.texture.type = texture.type; - this.texture.encoding = texture.encoding; + this.texture.colorSpace = texture.colorSpace; this.texture.generateMipmaps = texture.generateMipmaps; this.texture.minFilter = texture.minFilter; @@ -12601,7 +12991,7 @@ projectPoint( point, target ) { - return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); } @@ -12633,7 +13023,7 @@ } - return target.copy( direction ).multiplyScalar( t ).add( line.start ); + return target.copy( line.start ).addScaledVector( direction, t ); } @@ -12702,8 +13092,8 @@ } - const _sphere$2 = /*@__PURE__*/ new Sphere(); - const _vector$7 = /*@__PURE__*/ new Vector3(); + const _sphere$4 = /*@__PURE__*/ new Sphere(); + const _vector$6 = /*@__PURE__*/ new Vector3(); class Frustum { @@ -12764,23 +13154,33 @@ intersectsObject( object ) { - const geometry = object.geometry; + if ( object.boundingSphere !== undefined ) { - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + + _sphere$4.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } else { - _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + const geometry = object.geometry; - return this.intersectsSphere( _sphere$2 ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere$4.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } + + return this.intersectsSphere( _sphere$4 ); } intersectsSprite( sprite ) { - _sphere$2.center.set( 0, 0, 0 ); - _sphere$2.radius = 0.7071067811865476; - _sphere$2.applyMatrix4( sprite.matrixWorld ); + _sphere$4.center.set( 0, 0, 0 ); + _sphere$4.radius = 0.7071067811865476; + _sphere$4.applyMatrix4( sprite.matrixWorld ); - return this.intersectsSphere( _sphere$2 ); + return this.intersectsSphere( _sphere$4 ); } @@ -12816,11 +13216,11 @@ // corner at max distance - _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; - _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; - _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; + _vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x; + _vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y; + _vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z; - if ( plane.distanceToPoint( _vector$7 ) < 0 ) { + if ( plane.distanceToPoint( _vector$6 ) < 0 ) { return false; @@ -13179,6 +13579,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); @@ -13187,7 +13597,7 @@ } - var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif"; + var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; @@ -13195,7 +13605,7 @@ var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; - var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; + var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; @@ -13203,11 +13613,11 @@ var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; - var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\n\tvec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif"; + var bsdfs = "float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated"; var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif"; - var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; + var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif"; @@ -13225,7 +13635,7 @@ var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif"; - var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}"; + var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; @@ -13233,9 +13643,9 @@ var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; - var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif"; + var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; - var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; + var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; @@ -13263,7 +13673,7 @@ var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}"; - var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; + var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; @@ -13271,9 +13681,9 @@ var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert"; - var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; + var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; - var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif"; + var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; @@ -13283,28 +13693,13 @@ var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; - var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; + var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tanisotropyV /= material.anisotropy;\n\tmaterial.anisotropy = saturate( material.anisotropy );\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x - tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x + tbn[ 0 ] * anisotropyV.y;\n#endif"; - var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; + var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; -<<<<<<< HEAD - let camera = cameras[i]; - - if (camera === undefined) { - camera = new PerspectiveCamera(); - camera.layers.enable(i); - camera.viewport = new Vector4(); - cameras[i] = camera; - } - - camera.matrix.fromArray(view.transform.matrix); - camera.projectionMatrix.fromArray(view.projectionMatrix); - camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height); -======= var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; ->>>>>>> mrdoob-dev - var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; + var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometry.viewDir, geometry.normal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; @@ -13316,15 +13711,15 @@ var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif"; - var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; + var map_fragment = "#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, vMapUv );\n#endif"; var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; - var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; + var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; - var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; + var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; - var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; + var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; @@ -13336,9 +13731,9 @@ var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif"; - var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;"; + var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal, vNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 geometryNormal = normal;"; - var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; + var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; @@ -13346,19 +13741,19 @@ var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif"; - var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif"; + var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif"; var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif"; - var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif"; + var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif"; - var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif"; + var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif"; var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; - var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; + var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; - var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}"; + var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; @@ -13368,13 +13763,13 @@ var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif"; - var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; + var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; - var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; + var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; - var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; + var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; @@ -13388,35 +13783,29 @@ var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif"; - var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; + var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; - var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; - - var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif"; - - var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; - - var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif"; + var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; - var uv_pars_vertex = "#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif"; + var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; - var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; + var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; - var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; + var uv_pars_fragment = "#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif"; + var uv_pars_vertex = "#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; - var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif"; + var uv_vertex = "#ifdef USE_UV\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif"; var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; - const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; + const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; const vertex$g = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; @@ -13438,45 +13827,45 @@ const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; - const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; + const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; - const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; + const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; - const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; + const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; - const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; + const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; - const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; const fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const vertex$2 = "#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; + const vertex$2 = "#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; - const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; + const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"; @@ -13585,9 +13974,6 @@ uv_pars_fragment: uv_pars_fragment, uv_pars_vertex: uv_pars_vertex, uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, worldpos_vertex: worldpos_vertex, background_vert: vertex$h, @@ -13638,10 +14024,11 @@ opacity: { value: 1.0 }, map: { value: null }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() }, - uv2Transform: { value: /*@__PURE__*/ new Matrix3() }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } }, @@ -13649,6 +14036,7 @@ specularmap: { specularMap: { value: null }, + specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -13665,26 +14053,23 @@ aomap: { aoMap: { value: null }, - aoMapIntensity: { value: 1 } + aoMapIntensity: { value: 1 }, + aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, lightmap: { lightMap: { value: null }, - lightMapIntensity: { value: 1 } - - }, - - emissivemap: { - - emissiveMap: { value: null } + lightMapIntensity: { value: 1 }, + lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, bumpmap: { bumpMap: { value: null }, + bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, bumpScale: { value: 1 } }, @@ -13692,6 +14077,7 @@ normalmap: { normalMap: { value: null }, + normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } }, @@ -13699,20 +14085,30 @@ displacementmap: { displacementMap: { value: null }, + displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, displacementScale: { value: 1 }, displacementBias: { value: 0 } }, - roughnessmap: { + emissivemap: { - roughnessMap: { value: null } + emissiveMap: { value: null }, + emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, metalnessmap: { - metalnessMap: { value: null } + metalnessMap: { value: null }, + metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } + + }, + + roughnessmap: { + + roughnessMap: { value: null }, + roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -13819,6 +14215,7 @@ scale: { value: 1.0 }, map: { value: null }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaTest: { value: 0 }, uvTransform: { value: /*@__PURE__*/ new Matrix3() } @@ -13831,9 +14228,10 @@ center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, rotation: { value: 0.0 }, map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, - alphaTest: { value: 0 }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() } + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } } @@ -14139,33 +14537,47 @@ { clearcoat: { value: 0 }, clearcoatMap: { value: null }, + clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalMap: { value: null }, + clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, clearcoatRoughness: { value: 0 }, clearcoatRoughnessMap: { value: null }, - clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, - clearcoatNormalMap: { value: null }, + clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescence: { value: 0 }, iridescenceMap: { value: null }, + iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescenceIOR: { value: 1.3 }, iridescenceThicknessMinimum: { value: 100 }, iridescenceThicknessMaximum: { value: 400 }, iridescenceThicknessMap: { value: null }, + iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheen: { value: 0 }, sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, sheenColorMap: { value: null }, + sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheenRoughness: { value: 1 }, sheenRoughnessMap: { value: null }, + sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmission: { value: 0 }, transmissionMap: { value: null }, + transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, transmissionSamplerMap: { value: null }, thickness: { value: 0 }, thicknessMap: { value: null }, + thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, attenuationDistance: { value: 0 }, attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, - specularIntensity: { value: 1 }, - specularIntensityMap: { value: null }, specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, specularColorMap: { value: null }, + specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, + anisotropyMap: { value: null }, + anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, } ] ), @@ -14200,26 +14612,35 @@ } - // Ignore background in AR - // TODO: Reconsider this. + if ( background === null ) { - const xr = renderer.xr; - const session = xr.getSession && xr.getSession(); + setClear( clearColor, clearAlpha ); - if ( session && session.environmentBlendMode === 'additive' ) { + } else if ( background && background.isColor ) { - background = null; + setClear( background, 1 ); + forceClear = true; } - if ( background === null ) { + const xr = renderer.xr; + const environmentBlendMode = xr.getEnvironmentBlendMode(); - setClear( clearColor, clearAlpha ); + switch ( environmentBlendMode ) { - } else if ( background && background.isColor ) { + case 'opaque': + forceClear = true; + break; - setClear( background, 1 ); - forceClear = true; + case 'additive': + state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); + forceClear = true; + break; + + case 'alpha-blend': + state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); + forceClear = true; + break; } @@ -14275,7 +14696,7 @@ boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - boxMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + boxMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( currentBackground !== background || currentBackgroundVersion !== background.version || @@ -14331,7 +14752,7 @@ planeMesh.material.uniforms.t2D.value = background; planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - planeMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + planeMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( background.matrixAutoUpdate === true ) { @@ -14391,51 +14812,13 @@ }, setClearAlpha: function ( alpha ) { -<<<<<<< HEAD - function updateCommonMaterialProperties(material, parameters) { - const materialProperties = properties.get(material); - materialProperties.outputEncoding = parameters.outputEncoding; - materialProperties.instancing = parameters.instancing; - materialProperties.skinning = parameters.skinning; - materialProperties.morphTargets = parameters.morphTargets; - materialProperties.morphNormals = parameters.morphNormals; - materialProperties.morphColors = parameters.morphColors; - materialProperties.morphTargetsCount = parameters.morphTargetsCount; - materialProperties.numClippingPlanes = parameters.numClippingPlanes; - materialProperties.numIntersection = parameters.numClipIntersection; - materialProperties.vertexAlphas = parameters.vertexAlphas; - materialProperties.vertexTangents = parameters.vertexTangents; - materialProperties.toneMapping = parameters.toneMapping; - materialProperties.extraProgramCacheKey = parameters.extraProgramCacheKey; - } -======= clearAlpha = alpha; setClear( clearColor, clearAlpha ); ->>>>>>> mrdoob-dev }, render: render -<<<<<<< HEAD - textures.resetTextureUnits(); - const fog = scene.fog; - const environment = material.isMeshStandardMaterial ? scene.environment : null; - const encoding = _currentRenderTarget === null ? _this.outputEncoding : _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding; - const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment); - const vertexAlphas = material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4; - const vertexTangents = !!material.normalMap && !!geometry.attributes.tangent; - const morphTargets = !!geometry.morphAttributes.position; - const morphNormals = !!geometry.morphAttributes.normal; - const morphColors = !!geometry.morphAttributes.color; - const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = morphAttribute !== undefined ? morphAttribute.length : 0; - const materialProperties = properties.get(material); - const lights = currentRenderState.state.lights; - const extraProgramCacheKey = _this.extraProgramCacheKey; -======= }; ->>>>>>> mrdoob-dev } @@ -14446,50 +14829,7 @@ const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' ); const vaoAvailable = capabilities.isWebGL2 || extension !== null; -<<<<<<< HEAD - if (material.version === materialProperties.__version) { - if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) { - needsProgramChange = true; - } else if (materialProperties.outputEncoding !== encoding) { - needsProgramChange = true; - } else if (object.isInstancedMesh && materialProperties.instancing === false) { - needsProgramChange = true; - } else if (!object.isInstancedMesh && materialProperties.instancing === true) { - needsProgramChange = true; - } else if (object.isSkinnedMesh && materialProperties.skinning === false) { - needsProgramChange = true; - } else if (!object.isSkinnedMesh && materialProperties.skinning === true) { - needsProgramChange = true; - } else if (materialProperties.envMap !== envMap) { - needsProgramChange = true; - } else if (material.fog === true && materialProperties.fog !== fog) { - needsProgramChange = true; - } else if (materialProperties.numClippingPlanes !== undefined && (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)) { - needsProgramChange = true; - } else if (materialProperties.vertexAlphas !== vertexAlphas) { - needsProgramChange = true; - } else if (materialProperties.vertexTangents !== vertexTangents) { - needsProgramChange = true; - } else if (materialProperties.morphTargets !== morphTargets) { - needsProgramChange = true; - } else if (materialProperties.morphNormals !== morphNormals) { - needsProgramChange = true; - } else if (materialProperties.morphColors !== morphColors) { - needsProgramChange = true; - } else if (materialProperties.toneMapping !== toneMapping) { - needsProgramChange = true; - } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) { - needsProgramChange = true; - } else if (extraProgramCacheKey !== materialProperties.extraProgramCacheKey) { - needsProgramChange = true; - } - } else { - needsProgramChange = true; - materialProperties.__version = material.version; - } // -======= const bindingStates = {}; ->>>>>>> mrdoob-dev const defaultState = createBindingState( null ); let currentState = defaultState; @@ -14799,9 +15139,9 @@ } - function vertexAttribPointer( index, size, type, normalized, stride, offset ) { + function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { - if ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT ) ) { + if ( integer === true ) { gl.vertexAttribIPointer( index, size, type, stride, offset ); @@ -14859,6 +15199,10 @@ const type = attribute.type; const bytesPerElement = attribute.bytesPerElement; + // check for integer attributes (WebGL 2 only) + + const integer = ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ) ); + if ( geometryAttribute.isInterleavedBufferAttribute ) { const data = geometryAttribute.data; @@ -14899,7 +15243,8 @@ type, normalized, stride * bytesPerElement, - ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement + ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, + integer ); } @@ -14940,7 +15285,8 @@ type, normalized, size * bytesPerElement, - ( size / programAttribute.locationSize ) * i * bytesPerElement + ( size / programAttribute.locationSize ) * i * bytesPerElement, + integer ); } @@ -15216,7 +15562,7 @@ } - const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; + const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl.constructor.name === 'WebGL2RenderingContext'; let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; const maxPrecision = getMaxPrecision( precision ); @@ -15906,7 +16252,7 @@ generateMipmaps: false, type: HalfFloatType, format: RGBAFormat, - encoding: LinearEncoding, + colorSpace: LinearSRGBColorSpace, depthBuffer: false }; @@ -16789,6 +17135,18 @@ } + for ( const name in geometry.morphAttributes ) { + + const array = geometry.morphAttributes[ name ]; + + for ( let i = 0, l = array.length; i < l; i ++ ) { + + attributes.remove( array[ i ] ); + + } + + } + geometry.removeEventListener( 'dispose', onGeometryDispose ); delete geometries[ geometry.id ]; @@ -17078,7 +17436,6 @@ function reset() { - render.frame ++; render.calls = 0; render.triangles = 0; render.points = 0; @@ -17124,7 +17481,7 @@ } - function update( object, geometry, material, program ) { + function update( object, geometry, program ) { const objectInfluences = object.morphTargetInfluences; @@ -17503,6 +17860,7 @@ * */ + const emptyTexture = /*@__PURE__*/ new Texture(); const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); @@ -18632,16 +18990,16 @@ } - function getEncodingComponents( encoding ) { + function getEncodingComponents( colorSpace ) { - switch ( encoding ) { + switch ( colorSpace ) { - case LinearEncoding: + case LinearSRGBColorSpace: return [ 'Linear', '( value )' ]; - case sRGBEncoding: + case SRGBColorSpace: return [ 'sRGB', '( value )' ]; default: - console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding ); + console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); return [ 'Linear', '( value )' ]; } @@ -18672,9 +19030,9 @@ } - function getTexelEncodingFunction( functionName, encoding ) { + function getTexelEncodingFunction( functionName, colorSpace ) { - const components = getEncodingComponents( encoding ); + const components = getEncodingComponents( colorSpace ); return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; } @@ -18718,7 +19076,7 @@ function generateExtensions( parameters ) { const chunks = [ - ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', + ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.normalMapTangentSpace || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '', ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '', ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : '' @@ -19026,6 +19384,9 @@ prefixVertex = [ + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -19039,6 +19400,10 @@ prefixFragment = [ customExtensions, + + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -19055,6 +19420,7 @@ generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, @@ -19062,21 +19428,22 @@ parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', - - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', @@ -19085,11 +19452,9 @@ parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -19099,14 +19464,52 @@ parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', + + // + + parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', + parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', + parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', + parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', + parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', + parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', + parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', + parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', + + parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', + parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', + + parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', + + parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', + parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', + parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', + + parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', + parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', + + parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', + parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', + + parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', + parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', + parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', + + parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', + parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', + + // parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', @@ -19126,6 +19529,8 @@ parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -19153,6 +19558,24 @@ 'attribute vec3 normal;', 'attribute vec2 uv;', + '#ifdef USE_UV1', + + ' attribute vec2 uv1;', + + '#endif', + + '#ifdef USE_UV2', + + ' attribute vec2 uv2;', + + '#endif', + + '#ifdef USE_UV3', + + ' attribute vec2 uv3;', + + '#endif', + '#ifdef USE_TANGENT', ' attribute vec4 tangent;', @@ -19211,12 +19634,13 @@ generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', @@ -19229,11 +19653,14 @@ envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', @@ -19245,8 +19672,9 @@ parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -19254,20 +19682,21 @@ parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', - parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', @@ -19281,7 +19710,7 @@ parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', - parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -19298,7 +19727,7 @@ parameters.opaque ? '#define OPAQUE' : '', ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below - getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ), + getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', @@ -19391,16 +19820,26 @@ runnable = false; - const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); - const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + if ( typeof renderer.debug.onShaderError === 'function' ) { - console.error( - 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + - 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + - 'Program Info Log: ' + programLog + '\n' + - vertexErrors + '\n' + - fragmentErrors - ); + renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); + + } else { + + // default error reporting + + const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); + + } } else if ( programLog !== '' ) { @@ -19494,6 +19933,7 @@ // + this.type = parameters.shaderType; this.name = parameters.shaderName; this.id = programIdCount ++; this.cacheKey = cacheKey; @@ -19635,9 +20075,10 @@ const _customShaders = new WebGLShaderCache(); const programs = []; - const isWebGL2 = capabilities.isWebGL2; + const IS_WEBGL2 = capabilities.isWebGL2; const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; - const vertexTextures = capabilities.vertexTextures; + const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; + let precision = capabilities.precision; const shaderIDs = { @@ -19658,6 +20099,14 @@ SpriteMaterial: 'sprite' }; + function getChannel( value ) { + + if ( value === 0 ) return 'uv'; + + return `uv${ value }`; + + } + function getParameters( material, lights, shadows, scene, object ) { const fog = scene.fog; @@ -19721,16 +20170,65 @@ const currentRenderTarget = renderer.getRenderTarget(); - const useAlphaTest = material.alphaTest > 0; - const useClearcoat = material.clearcoat > 0; - const useIridescence = material.iridescence > 0; + const IS_INSTANCEDMESH = object.isInstancedMesh === true; + + const HAS_MAP = !! material.map; + const HAS_MATCAP = !! material.matcap; + const HAS_ENVMAP = !! envMap; + const HAS_AOMAP = !! material.aoMap; + const HAS_LIGHTMAP = !! material.lightMap; + const HAS_BUMPMAP = !! material.bumpMap; + const HAS_NORMALMAP = !! material.normalMap; + const HAS_DISPLACEMENTMAP = !! material.displacementMap; + const HAS_EMISSIVEMAP = !! material.emissiveMap; + + const HAS_METALNESSMAP = !! material.metalnessMap; + const HAS_ROUGHNESSMAP = !! material.roughnessMap; + + const HAS_ANISOTROPY = material.anisotropy > 0; + const HAS_CLEARCOAT = material.clearcoat > 0; + const HAS_IRIDESCENCE = material.iridescence > 0; + const HAS_SHEEN = material.sheen > 0; + const HAS_TRANSMISSION = material.transmission > 0; + + const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; + + const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; + const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; + const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; + + const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; + const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; + + const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; + const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; + + const HAS_SPECULARMAP = !! material.specularMap; + const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; + const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; + + const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; + const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; + + const HAS_GRADIENTMAP = !! material.gradientMap; + + const HAS_ALPHAMAP = !! material.alphaMap; + + const HAS_ALPHATEST = material.alphaTest > 0; + + const HAS_EXTENSIONS = !! material.extensions; + + const HAS_ATTRIBUTE_UV1 = !! geometry.attributes.uv1; + const HAS_ATTRIBUTE_UV2 = !! geometry.attributes.uv2; + const HAS_ATTRIBUTE_UV3 = !! geometry.attributes.uv3; const parameters = { - isWebGL2: isWebGL2, + isWebGL2: IS_WEBGL2, shaderID: shaderID, - shaderName: material.type, + shaderType: material.type, + shaderName: material.name, vertexShader: vertexShader, fragmentShader: fragmentShader, @@ -19744,72 +20242,115 @@ precision: precision, - instancing: object.isInstancedMesh === true, - instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + instancing: IS_INSTANCEDMESH, + instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, - supportsVertexTextures: vertexTextures, - outputEncoding: ( currentRenderTarget === null ) ? renderer.outputEncoding : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding ), - map: !! material.map, - matcap: !! material.matcap, - envMap: !! envMap, - envMapMode: envMap && envMap.mapping, + supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, + outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), + + map: HAS_MAP, + matcap: HAS_MATCAP, + envMap: HAS_ENVMAP, + envMapMode: HAS_ENVMAP && envMap.mapping, envMapCubeUVHeight: envMapCubeUVHeight, - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, - tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, - - decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ), - - clearcoat: useClearcoat, - clearcoatMap: useClearcoat && !! material.clearcoatMap, - clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap, - clearcoatNormalMap: useClearcoat && !! material.clearcoatNormalMap, - - iridescence: useIridescence, - iridescenceMap: useIridescence && !! material.iridescenceMap, - iridescenceThicknessMap: useIridescence && !! material.iridescenceThicknessMap, - - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - specularIntensityMap: !! material.specularIntensityMap, - specularColorMap: !! material.specularColorMap, + aoMap: HAS_AOMAP, + lightMap: HAS_LIGHTMAP, + bumpMap: HAS_BUMPMAP, + normalMap: HAS_NORMALMAP, + displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + emissiveMap: HAS_EMISSIVEMAP, - opaque: material.transparent === false && material.blending === NormalBlending, + normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, + normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, + + metalnessMap: HAS_METALNESSMAP, + roughnessMap: HAS_ROUGHNESSMAP, + + anisotropy: HAS_ANISOTROPY, + anisotropyMap: HAS_ANISOTROPYMAP, - alphaMap: !! material.alphaMap, - alphaTest: useAlphaTest, + clearcoat: HAS_CLEARCOAT, + clearcoatMap: HAS_CLEARCOATMAP, + clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, + clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, - gradientMap: !! material.gradientMap, + iridescence: HAS_IRIDESCENCE, + iridescenceMap: HAS_IRIDESCENCEMAP, + iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, - sheen: material.sheen > 0, - sheenColorMap: !! material.sheenColorMap, - sheenRoughnessMap: !! material.sheenRoughnessMap, + sheen: HAS_SHEEN, + sheenColorMap: HAS_SHEEN_COLORMAP, + sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, - transmission: material.transmission > 0, - transmissionMap: !! material.transmissionMap, - thicknessMap: !! material.thicknessMap, + specularMap: HAS_SPECULARMAP, + specularColorMap: HAS_SPECULAR_COLORMAP, + specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, + + transmission: HAS_TRANSMISSION, + transmissionMap: HAS_TRANSMISSIONMAP, + thicknessMap: HAS_THICKNESSMAP, + + gradientMap: HAS_GRADIENTMAP, + + opaque: material.transparent === false && material.blending === NormalBlending, + + alphaMap: HAS_ALPHAMAP, + alphaTest: HAS_ALPHATEST, combine: material.combine, - vertexTangents: ( !! material.normalMap && !! geometry.attributes.tangent ), + // + + mapUv: HAS_MAP && getChannel( material.map.channel ), + aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), + lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), + bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), + normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), + displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), + emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), + + metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), + roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), + + anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), + + clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), + clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), + clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), + + iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), + iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), + + sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), + sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), + + specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), + specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), + specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), + + transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), + thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), + + alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), + + // + + vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), vertexColors: material.vertexColors, vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, - vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || !! material.displacementMap || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheenColorMap || !! material.sheenRoughnessMap, - uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || material.transmission > 0 || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || material.sheen > 0 || !! material.sheenColorMap || !! material.sheenRoughnessMap ) && !! material.displacementMap, + vertexUv1s: HAS_ATTRIBUTE_UV1, + vertexUv2s: HAS_ATTRIBUTE_UV2, + vertexUv3s: HAS_ATTRIBUTE_UV3, + + pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), fog: !! fog, useFog: material.fog === true, fogExp2: ( fog && fog.isFogExp2 ), - flatShading: !! material.flatShading, + flatShading: material.flatShading === true, - sizeAttenuation: material.sizeAttenuation, + sizeAttenuation: material.sizeAttenuation === true, logarithmicDepthBuffer: logarithmicDepthBuffer, skinning: object.isSkinnedMesh === true, @@ -19841,26 +20382,26 @@ shadowMapType: renderer.shadowMap.type, toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, + useLegacyLights: renderer.useLegacyLights, premultipliedAlpha: material.premultipliedAlpha, doubleSided: material.side === DoubleSide, flipSided: material.side === BackSide, - useDepthPacking: !! material.depthPacking, + useDepthPacking: material.depthPacking >= 0, depthPacking: material.depthPacking || 0, index0AttributeName: material.index0AttributeName, - extensionDerivatives: material.extensions && material.extensions.derivatives, - extensionFragDepth: material.extensions && material.extensions.fragDepth, - extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, - extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, + extensionDerivatives: HAS_EXTENSIONS && material.extensions.derivatives === true, + extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true, + extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true, + extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true, - rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ), - rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ), - rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ), + rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ), + rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ), + rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ), customProgramCacheKey: material.customProgramCacheKey() @@ -19900,7 +20441,7 @@ getProgramCacheKeyParameters( array, parameters ); getProgramCacheKeyBooleans( array, parameters ); - array.push( renderer.outputEncoding ); + array.push( renderer.outputColorSpace ); } @@ -19913,11 +20454,33 @@ function getProgramCacheKeyParameters( array, parameters ) { array.push( parameters.precision ); - array.push( parameters.outputEncoding ); + array.push( parameters.outputColorSpace ); array.push( parameters.envMapMode ); array.push( parameters.envMapCubeUVHeight ); + array.push( parameters.mapUv ); + array.push( parameters.alphaMapUv ); + array.push( parameters.lightMapUv ); + array.push( parameters.aoMapUv ); + array.push( parameters.bumpMapUv ); + array.push( parameters.normalMapUv ); + array.push( parameters.displacementMapUv ); + array.push( parameters.emissiveMapUv ); + array.push( parameters.metalnessMapUv ); + array.push( parameters.roughnessMapUv ); + array.push( parameters.anisotropyMapUv ); + array.push( parameters.clearcoatMapUv ); + array.push( parameters.clearcoatNormalMapUv ); + array.push( parameters.clearcoatRoughnessMapUv ); + array.push( parameters.iridescenceMapUv ); + array.push( parameters.iridescenceThicknessMapUv ); + array.push( parameters.sheenColorMapUv ); + array.push( parameters.sheenRoughnessMapUv ); + array.push( parameters.specularMapUv ); + array.push( parameters.specularColorMapUv ); + array.push( parameters.specularIntensityMapUv ); + array.push( parameters.transmissionMapUv ); + array.push( parameters.thicknessMapUv ); array.push( parameters.combine ); - array.push( parameters.vertexUvs ); array.push( parameters.fogExp2 ); array.push( parameters.sizeAttenuation ); array.push( parameters.morphTargetsCount ); @@ -19952,64 +20515,34 @@ _programLayers.enable( 2 ); if ( parameters.instancingColor ) _programLayers.enable( 3 ); - if ( parameters.map ) - _programLayers.enable( 4 ); if ( parameters.matcap ) - _programLayers.enable( 5 ); + _programLayers.enable( 4 ); if ( parameters.envMap ) + _programLayers.enable( 5 ); + if ( parameters.normalMapObjectSpace ) _programLayers.enable( 6 ); - if ( parameters.lightMap ) + if ( parameters.normalMapTangentSpace ) _programLayers.enable( 7 ); - if ( parameters.aoMap ) + if ( parameters.clearcoat ) _programLayers.enable( 8 ); - if ( parameters.emissiveMap ) + if ( parameters.iridescence ) _programLayers.enable( 9 ); - if ( parameters.bumpMap ) + if ( parameters.alphaTest ) _programLayers.enable( 10 ); - if ( parameters.normalMap ) + if ( parameters.vertexColors ) _programLayers.enable( 11 ); - if ( parameters.objectSpaceNormalMap ) + if ( parameters.vertexAlphas ) _programLayers.enable( 12 ); - if ( parameters.tangentSpaceNormalMap ) + if ( parameters.vertexUv1s ) _programLayers.enable( 13 ); - if ( parameters.clearcoat ) + if ( parameters.vertexUv2s ) _programLayers.enable( 14 ); - if ( parameters.clearcoatMap ) + if ( parameters.vertexUv3s ) _programLayers.enable( 15 ); - if ( parameters.clearcoatRoughnessMap ) + if ( parameters.vertexTangents ) _programLayers.enable( 16 ); - if ( parameters.clearcoatNormalMap ) + if ( parameters.anisotropy ) _programLayers.enable( 17 ); - if ( parameters.iridescence ) - _programLayers.enable( 18 ); - if ( parameters.iridescenceMap ) - _programLayers.enable( 19 ); - if ( parameters.iridescenceThicknessMap ) - _programLayers.enable( 20 ); - if ( parameters.displacementMap ) - _programLayers.enable( 21 ); - if ( parameters.specularMap ) - _programLayers.enable( 22 ); - if ( parameters.roughnessMap ) - _programLayers.enable( 23 ); - if ( parameters.metalnessMap ) - _programLayers.enable( 24 ); - if ( parameters.gradientMap ) - _programLayers.enable( 25 ); - if ( parameters.alphaMap ) - _programLayers.enable( 26 ); - if ( parameters.alphaTest ) - _programLayers.enable( 27 ); - if ( parameters.vertexColors ) - _programLayers.enable( 28 ); - if ( parameters.vertexAlphas ) - _programLayers.enable( 29 ); - if ( parameters.vertexUvs ) - _programLayers.enable( 30 ); - if ( parameters.vertexTangents ) - _programLayers.enable( 31 ); - if ( parameters.uvsVertexOnly ) - _programLayers.enable( 32 ); array.push( _programLayers.mask ); _programLayers.disableAll(); @@ -20034,7 +20567,7 @@ _programLayers.enable( 8 ); if ( parameters.shadowMapEnabled ) _programLayers.enable( 9 ); - if ( parameters.physicallyCorrectLights ) + if ( parameters.useLegacyLights ) _programLayers.enable( 10 ); if ( parameters.doubleSided ) _programLayers.enable( 11 ); @@ -20044,26 +20577,14 @@ _programLayers.enable( 13 ); if ( parameters.dithering ) _programLayers.enable( 14 ); - if ( parameters.specularIntensityMap ) + if ( parameters.transmission ) _programLayers.enable( 15 ); - if ( parameters.specularColorMap ) + if ( parameters.sheen ) _programLayers.enable( 16 ); - if ( parameters.transmission ) + if ( parameters.opaque ) _programLayers.enable( 17 ); - if ( parameters.transmissionMap ) + if ( parameters.pointsUvs ) _programLayers.enable( 18 ); - if ( parameters.thicknessMap ) - _programLayers.enable( 19 ); - if ( parameters.sheen ) - _programLayers.enable( 20 ); - if ( parameters.sheenColorMap ) - _programLayers.enable( 21 ); - if ( parameters.sheenRoughnessMap ) - _programLayers.enable( 22 ); - if ( parameters.decodeVideoTexture ) - _programLayers.enable( 23 ); - if ( parameters.opaque ) - _programLayers.enable( 24 ); array.push( _programLayers.mask ); @@ -20642,7 +21163,7 @@ const matrix4 = new Matrix4(); const matrix42 = new Matrix4(); - function setup( lights, physicallyCorrectLights ) { + function setup( lights, useLegacyLights ) { let r = 0, g = 0, b = 0; @@ -20664,7 +21185,7 @@ lights.sort( shadowCastingAndTexturingLightsFirst ); // artist-friendly light intensity scaling factor - const scaleFactor = ( physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1; for ( let i = 0, l = lights.length; i < l; i ++ ) { @@ -21032,9 +21553,9 @@ } - function setupLights( physicallyCorrectLights ) { + function setupLights( useLegacyLights ) { - lights.setup( lightsArray, physicallyCorrectLights ); + lights.setup( lightsArray, useLegacyLights ); } @@ -21169,10 +21690,6 @@ this.type = 'MeshDistanceMaterial'; - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; - this.map = null; this.alphaMap = null; @@ -21189,10 +21706,6 @@ super.copy( source ); - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; - this.map = source.map; this.alphaMap = source.alphaMap; @@ -21266,6 +21779,7 @@ this.needsUpdate = false; this.type = PCFShadowMap; + let _previousType = this.type; this.render = function ( lights, scene, camera ) { @@ -21286,6 +21800,11 @@ _state.buffers.depth.setTest( true ); _state.setScissorTest( false ); + // check for shadow map type changes + + const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); + const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); + // render depth map for ( let i = 0, il = lights.length; i < il; i ++ ) { @@ -21330,10 +21849,16 @@ } - if ( shadow.map === null ) { + if ( shadow.map === null || toVSM === true || fromVSM === true ) { const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; + if ( shadow.map !== null ) { + + shadow.map.dispose(); + + } + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); shadow.map.texture.name = light.name + '.shadowMap'; @@ -21379,6 +21904,8 @@ } + _previousType = this.type; + scope.needsUpdate = false; _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); @@ -21425,7 +21952,7 @@ } - function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) { + function getDepthMaterial( object, material, light, type ) { let result = null; @@ -21503,9 +22030,8 @@ if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { - result.referencePosition.setFromMatrixPosition( light.matrixWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; + const materialProperties = _renderer.properties.get( result ); + materialProperties.light = light; } @@ -21539,7 +22065,7 @@ if ( groupMaterial && groupMaterial.visible ) { - const depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); @@ -21549,7 +22075,7 @@ } else if ( material.visible ) { - const depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, material, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); @@ -21932,7 +22458,7 @@ const currentScissor = new Vector4().fromArray( scissorParam ); const currentViewport = new Vector4().fromArray( viewportParam ); - function createTexture( type, target, count ) { + function createTexture( type, target, count, dimensions ) { const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. const texture = gl.createTexture(); @@ -21943,7 +22469,15 @@ for ( let i = 0; i < count; i ++ ) { - gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + if ( isWebGL2 && ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) ) { + + gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } else { + + gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } } @@ -21955,6 +22489,13 @@ emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); + if ( isWebGL2 ) { + + emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); + emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); + + } + // init colorBuffer.setClear( 0, 0, 0, 1 ); @@ -22991,7 +23532,7 @@ } - function getInternalFormat( internalFormatName, glFormat, glType, encoding, forceLinearEncoding = false ) { + function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { if ( isWebGL2 === false ) return glFormat; @@ -23025,7 +23566,7 @@ if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; - if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( encoding === sRGBEncoding && forceLinearEncoding === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( colorSpace === SRGBColorSpace && forceLinearTransfer === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; @@ -23282,7 +23823,7 @@ array.push( texture.premultiplyAlpha ); array.push( texture.flipY ); array.push( texture.unpackAlignment ); - array.push( texture.encoding ); + array.push( texture.colorSpace ); return array.join(); @@ -23382,6 +23923,17 @@ [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR }; + const compareToGL = { + [ NeverCompare ]: _gl.NEVER, + [ AlwaysCompare ]: _gl.ALWAYS, + [ LessCompare ]: _gl.LESS, + [ LessEqualCompare ]: _gl.LEQUAL, + [ EqualCompare ]: _gl.EQUAL, + [ GreaterEqualCompare ]: _gl.GEQUAL, + [ GreaterCompare ]: _gl.GREATER, + [ NotEqualCompare ]: _gl.NOTEQUAL + }; + function setTextureParameters( textureType, texture, supportsMips ) { if ( supportsMips ) { @@ -23426,6 +23978,13 @@ } + if ( texture.compareFunction ) { + + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); + + } + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); @@ -23554,10 +24113,10 @@ image = verifyColorSpace( texture, image ); const supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ); + glFormat = utils.convert( texture.format, texture.colorSpace ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); setTextureParameters( textureType, texture, supportsMips ); @@ -23986,9 +24545,9 @@ const image = cubeImage[ 0 ], supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ), + glFormat = utils.convert( texture.format, texture.colorSpace ), glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); @@ -24155,9 +24714,9 @@ // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) { - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const renderTargetProperties = properties.get( renderTarget ); if ( ! renderTargetProperties.__hasExternalTextures ) { @@ -24267,9 +24826,9 @@ const texture = textures[ i ]; - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const samples = getRenderTargetSamples( renderTarget ); if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { @@ -24502,9 +25061,9 @@ _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, renderTarget.isXRRenderTarget === true ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); const samples = getRenderTargetSamples( renderTarget ); _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); @@ -24776,17 +25335,17 @@ function verifyColorSpace( texture, image ) { - const encoding = texture.encoding; + const colorSpace = texture.colorSpace; const format = texture.format; const type = texture.type; - if ( texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat ) return image; + if ( texture.isCompressedTexture === true || texture.format === _SRGBAFormat ) return image; - if ( encoding !== LinearEncoding ) { + if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { // sRGB - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { if ( isWebGL2 === false ) { @@ -24823,7 +25382,7 @@ } else { - console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding ); + console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); } @@ -24856,7 +25415,7 @@ const isWebGL2 = capabilities.isWebGL2; - function convert( p, encoding = null ) { + function convert( p, colorSpace = NoColorSpace ) { let extension; @@ -24926,7 +25485,7 @@ if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); @@ -25011,8 +25570,8 @@ if ( extension !== null ) { - if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; - if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + if ( p === RGB_ETC2_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; } else { @@ -25034,20 +25593,20 @@ if ( extension !== null ) { - if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; - if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; - if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; - if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; - if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; - if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; - if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; - if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; - if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; - if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; - if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; - if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; - if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; - if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; + if ( p === RGBA_ASTC_4x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; } else { @@ -25065,7 +25624,7 @@ if ( extension !== null ) { - if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + if ( p === RGBA_BPTC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; } else { @@ -25322,6 +25881,7 @@ joint.matrix.fromArray( jointPose.transform.matrix ); joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); + joint.matrixWorldNeedsUpdate = true; joint.jointRadius = jointPose.radius; } @@ -25370,6 +25930,7 @@ grip.matrix.fromArray( gripPose.transform.matrix ); grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + grip.matrixWorldNeedsUpdate = true; if ( gripPose.linearVelocity ) { @@ -25414,6 +25975,7 @@ targetRay.matrix.fromArray( inputPose.transform.matrix ); targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + targetRay.matrixWorldNeedsUpdate = true; if ( inputPose.linearVelocity ) { @@ -25516,8 +26078,30 @@ this.flipY = false; this.generateMipmaps = false; + this.compareFunction = null; + + } + + + copy( source ) { + + super.copy( source ); + + this.compareFunction = source.compareFunction; + + return this; + } + toJSON( meta ) { + + const data = super.toJSON( meta ); + + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; + + return data; + + } } @@ -25530,6 +26114,7 @@ const scope = this; let session = null; + let framebufferScaleFactor = 1.0; let referenceSpace = null; @@ -25550,11 +26135,10 @@ const controllers = []; const controllerInputSources = []; - const planes = new Set(); - const planesLastChangedTimes = new Map(); - // + let userCamera = null; + const cameraL = new PerspectiveCamera(); cameraL.layers.enable( 1 ); cameraL.viewport = new Vector4(); @@ -25565,20 +26149,28 @@ const cameras = [ cameraL, cameraR ]; - const cameraVR = new ArrayCamera(); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + const cameraXR = new ArrayCamera(); + cameraXR.layers.enable( 1 ); + cameraXR.layers.enable( 2 ); let _currentDepthNear = null; let _currentDepthFar = null; // - this.cameraAutoUpdate = true; + this.cameraAutoUpdate = true; // @deprecated, r153 this.enabled = false; this.isPresenting = false; + this.getCamera = function () {}; // @deprecated, r153 + + this.setUserCamera = function ( value ) { + + userCamera = value; + + }; + this.getController = function ( index ) { let controller = controllers[ index ]; @@ -25640,6 +26232,7 @@ if ( controller !== undefined ) { + controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); controller.dispatchEvent( { type: event.type, data: event.inputSource } ); } @@ -25779,7 +26372,7 @@ const layerInit = { antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true, - alpha: attributes.alpha, + alpha: true, depth: attributes.depth, stencil: attributes.stencil, framebufferScaleFactor: framebufferScaleFactor @@ -25795,7 +26388,7 @@ { format: RGBAFormat, type: UnsignedByteType, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, stencilBuffer: attributes.stencil } ); @@ -25834,7 +26427,7 @@ type: UnsignedByteType, depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), stencilBuffer: attributes.stencil, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, samples: attributes.antialias ? 4 : 0 } ); @@ -25861,6 +26454,16 @@ }; + this.getEnvironmentBlendMode = function () { + + if ( session !== null ) { + + return session.environmentBlendMode; + + } + + }; + function onInputSourcesChange( event ) { // Notify disconnected @@ -25984,6 +26587,7 @@ const bottom2 = bottomFov * far / far2 * near2; camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); } @@ -26003,31 +26607,37 @@ } - this.updateCamera = function ( camera ) { + this.updateCameraXR = function ( camera ) { + + if ( session === null ) return camera; - if ( session === null ) return; + if ( userCamera ) { - cameraVR.near = cameraR.near = cameraL.near = camera.near; - cameraVR.far = cameraR.far = cameraL.far = camera.far; + camera = userCamera; + + } - if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { + cameraXR.near = cameraR.near = cameraL.near = camera.near; + cameraXR.far = cameraR.far = cameraL.far = camera.far; + + if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { // Note that the new renderState won't apply until the next frame. See #18320 session.updateRenderState( { - depthNear: cameraVR.near, - depthFar: cameraVR.far + depthNear: cameraXR.near, + depthFar: cameraXR.far } ); - _currentDepthNear = cameraVR.near; - _currentDepthFar = cameraVR.far; + _currentDepthNear = cameraXR.near; + _currentDepthFar = cameraXR.far; } const parent = camera.parent; - const cameras = cameraVR.cameras; + const cameras = cameraXR.cameras; - updateCamera( cameraVR, parent ); + updateCamera( cameraXR, parent ); for ( let i = 0; i < cameras.length; i ++ ) { @@ -26035,42 +26645,70 @@ } - cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale ); + // update projection matrix for proper view frustum culling - // update user camera and its children + if ( cameras.length === 2 ) { - camera.matrix.copy( cameraVR.matrix ); - camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + setProjectionFromUnion( cameraXR, cameraL, cameraR ); - const children = camera.children; + } else { - for ( let i = 0, l = children.length; i < l; i ++ ) { + // assume single camera setup (AR) - children[ i ].updateMatrixWorld( true ); + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); } - // update projection matrix for proper view frustum culling + // update user camera and its children - if ( cameras.length === 2 ) { + if ( userCamera ) { + + updateUserCamera( cameraXR, parent ); + + } - setProjectionFromUnion( cameraVR, cameraL, cameraR ); + return cameraXR; + + }; + + function updateUserCamera( cameraXR, parent ) { + + const camera = userCamera; + + if ( parent === null ) { + + camera.matrix.copy( cameraXR.matrixWorld ); } else { - // assume single camera setup (AR) + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); + + } + + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); + + const children = camera.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + children[ i ].updateMatrixWorld( true ); } - }; + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); - this.getCamera = function () { + if ( camera.isPerspectiveCamera ) { - return cameraVR; + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; - }; + } + + } this.getFoveation = function () { @@ -26105,12 +26743,6 @@ }; - this.getPlanes = function () { - - return planes; - - }; - // Animation Loop let onAnimationFrameCallback = null; @@ -26131,14 +26763,14 @@ } - let cameraVRNeedsUpdate = false; + let cameraXRNeedsUpdate = false; - // check if it's necessary to rebuild cameraVR's camera list + // check if it's necessary to rebuild cameraXR's camera list - if ( views.length !== cameraVR.cameras.length ) { + if ( views.length !== cameraXR.cameras.length ) { - cameraVR.cameras.length = 0; - cameraVRNeedsUpdate = true; + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; } @@ -26183,18 +26815,21 @@ } camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); if ( i === 0 ) { - cameraVR.matrix.copy( camera.matrix ); + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); } - if ( cameraVRNeedsUpdate === true ) { + if ( cameraXRNeedsUpdate === true ) { - cameraVR.cameras.push( camera ); + cameraXR.cameras.push( camera ); } @@ -26221,60 +26856,7 @@ if ( frame.detectedPlanes ) { - scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } ); - - let planesToRemove = null; - - for ( const plane of planes ) { - - if ( ! frame.detectedPlanes.has( plane ) ) { - - if ( planesToRemove === null ) { - - planesToRemove = []; - - } - - planesToRemove.push( plane ); - - } - - } - - if ( planesToRemove !== null ) { - - for ( const plane of planesToRemove ) { - - planes.delete( plane ); - planesLastChangedTimes.delete( plane ); - scope.dispatchEvent( { type: 'planeremoved', data: plane } ); - - } - - } - - for ( const plane of frame.detectedPlanes ) { - - if ( ! planes.has( plane ) ) { - - planes.add( plane ); - planesLastChangedTimes.set( plane, frame.lastChangedTime ); - scope.dispatchEvent( { type: 'planeadded', data: plane } ); - - } else { - - const lastKnownTime = planesLastChangedTimes.get( plane ); - - if ( plane.lastChangedTime > lastKnownTime ) { - - planesLastChangedTimes.set( plane, plane.lastChangedTime ); - scope.dispatchEvent( { type: 'planechanged', data: plane } ); - - } - - } - - } + scope.dispatchEvent( { type: 'planesdetected', data: frame } ); } @@ -26300,6 +26882,18 @@ function WebGLMaterials( renderer, properties ) { + function refreshTransformUniform( map, uniform ) { + + if ( map.matrixAutoUpdate === true ) { + + map.updateMatrix(); + + } + + uniform.value.copy( map.matrix ); + + } + function refreshFogUniforms( uniforms, fog ) { fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); @@ -26417,25 +27011,56 @@ uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.bumpMap ) { uniforms.bumpMap.value = material.bumpMap; + + refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); + uniforms.bumpScale.value = material.bumpScale; - if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; + + if ( material.side === BackSide ) { + + uniforms.bumpScale.value *= - 1; + + } + + } + + if ( material.normalMap ) { + + uniforms.normalMap.value = material.normalMap; + + refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); + + uniforms.normalScale.value.copy( material.normalScale ); + + if ( material.side === BackSide ) { + + uniforms.normalScale.value.negate(); + + } } if ( material.displacementMap ) { uniforms.displacementMap.value = material.displacementMap; + + refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); + uniforms.displacementScale.value = material.displacementScale; uniforms.displacementBias.value = material.displacementBias; @@ -26445,13 +27070,7 @@ uniforms.emissiveMap.value = material.emissiveMap; - } - - if ( material.normalMap ) { - - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); - if ( material.side === BackSide ) uniforms.normalScale.value.negate(); + refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); } @@ -26459,6 +27078,8 @@ uniforms.specularMap.value = material.specularMap; + refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26486,10 +27107,12 @@ uniforms.lightMap.value = material.lightMap; // artist-friendly light intensity scaling factor - const scaleFactor = ( renderer.physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( renderer.useLegacyLights === true ) ? Math.PI : 1; uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; + refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); + } if ( material.aoMap ) { @@ -26497,175 +27120,27 @@ uniforms.aoMap.value = material.aoMap; uniforms.aoMapIntensity.value = material.aoMapIntensity; - } - - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. displacementMap map - // 4. normal map - // 5. bump map - // 6. roughnessMap map - // 7. metalnessMap map - // 8. alphaMap map - // 9. emissiveMap map - // 10. clearcoat map - // 11. clearcoat normal map - // 12. clearcoat roughnessMap map - // 13. iridescence map - // 14. iridescence thickness map - // 15. specular intensity map - // 16. specular tint map - // 17. transmission map - // 18. thickness map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.specularMap ) { - - uvScaleMap = material.specularMap; - - } else if ( material.displacementMap ) { - - uvScaleMap = material.displacementMap; - - } else if ( material.normalMap ) { - - uvScaleMap = material.normalMap; - - } else if ( material.bumpMap ) { - - uvScaleMap = material.bumpMap; - - } else if ( material.roughnessMap ) { - - uvScaleMap = material.roughnessMap; - - } else if ( material.metalnessMap ) { - - uvScaleMap = material.metalnessMap; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } else if ( material.emissiveMap ) { - - uvScaleMap = material.emissiveMap; - - } else if ( material.clearcoatMap ) { - - uvScaleMap = material.clearcoatMap; - - } else if ( material.clearcoatNormalMap ) { - - uvScaleMap = material.clearcoatNormalMap; - - } else if ( material.clearcoatRoughnessMap ) { - - uvScaleMap = material.clearcoatRoughnessMap; - - } else if ( material.iridescenceMap ) { - - uvScaleMap = material.iridescenceMap; - - } else if ( material.iridescenceThicknessMap ) { - - uvScaleMap = material.iridescenceThicknessMap; - - } else if ( material.specularIntensityMap ) { - - uvScaleMap = material.specularIntensityMap; - - } else if ( material.specularColorMap ) { - - uvScaleMap = material.specularColorMap; - - } else if ( material.transmissionMap ) { - - uvScaleMap = material.transmissionMap; - - } else if ( material.thicknessMap ) { - - uvScaleMap = material.thicknessMap; - - } else if ( material.sheenColorMap ) { - - uvScaleMap = material.sheenColorMap; - - } else if ( material.sheenRoughnessMap ) { - - uvScaleMap = material.sheenRoughnessMap; + refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); } - if ( uvScaleMap !== undefined ) { - - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { - - uvScaleMap = uvScaleMap.texture; - - } - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - - // uv repeat and offset setting priorities for uv2 - // 1. ao map - // 2. light map - - let uv2ScaleMap; - - if ( material.aoMap ) { - - uv2ScaleMap = material.aoMap; - - } else if ( material.lightMap ) { - - uv2ScaleMap = material.lightMap; - - } - - if ( uv2ScaleMap !== undefined ) { - - // backwards compatibility - if ( uv2ScaleMap.isWebGLRenderTarget ) { - - uv2ScaleMap = uv2ScaleMap.texture; + } - } + function refreshUniformsLine( uniforms, material ) { - if ( uv2ScaleMap.matrixAutoUpdate === true ) { + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - uv2ScaleMap.updateMatrix(); + if ( material.map ) { - } + uniforms.map.value = material.map; - uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix ); + refreshTransformUniform( material.map, uniforms.mapTransform ); } } - function refreshUniformsLine( uniforms, material ) { - - uniforms.diffuse.value.copy( material.color ); - uniforms.opacity.value = material.opacity; - - } - function refreshUniformsDash( uniforms, material ) { uniforms.dashSize.value = material.dashSize; @@ -26685,12 +27160,16 @@ uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.uvTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26699,34 +27178,6 @@ } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsSprites( uniforms, material ) { @@ -26739,12 +27190,16 @@ uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26753,34 +27208,6 @@ } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsPhong( uniforms, material ) { @@ -26802,18 +27229,23 @@ function refreshUniformsStandard( uniforms, material ) { - uniforms.roughness.value = material.roughness; uniforms.metalness.value = material.metalness; - if ( material.roughnessMap ) { + if ( material.metalnessMap ) { - uniforms.roughnessMap.value = material.roughnessMap; + uniforms.metalnessMap.value = material.metalnessMap; + + refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); } - if ( material.metalnessMap ) { + uniforms.roughness.value = material.roughness; - uniforms.metalnessMap.value = material.metalnessMap; + if ( material.roughnessMap ) { + + uniforms.roughnessMap.value = material.roughnessMap; + + refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); } @@ -26842,12 +27274,16 @@ uniforms.sheenColorMap.value = material.sheenColorMap; + refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); + } if ( material.sheenRoughnessMap ) { uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; + refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); + } } @@ -26861,19 +27297,26 @@ uniforms.clearcoatMap.value = material.clearcoatMap; + refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); + } if ( material.clearcoatRoughnessMap ) { uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; + refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); + } if ( material.clearcoatNormalMap ) { - uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; + refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); + + uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); + if ( material.side === BackSide ) { uniforms.clearcoatNormalScale.value.negate(); @@ -26895,12 +27338,16 @@ uniforms.iridescenceMap.value = material.iridescenceMap; + refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); + } if ( material.iridescenceThicknessMap ) { uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; + refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); + } } @@ -26915,6 +27362,8 @@ uniforms.transmissionMap.value = material.transmissionMap; + refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); + } uniforms.thickness.value = material.thickness; @@ -26923,6 +27372,8 @@ uniforms.thicknessMap.value = material.thicknessMap; + refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); + } uniforms.attenuationDistance.value = material.attenuationDistance; @@ -26930,19 +27381,37 @@ } - uniforms.specularIntensity.value = material.specularIntensity; - uniforms.specularColor.value.copy( material.specularColor ); + if ( material.anisotropy > 0 ) { - if ( material.specularIntensityMap ) { + uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - uniforms.specularIntensityMap.value = material.specularIntensityMap; + if ( material.anisotropyMap ) { + + uniforms.anisotropyMap.value = material.anisotropyMap; + + refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); + + } } + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy( material.specularColor ); + if ( material.specularColorMap ) { uniforms.specularColorMap.value = material.specularColorMap; + refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); + + } + + if ( material.specularIntensityMap ) { + + uniforms.specularIntensityMap.value = material.specularIntensityMap; + + refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); + } } @@ -26959,9 +27428,11 @@ function refreshUniformsDistance( uniforms, material ) { - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; + const light = properties.get( material ).light; + + uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); + uniforms.nearDistance.value = light.shadow.camera.near; + uniforms.farDistance.value = light.shadow.camera.far; } @@ -27391,2199 +27862,2374 @@ } - function WebGLRenderer( parameters = {} ) { + class WebGLRenderer { - this.isWebGLRenderer = true; + constructor( parameters = {} ) { - const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(), - _context = parameters.context !== undefined ? parameters.context : null, + const { + canvas = createCanvasElement(), + context = null, + depth = true, + stencil = true, + alpha = false, + antialias = false, + premultipliedAlpha = true, + preserveDrawingBuffer = false, + powerPreference = 'default', + failIfMajorPerformanceCaveat = false, + } = parameters; - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, - _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', - _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; + this.isWebGLRenderer = true; - let _alpha; + let _alpha; - if ( _context !== null ) { + if ( context !== null ) { - _alpha = _context.getContextAttributes().alpha; + _alpha = context.getContextAttributes().alpha; - } else { + } else { - _alpha = parameters.alpha !== undefined ? parameters.alpha : false; + _alpha = alpha; - } + } - let currentRenderList = null; - let currentRenderState = null; + const uintClearColor = new Uint32Array( 4 ); + const intClearColor = new Int32Array( 4 ); - // render() can be called from within a callback triggered by another render. - // We track this so that the nested render call gets its list and state isolated from the parent render call. + let currentRenderList = null; + let currentRenderState = null; - const renderListStack = []; - const renderStateStack = []; + // render() can be called from within a callback triggered by another render. + // We track this so that the nested render call gets its list and state isolated from the parent render call. - // public properties + const renderListStack = []; + const renderStateStack = []; - this.domElement = _canvas; + // public properties - // Debug configuration container - this.debug = { + this.domElement = canvas; - /** - * Enables error checking and reporting when shader programs are being compiled - * @type {boolean} - */ - checkShaderErrors: true - }; + // Debug configuration container + this.debug = { - // clearing + /** + * Enables error checking and reporting when shader programs are being compiled + * @type {boolean} + */ + checkShaderErrors: true, + /** + * Callback for custom error reporting. + * @type {?Function} + */ + onShaderError: null + }; - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; + // clearing - // scene graph + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; - this.sortObjects = true; + // scene graph - // user-defined clipping + this.sortObjects = true; - this.clippingPlanes = []; - this.localClippingEnabled = false; + // user-defined clipping - // physically based shading + this.clippingPlanes = []; + this.localClippingEnabled = false; - this.outputEncoding = LinearEncoding; + // physically based shading - // physical lights + this.outputColorSpace = SRGBColorSpace; - this.physicallyCorrectLights = false; + // physical lights - // tone mapping + this.useLegacyLights = true; - this.toneMapping = NoToneMapping; - this.toneMappingExposure = 1.0; + // tone mapping - // internal properties + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; - const _this = this; + // internal properties - let _isContextLost = false; + const _this = this; - // internal state cache + let _isContextLost = false; - let _currentActiveCubeFace = 0; - let _currentActiveMipmapLevel = 0; - let _currentRenderTarget = null; - let _currentMaterialId = - 1; + // internal state cache - let _currentCamera = null; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = - 1; - const _currentViewport = new Vector4(); - const _currentScissor = new Vector4(); - let _currentScissorTest = null; + let _currentCamera = null; - // + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; - let _width = _canvas.width; - let _height = _canvas.height; + const _currentClearColor = new Color( 0x000000 ); + let _currentClearAlpha = 0; - let _pixelRatio = 1; - let _opaqueSort = null; - let _transparentSort = null; + // - const _viewport = new Vector4( 0, 0, _width, _height ); - const _scissor = new Vector4( 0, 0, _width, _height ); - let _scissorTest = false; + let _width = canvas.width; + let _height = canvas.height; - // frustum + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; - const _frustum = new Frustum(); + const _viewport = new Vector4( 0, 0, _width, _height ); + const _scissor = new Vector4( 0, 0, _width, _height ); + let _scissorTest = false; - // clipping + // frustum - let _clippingEnabled = false; - let _localClippingEnabled = false; + const _frustum = new Frustum(); - // transmission + // clipping - let _transmissionRenderTarget = null; + let _clippingEnabled = false; + let _localClippingEnabled = false; - // camera matrices cache + // transmission - const _projScreenMatrix = new Matrix4(); + let _transmissionRenderTarget = null; - const _vector2 = new Vector2(); - const _vector3 = new Vector3(); + // camera matrices cache - const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; + const _projScreenMatrix = new Matrix4(); - function getTargetPixelRatio() { + const _vector2 = new Vector2(); + const _vector3 = new Vector3(); - return _currentRenderTarget === null ? _pixelRatio : 1; + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; - } + function getTargetPixelRatio() { + + return _currentRenderTarget === null ? _pixelRatio : 1; + + } - // initialize + // initialize - let _gl = _context; + let _gl = context; - function getContext( contextNames, contextAttributes ) { + function getContext( contextNames, contextAttributes ) { - for ( let i = 0; i < contextNames.length; i ++ ) { + for ( let i = 0; i < contextNames.length; i ++ ) { - const contextName = contextNames[ i ]; - const context = _canvas.getContext( contextName, contextAttributes ); - if ( context !== null ) return context; + const contextName = contextNames[ i ]; + const context = canvas.getContext( contextName, contextAttributes ); + if ( context !== null ) return context; + + } + + return null; } - return null; + try { - } + const contextAttributes = { + alpha: true, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + powerPreference, + failIfMajorPerformanceCaveat, + }; - try { + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); - const contextAttributes = { - alpha: true, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer, - powerPreference: _powerPreference, - failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat - }; + // event listeners must be registered before WebGL context is created, see #12753 + canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + + if ( _gl === null ) { - // OffscreenCanvas does not have setAttribute, see #22811 - if ( 'setAttribute' in _canvas ) _canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); + const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; - // event listeners must be registered before WebGL context is created, see #12753 - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + if ( _this.isWebGL1Renderer === true ) { - if ( _gl === null ) { + contextNames.shift(); - const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; + } - if ( _this.isWebGL1Renderer === true ) { + _gl = getContext( contextNames, contextAttributes ); - contextNames.shift(); + if ( _gl === null ) { + + if ( getContext( contextNames ) ) { + + throw new Error( 'Error creating WebGL context with your selected attributes.' ); + + } else { + + throw new Error( 'Error creating WebGL context.' ); + + } + + } } - _gl = getContext( contextNames, contextAttributes ); + if ( _gl instanceof WebGLRenderingContext ) { // @deprecated, r153 - if ( _gl === null ) { + console.warn( 'THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.' ); - if ( getContext( contextNames ) ) { + } - throw new Error( 'Error creating WebGL context with your selected attributes.' ); + // Some experimental-webgl implementations do not have getShaderPrecisionFormat - } else { + if ( _gl.getShaderPrecisionFormat === undefined ) { - throw new Error( 'Error creating WebGL context.' ); + _gl.getShaderPrecisionFormat = function () { - } + return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + + }; } + } catch ( error ) { + + console.error( 'THREE.WebGLRenderer: ' + error.message ); + throw error; + } - // Some experimental-webgl implementations do not have getShaderPrecisionFormat + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; - if ( _gl.getShaderPrecisionFormat === undefined ) { + let background, morphtargets, bufferRenderer, indexedBufferRenderer; - _gl.getShaderPrecisionFormat = function () { + let utils, bindingStates, uniformsGroups; - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + function initGLContext() { - }; + extensions = new WebGLExtensions( _gl ); + + capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + + extensions.init( capabilities ); + + utils = new WebGLUtils( _gl, extensions, capabilities ); + + state = new WebGLState( _gl, extensions, capabilities ); + + info = new WebGLInfo( _gl ); + properties = new WebGLProperties(); + textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); + cubemaps = new WebGLCubeMaps( _this ); + cubeuvmaps = new WebGLCubeUVMaps( _this ); + attributes = new WebGLAttributes( _gl, capabilities ); + bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); + geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); + objects = new WebGLObjects( _gl, geometries, attributes, info ); + morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); + clipping = new WebGLClipping( properties ); + programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); + materials = new WebGLMaterials( _this, properties ); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates( extensions, capabilities ); + background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + shadowMap = new WebGLShadowMap( _this, objects, capabilities ); + uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); + + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); + + info.programs = programCache.programs; + + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.shadowMap = shadowMap; + _this.state = state; + _this.info = info; } - } catch ( error ) { + initGLContext(); - console.error( 'THREE.WebGLRenderer: ' + error.message ); - throw error; + // xr - } + const xr = new WebXRManager( _this, _gl ); - let extensions, capabilities, state, info; - let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; - let programCache, materials, renderLists, renderStates, clipping, shadowMap; + this.xr = xr; - let background, morphtargets, bufferRenderer, indexedBufferRenderer; + // API - let utils, bindingStates, uniformsGroups; + this.getContext = function () { - function initGLContext() { + return _gl; - extensions = new WebGLExtensions( _gl ); + }; - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + this.getContextAttributes = function () { - extensions.init( capabilities ); + return _gl.getContextAttributes(); - utils = new WebGLUtils( _gl, extensions, capabilities ); + }; - state = new WebGLState( _gl, extensions, capabilities ); + this.forceContextLoss = function () { - info = new WebGLInfo( _gl ); - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); - cubemaps = new WebGLCubeMaps( _this ); - cubeuvmaps = new WebGLCubeUVMaps( _this ); - attributes = new WebGLAttributes( _gl, capabilities ); - bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); - geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); - objects = new WebGLObjects( _gl, geometries, attributes, info ); - morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); - clipping = new WebGLClipping( properties ); - programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); - materials = new WebGLMaterials( _this, properties ); - renderLists = new WebGLRenderLists(); - renderStates = new WebGLRenderStates( extensions, capabilities ); - background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, _premultipliedAlpha ); - shadowMap = new WebGLShadowMap( _this, objects, capabilities ); - uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.loseContext(); - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); + }; - info.programs = programCache.programs; + this.forceContextRestore = function () { - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.shadowMap = shadowMap; - _this.state = state; - _this.info = info; + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); - } + }; + + this.getPixelRatio = function () { + + return _pixelRatio; + + }; + + this.setPixelRatio = function ( value ) { + + if ( value === undefined ) return; + + _pixelRatio = value; + + this.setSize( _width, _height, false ); + + }; + + this.getSize = function ( target ) { + + return target.set( _width, _height ); + + }; + + this.setSize = function ( width, height, updateStyle = true ) { + + if ( xr.isPresenting ) { + + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; - initGLContext(); + } + + _width = width; + _height = height; + + canvas.width = Math.floor( width * _pixelRatio ); + canvas.height = Math.floor( height * _pixelRatio ); + + if ( updateStyle === true ) { + + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; + + } + + this.setViewport( 0, 0, width, height ); + + }; + + this.getDrawingBufferSize = function ( target ) { + + return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + + }; + + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + + _width = width; + _height = height; + + _pixelRatio = pixelRatio; + + canvas.width = Math.floor( width * pixelRatio ); + canvas.height = Math.floor( height * pixelRatio ); + + this.setViewport( 0, 0, width, height ); + + }; + + this.getCurrentViewport = function ( target ) { + + return target.copy( _currentViewport ); + + }; + + this.getViewport = function ( target ) { + + return target.copy( _viewport ); + + }; + + this.setViewport = function ( x, y, width, height ) { + + if ( x.isVector4 ) { + + _viewport.set( x.x, x.y, x.z, x.w ); + + } else { - // xr + _viewport.set( x, y, width, height ); - const xr = new WebXRManager( _this, _gl ); + } - this.xr = xr; + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); - // API + }; - this.getContext = function () { + this.getScissor = function ( target ) { - return _gl; + return target.copy( _scissor ); - }; + }; - this.getContextAttributes = function () { + this.setScissor = function ( x, y, width, height ) { - return _gl.getContextAttributes(); + if ( x.isVector4 ) { - }; + _scissor.set( x.x, x.y, x.z, x.w ); - this.forceContextLoss = function () { + } else { - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.loseContext(); + _scissor.set( x, y, width, height ); - }; + } - this.forceContextRestore = function () { + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.restoreContext(); + }; - }; + this.getScissorTest = function () { - this.getPixelRatio = function () { + return _scissorTest; - return _pixelRatio; + }; - }; + this.setScissorTest = function ( boolean ) { - this.setPixelRatio = function ( value ) { + state.setScissorTest( _scissorTest = boolean ); - if ( value === undefined ) return; + }; - _pixelRatio = value; + this.setOpaqueSort = function ( method ) { - this.setSize( _width, _height, false ); + _opaqueSort = method; - }; + }; - this.getSize = function ( target ) { + this.setTransparentSort = function ( method ) { - return target.set( _width, _height ); + _transparentSort = method; - }; + }; - this.setSize = function ( width, height, updateStyle ) { + // Clearing - if ( xr.isPresenting ) { + this.getClearColor = function ( target ) { - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; + return target.copy( background.getClearColor() ); - } + }; - _width = width; - _height = height; + this.setClearColor = function () { - _canvas.width = Math.floor( width * _pixelRatio ); - _canvas.height = Math.floor( height * _pixelRatio ); + background.setClearColor.apply( background, arguments ); - if ( updateStyle !== false ) { + }; - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; + this.getClearAlpha = function () { - } + return background.getClearAlpha(); - this.setViewport( 0, 0, width, height ); + }; - }; + this.setClearAlpha = function () { - this.getDrawingBufferSize = function ( target ) { + background.setClearAlpha.apply( background, arguments ); - return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + }; - }; + this.clear = function ( color = true, depth = true, stencil = true ) { - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + let bits = 0; - _width = width; - _height = height; + if ( color ) { - _pixelRatio = pixelRatio; + // check if we're trying to clear an integer target + let isIntegerFormat = false; + if ( _currentRenderTarget !== null ) { - _canvas.width = Math.floor( width * pixelRatio ); - _canvas.height = Math.floor( height * pixelRatio ); + const targetFormat = _currentRenderTarget.texture.format; + isIntegerFormat = targetFormat === RGBAIntegerFormat || + targetFormat === RGIntegerFormat || + targetFormat === RedIntegerFormat; - this.setViewport( 0, 0, width, height ); + } - }; + // use the appropriate clear functions to clear the target if it's a signed + // or unsigned integer target + if ( isIntegerFormat ) { - this.getCurrentViewport = function ( target ) { + const targetType = _currentRenderTarget.texture.type; + const isUnsignedType = targetType === UnsignedByteType || + targetType === UnsignedIntType || + targetType === UnsignedShortType || + targetType === UnsignedInt248Type || + targetType === UnsignedShort4444Type || + targetType === UnsignedShort5551Type; - return target.copy( _currentViewport ); + const clearColor = background.getClearColor(); + const a = background.getClearAlpha(); + const r = clearColor.r; + const g = clearColor.g; + const b = clearColor.b; - }; + const __webglFramebuffer = properties.get( _currentRenderTarget ).__webglFramebuffer; - this.getViewport = function ( target ) { + if ( isUnsignedType ) { - return target.copy( _viewport ); + uintClearColor[ 0 ] = r; + uintClearColor[ 1 ] = g; + uintClearColor[ 2 ] = b; + uintClearColor[ 3 ] = a; + _gl.clearBufferuiv( _gl.COLOR, __webglFramebuffer, uintClearColor ); - }; + } else { - this.setViewport = function ( x, y, width, height ) { + intClearColor[ 0 ] = r; + intClearColor[ 1 ] = g; + intClearColor[ 2 ] = b; + intClearColor[ 3 ] = a; + _gl.clearBufferiv( _gl.COLOR, __webglFramebuffer, intClearColor ); - if ( x.isVector4 ) { + } - _viewport.set( x.x, x.y, x.z, x.w ); + } else { - } else { + bits |= _gl.COLOR_BUFFER_BIT; - _viewport.set( x, y, width, height ); + } - } + } - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); + if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( stencil ) bits |= _gl.STENCIL_BUFFER_BIT; - }; + _gl.clear( bits ); - this.getScissor = function ( target ) { + }; - return target.copy( _scissor ); + this.clearColor = function () { - }; + this.clear( true, false, false ); - this.setScissor = function ( x, y, width, height ) { + }; - if ( x.isVector4 ) { + this.clearDepth = function () { - _scissor.set( x.x, x.y, x.z, x.w ); + this.clear( false, true, false ); - } else { + }; - _scissor.set( x, y, width, height ); + this.clearStencil = function () { - } + this.clear( false, false, true ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); + }; - }; + // - this.getScissorTest = function () { + this.dispose = function () { - return _scissorTest; + canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - }; + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); - this.setScissorTest = function ( boolean ) { + xr.dispose(); - state.setScissorTest( _scissorTest = boolean ); + xr.removeEventListener( 'sessionstart', onXRSessionStart ); + xr.removeEventListener( 'sessionend', onXRSessionEnd ); - }; + if ( _transmissionRenderTarget ) { - this.setOpaqueSort = function ( method ) { + _transmissionRenderTarget.dispose(); + _transmissionRenderTarget = null; - _opaqueSort = method; + } - }; + animation.stop(); - this.setTransparentSort = function ( method ) { + }; - _transparentSort = method; + // Events - }; + function onContextLost( event ) { - // Clearing + event.preventDefault(); - this.getClearColor = function ( target ) { + console.log( 'THREE.WebGLRenderer: Context Lost.' ); - return target.copy( background.getClearColor() ); + _isContextLost = true; - }; + } - this.setClearColor = function () { + function onContextRestore( /* event */ ) { - background.setClearColor.apply( background, arguments ); + console.log( 'THREE.WebGLRenderer: Context Restored.' ); - }; + _isContextLost = false; - this.getClearAlpha = function () { + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; - return background.getClearAlpha(); + initGLContext(); - }; + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; - this.setClearAlpha = function () { + } - background.setClearAlpha.apply( background, arguments ); + function onContextCreationError( event ) { - }; + console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); - this.clear = function ( color = true, depth = true, stencil = true ) { + } - let bits = 0; + function onMaterialDispose( event ) { - if ( color ) bits |= _gl.COLOR_BUFFER_BIT; - if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; - if ( stencil ) bits |= _gl.STENCIL_BUFFER_BIT; + const material = event.target; - _gl.clear( bits ); + material.removeEventListener( 'dispose', onMaterialDispose ); - }; + deallocateMaterial( material ); - this.clearColor = function () { + } - this.clear( true, false, false ); + // Buffer deallocation - }; + function deallocateMaterial( material ) { - this.clearDepth = function () { + releaseMaterialProgramReferences( material ); - this.clear( false, true, false ); + properties.remove( material ); - }; + } - this.clearStencil = function () { - this.clear( false, false, true ); + function releaseMaterialProgramReferences( material ) { - }; + const programs = properties.get( material ).programs; - // + if ( programs !== undefined ) { - this.dispose = function () { + programs.forEach( function ( program ) { - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + programCache.releaseProgram( program ); - renderLists.dispose(); - renderStates.dispose(); - properties.dispose(); - cubemaps.dispose(); - cubeuvmaps.dispose(); - objects.dispose(); - bindingStates.dispose(); - uniformsGroups.dispose(); - programCache.dispose(); + } ); - xr.dispose(); + if ( material.isShaderMaterial ) { - xr.removeEventListener( 'sessionstart', onXRSessionStart ); - xr.removeEventListener( 'sessionend', onXRSessionEnd ); + programCache.releaseShaderCache( material ); - if ( _transmissionRenderTarget ) { + } - _transmissionRenderTarget.dispose(); - _transmissionRenderTarget = null; + } } - animation.stop(); + // Buffer rendering - }; + this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { - // Events + if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) - function onContextLost( event ) { + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); - event.preventDefault(); + const program = setProgram( camera, scene, geometry, material, object ); - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + state.setMaterial( material, frontFaceCW ); - _isContextLost = true; + // - } + let index = geometry.index; + let rangeFactor = 1; - function onContextRestore( /* event */ ) { + if ( material.wireframe === true ) { - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + index = geometries.getWireframeAttribute( geometry ); + rangeFactor = 2; - _isContextLost = false; + } - const infoAutoReset = info.autoReset; - const shadowMapEnabled = shadowMap.enabled; - const shadowMapAutoUpdate = shadowMap.autoUpdate; - const shadowMapNeedsUpdate = shadowMap.needsUpdate; - const shadowMapType = shadowMap.type; + // - initGLContext(); + const drawRange = geometry.drawRange; + const position = geometry.attributes.position; - info.autoReset = infoAutoReset; - shadowMap.enabled = shadowMapEnabled; - shadowMap.autoUpdate = shadowMapAutoUpdate; - shadowMap.needsUpdate = shadowMapNeedsUpdate; - shadowMap.type = shadowMapType; + let drawStart = drawRange.start * rangeFactor; + let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; - } + if ( group !== null ) { - function onContextCreationError( event ) { + drawStart = Math.max( drawStart, group.start * rangeFactor ); + drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); - console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); + } - } + if ( index !== null ) { - function onMaterialDispose( event ) { + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, index.count ); - const material = event.target; + } else if ( position !== undefined && position !== null ) { - material.removeEventListener( 'dispose', onMaterialDispose ); + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, position.count ); - deallocateMaterial( material ); + } - } + const drawCount = drawEnd - drawStart; - // Buffer deallocation + if ( drawCount < 0 || drawCount === Infinity ) return; - function deallocateMaterial( material ) { + // - releaseMaterialProgramReferences( material ); + bindingStates.setup( object, material, program, geometry, index ); - properties.remove( material ); + let attribute; + let renderer = bufferRenderer; - } + if ( index !== null ) { + attribute = attributes.get( index ); - function releaseMaterialProgramReferences( material ) { + renderer = indexedBufferRenderer; + renderer.setIndex( attribute ); - const programs = properties.get( material ).programs; + } - if ( programs !== undefined ) { + // - programs.forEach( function ( program ) { + if ( object.isMesh ) { - programCache.releaseProgram( program ); + if ( material.wireframe === true ) { - } ); + state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); + renderer.setMode( _gl.LINES ); - if ( material.isShaderMaterial ) { + } else { - programCache.releaseShaderCache( material ); + renderer.setMode( _gl.TRIANGLES ); - } + } - } + } else if ( object.isLine ) { - } + let lineWidth = material.linewidth; - // Buffer rendering + if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { + state.setLineWidth( lineWidth * getTargetPixelRatio() ); - if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) + if ( object.isLineSegments ) { - const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + renderer.setMode( _gl.LINES ); - const program = setProgram( camera, scene, geometry, material, object ); + } else if ( object.isLineLoop ) { - state.setMaterial( material, frontFaceCW ); + renderer.setMode( _gl.LINE_LOOP ); - // + } else { - let index = geometry.index; - let rangeFactor = 1; + renderer.setMode( _gl.LINE_STRIP ); - if ( material.wireframe === true ) { + } - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; + } else if ( object.isPoints ) { - } + renderer.setMode( _gl.POINTS ); - // + } else if ( object.isSprite ) { - const drawRange = geometry.drawRange; - const position = geometry.attributes.position; + renderer.setMode( _gl.TRIANGLES ); - let drawStart = drawRange.start * rangeFactor; - let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; + } - if ( group !== null ) { + if ( object.isInstancedMesh ) { - drawStart = Math.max( drawStart, group.start * rangeFactor ); - drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); + renderer.renderInstances( drawStart, drawCount, object.count ); - } + } else if ( geometry.isInstancedBufferGeometry ) { - if ( index !== null ) { + const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; + const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, index.count ); + renderer.renderInstances( drawStart, drawCount, instanceCount ); - } else if ( position !== undefined && position !== null ) { + } else { - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, position.count ); + renderer.render( drawStart, drawCount ); - } + } - const drawCount = drawEnd - drawStart; + }; - if ( drawCount < 0 || drawCount === Infinity ) return; + // Compile - // + this.compile = function ( scene, camera ) { - bindingStates.setup( object, material, program, geometry, index ); + function prepare( material, scene, object ) { - let attribute; - let renderer = bufferRenderer; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - if ( index !== null ) { + material.side = BackSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - attribute = attributes.get( index ); + material.side = FrontSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); + material.side = DoubleSide; - } + } else { - // + getProgram( material, scene, object ); - if ( object.isMesh ) { + } - if ( material.wireframe === true ) { + } - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( _gl.LINES ); + currentRenderState = renderStates.get( scene ); + currentRenderState.init(); - } else { + renderStateStack.push( currentRenderState ); - renderer.setMode( _gl.TRIANGLES ); + scene.traverseVisible( function ( object ) { - } + if ( object.isLight && object.layers.test( camera.layers ) ) { - } else if ( object.isLine ) { + currentRenderState.pushLight( object ); - let lineWidth = material.linewidth; + if ( object.castShadow ) { - if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material + currentRenderState.pushShadow( object ); - state.setLineWidth( lineWidth * getTargetPixelRatio() ); + } - if ( object.isLineSegments ) { + } - renderer.setMode( _gl.LINES ); + } ); - } else if ( object.isLineLoop ) { + currentRenderState.setupLights( _this.useLegacyLights ); - renderer.setMode( _gl.LINE_LOOP ); + scene.traverse( function ( object ) { - } else { + const material = object.material; - renderer.setMode( _gl.LINE_STRIP ); + if ( material ) { - } + if ( Array.isArray( material ) ) { - } else if ( object.isPoints ) { + for ( let i = 0; i < material.length; i ++ ) { - renderer.setMode( _gl.POINTS ); + const material2 = material[ i ]; - } else if ( object.isSprite ) { + prepare( material2, scene, object ); - renderer.setMode( _gl.TRIANGLES ); + } - } + } else { - if ( object.isInstancedMesh ) { + prepare( material, scene, object ); - renderer.renderInstances( drawStart, drawCount, object.count ); + } - } else if ( geometry.isInstancedBufferGeometry ) { + } - const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; - const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); + } ); - renderer.renderInstances( drawStart, drawCount, instanceCount ); + renderStateStack.pop(); + currentRenderState = null; - } else { + }; - renderer.render( drawStart, drawCount ); + // Animation Loop - } + let onAnimationFrameCallback = null; - }; + function onAnimationFrame( time ) { - // Compile + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); - this.compile = function ( scene, camera ) { + } - function prepare( material, scene, object ) { + function onXRSessionStart() { - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + animation.stop(); - material.side = BackSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + } - material.side = FrontSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + function onXRSessionEnd() { - material.side = DoubleSide; + animation.start(); - } else { + } - getProgram( material, scene, object ); + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); - } + if ( typeof self !== 'undefined' ) animation.setContext( self ); - } + this.setAnimationLoop = function ( callback ) { - currentRenderState = renderStates.get( scene ); - currentRenderState.init(); + onAnimationFrameCallback = callback; + xr.setAnimationLoop( callback ); - renderStateStack.push( currentRenderState ); + ( callback === null ) ? animation.stop() : animation.start(); - scene.traverseVisible( function ( object ) { + }; - if ( object.isLight && object.layers.test( camera.layers ) ) { + xr.addEventListener( 'sessionstart', onXRSessionStart ); + xr.addEventListener( 'sessionend', onXRSessionEnd ); - currentRenderState.pushLight( object ); + // Rendering - if ( object.castShadow ) { + this.render = function ( scene, camera ) { - currentRenderState.pushShadow( object ); + if ( camera !== undefined && camera.isCamera !== true ) { - } + console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + return; } - } ); + if ( _isContextLost === true ) return; - currentRenderState.setupLights( _this.physicallyCorrectLights ); + // update scene graph - scene.traverse( function ( object ) { + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); - const material = object.material; + // update camera matrices and frustum - if ( material ) { + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - if ( Array.isArray( material ) ) { + if ( xr.enabled === true && xr.isPresenting === true ) { - for ( let i = 0; i < material.length; i ++ ) { + camera = xr.updateCameraXR( camera ); // use XR camera for rendering - const material2 = material[ i ]; + } - prepare( material2, scene, object ); + // + if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); - } + currentRenderState = renderStates.get( scene, renderStateStack.length ); + currentRenderState.init(); - } else { + renderStateStack.push( currentRenderState ); - prepare( material, scene, object ); + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix ); - } + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); - } + currentRenderList = renderLists.get( scene, renderListStack.length ); + currentRenderList.init(); - } ); + renderListStack.push( currentRenderList ); - renderStateStack.pop(); - currentRenderState = null; + projectObject( scene, camera, 0, _this.sortObjects ); - }; + currentRenderList.finish(); - // Animation Loop + if ( _this.sortObjects === true ) { - let onAnimationFrameCallback = null; + currentRenderList.sort( _opaqueSort, _transparentSort ); - function onAnimationFrame( time ) { + } - if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); + // - } + if ( _clippingEnabled === true ) clipping.beginShadows(); - function onXRSessionStart() { + const shadowsArray = currentRenderState.state.shadowsArray; - animation.stop(); + shadowMap.render( shadowsArray, scene, camera ); - } + if ( _clippingEnabled === true ) clipping.endShadows(); - function onXRSessionEnd() { + // - animation.start(); + if ( this.info.autoReset === true ) this.info.reset(); - } + this.info.render.frame ++; - const animation = new WebGLAnimation(); - animation.setAnimationLoop( onAnimationFrame ); + // - if ( typeof self !== 'undefined' ) animation.setContext( self ); + background.render( currentRenderList, scene ); - this.setAnimationLoop = function ( callback ) { + // render scene - onAnimationFrameCallback = callback; - xr.setAnimationLoop( callback ); + currentRenderState.setupLights( _this.useLegacyLights ); - ( callback === null ) ? animation.stop() : animation.start(); + if ( camera.isArrayCamera ) { - }; + const cameras = camera.cameras; - xr.addEventListener( 'sessionstart', onXRSessionStart ); - xr.addEventListener( 'sessionend', onXRSessionEnd ); + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - // Rendering + const camera2 = cameras[ i ]; - this.render = function ( scene, camera ) { + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - if ( camera !== undefined && camera.isCamera !== true ) { + } - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; + } else { - } + renderScene( currentRenderList, scene, camera ); - if ( _isContextLost === true ) return; + } - // update scene graph + // - if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); + if ( _currentRenderTarget !== null ) { - // update camera matrices and frustum + // resolve multisample renderbuffers to a single-sample texture if necessary - if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); + textures.updateMultisampleRenderTarget( _currentRenderTarget ); - if ( xr.enabled === true && xr.isPresenting === true ) { + // Generate mipmap if we're using any kind of mipmap filtering - if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); + textures.updateRenderTargetMipmap( _currentRenderTarget ); - camera = xr.getCamera(); // use XR camera for rendering + } - } + // - // - if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); + if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); - currentRenderState = renderStates.get( scene, renderStateStack.length ); - currentRenderState.init(); + // _gl.finish(); - renderStateStack.push( currentRenderState ); + bindingStates.resetDefaultState(); + _currentMaterialId = - 1; + _currentCamera = null; - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromProjectionMatrix( _projScreenMatrix ); + renderStateStack.pop(); - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); + if ( renderStateStack.length > 0 ) { - currentRenderList = renderLists.get( scene, renderListStack.length ); - currentRenderList.init(); + currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; - renderListStack.push( currentRenderList ); + } else { - projectObject( scene, camera, 0, _this.sortObjects ); + currentRenderState = null; - currentRenderList.finish(); + } - if ( _this.sortObjects === true ) { + renderListStack.pop(); - currentRenderList.sort( _opaqueSort, _transparentSort ); + if ( renderListStack.length > 0 ) { - } + currentRenderList = renderListStack[ renderListStack.length - 1 ]; - // + } else { - if ( _clippingEnabled === true ) clipping.beginShadows(); + currentRenderList = null; - const shadowsArray = currentRenderState.state.shadowsArray; + } - shadowMap.render( shadowsArray, scene, camera ); + }; - if ( _clippingEnabled === true ) clipping.endShadows(); + function projectObject( object, camera, groupOrder, sortObjects ) { - // + if ( object.visible === false ) return; - if ( this.info.autoReset === true ) this.info.reset(); + const visible = object.layers.test( camera.layers ); - // + if ( visible ) { - background.render( currentRenderList, scene ); + if ( object.isGroup ) { - // render scene + groupOrder = object.renderOrder; - currentRenderState.setupLights( _this.physicallyCorrectLights ); + } else if ( object.isLOD ) { - if ( camera.isArrayCamera ) { + if ( object.autoUpdate === true ) object.update( camera ); - const cameras = camera.cameras; + } else if ( object.isLight ) { - for ( let i = 0, l = cameras.length; i < l; i ++ ) { + currentRenderState.pushLight( object ); - const camera2 = cameras[ i ]; + if ( object.castShadow ) { - renderScene( currentRenderList, scene, camera2, camera2.viewport ); + currentRenderState.pushShadow( object ); - } + } - } else { + } else if ( object.isSprite ) { - renderScene( currentRenderList, scene, camera ); + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - } + if ( sortObjects ) { - // + _vector3.setFromMatrixPosition( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - if ( _currentRenderTarget !== null ) { + } - // resolve multisample renderbuffers to a single-sample texture if necessary + const geometry = objects.update( object ); + const material = object.material; - textures.updateMultisampleRenderTarget( _currentRenderTarget ); + if ( material.visible ) { - // Generate mipmap if we're using any kind of mipmap filtering + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); - textures.updateRenderTargetMipmap( _currentRenderTarget ); + } - } + } - // + } else if ( object.isMesh || object.isLine || object.isPoints ) { - if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - // _gl.finish(); + if ( object.isSkinnedMesh ) { - bindingStates.resetDefaultState(); - _currentMaterialId = - 1; - _currentCamera = null; + // update skeleton only once in a frame - renderStateStack.pop(); + if ( object.skeleton.frame !== info.render.frame ) { - if ( renderStateStack.length > 0 ) { + object.skeleton.update(); + object.skeleton.frame = info.render.frame; - currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; + } - } else { + } - currentRenderState = null; + const geometry = objects.update( object ); + const material = object.material; - } + if ( sortObjects ) { - renderListStack.pop(); + if ( object.boundingSphere !== undefined ) { - if ( renderListStack.length > 0 ) { + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + _vector3.copy( object.boundingSphere.center ); - currentRenderList = renderListStack[ renderListStack.length - 1 ]; + } else { - } else { + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _vector3.copy( geometry.boundingSphere.center ); - currentRenderList = null; + } - } + _vector3 + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - }; + } - function projectObject( object, camera, groupOrder, sortObjects ) { + if ( Array.isArray( material ) ) { - if ( object.visible === false ) return; + const groups = geometry.groups; - const visible = object.layers.test( camera.layers ); + for ( let i = 0, l = groups.length; i < l; i ++ ) { - if ( visible ) { + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - if ( object.isGroup ) { + if ( groupMaterial && groupMaterial.visible ) { - groupOrder = object.renderOrder; + currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); - } else if ( object.isLOD ) { + } - if ( object.autoUpdate === true ) object.update( camera ); + } - } else if ( object.isLight ) { + } else if ( material.visible ) { - currentRenderState.pushLight( object ); + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); - if ( object.castShadow ) { + } - currentRenderState.pushShadow( object ); + } } - } else if ( object.isSprite ) { + } - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + const children = object.children; - if ( sortObjects ) { + for ( let i = 0, l = children.length; i < l; i ++ ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + projectObject( children[ i ], camera, groupOrder, sortObjects ); - } + } - const geometry = objects.update( object ); - const material = object.material; + } - if ( material.visible ) { + function renderScene( currentRenderList, scene, camera, viewport ) { - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; + const transparentObjects = currentRenderList.transparent; - } + currentRenderState.setupLightsView( camera ); - } + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - } else if ( object.isMesh || object.isLine || object.isPoints ) { + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - if ( object.isSkinnedMesh ) { + if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); - // update skeleton only once in a frame + if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); + if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); + if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); - if ( object.skeleton.frame !== info.render.frame ) { + // Ensure depth buffer writing is enabled so it can be cleared on next render - object.skeleton.update(); - object.skeleton.frame = info.render.frame; + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); - } + state.setPolygonOffset( false ); - } + } - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { - if ( sortObjects ) { + const isWebGL2 = capabilities.isWebGL2; - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + if ( _transmissionRenderTarget === null ) { - } + _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { + generateMipmaps: true, + type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: ( isWebGL2 && antialias === true ) ? 4 : 0 + } ); - const geometry = objects.update( object ); - const material = object.material; + // debug - if ( Array.isArray( material ) ) { + /* + const geometry = new PlaneGeometry(); + const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); - const groups = geometry.groups; + const mesh = new Mesh( geometry, material ); + scene.add( mesh ); + */ - for ( let i = 0, l = groups.length; i < l; i ++ ) { + } - const group = groups[ i ]; - const groupMaterial = material[ group.materialIndex ]; + _this.getDrawingBufferSize( _vector2 ); - if ( groupMaterial && groupMaterial.visible ) { + if ( isWebGL2 ) { - currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); + _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); - } + } else { - } + _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); - } else if ( material.visible ) { + } - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + // - } + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget( _transmissionRenderTarget ); - } + _this.getClearColor( _currentClearColor ); + _currentClearAlpha = _this.getClearAlpha(); + if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); - } + _this.clear(); - } + // Turn off the features which can affect the frag color for opaque objects pass. + // Otherwise they are applied twice in opaque objects pass and transmission objects pass. + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; - const children = object.children; + renderObjects( opaqueObjects, scene, camera ); - for ( let i = 0, l = children.length; i < l; i ++ ) { + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - projectObject( children[ i ], camera, groupOrder, sortObjects ); + let renderTargetNeedsUpdate = false; - } + for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { - } + const renderItem = transmissiveObjects[ i ]; - function renderScene( currentRenderList, scene, camera, viewport ) { + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = renderItem.material; + const group = renderItem.group; - const opaqueObjects = currentRenderList.opaque; - const transmissiveObjects = currentRenderList.transmissive; - const transparentObjects = currentRenderList.transparent; + if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { - currentRenderState.setupLightsView( camera ); + const currentSide = material.side; - if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); + material.side = BackSide; + material.needsUpdate = true; - if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, scene, camera ); + renderObject( object, scene, camera, geometry, material, group ); - if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); + material.side = currentSide; + material.needsUpdate = true; - if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); - if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); - if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); + renderTargetNeedsUpdate = true; - // Ensure depth buffer writing is enabled so it can be cleared on next render + } - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); + } - state.setPolygonOffset( false ); + if ( renderTargetNeedsUpdate === true ) { - } + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - function renderTransmissionPass( opaqueObjects, scene, camera ) { + } - const isWebGL2 = capabilities.isWebGL2; + _this.setRenderTarget( currentRenderTarget ); - if ( _transmissionRenderTarget === null ) { + _this.setClearColor( _currentClearColor, _currentClearAlpha ); - _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { - generateMipmaps: true, - type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, - minFilter: LinearMipmapLinearFilter, - samples: ( isWebGL2 && _antialias === true ) ? 4 : 0 - } ); + _this.toneMapping = currentToneMapping; } - _this.getDrawingBufferSize( _vector2 ); - - if ( isWebGL2 ) { + function renderObjects( renderList, scene, camera ) { - _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - } else { + for ( let i = 0, l = renderList.length; i < l; i ++ ) { - _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); + const renderItem = renderList[ i ]; - } + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = overrideMaterial === null ? renderItem.material : overrideMaterial; + const group = renderItem.group; - // + if ( object.layers.test( camera.layers ) ) { - const currentRenderTarget = _this.getRenderTarget(); - _this.setRenderTarget( _transmissionRenderTarget ); - _this.clear(); + renderObject( object, scene, camera, geometry, material, group ); - // Turn off the features which can affect the frag color for opaque objects pass. - // Otherwise they are applied twice in opaque objects pass and transmission objects pass. - const currentToneMapping = _this.toneMapping; - _this.toneMapping = NoToneMapping; + } - renderObjects( opaqueObjects, scene, camera ); + } - _this.toneMapping = currentToneMapping; + } - textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); - textures.updateRenderTargetMipmap( _transmissionRenderTarget ); + function renderObject( object, scene, camera, geometry, material, group ) { - _this.setRenderTarget( currentRenderTarget ); + object.onBeforeRender( _this, scene, camera, geometry, material, group ); - } + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - function renderObjects( renderList, scene, camera ) { + material.onBeforeRender( _this, scene, camera, geometry, object, group ); - const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - for ( let i = 0, l = renderList.length; i < l; i ++ ) { + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - const renderItem = renderList[ i ]; + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - const object = renderItem.object; - const geometry = renderItem.geometry; - const material = overrideMaterial === null ? renderItem.material : overrideMaterial; - const group = renderItem.group; + material.side = DoubleSide; - if ( object.layers.test( camera.layers ) ) { + } else { - renderObject( object, scene, camera, geometry, material, group ); + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); } + object.onAfterRender( _this, scene, camera, geometry, material, group ); + } - } + function getProgram( material, scene, object ) { - function renderObject( object, scene, camera, geometry, material, group ) { + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + const materialProperties = properties.get( material ); - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; - material.onBeforeRender( _this, scene, camera, geometry, object, group ); + const lightsStateVersion = lights.state.version; - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); + const programCacheKey = programCache.getProgramCacheKey( parameters ); - material.side = BackSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + let programs = materialProperties.programs; - material.side = FrontSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - material.side = DoubleSide; + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); - } else { + if ( programs === undefined ) { - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + // new material - } + material.addEventListener( 'dispose', onMaterialDispose ); - object.onAfterRender( _this, scene, camera, geometry, material, group ); + programs = new Map(); + materialProperties.programs = programs; - } + } - function getProgram( material, scene, object ) { + let program = programs.get( programCacheKey ); - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + if ( program !== undefined ) { - const materialProperties = properties.get( material ); + // early out if program and light state is identical + + if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { + + updateCommonMaterialProperties( material, parameters ); - const lights = currentRenderState.state.lights; - const shadowsArray = currentRenderState.state.shadowsArray; + return program; - const lightsStateVersion = lights.state.version; + } - const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); - const programCacheKey = programCache.getProgramCacheKey( parameters ); + } else { - let programs = materialProperties.programs; + parameters.uniforms = programCache.getUniforms( material ); - // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change + material.onBuild( object, parameters, _this ); - materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; - materialProperties.fog = scene.fog; - materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + material.onBeforeCompile( parameters, _this ); - if ( programs === undefined ) { + program = programCache.acquireProgram( parameters, programCacheKey ); + programs.set( programCacheKey, program ); - // new material + materialProperties.uniforms = parameters.uniforms; - material.addEventListener( 'dispose', onMaterialDispose ); + } - programs = new Map(); - materialProperties.programs = programs; + const uniforms = materialProperties.uniforms; - } + if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { - let program = programs.get( programCacheKey ); + uniforms.clippingPlanes = clipping.uniform; - if ( program !== undefined ) { + } - // early out if program and light state is identical + updateCommonMaterialProperties( material, parameters ); - if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { + // store the light setup it was created for - updateCommonMaterialProperties( material, parameters ); + materialProperties.needsLights = materialNeedsLights( material ); + materialProperties.lightsStateVersion = lightsStateVersion; - return program; + if ( materialProperties.needsLights ) { - } + // wire up the material to this renderer's lighting state - } else { + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.lightProbe.value = lights.state.probe; + uniforms.directionalLights.value = lights.state.directional; + uniforms.directionalLightShadows.value = lights.state.directionalShadow; + uniforms.spotLights.value = lights.state.spot; + uniforms.spotLightShadows.value = lights.state.spotShadow; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.ltc_1.value = lights.state.rectAreaLTC1; + uniforms.ltc_2.value = lights.state.rectAreaLTC2; + uniforms.pointLights.value = lights.state.point; + uniforms.pointLightShadows.value = lights.state.pointShadow; + uniforms.hemisphereLights.value = lights.state.hemi; - parameters.uniforms = programCache.getUniforms( material ); + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; + uniforms.spotLightMap.value = lights.state.spotLightMap; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + // TODO (abelnation): add area lights shadow info to uniforms - material.onBuild( object, parameters, _this ); + } - material.onBeforeCompile( parameters, _this ); + const progUniforms = program.getUniforms(); + const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); - program = programCache.acquireProgram( parameters, programCacheKey ); - programs.set( programCacheKey, program ); + materialProperties.currentProgram = program; + materialProperties.uniformsList = uniformsList; - materialProperties.uniforms = parameters.uniforms; + return program; } - const uniforms = materialProperties.uniforms; + function updateCommonMaterialProperties( material, parameters ) { - if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { + const materialProperties = properties.get( material ); - uniforms.clippingPlanes = clipping.uniform; + materialProperties.outputColorSpace = parameters.outputColorSpace; + materialProperties.instancing = parameters.instancing; + materialProperties.skinning = parameters.skinning; + materialProperties.morphTargets = parameters.morphTargets; + materialProperties.morphNormals = parameters.morphNormals; + materialProperties.morphColors = parameters.morphColors; + materialProperties.morphTargetsCount = parameters.morphTargetsCount; + materialProperties.numClippingPlanes = parameters.numClippingPlanes; + materialProperties.numIntersection = parameters.numClipIntersection; + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } - updateCommonMaterialProperties( material, parameters ); + function setProgram( camera, scene, geometry, material, object ) { - // store the light setup it was created for + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - materialProperties.needsLights = materialNeedsLights( material ); - materialProperties.lightsStateVersion = lightsStateVersion; + textures.resetTextureUnits(); - if ( materialProperties.needsLights ) { + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); + const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); + const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; + const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); + const morphTargets = !! geometry.morphAttributes.position; + const morphNormals = !! geometry.morphAttributes.normal; + const morphColors = !! geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; - // wire up the material to this renderer's lighting state + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.lightProbe.value = lights.state.probe; - uniforms.directionalLights.value = lights.state.directional; - uniforms.directionalLightShadows.value = lights.state.directionalShadow; - uniforms.spotLights.value = lights.state.spot; - uniforms.spotLightShadows.value = lights.state.spotShadow; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.ltc_1.value = lights.state.rectAreaLTC1; - uniforms.ltc_2.value = lights.state.rectAreaLTC2; - uniforms.pointLights.value = lights.state.point; - uniforms.pointLightShadows.value = lights.state.pointShadow; - uniforms.hemisphereLights.value = lights.state.hemi; + const materialProperties = properties.get( material ); + const lights = currentRenderState.state.lights; - uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; - uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; - uniforms.spotShadowMap.value = lights.state.spotShadowMap; - uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; - uniforms.spotLightMap.value = lights.state.spotLightMap; - uniforms.pointShadowMap.value = lights.state.pointShadowMap; - uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; - // TODO (abelnation): add area lights shadow info to uniforms + if ( _clippingEnabled === true ) { - } + if ( _localClippingEnabled === true || camera !== _currentCamera ) { - const progUniforms = program.getUniforms(); - const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); + const useCache = + camera === _currentCamera && + material.id === _currentMaterialId; - materialProperties.currentProgram = program; - materialProperties.uniformsList = uniformsList; + // we might want to call this function with some ClippingGroup + // object instead of the material, once it becomes feasible + // (#8465, #8379) + clipping.setState( material, camera, useCache ); - return program; + } - } + } - function updateCommonMaterialProperties( material, parameters ) { + // - const materialProperties = properties.get( material ); + let needsProgramChange = false; - materialProperties.outputEncoding = parameters.outputEncoding; - materialProperties.instancing = parameters.instancing; - materialProperties.skinning = parameters.skinning; - materialProperties.morphTargets = parameters.morphTargets; - materialProperties.morphNormals = parameters.morphNormals; - materialProperties.morphColors = parameters.morphColors; - materialProperties.morphTargetsCount = parameters.morphTargetsCount; - materialProperties.numClippingPlanes = parameters.numClippingPlanes; - materialProperties.numIntersection = parameters.numClipIntersection; - materialProperties.vertexAlphas = parameters.vertexAlphas; - materialProperties.vertexTangents = parameters.vertexTangents; - materialProperties.toneMapping = parameters.toneMapping; + if ( material.version === materialProperties.__version ) { - } + if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { - function setProgram( camera, scene, geometry, material, object ) { + needsProgramChange = true; - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + } else if ( materialProperties.outputColorSpace !== colorSpace ) { - textures.resetTextureUnits(); + needsProgramChange = true; - const fog = scene.fog; - const environment = material.isMeshStandardMaterial ? scene.environment : null; - const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding ); - const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); - const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; - const vertexTangents = !! material.normalMap && !! geometry.attributes.tangent; - const morphTargets = !! geometry.morphAttributes.position; - const morphNormals = !! geometry.morphAttributes.normal; - const morphColors = !! geometry.morphAttributes.color; - const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; + } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + needsProgramChange = true; - const materialProperties = properties.get( material ); - const lights = currentRenderState.state.lights; + } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { - if ( _clippingEnabled === true ) { + needsProgramChange = true; - if ( _localClippingEnabled === true || camera !== _currentCamera ) { + } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { - const useCache = - camera === _currentCamera && - material.id === _currentMaterialId; + needsProgramChange = true; - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - clipping.setState( material, camera, useCache ); + } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { - } + needsProgramChange = true; - } + } else if ( materialProperties.envMap !== envMap ) { - // + needsProgramChange = true; - let needsProgramChange = false; + } else if ( material.fog === true && materialProperties.fog !== fog ) { - if ( material.version === materialProperties.__version ) { + needsProgramChange = true; - if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { + } else if ( materialProperties.numClippingPlanes !== undefined && + ( materialProperties.numClippingPlanes !== clipping.numPlanes || + materialProperties.numIntersection !== clipping.numIntersection ) ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( materialProperties.outputEncoding !== encoding ) { + } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { + } else if ( materialProperties.vertexTangents !== vertexTangents ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { + } else if ( materialProperties.morphTargets !== morphTargets ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { + } else if ( materialProperties.morphNormals !== morphNormals ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { + } else if ( materialProperties.morphColors !== morphColors ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( materialProperties.envMap !== envMap ) { + } else if ( materialProperties.toneMapping !== toneMapping ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( material.fog === true && materialProperties.fog !== fog ) { + } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { - needsProgramChange = true; + needsProgramChange = true; - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== clipping.numPlanes || - materialProperties.numIntersection !== clipping.numIntersection ) ) { + } + + } else { needsProgramChange = true; + materialProperties.__version = material.version; - } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { + } - needsProgramChange = true; + // - } else if ( materialProperties.vertexTangents !== vertexTangents ) { + let program = materialProperties.currentProgram; - needsProgramChange = true; + if ( needsProgramChange === true ) { - } else if ( materialProperties.morphTargets !== morphTargets ) { + program = getProgram( material, scene, object ); - needsProgramChange = true; + } - } else if ( materialProperties.morphNormals !== morphNormals ) { + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; - needsProgramChange = true; + const p_uniforms = program.getUniforms(), + m_uniforms = materialProperties.uniforms; - } else if ( materialProperties.morphColors !== morphColors ) { + if ( state.useProgram( program.program ) ) { - needsProgramChange = true; + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; - } else if ( materialProperties.toneMapping !== toneMapping ) { + } - needsProgramChange = true; + if ( material.id !== _currentMaterialId ) { - } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { + _currentMaterialId = material.id; - needsProgramChange = true; + refreshMaterial = true; } - } else { + if ( refreshProgram || _currentCamera !== camera ) { - needsProgramChange = true; - materialProperties.__version = material.version; + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); - } + if ( capabilities.logarithmicDepthBuffer ) { - // + p_uniforms.setValue( _gl, 'logDepthBufFC', + 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + + } - let program = materialProperties.currentProgram; + if ( _currentCamera !== camera ) { - if ( needsProgramChange === true ) { + _currentCamera = camera; - program = getProgram( material, scene, object ); + // lighting uniforms depend on the camera so enforce an update + // now, in case this material supports lights - or later, when + // the next material that does gets activated: - } + refreshMaterial = true; // set to true on material change + refreshLights = true; // remains set until update done - let refreshProgram = false; - let refreshMaterial = false; - let refreshLights = false; + } - const p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.uniforms; + // load material specific uniforms + // (shader material also gets them for the sake of genericity) - if ( state.useProgram( program.program ) ) { + if ( material.isShaderMaterial || + material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshStandardMaterial || + material.envMap ) { - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; + const uCamPos = p_uniforms.map.cameraPosition; - } + if ( uCamPos !== undefined ) { - if ( material.id !== _currentMaterialId ) { + uCamPos.setValue( _gl, + _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + + } - _currentMaterialId = material.id; + } - refreshMaterial = true; + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial ) { - } + p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); - if ( refreshProgram || _currentCamera !== camera ) { + } - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial || + material.isShadowMaterial || + object.isSkinnedMesh ) { - if ( capabilities.logarithmicDepthBuffer ) { + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + } } - if ( _currentCamera !== camera ) { + // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures + // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures - _currentCamera = camera; + if ( object.isSkinnedMesh ) { - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: + p_uniforms.setOptional( _gl, object, 'bindMatrix' ); + p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done + const skeleton = object.skeleton; - } + if ( skeleton ) { + + if ( capabilities.floatVertexTextures ) { - // load material specific uniforms - // (shader material also gets them for the sake of genericity) + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshStandardMaterial || - material.envMap ) { + p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); + p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); - const uCamPos = p_uniforms.map.cameraPosition; + } else { - if ( uCamPos !== undefined ) { + console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + } } } - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial ) { + const morphAttributes = geometry.morphAttributes; - p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); + if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { + + morphtargets.update( object, geometry, program ); } - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.isShadowMaterial || - object.isSkinnedMesh ) { + if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); } - } + // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 - // skinning and morph target uniforms must be set even if material didn't change - // auto-setting of texture unit for bone and morph texture must go before other textures - // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures + if ( material.isMeshGouraudMaterial && material.envMap !== null ) { - if ( object.isSkinnedMesh ) { + m_uniforms.envMap.value = envMap; - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); + m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - const skeleton = object.skeleton; + } - if ( skeleton ) { + if ( refreshMaterial ) { - if ( capabilities.floatVertexTextures ) { + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); + if ( materialProperties.needsLights ) { - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); + // the current material requires lighting info - } else { + // note: all lighting uniforms are always set correctly + // they simply reference the renderer's state for their + // values + // + // use the current material's .needsUpdate flags to set + // the GL state when required - console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); + markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); } - } - - } - - const morphAttributes = geometry.morphAttributes; + // refresh uniforms common to several materials - if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { + if ( fog && material.fog === true ) { - morphtargets.update( object, geometry, material, program ); + materials.refreshFogUniforms( m_uniforms, fog ); - } + } - if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { + materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); - materialProperties.receiveShadow = object.receiveShadow; - p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - } + } - // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 + if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { - if ( material.isMeshGouraudMaterial && material.envMap !== null ) { + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + material.uniformsNeedUpdate = false; - m_uniforms.envMap.value = envMap; + } - m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; + if ( material.isSpriteMaterial ) { - } + p_uniforms.setValue( _gl, 'center', object.center ); - if ( refreshMaterial ) { + } - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); + // common matrices - if ( materialProperties.needsLights ) { + p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); + p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - // the current material requires lighting info + // UBOs - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); + const groups = material.uniformsGroups; - } + for ( let i = 0, l = groups.length; i < l; i ++ ) { - // refresh uniforms common to several materials + if ( capabilities.isWebGL2 ) { - if ( fog && material.fog === true ) { + const group = groups[ i ]; - materials.refreshFogUniforms( m_uniforms, fog ); + uniformsGroups.update( group, program ); + uniformsGroups.bind( group, program ); - } + } else { - materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); + console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + } - } + } - if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { + } - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - material.uniformsNeedUpdate = false; + return program; } - if ( material.isSpriteMaterial ) { - - p_uniforms.setValue( _gl, 'center', object.center ); + // If uniforms are marked as clean, they don't need to be loaded to the GPU. - } + function markUniformsLightsNeedsUpdate( uniforms, value ) { - // common matrices + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + uniforms.directionalLights.needsUpdate = value; + uniforms.directionalLightShadows.needsUpdate = value; + uniforms.pointLights.needsUpdate = value; + uniforms.pointLightShadows.needsUpdate = value; + uniforms.spotLights.needsUpdate = value; + uniforms.spotLightShadows.needsUpdate = value; + uniforms.rectAreaLights.needsUpdate = value; + uniforms.hemisphereLights.needsUpdate = value; - // UBOs + } - if ( material.isShaderMaterial || material.isRawShaderMaterial ) { + function materialNeedsLights( material ) { - const groups = material.uniformsGroups; + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + material.isMeshStandardMaterial || material.isShadowMaterial || + ( material.isShaderMaterial && material.lights === true ); - for ( let i = 0, l = groups.length; i < l; i ++ ) { + } - if ( capabilities.isWebGL2 ) { + this.getActiveCubeFace = function () { - const group = groups[ i ]; + return _currentActiveCubeFace; - uniformsGroups.update( group, program ); - uniformsGroups.bind( group, program ); + }; - } else { + this.getActiveMipmapLevel = function () { - console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); + return _currentActiveMipmapLevel; - } + }; - } + this.getRenderTarget = function () { - } + return _currentRenderTarget; - return program; + }; - } + this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { - // If uniforms are marked as clean, they don't need to be loaded to the GPU. + properties.get( renderTarget.texture ).__webglTexture = colorTexture; + properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; - function markUniformsLightsNeedsUpdate( uniforms, value ) { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; - uniforms.ambientLightColor.needsUpdate = value; - uniforms.lightProbe.needsUpdate = value; + if ( renderTargetProperties.__hasExternalTextures ) { - uniforms.directionalLights.needsUpdate = value; - uniforms.directionalLightShadows.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.pointLightShadows.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.spotLightShadows.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; - } + if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { - function materialNeedsLights( material ) { + // The multisample_render_to_texture extension doesn't work properly if there + // are midframe flushes and an external depth buffer. Disable use of the extension. + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { - return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || - material.isMeshStandardMaterial || material.isShadowMaterial || - ( material.isShaderMaterial && material.lights === true ); + console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); + renderTargetProperties.__useRenderToTexture = false; - } + } - this.getActiveCubeFace = function () { + } - return _currentActiveCubeFace; + } - }; + }; - this.getActiveMipmapLevel = function () { + this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { - return _currentActiveMipmapLevel; + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; - }; + }; - this.getRenderTarget = function () { + this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { - return _currentRenderTarget; + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; - }; + let useDefaultFramebuffer = true; + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; - this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { + if ( renderTarget ) { - properties.get( renderTarget.texture ).__webglTexture = colorTexture; - properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; + const renderTargetProperties = properties.get( renderTarget ); - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__hasExternalTextures = true; + if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { - if ( renderTargetProperties.__hasExternalTextures ) { + // We need to make sure to rebind the framebuffer. + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); + useDefaultFramebuffer = false; - renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; + } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { - if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { + textures.setupRenderTarget( renderTarget ); - // The multisample_render_to_texture extension doesn't work properly if there - // are midframe flushes and an external depth buffer. Disable use of the extension. - if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { + } else if ( renderTargetProperties.__hasExternalTextures ) { - console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); - renderTargetProperties.__useRenderToTexture = false; + // Color and depth texture must be rebound in order for the swapchain to update. + textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); } - } - - } - - }; + const texture = renderTarget.texture; - this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { + if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__webglFramebuffer = defaultFramebuffer; - renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; + isRenderTarget3D = true; - }; + } - this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { + const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - _currentRenderTarget = renderTarget; - _currentActiveCubeFace = activeCubeFace; - _currentActiveMipmapLevel = activeMipmapLevel; + if ( renderTarget.isWebGLCubeRenderTarget ) { - let useDefaultFramebuffer = true; - let framebuffer = null; - let isCube = false; - let isRenderTarget3D = false; + framebuffer = __webglFramebuffer[ activeCubeFace ]; + isCube = true; - if ( renderTarget ) { + } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { - const renderTargetProperties = properties.get( renderTarget ); + framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; - if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { + } else { - // We need to make sure to rebind the framebuffer. - state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - useDefaultFramebuffer = false; + framebuffer = __webglFramebuffer; - } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { + } - textures.setupRenderTarget( renderTarget ); + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; - } else if ( renderTargetProperties.__hasExternalTextures ) { + } else { - // Color and depth texture must be rebound in order for the swapchain to update. - textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); + _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); + _currentScissorTest = _scissorTest; } - const texture = renderTarget.texture; + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { - isRenderTarget3D = true; + state.drawBuffers( renderTarget, framebuffer ); } - const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); - if ( renderTarget.isWebGLCubeRenderTarget ) { + if ( isCube ) { - framebuffer = __webglFramebuffer[ activeCubeFace ]; - isCube = true; + const textureProperties = properties.get( renderTarget.texture ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); - } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { + } else if ( isRenderTarget3D ) { - framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; + const textureProperties = properties.get( renderTarget.texture ); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); - } else { + } - framebuffer = __webglFramebuffer; + _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings - } + }; - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; + this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - } else { + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); - _currentScissorTest = _scissorTest; + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; - } + } - const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - state.drawBuffers( renderTarget, framebuffer ); + framebuffer = framebuffer[ activeCubeFaceIndex ]; - } + } - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); + if ( framebuffer ) { - if ( isCube ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - const textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); + try { - } else if ( isRenderTarget3D ) { + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - const textureProperties = properties.get( renderTarget.texture ); - const layer = activeCubeFace || 0; - _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { - } + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + return; - _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings + } - }; + const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) + ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox + ! halfFloatSupportedByExt ) { - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + return; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; + } - } + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - let framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - framebuffer = framebuffer[ activeCubeFaceIndex ]; + } - } + } finally { - if ( framebuffer ) { + // restore framebuffer of current render target if necessary - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - try { + } - const texture = renderTarget.texture; - const textureFormat = texture.format; - const textureType = texture.type; + } - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + }; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; + this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { - } + const levelScale = Math.pow( 2, - level ); + const width = Math.floor( texture.image.width * levelScale ); + const height = Math.floor( texture.image.height * levelScale ); - const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); + textures.setTexture2D( texture, 0 ); - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! halfFloatSupportedByExt ) { + _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; + state.unbindTexture(); - } + }; - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + const width = srcTexture.image.width; + const height = srcTexture.image.height; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); + textures.setTexture2D( dstTexture, 0 ); - } + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - } finally { + if ( srcTexture.isDataTexture ) { - // restore framebuffer of current render target if necessary + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); - const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + } else { - } + if ( srcTexture.isCompressedTexture ) { - } + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); - }; + } else { - this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); - const levelScale = Math.pow( 2, - level ); - const width = Math.floor( texture.image.width * levelScale ); - const height = Math.floor( texture.image.height * levelScale ); + } - textures.setTexture2D( texture, 0 ); + } - _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); - state.unbindTexture(); + state.unbindTexture(); - }; + }; - this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { + this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { - const width = srcTexture.image.width; - const height = srcTexture.image.height; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); + if ( _this.isWebGL1Renderer ) { - textures.setTexture2D( dstTexture, 0 ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); + return; - // As another texture upload may have changed pixelStorei - // parameters, make sure they are correct for the dstTexture - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + } - if ( srcTexture.isDataTexture ) { + const width = sourceBox.max.x - sourceBox.min.x + 1; + const height = sourceBox.max.y - sourceBox.min.y + 1; + const depth = sourceBox.max.z - sourceBox.min.z + 1; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; - _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); + if ( dstTexture.isData3DTexture ) { - } else { + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; - if ( srcTexture.isCompressedTexture ) { + } else if ( dstTexture.isDataArrayTexture ) { - _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; } else { - _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; } - } - - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - state.unbindTexture(); + const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - }; + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; - this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); - if ( _this.isWebGL1Renderer ) { + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); - return; + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); - } + } else { - const width = sourceBox.max.x - sourceBox.min.x + 1; - const height = sourceBox.max.y - sourceBox.min.y + 1; - const depth = sourceBox.max.z - sourceBox.min.z + 1; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); - let glTarget; + if ( srcTexture.isCompressedArrayTexture ) { - if ( dstTexture.isData3DTexture ) { + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); + _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); - textures.setTexture3D( dstTexture, 0 ); - glTarget = _gl.TEXTURE_3D; + } else { - } else if ( dstTexture.isDataArrayTexture ) { + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); - textures.setTexture2DArray( dstTexture, 0 ); - glTarget = _gl.TEXTURE_2D_ARRAY; + } - } else { + } - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); - return; + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); - } + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + state.unbindTexture(); - const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); - const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); - const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); - const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); - const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); + }; - const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; + this.initTexture = function ( texture ) { - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); + if ( texture.isCubeTexture ) { - if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { + textures.setTextureCube( texture, 0 ); - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); + } else if ( texture.isData3DTexture ) { - } else { + textures.setTexture3D( texture, 0 ); - if ( srcTexture.isCompressedArrayTexture ) { + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); - _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); + textures.setTexture2DArray( texture, 0 ); } else { - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); + textures.setTexture2D( texture, 0 ); } - } - - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); - - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); + state.unbindTexture(); - state.unbindTexture(); + }; - }; + this.resetState = function () { - this.initTexture = function ( texture ) { + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; - if ( texture.isCubeTexture ) { + state.reset(); + bindingStates.reset(); - textures.setTextureCube( texture, 0 ); + }; - } else if ( texture.isData3DTexture ) { + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - textures.setTexture3D( texture, 0 ); + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); - } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + } - textures.setTexture2DArray( texture, 0 ); + } - } else { + get physicallyCorrectLights() { // @deprecated, r150 - textures.setTexture2D( texture, 0 ); + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + return ! this.useLegacyLights; - } + } - state.unbindTexture(); + set physicallyCorrectLights( value ) { // @deprecated, r150 - }; + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + this.useLegacyLights = ! value; - this.resetState = function () { + } - _currentActiveCubeFace = 0; - _currentActiveMipmapLevel = 0; - _currentRenderTarget = null; + get outputEncoding() { // @deprecated, r152 - state.reset(); - bindingStates.reset(); + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + return this.outputColorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; - }; + } - if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + set outputEncoding( encoding ) { // @deprecated, r152 - __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + this.outputColorSpace = encoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; } @@ -29716,16 +30362,14 @@ } - // @deprecated - - get autoUpdate() { + get autoUpdate() { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); return this.matrixWorldAutoUpdate; } - set autoUpdate( value ) { + set autoUpdate( value ) { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); this.matrixWorldAutoUpdate = value; @@ -29875,7 +30519,7 @@ } - const _vector$6 = /*@__PURE__*/ new Vector3(); + const _vector$5 = /*@__PURE__*/ new Vector3(); class InterleavedBufferAttribute { @@ -29915,11 +30559,11 @@ for ( let i = 0, l = this.data.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.applyMatrix4( m ); + _vector$5.applyMatrix4( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -29931,11 +30575,11 @@ for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.applyNormalMatrix( m ); + _vector$5.applyNormalMatrix( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -29947,11 +30591,11 @@ for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.transformDirection( m ); + _vector$5.transformDirection( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -30371,7 +31015,7 @@ distance: distance, point: _intersectPoint.clone(), - uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), + uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), face: null, object: this @@ -30634,8 +31278,13 @@ const _skinIndex = /*@__PURE__*/ new Vector4(); const _skinWeight = /*@__PURE__*/ new Vector4(); - const _vector$5 = /*@__PURE__*/ new Vector3(); - const _matrix = /*@__PURE__*/ new Matrix4(); + const _vector3 = /*@__PURE__*/ new Vector3(); + const _matrix4 = /*@__PURE__*/ new Matrix4(); + const _vertex = /*@__PURE__*/ new Vector3(); + + const _sphere$3 = /*@__PURE__*/ new Sphere(); + const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); + const _ray$2 = /*@__PURE__*/ new Ray(); class SkinnedMesh extends Mesh { @@ -30651,6 +31300,57 @@ this.bindMatrix = new Matrix4(); this.bindMatrixInverse = new Matrix4(); + this.boundingBox = null; + this.boundingSphere = null; + + } + + computeBoundingBox() { + + const geometry = this.geometry; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + this.boundingBox.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + this.boundingSphere.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); + + } + } copy( source, recursive ) { @@ -30663,10 +31363,58 @@ this.skeleton = source.skeleton; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } + raycast( raycaster, intersects ) { + + const material = this.material; + const matrixWorld = this.matrixWorld; + + if ( material === undefined ) return; + + // test with bounding sphere in world space + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$3.copy( this.boundingSphere ); + _sphere$3.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; + + // convert ray to local space of skinned mesh + + _inverseMatrix$2.copy( matrixWorld ).invert(); + _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); + + // test with bounding box in local space + + if ( this.boundingBox !== null ) { + + if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; + + } + + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$2 ); + + } + + getVertexPosition( index, target ) { + + super.getVertexPosition( index, target ); + + this.applyBoneTransform( index, target ); + + return target; + + } + bind( skeleton, bindMatrix ) { this.skeleton = skeleton; @@ -30740,7 +31488,7 @@ } - boneTransform( index, target ) { + applyBoneTransform( index, vector ) { const skeleton = this.skeleton; const geometry = this.geometry; @@ -30748,9 +31496,9 @@ _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - _basePosition.copy( target ).applyMatrix4( this.bindMatrix ); + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); - target.set( 0, 0, 0 ); + vector.set( 0, 0, 0 ); for ( let i = 0; i < 4; i ++ ) { @@ -30760,18 +31508,26 @@ const boneIndex = _skinIndex.getComponent( i ); - _matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - target.addScaledVector( _vector$5.copy( _basePosition ).applyMatrix4( _matrix ), weight ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); } } - return target.applyMatrix4( this.bindMatrixInverse ); + return vector.applyMatrix4( this.bindMatrixInverse ); } + boneTransform( index, vector ) { // @deprecated, r151 + + console.warn( 'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' ); + return this.applyBoneTransform( index, vector ); + + } + + } class Bone extends Object3D { @@ -30790,9 +31546,9 @@ class DataTexture extends Texture { - constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding ) { + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isDataTexture = true; @@ -31048,7 +31804,7 @@ const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Skeleton', generator: 'Skeleton.toJSON' }, @@ -31118,8 +31874,10 @@ const _instanceIntersects = []; + const _box3 = /*@__PURE__*/ new Box3(); const _identity = /*@__PURE__*/ new Matrix4(); const _mesh = /*@__PURE__*/ new Mesh(); + const _sphere$2 = /*@__PURE__*/ new Sphere(); class InstancedMesh extends Mesh { @@ -31134,7 +31892,8 @@ this.count = count; - this.frustumCulled = false; + this.boundingBox = null; + this.boundingSphere = null; for ( let i = 0; i < count; i ++ ) { @@ -31144,6 +31903,68 @@ } + computeBoundingBox() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + this.boundingBox.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingBox.union( _box3 ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + if ( geometry.boundingSphere === null ) { + + geometry.computeBoundingSphere(); + + } + + this.boundingSphere.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingSphere.union( _sphere$2 ); + + } + + } + copy( source, recursive ) { super.copy( source, recursive ); @@ -31154,6 +31975,9 @@ this.count = source.count; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } @@ -31180,6 +32004,17 @@ if ( _mesh.material === undefined ) return; + // test with bounding sphere first + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$2.copy( this.boundingSphere ); + _sphere$2.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return; + + // now test each instance + for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { // calculate the world matrix for each instance @@ -31253,6 +32088,8 @@ this.color = new Color( 0xffffff ); + this.map = null; + this.linewidth = 1; this.linecap = 'round'; this.linejoin = 'round'; @@ -31270,6 +32107,8 @@ this.color.copy( source.color ); + this.map = source.map; + this.linewidth = source.linewidth; this.linecap = source.linecap; this.linejoin = source.linejoin; @@ -31814,14 +32653,12 @@ class FramebufferTexture extends Texture { - constructor( width, height, format ) { + constructor( width, height ) { super( { width, height } ); this.isFramebufferTexture = true; - this.format = format; - this.magFilter = NearestFilter; this.minFilter = NearestFilter; @@ -31835,9 +32672,9 @@ class CompressedTexture extends Texture { - constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCompressedTexture = true; @@ -32272,7 +33109,7 @@ const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Curve', generator: 'Curve.toJSON' } @@ -32978,13 +33815,15 @@ } - getTangent( t, optionalTarget ) { + getTangent( t, optionalTarget = new Vector2() ) { - const tangent = optionalTarget || new Vector2(); + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); - tangent.copy( this.v2 ).sub( this.v1 ).normalize(); + } - return tangent; + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); } @@ -33061,6 +33900,19 @@ return this.getPoint( u, optionalTarget ); } + + getTangent( t, optionalTarget = new Vector3() ) { + + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); + + } + + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); + + } + copy( source ) { super.copy( source ); @@ -33935,6 +34787,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); @@ -34048,6 +34910,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); @@ -34317,6 +35189,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); @@ -34648,6 +35530,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); @@ -34851,6 +35743,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } class Shape extends Path { @@ -35849,6 +36751,7 @@ * } */ + class ExtrudeGeometry extends BufferGeometry { constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) { @@ -35991,7 +36894,7 @@ if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); - return vec.clone().multiplyScalar( size ).add( pt ); + return pt.clone().addScaledVector( vec, size ); } @@ -36498,6 +37401,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -36796,6 +37709,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); @@ -36930,6 +37853,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -37030,11 +37963,11 @@ let uOffset = 0; - if ( iy == 0 && thetaStart == 0 ) { + if ( iy === 0 && thetaStart === 0 ) { uOffset = 0.5 / widthSegments; - } else if ( iy == heightSegments && thetaEnd == Math.PI ) { + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { uOffset = - 0.5 / widthSegments; @@ -37096,6 +38029,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); @@ -37232,6 +38175,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); @@ -37384,6 +38337,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); @@ -37551,6 +38514,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -37687,6 +38660,16 @@ } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } function isUniqueEdge( start, end, edges ) { @@ -37915,6 +38898,9 @@ this.type = 'MeshPhysicalMaterial'; + this.anisotropyRotation = 0; + this.anisotropyMap = null; + this.clearcoatMap = null; this.clearcoatRoughness = 0.0; this.clearcoatRoughnessMap = null; @@ -37958,30 +38944,31 @@ this.specularColor = new Color( 1, 1, 1 ); this.specularColorMap = null; - this._sheen = 0.0; + this._anisotropy = 0; this._clearcoat = 0; this._iridescence = 0; + this._sheen = 0.0; this._transmission = 0; this.setValues( parameters ); } - get sheen() { + get anisotropy() { - return this._sheen; + return this._anisotropy; } - set sheen( value ) { + set anisotropy( value ) { - if ( this._sheen > 0 !== value > 0 ) { + if ( this._anisotropy > 0 !== value > 0 ) { this.version ++; } - this._sheen = value; + this._anisotropy = value; } @@ -38021,6 +39008,24 @@ } + get sheen() { + + return this._sheen; + + } + + set sheen( value ) { + + if ( this._sheen > 0 !== value > 0 ) { + + this.version ++; + + } + + this._sheen = value; + + } + get transmission() { return this._transmission; @@ -38050,6 +39055,10 @@ }; + this.anisotropy = source.anisotropy; + this.anisotropyRotation = source.anisotropyRotation; + this.anisotropyMap = source.anisotropyMap; + this.clearcoat = source.clearcoat; this.clearcoatMap = source.clearcoatMap; this.clearcoatRoughness = source.clearcoatRoughness; @@ -38921,17 +39930,16 @@ } - var AnimationUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, + const AnimationUtils = { arraySlice: arraySlice, convertArray: convertArray, - flattenJSON: flattenJSON, - getKeyframeOrder: getKeyframeOrder, isTypedArray: isTypedArray, - makeClipAdditive: makeClipAdditive, + getKeyframeOrder: getKeyframeOrder, sortedArray: sortedArray, - subclip: subclip - }); + flattenJSON: flattenJSON, + subclip: subclip, + makeClipAdditive: makeClipAdditive + }; /** * Abstract base class of interpolants over parametric samples. @@ -41282,7 +42290,11 @@ texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - if ( texData.encoding !== undefined ) { + if ( texData.colorSpace !== undefined ) { + + texture.colorSpace = texData.colorSpace; + + } else if ( texData.encoding !== undefined ) { // @deprecated, r152 texture.encoding = texData.encoding; @@ -42331,6 +43343,8 @@ if ( json.thickness !== undefined ) material.thickness = json.thickness; if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); + if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; + if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; if ( json.fog !== undefined ) material.fog = json.fog; if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; if ( json.blending !== undefined ) material.blending = json.blending; @@ -42459,6 +43473,9 @@ } + if ( json.lights !== undefined ) material.lights = json.lights; + if ( json.clipping !== undefined ) material.clipping = json.clipping; + // for PointsMaterial if ( json.size !== undefined ) material.size = json.size; @@ -42531,6 +43548,8 @@ if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); + if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); + if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); @@ -43132,7 +44151,7 @@ geometry.uuid = data.uuid; if ( data.name !== undefined ) geometry.name = data.name; - if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData; + if ( data.userData !== undefined ) geometry.userData = data.userData; geometries[ data.uuid ] = geometry; @@ -43474,6 +44493,7 @@ if ( data.name !== undefined ) texture.name = data.name; if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); + if ( data.channel !== undefined ) texture.channel = data.channel; if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); @@ -43488,8 +44508,10 @@ } if ( data.format !== undefined ) texture.format = data.format; + if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; if ( data.type !== undefined ) texture.type = data.type; - if ( data.encoding !== undefined ) texture.encoding = data.encoding; + if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; + if ( data.encoding !== undefined ) texture.encoding = data.encoding; // @deprecated, r152 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); @@ -43500,6 +44522,7 @@ if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; + if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; if ( data.userData !== undefined ) texture.userData = data.userData; @@ -43798,6 +44821,8 @@ } + if ( data.up !== undefined ) object.up.fromArray( data.up ); + if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; @@ -44069,25 +45094,31 @@ onLoad( audioBuffer ); - } ); + }, handleError ); } catch ( e ) { - if ( onError ) { + handleError( e ); - onError( e ); + } - } else { + }, onProgress, onError ); - console.error( e ); + function handleError( e ) { - } + if ( onError ) { - scope.manager.itemError( url ); + onError( e ); + + } else { + + console.error( e ); } - }, onProgress, onError ); + scope.manager.itemError( url ); + + } } @@ -48188,6 +49219,7 @@ * The azimuthal angle (theta) is measured from the positive z-axis. */ + class Spherical { constructor( radius = 1, phi = 0, theta = 0 ) { @@ -48484,8 +49516,7 @@ distanceToPoint( point ) { - const clampedPoint = _vector$4.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector$4 ).distanceTo( point ); } @@ -48494,6 +49525,8 @@ this.min.max( box.min ); this.max.min( box.max ); + if ( this.isEmpty() ) this.makeEmpty(); + return this; } @@ -50137,179 +51170,7 @@ } - // Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - - const _tables = /*@__PURE__*/ _generateTables(); - - function _generateTables() { - - // float32 to float16 helpers - - const buffer = new ArrayBuffer( 4 ); - const floatView = new Float32Array( buffer ); - const uint32View = new Uint32Array( buffer ); - - const baseTable = new Uint32Array( 512 ); - const shiftTable = new Uint32Array( 512 ); - - for ( let i = 0; i < 256; ++ i ) { - - const e = i - 127; - - // very small number (0, -0) - - if ( e < - 27 ) { - - baseTable[ i ] = 0x0000; - baseTable[ i | 0x100 ] = 0x8000; - shiftTable[ i ] = 24; - shiftTable[ i | 0x100 ] = 24; - - // small number (denorm) - - } else if ( e < - 14 ) { - - baseTable[ i ] = 0x0400 >> ( - e - 14 ); - baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; - shiftTable[ i ] = - e - 1; - shiftTable[ i | 0x100 ] = - e - 1; - - // normal number - - } else if ( e <= 15 ) { - - baseTable[ i ] = ( e + 15 ) << 10; - baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; - shiftTable[ i ] = 13; - shiftTable[ i | 0x100 ] = 13; - - // large number (Infinity, -Infinity) - - } else if ( e < 128 ) { - - baseTable[ i ] = 0x7c00; - baseTable[ i | 0x100 ] = 0xfc00; - shiftTable[ i ] = 24; - shiftTable[ i | 0x100 ] = 24; - - // stay (NaN, Infinity, -Infinity) - - } else { - - baseTable[ i ] = 0x7c00; - baseTable[ i | 0x100 ] = 0xfc00; - shiftTable[ i ] = 13; - shiftTable[ i | 0x100 ] = 13; - - } - - } - - // float16 to float32 helpers - - const mantissaTable = new Uint32Array( 2048 ); - const exponentTable = new Uint32Array( 64 ); - const offsetTable = new Uint32Array( 64 ); - - for ( let i = 1; i < 1024; ++ i ) { - - let m = i << 13; // zero pad mantissa bits - let e = 0; // zero exponent - - // normalized - while ( ( m & 0x00800000 ) === 0 ) { - - m <<= 1; - e -= 0x00800000; // decrement exponent - - } - - m &= ~ 0x00800000; // clear leading 1 bit - e += 0x38800000; // adjust bias - - mantissaTable[ i ] = m | e; - - } - - for ( let i = 1024; i < 2048; ++ i ) { - - mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); - - } - - for ( let i = 1; i < 31; ++ i ) { - - exponentTable[ i ] = i << 23; - - } - - exponentTable[ 31 ] = 0x47800000; - exponentTable[ 32 ] = 0x80000000; - - for ( let i = 33; i < 63; ++ i ) { - - exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); - - } - - exponentTable[ 63 ] = 0xc7800000; - - for ( let i = 1; i < 64; ++ i ) { - - if ( i !== 32 ) { - - offsetTable[ i ] = 1024; - - } - - } - - return { - floatView: floatView, - uint32View: uint32View, - baseTable: baseTable, - shiftTable: shiftTable, - mantissaTable: mantissaTable, - exponentTable: exponentTable, - offsetTable: offsetTable - }; - - } - - // float32 to float16 - - function toHalfFloat( val ) { - - if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); - - val = clamp( val, - 65504, 65504 ); - - _tables.floatView[ 0 ] = val; - const f = _tables.uint32View[ 0 ]; - const e = ( f >> 23 ) & 0x1ff; - return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); - - } - - // float16 to float32 - - function fromHalfFloat( val ) { - - const m = val >> 10; - _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; - return _tables.floatView[ 0 ]; - - } - - var DataUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, - fromHalfFloat: fromHalfFloat, - toHalfFloat: toHalfFloat - }); - - // r144 - - class BoxBufferGeometry extends BoxGeometry { + class BoxBufferGeometry extends BoxGeometry { // @deprecated, r144 constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) { @@ -50321,9 +51182,7 @@ } - // r144 - - class CapsuleBufferGeometry extends CapsuleGeometry { + class CapsuleBufferGeometry extends CapsuleGeometry { // @deprecated, r144 constructor( radius, length, capSegments, radialSegments ) { @@ -50334,9 +51193,7 @@ } - // r144 - - class CircleBufferGeometry extends CircleGeometry { + class CircleBufferGeometry extends CircleGeometry { // @deprecated, r144 constructor( radius, segments, thetaStart, thetaLength ) { @@ -50347,9 +51204,7 @@ } - // r144 - - class ConeBufferGeometry extends ConeGeometry { + class ConeBufferGeometry extends ConeGeometry { // @deprecated, r144 constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -50360,9 +51215,7 @@ } - // r144 - - class CylinderBufferGeometry extends CylinderGeometry { + class CylinderBufferGeometry extends CylinderGeometry { // @deprecated, r144 constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -50373,9 +51226,7 @@ } - // r144 - - class DodecahedronBufferGeometry extends DodecahedronGeometry { + class DodecahedronBufferGeometry extends DodecahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50386,9 +51237,7 @@ } - // r144 - - class ExtrudeBufferGeometry extends ExtrudeGeometry { + class ExtrudeBufferGeometry extends ExtrudeGeometry { // @deprecated, r144 constructor( shapes, options ) { @@ -50399,9 +51248,7 @@ } - // r144 - - class IcosahedronBufferGeometry extends IcosahedronGeometry { + class IcosahedronBufferGeometry extends IcosahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50412,9 +51259,7 @@ } - // r144 - - class LatheBufferGeometry extends LatheGeometry { + class LatheBufferGeometry extends LatheGeometry { // @deprecated, r144 constructor( points, segments, phiStart, phiLength ) { @@ -50425,9 +51270,7 @@ } - // r144 - - class OctahedronBufferGeometry extends OctahedronGeometry { + class OctahedronBufferGeometry extends OctahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50438,9 +51281,7 @@ } - // r144 - - class PlaneBufferGeometry extends PlaneGeometry { + class PlaneBufferGeometry extends PlaneGeometry { // @deprecated, r144 constructor( width, height, widthSegments, heightSegments ) { @@ -50451,9 +51292,7 @@ } - // r144 - - class PolyhedronBufferGeometry extends PolyhedronGeometry { + class PolyhedronBufferGeometry extends PolyhedronGeometry { // @deprecated, r144 constructor( vertices, indices, radius, detail ) { @@ -50464,9 +51303,7 @@ } - // r144 - - class RingBufferGeometry extends RingGeometry { + class RingBufferGeometry extends RingGeometry { // @deprecated, r144 constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { @@ -50477,9 +51314,7 @@ } - // r144 - - class ShapeBufferGeometry extends ShapeGeometry { + class ShapeBufferGeometry extends ShapeGeometry { // @deprecated, r144 constructor( shapes, curveSegments ) { @@ -50490,9 +51325,7 @@ } - // r144 - - class SphereBufferGeometry extends SphereGeometry { + class SphereBufferGeometry extends SphereGeometry { // @deprecated, r144 constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { @@ -50503,9 +51336,7 @@ } - // r144 - - class TetrahedronBufferGeometry extends TetrahedronGeometry { + class TetrahedronBufferGeometry extends TetrahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50516,9 +51347,7 @@ } - // r144 - - class TorusBufferGeometry extends TorusGeometry { + class TorusBufferGeometry extends TorusGeometry { // @deprecated, r144 constructor( radius, tube, radialSegments, tubularSegments, arc ) { @@ -50529,9 +51358,7 @@ } - // r144 - - class TorusKnotBufferGeometry extends TorusKnotGeometry { + class TorusKnotBufferGeometry extends TorusKnotGeometry { // @deprecated, r144 constructor( radius, tube, tubularSegments, radialSegments, p, q ) { @@ -50542,9 +51369,7 @@ } - // r144 - - class TubeBufferGeometry extends TubeGeometry { + class TubeBufferGeometry extends TubeGeometry { // @deprecated, r144 constructor( path, tubularSegments, radius, radialSegments, closed ) { @@ -50583,10 +51408,12 @@ exports.AdditiveAnimationBlendMode = AdditiveAnimationBlendMode; exports.AdditiveBlending = AdditiveBlending; exports.AlphaFormat = AlphaFormat; + exports.AlwaysCompare = AlwaysCompare; exports.AlwaysDepth = AlwaysDepth; exports.AlwaysStencilFunc = AlwaysStencilFunc; exports.AmbientLight = AmbientLight; exports.AmbientLightProbe = AmbientLightProbe; + exports.AnimationAction = AnimationAction; exports.AnimationClip = AnimationClip; exports.AnimationLoader = AnimationLoader; exports.AnimationMixer = AnimationMixer; @@ -50670,6 +51497,7 @@ exports.DirectionalLight = DirectionalLight; exports.DirectionalLightHelper = DirectionalLightHelper; exports.DiscreteInterpolant = DiscreteInterpolant; + exports.DisplayP3ColorSpace = DisplayP3ColorSpace; exports.DodecahedronBufferGeometry = DodecahedronBufferGeometry; exports.DodecahedronGeometry = DodecahedronGeometry; exports.DoubleSide = DoubleSide; @@ -50680,6 +51508,7 @@ exports.DynamicReadUsage = DynamicReadUsage; exports.EdgesGeometry = EdgesGeometry; exports.EllipseCurve = EllipseCurve; + exports.EqualCompare = EqualCompare; exports.EqualDepth = EqualDepth; exports.EqualStencilFunc = EqualStencilFunc; exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping; @@ -50701,7 +51530,9 @@ exports.GLBufferAttribute = GLBufferAttribute; exports.GLSL1 = GLSL1; exports.GLSL3 = GLSL3; + exports.GreaterCompare = GreaterCompare; exports.GreaterDepth = GreaterDepth; + exports.GreaterEqualCompare = GreaterEqualCompare; exports.GreaterEqualDepth = GreaterEqualDepth; exports.GreaterEqualStencilFunc = GreaterEqualStencilFunc; exports.GreaterStencilFunc = GreaterStencilFunc; @@ -50739,7 +51570,9 @@ exports.LatheBufferGeometry = LatheBufferGeometry; exports.LatheGeometry = LatheGeometry; exports.Layers = Layers; + exports.LessCompare = LessCompare; exports.LessDepth = LessDepth; + exports.LessEqualCompare = LessEqualCompare; exports.LessEqualDepth = LessEqualDepth; exports.LessEqualStencilFunc = LessEqualStencilFunc; exports.LessStencilFunc = LessStencilFunc; @@ -50798,6 +51631,7 @@ exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter; exports.NearestMipmapLinearFilter = NearestMipmapLinearFilter; exports.NearestMipmapNearestFilter = NearestMipmapNearestFilter; + exports.NeverCompare = NeverCompare; exports.NeverDepth = NeverDepth; exports.NeverStencilFunc = NeverStencilFunc; exports.NoBlending = NoBlending; @@ -50805,6 +51639,7 @@ exports.NoToneMapping = NoToneMapping; exports.NormalAnimationBlendMode = NormalAnimationBlendMode; exports.NormalBlending = NormalBlending; + exports.NotEqualCompare = NotEqualCompare; exports.NotEqualDepth = NotEqualDepth; exports.NotEqualStencilFunc = NotEqualStencilFunc; exports.NumberKeyframeTrack = NumberKeyframeTrack; diff --git a/build/three.min.js b/build/three.min.js index e28e6cdf3fc26e..5ca84a89c6830a 100644 --- a/build/three.min.js +++ b/build/three.min.js @@ -1,10 +1,7 @@ +console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated with r150+, and will be removed with r160. Please use ES Modules or alternatives: https://threejs.org/docs/index.html#manual/en/introduction/Installation' ); /** * @license * Copyright 2010-2023 Three.js Authors * SPDX-License-Identifier: MIT */ -<<<<<<< HEAD -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).THREE={})}(this,(function(t){"use strict";const e="141dev",i=100,n=300,r=301,s=302,a=303,o=304,l=306,c=1e3,h=1001,u=1002,d=1003,p=1004,m=1005,f=1006,g=1007,v=1008,x=1009,y=1012,_=1014,M=1015,b=1016,w=1020,S=1023,T=1026,A=1027,E=33776,C=33777,L=33778,R=33779,P=35840,I=35841,D=35842,N=35843,z=37492,O=37496,F=37808,B=37809,U=37810,k=37811,G=37812,V=37813,H=37814,W=37815,j=37816,q=37817,X=37818,J=37819,Y=37820,Z=37821,K=36492,Q=2300,$=2301,tt=2302,et=2400,it=2401,nt=2402,rt=2500,st=2501,at=3e3,ot=3001,lt="srgb",ct="srgb-linear",ht=7680,ut=35044,dt="300 es",pt=1035;class mt{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const i=this._listeners;void 0===i[t]&&(i[t]=[]),-1===i[t].indexOf(e)&&i[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const i=this._listeners;return void 0!==i[t]&&-1!==i[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const i=this._listeners[t];if(void 0!==i){const t=i.indexOf(e);-1!==t&&i.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const i=e.slice(0);for(let e=0,n=i.length;e>8&255]+ft[t>>16&255]+ft[t>>24&255]+"-"+ft[255&e]+ft[e>>8&255]+"-"+ft[e>>16&15|64]+ft[e>>24&255]+"-"+ft[63&i|128]+ft[i>>8&255]+"-"+ft[i>>16&255]+ft[i>>24&255]+ft[255&n]+ft[n>>8&255]+ft[n>>16&255]+ft[n>>24&255]).toLowerCase()}function _t(t,e,i){return Math.max(e,Math.min(i,t))}function Mt(t,e){return(t%e+e)%e}function bt(t,e,i){return(1-i)*t+i*e}function wt(t){return 0==(t&t-1)&&0!==t}function St(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function Tt(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}var At=Object.freeze({__proto__:null,DEG2RAD:vt,RAD2DEG:xt,generateUUID:yt,clamp:_t,euclideanModulo:Mt,mapLinear:function(t,e,i,n,r){return n+(t-e)*(r-n)/(i-e)},inverseLerp:function(t,e,i){return t!==e?(i-t)/(e-t):0},lerp:bt,damp:function(t,e,i,n){return bt(t,e,1-Math.exp(-i*n))},pingpong:function(t,e=1){return e-Math.abs(Mt(t,2*e)-e)},smoothstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*(3-2*t)},smootherstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(gt=t);let e=gt+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*vt},radToDeg:function(t){return t*xt},isPowerOfTwo:wt,ceilPowerOfTwo:St,floorPowerOfTwo:Tt,setQuaternionFromProperEuler:function(t,e,i,n,r){const s=Math.cos,a=Math.sin,o=s(i/2),l=a(i/2),c=s((e+n)/2),h=a((e+n)/2),u=s((e-n)/2),d=a((e-n)/2),p=s((n-e)/2),m=a((n-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:function(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}},denormalize:function(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}});class Et{constructor(t=0,e=0){this.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this)}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this)}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,i=this.y,n=t.elements;return this.x=n[0]*e+n[3]*i+n[6],this.y=n[1]*e+n[4]*i+n[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y;return e*e+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e,i){return void 0!==i&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const i=Math.cos(e),n=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*i-s*n+t.x,this.y=r*n+s*i+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Ct{constructor(){this.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}set(t,e,i,n,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=n,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=i,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],this}extractBasis(t,e,i){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),i.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[3],o=i[6],l=i[1],c=i[4],h=i[7],u=i[2],d=i[5],p=i[8],m=n[0],f=n[3],g=n[6],v=n[1],x=n[4],y=n[7],_=n[2],M=n[5],b=n[8];return r[0]=s*m+a*v+o*_,r[3]=s*f+a*x+o*M,r[6]=s*g+a*y+o*b,r[1]=l*m+c*v+h*_,r[4]=l*f+c*x+h*M,r[7]=l*g+c*y+h*b,r[2]=u*m+d*v+p*_,r[5]=u*f+d*x+p*M,r[8]=u*g+d*y+p*b,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-i*r*c+i*a*o+n*r*l-n*s*o}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+i*u+n*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(n*l-c*i)*m,t[2]=(a*i-n*s)*m,t[3]=u*m,t[4]=(c*e-n*o)*m,t[5]=(n*r-a*e)*m,t[6]=d*m,t[7]=(i*o-l*e)*m,t[8]=(s*e-i*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,i,n,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(i*o,i*l,-i*(o*s+l*a)+s+t,-n*l,n*o,-n*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){const i=this.elements;return i[0]*=t,i[3]*=t,i[6]*=t,i[1]*=e,i[4]*=e,i[7]*=e,this}rotate(t){const e=Math.cos(t),i=Math.sin(t),n=this.elements,r=n[0],s=n[3],a=n[6],o=n[1],l=n[4],c=n[7];return n[0]=e*r+i*o,n[3]=e*s+i*l,n[6]=e*a+i*c,n[1]=-i*r+e*o,n[4]=-i*s+e*l,n[7]=-i*a+e*c,this}translate(t,e){const i=this.elements;return i[0]+=t*i[2],i[3]+=t*i[5],i[6]+=t*i[8],i[1]+=e*i[2],i[4]+=e*i[5],i[7]+=e*i[8],this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<9;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<9;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}function Lt(t){for(let e=t.length-1;e>=0;--e)if(t[e]>65535)return!0;return!1}const Rt={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function Pt(t,e){return new Rt[t](e)}function It(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function Dt(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function Nt(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}const zt={[lt]:{[ct]:Dt},[ct]:{[lt]:Nt}},Ot={legacyMode:!0,get workingColorSpace(){return ct},set workingColorSpace(t){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(t,e,i){if(this.legacyMode||e===i||!e||!i)return t;if(zt[e]&&void 0!==zt[e][i]){const n=zt[e][i];return t.r=n(t.r),t.g=n(t.g),t.b=n(t.b),t}throw new Error("Unsupported color space conversion.")},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)}},Ft={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Bt={r:0,g:0,b:0},Ut={h:0,s:0,l:0},kt={h:0,s:0,l:0};function Gt(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+6*(e-t)*(2/3-i):t}function Vt(t,e){return e.r=t.r,e.g=t.g,e.b=t.b,e}class Ht{constructor(t,e,i){return this.isColor=!0,this.r=1,this.g=1,this.b=1,void 0===e&&void 0===i?this.set(t):this.setRGB(t,e,i)}set(t){return t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t),this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e="srgb"){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,Ot.toWorkingColorSpace(this,e),this}setRGB(t,e,i,n="srgb-linear"){return this.r=t,this.g=e,this.b=i,Ot.toWorkingColorSpace(this,n),this}setHSL(t,e,i,n="srgb-linear"){if(t=Mt(t,1),e=_t(e,0,1),i=_t(i,0,1),0===e)this.r=this.g=this.b=i;else{const n=i<=.5?i*(1+e):i+e-i*e,r=2*i-n;this.r=Gt(r,n,t+1/3),this.g=Gt(r,n,t),this.b=Gt(r,n,t-1/3)}return Ot.toWorkingColorSpace(this,n),this}setStyle(t,e="srgb"){function i(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let n;if(n=/^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(t)){let t;const r=n[1],s=n[2];switch(r){case"rgb":case"rgba":if(t=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(255,parseInt(t[1],10))/255,this.g=Math.min(255,parseInt(t[2],10))/255,this.b=Math.min(255,parseInt(t[3],10))/255,Ot.toWorkingColorSpace(this,e),i(t[4]),this;if(t=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(100,parseInt(t[1],10))/100,this.g=Math.min(100,parseInt(t[2],10))/100,this.b=Math.min(100,parseInt(t[3],10))/100,Ot.toWorkingColorSpace(this,e),i(t[4]),this;break;case"hsl":case"hsla":if(t=/^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s)){const n=parseFloat(t[1])/360,r=parseInt(t[2],10)/100,s=parseInt(t[3],10)/100;return i(t[4]),this.setHSL(n,r,s,e)}}}else if(n=/^\#([A-Fa-f\d]+)$/.exec(t)){const t=n[1],i=t.length;if(3===i)return this.r=parseInt(t.charAt(0)+t.charAt(0),16)/255,this.g=parseInt(t.charAt(1)+t.charAt(1),16)/255,this.b=parseInt(t.charAt(2)+t.charAt(2),16)/255,Ot.toWorkingColorSpace(this,e),this;if(6===i)return this.r=parseInt(t.charAt(0)+t.charAt(1),16)/255,this.g=parseInt(t.charAt(2)+t.charAt(3),16)/255,this.b=parseInt(t.charAt(4)+t.charAt(5),16)/255,Ot.toWorkingColorSpace(this,e),this}return t&&t.length>0?this.setColorName(t,e):this}setColorName(t,e="srgb"){const i=Ft[t.toLowerCase()];return void 0!==i?this.setHex(i,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=Dt(t.r),this.g=Dt(t.g),this.b=Dt(t.b),this}copyLinearToSRGB(t){return this.r=Nt(t.r),this.g=Nt(t.g),this.b=Nt(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t="srgb"){return Ot.fromWorkingColorSpace(Vt(this,Bt),t),_t(255*Bt.r,0,255)<<16^_t(255*Bt.g,0,255)<<8^_t(255*Bt.b,0,255)<<0}getHexString(t="srgb"){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e="srgb-linear"){Ot.fromWorkingColorSpace(Vt(this,Bt),e);const i=Bt.r,n=Bt.g,r=Bt.b,s=Math.max(i,n,r),a=Math.min(i,n,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c<=.5?t/(s+a):t/(2-s-a),s){case i:o=(n-r)/t+(n2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=It("canvas");e.width=t.width,e.height=t.height;const i=e.getContext("2d");i.drawImage(t,0,0,t.width,t.height);const n=i.getImageData(0,0,t.width,t.height),r=n.data;for(let t=0;t1)switch(this.wrapS){case c:t.x=t.x-Math.floor(t.x);break;case h:t.x=t.x<0?0:1;break;case u:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case c:t.y=t.y-Math.floor(t.y);break;case h:t.y=t.y<0?0:1;break;case u:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}}Yt.DEFAULT_IMAGE=null,Yt.DEFAULT_MAPPING=n;class Zt{constructor(t=0,e=0,i=0,n=1){this.isVector4=!0,this.x=t,this.y=e,this.z=i,this.w=n}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,i,n){return this.x=t,this.y=e,this.z=i,this.w=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this)}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this)}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*i+s[8]*n+s[12]*r,this.y=s[1]*e+s[5]*i+s[9]*n+s[13]*r,this.z=s[2]*e+s[6]*i+s[10]*n+s[14]*r,this.w=s[3]*e+s[7]*i+s[11]*n+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,i,n,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,n=1-e*e;if(n>Number.EPSILON){const r=Math.sqrt(n),s=Math.atan2(r,e*i);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*i;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,i,n,r,s){const a=i[n],o=i[n+1],l=i[n+2],c=i[n+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,i,n){return this._x=t,this._y=e,this._z=i,this._w=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){if(!t||!t.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");const i=t._x,n=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(i/2),c=a(n/2),h=a(r/2),u=o(i/2),d=o(n/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const i=e/2,n=Math.sin(i);return this._x=t.x*n,this._y=t.y*n,this._z=t.z*n,this._w=Math.cos(i),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,i=e[0],n=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=i+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-n)*t}else if(i>a&&i>h){const t=2*Math.sqrt(1+i-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(n+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-i-h);this._w=(r-l)/t,this._x=(n+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-i-a);this._w=(s-n)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let i=t.dot(e)+1;return iMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=i):(this._x=0,this._y=-t.z,this._z=t.y,this._w=i)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=i),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(_t(this.dot(t),-1,1)))}rotateTowards(t,e){const i=this.angleTo(t);if(0===i)return this;const n=Math.min(1,e/i);return this.slerp(t,n),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t,e){return void 0!==e?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(t,e)):this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const i=t._x,n=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=i*c+s*a+n*l-r*o,this._y=n*c+s*o+r*a-i*l,this._z=r*c+s*l+i*o-n*a,this._w=s*c-i*a-n*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const i=this._x,n=this._y,r=this._z,s=this._w;let a=s*t._w+i*t._x+n*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=i,this._y=n,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*i+e*this._x,this._y=t*n+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=i*h+this._x*u,this._y=n*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,i){return this.copy(t).slerp(e,i)}random(){const t=Math.random(),e=Math.sqrt(1-t),i=Math.sqrt(t),n=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(n),i*Math.sin(r),i*Math.cos(r),e*Math.sin(n))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class ee{constructor(t=0,e=0,i=0){this.isVector3=!0,this.x=t,this.y=e,this.z=i}set(t,e,i){return void 0===i&&(i=this.z),this.x=t,this.y=e,this.z=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t,e){return void 0!==e?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(t,e)):(this.x+=t.x,this.y+=t.y,this.z+=t.z,this)}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t,e){return void 0!==e?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(t,e)):(this.x-=t.x,this.y-=t.y,this.z-=t.z,this)}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t,e){return void 0!==e?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(t,e)):(this.x*=t.x,this.y*=t.y,this.z*=t.z,this)}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return t&&t.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(ne.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(ne.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[3]*i+r[6]*n,this.y=r[1]*e+r[4]*i+r[7]*n,this.z=r[2]*e+r[5]*i+r[8]*n,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=t.elements,s=1/(r[3]*e+r[7]*i+r[11]*n+r[15]);return this.x=(r[0]*e+r[4]*i+r[8]*n+r[12])*s,this.y=(r[1]*e+r[5]*i+r[9]*n+r[13])*s,this.z=(r[2]*e+r[6]*i+r[10]*n+r[14])*s,this}applyQuaternion(t){const e=this.x,i=this.y,n=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*n-a*i,c=o*i+a*e-r*n,h=o*n+r*i-s*e,u=-r*e-s*i-a*n;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[4]*i+r[8]*n,this.y=r[1]*e+r[5]*i+r[9]*n,this.z=r[2]*e+r[6]*i+r[10]*n,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this.z=t.z+(e.z-t.z)*i,this}cross(t,e){return void 0!==e?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(t,e)):this.crossVectors(this,t)}crossVectors(t,e){const i=t.x,n=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=n*o-r*a,this.y=r*s-i*o,this.z=i*a-n*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const i=t.dot(this)/e;return this.copy(t).multiplyScalar(i)}projectOnPlane(t){return ie.copy(this).projectOnVector(t),this.sub(ie)}reflect(t){return this.sub(ie.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const i=this.dot(t)/e;return Math.acos(_t(i,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y,n=this.z-t.z;return e*e+i*i+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,i){const n=Math.sin(e)*t;return this.x=n*Math.sin(i),this.y=Math.cos(e)*t,this.z=n*Math.cos(i),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,i){return this.x=t*Math.sin(e),this.y=i,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),i=this.setFromMatrixColumn(t,1).length(),n=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=i,this.z=n,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e,i){return void 0!==i&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,i=Math.sqrt(1-t**2);return this.x=i*Math.cos(e),this.y=i*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const ie=new ee,ne=new te;class re{constructor(t=new ee(1/0,1/0,1/0),e=new ee(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.length;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromBufferAttribute(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.count;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromPoints(t){this.makeEmpty();for(let e=0,i=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,ae),ae.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,i;return t.normal.x>0?(e=t.normal.x*this.min.x,i=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,i=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,i+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,i+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,i+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,i+=t.normal.z*this.min.z),e<=-t.constant&&i>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(me),fe.subVectors(this.max,me),le.subVectors(t.a,me),ce.subVectors(t.b,me),he.subVectors(t.c,me),ue.subVectors(ce,le),de.subVectors(he,ce),pe.subVectors(le,he);let e=[0,-ue.z,ue.y,0,-de.z,de.y,0,-pe.z,pe.y,ue.z,0,-ue.x,de.z,0,-de.x,pe.z,0,-pe.x,-ue.y,ue.x,0,-de.y,de.x,0,-pe.y,pe.x,0];return!!xe(e,le,ce,he,fe)&&(e=[1,0,0,0,1,0,0,0,1],!!xe(e,le,ce,he,fe)&&(ge.crossVectors(ue,de),e=[ge.x,ge.y,ge.z],xe(e,le,ce,he,fe)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return ae.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return this.getCenter(t.center),t.radius=.5*this.getSize(ae).length(),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(se[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),se[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),se[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),se[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),se[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),se[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),se[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),se[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(se)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const se=[new ee,new ee,new ee,new ee,new ee,new ee,new ee,new ee],ae=new ee,oe=new re,le=new ee,ce=new ee,he=new ee,ue=new ee,de=new ee,pe=new ee,me=new ee,fe=new ee,ge=new ee,ve=new ee;function xe(t,e,i,n,r){for(let s=0,a=t.length-3;s<=a;s+=3){ve.fromArray(t,s);const a=r.x*Math.abs(ve.x)+r.y*Math.abs(ve.y)+r.z*Math.abs(ve.z),o=e.dot(ve),l=i.dot(ve),c=n.dot(ve);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const ye=new re,_e=new ee,Me=new ee,be=new ee;class we{constructor(t=new ee,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const i=this.center;void 0!==e?i.copy(e):ye.setFromPoints(t).getCenter(i);let n=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){be.subVectors(t,this.center);const e=be.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),i=.5*(t-this.radius);this.center.add(be.multiplyScalar(i/t)),this.radius+=i}return this}union(t){return!0===this.center.equals(t.center)?Me.set(0,0,1).multiplyScalar(t.radius):Me.subVectors(t.center,this.center).normalize().multiplyScalar(t.radius),this.expandByPoint(_e.copy(t.center).add(Me)),this.expandByPoint(_e.copy(t.center).sub(Me)),this}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Se=new ee,Te=new ee,Ae=new ee,Ee=new ee,Ce=new ee,Le=new ee,Re=new ee;class Pe{constructor(t=new ee,e=new ee(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.direction).multiplyScalar(t).add(this.origin)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,Se)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const i=e.dot(this.direction);return i<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(i).add(this.origin)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=Se.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Se.copy(this.direction).multiplyScalar(e).add(this.origin),Se.distanceToSquared(t))}distanceSqToSegment(t,e,i,n){Te.copy(t).add(e).multiplyScalar(.5),Ae.copy(e).sub(t).normalize(),Ee.copy(this.origin).sub(Te);const r=.5*t.distanceTo(e),s=-this.direction.dot(Ae),a=Ee.dot(this.direction),o=-Ee.dot(Ae),l=Ee.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return i&&i.copy(this.direction).multiplyScalar(h).add(this.origin),n&&n.copy(Ae).multiplyScalar(u).add(Te),d}intersectSphere(t,e){Se.subVectors(t.center,this.origin);const i=Se.dot(this.direction),n=Se.dot(Se)-i*i,r=t.radius*t.radius;if(n>r)return null;const s=Math.sqrt(r-n),a=i-s,o=i+s;return a<0&&o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const i=-(this.origin.dot(t.normal)+t.constant)/e;return i>=0?i:null}intersectPlane(t,e){const i=this.distanceToPlane(t);return null===i?null:this.at(i,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let i,n,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(i=(t.min.x-u.x)*l,n=(t.max.x-u.x)*l):(i=(t.max.x-u.x)*l,n=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),i>s||r>n?null:((r>i||i!=i)&&(i=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),i>o||a>n?null:((a>i||i!=i)&&(i=a),(o=0?i:n,e)))}intersectsBox(t){return null!==this.intersectBox(t,Se)}intersectTriangle(t,e,i,n,r){Ce.subVectors(e,t),Le.subVectors(i,t),Re.crossVectors(Ce,Le);let s,a=this.direction.dot(Re);if(a>0){if(n)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}Ee.subVectors(this.origin,t);const o=s*this.direction.dot(Le.crossVectors(Ee,Le));if(o<0)return null;const l=s*this.direction.dot(Ce.cross(Ee));if(l<0)return null;if(o+l>a)return null;const c=-s*Ee.dot(Re);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class Ie{constructor(){this.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}set(t,e,i,n,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=i,g[12]=n,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new Ie).fromArray(this.elements)}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],e[9]=i[9],e[10]=i[10],e[11]=i[11],e[12]=i[12],e[13]=i[13],e[14]=i[14],e[15]=i[15],this}copyPosition(t){const e=this.elements,i=t.elements;return e[12]=i[12],e[13]=i[13],e[14]=i[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,i){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this}makeBasis(t,e,i){return this.set(t.x,e.x,i.x,0,t.y,e.y,i.y,0,t.z,e.z,i.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,i=t.elements,n=1/De.setFromMatrixColumn(t,0).length(),r=1/De.setFromMatrixColumn(t,1).length(),s=1/De.setFromMatrixColumn(t,2).length();return e[0]=i[0]*n,e[1]=i[1]*n,e[2]=i[2]*n,e[3]=0,e[4]=i[4]*r,e[5]=i[5]*r,e[6]=i[6]*r,e[7]=0,e[8]=i[8]*s,e[9]=i[9]*s,e[10]=i[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){t&&t.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");const e=this.elements,i=t.x,n=t.y,r=t.z,s=Math.cos(i),a=Math.sin(i),o=Math.cos(n),l=Math.sin(n),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=i+n*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=n+i*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t+r*a,e[4]=n*a-i,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=i*a-n,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=n+i*a,e[1]=i+n*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=n*l-i,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=i*l-n,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=n*h+i,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=i*h+n,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=i*h-n,e[2]=n*h-i,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(ze,t,Oe)}lookAt(t,e,i){const n=this.elements;return Ue.subVectors(t,e),0===Ue.lengthSq()&&(Ue.z=1),Ue.normalize(),Fe.crossVectors(i,Ue),0===Fe.lengthSq()&&(1===Math.abs(i.z)?Ue.x+=1e-4:Ue.z+=1e-4,Ue.normalize(),Fe.crossVectors(i,Ue)),Fe.normalize(),Be.crossVectors(Ue,Fe),n[0]=Fe.x,n[4]=Be.x,n[8]=Ue.x,n[1]=Fe.y,n[5]=Be.y,n[9]=Ue.y,n[2]=Fe.z,n[6]=Be.z,n[10]=Ue.z,this}multiply(t,e){return void 0!==e?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(t,e)):this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[4],o=i[8],l=i[12],c=i[1],h=i[5],u=i[9],d=i[13],p=i[2],m=i[6],f=i[10],g=i[14],v=i[3],x=i[7],y=i[11],_=i[15],M=n[0],b=n[4],w=n[8],S=n[12],T=n[1],A=n[5],E=n[9],C=n[13],L=n[2],R=n[6],P=n[10],I=n[14],D=n[3],N=n[7],z=n[11],O=n[15];return r[0]=s*M+a*T+o*L+l*D,r[4]=s*b+a*A+o*R+l*N,r[8]=s*w+a*E+o*P+l*z,r[12]=s*S+a*C+o*I+l*O,r[1]=c*M+h*T+u*L+d*D,r[5]=c*b+h*A+u*R+d*N,r[9]=c*w+h*E+u*P+d*z,r[13]=c*S+h*C+u*I+d*O,r[2]=p*M+m*T+f*L+g*D,r[6]=p*b+m*A+f*R+g*N,r[10]=p*w+m*E+f*P+g*z,r[14]=p*S+m*C+f*I+g*O,r[3]=v*M+x*T+y*L+_*D,r[7]=v*b+x*A+y*R+_*N,r[11]=v*w+x*E+y*P+_*z,r[15]=v*S+x*C+y*I+_*O,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[4],n=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-n*l*h-r*a*u+i*l*u+n*a*d-i*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-n*s*d+n*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+i*s*d+r*a*c-i*l*c)+t[15]*(-n*a*c-e*o*h+e*a*u+n*s*h-i*s*u+i*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,i){const n=this.elements;return t.isVector3?(n[12]=t.x,n[13]=t.y,n[14]=t.z):(n[12]=t,n[13]=e,n[14]=i),this}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,x=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,y=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,_=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+i*x+n*y+r*_;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const b=1/M;return t[0]=v*b,t[1]=(m*u*r-h*f*r-m*n*d+i*f*d+h*n*g-i*u*g)*b,t[2]=(a*f*r-m*o*r+m*n*l-i*f*l-a*n*g+i*o*g)*b,t[3]=(h*o*r-a*u*r-h*n*l+i*u*l+a*n*d-i*o*d)*b,t[4]=x*b,t[5]=(c*f*r-p*u*r+p*n*d-e*f*d-c*n*g+e*u*g)*b,t[6]=(p*o*r-s*f*r-p*n*l+e*f*l+s*n*g-e*o*g)*b,t[7]=(s*u*r-c*o*r+c*n*l-e*u*l-s*n*d+e*o*d)*b,t[8]=y*b,t[9]=(p*h*r-c*m*r-p*i*d+e*m*d+c*i*g-e*h*g)*b,t[10]=(s*m*r-p*a*r+p*i*l-e*m*l-s*i*g+e*a*g)*b,t[11]=(c*a*r-s*h*r-c*i*l+e*h*l+s*i*d-e*a*d)*b,t[12]=_*b,t[13]=(c*m*n-p*h*n+p*i*u-e*m*u-c*i*f+e*h*f)*b,t[14]=(p*a*n-s*m*n-p*i*o+e*m*o+s*i*f-e*a*f)*b,t[15]=(s*h*n-c*a*n+c*i*o-e*h*o-s*i*u+e*a*u)*b,this}scale(t){const e=this.elements,i=t.x,n=t.y,r=t.z;return e[0]*=i,e[4]*=n,e[8]*=r,e[1]*=i,e[5]*=n,e[9]*=r,e[2]*=i,e[6]*=n,e[10]*=r,e[3]*=i,e[7]*=n,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],i=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],n=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,i,n))}makeTranslation(t,e,i){return this.set(1,0,0,t,0,1,0,e,0,0,1,i,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),i=Math.sin(t);return this.set(1,0,0,0,0,e,-i,0,0,i,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,0,i,0,0,1,0,0,-i,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,-i,0,0,i,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const i=Math.cos(e),n=Math.sin(e),r=1-i,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+i,l*a-n*o,l*o+n*a,0,l*a+n*o,c*a+i,c*o-n*s,0,l*o-n*a,c*o+n*s,r*o*o+i,0,0,0,0,1),this}makeScale(t,e,i){return this.set(t,0,0,0,0,e,0,0,0,0,i,0,0,0,0,1),this}makeShear(t,e,i,n,r,s){return this.set(1,i,r,0,t,1,s,0,e,n,1,0,0,0,0,1),this}compose(t,e,i){const n=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,x=o*c,y=o*h,_=i.x,M=i.y,b=i.z;return n[0]=(1-(m+g))*_,n[1]=(d+y)*_,n[2]=(p-x)*_,n[3]=0,n[4]=(d-y)*M,n[5]=(1-(u+g))*M,n[6]=(f+v)*M,n[7]=0,n[8]=(p+x)*b,n[9]=(f-v)*b,n[10]=(1-(u+m))*b,n[11]=0,n[12]=t.x,n[13]=t.y,n[14]=t.z,n[15]=1,this}decompose(t,e,i){const n=this.elements;let r=De.set(n[0],n[1],n[2]).length();const s=De.set(n[4],n[5],n[6]).length(),a=De.set(n[8],n[9],n[10]).length();this.determinant()<0&&(r=-r),t.x=n[12],t.y=n[13],t.z=n[14],Ne.copy(this);const o=1/r,l=1/s,c=1/a;return Ne.elements[0]*=o,Ne.elements[1]*=o,Ne.elements[2]*=o,Ne.elements[4]*=l,Ne.elements[5]*=l,Ne.elements[6]*=l,Ne.elements[8]*=c,Ne.elements[9]*=c,Ne.elements[10]*=c,e.setFromRotationMatrix(Ne),i.x=r,i.y=s,i.z=a,this}makePerspective(t,e,i,n,r,s){void 0===s&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");const a=this.elements,o=2*r/(e-t),l=2*r/(i-n),c=(e+t)/(e-t),h=(i+n)/(i-n),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,i,n,r,s){const a=this.elements,o=1/(e-t),l=1/(i-n),c=1/(s-r),h=(e+t)*o,u=(i+n)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<16;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<16;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t[e+9]=i[9],t[e+10]=i[10],t[e+11]=i[11],t[e+12]=i[12],t[e+13]=i[13],t[e+14]=i[14],t[e+15]=i[15],t}}const De=new ee,Ne=new Ie,ze=new ee(0,0,0),Oe=new ee(1,1,1),Fe=new ee,Be=new ee,Ue=new ee,ke=new Ie,Ge=new te;class Ve{constructor(t=0,e=0,i=0,n=Ve.DefaultOrder){this.isEuler=!0,this._x=t,this._y=e,this._z=i,this._order=n}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,i,n=this._order){return this._x=t,this._y=e,this._z=i,this._order=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,i=!0){const n=t.elements,r=n[0],s=n[4],a=n[8],o=n[1],l=n[5],c=n[9],h=n[2],u=n[6],d=n[10];switch(e){case"XYZ":this._y=Math.asin(_t(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-_t(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(_t(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-_t(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(_t(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-_t(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===i&&this._onChangeCallback(),this}setFromQuaternion(t,e,i){return ke.makeRotationFromQuaternion(t),this.setFromRotationMatrix(ke,e,i)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return Ge.setFromEuler(this),this.setFromQuaternion(Ge,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}toVector3(){console.error("THREE.Euler: .toVector3() has been removed. Use Vector3.setFromEuler() instead")}}Ve.DefaultOrder="XYZ",Ve.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"];class He{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0){n.children=[];for(let e=0;e0){n.animations=[];for(let e=0;e0&&(i.geometries=e),n.length>0&&(i.materials=n),r.length>0&&(i.textures=r),a.length>0&&(i.images=a),o.length>0&&(i.shapes=o),l.length>0&&(i.skeletons=l),c.length>0&&(i.animations=c),h.length>0&&(i.nodes=h)}return i.object=n,i;function s(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?n.multiplyScalar(1/Math.sqrt(r)):n.set(0,0,0)}static getBarycoord(t,e,i,n,r){ri.subVectors(n,e),si.subVectors(i,e),ai.subVectors(t,e);const s=ri.dot(ri),a=ri.dot(si),o=ri.dot(ai),l=si.dot(si),c=si.dot(ai),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,i,n){return this.getBarycoord(t,e,i,n,oi),oi.x>=0&&oi.y>=0&&oi.x+oi.y<=1}static getUV(t,e,i,n,r,s,a,o){return this.getBarycoord(t,e,i,n,oi),o.set(0,0),o.addScaledVector(r,oi.x),o.addScaledVector(s,oi.y),o.addScaledVector(a,oi.z),o}static isFrontFacing(t,e,i,n){return ri.subVectors(i,e),si.subVectors(t,e),ri.cross(si).dot(n)<0}set(t,e,i){return this.a.copy(t),this.b.copy(e),this.c.copy(i),this}setFromPointsAndIndices(t,e,i,n){return this.a.copy(t[e]),this.b.copy(t[i]),this.c.copy(t[n]),this}setFromAttributeAndIndices(t,e,i,n){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,i),this.c.fromBufferAttribute(t,n),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return ri.subVectors(this.c,this.b),si.subVectors(this.a,this.b),.5*ri.cross(si).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return mi.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return mi.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,i,n,r){return mi.getUV(t,this.a,this.b,this.c,e,i,n,r)}containsPoint(t){return mi.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return mi.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const i=this.a,n=this.b,r=this.c;let s,a;li.subVectors(n,i),ci.subVectors(r,i),ui.subVectors(t,i);const o=li.dot(ui),l=ci.dot(ui);if(o<=0&&l<=0)return e.copy(i);di.subVectors(t,n);const c=li.dot(di),h=ci.dot(di);if(c>=0&&h<=c)return e.copy(n);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(i).addScaledVector(li,s);pi.subVectors(t,r);const d=li.dot(pi),p=ci.dot(pi);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(i).addScaledVector(ci,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return hi.subVectors(r,n),a=(h-c)/(h-c+(d-p)),e.copy(n).addScaledVector(hi,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(i).addScaledVector(li,s).addScaledVector(ci,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let fi=0;class gi extends mt{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:fi++}),this.uuid=yt(),this.name="",this.type="Material",this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=i,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=ht,this.stencilZFail=ht,this.stencilZPass=ht,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const i=t[e];if(void 0===i){console.warn("THREE.Material: '"+e+"' parameter is undefined.");continue}if("shading"===e){console.warn("THREE."+this.type+": .shading has been removed. Use the boolean .flatShading instead."),this.flatShading=1===i;continue}const n=this[e];void 0!==n?n&&n.isColor?n.set(i):n&&n.isVector3&&i&&i.isVector3?n.copy(i):this[e]=i:console.warn("THREE."+this.type+": '"+e+"' is not a property of this material.")}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const i={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};function n(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}if(i.uuid=this.uuid,i.type=this.type,""!==this.name&&(i.name=this.name),this.color&&this.color.isColor&&(i.color=this.color.getHex()),void 0!==this.roughness&&(i.roughness=this.roughness),void 0!==this.metalness&&(i.metalness=this.metalness),void 0!==this.sheen&&(i.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(i.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(i.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(i.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(i.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(i.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(i.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(i.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(i.shininess=this.shininess),void 0!==this.clearcoat&&(i.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(i.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(i.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(i.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(i.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,i.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(i.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(i.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(i.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(i.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(i.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(i.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(i.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(i.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(i.lightMap=this.lightMap.toJSON(t).uuid,i.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(i.aoMap=this.aoMap.toJSON(t).uuid,i.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(i.bumpMap=this.bumpMap.toJSON(t).uuid,i.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(i.normalMap=this.normalMap.toJSON(t).uuid,i.normalMapType=this.normalMapType,i.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(i.displacementMap=this.displacementMap.toJSON(t).uuid,i.displacementScale=this.displacementScale,i.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(i.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(i.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(i.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(i.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(i.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(i.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(i.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(i.combine=this.combine)),void 0!==this.envMapIntensity&&(i.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(i.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(i.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(i.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(i.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(i.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(i.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(i.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&(i.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(i.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(i.size=this.size),null!==this.shadowSide&&(i.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(i.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(i.blending=this.blending),0!==this.side&&(i.side=this.side),this.vertexColors&&(i.vertexColors=!0),this.opacity<1&&(i.opacity=this.opacity),!0===this.transparent&&(i.transparent=this.transparent),i.depthFunc=this.depthFunc,i.depthTest=this.depthTest,i.depthWrite=this.depthWrite,i.colorWrite=this.colorWrite,i.stencilWrite=this.stencilWrite,i.stencilWriteMask=this.stencilWriteMask,i.stencilFunc=this.stencilFunc,i.stencilRef=this.stencilRef,i.stencilFuncMask=this.stencilFuncMask,i.stencilFail=this.stencilFail,i.stencilZFail=this.stencilZFail,i.stencilZPass=this.stencilZPass,void 0!==this.rotation&&0!==this.rotation&&(i.rotation=this.rotation),!0===this.polygonOffset&&(i.polygonOffset=!0),0!==this.polygonOffsetFactor&&(i.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(i.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(i.linewidth=this.linewidth),void 0!==this.dashSize&&(i.dashSize=this.dashSize),void 0!==this.gapSize&&(i.gapSize=this.gapSize),void 0!==this.scale&&(i.scale=this.scale),!0===this.dithering&&(i.dithering=!0),this.alphaTest>0&&(i.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(i.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(i.flatShading=this.flatShading),!1===this.visible&&(i.visible=!1),!1===this.toneMapped&&(i.toneMapped=!1),!1===this.fog&&(i.fog=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),e){const e=n(t.textures),r=n(t.images);e.length>0&&(i.textures=e),r.length>0&&(i.images=r)}return i}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let i=null;if(null!==e){const t=e.length;i=new Array(t);for(let n=0;n!==t;++n)i[n]=e[n].clone()}return this.clippingPlanes=i,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}get vertexTangents(){return console.warn("THREE."+this.type+": .vertexTangents has been removed."),!1}set vertexTangents(t){console.warn("THREE."+this.type+": .vertexTangents has been removed.")}}gi.fromType=function(){return null};class vi extends gi{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Ht(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const xi=new ee,yi=new Et;class _i{constructor(t,e,i){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=!0===i,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,i){t*=this.itemSize,i*=e.itemSize;for(let n=0,r=this.itemSize;n0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const i in e)void 0!==e[i]&&(t[i]=e[i]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const i=this.attributes;for(const e in i){const n=i[e];t.data.attributes[e]=n.toJSON(t.data)}const n={};let r=!1;for(const e in this.morphAttributes){const i=this.morphAttributes[e],s=[];for(let e=0,n=i.length;e0&&(n[e]=s,r=!0)}r&&(t.data.morphAttributes=n,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const i=t.index;null!==i&&this.setIndex(i.clone(e));const n=t.attributes;for(const t in n){const i=n[t];this.setAttribute(t,i.clone(e))}const r=t.morphAttributes;for(const t in r){const i=[],n=r[t];for(let t=0,r=n.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;ti.far?null:{distance:c,point:Ji.clone(),object:t}}(t,e,i,n,zi,Oi,Fi,Xi);if(p){o&&(Wi.fromBufferAttribute(o,c),ji.fromBufferAttribute(o,h),qi.fromBufferAttribute(o,u),p.uv=mi.getUV(Xi,zi,Oi,Fi,Wi,ji,qi,new Et)),l&&(Wi.fromBufferAttribute(l,c),ji.fromBufferAttribute(l,h),qi.fromBufferAttribute(l,u),p.uv2=mi.getUV(Xi,zi,Oi,Fi,Wi,ji,qi,new Et));const t={a:c,b:h,c:u,normal:new ee,materialIndex:0};mi.getNormal(zi,Oi,Fi,t.normal),p.face=t}return p}class Ki extends Pi{constructor(t=1,e=1,i=1,n=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:i,widthSegments:n,heightSegments:r,depthSegments:s};const a=this;n=Math.floor(n),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,i,n,r,s,p,m,f,g,v){const x=s/f,y=p/g,_=s/2,M=p/2,b=m/2,w=f+1,S=g+1;let T=0,A=0;const E=new ee;for(let s=0;s0?1:-1,c.push(E.x,E.y,E.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;const i={};for(const t in this.extensions)!0===this.extensions[t]&&(i[t]=!0);return Object.keys(i).length>0&&(e.extensions=i),e}}class nn extends ni{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new Ie,this.projectionMatrix=new Ie,this.projectionMatrixInverse=new Ie}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class rn extends nn{constructor(t=50,e=1,i=.1,n=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=i,this.far=n,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*xt*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*vt*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*xt*Math.atan(Math.tan(.5*vt*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,i,n,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*vt*this.fov)/this.zoom,i=2*e,n=this.aspect*i,r=-.5*n;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*n/t,e-=s.offsetY*i/a,n*=s.width/t,i*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+n,e,e-i,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const sn=90;class an extends ni{constructor(t,e,i){if(super(),this.type="CubeCamera",!0!==i.isWebGLCubeRenderTarget)return void console.error("THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.");this.renderTarget=i;const n=new rn(sn,1,t,e);n.layers=this.layers,n.up.set(0,-1,0),n.lookAt(new ee(1,0,0)),this.add(n);const r=new rn(sn,1,t,e);r.layers=this.layers,r.up.set(0,-1,0),r.lookAt(new ee(-1,0,0)),this.add(r);const s=new rn(sn,1,t,e);s.layers=this.layers,s.up.set(0,0,1),s.lookAt(new ee(0,1,0)),this.add(s);const a=new rn(sn,1,t,e);a.layers=this.layers,a.up.set(0,0,-1),a.lookAt(new ee(0,-1,0)),this.add(a);const o=new rn(sn,1,t,e);o.layers=this.layers,o.up.set(0,-1,0),o.lookAt(new ee(0,0,1)),this.add(o);const l=new rn(sn,1,t,e);l.layers=this.layers,l.up.set(0,-1,0),l.lookAt(new ee(0,0,-1)),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const i=this.renderTarget,[n,r,s,a,o,l]=this.children,c=t.getRenderTarget(),h=t.toneMapping,u=t.xr.enabled;t.toneMapping=0,t.xr.enabled=!1;const d=i.texture.generateMipmaps;i.texture.generateMipmaps=!1,t.setRenderTarget(i,0),t.render(e,n),t.setRenderTarget(i,1),t.render(e,r),t.setRenderTarget(i,2),t.render(e,s),t.setRenderTarget(i,3),t.render(e,a),t.setRenderTarget(i,4),t.render(e,o),i.texture.generateMipmaps=d,t.setRenderTarget(i,5),t.render(e,l),t.setRenderTarget(c),t.toneMapping=h,t.xr.enabled=u,i.texture.needsPMREMUpdate=!0}}class on extends Yt{constructor(t,e,i,n,s,a,o,l,c,h){super(t=void 0!==t?t:[],e=void 0!==e?e:r,i,n,s,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class ln extends Kt{constructor(t,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const i={width:t,height:t,depth:1},n=[i,i,i,i,i,i];this.texture=new on(n,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:f}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.encoding=e.encoding,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const i={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},n=new Ki(5,5,5),r=new en({name:"CubemapFromEquirect",uniforms:Qi(i.uniforms),vertexShader:i.vertexShader,fragmentShader:i.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new Yi(n,r),a=e.minFilter;e.minFilter===v&&(e.minFilter=f);return new an(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,i,n){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,i,n);t.setRenderTarget(r)}}const cn=new ee,hn=new ee,un=new Ct;class dn{constructor(t=new ee(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,i,n){return this.normal.set(t,e,i),this.constant=n,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,i){const n=cn.subVectors(i,e).cross(hn.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(n,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)}intersectLine(t,e){const i=t.delta(cn),n=this.normal.dot(i);if(0===n)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/n;return r<0||r>1?null:e.copy(i).multiplyScalar(r).add(t.start)}intersectsLine(t){const e=this.distanceToPoint(t.start),i=this.distanceToPoint(t.end);return e<0&&i>0||i<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const i=e||un.getNormalMatrix(t),n=this.coplanarPoint(cn).applyMatrix4(t),r=this.normal.applyMatrix3(i).normalize();return this.constant=-n.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const pn=new we,mn=new ee;class fn{constructor(t=new dn,e=new dn,i=new dn,n=new dn,r=new dn,s=new dn){this.planes=[t,e,i,n,r,s]}set(t,e,i,n,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(i),a[3].copy(n),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let i=0;i<6;i++)e[i].copy(t.planes[i]);return this}setFromProjectionMatrix(t){const e=this.planes,i=t.elements,n=i[0],r=i[1],s=i[2],a=i[3],o=i[4],l=i[5],c=i[6],h=i[7],u=i[8],d=i[9],p=i[10],m=i[11],f=i[12],g=i[13],v=i[14],x=i[15];return e[0].setComponents(a-n,h-o,m-u,x-f).normalize(),e[1].setComponents(a+n,h+o,m+u,x+f).normalize(),e[2].setComponents(a+r,h+l,m+d,x+g).normalize(),e[3].setComponents(a-r,h-l,m-d,x-g).normalize(),e[4].setComponents(a-s,h-c,m-p,x-v).normalize(),e[5].setComponents(a+s,h+c,m+p,x+v).normalize(),this}intersectsObject(t){const e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),pn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(pn)}intersectsSprite(t){return pn.center.set(0,0,0),pn.radius=.7071067811865476,pn.applyMatrix4(t.matrixWorld),this.intersectsSphere(pn)}intersectsSphere(t){const e=this.planes,i=t.center,n=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(i)0?t.max.x:t.min.x,mn.y=n.normal.y>0?t.max.y:t.min.y,mn.z=n.normal.z>0?t.max.z:t.min.z,n.distanceToPoint(mn)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let i=0;i<6;i++)if(e[i].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function gn(){let t=null,e=!1,i=null,n=null;function r(e,s){i(e,s),n=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==i&&(n=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(n),e=!1},setAnimationLoop:function(t){i=t},setContext:function(e){t=e}}}function vn(t,e){const i=e.isWebGL2,n=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),n.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const i=n.get(e);i&&(t.deleteBuffer(i.buffer),n.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=n.get(e);return void((!t||t.version 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif",iridescence_fragment:"#ifdef USE_IRIDESCENCE\nconst mat3 XYZ_TO_REC709 = mat3(\n\t\t3.2404542, -0.9692660,\t0.0556434,\n\t -1.5371385,\t1.8760108, -0.2040259,\n\t -0.4985314,\t0.0415560,\t1.0572252\n);\nvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t vec3 sqrtF0 = sqrt( fresnel0 );\n\t return ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n}\nvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t return pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n}\nfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t return pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n}\nvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t float phase = 2.0 * PI * OPD * 1.0e-9;\n\t vec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t vec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t vec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t vec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( -pow2( phase ) * var );\n\t xyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[0] ) * exp( -4.5282e+09 * pow2( phase ) );\n\t xyz /= 1.0685e-7;\n\t vec3 srgb = XYZ_TO_REC709 * xyz;\n\t return srgb;\n}\nvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t vec3 I;\n\t float iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t float sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t float cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t if ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t }\n\t float cosTheta2 = sqrt( cosTheta2Sq );\n\t float R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t float R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t float R21 = R12;\n\t float T121 = 1.0 - R12;\n\t float phi12 = 0.0;\n\t if ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t float phi21 = PI - phi12;\n\t vec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t vec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t vec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t vec3 phi23 = vec3( 0.0 );\n\t if ( baseIOR[0] < iridescenceIOR ) phi23[0] = PI;\n\t if ( baseIOR[1] < iridescenceIOR ) phi23[1] = PI;\n\t if ( baseIOR[2] < iridescenceIOR ) phi23[2] = PI;\n\t float OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t vec3 phi = vec3( phi21 ) + phi23;\n\t vec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t vec3 r123 = sqrt( R123 );\n\t vec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t vec3 C0 = R12 + Rs;\n\t I = C0;\n\t vec3 Cm = Rs - T121;\n\t for ( int m = 1; m <= 2; ++m ) {\n\t\t\t Cm *= r123;\n\t\t\t vec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\t I += Cm * Sm;\n\t }\n\t return max( I, vec3( 0.0 ) );\n}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, worldNormal );\n\t\t\t#endif\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\t#else\n\t\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec );\n\t\t\t#endif\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry.normal );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointLightInfo( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotLightInfo( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(\t\t0, 1,\t\t0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\nfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\nif ( material.iridescenceThickness == 0.0 ) {\n\tmaterial.iridescence = 0.0;\n} else {\n\tmaterial.iridescence = saturate( material.iridescence );\n}\nif ( material.iridescence > 0.0 ) {\n\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && ( defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE ) )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t\tf.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\tvec4 shadowWorldPosition;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(\t1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,\t1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,\t1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tfloat transmissionAlpha = 1.0;\n\tfloat transmissionFactor = transmission;\n\tfloat thicknessFactor = thickness;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\ttransmissionFactor *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tthicknessFactor *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n\t\tattenuationColor, attenuationDistance );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n\ttransmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tgl_FragColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tgl_FragColor = vec4( mix( pow( gl_FragColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), gl_FragColor.rgb * 0.0773993808, vec3( lessThanEqual( gl_FragColor.rgb, vec3( 0.04045 ) ) ) ), gl_FragColor.w );\n\t#endif\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},_n={common:{diffuse:{value:new Ht(16777215)},opacity:{value:1},map:{value:null},uvTransform:{value:new Ct},uv2Transform:{value:new Ct},alphaMap:{value:null},alphaTest:{value:0}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new Et(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Ht(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotShadowMap:{value:[]},spotShadowMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Ht(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Ct}},sprite:{diffuse:{value:new Ht(16777215)},opacity:{value:1},center:{value:new Et(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Ct}}},Mn={basic:{uniforms:$i([_n.common,_n.specularmap,_n.envmap,_n.aomap,_n.lightmap,_n.fog]),vertexShader:yn.meshbasic_vert,fragmentShader:yn.meshbasic_frag},lambert:{uniforms:$i([_n.common,_n.specularmap,_n.envmap,_n.aomap,_n.lightmap,_n.emissivemap,_n.fog,_n.lights,{emissive:{value:new Ht(0)}}]),vertexShader:yn.meshlambert_vert,fragmentShader:yn.meshlambert_frag},phong:{uniforms:$i([_n.common,_n.specularmap,_n.envmap,_n.aomap,_n.lightmap,_n.emissivemap,_n.bumpmap,_n.normalmap,_n.displacementmap,_n.fog,_n.lights,{emissive:{value:new Ht(0)},specular:{value:new Ht(1118481)},shininess:{value:30}}]),vertexShader:yn.meshphong_vert,fragmentShader:yn.meshphong_frag},standard:{uniforms:$i([_n.common,_n.envmap,_n.aomap,_n.lightmap,_n.emissivemap,_n.bumpmap,_n.normalmap,_n.displacementmap,_n.roughnessmap,_n.metalnessmap,_n.fog,_n.lights,{emissive:{value:new Ht(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:yn.meshphysical_vert,fragmentShader:yn.meshphysical_frag},toon:{uniforms:$i([_n.common,_n.aomap,_n.lightmap,_n.emissivemap,_n.bumpmap,_n.normalmap,_n.displacementmap,_n.gradientmap,_n.fog,_n.lights,{emissive:{value:new Ht(0)}}]),vertexShader:yn.meshtoon_vert,fragmentShader:yn.meshtoon_frag},matcap:{uniforms:$i([_n.common,_n.bumpmap,_n.normalmap,_n.displacementmap,_n.fog,{matcap:{value:null}}]),vertexShader:yn.meshmatcap_vert,fragmentShader:yn.meshmatcap_frag},points:{uniforms:$i([_n.points,_n.fog]),vertexShader:yn.points_vert,fragmentShader:yn.points_frag},dashed:{uniforms:$i([_n.common,_n.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:yn.linedashed_vert,fragmentShader:yn.linedashed_frag},depth:{uniforms:$i([_n.common,_n.displacementmap]),vertexShader:yn.depth_vert,fragmentShader:yn.depth_frag},normal:{uniforms:$i([_n.common,_n.bumpmap,_n.normalmap,_n.displacementmap,{opacity:{value:1}}]),vertexShader:yn.meshnormal_vert,fragmentShader:yn.meshnormal_frag},sprite:{uniforms:$i([_n.sprite,_n.fog]),vertexShader:yn.sprite_vert,fragmentShader:yn.sprite_frag},background:{uniforms:{uvTransform:{value:new Ct},t2D:{value:null}},vertexShader:yn.background_vert,fragmentShader:yn.background_frag},cube:{uniforms:$i([_n.envmap,{opacity:{value:1}}]),vertexShader:yn.cube_vert,fragmentShader:yn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:yn.equirect_vert,fragmentShader:yn.equirect_frag},distanceRGBA:{uniforms:$i([_n.common,_n.displacementmap,{referencePosition:{value:new ee},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:yn.distanceRGBA_vert,fragmentShader:yn.distanceRGBA_frag},shadow:{uniforms:$i([_n.lights,_n.fog,{color:{value:new Ht(0)},opacity:{value:1}}]),vertexShader:yn.shadow_vert,fragmentShader:yn.shadow_frag}};function bn(t,e,i,n,r,s){const a=new Ht(0);let o,c,h=!0===r?0:1,u=null,d=0,p=null;function m(t,e){i.buffers.color.setClear(t.r,t.g,t.b,e,s)}return{getClearColor:function(){return a},setClearColor:function(t,e=1){a.set(t),h=e,m(a,h)},getClearAlpha:function(){return h},setClearAlpha:function(t){h=t,m(a,h)},render:function(i,r){let s=!1,f=!0===r.isScene?r.background:null;f&&f.isTexture&&(f=e.get(f));const g=t.xr,v=g.getSession&&g.getSession();v&&"additive"===v.environmentBlendMode&&(f=null),null===f?m(a,h):f&&f.isColor&&(m(f,1),s=!0),(t.autoClear||s)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),f&&(f.isCubeTexture||f.mapping===l)?(void 0===c&&(c=new Yi(new Ki(1,1,1),new en({name:"BackgroundCubeMaterial",uniforms:Qi(Mn.cube.uniforms),vertexShader:Mn.cube.vertexShader,fragmentShader:Mn.cube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(t,e,i){this.matrixWorld.copyPosition(i.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),n.update(c)),c.material.uniforms.envMap.value=f,c.material.uniforms.flipEnvMap.value=f.isCubeTexture&&!1===f.isRenderTargetTexture?-1:1,u===f&&d===f.version&&p===t.toneMapping||(c.material.needsUpdate=!0,u=f,d=f.version,p=t.toneMapping),c.layers.enableAll(),i.unshift(c,c.geometry,c.material,0,0,null)):f&&f.isTexture&&(void 0===o&&(o=new Yi(new xn(2,2),new en({name:"BackgroundMaterial",uniforms:Qi(Mn.background.uniforms),vertexShader:Mn.background.vertexShader,fragmentShader:Mn.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),o.geometry.deleteAttribute("normal"),Object.defineProperty(o.material,"map",{get:function(){return this.uniforms.t2D.value}}),n.update(o)),o.material.uniforms.t2D.value=f,!0===f.matrixAutoUpdate&&f.updateMatrix(),o.material.uniforms.uvTransform.value.copy(f.matrix),u===f&&d===f.version&&p===t.toneMapping||(o.material.needsUpdate=!0,u=f,d=f.version,p=t.toneMapping),o.layers.enableAll(),i.unshift(o,o.geometry,o.material,0,0,null))}}}function wn(t,e,i,n){const r=t.getParameter(34921),s=n.isWebGL2?null:e.get("OES_vertex_array_object"),a=n.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return n.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return n.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],i=[],n=[];for(let t=0;t=0){const i=r[e];let n=s[e];if(void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor)),void 0===i)return!0;if(i.attribute!==n)return!0;if(n&&i.data!==n.data)return!0;a++}}return c.attributesNum!==a||c.index!==n}(r,y,d,_),M&&function(t,e,i,n){const r={},s=e.attributes;let a=0;const o=i.getAttributes();for(const e in o){if(o[e].location>=0){let i=s[e];void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor));const n={};n.attribute=i,i&&i.data&&(n.data=i.data),r[e]=n,a++}}c.attributes=r,c.attributesNum=a,c.index=n}(r,y,d,_)}else{const t=!0===l.wireframe;c.geometry===y.id&&c.program===d.id&&c.wireframe===t||(c.geometry=y.id,c.program=d.id,c.wireframe=t,M=!0)}null!==_&&i.update(_,34963),(M||h)&&(h=!1,function(r,s,a,o){if(!1===n.isWebGL2&&(r.isInstancedMesh||o.isInstancedBufferGeometry)&&null===e.get("ANGLE_instanced_arrays"))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const n=c[e];if(n.location>=0){let s=l[e];if(void 0===s&&("instanceMatrix"===e&&r.instanceMatrix&&(s=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(s=r.instanceColor)),void 0!==s){const e=s.normalized,a=s.itemSize,l=i.get(s);if(void 0===l)continue;const c=l.buffer,h=l.type,u=l.bytesPerElement;if(s.isInterleavedBufferAttribute){const i=s.data,l=i.stride,d=s.offset;if(i.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext||"undefined"!=typeof WebGL2ComputeRenderingContext&&t instanceof WebGL2ComputeRenderingContext;let a=void 0!==i.precision?i.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===i.logarithmicDepthBuffer,h=t.getParameter(34930),u=t.getParameter(35660),d=t.getParameter(3379),p=t.getParameter(34076),m=t.getParameter(34921),f=t.getParameter(36347),g=t.getParameter(36348),v=t.getParameter(36349),x=u>0,y=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==n)return n;if(!0===e.has("EXT_texture_filter_anisotropic")){const i=e.get("EXT_texture_filter_anisotropic");n=t.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else n=0;return n},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:x,floatFragmentTextures:y,floatVertexTextures:x&&y,maxSamples:s?t.getParameter(36183):0}}function An(t){const e=this;let i=null,n=0,r=!1,s=!1;const a=new dn,o=new Ct,l={value:null,needsUpdate:!1};function c(){l.value!==i&&(l.value=i,l.needsUpdate=n>0),e.numPlanes=n,e.numIntersection=0}function h(t,i,n,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=n+4*s,r=i.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0){const a=new ln(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",n),i(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}Mn.physical={uniforms:$i([Mn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatNormalScale:{value:new Et(1,1)},clearcoatNormalMap:{value:null},iridescence:{value:0},iridescenceMap:{value:null},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},sheen:{value:0},sheenColor:{value:new Ht(0)},sheenColorMap:{value:null},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},transmission:{value:0},transmissionMap:{value:null},transmissionSamplerSize:{value:new Et},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},attenuationDistance:{value:0},attenuationColor:{value:new Ht(0)},specularIntensity:{value:1},specularIntensityMap:{value:null},specularColor:{value:new Ht(1,1,1)},specularColorMap:{value:null}}]),vertexShader:yn.meshphysical_vert,fragmentShader:yn.meshphysical_frag};class Cn extends nn{constructor(t=-1,e=1,i=1,n=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=i,this.bottom=n,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,i,n,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),i=(this.right+this.left)/2,n=(this.top+this.bottom)/2;let r=i-t,s=i+t,a=n+e,o=n-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}const Ln=[.125,.215,.35,.446,.526,.582],Rn=20,Pn=new Cn,In=new Ht;let Dn=null;const Nn=(1+Math.sqrt(5))/2,zn=1/Nn,On=[new ee(1,1,1),new ee(-1,1,1),new ee(1,1,-1),new ee(-1,1,-1),new ee(0,Nn,zn),new ee(0,Nn,-zn),new ee(zn,0,Nn),new ee(-zn,0,Nn),new ee(Nn,zn,0),new ee(-Nn,zn,0)];class Fn{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,i=.1,n=100,r=null,s=null){return Dn=this._renderer.getRenderTarget(),r||(r=this._allocateTargets()),s&&(this._pingPongRenderTarget=s),this._setSize(256),r.depthBuffer=!0,this._sceneToCubeUV(t,i,n,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}prepareForRenderTarget(t,e=null,i=256){this._setSize(i);const{_lodMax:n}=this;({sizeLods:this._sizeLods,lodPlanes:this._lodPlanes,sigmas:this._sigmas}=Bn(n));const r=3*Math.max(this._cubeSize,112),s=4*this._cubeSize;this._blurMaterial=Gn(n,r,s),t.setSize(r,s),e&&e.setSize(r,s)}fromSceneToRenderTarget(t,e,i,n=0,r=.1,s=100){return Dn=this._renderer.getRenderTarget(),this._pingPongRenderTarget=i,this._sceneToCubeUV(t,r,s,e),n>0&&this._blur(e,0,0,n),this._applyPMREM(e),this._renderer.setRenderTarget(Dn),e.scissorTest=!1,kn(e,0,0,e.width,e.height),e}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=Hn(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=Vn(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let t=0;t2?l:0,l,l),o.setRenderTarget(n),d&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=p}_textureToCubeUV(t,e){const i=this._renderer,n=t.mapping===r||t.mapping===s;n?(null===this._cubemapMaterial&&(this._cubemapMaterial=Hn()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=Vn());const a=n?this._cubemapMaterial:this._equirectMaterial,o=new Yi(this._lodPlanes[0],a);a.uniforms.envMap.value=t;const l=this._cubeSize;kn(e,0,0,3*l,2*l),i.setRenderTarget(e),i.render(o,Pn)}_applyPMREM(t){const e=this._renderer,i=e.autoClear;e.autoClear=!1;for(let e=1;eRn&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;tv-4?n-v+4:0),4*(this._cubeSize-x),3*x,2*x),o.setRenderTarget(e),o.render(c,Pn)}}function Bn(t){const e=[],i=[],n=[];let r=t;const s=t-4+1+Ln.length;for(let a=0;at-4?o=Ln[a-t+4-1]:0===a&&(o=0),n.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),x=new Float32Array(f*p*d),y=new Float32Array(g*p*d);for(let t=0;t2?0:-1,n=[e,i,0,e+2/3,i,0,e+2/3,i+1,0,e,i,0,e+2/3,i+1,0,e,i+1,0];v.set(n,m*p*t),x.set(u,f*p*t);const r=[t,t,t,t,t,t];y.set(r,g*p*t)}const _=new Pi;_.setAttribute("position",new _i(v,m)),_.setAttribute("uv",new _i(x,f)),_.setAttribute("faceIndex",new _i(y,g)),e.push(_),r>4&&r--}return{lodPlanes:e,sizeLods:i,sigmas:n}}function Un(t,e,i){const n=new Kt(t,e,i);return n.texture.mapping=l,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function kn(t,e,i,n,r){t.viewport.set(e,i,n,r),t.scissor.set(e,i,n,r)}function Gn(t,e,i){const n=new Float32Array(Rn),r=new ee(0,1,0);return new en({name:"SphericalGaussianBlur",defines:{n:Rn,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/i,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:Wn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function Vn(){return new en({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:Wn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function Hn(){return new en({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:Wn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function Wn(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\tmat3 getRotationMatrix(vec3 axis, float angle) {\n\t\t\taxis = normalize(axis);\n\t\t\tfloat s = sin(angle);\n\t\t\tfloat c = cos(angle);\n\t\t\tfloat oc = 1.0 - c;\n\t\t\n\t\t\treturn mat3(oc * axis.x * axis.x + c,\t\t\t\t\t oc * axis.x * axis.y - axis.z * s,\toc * axis.z * axis.x + axis.y * s,\n\t\t\t\t\t\toc * axis.x * axis.y + axis.z * s,\toc * axis.y * axis.y + c,\t\t\t\t\t oc * axis.y * axis.z - axis.x * s,\n\t\t\t\t\t\toc * axis.z * axis.x - axis.y * s,\toc * axis.y * axis.z + axis.x * s,\toc * axis.z * axis.z + c);\n\t\t}\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\t\t\tmat3 rotationMatrix = getRotationMatrix(vec3(1.0, 0.0, 0.0), 1.57);\n\t\t\tdirection = rotationMatrix * direction;\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function jn(t){let e=new WeakMap,i=null;function n(t){const i=t.target;i.removeEventListener("dispose",n);const r=e.get(i);void 0!==r&&(e.delete(i),r.dispose())}return{get:function(l){if(l&&l.isTexture){const c=l.mapping,h=c===a||c===o,u=c===r||c===s;if(h||u){if(l.isRenderTargetTexture&&!0===l.needsPMREMUpdate){l.needsPMREMUpdate=!1;let n=e.get(l);return null===i&&(i=new Fn(t)),n=h?i.fromEquirectangular(l,n):i.fromCubemap(l,n),e.set(l,n),n.texture}if(e.has(l))return e.get(l).texture;{const r=l.image;if(h&&r&&r.height>0||u&&r&&function(t){let e=0;const i=6;for(let n=0;ne.maxTextureSize&&(E=Math.ceil(A/e.maxTextureSize),A=e.maxTextureSize);const C=new Float32Array(A*E*4*m),L=new Qt(C,A,E,m);L.type=M,L.needsUpdate=!0;const R=4*T;for(let I=0;I0)return t;const r=e*i;let s=sr[r];if(void 0===s&&(s=new Float32Array(r),sr[r]=s),0!==e){n.toArray(s,0);for(let n=1,r=0;n!==e;++n)r+=i,t[n].toArray(s,r)}return s}function ur(t,e){if(t.length!==e.length)return!1;for(let i=0,n=t.length;i":" "} ${r}: ${i[t]}`)}return n.join("\n")}(t.getShaderSource(e),n)}return r}function ls(t,e){const i=function(t){switch(t){case at:return["Linear","( value )"];case ot:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported encoding:",t),["Linear","( value )"]}}(e);return"vec4 "+t+"( vec4 value ) { return LinearTo"+i[0]+i[1]+"; }"}function cs(t,e){let i;switch(e){case 1:i="Linear";break;case 2:i="Reinhard";break;case 3:i="OptimizedCineon";break;case 4:i="ACESFilmic";break;case 5:i="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),i="Linear"}return"vec3 "+t+"( vec3 color ) { return "+i+"ToneMapping( color ); }"}function hs(t){return""!==t}function us(t,e){return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function ds(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const ps=/^[ \t]*#include +<([\w\d./]+)>/gm;function ms(t){return t.replace(ps,fs)}function fs(t,e){const i=yn[e];if(void 0===i)throw new Error("Can not resolve #include <"+e+">");return ms(i)}const gs=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,vs=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function xs(t){return t.replace(vs,_s).replace(gs,ys)}function ys(t,e,i,n){return console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."),_s(t,e,i,n)}function _s(t,e,i,n){let r="";for(let t=parseInt(e);t0&&(y+="\n"),_=[g,v].filter(hs).join("\n"),_.length>0&&(_+="\n")):(y=[Ms(i),"#define SHADER_NAME "+i.shaderName,v,i.instancing?"#define USE_INSTANCING":"",i.instancingColor?"#define USE_INSTANCING_COLOR":"",i.supportsVertexTextures?"#define VERTEX_TEXTURES":"",i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+p:"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.displacementMap&&i.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.flatShading?"#define FLAT_SHADED":"",i.skinning?"#define USE_SKINNING":"",i.morphTargets?"#define USE_MORPHTARGETS":"",i.morphNormals&&!1===i.flatShading?"#define USE_MORPHNORMALS":"",i.morphColors&&i.isWebGL2?"#define USE_MORPHCOLORS":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+i.morphTextureStride:"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_COUNT "+i.morphTargetsCount:"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.sizeAttenuation?"#define USE_SIZEATTENUATION":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(hs).join("\n"),_=[g,Ms(i),"#define SHADER_NAME "+i.shaderName,v,i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.matcap?"#define USE_MATCAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+d:"",i.envMap?"#define "+p:"",i.envMap?"#define "+m:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoat?"#define USE_CLEARCOAT":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescence?"#define USE_IRIDESCENCE":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.alphaTest?"#define USE_ALPHATEST":"",i.sheen?"#define USE_SHEEN":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors||i.instancingColor?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.gradientMap?"#define USE_GRADIENTMAP":"",i.flatShading?"#define FLAT_SHADED":"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",i.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==i.toneMapping?"#define TONE_MAPPING":"",0!==i.toneMapping?yn.tonemapping_pars_fragment:"",0!==i.toneMapping?cs("toneMapping",i.toneMapping):"",i.dithering?"#define DITHERING":"",i.opaque?"#define OPAQUE":"",yn.encodings_pars_fragment,ls("linearToOutputTexel",i.outputEncoding),i.useDepthPacking?"#define DEPTH_PACKING "+i.depthPacking:"","\n"].filter(hs).join("\n")),t.onShaderBeforeResolve){const e=t.onShaderBeforeResolve(c,h,i);c=e.vertexShader,h=e.fragmentShader}c=ms(c),c=us(c,i),c=ds(c,i),h=ms(h),h=us(h,i),h=ds(h,i),c=xs(c),h=xs(h),i.isWebGL2&&!0!==i.isRawShaderMaterial&&(M="#version 300 es\n",y=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,_=["#define varying in",i.glslVersion===dt?"":"layout(location = 0) out highp vec4 pc_fragColor;",i.glslVersion===dt?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+_);let b=M+y+c,w=M+_+h;if(t.onShaderBeforeCompile){const e=t.onShaderBeforeCompile(b,w,i);b=e.vertexShader,w=e.fragmentShader}const S=ss(a,35633,b),T=ss(a,35632,w);if(a.attachShader(x,S),a.attachShader(x,T),void 0!==i.index0AttributeName?a.bindAttribLocation(x,0,i.index0AttributeName):!0===i.morphTargets&&a.bindAttribLocation(x,0,"position"),a.linkProgram(x),t.debug.checkShaderErrors){const t=a.getProgramInfoLog(x).trim(),e=a.getShaderInfoLog(S).trim(),i=a.getShaderInfoLog(T).trim();let n=!0,r=!0;if(!1===a.getProgramParameter(x,35714)){n=!1;const e=os(a,S,"vertex"),i=os(a,T,"fragment");console.error("THREE.WebGLProgram: Shader Error "+a.getError()+" - VALIDATE_STATUS "+a.getProgramParameter(x,35715)+"\n\nProgram Info Log: "+t+"\n"+e+"\n"+i)}else""!==t?console.warn("THREE.WebGLProgram: Program Info Log:",t):""!==e&&""!==i||(r=!1);r&&(this.diagnostics={runnable:n,programLog:t,vertexShader:{log:e,prefix:y},fragmentShader:{log:i,prefix:_}})}let A,E;return a.deleteShader(S),a.deleteShader(T),this.getUniforms=function(){return void 0===A&&(A=new rs(a,x)),A},this.getAttributes=function(){return void 0===E&&(E=function(t,e){const i={},n=t.getProgramParameter(e,35721);for(let r=0;r0,D=s.clearcoat>0,N=s.iridescence>0;return{isWebGL2:u,shaderID:w,shaderName:s.type,vertexShader:A,fragmentShader:E,defines:s.defines,customVertexShaderID:C,customFragmentShaderID:L,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:m,instancing:!0===v.isInstancedMesh,instancingColor:!0===v.isInstancedMesh&&null!==v.instanceColor,supportsVertexTextures:p,outputEncoding:null===P?t.outputEncoding:!0===P.isXRRenderTarget?P.texture.encoding:at,map:!!s.map,matcap:!!s.matcap,envMap:!!M,envMapMode:M&&M.mapping,envMapCubeUVHeight:b,lightMap:!!s.lightMap,aoMap:!!s.aoMap,emissiveMap:!!s.emissiveMap,bumpMap:!!s.bumpMap,normalMap:!!s.normalMap,objectSpaceNormalMap:1===s.normalMapType,tangentSpaceNormalMap:0===s.normalMapType,decodeVideoTexture:!!s.map&&!0===s.map.isVideoTexture&&s.map.encoding===ot,clearcoat:D,clearcoatMap:D&&!!s.clearcoatMap,clearcoatRoughnessMap:D&&!!s.clearcoatRoughnessMap,clearcoatNormalMap:D&&!!s.clearcoatNormalMap,iridescence:N,iridescenceMap:N&&!!s.iridescenceMap,iridescenceThicknessMap:N&&!!s.iridescenceThicknessMap,displacementMap:!!s.displacementMap,roughnessMap:!!s.roughnessMap,metalnessMap:!!s.metalnessMap,specularMap:!!s.specularMap,specularIntensityMap:!!s.specularIntensityMap,specularColorMap:!!s.specularColorMap,opaque:!1===s.transparent&&1===s.blending,alphaMap:!!s.alphaMap,alphaTest:I,gradientMap:!!s.gradientMap,sheen:s.sheen>0,sheenColorMap:!!s.sheenColorMap,sheenRoughnessMap:!!s.sheenRoughnessMap,transmission:s.transmission>0,transmissionMap:!!s.transmissionMap,thicknessMap:!!s.thicknessMap,combine:s.combine,vertexTangents:!!s.normalMap&&!!y.attributes.tangent,vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!y.attributes.color&&4===y.attributes.color.itemSize,vertexUvs:!!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatMap||s.clearcoatRoughnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.displacementMap||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheenColorMap||s.sheenRoughnessMap),uvsVertexOnly:!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.transmission>0||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheen>0||s.sheenColorMap||s.sheenRoughnessMap||!s.displacementMap),fog:!!x,useFog:!0===s.fog,fogExp2:x&&x.isFogExp2,flatShading:!!s.flatShading,sizeAttenuation:s.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===v.isSkinnedMesh,morphTargets:void 0!==y.morphAttributes.position,morphNormals:void 0!==y.morphAttributes.normal,morphColors:void 0!==y.morphAttributes.color,morphTargetsCount:T,morphTextureStride:R,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:1===s.side,useDepthPacking:!!s.depthPacking,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:s.extensions&&s.extensions.derivatives,extensionFragDepth:s.extensions&&s.extensions.fragDepth,extensionDrawBuffers:s.extensions&&s.extensions.drawBuffers,extensionShaderTextureLOD:s.extensions&&s.extensions.shaderTextureLOD,rendererExtensionFragDepth:u||n.has("EXT_frag_depth"),rendererExtensionDrawBuffers:u||n.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:u||n.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey(),extraProgramCacheKey:t.extraProgramCacheKey}},getProgramCacheKey:function(e){const i=[];if(e.shaderID?i.push(e.shaderID):(i.push(e.customVertexShaderID),i.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)i.push(t),i.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputEncoding),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.combine),t.push(e.vertexUvs),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(i,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.map&&o.enable(4);e.matcap&&o.enable(5);e.envMap&&o.enable(6);e.lightMap&&o.enable(7);e.aoMap&&o.enable(8);e.emissiveMap&&o.enable(9);e.bumpMap&&o.enable(10);e.normalMap&&o.enable(11);e.objectSpaceNormalMap&&o.enable(12);e.tangentSpaceNormalMap&&o.enable(13);e.clearcoat&&o.enable(14);e.clearcoatMap&&o.enable(15);e.clearcoatRoughnessMap&&o.enable(16);e.clearcoatNormalMap&&o.enable(17);e.iridescence&&o.enable(18);e.iridescenceMap&&o.enable(19);e.iridescenceThicknessMap&&o.enable(20);e.displacementMap&&o.enable(21);e.specularMap&&o.enable(22);e.roughnessMap&&o.enable(23);e.metalnessMap&&o.enable(24);e.gradientMap&&o.enable(25);e.alphaMap&&o.enable(26);e.alphaTest&&o.enable(27);e.vertexColors&&o.enable(28);e.vertexAlphas&&o.enable(29);e.vertexUvs&&o.enable(30);e.vertexTangents&&o.enable(31);e.uvsVertexOnly&&o.enable(32);e.fog&&o.enable(33);t.push(o.mask),o.disableAll(),e.useFog&&o.enable(0);e.flatShading&&o.enable(1);e.logarithmicDepthBuffer&&o.enable(2);e.skinning&&o.enable(3);e.morphTargets&&o.enable(4);e.morphNormals&&o.enable(5);e.morphColors&&o.enable(6);e.premultipliedAlpha&&o.enable(7);e.shadowMapEnabled&&o.enable(8);e.physicallyCorrectLights&&o.enable(9);e.doubleSided&&o.enable(10);e.flipSided&&o.enable(11);e.useDepthPacking&&o.enable(12);e.dithering&&o.enable(13);e.specularIntensityMap&&o.enable(14);e.specularColorMap&&o.enable(15);e.transmission&&o.enable(16);e.transmissionMap&&o.enable(17);e.thicknessMap&&o.enable(18);e.sheen&&o.enable(19);e.sheenColorMap&&o.enable(20);e.sheenRoughnessMap&&o.enable(21);e.decodeVideoTexture&&o.enable(22);e.opaque&&o.enable(23);t.push(o.mask)}(i,e),i.push(t.outputEncoding)),i.push(e.customProgramCacheKey),t.extraProgramCacheKey&&i.push(t.extraProgramCacheKey),i.join()},getUniforms:function(t){const e=f[t.type];let i;if(e){const t=Mn[e];i=tn.clone(t.uniforms)}else i=t.uniforms;return i},acquireProgram:function(e,i){let n;for(let t=0,e=h.length;t0?n.push(h):!0===a.transparent?r.push(h):i.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?n.unshift(h):!0===a.transparent?r.unshift(h):i.unshift(h)},finish:function(){for(let i=e,n=t.length;i1&&i.sort(t||Cs),n.length>1&&n.sort(e||Ls),r.length>1&&r.sort(e||Ls)}}}function Ps(){let t=new WeakMap;return{get:function(e,i){let n;return!1===t.has(e)?(n=new Rs,t.set(e,[n])):i>=t.get(e).length?(n=new Rs,t.get(e).push(n)):n=t.get(e)[i],n},dispose:function(){t=new WeakMap}}}function Is(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":i={direction:new ee,color:new Ht};break;case"SpotLight":i={position:new ee,direction:new ee,color:new Ht,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":i={position:new ee,color:new Ht,distance:0,decay:0};break;case"HemisphereLight":i={direction:new ee,skyColor:new Ht,groundColor:new Ht};break;case"RectAreaLight":i={color:new Ht,position:new ee,halfWidth:new ee,halfHeight:new ee}}return t[e.id]=i,i}}}let Ds=0;function Ns(t,e){return(e.castShadow?1:0)-(t.castShadow?1:0)}function zs(t,e){const i=new Is,n=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":case"SpotLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Et};break;case"PointLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Et,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=i,i}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadow:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]};for(let t=0;t<9;t++)r.probe.push(new ee);const s=new ee,a=new Ie,o=new Ie;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0;s.sort(Ns);const x=!0!==a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=_n.LTC_FLOAT_1,r.rectAreaLTC2=_n.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=_n.LTC_HALF_1,r.rectAreaLTC2=_n.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const y=r.hash;y.directionalLength===h&&y.pointLength===u&&y.spotLength===d&&y.rectAreaLength===p&&y.hemiLength===m&&y.numDirectionalShadows===f&&y.numPointShadows===g&&y.numSpotShadows===v||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotShadowMatrix.length=v,y.directionalLength=h,y.pointLength=u,y.spotLength=d,y.rectAreaLength=p,y.hemiLength=m,y.numDirectionalShadows=f,y.numPointShadows=g,y.numSpotShadows=v,r.version=Ds++)},setupView:function(t,e){let i=0,n=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=i.get(n).length?(s=new Os(t,e),i.get(n).push(s)):s=i.get(n)[r],s},dispose:function(){i=new WeakMap}}}class Bs extends gi{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Us extends gi{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.referencePosition=new ee,this.nearDistance=1,this.farDistance=1e3,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function ks(t,e,i){let n=new fn;const r=new Et,s=new Et,a=new Zt,o=new Bs({depthPacking:3201}),l=new Us,c={},h=i.maxTextureSize,u={0:1,1:0,2:2},p=new en({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new Et},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),m=p.clone();m.defines.HORIZONTAL_PASS=1;const f=new Pi;f.setAttribute("position",new _i(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new Yi(f,p),v=this;function x(i,n){const r=e.update(g);p.defines.VSM_SAMPLES!==i.blurSamples&&(p.defines.VSM_SAMPLES=i.blurSamples,m.defines.VSM_SAMPLES=i.blurSamples,p.needsUpdate=!0,m.needsUpdate=!0),p.uniforms.shadow_pass.value=i.map.texture,p.uniforms.resolution.value=i.mapSize,p.uniforms.radius.value=i.radius,t.setRenderTarget(i.mapPass),t.clear(),t.renderBufferDirect(n,null,r,p,g,null),m.uniforms.shadow_pass.value=i.mapPass.texture,m.uniforms.resolution.value=i.mapSize,m.uniforms.radius.value=i.radius,t.setRenderTarget(i.map),t.clear(),t.renderBufferDirect(n,null,r,m,g,null)}function y(e,i,n,r,s,a){let h=null;const d=!0===n.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(h=void 0!==d?d:!0===n.isPointLight?l:o,t.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length||i.displacementMap&&0!==i.displacementScale||i.alphaMap&&i.alphaTest>0){const t=h.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=h.clone(),n[e]=r),h=r}return h.visible=i.visible,h.wireframe=i.wireframe,h.side=3===a?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],h.alphaMap=i.alphaMap,h.alphaTest=i.alphaTest,h.clipShadows=i.clipShadows,h.clippingPlanes=i.clippingPlanes,h.clipIntersection=i.clipIntersection,h.displacementMap=i.displacementMap,h.displacementScale=i.displacementScale,h.displacementBias=i.displacementBias,h.wireframeLinewidth=i.wireframeLinewidth,h.linewidth=i.linewidth,!0===n.isPointLight&&!0===h.isMeshDistanceMaterial&&(h.referencePosition.setFromMatrixPosition(n.matrixWorld),h.nearDistance=r,h.farDistance=s),h}function _(i,r,s,a,o){if(!1===i.visible)return;if(i.layers.test(r.layers)&&(i.isMesh||i.isLine||i.isPoints)&&(i.castShadow||i.receiveShadow&&3===o)&&(!i.frustumCulled||n.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,i.matrixWorld);const n=e.update(i),r=i.material;if(Array.isArray(r)){const e=n.groups;for(let l=0,c=e.length;lh||r.y>h)&&(r.x>h&&(s.x=Math.floor(h/m.x),r.x=s.x*m.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/m.y),r.y=s.y*m.y,u.mapSize.y=s.y)),null!==u.map||u.isPointLightShadow||3!==this.type||(u.map=new Kt(r.x,r.y),u.map.texture.name=c.name+".shadowMap",u.mapPass=new Kt(r.x,r.y),u.camera.updateProjectionMatrix()),null===u.map){const t={minFilter:d,magFilter:d,format:S};u.map=new Kt(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const f=u.getViewportCount();for(let t=0;t=1):-1!==R.indexOf("OpenGL ES")&&(L=parseFloat(/^OpenGL ES (\d)/.exec(R)[1]),C=L>=2);let P=null,I={};const D=t.getParameter(3088),N=t.getParameter(2978),z=(new Zt).fromArray(D),O=(new Zt).fromArray(N);function F(e,i,n){const r=new Uint8Array(4),s=t.createTexture();t.bindTexture(e,s),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(let e=0;en||t.height>n)&&(r=n/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const n=e?Tt:Math.floor,s=n(r*t.width),a=n(r*t.height);void 0===D&&(D=O(s,a));const o=i?O(s,a):D;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function B(t){return wt(t.width)&&wt(t.height)}function U(t,e){return t.generateMipmaps&&e&&t.minFilter!==d&&t.minFilter!==f}function k(e){t.generateMipmap(e)}function G(i,n,r,s,a=!1){if(!1===o)return n;if(null!==i){if(void 0!==t[i])return t[i];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+i+"'")}let l=n;return 6403===n&&(5126===r&&(l=33326),5131===r&&(l=33325),5121===r&&(l=33321)),33319===n&&(5126===r&&(l=33328),5131===r&&(l=33327),5121===r&&(l=33323)),6408===n&&(5126===r&&(l=34836),5131===r&&(l=34842),5121===r&&(l=s===ot&&!1===a?35907:32856),32819===r&&(l=32854),32820===r&&(l=32855)),33325!==l&&33326!==l&&33327!==l&&33328!==l&&34842!==l&&34836!==l||e.get("EXT_color_buffer_float"),l}function V(t,e,i){return!0===U(t,i)||t.isFramebufferTexture&&t.minFilter!==d&&t.minFilter!==f?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function H(t){return t===d||t===p||t===m?9728:9729}function W(t){const e=t.target;e.removeEventListener("dispose",W),function(t){const e=n.get(t);if(void 0===e.__webglInit)return;const i=t.source,r=N.get(i);if(r){const n=r[e.__cacheKey];n.usedTimes--,0===n.usedTimes&&q(t),0===Object.keys(r).length&&N.delete(i)}n.remove(t)}(e),e.isVideoTexture&&I.delete(e)}function j(e){const i=e.target;i.removeEventListener("dispose",j),function(e){const i=e.texture,r=n.get(e),s=n.get(i);void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else{if(t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e0&&r.__version!==t.version){const i=t.image;if(null===i)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==i.complete)return void $(r,t,e);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}i.activeTexture(33984+e),i.bindTexture(3553,r.__webglTexture)}const Y={[c]:10497,[h]:33071,[u]:33648},Z={[d]:9728,[p]:9984,[m]:9986,[f]:9729,[g]:9985,[v]:9987};function K(i,s,a){if(a?(t.texParameteri(i,10242,Y[s.wrapS]),t.texParameteri(i,10243,Y[s.wrapT]),32879!==i&&35866!==i||t.texParameteri(i,32882,Y[s.wrapR]),t.texParameteri(i,10240,Z[s.magFilter]),t.texParameteri(i,10241,Z[s.minFilter])):(t.texParameteri(i,10242,33071),t.texParameteri(i,10243,33071),32879!==i&&35866!==i||t.texParameteri(i,32882,33071),s.wrapS===h&&s.wrapT===h||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(i,10240,H(s.magFilter)),t.texParameteri(i,10241,H(s.minFilter)),s.minFilter!==d&&s.minFilter!==f&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),!0===e.has("EXT_texture_filter_anisotropic")){const a=e.get("EXT_texture_filter_anisotropic");if(s.type===M&&!1===e.has("OES_texture_float_linear"))return;if(!1===o&&s.type===b&&!1===e.has("OES_texture_half_float_linear"))return;(s.anisotropy>1||n.get(s).__currentAnisotropy)&&(t.texParameterf(i,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),n.get(s).__currentAnisotropy=s.anisotropy)}}function Q(e,i){let n=!1;void 0===e.__webglInit&&(e.__webglInit=!0,i.addEventListener("dispose",W));const r=i.source;let s=N.get(r);void 0===s&&(s={},N.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.encoding),e.join()}(i);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,n=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&q(i)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return n}function $(e,n,r){let a=3553;n.isDataArrayTexture&&(a=35866),n.isData3DTexture&&(a=32879);const l=Q(e,n),c=n.source;if(i.activeTexture(33984+r),i.bindTexture(a,e.__webglTexture),c.version!==c.__currentVersion||!0===l){t.pixelStorei(37440,n.flipY),t.pixelStorei(37441,n.premultiplyAlpha),t.pixelStorei(3317,n.unpackAlignment),t.pixelStorei(37443,0);const e=function(t){return!o&&(t.wrapS!==h||t.wrapT!==h||t.minFilter!==d&&t.minFilter!==f)}(n)&&!1===B(n.image);let r=F(n.image,e,!1,C);r=st(n,r);const u=B(r)||o,p=s.convert(n.format,n.encoding);let m,g=s.convert(n.type),v=G(n.internalFormat,p,g,n.encoding,n.isVideoTexture);K(a,n,u);const x=n.mipmaps,b=o&&!0!==n.isVideoTexture,E=void 0===c.__currentVersion||!0===l,L=V(n,r,u);if(n.isDepthTexture)v=6402,o?v=n.type===M?36012:n.type===_?33190:n.type===w?35056:33189:n.type===M&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),n.format===T&&6402===v&&n.type!==y&&n.type!==_&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),n.type=_,g=s.convert(n.type)),n.format===A&&6402===v&&(v=34041,n.type!==w&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),n.type=w,g=s.convert(n.type))),E&&(b?i.texStorage2D(3553,1,v,r.width,r.height):i.texImage2D(3553,0,v,r.width,r.height,0,p,g,null));else if(n.isDataTexture)if(x.length>0&&u){b&&E&&i.texStorage2D(3553,L,v,x[0].width,x[0].height);for(let t=0,e=x.length;t>=1,e>>=1}}else if(x.length>0&&u){b&&E&&i.texStorage2D(3553,L,v,x[0].width,x[0].height);for(let t=0,e=x.length;t0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==i.__useRenderToTexture}function st(t,i){const n=t.encoding,r=t.format,s=t.type;return!0===t.isCompressedTexture||!0===t.isVideoTexture||t.format===pt||n!==at&&(n===ot?!1===o?!0===e.has("EXT_sRGB")&&r===S?(t.format=pt,t.minFilter=f,t.generateMipmaps=!1):i=jt.sRGBToLinear(i):r===S&&s===x||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture encoding:",n)),i}this.allocateTextureUnit=function(){const t=X;return t>=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),X+=1,t},this.resetTextureUnits=function(){X=0},this.setTexture2D=J,this.setTexture2DArray=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?$(r,t,e):(i.activeTexture(33984+e),i.bindTexture(35866,r.__webglTexture))},this.setTexture3D=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?$(r,t,e):(i.activeTexture(33984+e),i.bindTexture(32879,r.__webglTexture))},this.setTextureCube=function(e,r){const a=n.get(e);e.version>0&&a.__version!==e.version?function(e,n,r){if(6!==n.image.length)return;const a=Q(e,n),l=n.source;if(i.activeTexture(33984+r),i.bindTexture(34067,e.__webglTexture),l.version!==l.__currentVersion||!0===a){t.pixelStorei(37440,n.flipY),t.pixelStorei(37441,n.premultiplyAlpha),t.pixelStorei(3317,n.unpackAlignment),t.pixelStorei(37443,0);const e=n.isCompressedTexture||n.image[0].isCompressedTexture,r=n.image[0]&&n.image[0].isDataTexture,c=[];for(let t=0;t<6;t++)c[t]=e||r?r?n.image[t].image:n.image[t]:F(n.image[t],!1,!0,E),c[t]=st(n,c[t]);const h=c[0],u=B(h)||o,d=s.convert(n.format,n.encoding),p=s.convert(n.type),m=G(n.internalFormat,d,p,n.encoding),f=o&&!0!==n.isVideoTexture,g=void 0===l.__currentVersion||!0===a;let v,x=V(n,h,u);if(K(34067,n,u),e){f&&g&&i.texStorage2D(34067,x,m,h.width,h.height);for(let t=0;t<6;t++){v=c[t].mipmaps;for(let e=0;e0&&x++,i.texStorage2D(34067,x,m,c[0].width,c[0].height));for(let t=0;t<6;t++)if(r){f?i.texSubImage2D(34069+t,0,0,0,c[t].width,c[t].height,d,p,c[t].data):i.texImage2D(34069+t,0,m,c[t].width,c[t].height,0,d,p,c[t].data);for(let e=0;e0&&!1===rt(e)){const n=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],i.bindFramebuffer(36160,c.__webglMultisampledFramebuffer);for(let i=0;i0&&!1===rt(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=16384;const l=[],c=e.stencilBuffer?33306:36096,h=n.get(e),u=!0===e.isWebGLMultipleRenderTargets;if(u)for(let e=0;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,i),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));return null!==a&&(a.visible=null!==n),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}}class Js extends Yt{constructor(t,e,i,n,r,s,a,o,l,c){if((c=void 0!==c?c:T)!==T&&c!==A)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===i&&c===T&&(i=_),void 0===i&&c===A&&(i=w),super(null,n,r,s,a,o,c,i,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:d,this.minFilter=void 0!==o?o:d,this.flipY=!1,this.generateMipmaps=!1}}class Ys extends mt{constructor(t,e){super();const i=this;let n=null,r=1,s=null,a="local-floor",o=null,l=null,c=null,h=null,u=null,d=null;const p=e.getContextAttributes();let m=null,f=null;const g=[],v=new Map,y=new rn;y.layers.enable(1),y.viewport=new Zt;const M=new rn;M.layers.enable(2),M.viewport=new Zt;const b=[y,M],E=new Ws;E.layers.enable(1),E.layers.enable(2);let C=null,L=null;function R(t){const e=v.get(t.inputSource);void 0!==e&&e.dispatchEvent({type:t.type,data:t.inputSource})}function P(){n.removeEventListener("select",R),n.removeEventListener("selectstart",R),n.removeEventListener("selectend",R),n.removeEventListener("squeeze",R),n.removeEventListener("squeezestart",R),n.removeEventListener("squeezeend",R),n.removeEventListener("end",P),n.removeEventListener("inputsourceschange",I),v.forEach((function(t,e){void 0!==t&&t.disconnect(e)})),v.clear(),C=null,L=null,t.setRenderTarget(m),u=null,h=null,c=null,n=null,f=null,F.stop(),i.isPresenting=!1,i.dispatchEvent({type:"sessionend"})}function I(t){const e=n.inputSources;for(let t=0;t0&&(i.alphaTest.value=n.alphaTest);const r=e.get(n).envMap;if(r&&(i.envMap.value=r,i.flipEnvMap.value=r.isCubeTexture&&!1===r.isRenderTargetTexture?-1:1,i.reflectivity.value=n.reflectivity,i.ior.value=n.ior,i.refractionRatio.value=n.refractionRatio),n.lightMap){i.lightMap.value=n.lightMap;const e=!0!==t.physicallyCorrectLights?Math.PI:1;i.lightMapIntensity.value=n.lightMapIntensity*e}let s,a;n.aoMap&&(i.aoMap.value=n.aoMap,i.aoMapIntensity.value=n.aoMapIntensity),n.map?s=n.map:n.specularMap?s=n.specularMap:n.displacementMap?s=n.displacementMap:n.normalMap?s=n.normalMap:n.bumpMap?s=n.bumpMap:n.roughnessMap?s=n.roughnessMap:n.metalnessMap?s=n.metalnessMap:n.alphaMap?s=n.alphaMap:n.emissiveMap?s=n.emissiveMap:n.clearcoatMap?s=n.clearcoatMap:n.clearcoatNormalMap?s=n.clearcoatNormalMap:n.clearcoatRoughnessMap?s=n.clearcoatRoughnessMap:n.iridescenceMap?s=n.iridescenceMap:n.iridescenceThicknessMap?s=n.iridescenceThicknessMap:n.specularIntensityMap?s=n.specularIntensityMap:n.specularColorMap?s=n.specularColorMap:n.transmissionMap?s=n.transmissionMap:n.thicknessMap?s=n.thicknessMap:n.sheenColorMap?s=n.sheenColorMap:n.sheenRoughnessMap&&(s=n.sheenRoughnessMap),void 0!==s&&(s.isWebGLRenderTarget&&(s=s.texture),!0===s.matrixAutoUpdate&&s.updateMatrix(),i.uvTransform.value.copy(s.matrix)),n.aoMap?a=n.aoMap:n.lightMap&&(a=n.lightMap),void 0!==a&&(a.isWebGLRenderTarget&&(a=a.texture),!0===a.matrixAutoUpdate&&a.updateMatrix(),i.uv2Transform.value.copy(a.matrix))}return{refreshFogUniforms:function(t,e){t.fogColor.value.copy(e.color),e.isFog?(t.fogNear.value=e.near,t.fogFar.value=e.far):e.isFogExp2&&(t.fogDensity.value=e.density)},refreshMaterialUniforms:function(t,n,r,s,a){n.isMeshBasicMaterial||n.isMeshLambertMaterial?i(t,n):n.isMeshToonMaterial?(i(t,n),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,n)):n.isMeshPhongMaterial?(i(t,n),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,n)):n.isMeshStandardMaterial?(i(t,n),function(t,i){t.roughness.value=i.roughness,t.metalness.value=i.metalness,i.roughnessMap&&(t.roughnessMap.value=i.roughnessMap);i.metalnessMap&&(t.metalnessMap.value=i.metalnessMap);e.get(i).envMap&&(t.envMapIntensity.value=i.envMapIntensity)}(t,n),n.isMeshPhysicalMaterial&&function(t,e,i){t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap),e.clearcoatNormalMap&&(t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),t.clearcoatNormalMap.value=e.clearcoatNormalMap,1===e.side&&t.clearcoatNormalScale.value.negate()));e.iridescence>0&&(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&&(t.iridescenceMap.value=e.iridescenceMap),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap);e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap)}(t,n,a)):n.isMeshMatcapMaterial?(i(t,n),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,n)):n.isMeshDepthMaterial?i(t,n):n.isMeshDistanceMaterial?(i(t,n),function(t,e){t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(t,n)):n.isMeshNormalMaterial?i(t,n):n.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(t,n),n.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,n)):n.isPointsMaterial?function(t,e,i,n){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*n,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let r;e.map?r=e.map:e.alphaMap&&(r=e.alphaMap);void 0!==r&&(!0===r.matrixAutoUpdate&&r.updateMatrix(),t.uvTransform.value.copy(r.matrix))}(t,n,r,s):n.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let i;e.map?i=e.map:e.alphaMap&&(i=e.alphaMap);void 0!==i&&(!0===i.matrixAutoUpdate&&i.updateMatrix(),t.uvTransform.value.copy(i.matrix))}(t,n):n.isShadowMaterial?(t.color.value.copy(n.color),t.opacity.value=n.opacity):n.isShaderMaterial&&(n.uniformsNeedUpdate=!1)}}}function Ks(t={}){this.isWebGLRenderer=!0;const e=void 0!==t.canvas?t.canvas:function(){const t=It("canvas");return t.style.display="block",t}(),i=void 0!==t.context?t.context:null,n=void 0===t.depth||t.depth,r=void 0===t.stencil||t.stencil,s=void 0!==t.antialias&&t.antialias,a=void 0===t.premultipliedAlpha||t.premultipliedAlpha,o=void 0!==t.preserveDrawingBuffer&&t.preserveDrawingBuffer,l=void 0!==t.powerPreference?t.powerPreference:"default",c=void 0!==t.failIfMajorPerformanceCaveat&&t.failIfMajorPerformanceCaveat;let h;h=null!==i?i.getContextAttributes().alpha:void 0!==t.alpha&&t.alpha;let u=null,d=null;const p=[],m=[];this.domElement=e,this.debug={checkShaderErrors:!0},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this.outputEncoding=at,this.physicallyCorrectLights=!1,this.toneMapping=0,this.toneMappingExposure=1,Object.defineProperties(this,{gammaFactor:{get:function(){return console.warn("THREE.WebGLRenderer: .gammaFactor has been removed."),2},set:function(){console.warn("THREE.WebGLRenderer: .gammaFactor has been removed.")}}});const f=this;let g=!1,y=0,_=0,w=null,T=-1,A=null;const E=new Zt,C=new Zt;let L=null,R=e.width,P=e.height,I=1,D=null,N=null;const z=new Zt(0,0,R,P),O=new Zt(0,0,R,P);let F=!1;const B=new fn;let U=!1,k=!1,G=null;const V=new Ie,H=new Et,W=new ee,j={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};function q(){return null===w?I:1}let X,J,Y,Z,K,Q,$,tt,et,it,nt,rt,st,ot,lt,ct,ht,ut,dt,pt,mt,ft,gt,vt=i;function xt(t,i){for(let n=0;n0&&function(t,e,i){const n=J.isWebGL2;null===G&&(G=new Kt(1,1,{generateMipmaps:!0,type:X.has("EXT_color_buffer_half_float")?b:x,minFilter:v,samples:n&&!0===s?4:0}));f.getDrawingBufferSize(H),n?G.setSize(H.x,H.y):G.setSize(Tt(H.x),Tt(H.y));const r=f.getRenderTarget();f.setRenderTarget(G),f.clear();const a=f.toneMapping;f.toneMapping=0,Nt(t,e,i),f.toneMapping=a,Q.updateMultisampleRenderTarget(G),Q.updateRenderTargetMipmap(G),f.setRenderTarget(r)}(r,e,i),n&&Y.viewport(E.copy(n)),r.length>0&&Nt(r,e,i),a.length>0&&Nt(a,e,i),o.length>0&&Nt(o,e,i),Y.buffers.depth.setTest(!0),Y.buffers.depth.setMask(!0),Y.buffers.color.setMask(!0),Y.setPolygonOffset(!1)}function Nt(t,e,i){const n=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?m[m.length-1]:null,p.pop(),u=p.length>0?p[p.length-1]:null},this.getActiveCubeFace=function(){return y},this.getActiveMipmapLevel=function(){return _},this.getRenderTarget=function(){return w},this.setRenderTargetTextures=function(t,e,i){K.get(t.texture).__webglTexture=e,K.get(t.depthTexture).__webglTexture=i;const n=K.get(t);n.__hasExternalTextures=!0,n.__hasExternalTextures&&(n.__autoAllocateDepthBuffer=void 0===i,n.__autoAllocateDepthBuffer||!0===X.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),n.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(t,e){const i=K.get(t);i.__webglFramebuffer=e,i.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,i=0){w=t,y=e,_=i;let n=!0;if(t){const e=K.get(t);void 0!==e.__useDefaultFramebuffer?(Y.bindFramebuffer(36160,null),n=!1):void 0===e.__webglFramebuffer?Q.setupRenderTarget(t):e.__hasExternalTextures&&Q.rebindTextures(t,K.get(t.texture).__webglTexture,K.get(t.depthTexture).__webglTexture)}let r=null,s=!1,a=!1;if(t){const i=t.texture;(i.isData3DTexture||i.isDataArrayTexture)&&(a=!0);const n=K.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=n[e],s=!0):r=J.isWebGL2&&t.samples>0&&!1===Q.useMultisampledRTT(t)?K.get(t).__webglMultisampledFramebuffer:n,E.copy(t.viewport),C.copy(t.scissor),L=t.scissorTest}else E.copy(z).multiplyScalar(I).floor(),C.copy(O).multiplyScalar(I).floor(),L=F;if(Y.bindFramebuffer(36160,r)&&J.drawBuffers&&n&&Y.drawBuffers(t,r),Y.viewport(E),Y.scissor(C),Y.setScissorTest(L),s){const n=K.get(t.texture);vt.framebufferTexture2D(36160,36064,34069+e,n.__webglTexture,i)}else if(a){const n=K.get(t.texture),r=e||0;vt.framebufferTextureLayer(36160,36064,n.__webglTexture,i||0,r)}T=-1},this.readRenderTargetPixels=function(t,e,i,n,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=K.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){Y.bindFramebuffer(36160,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==S&&ft.convert(o)!==vt.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===b&&(X.has("EXT_color_buffer_half_float")||J.isWebGL2&&X.has("EXT_color_buffer_float"));if(!(l===x||ft.convert(l)===vt.getParameter(35738)||l===M&&(J.isWebGL2||X.has("OES_texture_float")||X.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-n&&i>=0&&i<=t.height-r&&vt.readPixels(e,i,n,r,ft.convert(o),ft.convert(l),s)}finally{const t=null!==w?K.get(w).__webglFramebuffer:null;Y.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,i=0){const n=Math.pow(2,-i),r=Math.floor(e.image.width*n),s=Math.floor(e.image.height*n);Q.setTexture2D(e,0),vt.copyTexSubImage2D(3553,i,0,0,t.x,t.y,r,s),Y.unbindTexture()},this.copyTextureToTexture=function(t,e,i,n=0){const r=e.image.width,s=e.image.height,a=ft.convert(i.format),o=ft.convert(i.type);Q.setTexture2D(i,0),vt.pixelStorei(37440,i.flipY),vt.pixelStorei(37441,i.premultiplyAlpha),vt.pixelStorei(3317,i.unpackAlignment),e.isDataTexture?vt.texSubImage2D(3553,n,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?vt.compressedTexSubImage2D(3553,n,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):vt.texSubImage2D(3553,n,t.x,t.y,a,o,e.image),0===n&&i.generateMipmaps&&vt.generateMipmap(3553),Y.unbindTexture()},this.copyTextureToTexture3D=function(t,e,i,n,r=0){if(f.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=ft.convert(n.format),c=ft.convert(n.type);let h;if(n.isData3DTexture)Q.setTexture3D(n,0),h=32879;else{if(!n.isDataArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");Q.setTexture2DArray(n,0),h=35866}vt.pixelStorei(37440,n.flipY),vt.pixelStorei(37441,n.premultiplyAlpha),vt.pixelStorei(3317,n.unpackAlignment);const u=vt.getParameter(3314),d=vt.getParameter(32878),p=vt.getParameter(3316),m=vt.getParameter(3315),g=vt.getParameter(32877),v=i.isCompressedTexture?i.mipmaps[0]:i.image;vt.pixelStorei(3314,v.width),vt.pixelStorei(32878,v.height),vt.pixelStorei(3316,t.min.x),vt.pixelStorei(3315,t.min.y),vt.pixelStorei(32877,t.min.z),i.isDataTexture||i.isData3DTexture?vt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v.data):i.isCompressedTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),vt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,v.data)):vt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v),vt.pixelStorei(3314,u),vt.pixelStorei(32878,d),vt.pixelStorei(3316,p),vt.pixelStorei(3315,m),vt.pixelStorei(32877,g),0===r&&n.generateMipmaps&&vt.generateMipmap(h),Y.unbindTexture()},this.initTexture=function(t){Q.setTexture2D(t,0),Y.unbindTexture()},this.resetState=function(){y=0,_=0,w=null,Y.reset(),gt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}class Qs extends Ks{}Qs.prototype.isWebGL1Renderer=!0;class $s{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new Ht(t),this.density=e}clone(){return new $s(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}class ta{constructor(t,e=1,i=1e3){this.isFog=!0,this.name="",this.color=new Ht(t),this.near=e,this.far=i}clone(){return new ta(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}class ea extends ni{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.autoUpdate=t.autoUpdate,this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),e}}class ia{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=ut,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=yt()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,i){t*=this.stride,i*=e.stride;for(let n=0,r=this.stride;nt.far||e.push({distance:o,point:oa.clone(),uv:mi.getUV(oa,pa,ma,fa,ga,va,xa,new Et),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function _a(t,e,i,n,r,s){ha.subVectors(t,i).addScalar(.5).multiply(n),void 0!==r?(ua.x=s*ha.x-r*ha.y,ua.y=r*ha.x+s*ha.y):ua.copy(ha),t.copy(e),t.x+=ua.x,t.y+=ua.y,t.applyMatrix4(da)}const Ma=new ee,ba=new ee;class wa extends ni{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,i=e.length;t0){let i,n;for(i=1,n=e.length;i0){Ma.setFromMatrixPosition(this.matrixWorld);const i=t.ray.origin.distanceTo(Ma);this.getObjectForDistance(i).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Ma.setFromMatrixPosition(t.matrixWorld),ba.setFromMatrixPosition(this.matrixWorld);const i=Ma.distanceTo(ba)/t.zoom;let n,r;for(e[0].object.visible=!0,n=1,r=e.length;n=e[n].distance;n++)e[n-1].object.visible=!1,e[n].object.visible=!0;for(this._currentLevel=n-1;no)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);st.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}else{for(let i=Math.max(0,s.start),n=Math.min(m.count,s.start+s.count)-1;io)continue;u.applyMatrix4(this.matrixWorld);const n=t.ray.origin.distanceTo(u);nt.far||e.push({distance:n,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length>0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:i,index:e,face:null,object:a})}}class so extends Yt{constructor(t,e,i,n,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,n,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:i},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class ao{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const i=this.getUtoTmapping(t);return this.getPoint(i,e)}getPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPoint(i/t));return e}getSpacedPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPointAt(i/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let i,n=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)i=this.getPoint(s/t),r+=i.distanceTo(n),e.push(r),n=i;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const i=this.getLengths();let n=0;const r=i.length;let s;s=e||t*i[r-1];let a,o=0,l=r-1;for(;o<=l;)if(n=Math.floor(o+(l-o)/2),a=i[n]-s,a<0)o=n+1;else{if(!(a>0)){l=n;break}l=n-1}if(n=l,i[n]===s)return n/(r-1);const c=i[n];return(n+(s-c)/(i[n+1]-c))/(r-1)}getTangent(t,e){const i=1e-4;let n=t-i,r=t+i;n<0&&(n=0),r>1&&(r=1);const s=this.getPoint(n),a=this.getPoint(r),o=e||(s.isVector2?new Et:new ee);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const i=this.getUtoTmapping(t);return this.getTangent(i,e)}computeFrenetFrames(t,e){const i=new ee,n=[],r=[],s=[],a=new ee,o=new Ie;for(let e=0;e<=t;e++){const i=e/t;n[e]=this.getTangentAt(i,new ee)}r[0]=new ee,s[0]=new ee;let l=Number.MAX_VALUE;const c=Math.abs(n[0].x),h=Math.abs(n[0].y),u=Math.abs(n[0].z);c<=l&&(l=c,i.set(1,0,0)),h<=l&&(l=h,i.set(0,1,0)),u<=l&&i.set(0,0,1),a.crossVectors(n[0],i).normalize(),r[0].crossVectors(n[0],a),s[0].crossVectors(n[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(n[e-1],n[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(_t(n[e-1].dot(n[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(n[e],r[e])}if(!0===e){let e=Math.acos(_t(r[0].dot(r[t]),-1,1));e/=t,n[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let i=1;i<=t;i++)r[i].applyMatrix4(o.makeRotationAxis(n[i],e*i)),s[i].crossVectors(n[i],r[i])}return{tangents:n,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class oo extends ao{constructor(t=0,e=0,i=1,n=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=i,this.yRadius=n,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const i=e||new Et,n=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)n;)r-=n;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=n[(l-1)%r]:(ho.subVectors(n[0],n[1]).add(n[0]),a=ho);const h=n[l%r],u=n[(l+1)%r];if(this.closed||l+2n.length-2?n.length-1:s+1],h=n[s>n.length-3?n.length-1:s+2];return i.set(go(a,o.x,l.x,c.x,h.x),go(a,o.y,l.y,c.y,h.y)),i}copy(t){super.copy(t),this.points=[];for(let e=0,i=t.points.length;e=i){const t=n[r]-i,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let i=0,n=this.curves.length;i1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,i=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class Lo extends Pi{constructor(t=[new Et(0,.5),new Et(.5,0),new Et(0,-.5)],e=12,i=0,n=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:i,phiLength:n},e=Math.floor(e),n=_t(n,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new ee,u=new Et,d=new ee,p=new ee,m=new ee;let f=0,g=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=i+r*c*n,p=Math.sin(d),m=Math.cos(d);for(let i=0;i<=t.length-1;i++){h.x=t[i].x*p,h.y=t[i].y,h.z=t[i].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=i/(t.length-1),a.push(u.x,u.y);const n=o[3*i+0]*p,c=o[3*i+1],d=o[3*i+0]*m;l.push(n,c,d)}}for(let i=0;i0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new wi(h,3)),this.setAttribute("normal",new wi(u,3)),this.setAttribute("uv",new wi(d,2))}static fromJSON(t){return new Io(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Do extends Io{constructor(t=1,e=1,i=8,n=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,i,n,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:i,heightSegments:n,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new Do(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class No extends Pi{constructor(t=[],e=[],i=1,n=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:i,detail:n};const r=[],s=[];function a(t,e,i,n){const r=n+1,s=[];for(let n=0;n<=r;n++){s[n]=[];const a=t.clone().lerp(i,n/r),o=e.clone().lerp(i,n/r),l=r-n;for(let t=0;t<=l;t++)s[n][t]=0===t&&n===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),i<.2&&(s[t+2]+=1),n<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new wi(r,3)),this.setAttribute("normal",new wi(r.slice(),3)),this.setAttribute("uv",new wi(s,2)),0===n?this.computeVertexNormals():this.normalizeNormals()}static fromJSON(t){return new No(t.vertices,t.indices,t.radius,t.details)}}class zo extends No{constructor(t=1,e=0){const i=(1+Math.sqrt(5))/2,n=1/i;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-n,-i,0,-n,i,0,n,-i,0,n,i,-n,-i,0,-n,i,0,n,-i,0,n,i,0,-i,0,-n,i,0,-n,-i,0,n,i,0,n],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new zo(t.radius,t.detail)}}const Oo=new ee,Fo=new ee,Bo=new ee,Uo=new mi;class ko extends Pi{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const i=4,n=Math.pow(10,i),r=Math.cos(vt*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t80*i){o=c=t[0],l=h=t[1];for(let e=i;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?1/p:0}return jo(s,a,i,o,l,p),a};function Ho(t,e,i,n,r){let s,a;if(r===function(t,e,i,n){let r=0;for(let s=e,a=i-n;s0)for(s=e;s=e;s-=n)a=hl(s,t[s],t[s+1],a);return a&&rl(a,a.next)&&(ul(a),a=a.next),a}function Wo(t,e){if(!t)return t;e||(e=t);let i,n=t;do{if(i=!1,n.steiner||!rl(n,n.next)&&0!==nl(n.prev,n,n.next))n=n.next;else{if(ul(n),n=e=n.prev,n===n.next)break;i=!0}}while(i||n!==e);return e}function jo(t,e,i,n,r,s,a){if(!t)return;!a&&s&&function(t,e,i,n){let r=t;do{null===r.z&&(r.z=$o(r.x,r.y,e,i,n)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,i,n,r,s,a,o,l,c=1;do{for(i=t,t=null,s=null,a=0;i;){for(a++,n=i,o=0,e=0;e0||l>0&&n;)0!==o&&(0===l||!n||i.z<=n.z)?(r=i,i=i.nextZ,o--):(r=n,n=n.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;i=n}s.nextZ=null,c*=2}while(a>1)}(r)}(t,n,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Xo(t,n,r,s):qo(t))e.push(o.i/i),e.push(t.i/i),e.push(l.i/i),ul(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?jo(t=Jo(Wo(t),e,i),e,i,n,r,s,2):2===a&&Yo(t,e,i,n,r,s):jo(Wo(t),e,i,n,r,s,1);break}}function qo(t){const e=t.prev,i=t,n=t.next;if(nl(e,i,n)>=0)return!1;let r=t.next.next;for(;r!==t.prev;){if(el(e.x,e.y,i.x,i.y,n.x,n.y,r.x,r.y)&&nl(r.prev,r,r.next)>=0)return!1;r=r.next}return!0}function Xo(t,e,i,n){const r=t.prev,s=t,a=t.next;if(nl(r,s,a)>=0)return!1;const o=r.xs.x?r.x>a.x?r.x:a.x:s.x>a.x?s.x:a.x,h=r.y>s.y?r.y>a.y?r.y:a.y:s.y>a.y?s.y:a.y,u=$o(o,l,e,i,n),d=$o(c,h,e,i,n);let p=t.prevZ,m=t.nextZ;for(;p&&p.z>=u&&m&&m.z<=d;){if(p!==t.prev&&p!==t.next&&el(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&nl(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,m!==t.prev&&m!==t.next&&el(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&nl(m.prev,m,m.next)>=0)return!1;m=m.nextZ}for(;p&&p.z>=u;){if(p!==t.prev&&p!==t.next&&el(r.x,r.y,s.x,s.y,a.x,a.y,p.x,p.y)&&nl(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;m&&m.z<=d;){if(m!==t.prev&&m!==t.next&&el(r.x,r.y,s.x,s.y,a.x,a.y,m.x,m.y)&&nl(m.prev,m,m.next)>=0)return!1;m=m.nextZ}return!0}function Jo(t,e,i){let n=t;do{const r=n.prev,s=n.next.next;!rl(r,s)&&sl(r,n,n.next,s)&&ll(r,s)&&ll(s,r)&&(e.push(r.i/i),e.push(n.i/i),e.push(s.i/i),ul(n),ul(n.next),n=t=s),n=n.next}while(n!==t);return Wo(n)}function Yo(t,e,i,n,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&il(a,t)){let o=cl(a,t);return a=Wo(a,a.next),o=Wo(o,o.next),jo(a,e,i,n,r,s),void jo(o,e,i,n,r,s)}t=t.next}a=a.next}while(a!==t)}function Zo(t,e){return t.x-e.x}function Ko(t,e){if(e=function(t,e){let i=e;const n=t.x,r=t.y;let s,a=-1/0;do{if(r<=i.y&&r>=i.next.y&&i.next.y!==i.y){const t=i.x+(r-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=n&&t>a){if(a=t,t===n){if(r===i.y)return i;if(r===i.next.y)return i.next}s=i.x=i.x&&i.x>=l&&n!==i.x&&el(rs.x||i.x===s.x&&Qo(s,i)))&&(s=i,u=h)),i=i.next}while(i!==o);return s}(t,e),e){const i=cl(e,t);Wo(e,e.next),Wo(i,i.next)}}function Qo(t,e){return nl(t.prev,t,e.prev)<0&&nl(e.next,t,t.next)<0}function $o(t,e,i,n,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-i)*r)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-n)*r)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function tl(t){let e=t,i=t;do{(e.x=0&&(t-a)*(n-o)-(i-a)*(e-o)>=0&&(i-a)*(s-o)-(r-a)*(n-o)>=0}function il(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let i=t;do{if(i.i!==t.i&&i.next.i!==t.i&&i.i!==e.i&&i.next.i!==e.i&&sl(i,i.next,t,e))return!0;i=i.next}while(i!==t);return!1}(t,e)&&(ll(t,e)&&ll(e,t)&&function(t,e){let i=t,n=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{i.y>s!=i.next.y>s&&i.next.y!==i.y&&r<(i.next.x-i.x)*(s-i.y)/(i.next.y-i.y)+i.x&&(n=!n),i=i.next}while(i!==t);return n}(t,e)&&(nl(t.prev,t,e.prev)||nl(t,e.prev,e))||rl(t,e)&&nl(t.prev,t,t.next)>0&&nl(e.prev,e,e.next)>0)}function nl(t,e,i){return(e.y-t.y)*(i.x-e.x)-(e.x-t.x)*(i.y-e.y)}function rl(t,e){return t.x===e.x&&t.y===e.y}function sl(t,e,i,n){const r=ol(nl(t,e,i)),s=ol(nl(t,e,n)),a=ol(nl(i,n,t)),o=ol(nl(i,n,e));return r!==s&&a!==o||(!(0!==r||!al(t,i,e))||(!(0!==s||!al(t,n,e))||(!(0!==a||!al(i,t,n))||!(0!==o||!al(i,e,n)))))}function al(t,e,i){return e.x<=Math.max(t.x,i.x)&&e.x>=Math.min(t.x,i.x)&&e.y<=Math.max(t.y,i.y)&&e.y>=Math.min(t.y,i.y)}function ol(t){return t>0?1:t<0?-1:0}function ll(t,e){return nl(t.prev,t,t.next)<0?nl(t,e,t.next)>=0&&nl(t,t.prev,e)>=0:nl(t,e,t.prev)<0||nl(t,t.next,e)<0}function cl(t,e){const i=new dl(t.i,t.x,t.y),n=new dl(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,i.next=r,r.prev=i,n.next=i,i.prev=n,s.next=n,n.prev=s,n}function hl(t,e,i,n){const r=new dl(t,e,i);return n?(r.next=n.next,r.prev=n,n.next.prev=r,n.next=r):(r.prev=r,r.next=r),r}function ul(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function dl(t,e,i){this.i=t,this.x=e,this.y=i,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}class pl{static area(t){const e=t.length;let i=0;for(let n=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function fl(t,e){for(let i=0;iNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((i.x-c/d-p)*c-(i.y+l/d-m)*l)/(a*c-o*l);n=p+a*f-t.x,r=m+o*f-t.y;const g=n*n+r*r;if(g<=2)return new Et(n,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(n=-o,r=a,s=Math.sqrt(h)):(n=a,r=o,s=Math.sqrt(h/2))}return new Et(n/s,r/s)}const P=[];for(let t=0,e=A.length,i=e-1,n=t+1;t=0;t--){const e=t/p,i=h*Math.cos(e*Math.PI/2),n=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=A.length;t=0;){const n=i;let r=i-1;r<0&&(r=t.length-1);for(let t=0,i=o+2*p;t0)&&d.push(e,r,l),(t!==i-1||o0!=t>0&&this.version++,this._sheen=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class Nl extends gi{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Ht(16777215),this.specular=new Ht(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Ht(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Et(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class zl extends gi{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Ht(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Ht(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Et(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class Ol extends gi{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Et(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class Fl extends gi{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Ht(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Ht(0),this.emissiveIntensity=1,this.emissiveMap=null,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class Bl extends gi{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Ht(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Et(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Ul extends Ga{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}const kl={ShadowMaterial:Rl,SpriteMaterial:sa,RawShaderMaterial:Pl,ShaderMaterial:en,PointsMaterial:Qa,MeshPhysicalMaterial:Dl,MeshStandardMaterial:Il,MeshPhongMaterial:Nl,MeshToonMaterial:zl,MeshNormalMaterial:Ol,MeshLambertMaterial:Fl,MeshDepthMaterial:Bs,MeshDistanceMaterial:Us,MeshBasicMaterial:vi,MeshMatcapMaterial:Bl,LineDashedMaterial:Ul,LineBasicMaterial:Ga,Material:gi};gi.fromType=function(t){return new kl[t]};const Gl={arraySlice:function(t,e,i){return Gl.isTypedArray(t)?new t.constructor(t.subarray(e,void 0!==i?i:t.length)):t.slice(e,i)},convertArray:function(t,e,i){return!t||!i&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)},isTypedArray:function(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)},getKeyframeOrder:function(t){const e=t.length,i=new Array(e);for(let t=0;t!==e;++t)i[t]=t;return i.sort((function(e,i){return t[e]-t[i]})),i},sortedArray:function(t,e,i){const n=t.length,r=new t.constructor(n);for(let s=0,a=0;a!==n;++s){const n=i[s]*e;for(let i=0;i!==e;++i)r[a++]=t[n+i]}return r},flattenJSON:function(t,e,i,n){let r=1,s=t[0];for(;void 0!==s&&void 0===s[n];)s=t[r++];if(void 0===s)return;let a=s[n];if(void 0!==a)if(Array.isArray(a))do{a=s[n],void 0!==a&&(e.push(s.time),i.push.apply(i,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[n],void 0!==a&&(e.push(s.time),a.toArray(i,i.length)),s=t[r++]}while(void 0!==s);else do{a=s[n],void 0!==a&&(e.push(s.time),i.push(a)),s=t[r++]}while(void 0!==s)},subclip:function(t,e,i,n,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=n)){l.push(e.times[t]);for(let i=0;is.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=n.times[u]){const t=u*l+o,e=t+l-o;d=Gl.arraySlice(n.values,t,e)}else{const t=n.createInterpolant(),e=o,i=l-o;t.evaluate(s),d=Gl.arraySlice(t.resultBuffer,e,i)}if("quaternion"===r){(new te).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=i,i=0}}for(;i>>1;te;)--s;if(++s,0!==r||s!==n){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=Gl.arraySlice(i,r,s),this.values=Gl.arraySlice(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const i=this.times,n=this.values,r=i.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const n=i[e];if("number"==typeof n&&isNaN(n)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,n),t=!1;break}if(null!==s&&s>n){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,n,s),t=!1;break}s=n}if(void 0!==n&&Gl.isTypedArray(n))for(let e=0,i=n.length;e!==i;++e){const i=n[e];if(isNaN(i)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,i),t=!1;break}}return t}optimize(){const t=Gl.arraySlice(this.times),e=Gl.arraySlice(this.values),i=this.getValueSize(),n=this.getInterpolation()===tt,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*i,n=s*i,a=0;a!==i;++a)e[n+a]=e[t+a];++s}return s!==t.length?(this.times=Gl.arraySlice(t,0,s),this.values=Gl.arraySlice(e,0,s*i)):(this.times=t,this.values=e),this}clone(){const t=Gl.arraySlice(this.times,0),e=Gl.arraySlice(this.values,0),i=new(0,this.constructor)(this.name,t,e);return i.createInterpolant=this.createInterpolant,i}}ql.prototype.TimeBufferType=Float32Array,ql.prototype.ValueBufferType=Float32Array,ql.prototype.DefaultInterpolation=$;class Xl extends ql{}Xl.prototype.ValueTypeName="bool",Xl.prototype.ValueBufferType=Array,Xl.prototype.DefaultInterpolation=Q,Xl.prototype.InterpolantFactoryMethodLinear=void 0,Xl.prototype.InterpolantFactoryMethodSmooth=void 0;class Jl extends ql{}Jl.prototype.ValueTypeName="color";class Yl extends ql{}Yl.prototype.ValueTypeName="number";class Zl extends Vl{constructor(t,e,i,n){super(t,e,i,n)}interpolate_(t,e,i,n){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(i-e)/(n-e);let l=t*a;for(let t=l+a;l!==t;l+=4)te.slerpFlat(r,0,s,l-a,s,l,o);return r}}class Kl extends ql{InterpolantFactoryMethodLinear(t){return new Zl(this.times,this.values,this.getValueSize(),t)}}Kl.prototype.ValueTypeName="quaternion",Kl.prototype.DefaultInterpolation=$,Kl.prototype.InterpolantFactoryMethodSmooth=void 0;class Ql extends ql{}Ql.prototype.ValueTypeName="string",Ql.prototype.ValueBufferType=Array,Ql.prototype.DefaultInterpolation=Q,Ql.prototype.InterpolantFactoryMethodLinear=void 0,Ql.prototype.InterpolantFactoryMethodSmooth=void 0;class $l extends ql{}$l.prototype.ValueTypeName="vector";class tc{constructor(t,e=-1,i,n=2500){this.name=t,this.tracks=i,this.duration=e,this.blendMode=n,this.uuid=yt(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],i=t.tracks,n=1/(t.fps||1);for(let t=0,r=i.length;t!==r;++t)e.push(ec(i[t]).scale(n));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],i=t.tracks,n={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,n=i.length;t!==n;++t)e.push(ql.toJSON(i[t]));return n}static CreateFromMorphTargetSequence(t,e,i,n){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=n[t];e||(n[t]=e=[]),e.push(i)}}const s=[];for(const t in n)s.push(this.CreateFromMorphTargetSequence(t,n[t],e,i));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const i=function(t,e,i,n,r){if(0!==i.length){const s=[],a=[];Gl.flattenJSON(i,s,a,n),0!==s.length&&r.push(new t(e,s,a))}},n=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==ac[t])return void ac[t].push({onLoad:e,onProgress:i,onError:n});ac[t]=[],ac[t].push({onLoad:e,onProgress:i,onError:n});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),a=this.mimeType,o=this.responseType;fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const i=ac[t],n=e.body.getReader(),r=e.headers.get("Content-Length"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){n.read().then((({done:n,value:r})=>{if(n)t.close();else{o+=r.byteLength;const n=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=i.length;t{switch(o){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,a)));case"json":return t.json();default:if(void 0===a)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(a),i=e&&e[1]?e[1].toLowerCase():void 0,n=new TextDecoder(i);return t.arrayBuffer().then((t=>n.decode(t)))}}})).then((e=>{ic.add(t,e);const i=ac[t];delete ac[t];for(let t=0,n=i.length;t{const i=ac[t];if(void 0===i)throw this.manager.itemError(t),e;delete ac[t];for(let t=0,n=i.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class lc extends sc{constructor(t){super(t)}load(t,e,i,n){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=ic.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=It("img");function o(){c(),ic.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),n&&n(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.slice(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class cc extends ni{constructor(t,e=1){super(),this.isLight=!0,this.type="Light",this.color=new Ht(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,void 0!==this.groundColor&&(e.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(e.object.distance=this.distance),void 0!==this.angle&&(e.object.angle=this.angle),void 0!==this.decay&&(e.object.decay=this.decay),void 0!==this.penumbra&&(e.object.penumbra=this.penumbra),void 0!==this.shadow&&(e.object.shadow=this.shadow.toJSON()),e}}class hc extends cc{constructor(t,e,i){super(t,i),this.isHemisphereLight=!0,this.type="HemisphereLight",this.position.copy(ni.DefaultUp),this.updateMatrix(),this.groundColor=new Ht(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const uc=new Ie,dc=new ee,pc=new ee;class mc{constructor(t){this.camera=t,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new Et(512,512),this.map=null,this.mapPass=null,this.matrix=new Ie,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new fn,this._frameExtents=new Et(1,1),this._viewportCount=1,this._viewports=[new Zt(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,i=this.matrix;dc.setFromMatrixPosition(t.matrixWorld),e.position.copy(dc),pc.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(pc),e.updateMatrixWorld(),uc.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(uc),i.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),i.multiply(e.projectionMatrix),i.multiply(e.matrixWorldInverse)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.bias=t.bias,this.radius=t.radius,this.mapSize.copy(t.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const t={};return 0!==this.bias&&(t.bias=this.bias),0!==this.normalBias&&(t.normalBias=this.normalBias),1!==this.radius&&(t.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}class fc extends mc{constructor(){super(new rn(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(t){const e=this.camera,i=2*xt*t.angle*this.focus,n=this.mapSize.width/this.mapSize.height,r=t.distance||e.far;i===e.fov&&n===e.aspect&&r===e.far||(e.fov=i,e.aspect=n,e.far=r,e.updateProjectionMatrix()),super.updateMatrices(t)}copy(t){return super.copy(t),this.focus=t.focus,this}}class gc extends cc{constructor(t,e,i=0,n=Math.PI/3,r=0,s=1){super(t,e),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(ni.DefaultUp),this.updateMatrix(),this.target=new ni,this.distance=i,this.angle=n,this.penumbra=r,this.decay=s,this.shadow=new fc}get power(){return this.intensity*Math.PI}set power(t){this.intensity=t/Math.PI}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.angle=t.angle,this.penumbra=t.penumbra,this.decay=t.decay,this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}const vc=new Ie,xc=new ee,yc=new ee;class _c extends mc{constructor(){super(new rn(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new Et(4,2),this._viewportCount=6,this._viewports=[new Zt(2,1,1,1),new Zt(0,1,1,1),new Zt(3,1,1,1),new Zt(1,1,1,1),new Zt(3,0,1,1),new Zt(1,0,1,1)],this._cubeDirections=[new ee(1,0,0),new ee(-1,0,0),new ee(0,0,1),new ee(0,0,-1),new ee(0,1,0),new ee(0,-1,0)],this._cubeUps=[new ee(0,1,0),new ee(0,1,0),new ee(0,1,0),new ee(0,1,0),new ee(0,0,1),new ee(0,0,-1)]}updateMatrices(t,e=0){const i=this.camera,n=this.matrix,r=t.distance||i.far;r!==i.far&&(i.far=r,i.updateProjectionMatrix()),xc.setFromMatrixPosition(t.matrixWorld),i.position.copy(xc),yc.copy(i.position),yc.add(this._cubeDirections[e]),i.up.copy(this._cubeUps[e]),i.lookAt(yc),i.updateMatrixWorld(),n.makeTranslation(-xc.x,-xc.y,-xc.z),vc.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),this._frustum.setFromProjectionMatrix(vc)}}class Mc extends cc{constructor(t,e,i=0,n=1){super(t,e),this.isPointLight=!0,this.type="PointLight",this.distance=i,this.decay=n,this.shadow=new _c}get power(){return 4*this.intensity*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class bc extends mc{constructor(){super(new Cn(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class wc extends cc{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(ni.DefaultUp),this.updateMatrix(),this.target=new ni,this.shadow=new bc}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class Sc extends cc{constructor(t,e){super(t,e),this.isAmbientLight=!0,this.type="AmbientLight"}}class Tc extends cc{constructor(t,e,i=10,n=10){super(t,e),this.isRectAreaLight=!0,this.type="RectAreaLight",this.width=i,this.height=n}get power(){return this.intensity*this.width*this.height*Math.PI}set power(t){this.intensity=t/(this.width*this.height*Math.PI)}copy(t){return super.copy(t),this.width=t.width,this.height=t.height,this}toJSON(t){const e=super.toJSON(t);return e.object.width=this.width,e.object.height=this.height,e}}class Ac{constructor(){this.isSphericalHarmonics3=!0,this.coefficients=[];for(let t=0;t<9;t++)this.coefficients.push(new ee)}set(t){for(let e=0;e<9;e++)this.coefficients[e].copy(t[e]);return this}zero(){for(let t=0;t<9;t++)this.coefficients[t].set(0,0,0);return this}getAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.282095),e.addScaledVector(s[1],.488603*n),e.addScaledVector(s[2],.488603*r),e.addScaledVector(s[3],.488603*i),e.addScaledVector(s[4],i*n*1.092548),e.addScaledVector(s[5],n*r*1.092548),e.addScaledVector(s[6],.315392*(3*r*r-1)),e.addScaledVector(s[7],i*r*1.092548),e.addScaledVector(s[8],.546274*(i*i-n*n)),e}getIrradianceAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.886227),e.addScaledVector(s[1],1.023328*n),e.addScaledVector(s[2],1.023328*r),e.addScaledVector(s[3],1.023328*i),e.addScaledVector(s[4],.858086*i*n),e.addScaledVector(s[5],.858086*n*r),e.addScaledVector(s[6],.743125*r*r-.247708),e.addScaledVector(s[7],.858086*i*r),e.addScaledVector(s[8],.429043*(i*i-n*n)),e}add(t){for(let e=0;e<9;e++)this.coefficients[e].add(t.coefficients[e]);return this}addScaledSH(t,e){for(let i=0;i<9;i++)this.coefficients[i].addScaledVector(t.coefficients[i],e);return this}scale(t){for(let e=0;e<9;e++)this.coefficients[e].multiplyScalar(t);return this}lerp(t,e){for(let i=0;i<9;i++)this.coefficients[i].lerp(t.coefficients[i],e);return this}equals(t){for(let e=0;e<9;e++)if(!this.coefficients[e].equals(t.coefficients[e]))return!1;return!0}copy(t){return this.set(t.coefficients)}clone(){return(new this.constructor).copy(this)}fromArray(t,e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].fromArray(t,e+3*n);return this}toArray(t=[],e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].toArray(t,e+3*n);return t}static getBasisAt(t,e){const i=t.x,n=t.y,r=t.z;e[0]=.282095,e[1]=.488603*n,e[2]=.488603*r,e[3]=.488603*i,e[4]=1.092548*i*n,e[5]=1.092548*n*r,e[6]=.315392*(3*r*r-1),e[7]=1.092548*i*r,e[8]=.546274*(i*i-n*n)}}class Ec extends cc{constructor(t=new Ac,e=1){super(void 0,e),this.isLightProbe=!0,this.sh=t}copy(t){return super.copy(t),this.sh.copy(t.sh),this}fromJSON(t){return this.intensity=t.intensity,this.sh.fromArray(t.sh),this}toJSON(t){const e=super.toJSON(t);return e.object.sh=this.sh.toArray(),e}}class Cc extends sc{constructor(t){super(t),this.textures={}}load(t,e,i,n){const r=this,s=new oc(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=this.textures;function i(t){return void 0===e[t]&&console.warn("THREE.MaterialLoader: Undefined texture",t),e[t]}const n=gi.fromType(t.type);if(void 0!==t.uuid&&(n.uuid=t.uuid),void 0!==t.name&&(n.name=t.name),void 0!==t.color&&void 0!==n.color&&n.color.setHex(t.color),void 0!==t.roughness&&(n.roughness=t.roughness),void 0!==t.metalness&&(n.metalness=t.metalness),void 0!==t.sheen&&(n.sheen=t.sheen),void 0!==t.sheenColor&&(n.sheenColor=(new Ht).setHex(t.sheenColor)),void 0!==t.sheenRoughness&&(n.sheenRoughness=t.sheenRoughness),void 0!==t.emissive&&void 0!==n.emissive&&n.emissive.setHex(t.emissive),void 0!==t.specular&&void 0!==n.specular&&n.specular.setHex(t.specular),void 0!==t.specularIntensity&&(n.specularIntensity=t.specularIntensity),void 0!==t.specularColor&&void 0!==n.specularColor&&n.specularColor.setHex(t.specularColor),void 0!==t.shininess&&(n.shininess=t.shininess),void 0!==t.clearcoat&&(n.clearcoat=t.clearcoat),void 0!==t.clearcoatRoughness&&(n.clearcoatRoughness=t.clearcoatRoughness),void 0!==t.iridescence&&(n.iridescence=t.iridescence),void 0!==t.iridescenceIOR&&(n.iridescenceIOR=t.iridescenceIOR),void 0!==t.iridescenceThicknessRange&&(n.iridescenceThicknessRange=t.iridescenceThicknessRange),void 0!==t.transmission&&(n.transmission=t.transmission),void 0!==t.thickness&&(n.thickness=t.thickness),void 0!==t.attenuationDistance&&(n.attenuationDistance=t.attenuationDistance),void 0!==t.attenuationColor&&void 0!==n.attenuationColor&&n.attenuationColor.setHex(t.attenuationColor),void 0!==t.fog&&(n.fog=t.fog),void 0!==t.flatShading&&(n.flatShading=t.flatShading),void 0!==t.blending&&(n.blending=t.blending),void 0!==t.combine&&(n.combine=t.combine),void 0!==t.side&&(n.side=t.side),void 0!==t.shadowSide&&(n.shadowSide=t.shadowSide),void 0!==t.opacity&&(n.opacity=t.opacity),void 0!==t.transparent&&(n.transparent=t.transparent),void 0!==t.alphaTest&&(n.alphaTest=t.alphaTest),void 0!==t.depthTest&&(n.depthTest=t.depthTest),void 0!==t.depthWrite&&(n.depthWrite=t.depthWrite),void 0!==t.colorWrite&&(n.colorWrite=t.colorWrite),void 0!==t.stencilWrite&&(n.stencilWrite=t.stencilWrite),void 0!==t.stencilWriteMask&&(n.stencilWriteMask=t.stencilWriteMask),void 0!==t.stencilFunc&&(n.stencilFunc=t.stencilFunc),void 0!==t.stencilRef&&(n.stencilRef=t.stencilRef),void 0!==t.stencilFuncMask&&(n.stencilFuncMask=t.stencilFuncMask),void 0!==t.stencilFail&&(n.stencilFail=t.stencilFail),void 0!==t.stencilZFail&&(n.stencilZFail=t.stencilZFail),void 0!==t.stencilZPass&&(n.stencilZPass=t.stencilZPass),void 0!==t.wireframe&&(n.wireframe=t.wireframe),void 0!==t.wireframeLinewidth&&(n.wireframeLinewidth=t.wireframeLinewidth),void 0!==t.wireframeLinecap&&(n.wireframeLinecap=t.wireframeLinecap),void 0!==t.wireframeLinejoin&&(n.wireframeLinejoin=t.wireframeLinejoin),void 0!==t.rotation&&(n.rotation=t.rotation),1!==t.linewidth&&(n.linewidth=t.linewidth),void 0!==t.dashSize&&(n.dashSize=t.dashSize),void 0!==t.gapSize&&(n.gapSize=t.gapSize),void 0!==t.scale&&(n.scale=t.scale),void 0!==t.polygonOffset&&(n.polygonOffset=t.polygonOffset),void 0!==t.polygonOffsetFactor&&(n.polygonOffsetFactor=t.polygonOffsetFactor),void 0!==t.polygonOffsetUnits&&(n.polygonOffsetUnits=t.polygonOffsetUnits),void 0!==t.dithering&&(n.dithering=t.dithering),void 0!==t.alphaToCoverage&&(n.alphaToCoverage=t.alphaToCoverage),void 0!==t.premultipliedAlpha&&(n.premultipliedAlpha=t.premultipliedAlpha),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.toneMapped&&(n.toneMapped=t.toneMapped),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.vertexColors&&("number"==typeof t.vertexColors?n.vertexColors=t.vertexColors>0:n.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(n.uniforms[e]={},r.type){case"t":n.uniforms[e].value=i(r.value);break;case"c":n.uniforms[e].value=(new Ht).setHex(r.value);break;case"v2":n.uniforms[e].value=(new Et).fromArray(r.value);break;case"v3":n.uniforms[e].value=(new ee).fromArray(r.value);break;case"v4":n.uniforms[e].value=(new Zt).fromArray(r.value);break;case"m3":n.uniforms[e].value=(new Ct).fromArray(r.value);break;case"m4":n.uniforms[e].value=(new Ie).fromArray(r.value);break;default:n.uniforms[e].value=r.value}}if(void 0!==t.defines&&(n.defines=t.defines),void 0!==t.vertexShader&&(n.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(n.fragmentShader=t.fragmentShader),void 0!==t.extensions)for(const e in t.extensions)n.extensions[e]=t.extensions[e];if(void 0!==t.shading&&(n.flatShading=1===t.shading),void 0!==t.size&&(n.size=t.size),void 0!==t.sizeAttenuation&&(n.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(n.map=i(t.map)),void 0!==t.matcap&&(n.matcap=i(t.matcap)),void 0!==t.alphaMap&&(n.alphaMap=i(t.alphaMap)),void 0!==t.bumpMap&&(n.bumpMap=i(t.bumpMap)),void 0!==t.bumpScale&&(n.bumpScale=t.bumpScale),void 0!==t.normalMap&&(n.normalMap=i(t.normalMap)),void 0!==t.normalMapType&&(n.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),n.normalScale=(new Et).fromArray(e)}return void 0!==t.displacementMap&&(n.displacementMap=i(t.displacementMap)),void 0!==t.displacementScale&&(n.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(n.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(n.roughnessMap=i(t.roughnessMap)),void 0!==t.metalnessMap&&(n.metalnessMap=i(t.metalnessMap)),void 0!==t.emissiveMap&&(n.emissiveMap=i(t.emissiveMap)),void 0!==t.emissiveIntensity&&(n.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(n.specularMap=i(t.specularMap)),void 0!==t.specularIntensityMap&&(n.specularIntensityMap=i(t.specularIntensityMap)),void 0!==t.specularColorMap&&(n.specularColorMap=i(t.specularColorMap)),void 0!==t.envMap&&(n.envMap=i(t.envMap)),void 0!==t.envMapIntensity&&(n.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(n.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(n.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(n.lightMap=i(t.lightMap)),void 0!==t.lightMapIntensity&&(n.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(n.aoMap=i(t.aoMap)),void 0!==t.aoMapIntensity&&(n.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(n.gradientMap=i(t.gradientMap)),void 0!==t.clearcoatMap&&(n.clearcoatMap=i(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(n.clearcoatRoughnessMap=i(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(n.clearcoatNormalMap=i(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(n.clearcoatNormalScale=(new Et).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(n.iridescenceMap=i(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(n.iridescenceThicknessMap=i(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(n.transmissionMap=i(t.transmissionMap)),void 0!==t.thicknessMap&&(n.thicknessMap=i(t.thicknessMap)),void 0!==t.sheenColorMap&&(n.sheenColorMap=i(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(n.sheenRoughnessMap=i(t.sheenRoughnessMap)),n}setTextures(t){return this.textures=t,this}}class Lc{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let i=0,n=t.length;i0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(i,n,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(i[t]!==i[t+e]){a.setValue(i,n);break}}saveOriginalState(){const t=this.binding,e=this.buffer,i=this.valueSize,n=i*this._origIndex;t.getValue(e,n);for(let t=i,r=n;t!==r;++t)e[t]=e[n+t%i];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let i=t;i=.5)for(let n=0;n!==r;++n)t[e+n]=t[i+n]}_slerp(t,e,i,n){te.slerpFlat(t,e,t,e,t,i,n)}_slerpAdditive(t,e,i,n,r){const s=this._workIndex*r;te.multiplyQuaternionsFlat(t,s,t,e,t,i),te.slerpFlat(t,e,t,e,t,s,n)}_lerp(t,e,i,n,r){const s=1-n;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[i+a]*n}}_lerpAdditive(t,e,i,n,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[i+s]*n}}}const Qc="\\[\\]\\.:\\/",$c=new RegExp("[\\[\\]\\.:\\/]","g"),th="[^\\[\\]\\.:\\/]",eh="[^"+Qc.replace("\\.","")+"]",ih=/((?:WC+[\/:])*)/.source.replace("WC",th),nh=/(WCOD+)?/.source.replace("WCOD",eh),rh=/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",th),sh=/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",th),ah=new RegExp("^"+ih+nh+rh+sh+"$"),oh=["material","materials","bones"];class lh{constructor(t,e,i){this.path=e,this.parsedPath=i||lh.parseTrackName(e),this.node=lh.findNode(t,this.parsedPath.nodeName)||t,this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,i){return t&&t.isAnimationObjectGroup?new lh.Composite(t,e,i):new lh(t,e,i)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace($c,"")}static parseTrackName(t){const e=ah.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const i={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},n=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==n&&-1!==n){const t=i.nodeName.substring(n+1);-1!==oh.indexOf(t)&&(i.nodeName=i.nodeName.substring(0,n),i.objectName=t)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return i}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const i=t.skeleton.getBoneByName(e);if(void 0!==i)return i}if(t.children){const i=function(t){for(let n=0;n0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===st)for(let i=0,n=t.length;i!==n;++i)t[i].evaluate(s),e[i].accumulateAdditive(a);else for(let i=0,r=t.length;i!==r;++i)t[i].evaluate(s),e[i].accumulate(n,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const i=this._weightInterpolant;if(null!==i){const n=i.evaluate(t)[0];e*=n,t>i.parameterPositions[1]&&(this.stopFading(),0===n&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const i=this._timeScaleInterpolant;if(null!==i){e*=i.evaluate(t)[0],t>i.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,i=this.loop;let n=this.time+t,r=this._loopCount;const s=2202===i;if(0===t)return-1===r?n:s&&1==(1&r)?e-n:n;if(2200===i){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(n>=e)n=e;else{if(!(n<0)){this.time=n;break t}n=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),n>=e||n<0){const i=Math.floor(n/e);n-=e*i,r+=Math.abs(i);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,n=t>0?e:0,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:i})}}else this.time=n;if(s&&1==(1&r))return e-n}return n}_setEndings(t,e,i){const n=this._interpolantSettings;i?(n.endingStart=it,n.endingEnd=it):(n.endingStart=t?this.zeroSlopeAtStart?it:et:nt,n.endingEnd=e?this.zeroSlopeAtEnd?it:et:nt)}_scheduleFading(t,e,i){const n=this._mixer,r=n.time;let s=this._weightInterpolant;null===s&&(s=n._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=i,this}}const hh=new Float32Array(1);class uh{constructor(t){"string"==typeof t&&(console.warn("THREE.Uniform: Type parameter is no longer needed."),t=arguments[1]),this.value=t}clone(){return new uh(void 0===this.value.clone?this.value:this.value.clone())}}function dh(t,e){return t.distance-e.distance}function ph(t,e,i,n){if(t.layers.test(e.layers)&&t.raycast(e,i),!0===n){const n=t.children;for(let t=0,r=n.length;t>-e-14,Bh[256|t]=1024>>-e-14|32768,Uh[t]=-e-1,Uh[256|t]=-e-1):e<=15?(Bh[t]=e+15<<10,Bh[256|t]=e+15<<10|32768,Uh[t]=13,Uh[256|t]=13):e<128?(Bh[t]=31744,Bh[256|t]=64512,Uh[t]=24,Uh[256|t]=24):(Bh[t]=31744,Bh[256|t]=64512,Uh[t]=13,Uh[256|t]=13)}const kh=new Uint32Array(2048),Gh=new Uint32Array(64),Vh=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,i=0;for(;0==(8388608&e);)e<<=1,i-=8388608;e&=-8388609,i+=947912704,kh[t]=e|i}for(let t=1024;t<2048;++t)kh[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)Gh[t]=t<<23;Gh[31]=1199570944,Gh[32]=2147483648;for(let t=33;t<63;++t)Gh[t]=2147483648+(t-32<<23);Gh[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(Vh[t]=1024);"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:e}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=e),t.ACESFilmicToneMapping=4,t.AddEquation=i,t.AddOperation=2,t.AdditiveAnimationBlendMode=st,t.AdditiveBlending=2,t.AlphaFormat=1021,t.AlwaysDepth=1,t.AlwaysStencilFunc=519,t.AmbientLight=Sc,t.AmbientLightProbe=class extends Ec{constructor(t,e=1){super(void 0,e),this.isAmbientLightProbe=!0;const i=(new Ht).set(t);this.sh.coefficients[0].set(i.r,i.g,i.b).multiplyScalar(2*Math.sqrt(Math.PI))}},t.AnimationClip=tc,t.AnimationLoader=class extends sc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=new oc(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=[];for(let i=0;i=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,i=this._nActiveActions,n=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==i;++a){e[a]._update(n,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;t=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=n;t!==e;++t){const e=i[t],n=e[s],r=e[l];e[l]=n,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,i=this._bindings,n=i.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=n;t!==e;++t){const e=i[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const i=this._bindingsIndicesByPath;let n=i[t];const r=this._bindings;if(void 0!==n)return r[n];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);n=r.length,i[t]=n,s.push(t),a.push(e),r.push(h);for(let i=c,n=o.length;i!==n;++i){const n=o[i];h[i]=new lh(n,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,i=e[t];if(void 0!==i){const n=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=i,s[i]=o,s.pop(),r[i]=r[a],r.pop(),n[i]=n[a],n.pop()}}},t.AnimationUtils=Gl,t.ArcCurve=lo,t.ArrayCamera=Ws,t.ArrowHelper=class extends ni{constructor(t=new ee(0,0,1),e=new ee(0,0,0),i=1,n=16776960,r=.2*i,s=.2*r){super(),this.type="ArrowHelper",void 0===Dh&&(Dh=new Pi,Dh.setAttribute("position",new wi([0,0,0,0,1,0],3)),Nh=new Io(0,.5,1,5,1),Nh.translate(0,-.5,0)),this.position.copy(e),this.line=new Xa(Dh,new Ga({color:n,toneMapped:!1})),this.line.matrixAutoUpdate=!1,this.add(this.line),this.cone=new Yi(Nh,new vi({color:n,toneMapped:!1})),this.cone.matrixAutoUpdate=!1,this.add(this.cone),this.setDirection(t),this.setLength(i,r,s)}setDirection(t){if(t.y>.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{Ih.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(Ih,e)}}setLength(t,e=.2*t,i=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(i,e,i),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}},t.Audio=qc,t.AudioAnalyser=class{constructor(t,e=2048){this.analyser=t.context.createAnalyser(),this.analyser.fftSize=e,this.data=new Uint8Array(this.analyser.frequencyBinCount),t.getOutput().connect(this.analyser)}getFrequencyData(){return this.analyser.getByteFrequencyData(this.data),this.data}getAverageFrequency(){let t=0;const e=this.getFrequencyData();for(let i=0;ithis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return mh.copy(t).clamp(this.min,this.max).sub(t).length()}intersect(t){return this.min.max(t.min),this.max.min(t.max),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}},t.Box3=re,t.Box3Helper=class extends Za{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new Pi;n.setIndex(new _i(i,1)),n.setAttribute("position",new wi([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(n,new Ga({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}},t.BoxBufferGeometry=Ki,t.BoxGeometry=Ki,t.BoxHelper=class extends Za{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new Float32Array(24),r=new Pi;r.setIndex(new _i(i,1)),r.setAttribute("position",new _i(n,3)),super(r,new Ga({color:e,toneMapped:!1})),this.object=t,this.type="BoxHelper",this.matrixAutoUpdate=!1,this.update()}update(t){if(void 0!==t&&console.warn("THREE.BoxHelper: .update() has no longer arguments."),void 0!==this.object&&Ph.setFromObject(this.object),Ph.isEmpty())return;const e=Ph.min,i=Ph.max,n=this.geometry.attributes.position,r=n.array;r[0]=i.x,r[1]=i.y,r[2]=i.z,r[3]=e.x,r[4]=i.y,r[5]=i.z,r[6]=e.x,r[7]=e.y,r[8]=i.z,r[9]=i.x,r[10]=e.y,r[11]=i.z,r[12]=i.x,r[13]=i.y,r[14]=e.z,r[15]=e.x,r[16]=i.y,r[17]=e.z,r[18]=e.x,r[19]=e.y,r[20]=e.z,r[21]=i.x,r[22]=e.y,r[23]=e.z,n.needsUpdate=!0,this.geometry.computeBoundingSphere()}setFromObject(t){return this.object=t,this.update(),this}copy(t,e){return super.copy(t,e),this.object=t.object,this}},t.BufferAttribute=_i,t.BufferGeometry=Pi,t.BufferGeometryLoader=Pc,t.ByteType=1010,t.Cache=ic,t.Camera=nn,t.CameraHelper=class extends Za{constructor(t){const e=new Pi,i=new Ga({color:16777215,vertexColors:!0,toneMapped:!1}),n=[],r=[],s={},a=new Ht(16755200),o=new Ht(16711680),l=new Ht(43775),c=new Ht(16777215),h=new Ht(3355443);function u(t,e,i){d(t,i),d(e,i)}function d(t,e){n.push(0,0,0),r.push(e.r,e.g,e.b),void 0===s[t]&&(s[t]=[]),s[t].push(n.length/3-1)}u("n1","n2",a),u("n2","n4",a),u("n4","n3",a),u("n3","n1",a),u("f1","f2",a),u("f2","f4",a),u("f4","f3",a),u("f3","f1",a),u("n1","f1",a),u("n2","f2",a),u("n3","f3",a),u("n4","f4",a),u("p","n1",o),u("p","n2",o),u("p","n3",o),u("p","n4",o),u("u1","u2",l),u("u2","u3",l),u("u3","u1",l),u("c","t",c),u("p","c",h),u("cn1","cn2",h),u("cn3","cn4",h),u("cf1","cf2",h),u("cf3","cf4",h),e.setAttribute("position",new wi(n,3)),e.setAttribute("color",new wi(r,3)),super(e,i),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update()}update(){const t=this.geometry,e=this.pointMap;Lh.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),Rh("c",e,t,Lh,0,0,-1),Rh("t",e,t,Lh,0,0,1),Rh("n1",e,t,Lh,-1,-1,-1),Rh("n2",e,t,Lh,1,-1,-1),Rh("n3",e,t,Lh,-1,1,-1),Rh("n4",e,t,Lh,1,1,-1),Rh("f1",e,t,Lh,-1,-1,1),Rh("f2",e,t,Lh,1,-1,1),Rh("f3",e,t,Lh,-1,1,1),Rh("f4",e,t,Lh,1,1,1),Rh("u1",e,t,Lh,.7,1.1,-1),Rh("u2",e,t,Lh,-.7,1.1,-1),Rh("u3",e,t,Lh,0,2,-1),Rh("cf1",e,t,Lh,-1,0,1),Rh("cf2",e,t,Lh,1,0,1),Rh("cf3",e,t,Lh,0,-1,1),Rh("cf4",e,t,Lh,0,1,1),Rh("cn1",e,t,Lh,-1,0,-1),Rh("cn2",e,t,Lh,1,0,-1),Rh("cn3",e,t,Lh,0,-1,-1),Rh("cn4",e,t,Lh,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasTexture=class extends Yt{constructor(t,e,i,n,r,s,a,o,l){super(t,e,i,n,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}},t.CapsuleBufferGeometry=Ro,t.CapsuleGeometry=Ro,t.CatmullRomCurve3=fo,t.CineonToneMapping=3,t.CircleBufferGeometry=Po,t.CircleGeometry=Po,t.ClampToEdgeWrapping=h,t.Clock=kc,t.Color=Ht,t.ColorKeyframeTrack=Jl,t.ColorManagement=Ot,t.CompressedTexture=so,t.CompressedTextureLoader=class extends sc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=[],a=new so,o=new oc(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const i=r.parse(t,!0);s[c]={width:i.width,height:i.height,format:i.format,mipmaps:i.mipmaps},l+=1,6===l&&(1===i.mipmapCount&&(a.minFilter=f),a.image=s,a.format=i.format,a.needsUpdate=!0,e&&e(a))}),i,n)}if(Array.isArray(t))for(let e=0,i=t.length;e65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=_t(t,-65504,65504),Oh[0]=t;const e=Fh[0],i=e>>23&511;return Bh[i]+((8388607&e)>>Uh[i])}static fromHalfFloat(t){const e=t>>10;return Fh[0]=kh[Vh[e]+(1023&t)]+Gh[e],Oh[0]}},t.DecrementStencilOp=7683,t.DecrementWrapStencilOp=34056,t.DefaultLoadingManager=rc,t.DepthFormat=T,t.DepthStencilFormat=A,t.DepthTexture=Js,t.DirectionalLight=wc,t.DirectionalLightHelper=class extends ni{constructor(t,e,i){super(),this.light=t,this.light.updateMatrixWorld(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=i,void 0===e&&(e=1);let n=new Pi;n.setAttribute("position",new wi([-e,e,0,e,e,0,e,-e,0,-e,-e,0,-e,e,0],3));const r=new Ga({fog:!1,toneMapped:!1});this.lightPlane=new Xa(n,r),this.add(this.lightPlane),n=new Pi,n.setAttribute("position",new wi([0,0,0,0,0,1],3)),this.targetLine=new Xa(n,r),this.add(this.targetLine),this.update()}dispose(){this.lightPlane.geometry.dispose(),this.lightPlane.material.dispose(),this.targetLine.geometry.dispose(),this.targetLine.material.dispose()}update(){Th.setFromMatrixPosition(this.light.matrixWorld),Ah.setFromMatrixPosition(this.light.target.matrixWorld),Eh.subVectors(Ah,Th),this.lightPlane.lookAt(Ah),void 0!==this.color?(this.lightPlane.material.color.set(this.color),this.targetLine.material.color.set(this.color)):(this.lightPlane.material.color.copy(this.light.color),this.targetLine.material.color.copy(this.light.color)),this.targetLine.lookAt(Ah),this.targetLine.scale.z=Eh.length()}},t.DiscreteInterpolant=jl,t.DodecahedronBufferGeometry=zo,t.DodecahedronGeometry=zo,t.DoubleSide=2,t.DstAlphaFactor=206,t.DstColorFactor=208,t.DynamicCopyUsage=35050,t.DynamicDrawUsage=35048,t.DynamicReadUsage=35049,t.EdgesGeometry=ko,t.EllipseCurve=oo,t.EqualDepth=4,t.EqualStencilFunc=514,t.EquirectangularReflectionMapping=a,t.EquirectangularRefractionMapping=o,t.Euler=Ve,t.EventDispatcher=mt,t.ExtrudeBufferGeometry=gl,t.ExtrudeGeometry=gl,t.FileLoader=oc,t.FlatShading=1,t.Float16BufferAttribute=class extends _i{constructor(t,e,i){super(new Uint16Array(t),e,i),this.isFloat16BufferAttribute=!0}},t.Float32BufferAttribute=wi,t.Float64BufferAttribute=class extends _i{constructor(t,e,i){super(new Float64Array(t),e,i)}},t.FloatType=M,t.Fog=ta,t.FogExp2=$s,t.Font=function(){console.error("THREE.Font has been moved to /examples/jsm/loaders/FontLoader.js")},t.FontLoader=function(){console.error("THREE.FontLoader has been moved to /examples/jsm/loaders/FontLoader.js")},t.FramebufferTexture=class extends Yt{constructor(t,e,i){super({width:t,height:e}),this.isFramebufferTexture=!0,this.format=i,this.magFilter=d,this.minFilter=d,this.generateMipmaps=!1,this.needsUpdate=!0}},t.FrontSide=0,t.Frustum=fn,t.GLBufferAttribute=class{constructor(t,e,i,n,r){this.isGLBufferAttribute=!0,this.buffer=t,this.type=e,this.itemSize=i,this.elementSize=n,this.count=r,this.version=0}set needsUpdate(t){!0===t&&this.version++}setBuffer(t){return this.buffer=t,this}setType(t,e){return this.type=t,this.elementSize=e,this}setItemSize(t){return this.itemSize=t,this}setCount(t){return this.count=t,this}},t.GLSL1="100",t.GLSL3=dt,t.GreaterDepth=6,t.GreaterEqualDepth=5,t.GreaterEqualStencilFunc=518,t.GreaterStencilFunc=516,t.GridHelper=class extends Za{constructor(t=10,e=10,i=4473924,n=8947848){i=new Ht(i),n=new Ht(n);const r=e/2,s=t/e,a=t/2,o=[],l=[];for(let t=0,c=0,h=-a;t<=e;t++,h+=s){o.push(-a,0,h,a,0,h),o.push(h,0,-a,h,0,a);const e=t===r?i:n;e.toArray(l,c),c+=3,e.toArray(l,c),c+=3,e.toArray(l,c),c+=3,e.toArray(l,c),c+=3}const c=new Pi;c.setAttribute("position",new wi(o,3)),c.setAttribute("color",new wi(l,3));super(c,new Ga({vertexColors:!0,toneMapped:!1})),this.type="GridHelper"}},t.Group=js,t.HalfFloatType=b,t.HemisphereLight=hc,t.HemisphereLightHelper=class extends ni{constructor(t,e,i){super(),this.light=t,this.light.updateMatrixWorld(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=i;const n=new yl(e);n.rotateY(.5*Math.PI),this.material=new vi({wireframe:!0,fog:!1,toneMapped:!1}),void 0===this.color&&(this.material.vertexColors=!0);const r=n.getAttribute("position"),s=new Float32Array(3*r.count);n.setAttribute("color",new _i(s,3)),this.add(new Yi(n,this.material)),this.update()}dispose(){this.children[0].geometry.dispose(),this.children[0].material.dispose()}update(){const t=this.children[0];if(void 0!==this.color)this.material.color.set(this.color);else{const e=t.geometry.getAttribute("color");wh.copy(this.light.color),Sh.copy(this.light.groundColor);for(let t=0,i=e.count;t0){const i=new nc(e);r=new lc(i),r.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e0){n=new lc(this.manager),n.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;eNumber.EPSILON){if(l<0&&(i=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===i.y){if(t.x===i.x)return!0}else{const e=l*(t.x-i.x)-o*(t.y-i.y);if(0===e)return!0;if(e<0)continue;n=!n}}else{if(t.y!==i.y)continue;if(a.x<=t.x&&t.x<=i.x||i.x<=t.x&&t.x<=a.x)return!0}}return n}const r=pl.isClockWise,s=this.subPaths;if(0===s.length)return[];if(!0===e)return i(s);let a,o,l;const c=[];if(1===s.length)return o=s[0],l=new Go,l.curves=o.curves,c.push(l),c;let h=!r(s[0].getPoints());h=t?!h:h;const u=[],d=[];let p,m,f=[],g=0;d[g]=void 0,f[g]=[];for(let e=0,i=s.length;e1){let t=!1,e=0;for(let t=0,e=d.length;t0&&!1===t&&(f=u)}for(let t=0,e=d.length;t=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}},t.WebGL1Renderer=Qs,t.WebGL3DRenderTarget=class extends Kt{constructor(t,e,i){super(t,e),this.isWebGL3DRenderTarget=!0,this.depth=i,this.texture=new $t(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLArrayRenderTarget=class extends Kt{constructor(t,e,i){super(t,e),this.isWebGLArrayRenderTarget=!0,this.depth=i,this.texture=new Qt(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLCubeRenderTarget=ln,t.WebGLMultipleRenderTargets=class extends Kt{constructor(t,e,i,n={}){super(t,e,n),this.isWebGLMultipleRenderTargets=!0;const r=this.texture;this.texture=[];for(let t=0;t>8&255]+xt[t>>16&255]+xt[t>>24&255]+"-"+xt[255&e]+xt[e>>8&255]+"-"+xt[e>>16&15|64]+xt[e>>24&255]+"-"+xt[63&i|128]+xt[i>>8&255]+"-"+xt[i>>16&255]+xt[i>>24&255]+xt[255&n]+xt[n>>8&255]+xt[n>>16&255]+xt[n>>24&255]).toLowerCase()}function St(t,e,i){return Math.max(e,Math.min(i,t))}function wt(t,e){return(t%e+e)%e}function Tt(t,e,i){return(1-i)*t+i*e}function At(t){return 0==(t&t-1)&&0!==t}function Et(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function Ct(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}function Lt(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function Rt(t,e){switch(e.constructor){case Float32Array:return t;case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}var Pt=Object.freeze({__proto__:null,DEG2RAD:yt,RAD2DEG:Mt,ceilPowerOfTwo:Et,clamp:St,damp:function(t,e,i,n){return Tt(t,e,1-Math.exp(-i*n))},degToRad:function(t){return t*yt},denormalize:Lt,euclideanModulo:wt,floorPowerOfTwo:Ct,generateUUID:bt,inverseLerp:function(t,e,i){return t!==e?(i-t)/(e-t):0},isPowerOfTwo:At,lerp:Tt,mapLinear:function(t,e,i,n,r){return n+(t-e)*(r-n)/(i-e)},normalize:Rt,pingpong:function(t,e=1){return e-Math.abs(wt(t,2*e)-e)},radToDeg:function(t){return t*Mt},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},seededRandom:function(t){void 0!==t&&(_t=t);let e=_t+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},setQuaternionFromProperEuler:function(t,e,i,n,r){const s=Math.cos,a=Math.sin,o=s(i/2),l=a(i/2),c=s((e+n)/2),h=a((e+n)/2),u=s((e-n)/2),d=a((e-n)/2),p=s((n-e)/2),m=a((n-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},smootherstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*t*(t*(6*t-15)+10)},smoothstep:function(t,e,i){return t<=e?0:t>=i?1:(t=(t-e)/(i-e))*t*(3-2*t)}});class It{constructor(t=0,e=0){It.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,i=this.y,n=t.elements;return this.x=n[0]*e+n[3]*i+n[6],this.y=n[1]*e+n[4]*i+n[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y;return e*e+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const i=Math.cos(e),n=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*i-s*n+t.x,this.y=r*n+s*i+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Dt{constructor(){Dt.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1]}set(t,e,i,n,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=n,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=i,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],this}extractBasis(t,e,i){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),i.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[3],o=i[6],l=i[1],c=i[4],h=i[7],u=i[2],d=i[5],p=i[8],m=n[0],f=n[3],g=n[6],v=n[1],x=n[4],_=n[7],y=n[2],M=n[5],b=n[8];return r[0]=s*m+a*v+o*y,r[3]=s*f+a*x+o*M,r[6]=s*g+a*_+o*b,r[1]=l*m+c*v+h*y,r[4]=l*f+c*x+h*M,r[7]=l*g+c*_+h*b,r[2]=u*m+d*v+p*y,r[5]=u*f+d*x+p*M,r[8]=u*g+d*_+p*b,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-i*r*c+i*a*o+n*r*l-n*s*o}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+i*u+n*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(n*l-c*i)*m,t[2]=(a*i-n*s)*m,t[3]=u*m,t[4]=(c*e-n*o)*m,t[5]=(n*r-a*e)*m,t[6]=d*m,t[7]=(i*o-l*e)*m,t[8]=(s*e-i*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,i,n,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(i*o,i*l,-i*(o*s+l*a)+s+t,-n*l,n*o,-n*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(Nt.makeScale(t,e)),this}rotate(t){return this.premultiply(Nt.makeRotation(-t)),this}translate(t,e){return this.premultiply(Nt.makeTranslation(t,e)),this}makeTranslation(t,e){return this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,-i,0,i,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<9;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<9;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const Nt=new Dt;function Ot(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const zt={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function Ut(t,e){return new zt[t](e)}function Bt(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function Ft(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function kt(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}const Gt={[ut]:{[dt]:Ft},[dt]:{[ut]:kt}},Vt={legacyMode:!0,get workingColorSpace(){return dt},set workingColorSpace(t){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(t,e,i){if(this.legacyMode||e===i||!e||!i)return t;if(Gt[e]&&void 0!==Gt[e][i]){const n=Gt[e][i];return t.r=n(t.r),t.g=n(t.g),t.b=n(t.b),t}throw new Error("Unsupported color space conversion.")},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)}},Ht={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Wt={r:0,g:0,b:0},jt={h:0,s:0,l:0},qt={h:0,s:0,l:0};function Xt(t,e,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+6*(e-t)*(2/3-i):t}function Yt(t,e){return e.r=t.r,e.g=t.g,e.b=t.b,e}class Zt{constructor(t,e,i){return this.isColor=!0,this.r=1,this.g=1,this.b=1,void 0===e&&void 0===i?this.set(t):this.setRGB(t,e,i)}set(t){return t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t),this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=ut){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,Vt.toWorkingColorSpace(this,e),this}setRGB(t,e,i,n=Vt.workingColorSpace){return this.r=t,this.g=e,this.b=i,Vt.toWorkingColorSpace(this,n),this}setHSL(t,e,i,n=Vt.workingColorSpace){if(t=wt(t,1),e=St(e,0,1),i=St(i,0,1),0===e)this.r=this.g=this.b=i;else{const n=i<=.5?i*(1+e):i+e-i*e,r=2*i-n;this.r=Xt(r,n,t+1/3),this.g=Xt(r,n,t),this.b=Xt(r,n,t-1/3)}return Vt.toWorkingColorSpace(this,n),this}setStyle(t,e=ut){function i(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let n;if(n=/^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(t)){let t;const r=n[1],s=n[2];switch(r){case"rgb":case"rgba":if(t=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(255,parseInt(t[1],10))/255,this.g=Math.min(255,parseInt(t[2],10))/255,this.b=Math.min(255,parseInt(t[3],10))/255,Vt.toWorkingColorSpace(this,e),i(t[4]),this;if(t=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return this.r=Math.min(100,parseInt(t[1],10))/100,this.g=Math.min(100,parseInt(t[2],10))/100,this.b=Math.min(100,parseInt(t[3],10))/100,Vt.toWorkingColorSpace(this,e),i(t[4]),this;break;case"hsl":case"hsla":if(t=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s)){const n=parseFloat(t[1])/360,r=parseFloat(t[2])/100,s=parseFloat(t[3])/100;return i(t[4]),this.setHSL(n,r,s,e)}}}else if(n=/^\#([A-Fa-f\d]+)$/.exec(t)){const t=n[1],i=t.length;if(3===i)return this.r=parseInt(t.charAt(0)+t.charAt(0),16)/255,this.g=parseInt(t.charAt(1)+t.charAt(1),16)/255,this.b=parseInt(t.charAt(2)+t.charAt(2),16)/255,Vt.toWorkingColorSpace(this,e),this;if(6===i)return this.r=parseInt(t.charAt(0)+t.charAt(1),16)/255,this.g=parseInt(t.charAt(2)+t.charAt(3),16)/255,this.b=parseInt(t.charAt(4)+t.charAt(5),16)/255,Vt.toWorkingColorSpace(this,e),this}return t&&t.length>0?this.setColorName(t,e):this}setColorName(t,e=ut){const i=Ht[t.toLowerCase()];return void 0!==i?this.setHex(i,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=Ft(t.r),this.g=Ft(t.g),this.b=Ft(t.b),this}copyLinearToSRGB(t){return this.r=kt(t.r),this.g=kt(t.g),this.b=kt(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=ut){return Vt.fromWorkingColorSpace(Yt(this,Wt),t),St(255*Wt.r,0,255)<<16^St(255*Wt.g,0,255)<<8^St(255*Wt.b,0,255)<<0}getHexString(t=ut){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=Vt.workingColorSpace){Vt.fromWorkingColorSpace(Yt(this,Wt),e);const i=Wt.r,n=Wt.g,r=Wt.b,s=Math.max(i,n,r),a=Math.min(i,n,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c<=.5?t/(s+a):t/(2-s-a),s){case i:o=(n-r)/t+(n2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=Bt("canvas");e.width=t.width,e.height=t.height;const i=e.getContext("2d");i.drawImage(t,0,0,t.width,t.height);const n=i.getImageData(0,0,t.width,t.height),r=n.data;for(let t=0;t0&&(i.userData=this.userData),e||(t.textures[this.uuid]=i),i}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==n)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case c:t.x=t.x-Math.floor(t.x);break;case h:t.x=t.x<0?0:1;break;case u:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case c:t.y=t.y-Math.floor(t.y);break;case h:t.y=t.y<0?0:1;break;case u:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}}ee.DEFAULT_IMAGE=null,ee.DEFAULT_MAPPING=n,ee.DEFAULT_ANISOTROPY=1;class ie{constructor(t=0,e=0,i=0,n=1){ie.prototype.isVector4=!0,this.x=t,this.y=e,this.z=i,this.w=n}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,i,n){return this.x=t,this.y=e,this.z=i,this.w=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*i+s[8]*n+s[12]*r,this.y=s[1]*e+s[5]*i+s[9]*n+s[13]*r,this.z=s[2]*e+s[6]*i+s[10]*n+s[14]*r,this.w=s[3]*e+s[7]*i+s[11]*n+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,i,n,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,n=1-e*e;if(n>Number.EPSILON){const r=Math.sqrt(n),s=Math.atan2(r,e*i);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*i;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,i,n,r,s){const a=i[n],o=i[n+1],l=i[n+2],c=i[n+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,i,n){return this._x=t,this._y=e,this._z=i,this._w=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){const i=t._x,n=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(i/2),c=a(n/2),h=a(r/2),u=o(i/2),d=o(n/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const i=e/2,n=Math.sin(i);return this._x=t.x*n,this._y=t.y*n,this._z=t.z*n,this._w=Math.cos(i),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,i=e[0],n=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=i+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-n)*t}else if(i>a&&i>h){const t=2*Math.sqrt(1+i-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(n+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-i-h);this._w=(r-l)/t,this._x=(n+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-i-a);this._w=(s-n)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let i=t.dot(e)+1;return iMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=i):(this._x=0,this._y=-t.z,this._z=t.y,this._w=i)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=i),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(St(this.dot(t),-1,1)))}rotateTowards(t,e){const i=this.angleTo(t);if(0===i)return this;const n=Math.min(1,e/i);return this.slerp(t,n),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const i=t._x,n=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=i*c+s*a+n*l-r*o,this._y=n*c+s*o+r*a-i*l,this._z=r*c+s*l+i*o-n*a,this._w=s*c-i*a-n*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const i=this._x,n=this._y,r=this._z,s=this._w;let a=s*t._w+i*t._x+n*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=i,this._y=n,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*i+e*this._x,this._y=t*n+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=i*h+this._x*u,this._y=n*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,i){return this.copy(t).slerp(e,i)}random(){const t=Math.random(),e=Math.sqrt(1-t),i=Math.sqrt(t),n=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(n),i*Math.sin(r),i*Math.cos(r),e*Math.sin(n))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class oe{constructor(t=0,e=0,i=0){oe.prototype.isVector3=!0,this.x=t,this.y=e,this.z=i}set(t,e,i){return void 0===i&&(i=this.z),this.x=t,this.y=e,this.z=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(ce.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(ce.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[3]*i+r[6]*n,this.y=r[1]*e+r[4]*i+r[7]*n,this.z=r[2]*e+r[5]*i+r[8]*n,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,i=this.y,n=this.z,r=t.elements,s=1/(r[3]*e+r[7]*i+r[11]*n+r[15]);return this.x=(r[0]*e+r[4]*i+r[8]*n+r[12])*s,this.y=(r[1]*e+r[5]*i+r[9]*n+r[13])*s,this.z=(r[2]*e+r[6]*i+r[10]*n+r[14])*s,this}applyQuaternion(t){const e=this.x,i=this.y,n=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*n-a*i,c=o*i+a*e-r*n,h=o*n+r*i-s*e,u=-r*e-s*i-a*n;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,i=this.y,n=this.z,r=t.elements;return this.x=r[0]*e+r[4]*i+r[8]*n,this.y=r[1]*e+r[5]*i+r[9]*n,this.z=r[2]*e+r[6]*i+r[10]*n,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(t,Math.min(e,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,i){return this.x=t.x+(e.x-t.x)*i,this.y=t.y+(e.y-t.y)*i,this.z=t.z+(e.z-t.z)*i,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const i=t.x,n=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=n*o-r*a,this.y=r*s-i*o,this.z=i*a-n*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const i=t.dot(this)/e;return this.copy(t).multiplyScalar(i)}projectOnPlane(t){return le.copy(this).projectOnVector(t),this.sub(le)}reflect(t){return this.sub(le.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const i=this.dot(t)/e;return Math.acos(St(i,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,i=this.y-t.y,n=this.z-t.z;return e*e+i*i+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,i){const n=Math.sin(e)*t;return this.x=n*Math.sin(i),this.y=Math.cos(e)*t,this.z=n*Math.cos(i),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,i){return this.x=t*Math.sin(e),this.y=i,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),i=this.setFromMatrixColumn(t,1).length(),n=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=i,this.z=n,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,i=Math.sqrt(1-t**2);return this.x=i*Math.cos(e),this.y=i*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const le=new oe,ce=new ae;class he{constructor(t=new oe(1/0,1/0,1/0),e=new oe(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.length;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromBufferAttribute(t){let e=1/0,i=1/0,n=1/0,r=-1/0,s=-1/0,a=-1/0;for(let o=0,l=t.count;or&&(r=l),c>s&&(s=c),h>a&&(a=h)}return this.min.set(e,i,n),this.max.set(r,s,a),this}setFromPoints(t){this.makeEmpty();for(let e=0,i=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,de),de.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,i;return t.normal.x>0?(e=t.normal.x*this.min.x,i=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,i=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,i+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,i+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,i+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,i+=t.normal.z*this.min.z),e<=-t.constant&&i>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(ye),Me.subVectors(this.max,ye),me.subVectors(t.a,ye),fe.subVectors(t.b,ye),ge.subVectors(t.c,ye),ve.subVectors(fe,me),xe.subVectors(ge,fe),_e.subVectors(me,ge);let e=[0,-ve.z,ve.y,0,-xe.z,xe.y,0,-_e.z,_e.y,ve.z,0,-ve.x,xe.z,0,-xe.x,_e.z,0,-_e.x,-ve.y,ve.x,0,-xe.y,xe.x,0,-_e.y,_e.x,0];return!!we(e,me,fe,ge,Me)&&(e=[1,0,0,0,1,0,0,0,1],!!we(e,me,fe,ge,Me)&&(be.crossVectors(ve,xe),e=[be.x,be.y,be.z],we(e,me,fe,ge,Me)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return de.copy(t).clamp(this.min,this.max).sub(t).length()}getBoundingSphere(t){return this.getCenter(t.center),t.radius=.5*this.getSize(de).length(),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(ue[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),ue[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),ue[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),ue[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),ue[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),ue[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),ue[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),ue[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(ue)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const ue=[new oe,new oe,new oe,new oe,new oe,new oe,new oe,new oe],de=new oe,pe=new he,me=new oe,fe=new oe,ge=new oe,ve=new oe,xe=new oe,_e=new oe,ye=new oe,Me=new oe,be=new oe,Se=new oe;function we(t,e,i,n,r){for(let s=0,a=t.length-3;s<=a;s+=3){Se.fromArray(t,s);const a=r.x*Math.abs(Se.x)+r.y*Math.abs(Se.y)+r.z*Math.abs(Se.z),o=e.dot(Se),l=i.dot(Se),c=n.dot(Se);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const Te=new he,Ae=new oe,Ee=new oe;class Ce{constructor(t=new oe,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const i=this.center;void 0!==e?i.copy(e):Te.setFromPoints(t).getCenter(i);let n=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;Ae.subVectors(t,this.center);const e=Ae.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),i=.5*(t-this.radius);this.center.addScaledVector(Ae,i/t),this.radius+=i}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Ee.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Ae.copy(t.center).add(Ee)),this.expandByPoint(Ae.copy(t.center).sub(Ee))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Le=new oe,Re=new oe,Pe=new oe,Ie=new oe,De=new oe,Ne=new oe,Oe=new oe;class ze{constructor(t=new oe,e=new oe(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.direction).multiplyScalar(t).add(this.origin)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,Le)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const i=e.dot(this.direction);return i<0?e.copy(this.origin):e.copy(this.direction).multiplyScalar(i).add(this.origin)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=Le.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Le.copy(this.direction).multiplyScalar(e).add(this.origin),Le.distanceToSquared(t))}distanceSqToSegment(t,e,i,n){Re.copy(t).add(e).multiplyScalar(.5),Pe.copy(e).sub(t).normalize(),Ie.copy(this.origin).sub(Re);const r=.5*t.distanceTo(e),s=-this.direction.dot(Pe),a=Ie.dot(this.direction),o=-Ie.dot(Pe),l=Ie.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return i&&i.copy(this.direction).multiplyScalar(h).add(this.origin),n&&n.copy(Pe).multiplyScalar(u).add(Re),d}intersectSphere(t,e){Le.subVectors(t.center,this.origin);const i=Le.dot(this.direction),n=Le.dot(Le)-i*i,r=t.radius*t.radius;if(n>r)return null;const s=Math.sqrt(r-n),a=i-s,o=i+s;return a<0&&o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const i=-(this.origin.dot(t.normal)+t.constant)/e;return i>=0?i:null}intersectPlane(t,e){const i=this.distanceToPlane(t);return null===i?null:this.at(i,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let i,n,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(i=(t.min.x-u.x)*l,n=(t.max.x-u.x)*l):(i=(t.max.x-u.x)*l,n=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),i>s||r>n?null:((r>i||isNaN(i))&&(i=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),i>o||a>n?null:((a>i||i!=i)&&(i=a),(o=0?i:n,e)))}intersectsBox(t){return null!==this.intersectBox(t,Le)}intersectTriangle(t,e,i,n,r){De.subVectors(e,t),Ne.subVectors(i,t),Oe.crossVectors(De,Ne);let s,a=this.direction.dot(Oe);if(a>0){if(n)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}Ie.subVectors(this.origin,t);const o=s*this.direction.dot(Ne.crossVectors(Ie,Ne));if(o<0)return null;const l=s*this.direction.dot(De.cross(Ie));if(l<0)return null;if(o+l>a)return null;const c=-s*Ie.dot(Oe);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class Ue{constructor(){Ue.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}set(t,e,i,n,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=i,g[12]=n,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new Ue).fromArray(this.elements)}copy(t){const e=this.elements,i=t.elements;return e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],e[4]=i[4],e[5]=i[5],e[6]=i[6],e[7]=i[7],e[8]=i[8],e[9]=i[9],e[10]=i[10],e[11]=i[11],e[12]=i[12],e[13]=i[13],e[14]=i[14],e[15]=i[15],this}copyPosition(t){const e=this.elements,i=t.elements;return e[12]=i[12],e[13]=i[13],e[14]=i[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,i){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this}makeBasis(t,e,i){return this.set(t.x,e.x,i.x,0,t.y,e.y,i.y,0,t.z,e.z,i.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,i=t.elements,n=1/Be.setFromMatrixColumn(t,0).length(),r=1/Be.setFromMatrixColumn(t,1).length(),s=1/Be.setFromMatrixColumn(t,2).length();return e[0]=i[0]*n,e[1]=i[1]*n,e[2]=i[2]*n,e[3]=0,e[4]=i[4]*r,e[5]=i[5]*r,e[6]=i[6]*r,e[7]=0,e[8]=i[8]*s,e[9]=i[9]*s,e[10]=i[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,i=t.x,n=t.y,r=t.z,s=Math.cos(i),a=Math.sin(i),o=Math.cos(n),l=Math.sin(n),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=i+n*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=n+i*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t+r*a,e[4]=n*a-i,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=i*a-n,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,i=o*h,n=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=n+i*a,e[1]=i+n*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,i=s*h,n=a*c,r=a*h;e[0]=o*c,e[4]=n*l-i,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=i*l-n,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=n*h+i,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=i*h+n,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,i=s*l,n=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=i*h-n,e[2]=n*h-i,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(ke,t,Ge)}lookAt(t,e,i){const n=this.elements;return We.subVectors(t,e),0===We.lengthSq()&&(We.z=1),We.normalize(),Ve.crossVectors(i,We),0===Ve.lengthSq()&&(1===Math.abs(i.z)?We.x+=1e-4:We.z+=1e-4,We.normalize(),Ve.crossVectors(i,We)),Ve.normalize(),He.crossVectors(We,Ve),n[0]=Ve.x,n[4]=He.x,n[8]=We.x,n[1]=Ve.y,n[5]=He.y,n[9]=We.y,n[2]=Ve.z,n[6]=He.z,n[10]=We.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const i=t.elements,n=e.elements,r=this.elements,s=i[0],a=i[4],o=i[8],l=i[12],c=i[1],h=i[5],u=i[9],d=i[13],p=i[2],m=i[6],f=i[10],g=i[14],v=i[3],x=i[7],_=i[11],y=i[15],M=n[0],b=n[4],S=n[8],w=n[12],T=n[1],A=n[5],E=n[9],C=n[13],L=n[2],R=n[6],P=n[10],I=n[14],D=n[3],N=n[7],O=n[11],z=n[15];return r[0]=s*M+a*T+o*L+l*D,r[4]=s*b+a*A+o*R+l*N,r[8]=s*S+a*E+o*P+l*O,r[12]=s*w+a*C+o*I+l*z,r[1]=c*M+h*T+u*L+d*D,r[5]=c*b+h*A+u*R+d*N,r[9]=c*S+h*E+u*P+d*O,r[13]=c*w+h*C+u*I+d*z,r[2]=p*M+m*T+f*L+g*D,r[6]=p*b+m*A+f*R+g*N,r[10]=p*S+m*E+f*P+g*O,r[14]=p*w+m*C+f*I+g*z,r[3]=v*M+x*T+_*L+y*D,r[7]=v*b+x*A+_*R+y*N,r[11]=v*S+x*E+_*P+y*O,r[15]=v*w+x*C+_*I+y*z,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],i=t[4],n=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-n*l*h-r*a*u+i*l*u+n*a*d-i*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-n*s*d+n*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+i*s*d+r*a*c-i*l*c)+t[15]*(-n*a*c-e*o*h+e*a*u+n*s*h-i*s*u+i*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,i){const n=this.elements;return t.isVector3?(n[12]=t.x,n[13]=t.y,n[14]=t.z):(n[12]=t,n[13]=e,n[14]=i),this}invert(){const t=this.elements,e=t[0],i=t[1],n=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,x=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,_=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,y=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+i*x+n*_+r*y;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const b=1/M;return t[0]=v*b,t[1]=(m*u*r-h*f*r-m*n*d+i*f*d+h*n*g-i*u*g)*b,t[2]=(a*f*r-m*o*r+m*n*l-i*f*l-a*n*g+i*o*g)*b,t[3]=(h*o*r-a*u*r-h*n*l+i*u*l+a*n*d-i*o*d)*b,t[4]=x*b,t[5]=(c*f*r-p*u*r+p*n*d-e*f*d-c*n*g+e*u*g)*b,t[6]=(p*o*r-s*f*r-p*n*l+e*f*l+s*n*g-e*o*g)*b,t[7]=(s*u*r-c*o*r+c*n*l-e*u*l-s*n*d+e*o*d)*b,t[8]=_*b,t[9]=(p*h*r-c*m*r-p*i*d+e*m*d+c*i*g-e*h*g)*b,t[10]=(s*m*r-p*a*r+p*i*l-e*m*l-s*i*g+e*a*g)*b,t[11]=(c*a*r-s*h*r-c*i*l+e*h*l+s*i*d-e*a*d)*b,t[12]=y*b,t[13]=(c*m*n-p*h*n+p*i*u-e*m*u-c*i*f+e*h*f)*b,t[14]=(p*a*n-s*m*n-p*i*o+e*m*o+s*i*f-e*a*f)*b,t[15]=(s*h*n-c*a*n+c*i*o-e*h*o-s*i*u+e*a*u)*b,this}scale(t){const e=this.elements,i=t.x,n=t.y,r=t.z;return e[0]*=i,e[4]*=n,e[8]*=r,e[1]*=i,e[5]*=n,e[9]*=r,e[2]*=i,e[6]*=n,e[10]*=r,e[3]*=i,e[7]*=n,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],i=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],n=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,i,n))}makeTranslation(t,e,i){return this.set(1,0,0,t,0,1,0,e,0,0,1,i,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),i=Math.sin(t);return this.set(1,0,0,0,0,e,-i,0,0,i,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,0,i,0,0,1,0,0,-i,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),i=Math.sin(t);return this.set(e,-i,0,0,i,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const i=Math.cos(e),n=Math.sin(e),r=1-i,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+i,l*a-n*o,l*o+n*a,0,l*a+n*o,c*a+i,c*o-n*s,0,l*o-n*a,c*o+n*s,r*o*o+i,0,0,0,0,1),this}makeScale(t,e,i){return this.set(t,0,0,0,0,e,0,0,0,0,i,0,0,0,0,1),this}makeShear(t,e,i,n,r,s){return this.set(1,i,r,0,t,1,s,0,e,n,1,0,0,0,0,1),this}compose(t,e,i){const n=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,x=o*c,_=o*h,y=i.x,M=i.y,b=i.z;return n[0]=(1-(m+g))*y,n[1]=(d+_)*y,n[2]=(p-x)*y,n[3]=0,n[4]=(d-_)*M,n[5]=(1-(u+g))*M,n[6]=(f+v)*M,n[7]=0,n[8]=(p+x)*b,n[9]=(f-v)*b,n[10]=(1-(u+m))*b,n[11]=0,n[12]=t.x,n[13]=t.y,n[14]=t.z,n[15]=1,this}decompose(t,e,i){const n=this.elements;let r=Be.set(n[0],n[1],n[2]).length();const s=Be.set(n[4],n[5],n[6]).length(),a=Be.set(n[8],n[9],n[10]).length();this.determinant()<0&&(r=-r),t.x=n[12],t.y=n[13],t.z=n[14],Fe.copy(this);const o=1/r,l=1/s,c=1/a;return Fe.elements[0]*=o,Fe.elements[1]*=o,Fe.elements[2]*=o,Fe.elements[4]*=l,Fe.elements[5]*=l,Fe.elements[6]*=l,Fe.elements[8]*=c,Fe.elements[9]*=c,Fe.elements[10]*=c,e.setFromRotationMatrix(Fe),i.x=r,i.y=s,i.z=a,this}makePerspective(t,e,i,n,r,s){const a=this.elements,o=2*r/(e-t),l=2*r/(i-n),c=(e+t)/(e-t),h=(i+n)/(i-n),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,i,n,r,s){const a=this.elements,o=1/(e-t),l=1/(i-n),c=1/(s-r),h=(e+t)*o,u=(i+n)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,i=t.elements;for(let t=0;t<16;t++)if(e[t]!==i[t])return!1;return!0}fromArray(t,e=0){for(let i=0;i<16;i++)this.elements[i]=t[i+e];return this}toArray(t=[],e=0){const i=this.elements;return t[e]=i[0],t[e+1]=i[1],t[e+2]=i[2],t[e+3]=i[3],t[e+4]=i[4],t[e+5]=i[5],t[e+6]=i[6],t[e+7]=i[7],t[e+8]=i[8],t[e+9]=i[9],t[e+10]=i[10],t[e+11]=i[11],t[e+12]=i[12],t[e+13]=i[13],t[e+14]=i[14],t[e+15]=i[15],t}}const Be=new oe,Fe=new Ue,ke=new oe(0,0,0),Ge=new oe(1,1,1),Ve=new oe,He=new oe,We=new oe,je=new Ue,qe=new ae;class Xe{constructor(t=0,e=0,i=0,n=Xe.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=i,this._order=n}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,i,n=this._order){return this._x=t,this._y=e,this._z=i,this._order=n,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,i=!0){const n=t.elements,r=n[0],s=n[4],a=n[8],o=n[1],l=n[5],c=n[9],h=n[2],u=n[6],d=n[10];switch(e){case"XYZ":this._y=Math.asin(St(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-St(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(St(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-St(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(St(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-St(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===i&&this._onChangeCallback(),this}setFromQuaternion(t,e,i){return je.makeRotationFromQuaternion(t),this.setFromRotationMatrix(je,e,i)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return qe.setFromEuler(this),this.setFromQuaternion(qe,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}Xe.DEFAULT_ORDER="XYZ";class Ye{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0&&(i=i.concat(r))}return i}getWorldPosition(t){return this.updateWorldMatrix(!0,!1),t.setFromMatrixPosition(this.matrixWorld)}getWorldQuaternion(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(ti,t,ei),t}getWorldScale(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(ti,ii,t),t}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(e[8],e[9],e[10]).normalize()}raycast(){}traverse(t){t(this);const e=this.children;for(let i=0,n=e.length;i0&&(n.userData=this.userData),n.layers=this.layers.mask,n.matrix=this.matrix.toArray(),!1===this.matrixAutoUpdate&&(n.matrixAutoUpdate=!1),this.isInstancedMesh&&(n.type="InstancedMesh",n.count=this.count,n.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(n.instanceColor=this.instanceColor.toJSON())),this.isScene)this.background&&(this.background.isColor?n.background=this.background.toJSON():this.background.isTexture&&(n.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(n.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){n.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const i=e.shapes;if(Array.isArray(i))for(let e=0,n=i.length;e0){n.children=[];for(let e=0;e0){n.animations=[];for(let e=0;e0&&(i.geometries=e),n.length>0&&(i.materials=n),r.length>0&&(i.textures=r),a.length>0&&(i.images=a),o.length>0&&(i.shapes=o),l.length>0&&(i.skeletons=l),c.length>0&&(i.animations=c),h.length>0&&(i.nodes=h)}return i.object=n,i;function s(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?n.multiplyScalar(1/Math.sqrt(r)):n.set(0,0,0)}static getBarycoord(t,e,i,n,r){ci.subVectors(n,e),hi.subVectors(i,e),ui.subVectors(t,e);const s=ci.dot(ci),a=ci.dot(hi),o=ci.dot(ui),l=hi.dot(hi),c=hi.dot(ui),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,i,n){return this.getBarycoord(t,e,i,n,di),di.x>=0&&di.y>=0&&di.x+di.y<=1}static getUV(t,e,i,n,r,s,a,o){return this.getBarycoord(t,e,i,n,di),o.set(0,0),o.addScaledVector(r,di.x),o.addScaledVector(s,di.y),o.addScaledVector(a,di.z),o}static isFrontFacing(t,e,i,n){return ci.subVectors(i,e),hi.subVectors(t,e),ci.cross(hi).dot(n)<0}set(t,e,i){return this.a.copy(t),this.b.copy(e),this.c.copy(i),this}setFromPointsAndIndices(t,e,i,n){return this.a.copy(t[e]),this.b.copy(t[i]),this.c.copy(t[n]),this}setFromAttributeAndIndices(t,e,i,n){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,i),this.c.fromBufferAttribute(t,n),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return ci.subVectors(this.c,this.b),hi.subVectors(this.a,this.b),.5*ci.cross(hi).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return _i.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return _i.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,i,n,r){return _i.getUV(t,this.a,this.b,this.c,e,i,n,r)}containsPoint(t){return _i.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return _i.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const i=this.a,n=this.b,r=this.c;let s,a;pi.subVectors(n,i),mi.subVectors(r,i),gi.subVectors(t,i);const o=pi.dot(gi),l=mi.dot(gi);if(o<=0&&l<=0)return e.copy(i);vi.subVectors(t,n);const c=pi.dot(vi),h=mi.dot(vi);if(c>=0&&h<=c)return e.copy(n);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(i).addScaledVector(pi,s);xi.subVectors(t,r);const d=pi.dot(xi),p=mi.dot(xi);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(i).addScaledVector(mi,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return fi.subVectors(r,n),a=(h-c)/(h-c+(d-p)),e.copy(n).addScaledVector(fi,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(i).addScaledVector(pi,s).addScaledVector(mi,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let yi=0;class Mi extends vt{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:yi++}),this.uuid=bt(),this.name="",this.type="Material",this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=i,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=pt,this.stencilZFail=pt,this.stencilZPass=pt,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.forceSinglePass=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const i=t[e];if(void 0===i){console.warn("THREE.Material: '"+e+"' parameter is undefined.");continue}const n=this[e];void 0!==n?n&&n.isColor?n.set(i):n&&n.isVector3&&i&&i.isVector3?n.copy(i):this[e]=i:console.warn("THREE."+this.type+": '"+e+"' is not a property of this material.")}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const i={metadata:{version:4.5,type:"Material",generator:"Material.toJSON"}};function n(t){const e=[];for(const i in t){const n=t[i];delete n.metadata,e.push(n)}return e}if(i.uuid=this.uuid,i.type=this.type,""!==this.name&&(i.name=this.name),this.color&&this.color.isColor&&(i.color=this.color.getHex()),void 0!==this.roughness&&(i.roughness=this.roughness),void 0!==this.metalness&&(i.metalness=this.metalness),void 0!==this.sheen&&(i.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(i.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(i.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(i.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(i.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(i.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(i.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(i.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(i.shininess=this.shininess),void 0!==this.clearcoat&&(i.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(i.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(i.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(i.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(i.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,i.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(i.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(i.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(i.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(i.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(i.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(i.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(i.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(i.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(i.lightMap=this.lightMap.toJSON(t).uuid,i.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(i.aoMap=this.aoMap.toJSON(t).uuid,i.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(i.bumpMap=this.bumpMap.toJSON(t).uuid,i.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(i.normalMap=this.normalMap.toJSON(t).uuid,i.normalMapType=this.normalMapType,i.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(i.displacementMap=this.displacementMap.toJSON(t).uuid,i.displacementScale=this.displacementScale,i.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(i.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(i.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(i.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(i.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(i.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(i.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(i.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(i.combine=this.combine)),void 0!==this.envMapIntensity&&(i.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(i.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(i.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(i.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(i.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(i.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(i.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(i.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(i.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(i.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(i.size=this.size),null!==this.shadowSide&&(i.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(i.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(i.blending=this.blending),0!==this.side&&(i.side=this.side),this.vertexColors&&(i.vertexColors=!0),this.opacity<1&&(i.opacity=this.opacity),!0===this.transparent&&(i.transparent=this.transparent),i.depthFunc=this.depthFunc,i.depthTest=this.depthTest,i.depthWrite=this.depthWrite,i.colorWrite=this.colorWrite,i.stencilWrite=this.stencilWrite,i.stencilWriteMask=this.stencilWriteMask,i.stencilFunc=this.stencilFunc,i.stencilRef=this.stencilRef,i.stencilFuncMask=this.stencilFuncMask,i.stencilFail=this.stencilFail,i.stencilZFail=this.stencilZFail,i.stencilZPass=this.stencilZPass,void 0!==this.rotation&&0!==this.rotation&&(i.rotation=this.rotation),!0===this.polygonOffset&&(i.polygonOffset=!0),0!==this.polygonOffsetFactor&&(i.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(i.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(i.linewidth=this.linewidth),void 0!==this.dashSize&&(i.dashSize=this.dashSize),void 0!==this.gapSize&&(i.gapSize=this.gapSize),void 0!==this.scale&&(i.scale=this.scale),!0===this.dithering&&(i.dithering=!0),this.alphaTest>0&&(i.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(i.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.forceSinglePass&&(i.forceSinglePass=this.forceSinglePass),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(i.flatShading=this.flatShading),!1===this.visible&&(i.visible=!1),!1===this.toneMapped&&(i.toneMapped=!1),!1===this.fog&&(i.fog=!1),Object.keys(this.userData).length>0&&(i.userData=this.userData),e){const e=n(t.textures),r=n(t.images);e.length>0&&(i.textures=e),r.length>0&&(i.images=r)}return i}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let i=null;if(null!==e){const t=e.length;i=new Array(t);for(let n=0;n!==t;++n)i[n]=e[n].clone()}return this.clippingPlanes=i,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}class bi extends Mi{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Zt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const Si=new oe,wi=new It;class Ti{constructor(t,e,i=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=i,this.usage=mt,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,i){t*=this.itemSize,i*=e.itemSize;for(let n=0,r=this.itemSize;n0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const i in e)void 0!==e[i]&&(t[i]=e[i]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const i=this.attributes;for(const e in i){const n=i[e];t.data.attributes[e]=n.toJSON(t.data)}const n={};let r=!1;for(const e in this.morphAttributes){const i=this.morphAttributes[e],s=[];for(let e=0,n=i.length;e0&&(n[e]=s,r=!0)}r&&(t.data.morphAttributes=n,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const i=t.index;null!==i&&this.setIndex(i.clone(e));const n=t.attributes;for(const t in n){const i=n[t];this.setAttribute(t,i.clone(e))}const r=t.morphAttributes;for(const t in r){const i=[],n=r[t];for(let t=0,r=n.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;ti.far?null:{distance:c,point:Zi.clone(),object:t}}(t,e,i,n,ki,Gi,Vi,Yi);if(c){r&&(ji.fromBufferAttribute(r,a),qi.fromBufferAttribute(r,o),Xi.fromBufferAttribute(r,l),c.uv=_i.getUV(Yi,ki,Gi,Vi,ji,qi,Xi,new It)),s&&(ji.fromBufferAttribute(s,a),qi.fromBufferAttribute(s,o),Xi.fromBufferAttribute(s,l),c.uv2=_i.getUV(Yi,ki,Gi,Vi,ji,qi,Xi,new It));const t={a:a,b:o,c:l,normal:new oe,materialIndex:0};_i.getNormal(ki,Gi,Vi,t.normal),c.face=t}return c}class $i extends zi{constructor(t=1,e=1,i=1,n=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:i,widthSegments:n,heightSegments:r,depthSegments:s};const a=this;n=Math.floor(n),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,i,n,r,s,p,m,f,g,v){const x=s/f,_=p/g,y=s/2,M=p/2,b=m/2,S=f+1,w=g+1;let T=0,A=0;const E=new oe;for(let s=0;s0?1:-1,c.push(E.x,E.y,E.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader;const i={};for(const t in this.extensions)!0===this.extensions[t]&&(i[t]=!0);return Object.keys(i).length>0&&(e.extensions=i),e}}class sn extends li{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new Ue,this.projectionMatrix=new Ue,this.projectionMatrixInverse=new Ue}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class an extends sn{constructor(t=50,e=1,i=.1,n=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=i,this.far=n,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*Mt*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*yt*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*Mt*Math.atan(Math.tan(.5*yt*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,i,n,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*yt*this.fov)/this.zoom,i=2*e,n=this.aspect*i,r=-.5*n;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*n/t,e-=s.offsetY*i/a,n*=s.width/t,i*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+n,e,e-i,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const on=-90;class ln extends li{constructor(t,e,i){super(),this.type="CubeCamera",this.renderTarget=i;const n=new an(on,1,t,e);n.layers=this.layers,n.up.set(0,1,0),n.lookAt(1,0,0),this.add(n);const r=new an(on,1,t,e);r.layers=this.layers,r.up.set(0,1,0),r.lookAt(-1,0,0),this.add(r);const s=new an(on,1,t,e);s.layers=this.layers,s.up.set(0,0,-1),s.lookAt(0,1,0),this.add(s);const a=new an(on,1,t,e);a.layers=this.layers,a.up.set(0,0,1),a.lookAt(0,-1,0),this.add(a);const o=new an(on,1,t,e);o.layers=this.layers,o.up.set(0,1,0),o.lookAt(0,0,1),this.add(o);const l=new an(on,1,t,e);l.layers=this.layers,l.up.set(0,1,0),l.lookAt(0,0,-1),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const i=this.renderTarget,[n,r,s,a,o,l]=this.children,c=t.getRenderTarget(),h=t.toneMapping,u=t.xr.enabled;t.toneMapping=0,t.xr.enabled=!1;const d=i.texture.generateMipmaps;i.texture.generateMipmaps=!1,t.setRenderTarget(i,0),t.render(e,n),t.setRenderTarget(i,1),t.render(e,r),t.setRenderTarget(i,2),t.render(e,s),t.setRenderTarget(i,3),t.render(e,a),t.setRenderTarget(i,4),t.render(e,o),i.texture.generateMipmaps=d,t.setRenderTarget(i,5),t.render(e,l),t.setRenderTarget(c),t.toneMapping=h,t.xr.enabled=u,i.texture.needsPMREMUpdate=!0}}class cn extends ee{constructor(t,e,i,n,s,a,o,l,c,h){super(t=void 0!==t?t:[],e=void 0!==e?e:r,i,n,s,a,o,l,c,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class hn extends ne{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const i={width:t,height:t,depth:1},n=[i,i,i,i,i,i];this.texture=new cn(n,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.encoding),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:f}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.encoding=e.encoding,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const i={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},n=new $i(5,5,5),r=new rn({name:"CubemapFromEquirect",uniforms:Qi(i.uniforms),vertexShader:i.vertexShader,fragmentShader:i.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const s=new Ji(n,r),a=e.minFilter;e.minFilter===v&&(e.minFilter=f);return new ln(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,i,n){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,i,n);t.setRenderTarget(r)}}const un=new oe,dn=new oe,pn=new Dt;class mn{constructor(t=new oe(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,i,n){return this.normal.set(t,e,i),this.constant=n,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,i){const n=un.subVectors(i,e).cross(dn.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(n,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(this.normal).multiplyScalar(-this.distanceToPoint(t)).add(t)}intersectLine(t,e){const i=t.delta(un),n=this.normal.dot(i);if(0===n)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/n;return r<0||r>1?null:e.copy(i).multiplyScalar(r).add(t.start)}intersectsLine(t){const e=this.distanceToPoint(t.start),i=this.distanceToPoint(t.end);return e<0&&i>0||i<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const i=e||pn.getNormalMatrix(t),n=this.coplanarPoint(un).applyMatrix4(t),r=this.normal.applyMatrix3(i).normalize();return this.constant=-n.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const fn=new Ce,gn=new oe;class vn{constructor(t=new mn,e=new mn,i=new mn,n=new mn,r=new mn,s=new mn){this.planes=[t,e,i,n,r,s]}set(t,e,i,n,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(i),a[3].copy(n),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let i=0;i<6;i++)e[i].copy(t.planes[i]);return this}setFromProjectionMatrix(t){const e=this.planes,i=t.elements,n=i[0],r=i[1],s=i[2],a=i[3],o=i[4],l=i[5],c=i[6],h=i[7],u=i[8],d=i[9],p=i[10],m=i[11],f=i[12],g=i[13],v=i[14],x=i[15];return e[0].setComponents(a-n,h-o,m-u,x-f).normalize(),e[1].setComponents(a+n,h+o,m+u,x+f).normalize(),e[2].setComponents(a+r,h+l,m+d,x+g).normalize(),e[3].setComponents(a-r,h-l,m-d,x-g).normalize(),e[4].setComponents(a-s,h-c,m-p,x-v).normalize(),e[5].setComponents(a+s,h+c,m+p,x+v).normalize(),this}intersectsObject(t){const e=t.geometry;return null===e.boundingSphere&&e.computeBoundingSphere(),fn.copy(e.boundingSphere).applyMatrix4(t.matrixWorld),this.intersectsSphere(fn)}intersectsSprite(t){return fn.center.set(0,0,0),fn.radius=.7071067811865476,fn.applyMatrix4(t.matrixWorld),this.intersectsSphere(fn)}intersectsSphere(t){const e=this.planes,i=t.center,n=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(i)0?t.max.x:t.min.x,gn.y=n.normal.y>0?t.max.y:t.min.y,gn.z=n.normal.z>0?t.max.z:t.min.z,n.distanceToPoint(gn)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let i=0;i<6;i++)if(e[i].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function xn(){let t=null,e=!1,i=null,n=null;function r(e,s){i(e,s),n=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==i&&(n=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(n),e=!1},setAnimationLoop:function(t){i=t},setContext:function(e){t=e}}}function _n(t,e){const i=e.isWebGL2,n=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),n.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const i=n.get(e);i&&(t.deleteBuffer(i.buffer),n.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=n.get(e);return void((!t||t.version 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif",iridescence_fragment:"#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},bn={common:{diffuse:{value:new Zt(16777215)},opacity:{value:1},map:{value:null},uvTransform:{value:new Dt},uv2Transform:{value:new Dt},alphaMap:{value:null},alphaTest:{value:0}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new It(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Zt(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Zt(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Dt}},sprite:{diffuse:{value:new Zt(16777215)},opacity:{value:1},center:{value:new It(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},alphaTest:{value:0},uvTransform:{value:new Dt}}},Sn={basic:{uniforms:tn([bn.common,bn.specularmap,bn.envmap,bn.aomap,bn.lightmap,bn.fog]),vertexShader:Mn.meshbasic_vert,fragmentShader:Mn.meshbasic_frag},lambert:{uniforms:tn([bn.common,bn.specularmap,bn.envmap,bn.aomap,bn.lightmap,bn.emissivemap,bn.bumpmap,bn.normalmap,bn.displacementmap,bn.fog,bn.lights,{emissive:{value:new Zt(0)}}]),vertexShader:Mn.meshlambert_vert,fragmentShader:Mn.meshlambert_frag},phong:{uniforms:tn([bn.common,bn.specularmap,bn.envmap,bn.aomap,bn.lightmap,bn.emissivemap,bn.bumpmap,bn.normalmap,bn.displacementmap,bn.fog,bn.lights,{emissive:{value:new Zt(0)},specular:{value:new Zt(1118481)},shininess:{value:30}}]),vertexShader:Mn.meshphong_vert,fragmentShader:Mn.meshphong_frag},standard:{uniforms:tn([bn.common,bn.envmap,bn.aomap,bn.lightmap,bn.emissivemap,bn.bumpmap,bn.normalmap,bn.displacementmap,bn.roughnessmap,bn.metalnessmap,bn.fog,bn.lights,{emissive:{value:new Zt(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Mn.meshphysical_vert,fragmentShader:Mn.meshphysical_frag},toon:{uniforms:tn([bn.common,bn.aomap,bn.lightmap,bn.emissivemap,bn.bumpmap,bn.normalmap,bn.displacementmap,bn.gradientmap,bn.fog,bn.lights,{emissive:{value:new Zt(0)}}]),vertexShader:Mn.meshtoon_vert,fragmentShader:Mn.meshtoon_frag},matcap:{uniforms:tn([bn.common,bn.bumpmap,bn.normalmap,bn.displacementmap,bn.fog,{matcap:{value:null}}]),vertexShader:Mn.meshmatcap_vert,fragmentShader:Mn.meshmatcap_frag},points:{uniforms:tn([bn.points,bn.fog]),vertexShader:Mn.points_vert,fragmentShader:Mn.points_frag},dashed:{uniforms:tn([bn.common,bn.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Mn.linedashed_vert,fragmentShader:Mn.linedashed_frag},depth:{uniforms:tn([bn.common,bn.displacementmap]),vertexShader:Mn.depth_vert,fragmentShader:Mn.depth_frag},normal:{uniforms:tn([bn.common,bn.bumpmap,bn.normalmap,bn.displacementmap,{opacity:{value:1}}]),vertexShader:Mn.meshnormal_vert,fragmentShader:Mn.meshnormal_frag},sprite:{uniforms:tn([bn.sprite,bn.fog]),vertexShader:Mn.sprite_vert,fragmentShader:Mn.sprite_frag},background:{uniforms:{uvTransform:{value:new Dt},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Mn.background_vert,fragmentShader:Mn.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:Mn.backgroundCube_vert,fragmentShader:Mn.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Mn.cube_vert,fragmentShader:Mn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Mn.equirect_vert,fragmentShader:Mn.equirect_frag},distanceRGBA:{uniforms:tn([bn.common,bn.displacementmap,{referencePosition:{value:new oe},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Mn.distanceRGBA_vert,fragmentShader:Mn.distanceRGBA_frag},shadow:{uniforms:tn([bn.lights,bn.fog,{color:{value:new Zt(0)},opacity:{value:1}}]),vertexShader:Mn.shadow_vert,fragmentShader:Mn.shadow_frag}};Sn.physical={uniforms:tn([Sn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatNormalScale:{value:new It(1,1)},clearcoatNormalMap:{value:null},iridescence:{value:0},iridescenceMap:{value:null},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},sheen:{value:0},sheenColor:{value:new Zt(0)},sheenColorMap:{value:null},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},transmission:{value:0},transmissionMap:{value:null},transmissionSamplerSize:{value:new It},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},attenuationDistance:{value:0},attenuationColor:{value:new Zt(0)},specularIntensity:{value:1},specularIntensityMap:{value:null},specularColor:{value:new Zt(1,1,1)},specularColorMap:{value:null}}]),vertexShader:Mn.meshphysical_vert,fragmentShader:Mn.meshphysical_frag};const wn={r:0,b:0,g:0};function Tn(t,e,i,n,r,s,a){const o=new Zt(0);let c,h,u=!0===s?0:1,d=null,p=0,m=null;function f(e,i){e.getRGB(wn,en(t)),n.buffers.color.setClear(wn.r,wn.g,wn.b,i,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),u=e,f(o,u)},getClearAlpha:function(){return u},setClearAlpha:function(t){u=t,f(o,u)},render:function(n,s){let a=!1,g=!0===s.isScene?s.background:null;if(g&&g.isTexture){g=(s.backgroundBlurriness>0?i:e).get(g)}const v=t.xr,x=v.getSession&&v.getSession();x&&"additive"===x.environmentBlendMode&&(g=null),null===g?f(o,u):g&&g.isColor&&(f(g,1),a=!0),(t.autoClear||a)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),g&&(g.isCubeTexture||g.mapping===l)?(void 0===h&&(h=new Ji(new $i(1,1,1),new rn({name:"BackgroundCubeMaterial",uniforms:Qi(Sn.backgroundCube.uniforms),vertexShader:Sn.backgroundCube.vertexShader,fragmentShader:Sn.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(t,e,i){this.matrixWorld.copyPosition(i.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(h)),h.material.uniforms.envMap.value=g,h.material.uniforms.flipEnvMap.value=g.isCubeTexture&&!1===g.isRenderTargetTexture?-1:1,h.material.uniforms.backgroundBlurriness.value=s.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=s.backgroundIntensity,h.material.toneMapped=g.encoding!==ht,d===g&&p===g.version&&m===t.toneMapping||(h.material.needsUpdate=!0,d=g,p=g.version,m=t.toneMapping),h.layers.enableAll(),n.unshift(h,h.geometry,h.material,0,0,null)):g&&g.isTexture&&(void 0===c&&(c=new Ji(new yn(2,2),new rn({name:"BackgroundMaterial",uniforms:Qi(Sn.background.uniforms),vertexShader:Sn.background.vertexShader,fragmentShader:Sn.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(c)),c.material.uniforms.t2D.value=g,c.material.uniforms.backgroundIntensity.value=s.backgroundIntensity,c.material.toneMapped=g.encoding!==ht,!0===g.matrixAutoUpdate&&g.updateMatrix(),c.material.uniforms.uvTransform.value.copy(g.matrix),d===g&&p===g.version&&m===t.toneMapping||(c.material.needsUpdate=!0,d=g,p=g.version,m=t.toneMapping),c.layers.enableAll(),n.unshift(c,c.geometry,c.material,0,0,null))}}}function An(t,e,i,n){const r=t.getParameter(34921),s=n.isWebGL2?null:e.get("OES_vertex_array_object"),a=n.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return n.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return n.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],i=[],n=[];for(let t=0;t=0){const i=r[e];let n=s[e];if(void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor)),void 0===i)return!0;if(i.attribute!==n)return!0;if(n&&i.data!==n.data)return!0;a++}}return c.attributesNum!==a||c.index!==n}(r,_,d,y),M&&function(t,e,i,n){const r={},s=e.attributes;let a=0;const o=i.getAttributes();for(const e in o){if(o[e].location>=0){let i=s[e];void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor));const n={};n.attribute=i,i&&i.data&&(n.data=i.data),r[e]=n,a++}}c.attributes=r,c.attributesNum=a,c.index=n}(r,_,d,y)}else{const t=!0===l.wireframe;c.geometry===_.id&&c.program===d.id&&c.wireframe===t||(c.geometry=_.id,c.program=d.id,c.wireframe=t,M=!0)}null!==y&&i.update(y,34963),(M||h)&&(h=!1,function(r,s,a,o){if(!1===n.isWebGL2&&(r.isInstancedMesh||o.isInstancedBufferGeometry)&&null===e.get("ANGLE_instanced_arrays"))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const n=c[e];if(n.location>=0){let s=l[e];if(void 0===s&&("instanceMatrix"===e&&r.instanceMatrix&&(s=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(s=r.instanceColor)),void 0!==s){const e=s.normalized,a=s.itemSize,l=i.get(s);if(void 0===l)continue;const c=l.buffer,h=l.type,u=l.bytesPerElement;if(s.isInterleavedBufferAttribute){const i=s.data,l=i.stride,d=s.offset;if(i.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(35633,36337).precision>0&&t.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&t instanceof WebGL2RenderingContext;let a=void 0!==i.precision?i.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===i.logarithmicDepthBuffer,h=t.getParameter(34930),u=t.getParameter(35660),d=t.getParameter(3379),p=t.getParameter(34076),m=t.getParameter(34921),f=t.getParameter(36347),g=t.getParameter(36348),v=t.getParameter(36349),x=u>0,_=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==n)return n;if(!0===e.has("EXT_texture_filter_anisotropic")){const i=e.get("EXT_texture_filter_anisotropic");n=t.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else n=0;return n},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:x,floatFragmentTextures:_,floatVertexTextures:x&&_,maxSamples:s?t.getParameter(36183):0}}function Ln(t){const e=this;let i=null,n=0,r=!1,s=!1;const a=new mn,o=new Dt,l={value:null,needsUpdate:!1};function c(t,i,n,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=n+4*s,r=i.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);e.numPlanes=n,e.numIntersection=0}();else{const t=s?0:n,e=4*t;let r=m.clippingState||null;l.value=r,r=c(u,o,e,h);for(let t=0;t!==e;++t)r[t]=i[t];m.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=t}}}function Rn(t){let e=new WeakMap;function i(t,e){return e===a?t.mapping=r:e===o&&(t.mapping=s),t}function n(t){const i=t.target;i.removeEventListener("dispose",n);const r=e.get(i);void 0!==r&&(e.delete(i),r.dispose())}return{get:function(r){if(r&&r.isTexture&&!1===r.isRenderTargetTexture){const s=r.mapping;if(s===a||s===o){if(e.has(r)){return i(e.get(r).texture,r.mapping)}{const s=r.image;if(s&&s.height>0){const a=new hn(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",n),i(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class Pn extends sn{constructor(t=-1,e=1,i=1,n=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=i,this.bottom=n,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,i,n,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=i,this.view.offsetY=n,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),i=(this.right+this.left)/2,n=(this.top+this.bottom)/2;let r=i-t,s=i+t,a=n+e,o=n-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}const In=[.125,.215,.35,.446,.526,.582],Dn=20,Nn=new Pn,On=new Zt;let zn=null;const Un=(1+Math.sqrt(5))/2,Bn=1/Un,Fn=[new oe(1,1,1),new oe(-1,1,1),new oe(1,1,-1),new oe(-1,1,-1),new oe(0,Un,Bn),new oe(0,Un,-Bn),new oe(Bn,0,Un),new oe(-Bn,0,Un),new oe(Un,Bn,0),new oe(-Un,Bn,0)];class kn{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,i=.1,n=100){zn=this._renderer.getRenderTarget(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,i,n,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=Wn(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=Hn(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let t=0;tt-4?o=In[a-t+4-1]:0===a&&(o=0),n.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),x=new Float32Array(f*p*d),_=new Float32Array(g*p*d);for(let t=0;t2?0:-1,n=[e,i,0,e+2/3,i,0,e+2/3,i+1,0,e,i,0,e+2/3,i+1,0,e,i+1,0];v.set(n,m*p*t),x.set(u,f*p*t);const r=[t,t,t,t,t,t];_.set(r,g*p*t)}const y=new zi;y.setAttribute("position",new Ti(v,m)),y.setAttribute("uv",new Ti(x,f)),y.setAttribute("faceIndex",new Ti(_,g)),e.push(y),r>4&&r--}return{lodPlanes:e,sizeLods:i,sigmas:n}}(n)),this._blurMaterial=function(t,e,i){const n=new Float32Array(Dn),r=new oe(0,1,0),s=new rn({name:"SphericalGaussianBlur",defines:{n:Dn,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/i,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:jn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1});return s}(n,t,e)}return n}_compileMaterial(t){const e=new Ji(this._lodPlanes[0],t);this._renderer.compile(e,Nn)}_sceneToCubeUV(t,e,i,n){const r=new an(90,1,e,i),s=[1,-1,1,1,1,1],a=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(On),o.toneMapping=0,o.autoClear=!1;const h=new bi({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new Ji(new $i,h);let d=!1;const p=t.background;p?p.isColor&&(h.color.copy(p),t.background=null,d=!0):(h.color.copy(On),d=!0);for(let e=0;e<6;e++){const i=e%3;0===i?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===i?(r.up.set(0,0,s[e]),r.lookAt(0,a[e],0)):(r.up.set(0,s[e],0),r.lookAt(0,0,a[e]));const l=this._cubeSize;Vn(n,i*l,e>2?l:0,l,l),o.setRenderTarget(n),d&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=p}_textureToCubeUV(t,e){const i=this._renderer,n=t.mapping===r||t.mapping===s;n?(null===this._cubemapMaterial&&(this._cubemapMaterial=Wn()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=Hn());const a=n?this._cubemapMaterial:this._equirectMaterial,o=new Ji(this._lodPlanes[0],a);a.uniforms.envMap.value=t;const l=this._cubeSize;Vn(e,0,0,3*l,2*l),i.setRenderTarget(e),i.render(o,Nn)}_applyPMREM(t){const e=this._renderer,i=e.autoClear;e.autoClear=!1;for(let e=1;eDn&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const f=[];let g=0;for(let t=0;tv-4?n-v+4:0),4*(this._cubeSize-x),3*x,2*x),o.setRenderTarget(e),o.render(c,Nn)}}function Gn(t,e,i){const n=new ne(t,e,i);return n.texture.mapping=l,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function Vn(t,e,i,n,r){t.viewport.set(e,i,n,r),t.scissor.set(e,i,n,r)}function Hn(){return new rn({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:jn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function Wn(){return new rn({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:jn(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:0,depthTest:!1,depthWrite:!1})}function jn(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function qn(t){let e=new WeakMap,i=null;function n(t){const i=t.target;i.removeEventListener("dispose",n);const r=e.get(i);void 0!==r&&(e.delete(i),r.dispose())}return{get:function(l){if(l&&l.isTexture){const c=l.mapping,h=c===a||c===o,u=c===r||c===s;if(h||u){if(l.isRenderTargetTexture&&!0===l.needsPMREMUpdate){l.needsPMREMUpdate=!1;let n=e.get(l);return null===i&&(i=new kn(t)),n=h?i.fromEquirectangular(l,n):i.fromCubemap(l,n),e.set(l,n),n.texture}if(e.has(l))return e.get(l).texture;{const r=l.image;if(h&&r&&r.height>0||u&&r&&function(t){let e=0;const i=6;for(let n=0;ne.maxTextureSize&&(E=Math.ceil(A/e.maxTextureSize),A=e.maxTextureSize);const C=new Float32Array(A*E*4*m),L=new re(C,A,E,m);L.type=M,L.needsUpdate=!0;const R=4*T;for(let I=0;I0)return t;const r=e*i;let s=sr[r];if(void 0===s&&(s=new Float32Array(r),sr[r]=s),0!==e){n.toArray(s,0);for(let n=1,r=0;n!==e;++n)r+=i,t[n].toArray(s,r)}return s}function ur(t,e){if(t.length!==e.length)return!1;for(let i=0,n=t.length;i":" "} ${r}: ${i[t]}`)}return n.join("\n")}(t.getShaderSource(e),n)}return r}function ls(t,e){const i=function(t){switch(t){case ct:return["Linear","( value )"];case ht:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported encoding:",t),["Linear","( value )"]}}(e);return"vec4 "+t+"( vec4 value ) { return LinearTo"+i[0]+i[1]+"; }"}function cs(t,e){let i;switch(e){case 1:i="Linear";break;case 2:i="Reinhard";break;case 3:i="OptimizedCineon";break;case 4:i="ACESFilmic";break;case 5:i="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),i="Linear"}return"vec3 "+t+"( vec3 color ) { return "+i+"ToneMapping( color ); }"}function hs(t){return""!==t}function us(t,e){const i=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,i).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function ds(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const ps=/^[ \t]*#include +<([\w\d./]+)>/gm;function ms(t){return t.replace(ps,fs)}function fs(t,e){const i=Mn[e];if(void 0===i)throw new Error("Can not resolve #include <"+e+">");return ms(i)}const gs=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function vs(t){return t.replace(gs,xs)}function xs(t,e,i,n){let r="";for(let t=parseInt(e);t0&&(_+="\n"),y=[g,v].filter(hs).join("\n"),y.length>0&&(y+="\n")):(_=[_s(i),"#define SHADER_NAME "+i.shaderName,v,i.instancing?"#define USE_INSTANCING":"",i.instancingColor?"#define USE_INSTANCING_COLOR":"",i.supportsVertexTextures?"#define VERTEX_TEXTURES":"",i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+p:"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.displacementMap&&i.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.flatShading?"#define FLAT_SHADED":"",i.skinning?"#define USE_SKINNING":"",i.morphTargets?"#define USE_MORPHTARGETS":"",i.morphNormals&&!1===i.flatShading?"#define USE_MORPHNORMALS":"",i.morphColors&&i.isWebGL2?"#define USE_MORPHCOLORS":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+i.morphTextureStride:"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_COUNT "+i.morphTargetsCount:"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.sizeAttenuation?"#define USE_SIZEATTENUATION":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(hs).join("\n"),y=[g,_s(i),"#define SHADER_NAME "+i.shaderName,v,i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.matcap?"#define USE_MATCAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+d:"",i.envMap?"#define "+p:"",i.envMap?"#define "+m:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMap&&i.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",i.normalMap&&i.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",i.clearcoat?"#define USE_CLEARCOAT":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescence?"#define USE_IRIDESCENCE":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularIntensityMap?"#define USE_SPECULARINTENSITYMAP":"",i.specularColorMap?"#define USE_SPECULARCOLORMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.alphaTest?"#define USE_ALPHATEST":"",i.sheen?"#define USE_SHEEN":"",i.sheenColorMap?"#define USE_SHEENCOLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEENROUGHNESSMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",i.vertexTangents?"#define USE_TANGENT":"",i.vertexColors||i.instancingColor?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUvs?"#define USE_UV":"",i.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",i.gradientMap?"#define USE_GRADIENTMAP":"",i.flatShading?"#define FLAT_SHADED":"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+u:"",i.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",i.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==i.toneMapping?"#define TONE_MAPPING":"",0!==i.toneMapping?Mn.tonemapping_pars_fragment:"",0!==i.toneMapping?cs("toneMapping",i.toneMapping):"",i.dithering?"#define DITHERING":"",i.opaque?"#define OPAQUE":"",Mn.encodings_pars_fragment,ls("linearToOutputTexel",i.outputEncoding),i.useDepthPacking?"#define DEPTH_PACKING "+i.depthPacking:"","\n"].filter(hs).join("\n")),c=ms(c),c=us(c,i),c=ds(c,i),h=ms(h),h=us(h,i),h=ds(h,i),c=vs(c),h=vs(h),i.isWebGL2&&!0!==i.isRawShaderMaterial&&(M="#version 300 es\n",_=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+_,y=["#define varying in",i.glslVersion===ft?"":"layout(location = 0) out highp vec4 pc_fragColor;",i.glslVersion===ft?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+y);const b=M+y+h,S=ss(a,35633,M+_+c),w=ss(a,35632,b);if(a.attachShader(x,S),a.attachShader(x,w),void 0!==i.index0AttributeName?a.bindAttribLocation(x,0,i.index0AttributeName):!0===i.morphTargets&&a.bindAttribLocation(x,0,"position"),a.linkProgram(x),t.debug.checkShaderErrors){const t=a.getProgramInfoLog(x).trim(),e=a.getShaderInfoLog(S).trim(),i=a.getShaderInfoLog(w).trim();let n=!0,r=!0;if(!1===a.getProgramParameter(x,35714)){n=!1;const e=os(a,S,"vertex"),i=os(a,w,"fragment");console.error("THREE.WebGLProgram: Shader Error "+a.getError()+" - VALIDATE_STATUS "+a.getProgramParameter(x,35715)+"\n\nProgram Info Log: "+t+"\n"+e+"\n"+i)}else""!==t?console.warn("THREE.WebGLProgram: Program Info Log:",t):""!==e&&""!==i||(r=!1);r&&(this.diagnostics={runnable:n,programLog:t,vertexShader:{log:e,prefix:_},fragmentShader:{log:i,prefix:y}})}let T,A;return a.deleteShader(S),a.deleteShader(w),this.getUniforms=function(){return void 0===T&&(T=new rs(a,x)),T},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const i={},n=t.getProgramParameter(e,35721);for(let r=0;r0,D=s.clearcoat>0,N=s.iridescence>0;return{isWebGL2:u,shaderID:S,shaderName:s.type,vertexShader:A,fragmentShader:E,defines:s.defines,customVertexShaderID:C,customFragmentShaderID:L,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:m,instancing:!0===v.isInstancedMesh,instancingColor:!0===v.isInstancedMesh&&null!==v.instanceColor,supportsVertexTextures:p,outputEncoding:null===P?t.outputEncoding:!0===P.isXRRenderTarget?P.texture.encoding:ct,map:!!s.map,matcap:!!s.matcap,envMap:!!M,envMapMode:M&&M.mapping,envMapCubeUVHeight:b,lightMap:!!s.lightMap,aoMap:!!s.aoMap,emissiveMap:!!s.emissiveMap,bumpMap:!!s.bumpMap,normalMap:!!s.normalMap,objectSpaceNormalMap:1===s.normalMapType,tangentSpaceNormalMap:0===s.normalMapType,decodeVideoTexture:!!s.map&&!0===s.map.isVideoTexture&&s.map.encoding===ht,clearcoat:D,clearcoatMap:D&&!!s.clearcoatMap,clearcoatRoughnessMap:D&&!!s.clearcoatRoughnessMap,clearcoatNormalMap:D&&!!s.clearcoatNormalMap,iridescence:N,iridescenceMap:N&&!!s.iridescenceMap,iridescenceThicknessMap:N&&!!s.iridescenceThicknessMap,displacementMap:!!s.displacementMap,roughnessMap:!!s.roughnessMap,metalnessMap:!!s.metalnessMap,specularMap:!!s.specularMap,specularIntensityMap:!!s.specularIntensityMap,specularColorMap:!!s.specularColorMap,opaque:!1===s.transparent&&1===s.blending,alphaMap:!!s.alphaMap,alphaTest:I,gradientMap:!!s.gradientMap,sheen:s.sheen>0,sheenColorMap:!!s.sheenColorMap,sheenRoughnessMap:!!s.sheenRoughnessMap,transmission:s.transmission>0,transmissionMap:!!s.transmissionMap,thicknessMap:!!s.thicknessMap,combine:s.combine,vertexTangents:!!s.normalMap&&!!_.attributes.tangent,vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!_.attributes.color&&4===_.attributes.color.itemSize,vertexUvs:!!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatMap||s.clearcoatRoughnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.displacementMap||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheenColorMap||s.sheenRoughnessMap),uvsVertexOnly:!(s.map||s.bumpMap||s.normalMap||s.specularMap||s.alphaMap||s.emissiveMap||s.roughnessMap||s.metalnessMap||s.clearcoatNormalMap||s.iridescenceMap||s.iridescenceThicknessMap||s.transmission>0||s.transmissionMap||s.thicknessMap||s.specularIntensityMap||s.specularColorMap||s.sheen>0||s.sheenColorMap||s.sheenRoughnessMap||!s.displacementMap),fog:!!x,useFog:!0===s.fog,fogExp2:x&&x.isFogExp2,flatShading:!!s.flatShading,sizeAttenuation:s.sizeAttenuation,logarithmicDepthBuffer:d,skinning:!0===v.isSkinnedMesh,morphTargets:void 0!==_.morphAttributes.position,morphNormals:void 0!==_.morphAttributes.normal,morphColors:void 0!==_.morphAttributes.color,morphTargetsCount:T,morphTextureStride:R,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:0,physicallyCorrectLights:t.physicallyCorrectLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:1===s.side,useDepthPacking:!!s.depthPacking,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:s.extensions&&s.extensions.derivatives,extensionFragDepth:s.extensions&&s.extensions.fragDepth,extensionDrawBuffers:s.extensions&&s.extensions.drawBuffers,extensionShaderTextureLOD:s.extensions&&s.extensions.shaderTextureLOD,rendererExtensionFragDepth:u||n.has("EXT_frag_depth"),rendererExtensionDrawBuffers:u||n.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:u||n.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const i=[];if(e.shaderID?i.push(e.shaderID):(i.push(e.customVertexShaderID),i.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)i.push(t),i.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputEncoding),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.combine),t.push(e.vertexUvs),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numSpotLightMaps),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.numSpotLightShadowsWithMaps),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(i,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.map&&o.enable(4);e.matcap&&o.enable(5);e.envMap&&o.enable(6);e.lightMap&&o.enable(7);e.aoMap&&o.enable(8);e.emissiveMap&&o.enable(9);e.bumpMap&&o.enable(10);e.normalMap&&o.enable(11);e.objectSpaceNormalMap&&o.enable(12);e.tangentSpaceNormalMap&&o.enable(13);e.clearcoat&&o.enable(14);e.clearcoatMap&&o.enable(15);e.clearcoatRoughnessMap&&o.enable(16);e.clearcoatNormalMap&&o.enable(17);e.iridescence&&o.enable(18);e.iridescenceMap&&o.enable(19);e.iridescenceThicknessMap&&o.enable(20);e.displacementMap&&o.enable(21);e.specularMap&&o.enable(22);e.roughnessMap&&o.enable(23);e.metalnessMap&&o.enable(24);e.gradientMap&&o.enable(25);e.alphaMap&&o.enable(26);e.alphaTest&&o.enable(27);e.vertexColors&&o.enable(28);e.vertexAlphas&&o.enable(29);e.vertexUvs&&o.enable(30);e.vertexTangents&&o.enable(31);e.uvsVertexOnly&&o.enable(32);t.push(o.mask),o.disableAll(),e.fog&&o.enable(0);e.useFog&&o.enable(1);e.flatShading&&o.enable(2);e.logarithmicDepthBuffer&&o.enable(3);e.skinning&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.morphColors&&o.enable(7);e.premultipliedAlpha&&o.enable(8);e.shadowMapEnabled&&o.enable(9);e.physicallyCorrectLights&&o.enable(10);e.doubleSided&&o.enable(11);e.flipSided&&o.enable(12);e.useDepthPacking&&o.enable(13);e.dithering&&o.enable(14);e.specularIntensityMap&&o.enable(15);e.specularColorMap&&o.enable(16);e.transmission&&o.enable(17);e.transmissionMap&&o.enable(18);e.thicknessMap&&o.enable(19);e.sheen&&o.enable(20);e.sheenColorMap&&o.enable(21);e.sheenRoughnessMap&&o.enable(22);e.decodeVideoTexture&&o.enable(23);e.opaque&&o.enable(24);t.push(o.mask)}(i,e),i.push(t.outputEncoding)),i.push(e.customProgramCacheKey),i.join()},getUniforms:function(t){const e=f[t.type];let i;if(e){const t=Sn[e];i=nn.clone(t.uniforms)}else i=t.uniforms;return i},acquireProgram:function(e,i){let n;for(let t=0,e=h.length;t0?n.push(h):!0===a.transparent?r.push(h):i.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?n.unshift(h):!0===a.transparent?r.unshift(h):i.unshift(h)},finish:function(){for(let i=e,n=t.length;i1&&i.sort(t||As),n.length>1&&n.sort(e||Es),r.length>1&&r.sort(e||Es)}}}function Ls(){let t=new WeakMap;return{get:function(e,i){const n=t.get(e);let r;return void 0===n?(r=new Cs,t.set(e,[r])):i>=n.length?(r=new Cs,n.push(r)):r=n[i],r},dispose:function(){t=new WeakMap}}}function Rs(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":i={direction:new oe,color:new Zt};break;case"SpotLight":i={position:new oe,direction:new oe,color:new Zt,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":i={position:new oe,color:new Zt,distance:0,decay:0};break;case"HemisphereLight":i={direction:new oe,skyColor:new Zt,groundColor:new Zt};break;case"RectAreaLight":i={color:new Zt,position:new oe,halfWidth:new oe,halfHeight:new oe}}return t[e.id]=i,i}}}let Ps=0;function Is(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function Ds(t,e){const i=new Rs,n=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let i;switch(e.type){case"DirectionalLight":case"SpotLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new It};break;case"PointLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new It,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=i,i}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0};for(let t=0;t<9;t++)r.probe.push(new oe);const s=new oe,a=new Ue,o=new Ue;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,x=0,_=0;s.sort(Is);const y=!0!==a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=bn.LTC_FLOAT_1,r.rectAreaLTC2=bn.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=bn.LTC_HALF_1,r.rectAreaLTC2=bn.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const M=r.hash;M.directionalLength===h&&M.pointLength===u&&M.spotLength===d&&M.rectAreaLength===p&&M.hemiLength===m&&M.numDirectionalShadows===f&&M.numPointShadows===g&&M.numSpotShadows===v&&M.numSpotMaps===x||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotLightMatrix.length=v+x-_,r.spotLightMap.length=x,r.numSpotLightShadowsWithMaps=_,M.directionalLength=h,M.pointLength=u,M.spotLength=d,M.rectAreaLength=p,M.hemiLength=m,M.numDirectionalShadows=f,M.numPointShadows=g,M.numSpotShadows=v,M.numSpotMaps=x,r.version=Ps++)},setupView:function(t,e){let i=0,n=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=s.length?(a=new Ns(t,e),s.push(a)):a=s[r],a},dispose:function(){i=new WeakMap}}}class zs extends Mi{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Us extends Mi{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.referencePosition=new oe,this.nearDistance=1,this.farDistance=1e3,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.referencePosition.copy(t.referencePosition),this.nearDistance=t.nearDistance,this.farDistance=t.farDistance,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function Bs(t,e,i){let n=new vn;const r=new It,s=new It,a=new ie,o=new zs({depthPacking:3201}),l=new Us,c={},h=i.maxTextureSize,u={0:1,1:0,2:2},p=new rn({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new It},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),m=p.clone();m.defines.HORIZONTAL_PASS=1;const f=new zi;f.setAttribute("position",new Ti(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const g=new Ji(f,p),v=this;function x(i,n){const s=e.update(g);p.defines.VSM_SAMPLES!==i.blurSamples&&(p.defines.VSM_SAMPLES=i.blurSamples,m.defines.VSM_SAMPLES=i.blurSamples,p.needsUpdate=!0,m.needsUpdate=!0),null===i.mapPass&&(i.mapPass=new ne(r.x,r.y)),p.uniforms.shadow_pass.value=i.map.texture,p.uniforms.resolution.value=i.mapSize,p.uniforms.radius.value=i.radius,t.setRenderTarget(i.mapPass),t.clear(),t.renderBufferDirect(n,null,s,p,g,null),m.uniforms.shadow_pass.value=i.mapPass.texture,m.uniforms.resolution.value=i.mapSize,m.uniforms.radius.value=i.radius,t.setRenderTarget(i.map),t.clear(),t.renderBufferDirect(n,null,s,m,g,null)}function _(e,i,n,r,s,a){let h=null;const d=!0===n.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(void 0!==d)h=d;else if(h=!0===n.isPointLight?l:o,t.localClippingEnabled&&!0===i.clipShadows&&Array.isArray(i.clippingPlanes)&&0!==i.clippingPlanes.length||i.displacementMap&&0!==i.displacementScale||i.alphaMap&&i.alphaTest>0||i.map&&i.alphaTest>0){const t=h.uuid,e=i.uuid;let n=c[t];void 0===n&&(n={},c[t]=n);let r=n[e];void 0===r&&(r=h.clone(),n[e]=r),h=r}return h.visible=i.visible,h.wireframe=i.wireframe,h.side=3===a?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:u[i.side],h.alphaMap=i.alphaMap,h.alphaTest=i.alphaTest,h.map=i.map,h.clipShadows=i.clipShadows,h.clippingPlanes=i.clippingPlanes,h.clipIntersection=i.clipIntersection,h.displacementMap=i.displacementMap,h.displacementScale=i.displacementScale,h.displacementBias=i.displacementBias,h.wireframeLinewidth=i.wireframeLinewidth,h.linewidth=i.linewidth,!0===n.isPointLight&&!0===h.isMeshDistanceMaterial&&(h.referencePosition.setFromMatrixPosition(n.matrixWorld),h.nearDistance=r,h.farDistance=s),h}function y(i,r,s,a,o){if(!1===i.visible)return;if(i.layers.test(r.layers)&&(i.isMesh||i.isLine||i.isPoints)&&(i.castShadow||i.receiveShadow&&3===o)&&(!i.frustumCulled||n.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,i.matrixWorld);const n=e.update(i),r=i.material;if(Array.isArray(r)){const e=n.groups;for(let l=0,c=e.length;lh||r.y>h)&&(r.x>h&&(s.x=Math.floor(h/m.x),r.x=s.x*m.x,u.mapSize.x=s.x),r.y>h&&(s.y=Math.floor(h/m.y),r.y=s.y*m.y,u.mapSize.y=s.y)),null===u.map){const t=3!==this.type?{minFilter:d,magFilter:d}:{};u.map=new ne(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const f=u.getViewportCount();for(let t=0;t=1):-1!==I.indexOf("OpenGL ES")&&(P=parseFloat(/^OpenGL ES (\d)/.exec(I)[1]),R=P>=2);let D=null,N={};const O=t.getParameter(3088),z=t.getParameter(2978),U=(new ie).fromArray(O),B=(new ie).fromArray(z);function F(e,i,n){const r=new Uint8Array(4),s=t.createTexture();t.bindTexture(e,s),t.texParameteri(e,10241,9728),t.texParameteri(e,10240,9728);for(let e=0;en||t.height>n)&&(r=n/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const n=e?Ct:Math.floor,s=n(r*t.width),a=n(r*t.height);void 0===D&&(D=z(s,a));const o=i?z(s,a):D;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function B(t){return At(t.width)&&At(t.height)}function F(t,e){return t.generateMipmaps&&e&&t.minFilter!==d&&t.minFilter!==f}function k(e){t.generateMipmap(e)}function G(i,n,r,s,a=!1){if(!1===o)return n;if(null!==i){if(void 0!==t[i])return t[i];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+i+"'")}let l=n;return 6403===n&&(5126===r&&(l=33326),5131===r&&(l=33325),5121===r&&(l=33321)),33319===n&&(5126===r&&(l=33328),5131===r&&(l=33327),5121===r&&(l=33323)),6408===n&&(5126===r&&(l=34836),5131===r&&(l=34842),5121===r&&(l=s===ht&&!1===a?35907:32856),32819===r&&(l=32854),32820===r&&(l=32855)),33325!==l&&33326!==l&&33327!==l&&33328!==l&&34842!==l&&34836!==l||e.get("EXT_color_buffer_float"),l}function V(t,e,i){return!0===F(t,i)||t.isFramebufferTexture&&t.minFilter!==d&&t.minFilter!==f?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function H(t){return t===d||t===p||t===m?9728:9729}function W(t){const e=t.target;e.removeEventListener("dispose",W),function(t){const e=n.get(t);if(void 0===e.__webglInit)return;const i=t.source,r=N.get(i);if(r){const n=r[e.__cacheKey];n.usedTimes--,0===n.usedTimes&&q(t),0===Object.keys(r).length&&N.delete(i)}n.remove(t)}(e),e.isVideoTexture&&I.delete(e)}function j(e){const i=e.target;i.removeEventListener("dispose",j),function(e){const i=e.texture,r=n.get(e),s=n.get(i);void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else{if(t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e0&&r.__version!==t.version){const i=t.image;if(null===i)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==i.complete)return void Q(r,t,e);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}i.bindTexture(3553,r.__webglTexture,33984+e)}const Z={[c]:10497,[h]:33071,[u]:33648},J={[d]:9728,[p]:9984,[m]:9986,[f]:9729,[g]:9985,[v]:9987};function K(i,s,a){if(a?(t.texParameteri(i,10242,Z[s.wrapS]),t.texParameteri(i,10243,Z[s.wrapT]),32879!==i&&35866!==i||t.texParameteri(i,32882,Z[s.wrapR]),t.texParameteri(i,10240,J[s.magFilter]),t.texParameteri(i,10241,J[s.minFilter])):(t.texParameteri(i,10242,33071),t.texParameteri(i,10243,33071),32879!==i&&35866!==i||t.texParameteri(i,32882,33071),s.wrapS===h&&s.wrapT===h||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(i,10240,H(s.magFilter)),t.texParameteri(i,10241,H(s.minFilter)),s.minFilter!==d&&s.minFilter!==f&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),!0===e.has("EXT_texture_filter_anisotropic")){const a=e.get("EXT_texture_filter_anisotropic");if(s.magFilter===d)return;if(s.minFilter!==m&&s.minFilter!==v)return;if(s.type===M&&!1===e.has("OES_texture_float_linear"))return;if(!1===o&&s.type===b&&!1===e.has("OES_texture_half_float_linear"))return;(s.anisotropy>1||n.get(s).__currentAnisotropy)&&(t.texParameterf(i,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),n.get(s).__currentAnisotropy=s.anisotropy)}}function $(e,i){let n=!1;void 0===e.__webglInit&&(e.__webglInit=!0,i.addEventListener("dispose",W));const r=i.source;let s=N.get(r);void 0===s&&(s={},N.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.wrapR||0),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.encoding),e.join()}(i);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,n=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&q(i)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return n}function Q(e,r,a){let l=3553;(r.isDataArrayTexture||r.isCompressedArrayTexture)&&(l=35866),r.isData3DTexture&&(l=32879);const c=$(e,r),u=r.source;i.bindTexture(l,e.__webglTexture,33984+a);const p=n.get(u);if(u.version!==p.__version||!0===c){i.activeTexture(33984+a),t.pixelStorei(37440,r.flipY),t.pixelStorei(37441,r.premultiplyAlpha),t.pixelStorei(3317,r.unpackAlignment),t.pixelStorei(37443,0);const e=function(t){return!o&&(t.wrapS!==h||t.wrapT!==h||t.minFilter!==d&&t.minFilter!==f)}(r)&&!1===B(r.image);let n=U(r.image,e,!1,C);n=st(r,n);const m=B(n)||o,g=s.convert(r.format,r.encoding);let v,x=s.convert(r.type),b=G(r.internalFormat,g,x,r.encoding,r.isVideoTexture);K(l,r,m);const E=r.mipmaps,L=o&&!0!==r.isVideoTexture,R=void 0===p.__version||!0===c,P=V(r,n,m);if(r.isDepthTexture)b=6402,o?b=r.type===M?36012:r.type===y?33190:r.type===S?35056:33189:r.type===M&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),r.format===T&&6402===b&&r.type!==_&&r.type!==y&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=y,x=s.convert(r.type)),r.format===A&&6402===b&&(b=34041,r.type!==S&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=S,x=s.convert(r.type))),R&&(L?i.texStorage2D(3553,1,b,n.width,n.height):i.texImage2D(3553,0,b,n.width,n.height,0,g,x,null));else if(r.isDataTexture)if(E.length>0&&m){L&&R&&i.texStorage2D(3553,P,b,E[0].width,E[0].height);for(let t=0,e=E.length;t>=1,e>>=1}}else if(E.length>0&&m){L&&R&&i.texStorage2D(3553,P,b,E[0].width,E[0].height);for(let t=0,e=E.length;t=34069&&l<=34074)&&t.framebufferTexture2D(36160,o,l,n.get(a).__webglTexture,0),i.bindFramebuffer(36160,null)}function et(e,i,n){if(t.bindRenderbuffer(36161,e),i.depthBuffer&&!i.stencilBuffer){let r=33189;if(n||rt(i)){const e=i.depthTexture;e&&e.isDepthTexture&&(e.type===M?r=36012:e.type===y&&(r=33190));const n=nt(i);rt(i)?R.renderbufferStorageMultisampleEXT(36161,n,r,i.width,i.height):t.renderbufferStorageMultisample(36161,n,r,i.width,i.height)}else t.renderbufferStorage(36161,r,i.width,i.height);t.framebufferRenderbuffer(36160,36096,36161,e)}else if(i.depthBuffer&&i.stencilBuffer){const r=nt(i);n&&!1===rt(i)?t.renderbufferStorageMultisample(36161,r,35056,i.width,i.height):rt(i)?R.renderbufferStorageMultisampleEXT(36161,r,35056,i.width,i.height):t.renderbufferStorage(36161,34041,i.width,i.height),t.framebufferRenderbuffer(36160,33306,36161,e)}else{const e=!0===i.isWebGLMultipleRenderTargets?i.texture:[i.texture];for(let r=0;r0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==i.__useRenderToTexture}function st(t,i){const n=t.encoding,r=t.format,s=t.type;return!0===t.isCompressedTexture||!0===t.isVideoTexture||t.format===gt||n!==ct&&(n===ht?!1===o?!0===e.has("EXT_sRGB")&&r===w?(t.format=gt,t.minFilter=f,t.generateMipmaps=!1):i=Kt.sRGBToLinear(i):r===w&&s===x||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture encoding:",n)),i}this.allocateTextureUnit=function(){const t=X;return t>=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),X+=1,t},this.resetTextureUnits=function(){X=0},this.setTexture2D=Y,this.setTexture2DArray=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?Q(r,t,e):i.bindTexture(35866,r.__webglTexture,33984+e)},this.setTexture3D=function(t,e){const r=n.get(t);t.version>0&&r.__version!==t.version?Q(r,t,e):i.bindTexture(32879,r.__webglTexture,33984+e)},this.setTextureCube=function(e,r){const a=n.get(e);e.version>0&&a.__version!==e.version?function(e,r,a){if(6!==r.image.length)return;const l=$(e,r),c=r.source;i.bindTexture(34067,e.__webglTexture,33984+a);const h=n.get(c);if(c.version!==h.__version||!0===l){i.activeTexture(33984+a),t.pixelStorei(37440,r.flipY),t.pixelStorei(37441,r.premultiplyAlpha),t.pixelStorei(3317,r.unpackAlignment),t.pixelStorei(37443,0);const e=r.isCompressedTexture||r.image[0].isCompressedTexture,n=r.image[0]&&r.image[0].isDataTexture,u=[];for(let t=0;t<6;t++)u[t]=e||n?n?r.image[t].image:r.image[t]:U(r.image[t],!1,!0,E),u[t]=st(r,u[t]);const d=u[0],p=B(d)||o,m=s.convert(r.format,r.encoding),f=s.convert(r.type),g=G(r.internalFormat,m,f,r.encoding),v=o&&!0!==r.isVideoTexture,x=void 0===h.__version||!0===l;let _,y=V(r,d,p);if(K(34067,r,p),e){v&&x&&i.texStorage2D(34067,y,g,d.width,d.height);for(let t=0;t<6;t++){_=u[t].mipmaps;for(let e=0;e<_.length;e++){const n=_[e];r.format!==w?null!==m?v?i.compressedTexSubImage2D(34069+t,e,0,0,n.width,n.height,m,n.data):i.compressedTexImage2D(34069+t,e,g,n.width,n.height,0,n.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):v?i.texSubImage2D(34069+t,e,0,0,n.width,n.height,m,f,n.data):i.texImage2D(34069+t,e,g,n.width,n.height,0,m,f,n.data)}}}else{_=r.mipmaps,v&&x&&(_.length>0&&y++,i.texStorage2D(34067,y,g,u[0].width,u[0].height));for(let t=0;t<6;t++)if(n){v?i.texSubImage2D(34069+t,0,0,0,u[t].width,u[t].height,m,f,u[t].data):i.texImage2D(34069+t,0,g,u[t].width,u[t].height,0,m,f,u[t].data);for(let e=0;e<_.length;e++){const n=_[e].image[t].image;v?i.texSubImage2D(34069+t,e+1,0,0,n.width,n.height,m,f,n.data):i.texImage2D(34069+t,e+1,g,n.width,n.height,0,m,f,n.data)}}else{v?i.texSubImage2D(34069+t,0,0,0,m,f,u[t]):i.texImage2D(34069+t,0,g,m,f,u[t]);for(let e=0;e<_.length;e++){const n=_[e];v?i.texSubImage2D(34069+t,e+1,0,0,m,f,n.image[t]):i.texImage2D(34069+t,e+1,g,m,f,n.image[t])}}}F(r,p)&&k(34067),h.__version=c.version,r.onUpdate&&r.onUpdate(r)}e.__version=r.version}(a,e,r):i.bindTexture(34067,a.__webglTexture,33984+r)},this.rebindTextures=function(t,e,i){const r=n.get(t);void 0!==e&&tt(r.__webglFramebuffer,t,t.texture,36064,3553),void 0!==i&&it(t)},this.setupRenderTarget=function(e){const l=e.texture,c=n.get(e),h=n.get(l);e.addEventListener("dispose",j),!0!==e.isWebGLMultipleRenderTargets&&(void 0===h.__webglTexture&&(h.__webglTexture=t.createTexture()),h.__version=l.version,a.memory.textures++);const u=!0===e.isWebGLCubeRenderTarget,d=!0===e.isWebGLMultipleRenderTargets,p=B(e)||o;if(u){c.__webglFramebuffer=[];for(let e=0;e<6;e++)c.__webglFramebuffer[e]=t.createFramebuffer()}else{if(c.__webglFramebuffer=t.createFramebuffer(),d)if(r.drawBuffers){const i=e.texture;for(let e=0,r=i.length;e0&&!1===rt(e)){const n=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],i.bindFramebuffer(36160,c.__webglMultisampledFramebuffer);for(let i=0;i0&&!1===rt(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=16384;const l=[],c=e.stencilBuffer?33306:36096,h=n.get(e),u=!0===e.isWebGLMultipleRenderTargets;if(u)for(let e=0;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,i),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==a&&(n=e.getPose(t.targetRaySpace,i),null===n&&null!==r&&(n=r),null!==n&&(a.matrix.fromArray(n.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),n.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(n.linearVelocity)):a.hasLinearVelocity=!1,n.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(n.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Ws)))}return null!==a&&(a.visible=null!==n),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const i=new Hs;i.matrixAutoUpdate=!1,i.visible=!1,t.joints[e.jointName]=i,t.add(i)}return t.joints[e.jointName]}}class qs extends ee{constructor(t,e,i,n,r,s,a,o,l,c){if((c=void 0!==c?c:T)!==T&&c!==A)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===i&&c===T&&(i=y),void 0===i&&c===A&&(i=S),super(null,n,r,s,a,o,c,i,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:d,this.minFilter=void 0!==o?o:d,this.flipY=!1,this.generateMipmaps=!1}}class Xs extends vt{constructor(t,e){super();const i=this;let n=null,r=1,s=null,a="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const m=e.getContextAttributes();let f=null,g=null;const v=[],_=[],M=new Set,b=new Map,E=new an;E.layers.enable(1),E.viewport=new ie;const C=new an;C.layers.enable(2),C.viewport=new ie;const L=[E,C],R=new Vs;R.layers.enable(1),R.layers.enable(2);let P=null,I=null;function D(t){const e=_.indexOf(t.inputSource);if(-1===e)return;const i=v[e];void 0!==i&&i.dispatchEvent({type:t.type,data:t.inputSource})}function N(){n.removeEventListener("select",D),n.removeEventListener("selectstart",D),n.removeEventListener("selectend",D),n.removeEventListener("squeeze",D),n.removeEventListener("squeezestart",D),n.removeEventListener("squeezeend",D),n.removeEventListener("end",N),n.removeEventListener("inputsourceschange",O);for(let t=0;t=0&&(_[n]=null,v[n].disconnect(i))}for(let e=0;e=_.length){_.push(i),n=t;break}if(null===_[t]){_[t]=i,n=t;break}}if(-1===n)break}const r=v[n];r&&r.connect(i)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(t){let e=v[t];return void 0===e&&(e=new js,v[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=v[t];return void 0===e&&(e=new js,v[t]=e),e.getGripSpace()},this.getHand=function(t){let e=v[t];return void 0===e&&(e=new js,v[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){a=t,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||s},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return n},this.setSession=async function(c){if(n=c,null!==n){if(f=t.getRenderTarget(),n.addEventListener("select",D),n.addEventListener("selectstart",D),n.addEventListener("selectend",D),n.addEventListener("squeeze",D),n.addEventListener("squeezestart",D),n.addEventListener("squeezeend",D),n.addEventListener("end",N),n.addEventListener("inputsourceschange",O),!0!==m.xrCompatible&&await e.makeXRCompatible(),void 0===n.renderState.layers||!1===t.capabilities.isWebGL2){const i={antialias:void 0!==n.renderState.layers||m.antialias,alpha:m.alpha,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(n,e,i),n.updateRenderState({baseLayer:d}),g=new ne(d.framebufferWidth,d.framebufferHeight,{format:w,type:x,encoding:t.outputEncoding,stencilBuffer:m.stencil})}else{let i=null,s=null,a=null;m.depth&&(a=m.stencil?35056:33190,i=m.stencil?A:T,s=m.stencil?S:y);const o={colorFormat:32856,depthFormat:a,scaleFactor:r};h=new XRWebGLBinding(n,e),u=h.createProjectionLayer(o),n.updateRenderState({layers:[u]}),g=new ne(u.textureWidth,u.textureHeight,{format:w,type:x,depthTexture:new qs(u.textureWidth,u.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,i),stencilBuffer:m.stencil,encoding:t.outputEncoding,samples:m.antialias?4:0});t.properties.get(g).__ignoreDepthValues=u.ignoreDepthValues}g.isXRRenderTarget=!0,this.setFoveation(o),l=null,s=await n.requestReferenceSpace(a),k.setContext(n),k.start(),i.isPresenting=!0,i.dispatchEvent({type:"sessionstart"})}};const z=new oe,U=new oe;function B(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.updateCamera=function(t){if(null===n)return;R.near=C.near=E.near=t.near,R.far=C.far=E.far=t.far,P===R.near&&I===R.far||(n.updateRenderState({depthNear:R.near,depthFar:R.far}),P=R.near,I=R.far);const e=t.parent,i=R.cameras;B(R,e);for(let t=0;te&&(b.set(t,t.lastChangedTime),i.dispatchEvent({type:"planechanged",data:t}))}else M.add(t),b.set(t,n.lastChangedTime),i.dispatchEvent({type:"planeadded",data:t})}p=null})),this.setAnimationLoop=function(t){F=t},this.dispose=function(){}}}function Ys(t,e){function i(i,n){i.opacity.value=n.opacity,n.color&&i.diffuse.value.copy(n.color),n.emissive&&i.emissive.value.copy(n.emissive).multiplyScalar(n.emissiveIntensity),n.map&&(i.map.value=n.map),n.alphaMap&&(i.alphaMap.value=n.alphaMap),n.bumpMap&&(i.bumpMap.value=n.bumpMap,i.bumpScale.value=n.bumpScale,1===n.side&&(i.bumpScale.value*=-1)),n.displacementMap&&(i.displacementMap.value=n.displacementMap,i.displacementScale.value=n.displacementScale,i.displacementBias.value=n.displacementBias),n.emissiveMap&&(i.emissiveMap.value=n.emissiveMap),n.normalMap&&(i.normalMap.value=n.normalMap,i.normalScale.value.copy(n.normalScale),1===n.side&&i.normalScale.value.negate()),n.specularMap&&(i.specularMap.value=n.specularMap),n.alphaTest>0&&(i.alphaTest.value=n.alphaTest);const r=e.get(n).envMap;if(r&&(i.envMap.value=r,i.flipEnvMap.value=r.isCubeTexture&&!1===r.isRenderTargetTexture?-1:1,i.reflectivity.value=n.reflectivity,i.ior.value=n.ior,i.refractionRatio.value=n.refractionRatio),n.lightMap){i.lightMap.value=n.lightMap;const e=!0!==t.physicallyCorrectLights?Math.PI:1;i.lightMapIntensity.value=n.lightMapIntensity*e}let s,a;n.aoMap&&(i.aoMap.value=n.aoMap,i.aoMapIntensity.value=n.aoMapIntensity),n.map?s=n.map:n.specularMap?s=n.specularMap:n.displacementMap?s=n.displacementMap:n.normalMap?s=n.normalMap:n.bumpMap?s=n.bumpMap:n.roughnessMap?s=n.roughnessMap:n.metalnessMap?s=n.metalnessMap:n.alphaMap?s=n.alphaMap:n.emissiveMap?s=n.emissiveMap:n.clearcoatMap?s=n.clearcoatMap:n.clearcoatNormalMap?s=n.clearcoatNormalMap:n.clearcoatRoughnessMap?s=n.clearcoatRoughnessMap:n.iridescenceMap?s=n.iridescenceMap:n.iridescenceThicknessMap?s=n.iridescenceThicknessMap:n.specularIntensityMap?s=n.specularIntensityMap:n.specularColorMap?s=n.specularColorMap:n.transmissionMap?s=n.transmissionMap:n.thicknessMap?s=n.thicknessMap:n.sheenColorMap?s=n.sheenColorMap:n.sheenRoughnessMap&&(s=n.sheenRoughnessMap),void 0!==s&&(s.isWebGLRenderTarget&&(s=s.texture),!0===s.matrixAutoUpdate&&s.updateMatrix(),i.uvTransform.value.copy(s.matrix)),n.aoMap?a=n.aoMap:n.lightMap&&(a=n.lightMap),void 0!==a&&(a.isWebGLRenderTarget&&(a=a.texture),!0===a.matrixAutoUpdate&&a.updateMatrix(),i.uv2Transform.value.copy(a.matrix))}return{refreshFogUniforms:function(e,i){i.color.getRGB(e.fogColor.value,en(t)),i.isFog?(e.fogNear.value=i.near,e.fogFar.value=i.far):i.isFogExp2&&(e.fogDensity.value=i.density)},refreshMaterialUniforms:function(t,n,r,s,a){n.isMeshBasicMaterial||n.isMeshLambertMaterial?i(t,n):n.isMeshToonMaterial?(i(t,n),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,n)):n.isMeshPhongMaterial?(i(t,n),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,n)):n.isMeshStandardMaterial?(i(t,n),function(t,i){t.roughness.value=i.roughness,t.metalness.value=i.metalness,i.roughnessMap&&(t.roughnessMap.value=i.roughnessMap);i.metalnessMap&&(t.metalnessMap.value=i.metalnessMap);const n=e.get(i).envMap;n&&(t.envMapIntensity.value=i.envMapIntensity)}(t,n),n.isMeshPhysicalMaterial&&function(t,e,i){t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap),e.clearcoatNormalMap&&(t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),t.clearcoatNormalMap.value=e.clearcoatNormalMap,1===e.side&&t.clearcoatNormalScale.value.negate()));e.iridescence>0&&(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&&(t.iridescenceMap.value=e.iridescenceMap),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap);e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap)}(t,n,a)):n.isMeshMatcapMaterial?(i(t,n),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,n)):n.isMeshDepthMaterial?i(t,n):n.isMeshDistanceMaterial?(i(t,n),function(t,e){t.referencePosition.value.copy(e.referencePosition),t.nearDistance.value=e.nearDistance,t.farDistance.value=e.farDistance}(t,n)):n.isMeshNormalMaterial?i(t,n):n.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity}(t,n),n.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,n)):n.isPointsMaterial?function(t,e,i,n){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*n,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let r;e.map?r=e.map:e.alphaMap&&(r=e.alphaMap);void 0!==r&&(!0===r.matrixAutoUpdate&&r.updateMatrix(),t.uvTransform.value.copy(r.matrix))}(t,n,r,s):n.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map);e.alphaMap&&(t.alphaMap.value=e.alphaMap);e.alphaTest>0&&(t.alphaTest.value=e.alphaTest);let i;e.map?i=e.map:e.alphaMap&&(i=e.alphaMap);void 0!==i&&(!0===i.matrixAutoUpdate&&i.updateMatrix(),t.uvTransform.value.copy(i.matrix))}(t,n):n.isShadowMaterial?(t.color.value.copy(n.color),t.opacity.value=n.opacity):n.isShaderMaterial&&(n.uniformsNeedUpdate=!1)}}}function Zs(t,e,i,n){let r={},s={},a=[];const o=i.isWebGL2?t.getParameter(35375):0;function l(t,e,i){const n=t.value;if(void 0===i[e]){if("number"==typeof n)i[e]=n;else{const t=Array.isArray(n)?n:[n],r=[];for(let e=0;e0){r=i%n;0!==r&&n-r-a.boundary<0&&(i+=n-r,s.__offset=i)}i+=a.storage}r=i%n,r>0&&(i+=n-r);t.__size=i,t.__cache={}}(i),d=function(e){const i=function(){for(let t=0;t0&&function(t,e,i){const n=Z.isWebGL2;null===V&&(V=new ne(1,1,{generateMipmaps:!0,type:Y.has("EXT_color_buffer_half_float")?b:x,minFilter:v,samples:n&&!0===a?4:0}));g.getDrawingBufferSize(W),n?V.setSize(W.x,W.y):V.setSize(Ct(W.x),Ct(W.y));const r=g.getRenderTarget();g.setRenderTarget(V),g.clear();const s=g.toneMapping;g.toneMapping=0,Ot(t,e,i),g.toneMapping=s,Q.updateMultisampleRenderTarget(V),Q.updateRenderTargetMipmap(V),g.setRenderTarget(r)}(r,e,i),n&&J.viewport(C.copy(n)),r.length>0&&Ot(r,e,i),s.length>0&&Ot(s,e,i),o.length>0&&Ot(o,e,i),J.buffers.depth.setTest(!0),J.buffers.depth.setMask(!0),J.buffers.color.setMask(!0),J.setPolygonOffset(!1)}function Ot(t,e,i){const n=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?f[f.length-1]:null,m.pop(),d=m.length>0?m[m.length-1]:null},this.getActiveCubeFace=function(){return y},this.getActiveMipmapLevel=function(){return S},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(t,e,i){$.get(t.texture).__webglTexture=e,$.get(t.depthTexture).__webglTexture=i;const n=$.get(t);n.__hasExternalTextures=!0,n.__hasExternalTextures&&(n.__autoAllocateDepthBuffer=void 0===i,n.__autoAllocateDepthBuffer||!0===Y.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),n.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(t,e){const i=$.get(t);i.__webglFramebuffer=e,i.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,i=0){T=t,y=e,S=i;let n=!0,r=null,s=!1,a=!1;if(t){const i=$.get(t);void 0!==i.__useDefaultFramebuffer?(J.bindFramebuffer(36160,null),n=!1):void 0===i.__webglFramebuffer?Q.setupRenderTarget(t):i.__hasExternalTextures&&Q.rebindTextures(t,$.get(t.texture).__webglTexture,$.get(t.depthTexture).__webglTexture);const o=t.texture;(o.isData3DTexture||o.isDataArrayTexture||o.isCompressedArrayTexture)&&(a=!0);const l=$.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=l[e],s=!0):r=Z.isWebGL2&&t.samples>0&&!1===Q.useMultisampledRTT(t)?$.get(t).__webglMultisampledFramebuffer:l,C.copy(t.viewport),L.copy(t.scissor),R=t.scissorTest}else C.copy(z).multiplyScalar(D).floor(),L.copy(U).multiplyScalar(D).floor(),R=B;if(J.bindFramebuffer(36160,r)&&Z.drawBuffers&&n&&J.drawBuffers(t,r),J.viewport(C),J.scissor(L),J.setScissorTest(R),s){const n=$.get(t.texture);_t.framebufferTexture2D(36160,36064,34069+e,n.__webglTexture,i)}else if(a){const n=$.get(t.texture),r=e||0;_t.framebufferTextureLayer(36160,36064,n.__webglTexture,i||0,r)}A=-1},this.readRenderTargetPixels=function(t,e,i,n,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=$.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){J.bindFramebuffer(36160,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==w&>.convert(o)!==_t.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===b&&(Y.has("EXT_color_buffer_half_float")||Z.isWebGL2&&Y.has("EXT_color_buffer_float"));if(!(l===x||gt.convert(l)===_t.getParameter(35738)||l===M&&(Z.isWebGL2||Y.has("OES_texture_float")||Y.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-n&&i>=0&&i<=t.height-r&&_t.readPixels(e,i,n,r,gt.convert(o),gt.convert(l),s)}finally{const t=null!==T?$.get(T).__webglFramebuffer:null;J.bindFramebuffer(36160,t)}}},this.copyFramebufferToTexture=function(t,e,i=0){const n=Math.pow(2,-i),r=Math.floor(e.image.width*n),s=Math.floor(e.image.height*n);Q.setTexture2D(e,0),_t.copyTexSubImage2D(3553,i,0,0,t.x,t.y,r,s),J.unbindTexture()},this.copyTextureToTexture=function(t,e,i,n=0){const r=e.image.width,s=e.image.height,a=gt.convert(i.format),o=gt.convert(i.type);Q.setTexture2D(i,0),_t.pixelStorei(37440,i.flipY),_t.pixelStorei(37441,i.premultiplyAlpha),_t.pixelStorei(3317,i.unpackAlignment),e.isDataTexture?_t.texSubImage2D(3553,n,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?_t.compressedTexSubImage2D(3553,n,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):_t.texSubImage2D(3553,n,t.x,t.y,a,o,e.image),0===n&&i.generateMipmaps&&_t.generateMipmap(3553),J.unbindTexture()},this.copyTextureToTexture3D=function(t,e,i,n,r=0){if(g.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=gt.convert(n.format),c=gt.convert(n.type);let h;if(n.isData3DTexture)Q.setTexture3D(n,0),h=32879;else{if(!n.isDataArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");Q.setTexture2DArray(n,0),h=35866}_t.pixelStorei(37440,n.flipY),_t.pixelStorei(37441,n.premultiplyAlpha),_t.pixelStorei(3317,n.unpackAlignment);const u=_t.getParameter(3314),d=_t.getParameter(32878),p=_t.getParameter(3316),m=_t.getParameter(3315),f=_t.getParameter(32877),v=i.isCompressedTexture?i.mipmaps[0]:i.image;_t.pixelStorei(3314,v.width),_t.pixelStorei(32878,v.height),_t.pixelStorei(3316,t.min.x),_t.pixelStorei(3315,t.min.y),_t.pixelStorei(32877,t.min.z),i.isDataTexture||i.isData3DTexture?_t.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v.data):i.isCompressedArrayTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),_t.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,v.data)):_t.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,v),_t.pixelStorei(3314,u),_t.pixelStorei(32878,d),_t.pixelStorei(3316,p),_t.pixelStorei(3315,m),_t.pixelStorei(32877,f),0===r&&n.generateMipmaps&&_t.generateMipmap(h),J.unbindTexture()},this.initTexture=function(t){t.isCubeTexture?Q.setTextureCube(t,0):t.isData3DTexture?Q.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?Q.setTexture2DArray(t,0):Q.setTexture2D(t,0),J.unbindTexture()},this.resetState=function(){y=0,S=0,T=null,J.reset(),vt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}class Ks extends Js{}Ks.prototype.isWebGL1Renderer=!0;class $s{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new Zt(t),this.density=e}clone(){return new $s(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}class Qs{constructor(t,e=1,i=1e3){this.isFog=!0,this.name="",this.color=new Zt(t),this.near=e,this.far=i}clone(){return new Qs(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}class ta extends li{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e}get autoUpdate(){return console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate}set autoUpdate(t){console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate=t}}class ea{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=mt,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=bt()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,i){t*=this.stride,i*=e.stride;for(let n=0,r=this.stride;nt.far||e.push({distance:o,point:aa.clone(),uv:_i.getUV(aa,da,pa,ma,fa,ga,va,new It),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function _a(t,e,i,n,r,s){ca.subVectors(t,i).addScalar(.5).multiply(n),void 0!==r?(ha.x=s*ca.x-r*ca.y,ha.y=r*ca.x+s*ca.y):ha.copy(ca),t.copy(e),t.x+=ha.x,t.y+=ha.y,t.applyMatrix4(ua)}const ya=new oe,Ma=new oe;class ba extends li{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,i=e.length;t0){let i,n;for(i=1,n=e.length;i0){ya.setFromMatrixPosition(this.matrixWorld);const i=t.ray.origin.distanceTo(ya);this.getObjectForDistance(i).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){ya.setFromMatrixPosition(t.matrixWorld),Ma.setFromMatrixPosition(this.matrixWorld);const i=ya.distanceTo(Ma)/t.zoom;let n,r;for(e[0].object.visible=!0,n=1,r=e.length;n=t))break;e[n-1].object.visible=!1,e[n].object.visible=!0}for(this._currentLevel=n-1;no)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);st.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}else{for(let i=Math.max(0,s.start),n=Math.min(m.count,s.start+s.count)-1;io)continue;u.applyMatrix4(this.matrixWorld);const n=t.ray.origin.distanceTo(u);nt.far||e.push({distance:n,point:h.clone().applyMatrix4(this.matrixWorld),index:i,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length>0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;t0){const i=t[e[0]];if(void 0!==i){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=i.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:i,index:e,face:null,object:a})}}class so extends ee{constructor(t,e,i,n,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,n,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:i},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class ao{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const i=this.getUtoTmapping(t);return this.getPoint(i,e)}getPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPoint(i/t));return e}getSpacedPoints(t=5){const e=[];for(let i=0;i<=t;i++)e.push(this.getPointAt(i/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let i,n=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)i=this.getPoint(s/t),r+=i.distanceTo(n),e.push(r),n=i;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const i=this.getLengths();let n=0;const r=i.length;let s;s=e||t*i[r-1];let a,o=0,l=r-1;for(;o<=l;)if(n=Math.floor(o+(l-o)/2),a=i[n]-s,a<0)o=n+1;else{if(!(a>0)){l=n;break}l=n-1}if(n=l,i[n]===s)return n/(r-1);const c=i[n];return(n+(s-c)/(i[n+1]-c))/(r-1)}getTangent(t,e){const i=1e-4;let n=t-i,r=t+i;n<0&&(n=0),r>1&&(r=1);const s=this.getPoint(n),a=this.getPoint(r),o=e||(s.isVector2?new It:new oe);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const i=this.getUtoTmapping(t);return this.getTangent(i,e)}computeFrenetFrames(t,e){const i=new oe,n=[],r=[],s=[],a=new oe,o=new Ue;for(let e=0;e<=t;e++){const i=e/t;n[e]=this.getTangentAt(i,new oe)}r[0]=new oe,s[0]=new oe;let l=Number.MAX_VALUE;const c=Math.abs(n[0].x),h=Math.abs(n[0].y),u=Math.abs(n[0].z);c<=l&&(l=c,i.set(1,0,0)),h<=l&&(l=h,i.set(0,1,0)),u<=l&&i.set(0,0,1),a.crossVectors(n[0],i).normalize(),r[0].crossVectors(n[0],a),s[0].crossVectors(n[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(n[e-1],n[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(St(n[e-1].dot(n[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(n[e],r[e])}if(!0===e){let e=Math.acos(St(r[0].dot(r[t]),-1,1));e/=t,n[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let i=1;i<=t;i++)r[i].applyMatrix4(o.makeRotationAxis(n[i],e*i)),s[i].crossVectors(n[i],r[i])}return{tangents:n,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class oo extends ao{constructor(t=0,e=0,i=1,n=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=i,this.yRadius=n,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const i=e||new It,n=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)n;)r-=n;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=n[(l-1)%r]:(ho.subVectors(n[0],n[1]).add(n[0]),a=ho);const h=n[l%r],u=n[(l+1)%r];if(this.closed||l+2n.length-2?n.length-1:s+1],h=n[s>n.length-3?n.length-1:s+2];return i.set(go(a,o.x,l.x,c.x,h.x),go(a,o.y,l.y,c.y,h.y)),i}copy(t){super.copy(t),this.points=[];for(let e=0,i=t.points.length;e=i){const t=n[r]-i,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let i=0,n=this.curves.length;i1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,i=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class Lo extends zi{constructor(t=[new It(0,-.5),new It(.5,0),new It(0,.5)],e=12,i=0,n=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:i,phiLength:n},e=Math.floor(e),n=St(n,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new oe,u=new It,d=new oe,p=new oe,m=new oe;let f=0,g=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=i+r*c*n,p=Math.sin(d),m=Math.cos(d);for(let i=0;i<=t.length-1;i++){h.x=t[i].x*p,h.y=t[i].y,h.z=t[i].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=i/(t.length-1),a.push(u.x,u.y);const n=o[3*i+0]*p,c=o[3*i+1],d=o[3*i+0]*m;l.push(n,c,d)}}for(let i=0;i0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new Ci(h,3)),this.setAttribute("normal",new Ci(u,3)),this.setAttribute("uv",new Ci(d,2))}static fromJSON(t){return new Io(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Do extends Io{constructor(t=1,e=1,i=32,n=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,i,n,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:i,heightSegments:n,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new Do(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class No extends zi{constructor(t=[],e=[],i=1,n=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:i,detail:n};const r=[],s=[];function a(t,e,i,n){const r=n+1,s=[];for(let n=0;n<=r;n++){s[n]=[];const a=t.clone().lerp(i,n/r),o=e.clone().lerp(i,n/r),l=r-n;for(let t=0;t<=l;t++)s[n][t]=0===t&&n===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),i<.2&&(s[t+2]+=1),n<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new Ci(r,3)),this.setAttribute("normal",new Ci(r.slice(),3)),this.setAttribute("uv",new Ci(s,2)),0===n?this.computeVertexNormals():this.normalizeNormals()}static fromJSON(t){return new No(t.vertices,t.indices,t.radius,t.details)}}class Oo extends No{constructor(t=1,e=0){const i=(1+Math.sqrt(5))/2,n=1/i;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-n,-i,0,-n,i,0,n,-i,0,n,i,-n,-i,0,-n,i,0,n,-i,0,n,i,0,-i,0,-n,i,0,-n,-i,0,n,i,0,n],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new Oo(t.radius,t.detail)}}const zo=new oe,Uo=new oe,Bo=new oe,Fo=new _i;class ko extends zi{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const i=4,n=Math.pow(10,i),r=Math.cos(yt*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t80*i){o=c=t[0],l=h=t[1];for(let e=i;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return jo(s,a,i,o,l,p,0),a};function Ho(t,e,i,n,r){let s,a;if(r===function(t,e,i,n){let r=0;for(let s=e,a=i-n;s0)for(s=e;s=e;s-=n)a=hl(s,t[s],t[s+1],a);return a&&rl(a,a.next)&&(ul(a),a=a.next),a}function Wo(t,e){if(!t)return t;e||(e=t);let i,n=t;do{if(i=!1,n.steiner||!rl(n,n.next)&&0!==nl(n.prev,n,n.next))n=n.next;else{if(ul(n),n=e=n.prev,n===n.next)break;i=!0}}while(i||n!==e);return e}function jo(t,e,i,n,r,s,a){if(!t)return;!a&&s&&function(t,e,i,n){let r=t;do{0===r.z&&(r.z=Qo(r.x,r.y,e,i,n)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,i,n,r,s,a,o,l,c=1;do{for(i=t,t=null,s=null,a=0;i;){for(a++,n=i,o=0,e=0;e0||l>0&&n;)0!==o&&(0===l||!n||i.z<=n.z)?(r=i,i=i.nextZ,o--):(r=n,n=n.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;i=n}s.nextZ=null,c*=2}while(a>1)}(r)}(t,n,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Xo(t,n,r,s):qo(t))e.push(o.i/i|0),e.push(t.i/i|0),e.push(l.i/i|0),ul(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?jo(t=Yo(Wo(t),e,i),e,i,n,r,s,2):2===a&&Zo(t,e,i,n,r,s):jo(Wo(t),e,i,n,r,s,1);break}}function qo(t){const e=t.prev,i=t,n=t.next;if(nl(e,i,n)>=0)return!1;const r=e.x,s=i.x,a=n.x,o=e.y,l=i.y,c=n.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=n.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&el(r,o,s,l,a,c,m.x,m.y)&&nl(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Xo(t,e,i,n){const r=t.prev,s=t,a=t.next;if(nl(r,s,a)>=0)return!1;const o=r.x,l=s.x,c=a.x,h=r.y,u=s.y,d=a.y,p=ol?o>c?o:c:l>c?l:c,g=h>u?h>d?h:d:u>d?u:d,v=Qo(p,m,e,i,n),x=Qo(f,g,e,i,n);let _=t.prevZ,y=t.nextZ;for(;_&&_.z>=v&&y&&y.z<=x;){if(_.x>=p&&_.x<=f&&_.y>=m&&_.y<=g&&_!==r&&_!==a&&el(o,h,l,u,c,d,_.x,_.y)&&nl(_.prev,_,_.next)>=0)return!1;if(_=_.prevZ,y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&el(o,h,l,u,c,d,y.x,y.y)&&nl(y.prev,y,y.next)>=0)return!1;y=y.nextZ}for(;_&&_.z>=v;){if(_.x>=p&&_.x<=f&&_.y>=m&&_.y<=g&&_!==r&&_!==a&&el(o,h,l,u,c,d,_.x,_.y)&&nl(_.prev,_,_.next)>=0)return!1;_=_.prevZ}for(;y&&y.z<=x;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&el(o,h,l,u,c,d,y.x,y.y)&&nl(y.prev,y,y.next)>=0)return!1;y=y.nextZ}return!0}function Yo(t,e,i){let n=t;do{const r=n.prev,s=n.next.next;!rl(r,s)&&sl(r,n,n.next,s)&&ll(r,s)&&ll(s,r)&&(e.push(r.i/i|0),e.push(n.i/i|0),e.push(s.i/i|0),ul(n),ul(n.next),n=t=s),n=n.next}while(n!==t);return Wo(n)}function Zo(t,e,i,n,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&il(a,t)){let o=cl(a,t);return a=Wo(a,a.next),o=Wo(o,o.next),jo(a,e,i,n,r,s,0),void jo(o,e,i,n,r,s,0)}t=t.next}a=a.next}while(a!==t)}function Jo(t,e){return t.x-e.x}function Ko(t,e){const i=function(t,e){let i,n=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=n.y&&a>=n.next.y&&n.next.y!==n.y){const t=n.x+(a-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(t<=s&&t>r&&(r=t,i=n.x=n.x&&n.x>=l&&s!==n.x&&el(ai.x||n.x===i.x&&$o(i,n)))&&(i=n,u=h)),n=n.next}while(n!==o);return i}(t,e);if(!i)return e;const n=cl(i,t);return Wo(n,n.next),Wo(i,i.next)}function $o(t,e){return nl(t.prev,t,e.prev)<0&&nl(e.next,t,t.next)<0}function Qo(t,e,i,n,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-i)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-n)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function tl(t){let e=t,i=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(n-o)>=(i-a)*(e-o)&&(i-a)*(s-o)>=(r-a)*(n-o)}function il(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let i=t;do{if(i.i!==t.i&&i.next.i!==t.i&&i.i!==e.i&&i.next.i!==e.i&&sl(i,i.next,t,e))return!0;i=i.next}while(i!==t);return!1}(t,e)&&(ll(t,e)&&ll(e,t)&&function(t,e){let i=t,n=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{i.y>s!=i.next.y>s&&i.next.y!==i.y&&r<(i.next.x-i.x)*(s-i.y)/(i.next.y-i.y)+i.x&&(n=!n),i=i.next}while(i!==t);return n}(t,e)&&(nl(t.prev,t,e.prev)||nl(t,e.prev,e))||rl(t,e)&&nl(t.prev,t,t.next)>0&&nl(e.prev,e,e.next)>0)}function nl(t,e,i){return(e.y-t.y)*(i.x-e.x)-(e.x-t.x)*(i.y-e.y)}function rl(t,e){return t.x===e.x&&t.y===e.y}function sl(t,e,i,n){const r=ol(nl(t,e,i)),s=ol(nl(t,e,n)),a=ol(nl(i,n,t)),o=ol(nl(i,n,e));return r!==s&&a!==o||(!(0!==r||!al(t,i,e))||(!(0!==s||!al(t,n,e))||(!(0!==a||!al(i,t,n))||!(0!==o||!al(i,e,n)))))}function al(t,e,i){return e.x<=Math.max(t.x,i.x)&&e.x>=Math.min(t.x,i.x)&&e.y<=Math.max(t.y,i.y)&&e.y>=Math.min(t.y,i.y)}function ol(t){return t>0?1:t<0?-1:0}function ll(t,e){return nl(t.prev,t,t.next)<0?nl(t,e,t.next)>=0&&nl(t,t.prev,e)>=0:nl(t,e,t.prev)<0||nl(t,t.next,e)<0}function cl(t,e){const i=new dl(t.i,t.x,t.y),n=new dl(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,i.next=r,r.prev=i,n.next=i,i.prev=n,s.next=n,n.prev=s,n}function hl(t,e,i,n){const r=new dl(t,e,i);return n?(r.next=n.next,r.prev=n,n.next.prev=r,n.next=r):(r.prev=r,r.next=r),r}function ul(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function dl(t,e,i){this.i=t,this.x=e,this.y=i,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class pl{static area(t){const e=t.length;let i=0;for(let n=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function fl(t,e){for(let i=0;iNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((i.x-c/d-p)*c-(i.y+l/d-m)*l)/(a*c-o*l);n=p+a*f-t.x,r=m+o*f-t.y;const g=n*n+r*r;if(g<=2)return new It(n,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(n=-o,r=a,s=Math.sqrt(h)):(n=a,r=o,s=Math.sqrt(h/2))}return new It(n/s,r/s)}const P=[];for(let t=0,e=A.length,i=e-1,n=t+1;t=0;t--){const e=t/p,i=h*Math.cos(e*Math.PI/2),n=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=A.length;t=0;){const n=i;let r=i-1;r<0&&(r=t.length-1);for(let t=0,i=o+2*p;t0)&&d.push(e,r,l),(t!==i-1||o0!=t>0&&this.version++,this._sheen=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class Nl extends Mi{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Zt(16777215),this.specular=new Zt(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Zt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new It(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Ol extends Mi{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Zt(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Zt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new It(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class zl extends Mi{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new It(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class Ul extends Mi{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Zt(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Zt(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new It(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Bl extends Mi{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Zt(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new It(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Fl extends Ga{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function kl(t,e,i){return Vl(t)?new t.constructor(t.subarray(e,void 0!==i?i:t.length)):t.slice(e,i)}function Gl(t,e,i){return!t||!i&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Vl(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Hl(t){const e=t.length,i=new Array(e);for(let t=0;t!==e;++t)i[t]=t;return i.sort((function(e,i){return t[e]-t[i]})),i}function Wl(t,e,i){const n=t.length,r=new t.constructor(n);for(let s=0,a=0;a!==n;++s){const n=i[s]*e;for(let i=0;i!==e;++i)r[a++]=t[n+i]}return r}function jl(t,e,i,n){let r=1,s=t[0];for(;void 0!==s&&void 0===s[n];)s=t[r++];if(void 0===s)return;let a=s[n];if(void 0!==a)if(Array.isArray(a))do{a=s[n],void 0!==a&&(e.push(s.time),i.push.apply(i,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[n],void 0!==a&&(e.push(s.time),a.toArray(i,i.length)),s=t[r++]}while(void 0!==s);else do{a=s[n],void 0!==a&&(e.push(s.time),i.push(a)),s=t[r++]}while(void 0!==s)}var ql=Object.freeze({__proto__:null,arraySlice:kl,convertArray:Gl,flattenJSON:jl,getKeyframeOrder:Hl,isTypedArray:Vl,makeClipAdditive:function(t,e=0,i=t,n=30){n<=0&&(n=30);const r=i.tracks.length,s=e/n;for(let e=0;e=n.times[u]){const t=u*l+o,e=t+l-o;d=kl(n.values,t,e)}else{const t=n.createInterpolant(),e=o,i=l-o;t.evaluate(s),d=kl(t.resultBuffer,e,i)}if("quaternion"===r){(new ae).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=n)){l.push(e.times[t]);for(let i=0;is.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=i,i=0}}for(;i>>1;te;)--s;if(++s,0!==r||s!==n){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=kl(i,r,s),this.values=kl(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const i=this.times,n=this.values,r=i.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const n=i[e];if("number"==typeof n&&isNaN(n)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,n),t=!1;break}if(null!==s&&s>n){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,n,s),t=!1;break}s=n}if(void 0!==n&&Vl(n))for(let e=0,i=n.length;e!==i;++e){const i=n[e];if(isNaN(i)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,i),t=!1;break}}return t}optimize(){const t=kl(this.times),e=kl(this.values),i=this.getValueSize(),n=this.getInterpolation()===nt,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*i,n=s*i,a=0;a!==i;++a)e[n+a]=e[t+a];++s}return s!==t.length?(this.times=kl(t,0,s),this.values=kl(e,0,s*i)):(this.times=t,this.values=e),this}clone(){const t=kl(this.times,0),e=kl(this.values,0),i=new(0,this.constructor)(this.name,t,e);return i.createInterpolant=this.createInterpolant,i}}Kl.prototype.TimeBufferType=Float32Array,Kl.prototype.ValueBufferType=Float32Array,Kl.prototype.DefaultInterpolation=it;class $l extends Kl{}$l.prototype.ValueTypeName="bool",$l.prototype.ValueBufferType=Array,$l.prototype.DefaultInterpolation=et,$l.prototype.InterpolantFactoryMethodLinear=void 0,$l.prototype.InterpolantFactoryMethodSmooth=void 0;class Ql extends Kl{}Ql.prototype.ValueTypeName="color";class tc extends Kl{}tc.prototype.ValueTypeName="number";class ec extends Xl{constructor(t,e,i,n){super(t,e,i,n)}interpolate_(t,e,i,n){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(i-e)/(n-e);let l=t*a;for(let t=l+a;l!==t;l+=4)ae.slerpFlat(r,0,s,l-a,s,l,o);return r}}class ic extends Kl{InterpolantFactoryMethodLinear(t){return new ec(this.times,this.values,this.getValueSize(),t)}}ic.prototype.ValueTypeName="quaternion",ic.prototype.DefaultInterpolation=it,ic.prototype.InterpolantFactoryMethodSmooth=void 0;class nc extends Kl{}nc.prototype.ValueTypeName="string",nc.prototype.ValueBufferType=Array,nc.prototype.DefaultInterpolation=et,nc.prototype.InterpolantFactoryMethodLinear=void 0,nc.prototype.InterpolantFactoryMethodSmooth=void 0;class rc extends Kl{}rc.prototype.ValueTypeName="vector";class sc{constructor(t,e=-1,i,n=2500){this.name=t,this.tracks=i,this.duration=e,this.blendMode=n,this.uuid=bt(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],i=t.tracks,n=1/(t.fps||1);for(let t=0,r=i.length;t!==r;++t)e.push(ac(i[t]).scale(n));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],i=t.tracks,n={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,n=i.length;t!==n;++t)e.push(Kl.toJSON(i[t]));return n}static CreateFromMorphTargetSequence(t,e,i,n){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=n[t];e||(n[t]=e=[]),e.push(i)}}const s=[];for(const t in n)s.push(this.CreateFromMorphTargetSequence(t,n[t],e,i));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const i=function(t,e,i,n,r){if(0!==i.length){const s=[],a=[];jl(i,s,a,n),0!==s.length&&r.push(new t(e,s,a))}},n=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==uc[t])return void uc[t].push({onLoad:e,onProgress:i,onError:n});uc[t]=[],uc[t].push({onLoad:e,onProgress:i,onError:n});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),a=this.mimeType,o=this.responseType;fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const i=uc[t],n=e.body.getReader(),r=e.headers.get("Content-Length")||e.headers.get("X-File-Size"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){n.read().then((({done:n,value:r})=>{if(n)t.close();else{o+=r.byteLength;const n=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=i.length;t{switch(o){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,a)));case"json":return t.json();default:if(void 0===a)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(a),i=e&&e[1]?e[1].toLowerCase():void 0,n=new TextDecoder(i);return t.arrayBuffer().then((t=>n.decode(t)))}}})).then((e=>{oc.add(t,e);const i=uc[t];delete uc[t];for(let t=0,n=i.length;t{const i=uc[t];if(void 0===i)throw this.manager.itemError(t),e;delete uc[t];for(let t=0,n=i.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class mc extends hc{constructor(t){super(t)}load(t,e,i,n){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=oc.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=Bt("img");function o(){c(),oc.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),n&&n(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.slice(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class fc extends li{constructor(t,e=1){super(),this.isLight=!0,this.type="Light",this.color=new Zt(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,void 0!==this.groundColor&&(e.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(e.object.distance=this.distance),void 0!==this.angle&&(e.object.angle=this.angle),void 0!==this.decay&&(e.object.decay=this.decay),void 0!==this.penumbra&&(e.object.penumbra=this.penumbra),void 0!==this.shadow&&(e.object.shadow=this.shadow.toJSON()),e}}class gc extends fc{constructor(t,e,i){super(t,i),this.isHemisphereLight=!0,this.type="HemisphereLight",this.position.copy(li.DEFAULT_UP),this.updateMatrix(),this.groundColor=new Zt(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const vc=new Ue,xc=new oe,_c=new oe;class yc{constructor(t){this.camera=t,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new It(512,512),this.map=null,this.mapPass=null,this.matrix=new Ue,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new vn,this._frameExtents=new It(1,1),this._viewportCount=1,this._viewports=[new ie(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,i=this.matrix;xc.setFromMatrixPosition(t.matrixWorld),e.position.copy(xc),_c.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(_c),e.updateMatrixWorld(),vc.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(vc),i.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),i.multiply(vc)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.bias=t.bias,this.radius=t.radius,this.mapSize.copy(t.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const t={};return 0!==this.bias&&(t.bias=this.bias),0!==this.normalBias&&(t.normalBias=this.normalBias),1!==this.radius&&(t.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}class Mc extends yc{constructor(){super(new an(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(t){const e=this.camera,i=2*Mt*t.angle*this.focus,n=this.mapSize.width/this.mapSize.height,r=t.distance||e.far;i===e.fov&&n===e.aspect&&r===e.far||(e.fov=i,e.aspect=n,e.far=r,e.updateProjectionMatrix()),super.updateMatrices(t)}copy(t){return super.copy(t),this.focus=t.focus,this}}class bc extends fc{constructor(t,e,i=0,n=Math.PI/3,r=0,s=2){super(t,e),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(li.DEFAULT_UP),this.updateMatrix(),this.target=new li,this.distance=i,this.angle=n,this.penumbra=r,this.decay=s,this.map=null,this.shadow=new Mc}get power(){return this.intensity*Math.PI}set power(t){this.intensity=t/Math.PI}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.angle=t.angle,this.penumbra=t.penumbra,this.decay=t.decay,this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}const Sc=new Ue,wc=new oe,Tc=new oe;class Ac extends yc{constructor(){super(new an(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new It(4,2),this._viewportCount=6,this._viewports=[new ie(2,1,1,1),new ie(0,1,1,1),new ie(3,1,1,1),new ie(1,1,1,1),new ie(3,0,1,1),new ie(1,0,1,1)],this._cubeDirections=[new oe(1,0,0),new oe(-1,0,0),new oe(0,0,1),new oe(0,0,-1),new oe(0,1,0),new oe(0,-1,0)],this._cubeUps=[new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,0,1),new oe(0,0,-1)]}updateMatrices(t,e=0){const i=this.camera,n=this.matrix,r=t.distance||i.far;r!==i.far&&(i.far=r,i.updateProjectionMatrix()),wc.setFromMatrixPosition(t.matrixWorld),i.position.copy(wc),Tc.copy(i.position),Tc.add(this._cubeDirections[e]),i.up.copy(this._cubeUps[e]),i.lookAt(Tc),i.updateMatrixWorld(),n.makeTranslation(-wc.x,-wc.y,-wc.z),Sc.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Sc)}}class Ec extends fc{constructor(t,e,i=0,n=2){super(t,e),this.isPointLight=!0,this.type="PointLight",this.distance=i,this.decay=n,this.shadow=new Ac}get power(){return 4*this.intensity*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class Cc extends yc{constructor(){super(new Pn(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class Lc extends fc{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(li.DEFAULT_UP),this.updateMatrix(),this.target=new li,this.shadow=new Cc}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class Rc extends fc{constructor(t,e){super(t,e),this.isAmbientLight=!0,this.type="AmbientLight"}}class Pc extends fc{constructor(t,e,i=10,n=10){super(t,e),this.isRectAreaLight=!0,this.type="RectAreaLight",this.width=i,this.height=n}get power(){return this.intensity*this.width*this.height*Math.PI}set power(t){this.intensity=t/(this.width*this.height*Math.PI)}copy(t){return super.copy(t),this.width=t.width,this.height=t.height,this}toJSON(t){const e=super.toJSON(t);return e.object.width=this.width,e.object.height=this.height,e}}class Ic{constructor(){this.isSphericalHarmonics3=!0,this.coefficients=[];for(let t=0;t<9;t++)this.coefficients.push(new oe)}set(t){for(let e=0;e<9;e++)this.coefficients[e].copy(t[e]);return this}zero(){for(let t=0;t<9;t++)this.coefficients[t].set(0,0,0);return this}getAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.282095),e.addScaledVector(s[1],.488603*n),e.addScaledVector(s[2],.488603*r),e.addScaledVector(s[3],.488603*i),e.addScaledVector(s[4],i*n*1.092548),e.addScaledVector(s[5],n*r*1.092548),e.addScaledVector(s[6],.315392*(3*r*r-1)),e.addScaledVector(s[7],i*r*1.092548),e.addScaledVector(s[8],.546274*(i*i-n*n)),e}getIrradianceAt(t,e){const i=t.x,n=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.886227),e.addScaledVector(s[1],1.023328*n),e.addScaledVector(s[2],1.023328*r),e.addScaledVector(s[3],1.023328*i),e.addScaledVector(s[4],.858086*i*n),e.addScaledVector(s[5],.858086*n*r),e.addScaledVector(s[6],.743125*r*r-.247708),e.addScaledVector(s[7],.858086*i*r),e.addScaledVector(s[8],.429043*(i*i-n*n)),e}add(t){for(let e=0;e<9;e++)this.coefficients[e].add(t.coefficients[e]);return this}addScaledSH(t,e){for(let i=0;i<9;i++)this.coefficients[i].addScaledVector(t.coefficients[i],e);return this}scale(t){for(let e=0;e<9;e++)this.coefficients[e].multiplyScalar(t);return this}lerp(t,e){for(let i=0;i<9;i++)this.coefficients[i].lerp(t.coefficients[i],e);return this}equals(t){for(let e=0;e<9;e++)if(!this.coefficients[e].equals(t.coefficients[e]))return!1;return!0}copy(t){return this.set(t.coefficients)}clone(){return(new this.constructor).copy(this)}fromArray(t,e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].fromArray(t,e+3*n);return this}toArray(t=[],e=0){const i=this.coefficients;for(let n=0;n<9;n++)i[n].toArray(t,e+3*n);return t}static getBasisAt(t,e){const i=t.x,n=t.y,r=t.z;e[0]=.282095,e[1]=.488603*n,e[2]=.488603*r,e[3]=.488603*i,e[4]=1.092548*i*n,e[5]=1.092548*n*r,e[6]=.315392*(3*r*r-1),e[7]=1.092548*i*r,e[8]=.546274*(i*i-n*n)}}class Dc extends fc{constructor(t=new Ic,e=1){super(void 0,e),this.isLightProbe=!0,this.sh=t}copy(t){return super.copy(t),this.sh.copy(t.sh),this}fromJSON(t){return this.intensity=t.intensity,this.sh.fromArray(t.sh),this}toJSON(t){const e=super.toJSON(t);return e.object.sh=this.sh.toArray(),e}}class Nc extends hc{constructor(t){super(t),this.textures={}}load(t,e,i,n){const r=this,s=new pc(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=this.textures;function i(t){return void 0===e[t]&&console.warn("THREE.MaterialLoader: Undefined texture",t),e[t]}const n=Nc.createMaterialFromType(t.type);if(void 0!==t.uuid&&(n.uuid=t.uuid),void 0!==t.name&&(n.name=t.name),void 0!==t.color&&void 0!==n.color&&n.color.setHex(t.color),void 0!==t.roughness&&(n.roughness=t.roughness),void 0!==t.metalness&&(n.metalness=t.metalness),void 0!==t.sheen&&(n.sheen=t.sheen),void 0!==t.sheenColor&&(n.sheenColor=(new Zt).setHex(t.sheenColor)),void 0!==t.sheenRoughness&&(n.sheenRoughness=t.sheenRoughness),void 0!==t.emissive&&void 0!==n.emissive&&n.emissive.setHex(t.emissive),void 0!==t.specular&&void 0!==n.specular&&n.specular.setHex(t.specular),void 0!==t.specularIntensity&&(n.specularIntensity=t.specularIntensity),void 0!==t.specularColor&&void 0!==n.specularColor&&n.specularColor.setHex(t.specularColor),void 0!==t.shininess&&(n.shininess=t.shininess),void 0!==t.clearcoat&&(n.clearcoat=t.clearcoat),void 0!==t.clearcoatRoughness&&(n.clearcoatRoughness=t.clearcoatRoughness),void 0!==t.iridescence&&(n.iridescence=t.iridescence),void 0!==t.iridescenceIOR&&(n.iridescenceIOR=t.iridescenceIOR),void 0!==t.iridescenceThicknessRange&&(n.iridescenceThicknessRange=t.iridescenceThicknessRange),void 0!==t.transmission&&(n.transmission=t.transmission),void 0!==t.thickness&&(n.thickness=t.thickness),void 0!==t.attenuationDistance&&(n.attenuationDistance=t.attenuationDistance),void 0!==t.attenuationColor&&void 0!==n.attenuationColor&&n.attenuationColor.setHex(t.attenuationColor),void 0!==t.fog&&(n.fog=t.fog),void 0!==t.flatShading&&(n.flatShading=t.flatShading),void 0!==t.blending&&(n.blending=t.blending),void 0!==t.combine&&(n.combine=t.combine),void 0!==t.side&&(n.side=t.side),void 0!==t.shadowSide&&(n.shadowSide=t.shadowSide),void 0!==t.opacity&&(n.opacity=t.opacity),void 0!==t.transparent&&(n.transparent=t.transparent),void 0!==t.alphaTest&&(n.alphaTest=t.alphaTest),void 0!==t.depthTest&&(n.depthTest=t.depthTest),void 0!==t.depthWrite&&(n.depthWrite=t.depthWrite),void 0!==t.colorWrite&&(n.colorWrite=t.colorWrite),void 0!==t.stencilWrite&&(n.stencilWrite=t.stencilWrite),void 0!==t.stencilWriteMask&&(n.stencilWriteMask=t.stencilWriteMask),void 0!==t.stencilFunc&&(n.stencilFunc=t.stencilFunc),void 0!==t.stencilRef&&(n.stencilRef=t.stencilRef),void 0!==t.stencilFuncMask&&(n.stencilFuncMask=t.stencilFuncMask),void 0!==t.stencilFail&&(n.stencilFail=t.stencilFail),void 0!==t.stencilZFail&&(n.stencilZFail=t.stencilZFail),void 0!==t.stencilZPass&&(n.stencilZPass=t.stencilZPass),void 0!==t.wireframe&&(n.wireframe=t.wireframe),void 0!==t.wireframeLinewidth&&(n.wireframeLinewidth=t.wireframeLinewidth),void 0!==t.wireframeLinecap&&(n.wireframeLinecap=t.wireframeLinecap),void 0!==t.wireframeLinejoin&&(n.wireframeLinejoin=t.wireframeLinejoin),void 0!==t.rotation&&(n.rotation=t.rotation),1!==t.linewidth&&(n.linewidth=t.linewidth),void 0!==t.dashSize&&(n.dashSize=t.dashSize),void 0!==t.gapSize&&(n.gapSize=t.gapSize),void 0!==t.scale&&(n.scale=t.scale),void 0!==t.polygonOffset&&(n.polygonOffset=t.polygonOffset),void 0!==t.polygonOffsetFactor&&(n.polygonOffsetFactor=t.polygonOffsetFactor),void 0!==t.polygonOffsetUnits&&(n.polygonOffsetUnits=t.polygonOffsetUnits),void 0!==t.dithering&&(n.dithering=t.dithering),void 0!==t.alphaToCoverage&&(n.alphaToCoverage=t.alphaToCoverage),void 0!==t.premultipliedAlpha&&(n.premultipliedAlpha=t.premultipliedAlpha),void 0!==t.forceSinglePass&&(n.forceSinglePass=t.forceSinglePass),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.toneMapped&&(n.toneMapped=t.toneMapped),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.vertexColors&&("number"==typeof t.vertexColors?n.vertexColors=t.vertexColors>0:n.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(n.uniforms[e]={},r.type){case"t":n.uniforms[e].value=i(r.value);break;case"c":n.uniforms[e].value=(new Zt).setHex(r.value);break;case"v2":n.uniforms[e].value=(new It).fromArray(r.value);break;case"v3":n.uniforms[e].value=(new oe).fromArray(r.value);break;case"v4":n.uniforms[e].value=(new ie).fromArray(r.value);break;case"m3":n.uniforms[e].value=(new Dt).fromArray(r.value);break;case"m4":n.uniforms[e].value=(new Ue).fromArray(r.value);break;default:n.uniforms[e].value=r.value}}if(void 0!==t.defines&&(n.defines=t.defines),void 0!==t.vertexShader&&(n.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(n.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(n.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)n.extensions[e]=t.extensions[e];if(void 0!==t.size&&(n.size=t.size),void 0!==t.sizeAttenuation&&(n.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(n.map=i(t.map)),void 0!==t.matcap&&(n.matcap=i(t.matcap)),void 0!==t.alphaMap&&(n.alphaMap=i(t.alphaMap)),void 0!==t.bumpMap&&(n.bumpMap=i(t.bumpMap)),void 0!==t.bumpScale&&(n.bumpScale=t.bumpScale),void 0!==t.normalMap&&(n.normalMap=i(t.normalMap)),void 0!==t.normalMapType&&(n.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),n.normalScale=(new It).fromArray(e)}return void 0!==t.displacementMap&&(n.displacementMap=i(t.displacementMap)),void 0!==t.displacementScale&&(n.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(n.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(n.roughnessMap=i(t.roughnessMap)),void 0!==t.metalnessMap&&(n.metalnessMap=i(t.metalnessMap)),void 0!==t.emissiveMap&&(n.emissiveMap=i(t.emissiveMap)),void 0!==t.emissiveIntensity&&(n.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(n.specularMap=i(t.specularMap)),void 0!==t.specularIntensityMap&&(n.specularIntensityMap=i(t.specularIntensityMap)),void 0!==t.specularColorMap&&(n.specularColorMap=i(t.specularColorMap)),void 0!==t.envMap&&(n.envMap=i(t.envMap)),void 0!==t.envMapIntensity&&(n.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(n.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(n.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(n.lightMap=i(t.lightMap)),void 0!==t.lightMapIntensity&&(n.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(n.aoMap=i(t.aoMap)),void 0!==t.aoMapIntensity&&(n.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(n.gradientMap=i(t.gradientMap)),void 0!==t.clearcoatMap&&(n.clearcoatMap=i(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(n.clearcoatRoughnessMap=i(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(n.clearcoatNormalMap=i(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(n.clearcoatNormalScale=(new It).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(n.iridescenceMap=i(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(n.iridescenceThicknessMap=i(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(n.transmissionMap=i(t.transmissionMap)),void 0!==t.thicknessMap&&(n.thicknessMap=i(t.thicknessMap)),void 0!==t.sheenColorMap&&(n.sheenColorMap=i(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(n.sheenRoughnessMap=i(t.sheenRoughnessMap)),n}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:Rl,SpriteMaterial:ra,RawShaderMaterial:Pl,ShaderMaterial:rn,PointsMaterial:$a,MeshPhysicalMaterial:Dl,MeshStandardMaterial:Il,MeshPhongMaterial:Nl,MeshToonMaterial:Ol,MeshNormalMaterial:zl,MeshLambertMaterial:Ul,MeshDepthMaterial:zs,MeshDistanceMaterial:Us,MeshBasicMaterial:bi,MeshMatcapMaterial:Bl,LineDashedMaterial:Fl,LineBasicMaterial:Ga,Material:Mi}[t]}}class Oc{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let i=0,n=t.length;i0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(i,n,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(i[t]!==i[t+e]){a.setValue(i,n);break}}saveOriginalState(){const t=this.binding,e=this.buffer,i=this.valueSize,n=i*this._origIndex;t.getValue(e,n);for(let t=i,r=n;t!==r;++t)e[t]=e[n+t%i];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let i=t;i=.5)for(let n=0;n!==r;++n)t[e+n]=t[i+n]}_slerp(t,e,i,n){ae.slerpFlat(t,e,t,e,t,i,n)}_slerpAdditive(t,e,i,n,r){const s=this._workIndex*r;ae.multiplyQuaternionsFlat(t,s,t,e,t,i),ae.slerpFlat(t,e,t,e,t,s,n)}_lerp(t,e,i,n,r){const s=1-n;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[i+a]*n}}_lerpAdditive(t,e,i,n,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[i+s]*n}}}const rh="\\[\\]\\.:\\/",sh=new RegExp("["+rh+"]","g"),ah="[^"+rh+"]",oh="[^"+rh.replace("\\.","")+"]",lh=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",ah)+/(WCOD+)?/.source.replace("WCOD",oh)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",ah)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",ah)+"$"),ch=["material","materials","bones","map"];class hh{constructor(t,e,i){this.path=e,this.parsedPath=i||hh.parseTrackName(e),this.node=hh.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,i){return t&&t.isAnimationObjectGroup?new hh.Composite(t,e,i):new hh(t,e,i)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(sh,"")}static parseTrackName(t){const e=lh.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const i={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},n=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==n&&-1!==n){const t=i.nodeName.substring(n+1);-1!==ch.indexOf(t)&&(i.nodeName=i.nodeName.substring(0,n),i.objectName=t)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return i}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const i=t.skeleton.getBoneByName(e);if(void 0!==i)return i}if(t.children){const i=function(t){for(let n=0;n0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===lt)for(let i=0,n=t.length;i!==n;++i)t[i].evaluate(s),e[i].accumulateAdditive(a);else for(let i=0,r=t.length;i!==r;++i)t[i].evaluate(s),e[i].accumulate(n,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const i=this._weightInterpolant;if(null!==i){const n=i.evaluate(t)[0];e*=n,t>i.parameterPositions[1]&&(this.stopFading(),0===n&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const i=this._timeScaleInterpolant;if(null!==i){e*=i.evaluate(t)[0],t>i.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,i=this.loop;let n=this.time+t,r=this._loopCount;const s=2202===i;if(0===t)return-1===r?n:s&&1==(1&r)?e-n:n;if(2200===i){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(n>=e)n=e;else{if(!(n<0)){this.time=n;break t}n=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),n>=e||n<0){const i=Math.floor(n/e);n-=e*i,r+=Math.abs(i);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,n=t>0?e:0,this.time=n,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=n,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:i})}}else this.time=n;if(s&&1==(1&r))return e-n}return n}_setEndings(t,e,i){const n=this._interpolantSettings;i?(n.endingStart=st,n.endingEnd=st):(n.endingStart=t?this.zeroSlopeAtStart?st:rt:at,n.endingEnd=e?this.zeroSlopeAtEnd?st:rt:at)}_scheduleFading(t,e,i){const n=this._mixer,r=n.time;let s=this._weightInterpolant;null===s&&(s=n._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=i,this}}const dh=new Float32Array(1);class ph{constructor(t){this.value=t}clone(){return new ph(void 0===this.value.clone?this.value:this.value.clone())}}let mh=0;function fh(t,e){return t.distance-e.distance}function gh(t,e,i,n){if(t.layers.test(e.layers)&&t.raycast(e,i),!0===n){const n=t.children;for(let t=0,r=n.length;t>-e-14,n[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(n[t]=e+15<<10,n[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(n[t]=31744,n[256|t]=64512,r[t]=24,r[256|t]=24):(n[t]=31744,n[256|t]=64512,r[t]=13,r[256|t]=13)}const s=new Uint32Array(2048),a=new Uint32Array(64),o=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,i=0;for(;0==(8388608&e);)e<<=1,i-=8388608;e&=-8388609,i+=947912704,s[t]=e|i}for(let t=1024;t<2048;++t)s[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)a[t]=t<<23;a[31]=1199570944,a[32]=2147483648;for(let t=33;t<63;++t)a[t]=2147483648+(t-32<<23);a[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(o[t]=1024);return{floatView:e,uint32View:i,baseTable:n,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}var kh=Object.freeze({__proto__:null,fromHalfFloat:function(t){const e=t>>10;return Bh.uint32View[0]=Bh.mantissaTable[Bh.offsetTable[e]+(1023&t)]+Bh.exponentTable[e],Bh.floatView[0]},toHalfFloat:function(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=St(t,-65504,65504),Bh.floatView[0]=t;const e=Bh.uint32View[0],i=e>>23&511;return Bh.baseTable[i]+((8388607&e)>>Bh.shiftTable[i])}});"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:e}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=e),t.ACESFilmicToneMapping=4,t.AddEquation=i,t.AddOperation=2,t.AdditiveAnimationBlendMode=lt,t.AdditiveBlending=2,t.AlphaFormat=1021,t.AlwaysDepth=1,t.AlwaysStencilFunc=519,t.AmbientLight=Rc,t.AmbientLightProbe=class extends Dc{constructor(t,e=1){super(void 0,e),this.isAmbientLightProbe=!0;const i=(new Zt).set(t);this.sh.coefficients[0].set(i.r,i.g,i.b).multiplyScalar(2*Math.sqrt(Math.PI))}},t.AnimationClip=sc,t.AnimationLoader=class extends hc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=new pc(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(i){try{e(r.parse(JSON.parse(i)))}catch(e){n?n(e):console.error(e),r.manager.itemError(t)}}),i,n)}parse(t){const e=[];for(let i=0;i=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,i=this._nActiveActions,n=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==i;++a){e[a]._update(n,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;t=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=n;t!==e;++t){const e=i[t],n=e[s],r=e[l];e[l]=n,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,i=this._bindings,n=i.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=n;t!==e;++t){const e=i[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const i=this._bindingsIndicesByPath;let n=i[t];const r=this._bindings;if(void 0!==n)return r[n];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);n=r.length,i[t]=n,s.push(t),a.push(e),r.push(h);for(let i=c,n=o.length;i!==n;++i){const n=o[i];h[i]=new hh(n,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,i=e[t];if(void 0!==i){const n=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=i,s[i]=o,s.pop(),r[i]=r[a],r.pop(),n[i]=n[a],n.pop()}}},t.AnimationUtils=ql,t.ArcCurve=lo,t.ArrayCamera=Vs,t.ArrowHelper=class extends li{constructor(t=new oe(0,0,1),e=new oe(0,0,0),i=1,n=16776960,r=.2*i,s=.2*r){super(),this.type="ArrowHelper",void 0===zh&&(zh=new zi,zh.setAttribute("position",new Ci([0,0,0,0,1,0],3)),Uh=new Io(0,.5,1,5,1),Uh.translate(0,-.5,0)),this.position.copy(e),this.line=new Xa(zh,new Ga({color:n,toneMapped:!1})),this.line.matrixAutoUpdate=!1,this.add(this.line),this.cone=new Ji(Uh,new bi({color:n,toneMapped:!1})),this.cone.matrixAutoUpdate=!1,this.add(this.cone),this.setDirection(t),this.setLength(i,r,s)}setDirection(t){if(t.y>.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{Oh.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(Oh,e)}}setLength(t,e=.2*t,i=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(i,e,i),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}},t.Audio=$c,t.AudioAnalyser=class{constructor(t,e=2048){this.analyser=t.context.createAnalyser(),this.analyser.fftSize=e,this.data=new Uint8Array(this.analyser.frequencyBinCount),t.getOutput().connect(this.analyser)}getFrequencyData(){return this.analyser.getByteFrequencyData(this.data),this.data}getAverageFrequency(){let t=0;const e=this.getFrequencyData();for(let i=0;ithis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return vh.copy(t).clamp(this.min,this.max).sub(t).length()}intersect(t){return this.min.max(t.min),this.max.min(t.max),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}},t.Box3=he,t.Box3Helper=class extends Ja{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new zi;n.setIndex(new Ti(i,1)),n.setAttribute("position",new Ci([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(n,new Ga({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BoxBufferGeometry=class extends $i{constructor(t,e,i,n,r,s){console.warn("THREE.BoxBufferGeometry has been renamed to THREE.BoxGeometry."),super(t,e,i,n,r,s)}},t.BoxGeometry=$i,t.BoxHelper=class extends Ja{constructor(t,e=16776960){const i=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),n=new Float32Array(24),r=new zi;r.setIndex(new Ti(i,1)),r.setAttribute("position",new Ti(n,3)),super(r,new Ga({color:e,toneMapped:!1})),this.object=t,this.type="BoxHelper",this.matrixAutoUpdate=!1,this.update()}update(t){if(void 0!==t&&console.warn("THREE.BoxHelper: .update() has no longer arguments."),void 0!==this.object&&Nh.setFromObject(this.object),Nh.isEmpty())return;const e=Nh.min,i=Nh.max,n=this.geometry.attributes.position,r=n.array;r[0]=i.x,r[1]=i.y,r[2]=i.z,r[3]=e.x,r[4]=i.y,r[5]=i.z,r[6]=e.x,r[7]=e.y,r[8]=i.z,r[9]=i.x,r[10]=e.y,r[11]=i.z,r[12]=i.x,r[13]=i.y,r[14]=e.z,r[15]=e.x,r[16]=i.y,r[17]=e.z,r[18]=e.x,r[19]=e.y,r[20]=e.z,r[21]=i.x,r[22]=e.y,r[23]=e.z,n.needsUpdate=!0,this.geometry.computeBoundingSphere()}setFromObject(t){return this.object=t,this.update(),this}copy(t,e){return super.copy(t,e),this.object=t.object,this}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BufferAttribute=Ti,t.BufferGeometry=zi,t.BufferGeometryLoader=Uc,t.ByteType=1010,t.Cache=oc,t.Camera=sn,t.CameraHelper=class extends Ja{constructor(t){const e=new zi,i=new Ga({color:16777215,vertexColors:!0,toneMapped:!1}),n=[],r=[],s={};function a(t,e){o(t),o(e)}function o(t){n.push(0,0,0),r.push(0,0,0),void 0===s[t]&&(s[t]=[]),s[t].push(n.length/3-1)}a("n1","n2"),a("n2","n4"),a("n4","n3"),a("n3","n1"),a("f1","f2"),a("f2","f4"),a("f4","f3"),a("f3","f1"),a("n1","f1"),a("n2","f2"),a("n3","f3"),a("n4","f4"),a("p","n1"),a("p","n2"),a("p","n3"),a("p","n4"),a("u1","u2"),a("u2","u3"),a("u3","u1"),a("c","t"),a("p","c"),a("cn1","cn2"),a("cn3","cn4"),a("cf1","cf2"),a("cf3","cf4"),e.setAttribute("position",new Ci(n,3)),e.setAttribute("color",new Ci(r,3)),super(e,i),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update();const l=new Zt(16755200),c=new Zt(16711680),h=new Zt(43775),u=new Zt(16777215),d=new Zt(3355443);this.setColors(l,c,h,u,d)}setColors(t,e,i,n,r){const s=this.geometry.getAttribute("color");s.setXYZ(0,t.r,t.g,t.b),s.setXYZ(1,t.r,t.g,t.b),s.setXYZ(2,t.r,t.g,t.b),s.setXYZ(3,t.r,t.g,t.b),s.setXYZ(4,t.r,t.g,t.b),s.setXYZ(5,t.r,t.g,t.b),s.setXYZ(6,t.r,t.g,t.b),s.setXYZ(7,t.r,t.g,t.b),s.setXYZ(8,t.r,t.g,t.b),s.setXYZ(9,t.r,t.g,t.b),s.setXYZ(10,t.r,t.g,t.b),s.setXYZ(11,t.r,t.g,t.b),s.setXYZ(12,t.r,t.g,t.b),s.setXYZ(13,t.r,t.g,t.b),s.setXYZ(14,t.r,t.g,t.b),s.setXYZ(15,t.r,t.g,t.b),s.setXYZ(16,t.r,t.g,t.b),s.setXYZ(17,t.r,t.g,t.b),s.setXYZ(18,t.r,t.g,t.b),s.setXYZ(19,t.r,t.g,t.b),s.setXYZ(20,t.r,t.g,t.b),s.setXYZ(21,t.r,t.g,t.b),s.setXYZ(22,t.r,t.g,t.b),s.setXYZ(23,t.r,t.g,t.b),s.setXYZ(24,e.r,e.g,e.b),s.setXYZ(25,e.r,e.g,e.b),s.setXYZ(26,e.r,e.g,e.b),s.setXYZ(27,e.r,e.g,e.b),s.setXYZ(28,e.r,e.g,e.b),s.setXYZ(29,e.r,e.g,e.b),s.setXYZ(30,e.r,e.g,e.b),s.setXYZ(31,e.r,e.g,e.b),s.setXYZ(32,i.r,i.g,i.b),s.setXYZ(33,i.r,i.g,i.b),s.setXYZ(34,i.r,i.g,i.b),s.setXYZ(35,i.r,i.g,i.b),s.setXYZ(36,i.r,i.g,i.b),s.setXYZ(37,i.r,i.g,i.b),s.setXYZ(38,n.r,n.g,n.b),s.setXYZ(39,n.r,n.g,n.b),s.setXYZ(40,r.r,r.g,r.b),s.setXYZ(41,r.r,r.g,r.b),s.setXYZ(42,r.r,r.g,r.b),s.setXYZ(43,r.r,r.g,r.b),s.setXYZ(44,r.r,r.g,r.b),s.setXYZ(45,r.r,r.g,r.b),s.setXYZ(46,r.r,r.g,r.b),s.setXYZ(47,r.r,r.g,r.b),s.setXYZ(48,r.r,r.g,r.b),s.setXYZ(49,r.r,r.g,r.b),s.needsUpdate=!0}update(){const t=this.geometry,e=this.pointMap;Ih.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),Dh("c",e,t,Ih,0,0,-1),Dh("t",e,t,Ih,0,0,1),Dh("n1",e,t,Ih,-1,-1,-1),Dh("n2",e,t,Ih,1,-1,-1),Dh("n3",e,t,Ih,-1,1,-1),Dh("n4",e,t,Ih,1,1,-1),Dh("f1",e,t,Ih,-1,-1,1),Dh("f2",e,t,Ih,1,-1,1),Dh("f3",e,t,Ih,-1,1,1),Dh("f4",e,t,Ih,1,1,1),Dh("u1",e,t,Ih,.7,1.1,-1),Dh("u2",e,t,Ih,-.7,1.1,-1),Dh("u3",e,t,Ih,0,2,-1),Dh("cf1",e,t,Ih,-1,0,1),Dh("cf2",e,t,Ih,1,0,1),Dh("cf3",e,t,Ih,0,-1,1),Dh("cf4",e,t,Ih,0,1,1),Dh("cn1",e,t,Ih,-1,0,-1),Dh("cn2",e,t,Ih,1,0,-1),Dh("cn3",e,t,Ih,0,-1,-1),Dh("cn4",e,t,Ih,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasTexture=class extends ee{constructor(t,e,i,n,r,s,a,o,l){super(t,e,i,n,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}},t.CapsuleBufferGeometry=class extends Ro{constructor(t,e,i,n){console.warn("THREE.CapsuleBufferGeometry has been renamed to THREE.CapsuleGeometry."),super(t,e,i,n)}},t.CapsuleGeometry=Ro,t.CatmullRomCurve3=fo,t.CineonToneMapping=3,t.CircleBufferGeometry=class extends Po{constructor(t,e,i,n){console.warn("THREE.CircleBufferGeometry has been renamed to THREE.CircleGeometry."),super(t,e,i,n)}},t.CircleGeometry=Po,t.ClampToEdgeWrapping=h,t.Clock=qc,t.Color=Zt,t.ColorKeyframeTrack=Ql,t.ColorManagement=Vt,t.CompressedArrayTexture=class extends so{constructor(t,e,i,n,r,s){super(t,e,i,r,s),this.isCompressedArrayTexture=!0,this.image.depth=n,this.wrapR=h}},t.CompressedTexture=so,t.CompressedTextureLoader=class extends hc{constructor(t){super(t)}load(t,e,i,n){const r=this,s=[],a=new so,o=new pc(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const i=r.parse(t,!0);s[c]={width:i.width,height:i.height,format:i.format,mipmaps:i.mipmaps},l+=1,6===l&&(1===i.mipmapCount&&(a.minFilter=f),a.image=s,a.format=i.format,a.needsUpdate=!0,e&&e(a))}),i,n)}if(Array.isArray(t))for(let e=0,i=t.length;e0){const i=new lc(e);r=new mc(i),r.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e0){n=new mc(this.manager),n.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e1)for(let i=0;iNumber.EPSILON){if(l<0&&(i=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===i.y){if(t.x===i.x)return!0}else{const e=l*(t.x-i.x)-o*(t.y-i.y);if(0===e)return!0;if(e<0)continue;n=!n}}else{if(t.y!==i.y)continue;if(a.x<=t.x&&t.x<=i.x||i.x<=t.x&&t.x<=a.x)return!0}}return n}const i=pl.isClockWise,n=this.subPaths;if(0===n.length)return[];let r,s,a;const o=[];if(1===n.length)return s=n[0],a=new Go,a.curves=s.curves,o.push(a),o;let l=!i(n[0].getPoints());l=t?!l:l;const c=[],h=[];let u,d,p=[],m=0;h[m]=void 0,p[m]=[];for(let e=0,a=n.length;e1){let t=!1,i=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}},t.WebGL1Renderer=Ks,t.WebGL3DRenderTarget=class extends ne{constructor(t=1,e=1,i=1){super(t,e),this.isWebGL3DRenderTarget=!0,this.depth=i,this.texture=new se(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLArrayRenderTarget=class extends ne{constructor(t=1,e=1,i=1){super(t,e),this.isWebGLArrayRenderTarget=!0,this.depth=i,this.texture=new re(null,t,e,i),this.texture.isRenderTargetTexture=!0}},t.WebGLCubeRenderTarget=hn,t.WebGLMultipleRenderTargets=class extends ne{constructor(t=1,e=1,i=1,n={}){super(t,e,n),this.isWebGLMultipleRenderTargets=!0;const r=this.texture;this.texture=[];for(let t=0;t>>>>>> mrdoob-dev +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).THREE={})}(this,(function(t){"use strict";const e="153dev",n=0,i=1,r=2,s=1,a=2,o=3,l=0,c=1,h=2,u=0,d=1,p=2,m=3,f=4,g=5,v=100,_=101,y=102,x=103,M=104,S=200,b=201,T=202,E=203,w=204,A=205,R=206,C=207,L=208,P=209,I=210,U=0,D=1,N=2,O=3,F=4,B=5,z=6,G=7,H=0,k=1,V=2,W=0,X=1,j=2,q=3,Y=4,Z=5,J=300,K=301,$=302,Q=303,tt=304,et=306,nt=1e3,it=1001,rt=1002,st=1003,at=1004,ot=1005,lt=1006,ct=1007,ht=1008,ut=1009,dt=1010,pt=1011,mt=1012,ft=1013,gt=1014,vt=1015,_t=1016,yt=1017,xt=1018,Mt=1020,St=1021,bt=1023,Tt=1024,Et=1025,wt=1026,At=1027,Rt=1028,Ct=1029,Lt=1030,Pt=1031,It=1033,Ut=33776,Dt=33777,Nt=33778,Ot=33779,Ft=35840,Bt=35841,zt=35842,Gt=35843,Ht=36196,kt=37492,Vt=37496,Wt=37808,Xt=37809,jt=37810,qt=37811,Yt=37812,Zt=37813,Jt=37814,Kt=37815,$t=37816,Qt=37817,te=37818,ee=37819,ne=37820,ie=37821,re=36492,se=36283,ae=36284,oe=36285,le=36286,ce=2300,he=2301,ue=2302,de=2400,pe=2401,me=2402,fe=2500,ge=2501,ve=3e3,_e=3001,ye=3201,xe=0,Me=1,Se="",be="srgb",Te="srgb-linear",Ee="display-p3",we=7680,Ae=512,Re=513,Ce=514,Le=515,Pe=516,Ie=517,Ue=518,De=519,Ne=35044,Oe="300 es",Fe=1035;class Be{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[t]&&(n[t]=[]),-1===n[t].indexOf(e)&&n[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[t]&&-1!==n[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const n=this._listeners[t];if(void 0!==n){const t=n.indexOf(e);-1!==t&&n.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const n=e.slice(0);for(let e=0,i=n.length;e>8&255]+ze[t>>16&255]+ze[t>>24&255]+"-"+ze[255&e]+ze[e>>8&255]+"-"+ze[e>>16&15|64]+ze[e>>24&255]+"-"+ze[63&n|128]+ze[n>>8&255]+"-"+ze[n>>16&255]+ze[n>>24&255]+ze[255&i]+ze[i>>8&255]+ze[i>>16&255]+ze[i>>24&255]).toLowerCase()}function We(t,e,n){return Math.max(e,Math.min(n,t))}function Xe(t,e){return(t%e+e)%e}function je(t,e,n){return(1-n)*t+n*e}function qe(t){return 0==(t&t-1)&&0!==t}function Ye(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function Ze(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}function Je(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return t/4294967295;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int32Array:return Math.max(t/2147483647,-1);case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function Ke(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return Math.round(4294967295*t);case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int32Array:return Math.round(2147483647*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}const $e={DEG2RAD:He,RAD2DEG:ke,generateUUID:Ve,clamp:We,euclideanModulo:Xe,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:je,damp:function(t,e,n,i){return je(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(Xe(t,2*e)-e)},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(Ge=t);let e=Ge+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*He},radToDeg:function(t){return t*ke},isPowerOfTwo:qe,ceilPowerOfTwo:Ye,floorPowerOfTwo:Ze,setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Ke,denormalize:Je};class Qe{constructor(t=0,e=0){Qe.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(We(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class tn{constructor(t,e,n,i,r,s,a,o,l){tn.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l)}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],v=i[1],_=i[4],y=i[7],x=i[2],M=i[5],S=i[8];return r[0]=s*m+a*v+o*x,r[3]=s*f+a*_+o*M,r[6]=s*g+a*y+o*S,r[1]=l*m+c*v+h*x,r[4]=l*f+c*_+h*M,r[7]=l*g+c*y+h*S,r[2]=u*m+d*v+p*x,r[5]=u*f+d*_+p*M,r[8]=u*g+d*y+p*S,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(en.makeScale(t,e)),this}rotate(t){return this.premultiply(en.makeRotation(-t)),this}translate(t,e){return this.premultiply(en.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const en=new tn;function nn(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const rn={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function sn(t,e){return new rn[t](e)}function an(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}const on={};function ln(t){t in on||(on[t]=!0,console.warn(t))}function cn(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function hn(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}const un=(new tn).fromArray([.8224621,.0331941,.0170827,.177538,.9668058,.0723974,-1e-7,1e-7,.9105199]),dn=(new tn).fromArray([1.2249401,-.0420569,-.0196376,-.2249404,1.0420571,-.0786361,1e-7,0,1.0982735]);const pn={[Te]:t=>t,[be]:t=>t.convertSRGBToLinear(),[Ee]:function(t){return t.convertSRGBToLinear().applyMatrix3(dn)}},mn={[Te]:t=>t,[be]:t=>t.convertLinearToSRGB(),[Ee]:function(t){return t.applyMatrix3(un).convertLinearToSRGB()}},fn={enabled:!0,get legacyMode(){return console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),!this.enabled},set legacyMode(t){console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),this.enabled=!t},get workingColorSpace(){return Te},set workingColorSpace(t){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(t,e,n){if(!1===this.enabled||e===n||!e||!n)return t;const i=pn[e],r=mn[n];if(void 0===i||void 0===r)throw new Error(`Unsupported color space conversion, "${e}" to "${n}".`);return r(i(t))},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)}};let gn;class vn{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===gn&&(gn=an("canvas")),gn.width=t.width,gn.height=t.height;const n=gn.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=gn}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=an("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const i=n.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==J)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case nt:t.x=t.x-Math.floor(t.x);break;case it:t.x=t.x<0?0:1;break;case rt:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case nt:t.y=t.y-Math.floor(t.y);break;case it:t.y=t.y<0?0:1;break;case rt:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}get encoding(){return ln("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace===be?_e:ve}set encoding(t){ln("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace=t===_e?be:Se}}Sn.DEFAULT_IMAGE=null,Sn.DEFAULT_MAPPING=J,Sn.DEFAULT_ANISOTROPY=1;class bn{constructor(t=0,e=0,n=0,i=1){bn.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,i,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-i)*t}else if(n>a&&n>h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(We(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=n,this._y=i,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=Math.random(),e=Math.sqrt(1-t),n=Math.sqrt(t),i=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(i),n*Math.sin(r),n*Math.cos(r),e*Math.sin(i))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Rn{constructor(t=0,e=0,n=0){Rn.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(Ln.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(Ln.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*i-a*n,c=o*n+a*e-r*i,h=o*i+r*n-s*e,u=-r*e-s*n-a*i;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return Cn.copy(this).projectOnVector(t),this.sub(Cn)}reflect(t){return this.sub(Cn.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(We(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,n=Math.sqrt(1-t**2);return this.x=n*Math.cos(e),this.y=n*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Cn=new Rn,Ln=new An;class Pn{constructor(t=new Rn(1/0,1/0,1/0),e=new Rn(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,n=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,Un),Un.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Hn),kn.subVectors(this.max,Hn),Nn.subVectors(t.a,Hn),On.subVectors(t.b,Hn),Fn.subVectors(t.c,Hn),Bn.subVectors(On,Nn),zn.subVectors(Fn,On),Gn.subVectors(Nn,Fn);let e=[0,-Bn.z,Bn.y,0,-zn.z,zn.y,0,-Gn.z,Gn.y,Bn.z,0,-Bn.x,zn.z,0,-zn.x,Gn.z,0,-Gn.x,-Bn.y,Bn.x,0,-zn.y,zn.x,0,-Gn.y,Gn.x,0];return!!Xn(e,Nn,On,Fn,kn)&&(e=[1,0,0,0,1,0,0,0,1],!!Xn(e,Nn,On,Fn,kn)&&(Vn.crossVectors(Bn,zn),e=[Vn.x,Vn.y,Vn.z],Xn(e,Nn,On,Fn,kn)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Un).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(Un).length()),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(In[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),In[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),In[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),In[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),In[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),In[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),In[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),In[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(In)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const In=[new Rn,new Rn,new Rn,new Rn,new Rn,new Rn,new Rn,new Rn],Un=new Rn,Dn=new Pn,Nn=new Rn,On=new Rn,Fn=new Rn,Bn=new Rn,zn=new Rn,Gn=new Rn,Hn=new Rn,kn=new Rn,Vn=new Rn,Wn=new Rn;function Xn(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){Wn.fromArray(t,s);const a=r.x*Math.abs(Wn.x)+r.y*Math.abs(Wn.y)+r.z*Math.abs(Wn.z),o=e.dot(Wn),l=n.dot(Wn),c=i.dot(Wn);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const jn=new Pn,qn=new Rn,Yn=new Rn;class Zn{constructor(t=new Rn,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):jn.setFromPoints(t).getCenter(n);let i=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;qn.subVectors(t,this.center);const e=qn.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.addScaledVector(qn,n/t),this.radius+=n}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Yn.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(qn.copy(t.center).add(Yn)),this.expandByPoint(qn.copy(t.center).sub(Yn))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Jn=new Rn,Kn=new Rn,$n=new Rn,Qn=new Rn,ti=new Rn,ei=new Rn,ni=new Rn;class ii{constructor(t=new Rn,e=new Rn(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,Jn)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=Jn.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Jn.copy(this.origin).addScaledVector(this.direction,e),Jn.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){Kn.copy(t).add(e).multiplyScalar(.5),$n.copy(e).sub(t).normalize(),Qn.copy(this.origin).sub(Kn);const r=.5*t.distanceTo(e),s=-this.direction.dot($n),a=Qn.dot(this.direction),o=-Qn.dot($n),l=Qn.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(Kn).addScaledVector($n,u),d}intersectSphere(t,e){Jn.subVectors(t.center,this.origin);const n=Jn.dot(this.direction),i=Jn.dot(Jn)-n*n,r=t.radius*t.radius;if(i>r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,i,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),n>s||r>i?null:((r>n||isNaN(n))&&(n=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),n>o||a>i?null:((a>n||n!=n)&&(n=a),(o=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,Jn)}intersectTriangle(t,e,n,i,r){ti.subVectors(e,t),ei.subVectors(n,t),ni.crossVectors(ti,ei);let s,a=this.direction.dot(ni);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}Qn.subVectors(this.origin,t);const o=s*this.direction.dot(ei.crossVectors(Qn,ei));if(o<0)return null;const l=s*this.direction.dot(ti.cross(Qn));if(l<0)return null;if(o+l>a)return null;const c=-s*Qn.dot(ni);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class ri{constructor(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){ri.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f)}set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new ri).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/si.setFromMatrixColumn(t,0).length(),r=1/si.setFromMatrixColumn(t,1).length(),s=1/si.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=n*h-i,e[2]=i*h-n,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(oi,t,li)}lookAt(t,e,n){const i=this.elements;return ui.subVectors(t,e),0===ui.lengthSq()&&(ui.z=1),ui.normalize(),ci.crossVectors(n,ui),0===ci.lengthSq()&&(1===Math.abs(n.z)?ui.x+=1e-4:ui.z+=1e-4,ui.normalize(),ci.crossVectors(n,ui)),ci.normalize(),hi.crossVectors(ui,ci),i[0]=ci.x,i[4]=hi.x,i[8]=ui.x,i[1]=ci.y,i[5]=hi.y,i[9]=ui.y,i[2]=ci.z,i[6]=hi.z,i[10]=ui.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],v=n[3],_=n[7],y=n[11],x=n[15],M=i[0],S=i[4],b=i[8],T=i[12],E=i[1],w=i[5],A=i[9],R=i[13],C=i[2],L=i[6],P=i[10],I=i[14],U=i[3],D=i[7],N=i[11],O=i[15];return r[0]=s*M+a*E+o*C+l*U,r[4]=s*S+a*w+o*L+l*D,r[8]=s*b+a*A+o*P+l*N,r[12]=s*T+a*R+o*I+l*O,r[1]=c*M+h*E+u*C+d*U,r[5]=c*S+h*w+u*L+d*D,r[9]=c*b+h*A+u*P+d*N,r[13]=c*T+h*R+u*I+d*O,r[2]=p*M+m*E+f*C+g*U,r[6]=p*S+m*w+f*L+g*D,r[10]=p*b+m*A+f*P+g*N,r[14]=p*T+m*R+f*I+g*O,r[3]=v*M+_*E+y*C+x*U,r[7]=v*S+_*w+y*L+x*D,r[11]=v*b+_*A+y*P+x*N,r[15]=v*T+_*R+y*I+x*O,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],i=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,_=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,y=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,x=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+n*_+i*y+r*x;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const S=1/M;return t[0]=v*S,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*S,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*S,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*S,t[4]=_*S,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*S,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*S,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*S,t[8]=y*S,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*S,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*S,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*S,t[12]=x*S,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*S,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*S,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*S,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,_=o*c,y=o*h,x=n.x,M=n.y,S=n.z;return i[0]=(1-(m+g))*x,i[1]=(d+y)*x,i[2]=(p-_)*x,i[3]=0,i[4]=(d-y)*M,i[5]=(1-(u+g))*M,i[6]=(f+v)*M,i[7]=0,i[8]=(p+_)*S,i[9]=(f-v)*S,i[10]=(1-(u+m))*S,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=si.set(i[0],i[1],i[2]).length();const s=si.set(i[4],i[5],i[6]).length(),a=si.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],ai.copy(this);const o=1/r,l=1/s,c=1/a;return ai.elements[0]*=o,ai.elements[1]*=o,ai.elements[2]*=o,ai.elements[4]*=l,ai.elements[5]*=l,ai.elements[6]*=l,ai.elements[8]*=c,ai.elements[9]*=c,ai.elements[10]*=c,e.setFromRotationMatrix(ai),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s){const a=this.elements,o=2*r/(e-t),l=2*r/(n-i),c=(e+t)/(e-t),h=(n+i)/(n-i),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,n,i,r,s){const a=this.elements,o=1/(e-t),l=1/(n-i),c=1/(s-r),h=(e+t)*o,u=(n+i)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const si=new Rn,ai=new ri,oi=new Rn(0,0,0),li=new Rn(1,1,1),ci=new Rn,hi=new Rn,ui=new Rn,di=new ri,pi=new An;class mi{constructor(t=0,e=0,n=0,i=mi.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(We(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-We(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(We(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-We(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(We(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-We(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return di.makeRotationFromQuaternion(t),this.setFromRotationMatrix(di,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return pi.setFromEuler(this),this.setFromQuaternion(pi,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}mi.DEFAULT_ORDER="XYZ";class fi{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0&&(n=n.concat(r))}return n}getWorldPosition(t){return this.updateWorldMatrix(!0,!1),t.setFromMatrixPosition(this.matrixWorld)}getWorldQuaternion(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(Mi,t,Si),t}getWorldScale(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(Mi,bi,t),t}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(e[8],e[9],e[10]).normalize()}raycast(){}traverse(t){t(this);const e=this.children;for(let n=0,i=e.length;n0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const n=e.shapes;if(Array.isArray(n))for(let e=0,i=n.length;e0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(n.geometries=e),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),a.length>0&&(n.images=a),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){Li.subVectors(i,e),Pi.subVectors(n,e),Ii.subVectors(t,e);const s=Li.dot(Li),a=Li.dot(Pi),o=Li.dot(Ii),l=Pi.dot(Pi),c=Pi.dot(Ii),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,n,i){return this.getBarycoord(t,e,n,i,Ui),Ui.x>=0&&Ui.y>=0&&Ui.x+Ui.y<=1}static getUV(t,e,n,i,r,s,a,o){return!1===Gi&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),Gi=!0),this.getInterpolation(t,e,n,i,r,s,a,o)}static getInterpolation(t,e,n,i,r,s,a,o){return this.getBarycoord(t,e,n,i,Ui),o.setScalar(0),o.addScaledVector(r,Ui.x),o.addScaledVector(s,Ui.y),o.addScaledVector(a,Ui.z),o}static isFrontFacing(t,e,n,i){return Li.subVectors(n,e),Pi.subVectors(t,e),Li.cross(Pi).dot(i)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return Li.subVectors(this.c,this.b),Pi.subVectors(this.a,this.b),.5*Li.cross(Pi).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Hi.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Hi.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return!1===Gi&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),Gi=!0),Hi.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}getInterpolation(t,e,n,i,r){return Hi.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return Hi.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Hi.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;Di.subVectors(i,n),Ni.subVectors(r,n),Fi.subVectors(t,n);const o=Di.dot(Fi),l=Ni.dot(Fi);if(o<=0&&l<=0)return e.copy(n);Bi.subVectors(t,i);const c=Di.dot(Bi),h=Ni.dot(Bi);if(c>=0&&h<=c)return e.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(n).addScaledVector(Di,s);zi.subVectors(t,r);const d=Di.dot(zi),p=Ni.dot(zi);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(n).addScaledVector(Ni,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return Oi.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(Oi,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(Di,s).addScaledVector(Ni,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let ki=0;class Vi extends Be{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:ki++}),this.uuid=Ve(),this.name="",this.type="Material",this.blending=d,this.side=l,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.blendSrc=w,this.blendDst=A,this.blendEquation=v,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=O,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=we,this.stencilZFail=we,this.stencilZPass=we,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.forceSinglePass=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[e]=n:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),void 0!==this.anisotropy&&(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==d&&(n.blending=this.blending),this.side!==l&&(n.side=this.side),this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=this.transparent),n.depthFunc=this.depthFunc,n.depthTest=this.depthTest,n.depthWrite=this.depthWrite,n.colorWrite=this.colorWrite,n.stencilWrite=this.stencilWrite,n.stencilWriteMask=this.stencilWriteMask,n.stencilFunc=this.stencilFunc,n.stencilRef=this.stencilRef,n.stencilFuncMask=this.stencilFuncMask,n.stencilFail=this.stencilFail,n.stencilZFail=this.stencilZFail,n.stencilZPass=this.stencilZPass,void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(n.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.forceSinglePass&&(n.forceSinglePass=this.forceSinglePass),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=this.flatShading),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(n.textures=e),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}const Wi={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Xi={h:0,s:0,l:0},ji={h:0,s:0,l:0};function qi(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}class Yi{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(void 0===e&&void 0===n){const e=t;e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=be){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,fn.toWorkingColorSpace(this,e),this}setRGB(t,e,n,i=fn.workingColorSpace){return this.r=t,this.g=e,this.b=n,fn.toWorkingColorSpace(this,i),this}setHSL(t,e,n,i=fn.workingColorSpace){if(t=Xe(t,1),e=We(e,0,1),n=We(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=qi(r,i,t+1/3),this.g=qi(r,i,t),this.b=qi(r,i,t-1/3)}return fn.toWorkingColorSpace(this,i),this}setStyle(t,e=be){function n(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const s=i[1],a=i[2];switch(s){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(n,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=be){const n=Wi[t.toLowerCase()];return void 0!==n?this.setHex(n,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=cn(t.r),this.g=cn(t.g),this.b=cn(t.b),this}copyLinearToSRGB(t){return this.r=hn(t.r),this.g=hn(t.g),this.b=hn(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=be){return fn.fromWorkingColorSpace(Zi.copy(this),t),65536*Math.round(We(255*Zi.r,0,255))+256*Math.round(We(255*Zi.g,0,255))+Math.round(We(255*Zi.b,0,255))}getHexString(t=be){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=fn.workingColorSpace){fn.fromWorkingColorSpace(Zi.copy(this),e);const n=Zi.r,i=Zi.g,r=Zi.b,s=Math.max(n,i,r),a=Math.min(n,i,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c<=.5?t/(s+a):t/(2-s-a),s){case n:o=(i-r)/t+(i>-e-14,i[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(i[t]=e+15<<10,i[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[256|t]=64512,r[t]=13,r[256|t]=13)}const s=new Uint32Array(2048),a=new Uint32Array(64),o=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,n=0;for(;0==(8388608&e);)e<<=1,n-=8388608;e&=-8388609,n+=947912704,s[t]=e|n}for(let t=1024;t<2048;++t)s[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)a[t]=t<<23;a[31]=1199570944,a[32]=2147483648;for(let t=33;t<63;++t)a[t]=2147483648+(t-32<<23);a[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(o[t]=1024);return{floatView:e,uint32View:n,baseTable:i,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}function Qi(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=We(t,-65504,65504),Ki.floatView[0]=t;const e=Ki.uint32View[0],n=e>>23&511;return Ki.baseTable[n]+((8388607&e)>>Ki.shiftTable[n])}function tr(t){const e=t>>10;return Ki.uint32View[0]=Ki.mantissaTable[Ki.offsetTable[e]+(1023&t)]+Ki.exponentTable[e],Ki.floatView[0]}const er={toHalfFloat:Qi,fromHalfFloat:tr},nr=new Rn,ir=new Qe;class rr{constructor(t,e,n=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=n,this.usage=Ne,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&&(t[n]=e[n]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e0&&(i[e]=s,r=!0)}r&&(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;null!==n&&this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t(t.far-t.near)**2)return}gr.copy(r).invert(),vr.copy(t.ray).applyMatrix4(gr),null!==n.boundingBox&&!1===vr.intersectsBox(n.boundingBox)||this._computeIntersections(t,e,vr)}}_computeIntersections(t,e,n){let i;const r=this.geometry,s=this.material,a=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==a)if(Array.isArray(s))for(let r=0,o=u.length;rn.far?null:{distance:u,point:Ir.clone(),object:t}}(t,e,n,i,xr,Mr,Sr,Pr);if(d){r&&(Er.fromBufferAttribute(r,o),wr.fromBufferAttribute(r,h),Ar.fromBufferAttribute(r,u),d.uv=Hi.getInterpolation(Pr,xr,Mr,Sr,Er,wr,Ar,new Qe)),s&&(Er.fromBufferAttribute(s,o),wr.fromBufferAttribute(s,h),Ar.fromBufferAttribute(s,u),d.uv1=Hi.getInterpolation(Pr,xr,Mr,Sr,Er,wr,Ar,new Qe),d.uv2=d.uv1),a&&(Rr.fromBufferAttribute(a,o),Cr.fromBufferAttribute(a,h),Lr.fromBufferAttribute(a,u),d.normal=Hi.getInterpolation(Pr,xr,Mr,Sr,Rr,Cr,Lr,new Rn),d.normal.dot(i.direction)>0&&d.normal.multiplyScalar(-1));const t={a:o,b:h,c:u,normal:new Rn,materialIndex:0};Hi.getNormal(xr,Mr,Sr,t.normal),d.face=t}return d}class Nr extends fr{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const _=s/f,y=p/g,x=s/2,M=p/2,S=m/2,b=f+1,T=g+1;let E=0,w=0;const A=new Rn;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.z),h.push(o/f),h.push(1-s/g),E+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const t in this.extensions)!0===this.extensions[t]&&(n[t]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class Hr extends Ci{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new ri,this.projectionMatrix=new ri,this.projectionMatrixInverse=new ri}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class kr extends Hr{constructor(t=50,e=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*ke*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*He*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*ke*Math.atan(Math.tan(.5*He*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,n,i,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*He*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const Vr=-90;class Wr extends Ci{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n;const i=new kr(Vr,1,t,e);i.layers=this.layers,i.up.set(0,1,0),i.lookAt(1,0,0),this.add(i);const r=new kr(Vr,1,t,e);r.layers=this.layers,r.up.set(0,1,0),r.lookAt(-1,0,0),this.add(r);const s=new kr(Vr,1,t,e);s.layers=this.layers,s.up.set(0,0,-1),s.lookAt(0,1,0),this.add(s);const a=new kr(Vr,1,t,e);a.layers=this.layers,a.up.set(0,0,1),a.lookAt(0,-1,0),this.add(a);const o=new kr(Vr,1,t,e);o.layers=this.layers,o.up.set(0,1,0),o.lookAt(0,0,1),this.add(o);const l=new kr(Vr,1,t,e);l.layers=this.layers,l.up.set(0,1,0),l.lookAt(0,0,-1),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const n=this.renderTarget,[i,r,s,a,o,l]=this.children,c=t.getRenderTarget(),h=t.toneMapping,u=t.xr.enabled;t.toneMapping=W,t.xr.enabled=!1;const d=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0),t.render(e,i),t.setRenderTarget(n,1),t.render(e,r),t.setRenderTarget(n,2),t.render(e,s),t.setRenderTarget(n,3),t.render(e,a),t.setRenderTarget(n,4),t.render(e,o),n.texture.generateMipmaps=d,t.setRenderTarget(n,5),t.render(e,l),t.setRenderTarget(c),t.toneMapping=h,t.xr.enabled=u,n.texture.needsPMREMUpdate=!0}}class Xr extends Sn{constructor(t,e,n,i,r,s,a,o,l,c){super(t=void 0!==t?t:[],e=void 0!==e?e:K,n,i,r,s,a,o,l,c),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class jr extends Tn{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},i=[n,n,n,n,n,n];void 0!==e.encoding&&(ln("THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace."),e.colorSpace=e.encoding===_e?be:Se),this.texture=new Xr(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:lt}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new Nr(5,5,5),r=new Gr({name:"CubemapFromEquirect",uniforms:Or(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:c,blending:u});r.uniforms.tEquirect.value=e;const s=new Ur(i,r),a=e.minFilter;e.minFilter===ht&&(e.minFilter=lt);return new Wr(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}const qr=new Rn,Yr=new Rn,Zr=new tn;class Jr{constructor(t=new Rn(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=qr.subVectors(n,e).cross(Yr.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(t).addScaledVector(this.normal,-this.distanceToPoint(t))}intersectLine(t,e){const n=t.delta(qr),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||Zr.getNormalMatrix(t),i=this.coplanarPoint(qr).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const Kr=new Zn,$r=new Rn;class Qr{constructor(t=new Jr,e=new Jr,n=new Jr,i=new Jr,r=new Jr,s=new Jr){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t){const e=this.planes,n=t.elements,i=n[0],r=n[1],s=n[2],a=n[3],o=n[4],l=n[5],c=n[6],h=n[7],u=n[8],d=n[9],p=n[10],m=n[11],f=n[12],g=n[13],v=n[14],_=n[15];return e[0].setComponents(a-i,h-o,m-u,_-f).normalize(),e[1].setComponents(a+i,h+o,m+u,_+f).normalize(),e[2].setComponents(a+r,h+l,m+d,_+g).normalize(),e[3].setComponents(a-r,h-l,m-d,_-g).normalize(),e[4].setComponents(a-s,h-c,m-p,_-v).normalize(),e[5].setComponents(a+s,h+c,m+p,_+v).normalize(),this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&&t.computeBoundingSphere(),Kr.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&&e.computeBoundingSphere(),Kr.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(Kr)}intersectsSprite(t){return Kr.center.set(0,0,0),Kr.radius=.7071067811865476,Kr.applyMatrix4(t.matrixWorld),this.intersectsSphere(Kr)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(n)0?t.max.x:t.min.x,$r.y=i.normal.y>0?t.max.y:t.min.y,$r.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint($r)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function ts(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==n&&(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function es(t,e){const n=e.isWebGL2,i=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),i.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const n=i.get(e);n&&(t.deleteBuffer(n.buffer),i.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=i.get(e);return void((!t||t.version 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tanisotropyV /= material.anisotropy;\n\tmaterial.anisotropy = saturate( material.anisotropy );\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x - tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x + tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometry.viewDir, geometry.normal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, vMapUv );\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal, vNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},rs={common:{diffuse:{value:new Yi(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new tn},alphaMap:{value:null},alphaMapTransform:{value:new tn},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new tn}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new tn}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new tn}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new tn},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new tn},normalScale:{value:new Qe(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new tn},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new tn}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new tn}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new tn}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Yi(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Yi(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new tn},alphaTest:{value:0},uvTransform:{value:new tn}},sprite:{diffuse:{value:new Yi(16777215)},opacity:{value:1},center:{value:new Qe(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new tn},alphaMap:{value:null},alphaMapTransform:{value:new tn},alphaTest:{value:0}}},ss={basic:{uniforms:Fr([rs.common,rs.specularmap,rs.envmap,rs.aomap,rs.lightmap,rs.fog]),vertexShader:is.meshbasic_vert,fragmentShader:is.meshbasic_frag},lambert:{uniforms:Fr([rs.common,rs.specularmap,rs.envmap,rs.aomap,rs.lightmap,rs.emissivemap,rs.bumpmap,rs.normalmap,rs.displacementmap,rs.fog,rs.lights,{emissive:{value:new Yi(0)}}]),vertexShader:is.meshlambert_vert,fragmentShader:is.meshlambert_frag},phong:{uniforms:Fr([rs.common,rs.specularmap,rs.envmap,rs.aomap,rs.lightmap,rs.emissivemap,rs.bumpmap,rs.normalmap,rs.displacementmap,rs.fog,rs.lights,{emissive:{value:new Yi(0)},specular:{value:new Yi(1118481)},shininess:{value:30}}]),vertexShader:is.meshphong_vert,fragmentShader:is.meshphong_frag},standard:{uniforms:Fr([rs.common,rs.envmap,rs.aomap,rs.lightmap,rs.emissivemap,rs.bumpmap,rs.normalmap,rs.displacementmap,rs.roughnessmap,rs.metalnessmap,rs.fog,rs.lights,{emissive:{value:new Yi(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:is.meshphysical_vert,fragmentShader:is.meshphysical_frag},toon:{uniforms:Fr([rs.common,rs.aomap,rs.lightmap,rs.emissivemap,rs.bumpmap,rs.normalmap,rs.displacementmap,rs.gradientmap,rs.fog,rs.lights,{emissive:{value:new Yi(0)}}]),vertexShader:is.meshtoon_vert,fragmentShader:is.meshtoon_frag},matcap:{uniforms:Fr([rs.common,rs.bumpmap,rs.normalmap,rs.displacementmap,rs.fog,{matcap:{value:null}}]),vertexShader:is.meshmatcap_vert,fragmentShader:is.meshmatcap_frag},points:{uniforms:Fr([rs.points,rs.fog]),vertexShader:is.points_vert,fragmentShader:is.points_frag},dashed:{uniforms:Fr([rs.common,rs.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:is.linedashed_vert,fragmentShader:is.linedashed_frag},depth:{uniforms:Fr([rs.common,rs.displacementmap]),vertexShader:is.depth_vert,fragmentShader:is.depth_frag},normal:{uniforms:Fr([rs.common,rs.bumpmap,rs.normalmap,rs.displacementmap,{opacity:{value:1}}]),vertexShader:is.meshnormal_vert,fragmentShader:is.meshnormal_frag},sprite:{uniforms:Fr([rs.sprite,rs.fog]),vertexShader:is.sprite_vert,fragmentShader:is.sprite_frag},background:{uniforms:{uvTransform:{value:new tn},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:is.background_vert,fragmentShader:is.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:is.backgroundCube_vert,fragmentShader:is.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:is.cube_vert,fragmentShader:is.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:is.equirect_vert,fragmentShader:is.equirect_frag},distanceRGBA:{uniforms:Fr([rs.common,rs.displacementmap,{referencePosition:{value:new Rn},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:is.distanceRGBA_vert,fragmentShader:is.distanceRGBA_frag},shadow:{uniforms:Fr([rs.lights,rs.fog,{color:{value:new Yi(0)},opacity:{value:1}}]),vertexShader:is.shadow_vert,fragmentShader:is.shadow_frag}};ss.physical={uniforms:Fr([ss.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new tn},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new tn},clearcoatNormalScale:{value:new Qe(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new tn},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new tn},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new tn},sheen:{value:0},sheenColor:{value:new Yi(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new tn},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new tn},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new tn},transmissionSamplerSize:{value:new Qe},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new tn},attenuationDistance:{value:0},attenuationColor:{value:new Yi(0)},specularColor:{value:new Yi(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new tn},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new tn},anisotropyVector:{value:new Qe},anisotropyMap:{value:null},anisotropyMapTransform:{value:new tn}}]),vertexShader:is.meshphysical_vert,fragmentShader:is.meshphysical_frag};const as={r:0,b:0,g:0};function os(t,e,n,i,r,s,a){const o=new Yi(0);let h,u,d=!0===s?0:1,p=null,m=0,f=null;function g(e,n){e.getRGB(as,Br(t)),i.buffers.color.setClear(as.r,as.g,as.b,n,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),d=e,g(o,d)},getClearAlpha:function(){return d},setClearAlpha:function(t){d=t,g(o,d)},render:function(s,v){let _=!1,y=!0===v.isScene?v.background:null;if(y&&y.isTexture){y=(v.backgroundBlurriness>0?n:e).get(y)}switch(null===y?g(o,d):y&&y.isColor&&(g(y,1),_=!0),t.xr.getEnvironmentBlendMode()){case"opaque":_=!0;break;case"additive":i.buffers.color.setClear(0,0,0,1,a),_=!0;break;case"alpha-blend":i.buffers.color.setClear(0,0,0,0,a),_=!0}(t.autoClear||_)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),y&&(y.isCubeTexture||y.mapping===et)?(void 0===u&&(u=new Ur(new Nr(1,1,1),new Gr({name:"BackgroundCubeMaterial",uniforms:Or(ss.backgroundCube.uniforms),vertexShader:ss.backgroundCube.vertexShader,fragmentShader:ss.backgroundCube.fragmentShader,side:c,depthTest:!1,depthWrite:!1,fog:!1})),u.geometry.deleteAttribute("normal"),u.geometry.deleteAttribute("uv"),u.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(u.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(u)),u.material.uniforms.envMap.value=y,u.material.uniforms.flipEnvMap.value=y.isCubeTexture&&!1===y.isRenderTargetTexture?-1:1,u.material.uniforms.backgroundBlurriness.value=v.backgroundBlurriness,u.material.uniforms.backgroundIntensity.value=v.backgroundIntensity,u.material.toneMapped=y.colorSpace!==be,p===y&&m===y.version&&f===t.toneMapping||(u.material.needsUpdate=!0,p=y,m=y.version,f=t.toneMapping),u.layers.enableAll(),s.unshift(u,u.geometry,u.material,0,0,null)):y&&y.isTexture&&(void 0===h&&(h=new Ur(new ns(2,2),new Gr({name:"BackgroundMaterial",uniforms:Or(ss.background.uniforms),vertexShader:ss.background.vertexShader,fragmentShader:ss.background.fragmentShader,side:l,depthTest:!1,depthWrite:!1,fog:!1})),h.geometry.deleteAttribute("normal"),Object.defineProperty(h.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(h)),h.material.uniforms.t2D.value=y,h.material.uniforms.backgroundIntensity.value=v.backgroundIntensity,h.material.toneMapped=y.colorSpace!==be,!0===y.matrixAutoUpdate&&y.updateMatrix(),h.material.uniforms.uvTransform.value.copy(y.matrix),p===y&&m===y.version&&f===t.toneMapping||(h.material.needsUpdate=!0,p=y,m=y.version,f=t.toneMapping),h.layers.enableAll(),s.unshift(h,h.geometry,h.material,0,0,null))}}}function ls(t,e,n,i){const r=t.getParameter(t.MAX_VERTEX_ATTRIBS),s=i.isWebGL2?null:e.get("OES_vertex_array_object"),a=i.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return i.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return i.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],n=[],i=[];for(let t=0;t=0){const n=r[e];let i=s[e];if(void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;a++}}return c.attributesNum!==a||c.index!==i}(r,y,d,x),M&&function(t,e,n,i){const r={},s=e.attributes;let a=0;const o=n.getAttributes();for(const e in o){if(o[e].location>=0){let n=s[e];void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[e]=i,a++}}c.attributes=r,c.attributesNum=a,c.index=i}(r,y,d,x)}else{const t=!0===l.wireframe;c.geometry===y.id&&c.program===d.id&&c.wireframe===t||(c.geometry=y.id,c.program=d.id,c.wireframe=t,M=!0)}null!==x&&n.update(x,t.ELEMENT_ARRAY_BUFFER),(M||h)&&(h=!1,function(r,s,a,o){if(!1===i.isWebGL2&&(r.isInstancedMesh||o.isInstancedBufferGeometry)&&null===e.get("ANGLE_instanced_arrays"))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const s=c[e];if(s.location>=0){let a=l[e];if(void 0===a&&("instanceMatrix"===e&&r.instanceMatrix&&(a=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(a=r.instanceColor)),void 0!==a){const e=a.normalized,l=a.itemSize,c=n.get(a);if(void 0===c)continue;const h=c.buffer,u=c.type,d=c.bytesPerElement,p=!0===i.isWebGL2&&(u===t.INT||u===t.UNSIGNED_INT||a.gpuType===ft);if(a.isInterleavedBufferAttribute){const n=a.data,i=n.stride,c=a.offset;if(n.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.HIGH_FLOAT).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(t.VERTEX_SHADER,t.MEDIUM_FLOAT).precision>0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&"WebGL2RenderingContext"===t.constructor.name;let a=void 0!==n.precision?n.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===n.logarithmicDepthBuffer,h=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),u=t.getParameter(t.MAX_VERTEX_TEXTURE_IMAGE_UNITS),d=t.getParameter(t.MAX_TEXTURE_SIZE),p=t.getParameter(t.MAX_CUBE_MAP_TEXTURE_SIZE),m=t.getParameter(t.MAX_VERTEX_ATTRIBS),f=t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS),g=t.getParameter(t.MAX_VARYING_VECTORS),v=t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS),_=u>0,y=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==i)return i;if(!0===e.has("EXT_texture_filter_anisotropic")){const n=e.get("EXT_texture_filter_anisotropic");i=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else i=0;return i},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:_,floatFragmentTextures:y,floatVertexTextures:_&&y,maxSamples:s?t.getParameter(t.MAX_SAMPLES):0}}function us(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new Jr,o=new tn,l={value:null,needsUpdate:!1};function c(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);e.numPlanes=i,e.numIntersection=0}();else{const t=s?0:i,e=4*t;let r=m.clippingState||null;l.value=r,r=c(u,o,e,h);for(let t=0;t!==e;++t)r[t]=n[t];m.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=t}}}function ds(t){let e=new WeakMap;function n(t,e){return e===Q?t.mapping=K:e===tt&&(t.mapping=$),t}function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture&&!1===r.isRenderTargetTexture){const s=r.mapping;if(s===Q||s===tt){if(e.has(r)){return n(e.get(r).texture,r.mapping)}{const s=r.image;if(s&&s.height>0){const a=new jr(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",i),n(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class ps extends Hr{constructor(t=-1,e=1,n=1,i=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=n,this.bottom=i,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,n,i,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}const ms=4,fs=[.125,.215,.35,.446,.526,.582],gs=20,vs=new ps,_s=new Yi;let ys=null;const xs=(1+Math.sqrt(5))/2,Ms=1/xs,Ss=[new Rn(1,1,1),new Rn(-1,1,1),new Rn(1,1,-1),new Rn(-1,1,-1),new Rn(0,xs,Ms),new Rn(0,xs,-Ms),new Rn(Ms,0,xs),new Rn(-Ms,0,xs),new Rn(xs,Ms,0),new Rn(-xs,Ms,0)];class bs{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){ys=this._renderer.getRenderTarget(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,i,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=As(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=ws(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let t=0;tt-ms?o=fs[a-t+ms-1]:0===a&&(o=0),i.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),_=new Float32Array(f*p*d),y=new Float32Array(g*p*d);for(let t=0;t2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];v.set(i,m*p*t),_.set(u,f*p*t);const r=[t,t,t,t,t,t];y.set(r,g*p*t)}const x=new fr;x.setAttribute("position",new rr(v,m)),x.setAttribute("uv",new rr(_,f)),x.setAttribute("faceIndex",new rr(y,g)),e.push(x),r>ms&&r--}return{lodPlanes:e,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(t,e,n){const i=new Float32Array(gs),r=new Rn(0,1,0),s=new Gr({name:"SphericalGaussianBlur",defines:{n:gs,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:Rs(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:u,depthTest:!1,depthWrite:!1});return s}(i,t,e)}return i}_compileMaterial(t){const e=new Ur(this._lodPlanes[0],t);this._renderer.compile(e,vs)}_sceneToCubeUV(t,e,n,i){const r=new kr(90,1,e,n),s=[1,-1,1,1,1,1],a=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,h=o.toneMapping;o.getClearColor(_s),o.toneMapping=W,o.autoClear=!1;const u=new Ji({name:"PMREM.Background",side:c,depthWrite:!1,depthTest:!1}),d=new Ur(new Nr,u);let p=!1;const m=t.background;m?m.isColor&&(u.color.copy(m),t.background=null,p=!0):(u.color.copy(_s),p=!0);for(let e=0;e<6;e++){const n=e%3;0===n?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===n?(r.up.set(0,0,s[e]),r.lookAt(0,a[e],0)):(r.up.set(0,s[e],0),r.lookAt(0,0,a[e]));const l=this._cubeSize;Es(i,n*l,e>2?l:0,l,l),o.setRenderTarget(i),p&&o.render(d,r),o.render(t,r)}d.geometry.dispose(),d.material.dispose(),o.toneMapping=h,o.autoClear=l,t.background=m}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===K||t.mapping===$;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=As()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=ws());const r=i?this._cubemapMaterial:this._equirectMaterial,s=new Ur(this._lodPlanes[0],r);r.uniforms.envMap.value=t;const a=this._cubeSize;Es(e,0,0,3*a,2*a),n.setRenderTarget(e),n.render(s,vs)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;egs&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to ${gs}`);const f=[];let g=0;for(let t=0;tv-ms?i-v+ms:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(e),o.render(c,vs)}}function Ts(t,e,n){const i=new Tn(t,e,n);return i.texture.mapping=et,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function Es(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function ws(){return new Gr({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:Rs(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:u,depthTest:!1,depthWrite:!1})}function As(){return new Gr({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:Rs(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:u,depthTest:!1,depthWrite:!1})}function Rs(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function Cs(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const s=r.mapping,a=s===Q||s===tt,o=s===K||s===$;if(a||o){if(r.isRenderTargetTexture&&!0===r.needsPMREMUpdate){r.needsPMREMUpdate=!1;let i=e.get(r);return null===n&&(n=new bs(t)),i=a?n.fromEquirectangular(r,i):n.fromCubemap(r,i),e.set(r,i),i.texture}if(e.has(r))return e.get(r).texture;{const s=r.image;if(a&&s&&s.height>0||o&&s&&function(t){let e=0;const n=6;for(let i=0;ie.maxTextureSize&&(E=Math.ceil(T/e.maxTextureSize),T=e.maxTextureSize);const w=new Float32Array(T*E*4*p),A=new En(w,T,E,p);A.type=vt,A.needsUpdate=!0;const R=4*b;for(let L=0;L0)return t;const r=e*n;let s=ks[r];if(void 0===s&&(s=new Float32Array(r),ks[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function Ys(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n":" "} ${r}: ${n[t]}`)}return i.join("\n")}(t.getShaderSource(e),i)}return r}function Xa(t,e){const n=function(t){switch(t){case Te:return["Linear","( value )"];case be:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",t),["Linear","( value )"]}}(e);return"vec4 "+t+"( vec4 value ) { return LinearTo"+n[0]+n[1]+"; }"}function ja(t,e){let n;switch(e){case X:n="Linear";break;case j:n="Reinhard";break;case q:n="OptimizedCineon";break;case Y:n="ACESFilmic";break;case Z:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),n="Linear"}return"vec3 "+t+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}function qa(t){return""!==t}function Ya(t,e){const n=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function Za(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const Ja=/^[ \t]*#include +<([\w\d./]+)>/gm;function Ka(t){return t.replace(Ja,$a)}function $a(t,e){const n=is[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return Ka(n)}const Qa=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function to(t){return t.replace(Qa,eo)}function eo(t,e,n,i){let r="";for(let t=parseInt(e);t0&&(y+="\n"),x=[g,"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v].filter(qa).join("\n"),x.length>0&&(x+="\n")):(y=[no(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors&&n.isWebGL2?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.useLegacyLights?"#define LEGACY_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(qa).join("\n"),x=[g,no(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.envMap?"#define "+m:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.useLegacyLights?"#define LEGACY_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",n.toneMapping!==W?"#define TONE_MAPPING":"",n.toneMapping!==W?is.tonemapping_pars_fragment:"",n.toneMapping!==W?ja("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",is.encodings_pars_fragment,Xa("linearToOutputTexel",n.outputColorSpace),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(qa).join("\n")),c=Ka(c),c=Ya(c,n),c=Za(c,n),h=Ka(h),h=Ya(h,n),h=Za(h,n),c=to(c),h=to(h),n.isWebGL2&&!0!==n.isRawShaderMaterial&&(M="#version 300 es\n",y=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,x=["#define varying in",n.glslVersion===Oe?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===Oe?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+x);const S=M+y+c,b=M+x+h,T=ka(r,r.VERTEX_SHADER,S),E=ka(r,r.FRAGMENT_SHADER,b);if(r.attachShader(_,T),r.attachShader(_,E),void 0!==n.index0AttributeName?r.bindAttribLocation(_,0,n.index0AttributeName):!0===n.morphTargets&&r.bindAttribLocation(_,0,"position"),r.linkProgram(_),t.debug.checkShaderErrors){const e=r.getProgramInfoLog(_).trim(),n=r.getShaderInfoLog(T).trim(),i=r.getShaderInfoLog(E).trim();let s=!0,a=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(s=!1,"function"==typeof t.debug.onShaderError)t.debug.onShaderError(r,_,T,E);else{const t=Wa(r,T,"vertex"),n=Wa(r,E,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nProgram Info Log: "+e+"\n"+t+"\n"+n)}else""!==e?console.warn("THREE.WebGLProgram: Program Info Log:",e):""!==n&&""!==i||(a=!1);a&&(this.diagnostics={runnable:s,programLog:e,vertexShader:{log:n,prefix:y},fragmentShader:{log:i,prefix:x}})}let w,A;return r.deleteShader(T),r.deleteShader(E),this.getUniforms=function(){return void 0===w&&(w=new Ha(r,_)),w},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const n={},i=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES);for(let r=0;r0,Z=s.clearcoat>0,J=s.iridescence>0,K=s.sheen>0,$=s.transmission>0,Q=Y&&!!s.anisotropyMap,tt=Z&&!!s.clearcoatMap,nt=Z&&!!s.clearcoatNormalMap,it=Z&&!!s.clearcoatRoughnessMap,rt=J&&!!s.iridescenceMap,st=J&&!!s.iridescenceThicknessMap,at=K&&!!s.sheenColorMap,ot=K&&!!s.sheenRoughnessMap,lt=!!s.specularMap,ct=!!s.specularColorMap,ht=!!s.specularIntensityMap,ut=$&&!!s.transmissionMap,dt=$&&!!s.thicknessMap,pt=!!s.gradientMap,mt=!!s.alphaMap,ft=s.alphaTest>0,gt=!!s.extensions,vt=!!S.attributes.uv1,_t=!!S.attributes.uv2,yt=!!S.attributes.uv3;return{isWebGL2:p,shaderID:w,shaderType:s.type,shaderName:s.name,vertexShader:C,fragmentShader:L,defines:s.defines,customVertexShaderID:P,customFragmentShaderID:I,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:g,instancing:N,instancingColor:N&&null!==x.instanceColor,supportsVertexTextures:f,outputColorSpace:null===D?t.outputColorSpace:!0===D.isXRRenderTarget?D.texture.colorSpace:Te,map:O,matcap:F,envMap:B,envMapMode:B&&T.mapping,envMapCubeUVHeight:E,aoMap:z,lightMap:G,bumpMap:H,normalMap:k,displacementMap:f&&V,emissiveMap:X,normalMapObjectSpace:k&&s.normalMapType===Me,normalMapTangentSpace:k&&s.normalMapType===xe,metalnessMap:j,roughnessMap:q,anisotropy:Y,anisotropyMap:Q,clearcoat:Z,clearcoatMap:tt,clearcoatNormalMap:nt,clearcoatRoughnessMap:it,iridescence:J,iridescenceMap:rt,iridescenceThicknessMap:st,sheen:K,sheenColorMap:at,sheenRoughnessMap:ot,specularMap:lt,specularColorMap:ct,specularIntensityMap:ht,transmission:$,transmissionMap:ut,thicknessMap:dt,gradientMap:pt,opaque:!1===s.transparent&&s.blending===d,alphaMap:mt,alphaTest:ft,combine:s.combine,mapUv:O&&_(s.map.channel),aoMapUv:z&&_(s.aoMap.channel),lightMapUv:G&&_(s.lightMap.channel),bumpMapUv:H&&_(s.bumpMap.channel),normalMapUv:k&&_(s.normalMap.channel),displacementMapUv:V&&_(s.displacementMap.channel),emissiveMapUv:X&&_(s.emissiveMap.channel),metalnessMapUv:j&&_(s.metalnessMap.channel),roughnessMapUv:q&&_(s.roughnessMap.channel),anisotropyMapUv:Q&&_(s.anisotropyMap.channel),clearcoatMapUv:tt&&_(s.clearcoatMap.channel),clearcoatNormalMapUv:nt&&_(s.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:it&&_(s.clearcoatRoughnessMap.channel),iridescenceMapUv:rt&&_(s.iridescenceMap.channel),iridescenceThicknessMapUv:st&&_(s.iridescenceThicknessMap.channel),sheenColorMapUv:at&&_(s.sheenColorMap.channel),sheenRoughnessMapUv:ot&&_(s.sheenRoughnessMap.channel),specularMapUv:lt&&_(s.specularMap.channel),specularColorMapUv:ct&&_(s.specularColorMap.channel),specularIntensityMapUv:ht&&_(s.specularIntensityMap.channel),transmissionMapUv:ut&&_(s.transmissionMap.channel),thicknessMapUv:dt&&_(s.thicknessMap.channel),alphaMapUv:mt&&_(s.alphaMap.channel),vertexTangents:!!S.attributes.tangent&&(k||Y),vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!S.attributes.color&&4===S.attributes.color.itemSize,vertexUv1s:vt,vertexUv2s:_t,vertexUv3s:yt,pointsUvs:!0===x.isPoints&&!!S.attributes.uv&&(O||mt),fog:!!M,useFog:!0===s.fog,fogExp2:M&&M.isFogExp2,flatShading:!0===s.flatShading,sizeAttenuation:!0===s.sizeAttenuation,logarithmicDepthBuffer:m,skinning:!0===x.isSkinnedMesh,morphTargets:void 0!==S.morphAttributes.position,morphNormals:void 0!==S.morphAttributes.normal,morphColors:void 0!==S.morphAttributes.color,morphTargetsCount:R,morphTextureStride:U,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&u.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:W,useLegacyLights:t.useLegacyLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:s.side===h,flipSided:s.side===c,useDepthPacking:s.depthPacking>=0,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:gt&&!0===s.extensions.derivatives,extensionFragDepth:gt&&!0===s.extensions.fragDepth,extensionDrawBuffers:gt&&!0===s.extensions.drawBuffers,extensionShaderTextureLOD:gt&&!0===s.extensions.shaderTextureLOD,rendererExtensionFragDepth:p||i.has("EXT_frag_depth"),rendererExtensionDrawBuffers:p||i.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:p||i.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.customVertexShaderID),n.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputColorSpace),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.mapUv),t.push(e.alphaMapUv),t.push(e.lightMapUv),t.push(e.aoMapUv),t.push(e.bumpMapUv),t.push(e.normalMapUv),t.push(e.displacementMapUv),t.push(e.emissiveMapUv),t.push(e.metalnessMapUv),t.push(e.roughnessMapUv),t.push(e.anisotropyMapUv),t.push(e.clearcoatMapUv),t.push(e.clearcoatNormalMapUv),t.push(e.clearcoatRoughnessMapUv),t.push(e.iridescenceMapUv),t.push(e.iridescenceThicknessMapUv),t.push(e.sheenColorMapUv),t.push(e.sheenRoughnessMapUv),t.push(e.specularMapUv),t.push(e.specularColorMapUv),t.push(e.specularIntensityMapUv),t.push(e.transmissionMapUv),t.push(e.thicknessMapUv),t.push(e.combine),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numSpotLightMaps),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.numSpotLightShadowsWithMaps),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(n,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.matcap&&o.enable(4);e.envMap&&o.enable(5);e.normalMapObjectSpace&&o.enable(6);e.normalMapTangentSpace&&o.enable(7);e.clearcoat&&o.enable(8);e.iridescence&&o.enable(9);e.alphaTest&&o.enable(10);e.vertexColors&&o.enable(11);e.vertexAlphas&&o.enable(12);e.vertexUv1s&&o.enable(13);e.vertexUv2s&&o.enable(14);e.vertexUv3s&&o.enable(15);e.vertexTangents&&o.enable(16);e.anisotropy&&o.enable(17);t.push(o.mask),o.disableAll(),e.fog&&o.enable(0);e.useFog&&o.enable(1);e.flatShading&&o.enable(2);e.logarithmicDepthBuffer&&o.enable(3);e.skinning&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.morphColors&&o.enable(7);e.premultipliedAlpha&&o.enable(8);e.shadowMapEnabled&&o.enable(9);e.useLegacyLights&&o.enable(10);e.doubleSided&&o.enable(11);e.flipSided&&o.enable(12);e.useDepthPacking&&o.enable(13);e.dithering&&o.enable(14);e.transmission&&o.enable(15);e.sheen&&o.enable(16);e.opaque&&o.enable(17);e.pointsUvs&&o.enable(18);t.push(o.mask)}(n,e),n.push(t.outputColorSpace)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=v[t.type];let n;if(e){const t=ss[e];n=zr.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=u.length;t0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n1&&n.sort(t||co),i.length>1&&i.sort(e||ho),r.length>1&&r.sort(e||ho)}}}function po(){let t=new WeakMap;return{get:function(e,n){const i=t.get(e);let r;return void 0===i?(r=new uo,t.set(e,[r])):n>=i.length?(r=new uo,i.push(r)):r=i[n],r},dispose:function(){t=new WeakMap}}}function mo(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":n={direction:new Rn,color:new Yi};break;case"SpotLight":n={position:new Rn,direction:new Rn,color:new Yi,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new Rn,color:new Yi,distance:0,decay:0};break;case"HemisphereLight":n={direction:new Rn,skyColor:new Yi,groundColor:new Yi};break;case"RectAreaLight":n={color:new Yi,position:new Rn,halfWidth:new Rn,halfHeight:new Rn}}return t[e.id]=n,n}}}let fo=0;function go(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function vo(t,e){const n=new mo,i=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":case"SpotLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Qe};break;case"PointLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Qe,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0};for(let t=0;t<9;t++)r.probe.push(new Rn);const s=new Rn,a=new ri,o=new ri;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,_=0,y=0;s.sort(go);const x=!0===a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=rs.LTC_FLOAT_1,r.rectAreaLTC2=rs.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=rs.LTC_HALF_1,r.rectAreaLTC2=rs.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const M=r.hash;M.directionalLength===h&&M.pointLength===u&&M.spotLength===d&&M.rectAreaLength===p&&M.hemiLength===m&&M.numDirectionalShadows===f&&M.numPointShadows===g&&M.numSpotShadows===v&&M.numSpotMaps===_||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotLightMatrix.length=v+_-y,r.spotLightMap.length=_,r.numSpotLightShadowsWithMaps=y,M.directionalLength=h,M.pointLength=u,M.spotLength=d,M.rectAreaLength=p,M.hemiLength=m,M.numDirectionalShadows=f,M.numPointShadows=g,M.numSpotShadows=v,M.numSpotMaps=_,r.version=fo++)},setupView:function(t,e){let n=0,i=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=s.length?(a=new _o(t,e),s.push(a)):a=s[r],a},dispose:function(){n=new WeakMap}}}class xo extends Vi{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class Mo extends Vi{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function So(t,e,n){let i=new Qr;const r=new Qe,a=new Qe,d=new bn,p=new xo({depthPacking:ye}),m=new Mo,f={},g=n.maxTextureSize,v={[l]:c,[c]:l,[h]:h},_=new Gr({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new Qe},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),y=_.clone();y.defines.HORIZONTAL_PASS=1;const x=new fr;x.setAttribute("position",new rr(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const M=new Ur(x,_),S=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=s;let b=this.type;function T(n,i){const s=e.update(M);_.defines.VSM_SAMPLES!==n.blurSamples&&(_.defines.VSM_SAMPLES=n.blurSamples,y.defines.VSM_SAMPLES=n.blurSamples,_.needsUpdate=!0,y.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new Tn(r.x,r.y)),_.uniforms.shadow_pass.value=n.map.texture,_.uniforms.resolution.value=n.mapSize,_.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,s,_,M,null),y.uniforms.shadow_pass.value=n.mapPass.texture,y.uniforms.resolution.value=n.mapSize,y.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,s,y,M,null)}function E(e,n,i,r){let s=null;const a=!0===i.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(void 0!==a)s=a;else if(s=!0===i.isPointLight?m:p,t.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const t=s.uuid,e=n.uuid;let i=f[t];void 0===i&&(i={},f[t]=i);let r=i[e];void 0===r&&(r=s.clone(),i[e]=r),s=r}if(s.visible=n.visible,s.wireframe=n.wireframe,s.side=r===o?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:v[n.side],s.alphaMap=n.alphaMap,s.alphaTest=n.alphaTest,s.map=n.map,s.clipShadows=n.clipShadows,s.clippingPlanes=n.clippingPlanes,s.clipIntersection=n.clipIntersection,s.displacementMap=n.displacementMap,s.displacementScale=n.displacementScale,s.displacementBias=n.displacementBias,s.wireframeLinewidth=n.wireframeLinewidth,s.linewidth=n.linewidth,!0===i.isPointLight&&!0===s.isMeshDistanceMaterial){t.properties.get(s).light=i}return s}function w(n,r,s,a,l){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&l===o)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const i=e.update(n),r=n.material;if(Array.isArray(r)){const e=i.groups;for(let o=0,c=e.length;og||r.y>g)&&(r.x>g&&(a.x=Math.floor(g/u.x),r.x=a.x*u.x,h.mapSize.x=a.x),r.y>g&&(a.y=Math.floor(g/u.y),r.y=a.y*u.y,h.mapSize.y=a.y)),null===h.map||!0===m||!0===f){const t=this.type!==o?{minFilter:st,magFilter:st}:{};null!==h.map&&h.map.dispose(),h.map=new Tn(r.x,r.y,t),h.map.texture.name=c.name+".shadowMap",h.camera.updateProjectionMatrix()}t.setRenderTarget(h.map),t.clear();const v=h.getViewportCount();for(let t=0;t=1):-1!==dt.indexOf("OpenGL ES")&&(ut=parseFloat(/^OpenGL ES (\d)/.exec(dt)[1]),ht=ut>=2);let pt=null,mt={};const ft=t.getParameter(t.SCISSOR_BOX),gt=t.getParameter(t.VIEWPORT),vt=(new bn).fromArray(ft),_t=(new bn).fromArray(gt);function yt(e,n,i,r){const s=new Uint8Array(4),o=t.createTexture();t.bindTexture(e,o),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let o=0;oi||t.height>i)&&(r=i/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const i=e?Ze:Math.floor,s=i(r*t.width),a=i(r*t.height);void 0===f&&(f=_(s,a));const o=n?_(s,a):f;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function x(t){return qe(t.width)&&qe(t.height)}function M(t,e){return t.generateMipmaps&&e&&t.minFilter!==st&&t.minFilter!==lt}function S(e){t.generateMipmap(e)}function b(n,i,r,s,a=!1){if(!1===o)return i;if(null!==n){if(void 0!==t[n])return t[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let l=i;return i===t.RED&&(r===t.FLOAT&&(l=t.R32F),r===t.HALF_FLOAT&&(l=t.R16F),r===t.UNSIGNED_BYTE&&(l=t.R8)),i===t.RG&&(r===t.FLOAT&&(l=t.RG32F),r===t.HALF_FLOAT&&(l=t.RG16F),r===t.UNSIGNED_BYTE&&(l=t.RG8)),i===t.RGBA&&(r===t.FLOAT&&(l=t.RGBA32F),r===t.HALF_FLOAT&&(l=t.RGBA16F),r===t.UNSIGNED_BYTE&&(l=s===be&&!1===a?t.SRGB8_ALPHA8:t.RGBA8),r===t.UNSIGNED_SHORT_4_4_4_4&&(l=t.RGBA4),r===t.UNSIGNED_SHORT_5_5_5_1&&(l=t.RGB5_A1)),l!==t.R16F&&l!==t.R32F&&l!==t.RG16F&&l!==t.RG32F&&l!==t.RGBA16F&&l!==t.RGBA32F||e.get("EXT_color_buffer_float"),l}function T(t,e,n){return!0===M(t,n)||t.isFramebufferTexture&&t.minFilter!==st&&t.minFilter!==lt?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function E(e){return e===st||e===at||e===ot?t.NEAREST:t.LINEAR}function w(t){const e=t.target;e.removeEventListener("dispose",w),function(t){const e=i.get(t);if(void 0===e.__webglInit)return;const n=t.source,r=g.get(n);if(r){const i=r[e.__cacheKey];i.usedTimes--,0===i.usedTimes&&R(t),0===Object.keys(r).length&&g.delete(n)}i.remove(t)}(e),e.isVideoTexture&&m.delete(e)}function A(e){const n=e.target;n.removeEventListener("dispose",A),function(e){const n=e.texture,r=i.get(e),s=i.get(n);void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else{if(t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e0&&s.__version!==e.version){const t=e.image;if(null===t)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==t.complete)return void O(s,e,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(t.TEXTURE_2D,s.__webglTexture,t.TEXTURE0+r)}const P={[nt]:t.REPEAT,[it]:t.CLAMP_TO_EDGE,[rt]:t.MIRRORED_REPEAT},I={[st]:t.NEAREST,[at]:t.NEAREST_MIPMAP_NEAREST,[ot]:t.NEAREST_MIPMAP_LINEAR,[lt]:t.LINEAR,[ct]:t.LINEAR_MIPMAP_NEAREST,[ht]:t.LINEAR_MIPMAP_LINEAR},U={[Ae]:t.NEVER,[De]:t.ALWAYS,[Re]:t.LESS,[Le]:t.LEQUAL,[Ce]:t.EQUAL,[Ue]:t.GEQUAL,[Pe]:t.GREATER,[Ie]:t.NOTEQUAL};function D(n,s,a){if(a?(t.texParameteri(n,t.TEXTURE_WRAP_S,P[s.wrapS]),t.texParameteri(n,t.TEXTURE_WRAP_T,P[s.wrapT]),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,P[s.wrapR]),t.texParameteri(n,t.TEXTURE_MAG_FILTER,I[s.magFilter]),t.texParameteri(n,t.TEXTURE_MIN_FILTER,I[s.minFilter])):(t.texParameteri(n,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(n,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),s.wrapS===it&&s.wrapT===it||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(n,t.TEXTURE_MAG_FILTER,E(s.magFilter)),t.texParameteri(n,t.TEXTURE_MIN_FILTER,E(s.minFilter)),s.minFilter!==st&&s.minFilter!==lt&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),s.compareFunction&&(t.texParameteri(n,t.TEXTURE_COMPARE_MODE,t.COMPARE_REF_TO_TEXTURE),t.texParameteri(n,t.TEXTURE_COMPARE_FUNC,U[s.compareFunction])),!0===e.has("EXT_texture_filter_anisotropic")){const a=e.get("EXT_texture_filter_anisotropic");if(s.magFilter===st)return;if(s.minFilter!==ot&&s.minFilter!==ht)return;if(s.type===vt&&!1===e.has("OES_texture_float_linear"))return;if(!1===o&&s.type===_t&&!1===e.has("OES_texture_half_float_linear"))return;(s.anisotropy>1||i.get(s).__currentAnisotropy)&&(t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy)}}function N(e,n){let i=!1;void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",w));const r=n.source;let s=g.get(r);void 0===s&&(s={},g.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.wrapR||0),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.colorSpace),e.join()}(n);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,i=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&R(n)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return i}function O(e,r,a){let l=t.TEXTURE_2D;(r.isDataArrayTexture||r.isCompressedArrayTexture)&&(l=t.TEXTURE_2D_ARRAY),r.isData3DTexture&&(l=t.TEXTURE_3D);const c=N(e,r),u=r.source;n.bindTexture(l,e.__webglTexture,t.TEXTURE0+a);const d=i.get(u);if(u.version!==d.__version||!0===c){n.activeTexture(t.TEXTURE0+a),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,r.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,r.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,t.NONE);const e=function(t){return!o&&(t.wrapS!==it||t.wrapT!==it||t.minFilter!==st&&t.minFilter!==lt)}(r)&&!1===x(r.image);let i=y(r.image,e,!1,h);i=k(r,i);const p=x(i)||o,m=s.convert(r.format,r.colorSpace);let f,g=s.convert(r.type),v=b(r.internalFormat,m,g,r.colorSpace);D(l,r,p);const _=r.mipmaps,E=o&&!0!==r.isVideoTexture,w=void 0===d.__version||!0===c,A=T(r,i,p);if(r.isDepthTexture)v=t.DEPTH_COMPONENT,o?v=r.type===vt?t.DEPTH_COMPONENT32F:r.type===gt?t.DEPTH_COMPONENT24:r.type===Mt?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT16:r.type===vt&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),r.format===wt&&v===t.DEPTH_COMPONENT&&r.type!==mt&&r.type!==gt&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=gt,g=s.convert(r.type)),r.format===At&&v===t.DEPTH_COMPONENT&&(v=t.DEPTH_STENCIL,r.type!==Mt&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=Mt,g=s.convert(r.type))),w&&(E?n.texStorage2D(t.TEXTURE_2D,1,v,i.width,i.height):n.texImage2D(t.TEXTURE_2D,0,v,i.width,i.height,0,m,g,null));else if(r.isDataTexture)if(_.length>0&&p){E&&w&&n.texStorage2D(t.TEXTURE_2D,A,v,_[0].width,_[0].height);for(let e=0,i=_.length;e>=1,r>>=1}}else if(_.length>0&&p){E&&w&&n.texStorage2D(t.TEXTURE_2D,A,v,_[0].width,_[0].height);for(let e=0,i=_.length;e=t.TEXTURE_CUBE_MAP_POSITIVE_X&&l<=t.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&t.framebufferTexture2D(t.FRAMEBUFFER,o,l,i.get(a).__webglTexture,0),n.bindFramebuffer(t.FRAMEBUFFER,null)}function B(e,n,i){if(t.bindRenderbuffer(t.RENDERBUFFER,e),n.depthBuffer&&!n.stencilBuffer){let r=t.DEPTH_COMPONENT16;if(i||H(n)){const e=n.depthTexture;e&&e.isDepthTexture&&(e.type===vt?r=t.DEPTH_COMPONENT32F:e.type===gt&&(r=t.DEPTH_COMPONENT24));const i=G(n);H(n)?d.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,i,r,n.width,n.height):t.renderbufferStorageMultisample(t.RENDERBUFFER,i,r,n.width,n.height)}else t.renderbufferStorage(t.RENDERBUFFER,r,n.width,n.height);t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.RENDERBUFFER,e)}else if(n.depthBuffer&&n.stencilBuffer){const r=G(n);i&&!1===H(n)?t.renderbufferStorageMultisample(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):H(n)?d.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,n.width,n.height),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,e)}else{const e=!0===n.isWebGLMultipleRenderTargets?n.texture:[n.texture];for(let r=0;r0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function k(t,n){const i=t.colorSpace,r=t.format,s=t.type;return!0===t.isCompressedTexture||t.format===Fe||i!==Te&&i!==Se&&(i===be?!1===o?!0===e.has("EXT_sRGB")&&r===bt?(t.format=Fe,t.minFilter=lt,t.generateMipmaps=!1):n=vn.sRGBToLinear(n):r===bt&&s===ut||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",i)),n}this.allocateTextureUnit=function(){const t=C;return t>=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),C+=1,t},this.resetTextureUnits=function(){C=0},this.setTexture2D=L,this.setTexture2DArray=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?O(s,e,r):n.bindTexture(t.TEXTURE_2D_ARRAY,s.__webglTexture,t.TEXTURE0+r)},this.setTexture3D=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?O(s,e,r):n.bindTexture(t.TEXTURE_3D,s.__webglTexture,t.TEXTURE0+r)},this.setTextureCube=function(e,r){const a=i.get(e);e.version>0&&a.__version!==e.version?function(e,r,a){if(6!==r.image.length)return;const l=N(e,r),h=r.source;n.bindTexture(t.TEXTURE_CUBE_MAP,e.__webglTexture,t.TEXTURE0+a);const u=i.get(h);if(h.version!==u.__version||!0===l){n.activeTexture(t.TEXTURE0+a),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,r.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,r.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,t.NONE);const e=r.isCompressedTexture||r.image[0].isCompressedTexture,i=r.image[0]&&r.image[0].isDataTexture,d=[];for(let t=0;t<6;t++)d[t]=e||i?i?r.image[t].image:r.image[t]:y(r.image[t],!1,!0,c),d[t]=k(r,d[t]);const p=d[0],m=x(p)||o,f=s.convert(r.format,r.colorSpace),g=s.convert(r.type),v=b(r.internalFormat,f,g,r.colorSpace),_=o&&!0!==r.isVideoTexture,E=void 0===u.__version||!0===l;let w,A=T(r,p,m);if(D(t.TEXTURE_CUBE_MAP,r,m),e){_&&E&&n.texStorage2D(t.TEXTURE_CUBE_MAP,A,v,p.width,p.height);for(let e=0;e<6;e++){w=d[e].mipmaps;for(let i=0;i0&&A++,n.texStorage2D(t.TEXTURE_CUBE_MAP,A,v,d[0].width,d[0].height));for(let e=0;e<6;e++)if(i){_?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,0,0,d[e].width,d[e].height,f,g,d[e].data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,v,d[e].width,d[e].height,0,f,g,d[e].data);for(let i=0;i0&&!1===H(e)){const i=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],n.bindFramebuffer(t.FRAMEBUFFER,c.__webglMultisampledFramebuffer);for(let n=0;n0&&!1===H(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=t.COLOR_BUFFER_BIT;const l=[],c=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,h=i.get(e),u=!0===e.isWebGLMultipleRenderTargets;if(u)for(let e=0;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==a&&(i=e.getPose(t.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),a.matrixWorldNeedsUpdate=!0,i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Ro)))}return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const n=new Ao;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}class Lo extends Sn{constructor(t,e,n,i,r,s,a,o,l,c){if((c=void 0!==c?c:wt)!==wt&&c!==At)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===n&&c===wt&&(n=gt),void 0===n&&c===At&&(n=Mt),super(null,i,r,s,a,o,c,n,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:st,this.minFilter=void 0!==o?o:st,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(t){return super.copy(t),this.compareFunction=t.compareFunction,this}toJSON(t){const e=super.toJSON(t);return null!==this.compareFunction&&(e.compareFunction=this.compareFunction),e}}class Po extends Be{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const m=e.getContextAttributes();let f=null,g=null;const v=[],_=[];let y=null;const x=new kr;x.layers.enable(1),x.viewport=new bn;const M=new kr;M.layers.enable(2),M.viewport=new bn;const S=[x,M],b=new wo;b.layers.enable(1),b.layers.enable(2);let T=null,E=null;function w(t){const e=_.indexOf(t.inputSource);if(-1===e)return;const n=v[e];void 0!==n&&(n.update(t.inputSource,t.frame,l||s),n.dispatchEvent({type:t.type,data:t.inputSource}))}function A(){i.removeEventListener("select",w),i.removeEventListener("selectstart",w),i.removeEventListener("selectend",w),i.removeEventListener("squeeze",w),i.removeEventListener("squeezestart",w),i.removeEventListener("squeezeend",w),i.removeEventListener("end",A),i.removeEventListener("inputsourceschange",R);for(let t=0;t=0&&(_[i]=null,v[i].disconnect(n))}for(let e=0;e=_.length){_.push(n),i=t;break}if(null===_[t]){_[t]=n,i=t;break}}if(-1===i)break}const r=v[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getCamera=function(){},this.setUserCamera=function(t){y=t},this.getController=function(t){let e=v[t];return void 0===e&&(e=new Co,v[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=v[t];return void 0===e&&(e=new Co,v[t]=e),e.getGripSpace()},this.getHand=function(t){let e=v[t];return void 0===e&&(e=new Co,v[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){a=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||s},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(f=t.getRenderTarget(),i.addEventListener("select",w),i.addEventListener("selectstart",w),i.addEventListener("selectend",w),i.addEventListener("squeeze",w),i.addEventListener("squeezestart",w),i.addEventListener("squeezeend",w),i.addEventListener("end",A),i.addEventListener("inputsourceschange",R),!0!==m.xrCompatible&&await e.makeXRCompatible(),void 0===i.renderState.layers||!1===t.capabilities.isWebGL2){const n={antialias:void 0!==i.renderState.layers||m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,e,n),i.updateRenderState({baseLayer:d}),g=new Tn(d.framebufferWidth,d.framebufferHeight,{format:bt,type:ut,colorSpace:t.outputColorSpace,stencilBuffer:m.stencil})}else{let n=null,s=null,a=null;m.depth&&(a=m.stencil?e.DEPTH24_STENCIL8:e.DEPTH_COMPONENT24,n=m.stencil?At:wt,s=m.stencil?Mt:gt);const o={colorFormat:e.RGBA8,depthFormat:a,scaleFactor:r};h=new XRWebGLBinding(i,e),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),g=new Tn(u.textureWidth,u.textureHeight,{format:bt,type:ut,depthTexture:new Lo(u.textureWidth,u.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:m.stencil,colorSpace:t.outputColorSpace,samples:m.antialias?4:0});t.properties.get(g).__ignoreDepthValues=u.ignoreDepthValues}g.isXRRenderTarget=!0,this.setFoveation(o),l=null,s=await i.requestReferenceSpace(a),U.setContext(i),U.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode};const C=new Rn,L=new Rn;function P(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.updateCameraXR=function(t){if(null===i)return t;y&&(t=y),b.near=M.near=x.near=t.near,b.far=M.far=x.far=t.far,T===b.near&&E===b.far||(i.updateRenderState({depthNear:b.near,depthFar:b.far}),T=b.near,E=b.far);const e=t.parent,n=b.cameras;P(b,e);for(let t=0;t0&&(i.alphaTest.value=r.alphaTest);const s=e.get(r).envMap;if(s&&(i.envMap.value=s,i.flipEnvMap.value=s.isCubeTexture&&!1===s.isRenderTargetTexture?-1:1,i.reflectivity.value=r.reflectivity,i.ior.value=r.ior,i.refractionRatio.value=r.refractionRatio),r.lightMap){i.lightMap.value=r.lightMap;const e=!0===t.useLegacyLights?Math.PI:1;i.lightMapIntensity.value=r.lightMapIntensity*e,n(r.lightMap,i.lightMapTransform)}r.aoMap&&(i.aoMap.value=r.aoMap,i.aoMapIntensity.value=r.aoMapIntensity,n(r.aoMap,i.aoMapTransform))}return{refreshFogUniforms:function(e,n){n.color.getRGB(e.fogColor.value,Br(t)),n.isFog?(e.fogNear.value=n.near,e.fogFar.value=n.far):n.isFogExp2&&(e.fogDensity.value=n.density)},refreshMaterialUniforms:function(t,r,s,a,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(t,r):r.isMeshToonMaterial?(i(t,r),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,r)):r.isMeshPhongMaterial?(i(t,r),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,r)):r.isMeshStandardMaterial?(i(t,r),function(t,i){t.metalness.value=i.metalness,i.metalnessMap&&(t.metalnessMap.value=i.metalnessMap,n(i.metalnessMap,t.metalnessMapTransform));t.roughness.value=i.roughness,i.roughnessMap&&(t.roughnessMap.value=i.roughnessMap,n(i.roughnessMap,t.roughnessMapTransform));const r=e.get(i).envMap;r&&(t.envMapIntensity.value=i.envMapIntensity)}(t,r),r.isMeshPhysicalMaterial&&function(t,e,i){t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap,n(e.sheenColorMap,t.sheenColorMapTransform)),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap,n(e.sheenRoughnessMap,t.sheenRoughnessMapTransform)));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap,n(e.clearcoatMap,t.clearcoatMapTransform)),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap,n(e.clearcoatRoughnessMap,t.clearcoatRoughnessMapTransform)),e.clearcoatNormalMap&&(t.clearcoatNormalMap.value=e.clearcoatNormalMap,n(e.clearcoatNormalMap,t.clearcoatNormalMapTransform),t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),e.side===c&&t.clearcoatNormalScale.value.negate()));e.iridescence>0&&(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&&(t.iridescenceMap.value=e.iridescenceMap,n(e.iridescenceMap,t.iridescenceMapTransform)),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap,n(e.iridescenceThicknessMap,t.iridescenceThicknessMapTransform)));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap,n(e.transmissionMap,t.transmissionMapTransform)),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap,n(e.thicknessMap,t.thicknessMapTransform)),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));e.anisotropy>0&&(t.anisotropyVector.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation)),e.anisotropyMap&&(t.anisotropyMap.value=e.anisotropyMap,n(e.anisotropyMap,t.anisotropyMapTransform)));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap,n(e.specularColorMap,t.specularColorMapTransform));e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap,n(e.specularIntensityMap,t.specularIntensityMapTransform))}(t,r,o)):r.isMeshMatcapMaterial?(i(t,r),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,r)):r.isMeshDepthMaterial?i(t,r):r.isMeshDistanceMaterial?(i(t,r),function(t,n){const i=e.get(n).light;t.referencePosition.value.setFromMatrixPosition(i.matrixWorld),t.nearDistance.value=i.shadow.camera.near,t.farDistance.value=i.shadow.camera.far}(t,r)):r.isMeshNormalMaterial?i(t,r):r.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform))}(t,r),r.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,r)):r.isPointsMaterial?function(t,e,i,r){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*r,e.map&&(t.map.value=e.map,n(e.map,t.uvTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r,s,a):r.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r):r.isShadowMaterial?(t.color.value.copy(r.color),t.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function Uo(t,e,n,i){let r={},s={},a=[];const o=n.isWebGL2?t.getParameter(t.MAX_UNIFORM_BUFFER_BINDINGS):0;function l(t,e,n){const i=t.value;if(void 0===n[e]){if("number"==typeof i)n[e]=i;else{const t=Array.isArray(i)?i:[i],r=[];for(let e=0;e0){r=n%i;0!==r&&i-r-a.boundary<0&&(n+=i-r,s.__offset=n)}n+=a.storage}r=n%i,r>0&&(n+=i-r);t.__size=n,t.__cache={}}(n),d=function(e){const n=function(){for(let t=0;t0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,p=!!n.morphAttributes.color,m=i.toneMapped?S.toneMapping:W,f=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,g=void 0!==f?f.length:0,v=nt.get(i),_=y.state.lights;if(!0===V&&(!0===X||t!==R)){const e=t===R&&i.id===A;St.setState(i,t,e)}let x=!1;i.version===v.__version?v.needsLights&&v.lightsStateVersion!==_.state.version||v.outputColorSpace!==o||r.isInstancedMesh&&!1===v.instancing?x=!0:r.isInstancedMesh||!0!==v.instancing?r.isSkinnedMesh&&!1===v.skinning?x=!0:r.isSkinnedMesh||!0!==v.skinning?v.envMap!==l||!0===i.fog&&v.fog!==s?x=!0:void 0===v.numClippingPlanes||v.numClippingPlanes===St.numPlanes&&v.numIntersection===St.numIntersection?(v.vertexAlphas!==c||v.vertexTangents!==h||v.morphTargets!==u||v.morphNormals!==d||v.morphColors!==p||v.toneMapping!==m||!0===Q.isWebGL2&&v.morphTargetsCount!==g)&&(x=!0):x=!0:x=!0:x=!0:(x=!0,v.__version=i.version);let M=v.currentProgram;!0===x&&(M=Kt(i,e,r));let b=!1,T=!1,E=!1;const C=M.getUniforms(),L=v.uniforms;tt.useProgram(M.program)&&(b=!0,T=!0,E=!0);i.id!==A&&(A=i.id,T=!0);if(b||R!==t){if(C.setValue(Nt,"projectionMatrix",t.projectionMatrix),Q.logarithmicDepthBuffer&&C.setValue(Nt,"logDepthBufFC",2/(Math.log(t.far+1)/Math.LN2)),R!==t&&(R=t,T=!0,E=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshStandardMaterial||i.envMap){const e=C.map.cameraPosition;void 0!==e&&e.setValue(Nt,Z.setFromMatrixPosition(t.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&C.setValue(Nt,"isOrthographic",!0===t.isOrthographicCamera),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.isShadowMaterial||r.isSkinnedMesh)&&C.setValue(Nt,"viewMatrix",t.matrixWorldInverse)}if(r.isSkinnedMesh){C.setOptional(Nt,r,"bindMatrix"),C.setOptional(Nt,r,"bindMatrixInverse");const t=r.skeleton;t&&(Q.floatVertexTextures?(null===t.boneTexture&&t.computeBoneTexture(),C.setValue(Nt,"boneTexture",t.boneTexture,it),C.setValue(Nt,"boneTextureSize",t.boneTextureSize)):console.warn("THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required."))}const P=n.morphAttributes;(void 0!==P.position||void 0!==P.normal||void 0!==P.color&&!0===Q.isWebGL2)&&wt.update(r,n,M);(T||v.receiveShadow!==r.receiveShadow)&&(v.receiveShadow=r.receiveShadow,C.setValue(Nt,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(L.envMap.value=l,L.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);T&&(C.setValue(Nt,"toneMappingExposure",S.toneMappingExposure),v.needsLights&&(U=E,(I=L).ambientLightColor.needsUpdate=U,I.lightProbe.needsUpdate=U,I.directionalLights.needsUpdate=U,I.directionalLightShadows.needsUpdate=U,I.pointLights.needsUpdate=U,I.pointLightShadows.needsUpdate=U,I.spotLights.needsUpdate=U,I.spotLightShadows.needsUpdate=U,I.rectAreaLights.needsUpdate=U,I.hemisphereLights.needsUpdate=U),s&&!0===i.fog&&dt.refreshFogUniforms(L,s),dt.refreshMaterialUniforms(L,i,O,N,j),Ha.upload(Nt,v.uniformsList,L,it));var I,U;i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(Ha.upload(Nt,v.uniformsList,L,it),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&C.setValue(Nt,"center",r.center);if(C.setValue(Nt,"modelViewMatrix",r.modelViewMatrix),C.setValue(Nt,"normalMatrix",r.normalMatrix),C.setValue(Nt,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const t=i.uniformsGroups;for(let e=0,n=t.length;e0&&function(t,e,n,i){const r=Q.isWebGL2;null===j&&(j=new Tn(1,1,{generateMipmaps:!0,type:$.has("EXT_color_buffer_half_float")?_t:ut,minFilter:ht,samples:r&&!0===o?4:0}));S.getDrawingBufferSize(Y),r?j.setSize(Y.x,Y.y):j.setSize(Ze(Y.x),Ze(Y.y));const s=S.getRenderTarget();S.setRenderTarget(j),S.getClearColor(I),U=S.getClearAlpha(),U<1&&S.setClearColor(16777215,.5);S.clear();const a=S.toneMapping;S.toneMapping=W,Zt(t,n,i),it.updateMultisampleRenderTarget(j),it.updateRenderTargetMipmap(j);let l=!1;for(let t=0,r=e.length;t0&&Zt(r,e,n),s.length>0&&Zt(s,e,n),a.length>0&&Zt(a,e,n),tt.buffers.depth.setTest(!0),tt.buffers.depth.setMask(!0),tt.buffers.color.setMask(!0),tt.setPolygonOffset(!1)}function Zt(t,e,n){const i=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?M[M.length-1]:null,x.pop(),_=x.length>0?x[x.length-1]:null},this.getActiveCubeFace=function(){return T},this.getActiveMipmapLevel=function(){return E},this.getRenderTarget=function(){return w},this.setRenderTargetTextures=function(t,e,n){nt.get(t.texture).__webglTexture=e,nt.get(t.depthTexture).__webglTexture=n;const i=nt.get(t);i.__hasExternalTextures=!0,i.__hasExternalTextures&&(i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===$.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(t,e){const n=nt.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){w=t,T=e,E=n;let i=!0,r=null,s=!1,a=!1;if(t){const n=nt.get(t);void 0!==n.__useDefaultFramebuffer?(tt.bindFramebuffer(Nt.FRAMEBUFFER,null),i=!1):void 0===n.__webglFramebuffer?it.setupRenderTarget(t):n.__hasExternalTextures&&it.rebindTextures(t,nt.get(t.texture).__webglTexture,nt.get(t.depthTexture).__webglTexture);const o=t.texture;(o.isData3DTexture||o.isDataArrayTexture||o.isCompressedArrayTexture)&&(a=!0);const l=nt.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=l[e],s=!0):r=Q.isWebGL2&&t.samples>0&&!1===it.useMultisampledRTT(t)?nt.get(t).__webglMultisampledFramebuffer:l,C.copy(t.viewport),L.copy(t.scissor),P=t.scissorTest}else C.copy(z).multiplyScalar(O).floor(),L.copy(G).multiplyScalar(O).floor(),P=H;if(tt.bindFramebuffer(Nt.FRAMEBUFFER,r)&&Q.drawBuffers&&i&&tt.drawBuffers(t,r),tt.viewport(C),tt.scissor(L),tt.setScissorTest(P),s){const i=nt.get(t.texture);Nt.framebufferTexture2D(Nt.FRAMEBUFFER,Nt.COLOR_ATTACHMENT0,Nt.TEXTURE_CUBE_MAP_POSITIVE_X+e,i.__webglTexture,n)}else if(a){const i=nt.get(t.texture),r=e||0;Nt.framebufferTextureLayer(Nt.FRAMEBUFFER,Nt.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}A=-1},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=nt.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){tt.bindFramebuffer(Nt.FRAMEBUFFER,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==bt&&Lt.convert(o)!==Nt.getParameter(Nt.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===_t&&($.has("EXT_color_buffer_half_float")||Q.isWebGL2&&$.has("EXT_color_buffer_float"));if(!(l===ut||Lt.convert(l)===Nt.getParameter(Nt.IMPLEMENTATION_COLOR_READ_TYPE)||l===vt&&(Q.isWebGL2||$.has("OES_texture_float")||$.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&Nt.readPixels(e,n,i,r,Lt.convert(o),Lt.convert(l),s)}finally{const t=null!==w?nt.get(w).__webglFramebuffer:null;tt.bindFramebuffer(Nt.FRAMEBUFFER,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i);it.setTexture2D(e,0),Nt.copyTexSubImage2D(Nt.TEXTURE_2D,n,0,0,t.x,t.y,r,s),tt.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=Lt.convert(n.format),o=Lt.convert(n.type);it.setTexture2D(n,0),Nt.pixelStorei(Nt.UNPACK_FLIP_Y_WEBGL,n.flipY),Nt.pixelStorei(Nt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),Nt.pixelStorei(Nt.UNPACK_ALIGNMENT,n.unpackAlignment),e.isDataTexture?Nt.texSubImage2D(Nt.TEXTURE_2D,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?Nt.compressedTexSubImage2D(Nt.TEXTURE_2D,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):Nt.texSubImage2D(Nt.TEXTURE_2D,i,t.x,t.y,a,o,e.image),0===i&&n.generateMipmaps&&Nt.generateMipmap(Nt.TEXTURE_2D),tt.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(S.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=Lt.convert(i.format),c=Lt.convert(i.type);let h;if(i.isData3DTexture)it.setTexture3D(i,0),h=Nt.TEXTURE_3D;else{if(!i.isDataArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");it.setTexture2DArray(i,0),h=Nt.TEXTURE_2D_ARRAY}Nt.pixelStorei(Nt.UNPACK_FLIP_Y_WEBGL,i.flipY),Nt.pixelStorei(Nt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,i.premultiplyAlpha),Nt.pixelStorei(Nt.UNPACK_ALIGNMENT,i.unpackAlignment);const u=Nt.getParameter(Nt.UNPACK_ROW_LENGTH),d=Nt.getParameter(Nt.UNPACK_IMAGE_HEIGHT),p=Nt.getParameter(Nt.UNPACK_SKIP_PIXELS),m=Nt.getParameter(Nt.UNPACK_SKIP_ROWS),f=Nt.getParameter(Nt.UNPACK_SKIP_IMAGES),g=n.isCompressedTexture?n.mipmaps[0]:n.image;Nt.pixelStorei(Nt.UNPACK_ROW_LENGTH,g.width),Nt.pixelStorei(Nt.UNPACK_IMAGE_HEIGHT,g.height),Nt.pixelStorei(Nt.UNPACK_SKIP_PIXELS,t.min.x),Nt.pixelStorei(Nt.UNPACK_SKIP_ROWS,t.min.y),Nt.pixelStorei(Nt.UNPACK_SKIP_IMAGES,t.min.z),n.isDataTexture||n.isData3DTexture?Nt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g.data):n.isCompressedArrayTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),Nt.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,g.data)):Nt.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g),Nt.pixelStorei(Nt.UNPACK_ROW_LENGTH,u),Nt.pixelStorei(Nt.UNPACK_IMAGE_HEIGHT,d),Nt.pixelStorei(Nt.UNPACK_SKIP_PIXELS,p),Nt.pixelStorei(Nt.UNPACK_SKIP_ROWS,m),Nt.pixelStorei(Nt.UNPACK_SKIP_IMAGES,f),0===r&&i.generateMipmaps&&Nt.generateMipmap(h),tt.unbindTexture()},this.initTexture=function(t){t.isCubeTexture?it.setTextureCube(t,0):t.isData3DTexture?it.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?it.setTexture2DArray(t,0):it.setTexture2D(t,0),tt.unbindTexture()},this.resetState=function(){T=0,E=0,w=null,tt.reset(),Ut.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get physicallyCorrectLights(){return console.warn("THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),!this.useLegacyLights}set physicallyCorrectLights(t){console.warn("THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),this.useLegacyLights=!t}get outputEncoding(){return console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace===be?_e:ve}set outputEncoding(t){console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace=t===_e?be:Te}}class Oo extends No{}Oo.prototype.isWebGL1Renderer=!0;class Fo{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new Yi(t),this.density=e}clone(){return new Fo(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}class Bo{constructor(t,e=1,n=1e3){this.isFog=!0,this.name="",this.color=new Yi(t),this.near=e,this.far=n}clone(){return new Bo(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}class zo extends Ci{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e}get autoUpdate(){return console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate}set autoUpdate(t){console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate=t}}class Go{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=Ne,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=Ve()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:Xo.clone(),uv:Hi.getInterpolation(Xo,Ko,$o,Qo,tl,el,nl,new Qe),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function rl(t,e,n,i,r,s){Yo.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(Zo.x=s*Yo.x-r*Yo.y,Zo.y=r*Yo.x+s*Yo.y):Zo.copy(Yo),t.copy(e),t.x+=Zo.x,t.y+=Zo.y,t.applyMatrix4(Jo)}const sl=new Rn,al=new Rn;class ol extends Ci{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,n=e.length;t0){let n,i;for(n=1,i=e.length;n0){sl.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(sl);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){sl.setFromMatrixPosition(t.matrixWorld),al.setFromMatrixPosition(this.matrixWorld);const n=sl.distanceTo(al)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;io)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);st.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}else{for(let n=Math.max(0,s.start),i=Math.min(m.count,s.start+s.count)-1;no)continue;u.applyMatrix4(this.matrixWorld);const i=t.ray.origin.distanceTo(u);it.far||e.push({distance:i,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length>0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}class Jl extends Sn{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Kl{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)}getPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPoint(n/t));return e}getSpacedPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPointAt(n/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o<=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a<0)o=i+1;else{if(!(a>0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i<0&&(i=0),r>1&&(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new Qe:new Rn);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new Rn,i=[],r=[],s=[],a=new Rn,o=new ri;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new Rn)}r[0]=new Rn,s[0]=new Rn;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c<=l&&(l=c,n.set(1,0,0)),h<=l&&(l=h,n.set(0,1,0)),u<=l&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(i[e-1],i[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(We(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(We(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let n=1;n<=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.6,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class $l extends Kl{constructor(t=0,e=0,n=1,i=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const n=e||new Qe,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=i[(l-1)%r]:(ec.subVectors(i[0],i[1]).add(i[0]),a=ec);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2i.length-2?i.length-1:s+1],h=i[s>i.length-3?i.length-1:s+2];return n.set(ac(a,o.x,l.x,c.x,h.x),ac(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const t=i[r]-n,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let n=0,i=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class yc extends fr{constructor(t=[new Qe(0,-.5),new Qe(.5,0),new Qe(0,.5)],e=12,n=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:n,phiLength:i},e=Math.floor(e),i=We(i,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new Rn,u=new Qe,d=new Rn,p=new Rn,m=new Rn;let f=0,g=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=n+r*c*i,p=Math.sin(d),m=Math.cos(d);for(let n=0;n<=t.length-1;n++){h.x=t[n].x*p,h.y=t[n].y,h.z=t[n].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=n/(t.length-1),a.push(u.x,u.y);const i=o[3*n+0]*p,c=o[3*n+1],d=o[3*n+0]*m;l.push(i,c,d)}}for(let n=0;n0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new or(h,3)),this.setAttribute("normal",new or(u,3)),this.setAttribute("uv",new or(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Sc(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class bc extends Sc{constructor(t=1,e=1,n=32,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new bc(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Tc extends fr{constructor(t=[],e=[],n=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i<=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t<=l;t++)s[i][t]=0===t&&i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),n<.2&&(s[t+2]+=1),i<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new or(r,3)),this.setAttribute("normal",new or(r.slice(),3)),this.setAttribute("uv",new or(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Tc(t.vertices,t.indices,t.radius,t.details)}}class Ec extends Tc{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new Ec(t.radius,t.detail)}}const wc=new Rn,Ac=new Rn,Rc=new Rn,Cc=new Hi;class Lc extends fr{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(He*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t80*n){o=c=t[0],l=h=t[1];for(let e=n;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return Nc(s,a,n,o,l,p,0),a};function Uc(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s0)for(s=e;s=e;s-=i)a=th(s,t[s],t[s+1],a);return a&&Yc(a,a.next)&&(eh(a),a=a.next),a}function Dc(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!Yc(i,i.next)&&0!==qc(i.prev,i,i.next))i=i.next;else{if(eh(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function Nc(t,e,n,i,r,s,a){if(!t)return;!a&&s&&function(t,e,n,i){let r=t;do{0===r.z&&(r.z=Vc(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e0||l>0&&i;)0!==o&&(0===l||!i||n.z<=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a>1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Fc(t,i,r,s):Oc(t))e.push(o.i/n|0),e.push(t.i/n|0),e.push(l.i/n|0),eh(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Nc(t=Bc(Dc(t),e,n),e,n,i,r,s,2):2===a&&zc(t,e,n,i,r,s):Nc(Dc(t),e,n,i,r,s,1);break}}function Oc(t){const e=t.prev,n=t,i=t.next;if(qc(e,n,i)>=0)return!1;const r=e.x,s=n.x,a=i.x,o=e.y,l=n.y,c=i.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=i.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&Xc(r,o,s,l,a,c,m.x,m.y)&&qc(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Fc(t,e,n,i){const r=t.prev,s=t,a=t.next;if(qc(r,s,a)>=0)return!1;const o=r.x,l=s.x,c=a.x,h=r.y,u=s.y,d=a.y,p=ol?o>c?o:c:l>c?l:c,g=h>u?h>d?h:d:u>d?u:d,v=Vc(p,m,e,n,i),_=Vc(f,g,e,n,i);let y=t.prevZ,x=t.nextZ;for(;y&&y.z>=v&&x&&x.z<=_;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Xc(o,h,l,u,c,d,y.x,y.y)&&qc(y.prev,y,y.next)>=0)return!1;if(y=y.prevZ,x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Xc(o,h,l,u,c,d,x.x,x.y)&&qc(x.prev,x,x.next)>=0)return!1;x=x.nextZ}for(;y&&y.z>=v;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Xc(o,h,l,u,c,d,y.x,y.y)&&qc(y.prev,y,y.next)>=0)return!1;y=y.prevZ}for(;x&&x.z<=_;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Xc(o,h,l,u,c,d,x.x,x.y)&&qc(x.prev,x,x.next)>=0)return!1;x=x.nextZ}return!0}function Bc(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!Yc(r,s)&&Zc(r,i,i.next,s)&&$c(r,s)&&$c(s,r)&&(e.push(r.i/n|0),e.push(i.i/n|0),e.push(s.i/n|0),eh(i),eh(i.next),i=t=s),i=i.next}while(i!==t);return Dc(i)}function zc(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&jc(a,t)){let o=Qc(a,t);return a=Dc(a,a.next),o=Dc(o,o.next),Nc(a,e,n,i,r,s,0),void Nc(o,e,n,i,r,s,0)}t=t.next}a=a.next}while(a!==t)}function Gc(t,e){return t.x-e.x}function Hc(t,e){const n=function(t,e){let n,i=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=i.y&&a>=i.next.y&&i.next.y!==i.y){const t=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=s&&t>r&&(r=t,n=i.x=i.x&&i.x>=l&&s!==i.x&&Xc(an.x||i.x===n.x&&kc(n,i)))&&(n=i,u=h)),i=i.next}while(i!==o);return n}(t,e);if(!n)return e;const i=Qc(n,t);return Dc(i,i.next),Dc(n,n.next)}function kc(t,e){return qc(t.prev,t,e.prev)<0&&qc(e.next,t,t.next)<0}function Vc(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-n)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function Wc(t){let e=t,n=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(i-o)>=(n-a)*(e-o)&&(n-a)*(s-o)>=(r-a)*(i-o)}function jc(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&Zc(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&($c(t,e)&&$c(e,t)&&function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y>s!=n.next.y>s&&n.next.y!==n.y&&r<(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)&&(qc(t.prev,t,e.prev)||qc(t,e.prev,e))||Yc(t,e)&&qc(t.prev,t,t.next)>0&&qc(e.prev,e,e.next)>0)}function qc(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function Yc(t,e){return t.x===e.x&&t.y===e.y}function Zc(t,e,n,i){const r=Kc(qc(t,e,n)),s=Kc(qc(t,e,i)),a=Kc(qc(n,i,t)),o=Kc(qc(n,i,e));return r!==s&&a!==o||(!(0!==r||!Jc(t,n,e))||(!(0!==s||!Jc(t,i,e))||(!(0!==a||!Jc(n,t,i))||!(0!==o||!Jc(n,e,i)))))}function Jc(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function Kc(t){return t>0?1:t<0?-1:0}function $c(t,e){return qc(t.prev,t,t.next)<0?qc(t,e,t.next)>=0&&qc(t,t.prev,e)>=0:qc(t,e,t.prev)<0||qc(t,t.next,e)<0}function Qc(t,e){const n=new nh(t.i,t.x,t.y),i=new nh(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function th(t,e,n,i){const r=new nh(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function eh(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function nh(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class ih{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function sh(t,e){for(let n=0;nNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g<=2)return new Qe(i,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new Qe(i/s,r/s)}const P=[];for(let t=0,e=w.length,n=e-1,i=t+1;t=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=w.length;t=0;){const i=n;let r=n-1;r<0&&(r=t.length-1);for(let t=0,n=o+2*p;t0)&&d.push(e,r,l),(t!==n-1||o0!=t>0&&this.version++,this._anisotropy=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get sheen(){return this._sheen}set sheen(t){this._sheen>0!=t>0&&this.version++,this._sheen=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class Th extends Vi{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Yi(16777215),this.specular=new Yi(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Yi(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xe,this.normalScale=new Qe(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=H,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Eh extends Vi{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Yi(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Yi(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xe,this.normalScale=new Qe(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class wh extends Vi{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xe,this.normalScale=new Qe(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class Ah extends Vi{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Yi(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Yi(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xe,this.normalScale=new Qe(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=H,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Rh extends Vi{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Yi(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=xe,this.normalScale=new Qe(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Ch extends Il{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function Lh(t,e,n){return Ih(t)?new t.constructor(t.subarray(e,void 0!==n?n:t.length)):t.slice(e,n)}function Ph(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Ih(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Uh(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n}function Dh(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r}function Nh(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&&void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&&(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&&(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&&(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)}const Oh={arraySlice:Lh,convertArray:Ph,isTypedArray:Ih,getKeyframeOrder:Uh,sortedArray:Dh,flattenJSON:Nh,subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=i)){l.push(e.times[t]);for(let n=0;ns.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*l+o,e=t+l-o;d=Lh(i.values,t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=Lh(t.resultBuffer,e,n)}if("quaternion"===r){(new An).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=n,n=0}}for(;n>>1;te;)--s;if(++s,0!==r||s!==i){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=Lh(n,r,s),this.values=Lh(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==s&&s>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,s),t=!1;break}s=i}if(void 0!==i&&Ih(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,n),t=!1;break}}return t}optimize(){const t=Lh(this.times),e=Lh(this.values),n=this.getValueSize(),i=this.getInterpolation()===ue,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=Lh(t,0,s),this.values=Lh(e,0,s*n)):(this.times=t,this.values=e),this}clone(){const t=Lh(this.times,0),e=Lh(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}Hh.prototype.TimeBufferType=Float32Array,Hh.prototype.ValueBufferType=Float32Array,Hh.prototype.DefaultInterpolation=he;class kh extends Hh{}kh.prototype.ValueTypeName="bool",kh.prototype.ValueBufferType=Array,kh.prototype.DefaultInterpolation=ce,kh.prototype.InterpolantFactoryMethodLinear=void 0,kh.prototype.InterpolantFactoryMethodSmooth=void 0;class Vh extends Hh{}Vh.prototype.ValueTypeName="color";class Wh extends Hh{}Wh.prototype.ValueTypeName="number";class Xh extends Fh{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)An.slerpFlat(r,0,s,l-a,s,l,o);return r}}class jh extends Hh{InterpolantFactoryMethodLinear(t){return new Xh(this.times,this.values,this.getValueSize(),t)}}jh.prototype.ValueTypeName="quaternion",jh.prototype.DefaultInterpolation=he,jh.prototype.InterpolantFactoryMethodSmooth=void 0;class qh extends Hh{}qh.prototype.ValueTypeName="string",qh.prototype.ValueBufferType=Array,qh.prototype.DefaultInterpolation=ce,qh.prototype.InterpolantFactoryMethodLinear=void 0,qh.prototype.InterpolantFactoryMethodSmooth=void 0;class Yh extends Hh{}Yh.prototype.ValueTypeName="vector";class Zh{constructor(t,e=-1,n,i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=Ve(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(Jh(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(Hh.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];Nh(n,s,a,i),0!==s.length&&r.push(new t(e,s,a))}},i=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==eu[t])return void eu[t].push({onLoad:e,onProgress:n,onError:i});eu[t]=[],eu[t].push({onLoad:e,onProgress:n,onError:i});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),a=this.mimeType,o=this.responseType;fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const n=eu[t],i=e.body.getReader(),r=e.headers.get("Content-Length")||e.headers.get("X-File-Size"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t{switch(o){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,a)));case"json":return t.json();default:if(void 0===a)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(a),n=e&&e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(n);return t.arrayBuffer().then((t=>i.decode(t)))}}})).then((e=>{Kh.add(t,e);const n=eu[t];delete eu[t];for(let t=0,i=n.length;t{const n=eu[t];if(void 0===n)throw this.manager.itemError(t),e;delete eu[t];for(let t=0,i=n.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class ru extends tu{constructor(t){super(t)}load(t,e,n,i){void 0!==this.path&&(t=this.path+t),t=this.manager.resolveURL(t);const r=this,s=Kh.get(t);if(void 0!==s)return r.manager.itemStart(t),setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s;const a=an("img");function o(){c(),Kh.add(t,this),e&&e(this),r.manager.itemEnd(t)}function l(e){c(),i&&i(e),r.manager.itemError(t),r.manager.itemEnd(t)}function c(){a.removeEventListener("load",o,!1),a.removeEventListener("error",l,!1)}return a.addEventListener("load",o,!1),a.addEventListener("error",l,!1),"data:"!==t.slice(0,5)&&void 0!==this.crossOrigin&&(a.crossOrigin=this.crossOrigin),r.manager.itemStart(t),a.src=t,a}}class su extends Ci{constructor(t,e=1){super(),this.isLight=!0,this.type="Light",this.color=new Yi(t),this.intensity=e}dispose(){}copy(t,e){return super.copy(t,e),this.color.copy(t.color),this.intensity=t.intensity,this}toJSON(t){const e=super.toJSON(t);return e.object.color=this.color.getHex(),e.object.intensity=this.intensity,void 0!==this.groundColor&&(e.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(e.object.distance=this.distance),void 0!==this.angle&&(e.object.angle=this.angle),void 0!==this.decay&&(e.object.decay=this.decay),void 0!==this.penumbra&&(e.object.penumbra=this.penumbra),void 0!==this.shadow&&(e.object.shadow=this.shadow.toJSON()),e}}class au extends su{constructor(t,e,n){super(t,n),this.isHemisphereLight=!0,this.type="HemisphereLight",this.position.copy(Ci.DEFAULT_UP),this.updateMatrix(),this.groundColor=new Yi(e)}copy(t,e){return super.copy(t,e),this.groundColor.copy(t.groundColor),this}}const ou=new ri,lu=new Rn,cu=new Rn;class hu{constructor(t){this.camera=t,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new Qe(512,512),this.map=null,this.mapPass=null,this.matrix=new ri,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new Qr,this._frameExtents=new Qe(1,1),this._viewportCount=1,this._viewports=[new bn(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(t){const e=this.camera,n=this.matrix;lu.setFromMatrixPosition(t.matrixWorld),e.position.copy(lu),cu.setFromMatrixPosition(t.target.matrixWorld),e.lookAt(cu),e.updateMatrixWorld(),ou.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this._frustum.setFromProjectionMatrix(ou),n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(ou)}getViewport(t){return this._viewports[t]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(t){return this.camera=t.camera.clone(),this.bias=t.bias,this.radius=t.radius,this.mapSize.copy(t.mapSize),this}clone(){return(new this.constructor).copy(this)}toJSON(){const t={};return 0!==this.bias&&(t.bias=this.bias),0!==this.normalBias&&(t.normalBias=this.normalBias),1!==this.radius&&(t.radius=this.radius),512===this.mapSize.x&&512===this.mapSize.y||(t.mapSize=this.mapSize.toArray()),t.camera=this.camera.toJSON(!1).object,delete t.camera.matrix,t}}class uu extends hu{constructor(){super(new kr(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(t){const e=this.camera,n=2*ke*t.angle*this.focus,i=this.mapSize.width/this.mapSize.height,r=t.distance||e.far;n===e.fov&&i===e.aspect&&r===e.far||(e.fov=n,e.aspect=i,e.far=r,e.updateProjectionMatrix()),super.updateMatrices(t)}copy(t){return super.copy(t),this.focus=t.focus,this}}class du extends su{constructor(t,e,n=0,i=Math.PI/3,r=0,s=2){super(t,e),this.isSpotLight=!0,this.type="SpotLight",this.position.copy(Ci.DEFAULT_UP),this.updateMatrix(),this.target=new Ci,this.distance=n,this.angle=i,this.penumbra=r,this.decay=s,this.map=null,this.shadow=new uu}get power(){return this.intensity*Math.PI}set power(t){this.intensity=t/Math.PI}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.angle=t.angle,this.penumbra=t.penumbra,this.decay=t.decay,this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}const pu=new ri,mu=new Rn,fu=new Rn;class gu extends hu{constructor(){super(new kr(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new Qe(4,2),this._viewportCount=6,this._viewports=[new bn(2,1,1,1),new bn(0,1,1,1),new bn(3,1,1,1),new bn(1,1,1,1),new bn(3,0,1,1),new bn(1,0,1,1)],this._cubeDirections=[new Rn(1,0,0),new Rn(-1,0,0),new Rn(0,0,1),new Rn(0,0,-1),new Rn(0,1,0),new Rn(0,-1,0)],this._cubeUps=[new Rn(0,1,0),new Rn(0,1,0),new Rn(0,1,0),new Rn(0,1,0),new Rn(0,0,1),new Rn(0,0,-1)]}updateMatrices(t,e=0){const n=this.camera,i=this.matrix,r=t.distance||n.far;r!==n.far&&(n.far=r,n.updateProjectionMatrix()),mu.setFromMatrixPosition(t.matrixWorld),n.position.copy(mu),fu.copy(n.position),fu.add(this._cubeDirections[e]),n.up.copy(this._cubeUps[e]),n.lookAt(fu),n.updateMatrixWorld(),i.makeTranslation(-mu.x,-mu.y,-mu.z),pu.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(pu)}}class vu extends su{constructor(t,e,n=0,i=2){super(t,e),this.isPointLight=!0,this.type="PointLight",this.distance=n,this.decay=i,this.shadow=new gu}get power(){return 4*this.intensity*Math.PI}set power(t){this.intensity=t/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(t,e){return super.copy(t,e),this.distance=t.distance,this.decay=t.decay,this.shadow=t.shadow.clone(),this}}class _u extends hu{constructor(){super(new ps(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}}class yu extends su{constructor(t,e){super(t,e),this.isDirectionalLight=!0,this.type="DirectionalLight",this.position.copy(Ci.DEFAULT_UP),this.updateMatrix(),this.target=new Ci,this.shadow=new _u}dispose(){this.shadow.dispose()}copy(t){return super.copy(t),this.target=t.target.clone(),this.shadow=t.shadow.clone(),this}}class xu extends su{constructor(t,e){super(t,e),this.isAmbientLight=!0,this.type="AmbientLight"}}class Mu extends su{constructor(t,e,n=10,i=10){super(t,e),this.isRectAreaLight=!0,this.type="RectAreaLight",this.width=n,this.height=i}get power(){return this.intensity*this.width*this.height*Math.PI}set power(t){this.intensity=t/(this.width*this.height*Math.PI)}copy(t){return super.copy(t),this.width=t.width,this.height=t.height,this}toJSON(t){const e=super.toJSON(t);return e.object.width=this.width,e.object.height=this.height,e}}class Su{constructor(){this.isSphericalHarmonics3=!0,this.coefficients=[];for(let t=0;t<9;t++)this.coefficients.push(new Rn)}set(t){for(let e=0;e<9;e++)this.coefficients[e].copy(t[e]);return this}zero(){for(let t=0;t<9;t++)this.coefficients[t].set(0,0,0);return this}getAt(t,e){const n=t.x,i=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.282095),e.addScaledVector(s[1],.488603*i),e.addScaledVector(s[2],.488603*r),e.addScaledVector(s[3],.488603*n),e.addScaledVector(s[4],n*i*1.092548),e.addScaledVector(s[5],i*r*1.092548),e.addScaledVector(s[6],.315392*(3*r*r-1)),e.addScaledVector(s[7],n*r*1.092548),e.addScaledVector(s[8],.546274*(n*n-i*i)),e}getIrradianceAt(t,e){const n=t.x,i=t.y,r=t.z,s=this.coefficients;return e.copy(s[0]).multiplyScalar(.886227),e.addScaledVector(s[1],1.023328*i),e.addScaledVector(s[2],1.023328*r),e.addScaledVector(s[3],1.023328*n),e.addScaledVector(s[4],.858086*n*i),e.addScaledVector(s[5],.858086*i*r),e.addScaledVector(s[6],.743125*r*r-.247708),e.addScaledVector(s[7],.858086*n*r),e.addScaledVector(s[8],.429043*(n*n-i*i)),e}add(t){for(let e=0;e<9;e++)this.coefficients[e].add(t.coefficients[e]);return this}addScaledSH(t,e){for(let n=0;n<9;n++)this.coefficients[n].addScaledVector(t.coefficients[n],e);return this}scale(t){for(let e=0;e<9;e++)this.coefficients[e].multiplyScalar(t);return this}lerp(t,e){for(let n=0;n<9;n++)this.coefficients[n].lerp(t.coefficients[n],e);return this}equals(t){for(let e=0;e<9;e++)if(!this.coefficients[e].equals(t.coefficients[e]))return!1;return!0}copy(t){return this.set(t.coefficients)}clone(){return(new this.constructor).copy(this)}fromArray(t,e=0){const n=this.coefficients;for(let i=0;i<9;i++)n[i].fromArray(t,e+3*i);return this}toArray(t=[],e=0){const n=this.coefficients;for(let i=0;i<9;i++)n[i].toArray(t,e+3*i);return t}static getBasisAt(t,e){const n=t.x,i=t.y,r=t.z;e[0]=.282095,e[1]=.488603*i,e[2]=.488603*r,e[3]=.488603*n,e[4]=1.092548*n*i,e[5]=1.092548*i*r,e[6]=.315392*(3*r*r-1),e[7]=1.092548*n*r,e[8]=.546274*(n*n-i*i)}}class bu extends su{constructor(t=new Su,e=1){super(void 0,e),this.isLightProbe=!0,this.sh=t}copy(t){return super.copy(t),this.sh.copy(t.sh),this}fromJSON(t){return this.intensity=t.intensity,this.sh.fromArray(t.sh),this}toJSON(t){const e=super.toJSON(t);return e.object.sh=this.sh.toArray(),e}}class Tu extends tu{constructor(t){super(t),this.textures={}}load(t,e,n,i){const r=this,s=new iu(r.manager);s.setPath(r.path),s.setRequestHeader(r.requestHeader),s.setWithCredentials(r.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=this.textures;function n(t){return void 0===e[t]&&console.warn("THREE.MaterialLoader: Undefined texture",t),e[t]}const i=Tu.createMaterialFromType(t.type);if(void 0!==t.uuid&&(i.uuid=t.uuid),void 0!==t.name&&(i.name=t.name),void 0!==t.color&&void 0!==i.color&&i.color.setHex(t.color),void 0!==t.roughness&&(i.roughness=t.roughness),void 0!==t.metalness&&(i.metalness=t.metalness),void 0!==t.sheen&&(i.sheen=t.sheen),void 0!==t.sheenColor&&(i.sheenColor=(new Yi).setHex(t.sheenColor)),void 0!==t.sheenRoughness&&(i.sheenRoughness=t.sheenRoughness),void 0!==t.emissive&&void 0!==i.emissive&&i.emissive.setHex(t.emissive),void 0!==t.specular&&void 0!==i.specular&&i.specular.setHex(t.specular),void 0!==t.specularIntensity&&(i.specularIntensity=t.specularIntensity),void 0!==t.specularColor&&void 0!==i.specularColor&&i.specularColor.setHex(t.specularColor),void 0!==t.shininess&&(i.shininess=t.shininess),void 0!==t.clearcoat&&(i.clearcoat=t.clearcoat),void 0!==t.clearcoatRoughness&&(i.clearcoatRoughness=t.clearcoatRoughness),void 0!==t.iridescence&&(i.iridescence=t.iridescence),void 0!==t.iridescenceIOR&&(i.iridescenceIOR=t.iridescenceIOR),void 0!==t.iridescenceThicknessRange&&(i.iridescenceThicknessRange=t.iridescenceThicknessRange),void 0!==t.transmission&&(i.transmission=t.transmission),void 0!==t.thickness&&(i.thickness=t.thickness),void 0!==t.attenuationDistance&&(i.attenuationDistance=t.attenuationDistance),void 0!==t.attenuationColor&&void 0!==i.attenuationColor&&i.attenuationColor.setHex(t.attenuationColor),void 0!==t.anisotropy&&(i.anisotropy=t.anisotropy),void 0!==t.anisotropyRotation&&(i.anisotropyRotation=t.anisotropyRotation),void 0!==t.fog&&(i.fog=t.fog),void 0!==t.flatShading&&(i.flatShading=t.flatShading),void 0!==t.blending&&(i.blending=t.blending),void 0!==t.combine&&(i.combine=t.combine),void 0!==t.side&&(i.side=t.side),void 0!==t.shadowSide&&(i.shadowSide=t.shadowSide),void 0!==t.opacity&&(i.opacity=t.opacity),void 0!==t.transparent&&(i.transparent=t.transparent),void 0!==t.alphaTest&&(i.alphaTest=t.alphaTest),void 0!==t.depthTest&&(i.depthTest=t.depthTest),void 0!==t.depthWrite&&(i.depthWrite=t.depthWrite),void 0!==t.colorWrite&&(i.colorWrite=t.colorWrite),void 0!==t.stencilWrite&&(i.stencilWrite=t.stencilWrite),void 0!==t.stencilWriteMask&&(i.stencilWriteMask=t.stencilWriteMask),void 0!==t.stencilFunc&&(i.stencilFunc=t.stencilFunc),void 0!==t.stencilRef&&(i.stencilRef=t.stencilRef),void 0!==t.stencilFuncMask&&(i.stencilFuncMask=t.stencilFuncMask),void 0!==t.stencilFail&&(i.stencilFail=t.stencilFail),void 0!==t.stencilZFail&&(i.stencilZFail=t.stencilZFail),void 0!==t.stencilZPass&&(i.stencilZPass=t.stencilZPass),void 0!==t.wireframe&&(i.wireframe=t.wireframe),void 0!==t.wireframeLinewidth&&(i.wireframeLinewidth=t.wireframeLinewidth),void 0!==t.wireframeLinecap&&(i.wireframeLinecap=t.wireframeLinecap),void 0!==t.wireframeLinejoin&&(i.wireframeLinejoin=t.wireframeLinejoin),void 0!==t.rotation&&(i.rotation=t.rotation),1!==t.linewidth&&(i.linewidth=t.linewidth),void 0!==t.dashSize&&(i.dashSize=t.dashSize),void 0!==t.gapSize&&(i.gapSize=t.gapSize),void 0!==t.scale&&(i.scale=t.scale),void 0!==t.polygonOffset&&(i.polygonOffset=t.polygonOffset),void 0!==t.polygonOffsetFactor&&(i.polygonOffsetFactor=t.polygonOffsetFactor),void 0!==t.polygonOffsetUnits&&(i.polygonOffsetUnits=t.polygonOffsetUnits),void 0!==t.dithering&&(i.dithering=t.dithering),void 0!==t.alphaToCoverage&&(i.alphaToCoverage=t.alphaToCoverage),void 0!==t.premultipliedAlpha&&(i.premultipliedAlpha=t.premultipliedAlpha),void 0!==t.forceSinglePass&&(i.forceSinglePass=t.forceSinglePass),void 0!==t.visible&&(i.visible=t.visible),void 0!==t.toneMapped&&(i.toneMapped=t.toneMapped),void 0!==t.userData&&(i.userData=t.userData),void 0!==t.vertexColors&&("number"==typeof t.vertexColors?i.vertexColors=t.vertexColors>0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=n(r.value);break;case"c":i.uniforms[e].value=(new Yi).setHex(r.value);break;case"v2":i.uniforms[e].value=(new Qe).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Rn).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new bn).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new tn).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new ri).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&&(i.lights=t.lights),void 0!==t.clipping&&(i.clipping=t.clipping),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=n(t.map)),void 0!==t.matcap&&(i.matcap=n(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new Qe).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=n(t.envMap)),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Qe).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(i.iridescenceMap=n(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(i.iridescenceThicknessMap=n(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=n(t.thicknessMap)),void 0!==t.anisotropyMap&&(i.anisotropyMap=n(t.anisotropyMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:xh,SpriteMaterial:Vo,RawShaderMaterial:Mh,ShaderMaterial:Gr,PointsMaterial:Vl,MeshPhysicalMaterial:bh,MeshStandardMaterial:Sh,MeshPhongMaterial:Th,MeshToonMaterial:Eh,MeshNormalMaterial:wh,MeshLambertMaterial:Ah,MeshDepthMaterial:xo,MeshDistanceMaterial:Mo,MeshBasicMaterial:Ji,MeshMatcapMaterial:Rh,LineDashedMaterial:Ch,LineBasicMaterial:Il,Material:Vi}[t]}}class Eu{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;n0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let n=t;n=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){An.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;An.multiplyQuaternionsFlat(t,s,t,e,t,n),An.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const Yu="\\[\\]\\.:\\/",Zu=new RegExp("["+Yu+"]","g"),Ju="[^"+Yu+"]",Ku="[^"+Yu.replace("\\.","")+"]",$u=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",Ju)+/(WCOD+)?/.source.replace("WCOD",Ku)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",Ju)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",Ju)+"$"),Qu=["material","materials","bones","map"];class td{constructor(t,e,n){this.path=e,this.parsedPath=n||td.parseTrackName(e),this.node=td.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&&t.isAnimationObjectGroup?new td.Composite(t,e,n):new td(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(Zu,"")}static parseTrackName(t){const e=$u.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=n.nodeName.substring(i+1);-1!==Qu.indexOf(t)&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return n}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===ge)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&&1==(1&r)?e-i:i;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),i>=e||i<0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:n})}}else this.time=i;if(s&&1==(1&r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=pe,i.endingEnd=pe):(i.endingStart=t?this.zeroSlopeAtStart?pe:de:me,i.endingEnd=e?this.zeroSlopeAtEnd?pe:de:me)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&&(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}const nd=new Float32Array(1);class id{constructor(t){this.value=t}clone(){return new id(void 0===this.value.clone?this.value:this.value.clone())}}let rd=0;function sd(t,e){return t.distance-e.distance}function ad(t,e,n,i){if(t.layers.test(e.layers)&&t.raycast(e,n),!0===i){const i=t.children;for(let t=0,r=i.length;t=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;t=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new td(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}},t.AnimationUtils=Oh,t.ArcCurve=Ql,t.ArrayCamera=wo,t.ArrowHelper=class extends Ci{constructor(t=new Rn(0,0,1),e=new Rn(0,0,0),n=1,i=16776960,r=.2*n,s=.2*r){super(),this.type="ArrowHelper",void 0===wd&&(wd=new fr,wd.setAttribute("position",new or([0,0,0,0,1,0],3)),Ad=new Sc(0,.5,1,5,1),Ad.translate(0,-.5,0)),this.position.copy(e),this.line=new Bl(wd,new Il({color:i,toneMapped:!1})),this.line.matrixAutoUpdate=!1,this.add(this.line),this.cone=new Ur(Ad,new Ji({color:i,toneMapped:!1})),this.cone.matrixAutoUpdate=!1,this.add(this.cone),this.setDirection(t),this.setLength(n,r,s)}setDirection(t){if(t.y>.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{Ed.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(Ed,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}},t.Audio=ku,t.AudioAnalyser=class{constructor(t,e=2048){this.analyser=t.context.createAnalyser(),this.analyser.fftSize=e,this.data=new Uint8Array(this.analyser.frequencyBinCount),t.getOutput().connect(this.analyser)}getFrequencyData(){return this.analyser.getByteFrequencyData(this.data),this.data}getAverageFrequency(){let t=0;const e=this.getFrequencyData();for(let n=0;nthis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,od).distanceTo(t)}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}},t.Box3=Pn,t.Box3Helper=class extends Hl{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new fr;i.setIndex(new rr(n,1)),i.setAttribute("position",new or([1,1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1],3)),super(i,new Il({color:e,toneMapped:!1})),this.box=t,this.type="Box3Helper",this.geometry.computeBoundingSphere()}updateMatrixWorld(t){const e=this.box;e.isEmpty()||(e.getCenter(this.position),e.getSize(this.scale),this.scale.multiplyScalar(.5),super.updateMatrixWorld(t))}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BoxBufferGeometry=class extends Nr{constructor(t,e,n,i,r,s){console.warn("THREE.BoxBufferGeometry has been renamed to THREE.BoxGeometry."),super(t,e,n,i,r,s)}},t.BoxGeometry=Nr,t.BoxHelper=class extends Hl{constructor(t,e=16776960){const n=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),i=new Float32Array(24),r=new fr;r.setIndex(new rr(n,1)),r.setAttribute("position",new rr(i,3)),super(r,new Il({color:e,toneMapped:!1})),this.object=t,this.type="BoxHelper",this.matrixAutoUpdate=!1,this.update()}update(t){if(void 0!==t&&console.warn("THREE.BoxHelper: .update() has no longer arguments."),void 0!==this.object&&Td.setFromObject(this.object),Td.isEmpty())return;const e=Td.min,n=Td.max,i=this.geometry.attributes.position,r=i.array;r[0]=n.x,r[1]=n.y,r[2]=n.z,r[3]=e.x,r[4]=n.y,r[5]=n.z,r[6]=e.x,r[7]=e.y,r[8]=n.z,r[9]=n.x,r[10]=e.y,r[11]=n.z,r[12]=n.x,r[13]=n.y,r[14]=e.z,r[15]=e.x,r[16]=n.y,r[17]=e.z,r[18]=e.x,r[19]=e.y,r[20]=e.z,r[21]=n.x,r[22]=e.y,r[23]=e.z,i.needsUpdate=!0,this.geometry.computeBoundingSphere()}setFromObject(t){return this.object=t,this.update(),this}copy(t,e){return super.copy(t,e),this.object=t.object,this}dispose(){this.geometry.dispose(),this.material.dispose()}},t.BufferAttribute=rr,t.BufferGeometry=fr,t.BufferGeometryLoader=Au,t.ByteType=dt,t.Cache=Kh,t.Camera=Hr,t.CameraHelper=class extends Hl{constructor(t){const e=new fr,n=new Il({color:16777215,vertexColors:!0,toneMapped:!1}),i=[],r=[],s={};function a(t,e){o(t),o(e)}function o(t){i.push(0,0,0),r.push(0,0,0),void 0===s[t]&&(s[t]=[]),s[t].push(i.length/3-1)}a("n1","n2"),a("n2","n4"),a("n4","n3"),a("n3","n1"),a("f1","f2"),a("f2","f4"),a("f4","f3"),a("f3","f1"),a("n1","f1"),a("n2","f2"),a("n3","f3"),a("n4","f4"),a("p","n1"),a("p","n2"),a("p","n3"),a("p","n4"),a("u1","u2"),a("u2","u3"),a("u3","u1"),a("c","t"),a("p","c"),a("cn1","cn2"),a("cn3","cn4"),a("cf1","cf2"),a("cf3","cf4"),e.setAttribute("position",new or(i,3)),e.setAttribute("color",new or(r,3)),super(e,n),this.type="CameraHelper",this.camera=t,this.camera.updateProjectionMatrix&&this.camera.updateProjectionMatrix(),this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.pointMap=s,this.update();const l=new Yi(16755200),c=new Yi(16711680),h=new Yi(43775),u=new Yi(16777215),d=new Yi(3355443);this.setColors(l,c,h,u,d)}setColors(t,e,n,i,r){const s=this.geometry.getAttribute("color");s.setXYZ(0,t.r,t.g,t.b),s.setXYZ(1,t.r,t.g,t.b),s.setXYZ(2,t.r,t.g,t.b),s.setXYZ(3,t.r,t.g,t.b),s.setXYZ(4,t.r,t.g,t.b),s.setXYZ(5,t.r,t.g,t.b),s.setXYZ(6,t.r,t.g,t.b),s.setXYZ(7,t.r,t.g,t.b),s.setXYZ(8,t.r,t.g,t.b),s.setXYZ(9,t.r,t.g,t.b),s.setXYZ(10,t.r,t.g,t.b),s.setXYZ(11,t.r,t.g,t.b),s.setXYZ(12,t.r,t.g,t.b),s.setXYZ(13,t.r,t.g,t.b),s.setXYZ(14,t.r,t.g,t.b),s.setXYZ(15,t.r,t.g,t.b),s.setXYZ(16,t.r,t.g,t.b),s.setXYZ(17,t.r,t.g,t.b),s.setXYZ(18,t.r,t.g,t.b),s.setXYZ(19,t.r,t.g,t.b),s.setXYZ(20,t.r,t.g,t.b),s.setXYZ(21,t.r,t.g,t.b),s.setXYZ(22,t.r,t.g,t.b),s.setXYZ(23,t.r,t.g,t.b),s.setXYZ(24,e.r,e.g,e.b),s.setXYZ(25,e.r,e.g,e.b),s.setXYZ(26,e.r,e.g,e.b),s.setXYZ(27,e.r,e.g,e.b),s.setXYZ(28,e.r,e.g,e.b),s.setXYZ(29,e.r,e.g,e.b),s.setXYZ(30,e.r,e.g,e.b),s.setXYZ(31,e.r,e.g,e.b),s.setXYZ(32,n.r,n.g,n.b),s.setXYZ(33,n.r,n.g,n.b),s.setXYZ(34,n.r,n.g,n.b),s.setXYZ(35,n.r,n.g,n.b),s.setXYZ(36,n.r,n.g,n.b),s.setXYZ(37,n.r,n.g,n.b),s.setXYZ(38,i.r,i.g,i.b),s.setXYZ(39,i.r,i.g,i.b),s.setXYZ(40,r.r,r.g,r.b),s.setXYZ(41,r.r,r.g,r.b),s.setXYZ(42,r.r,r.g,r.b),s.setXYZ(43,r.r,r.g,r.b),s.setXYZ(44,r.r,r.g,r.b),s.setXYZ(45,r.r,r.g,r.b),s.setXYZ(46,r.r,r.g,r.b),s.setXYZ(47,r.r,r.g,r.b),s.setXYZ(48,r.r,r.g,r.b),s.setXYZ(49,r.r,r.g,r.b),s.needsUpdate=!0}update(){const t=this.geometry,e=this.pointMap;Sd.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse),bd("c",e,t,Sd,0,0,-1),bd("t",e,t,Sd,0,0,1),bd("n1",e,t,Sd,-1,-1,-1),bd("n2",e,t,Sd,1,-1,-1),bd("n3",e,t,Sd,-1,1,-1),bd("n4",e,t,Sd,1,1,-1),bd("f1",e,t,Sd,-1,-1,1),bd("f2",e,t,Sd,1,-1,1),bd("f3",e,t,Sd,-1,1,1),bd("f4",e,t,Sd,1,1,1),bd("u1",e,t,Sd,.7,1.1,-1),bd("u2",e,t,Sd,-.7,1.1,-1),bd("u3",e,t,Sd,0,2,-1),bd("cf1",e,t,Sd,-1,0,1),bd("cf2",e,t,Sd,1,0,1),bd("cf3",e,t,Sd,0,-1,1),bd("cf4",e,t,Sd,0,1,1),bd("cn1",e,t,Sd,-1,0,-1),bd("cn2",e,t,Sd,1,0,-1),bd("cn3",e,t,Sd,0,-1,-1),bd("cn4",e,t,Sd,0,1,-1),t.getAttribute("position").needsUpdate=!0}dispose(){this.geometry.dispose(),this.material.dispose()}},t.CanvasTexture=class extends Sn{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}},t.CapsuleBufferGeometry=class extends xc{constructor(t,e,n,i){console.warn("THREE.CapsuleBufferGeometry has been renamed to THREE.CapsuleGeometry."),super(t,e,n,i)}},t.CapsuleGeometry=xc,t.CatmullRomCurve3=sc,t.CineonToneMapping=q,t.CircleBufferGeometry=class extends Mc{constructor(t,e,n,i){console.warn("THREE.CircleBufferGeometry has been renamed to THREE.CircleGeometry."),super(t,e,n,i)}},t.CircleGeometry=Mc,t.ClampToEdgeWrapping=it,t.Clock=Ou,t.Color=Yi,t.ColorKeyframeTrack=Vh,t.ColorManagement=fn,t.CompressedArrayTexture=class extends Jl{constructor(t,e,n,i,r,s){super(t,e,n,r,s),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=it}},t.CompressedTexture=Jl,t.CompressedTextureLoader=class extends tu{constructor(t){super(t)}load(t,e,n,i){const r=this,s=[],a=new Jl,o=new iu(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(r.withCredentials);let l=0;function c(c){o.load(t[c],(function(t){const n=r.parse(t,!0);s[c]={width:n.width,height:n.height,format:n.format,mipmaps:n.mipmaps},l+=1,6===l&&(1===n.mipmapCount&&(a.minFilter=lt),a.image=s,a.format=n.format,a.needsUpdate=!0,e&&e(a))}),n,i)}if(Array.isArray(t))for(let e=0,n=t.length;e0){const n=new $h(e);r=new ru(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e0){i=new ru(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e1)for(let n=0;nNumber.EPSILON){if(l<0&&(n=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x<=t.x&&t.x<=n.x||n.x<=t.x&&t.x<=a.x)return!0}}return i}const n=ih.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,s,a;const o=[];if(1===i.length)return s=i[0],a=new Pc,a.curves=s.curves,o.push(a),o;let l=!n(i[0].getPoints());l=t?!l:l;const c=[],h=[];let u,d,p=[],m=0;h[m]=void 0,p[m]=[];for(let e=0,a=i.length;e1){let t=!1,n=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}},t.WebGL1Renderer=Oo,t.WebGL3DRenderTarget=class extends Tn{constructor(t=1,e=1,n=1){super(t,e),this.isWebGL3DRenderTarget=!0,this.depth=n,this.texture=new wn(null,t,e,n),this.texture.isRenderTargetTexture=!0}},t.WebGLArrayRenderTarget=class extends Tn{constructor(t=1,e=1,n=1){super(t,e),this.isWebGLArrayRenderTarget=!0,this.depth=n,this.texture=new En(null,t,e,n),this.texture.isRenderTargetTexture=!0}},t.WebGLCubeRenderTarget=jr,t.WebGLMultipleRenderTargets=class extends Tn{constructor(t=1,e=1,n=1,i={}){super(t,e,i),this.isWebGLMultipleRenderTargets=!0;const r=this.texture;this.texture=[];for(let t=0;t Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + +const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().fromArray( [ + 0.8224621, 0.0331941, 0.0170827, + 0.1775380, 0.9668058, 0.0723974, + - 0.0000001, 0.0000001, 0.9105199 +] ); + +const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().fromArray( [ + 1.2249401, - 0.0420569, - 0.0196376, + - 0.2249404, 1.0420571, - 0.0786361, + 0.0000001, 0.0000000, 1.0982735 +] ); + +function DisplayP3ToLinearSRGB( color ) { + + // Display P3 uses the sRGB transfer functions + return color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ); + +} + +function LinearSRGBToDisplayP3( color ) { + + // Display P3 uses the sRGB transfer functions + return color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(); + +} + +// Conversions from to Linear-sRGB reference space. +const TO_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertSRGBToLinear(), + [ DisplayP3ColorSpace ]: DisplayP3ToLinearSRGB, +}; + +// Conversions to from Linear-sRGB reference space. +const FROM_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertLinearToSRGB(), + [ DisplayP3ColorSpace ]: LinearSRGBToDisplayP3, }; const ColorManagement = { - legacyMode: true, + enabled: true, + + get legacyMode() { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + return ! this.enabled; + + }, + + set legacyMode( legacyMode ) { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + this.enabled = ! legacyMode; + + }, get workingColorSpace() { @@ -1500,25 +1635,22 @@ const ColorManagement = { convert: function ( color, sourceColorSpace, targetColorSpace ) { - if ( this.legacyMode || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { return color; } - if ( FN[ sourceColorSpace ] && FN[ sourceColorSpace ][ targetColorSpace ] !== undefined ) { - - const fn = FN[ sourceColorSpace ][ targetColorSpace ]; + const sourceToLinear = TO_LINEAR[ sourceColorSpace ]; + const targetFromLinear = FROM_LINEAR[ targetColorSpace ]; - color.r = fn( color.r ); - color.g = fn( color.g ); - color.b = fn( color.b ); + if ( sourceToLinear === undefined || targetFromLinear === undefined ) { - return color; + throw new Error( `Unsupported color space conversion, "${ sourceColorSpace }" to "${ targetColorSpace }".` ); } - throw new Error( 'Unsupported color space conversion.' ); + return targetFromLinear( sourceToLinear( color ) ); }, @@ -1536,3211 +1668,2658 @@ const ColorManagement = { }; -const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, - 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, - 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, - 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, - 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, - 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, - 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, - 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, - 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, - 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, - 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, - 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, - 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, - 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, - 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, - 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, - 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, - 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, - 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, - 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, - 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, - 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, - 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, - 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - -const _rgb$1 = { r: 0, g: 0, b: 0 }; -const _hslA = { h: 0, s: 0, l: 0 }; -const _hslB = { h: 0, s: 0, l: 0 }; - -function hue2rgb( p, q, t ) { - - if ( t < 0 ) t += 1; - if ( t > 1 ) t -= 1; - if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; - if ( t < 1 / 2 ) return q; - if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); - return p; - -} - -function toComponents( source, target ) { - - target.r = source.r; - target.g = source.g; - target.b = source.b; - - return target; +let _canvas; -} +class ImageUtils { -class Color { + static getDataURL( image ) { - constructor( r, g, b ) { + if ( /^data:/i.test( image.src ) ) { - this.isColor = true; + return image.src; - this.r = 1; - this.g = 1; - this.b = 1; + } - if ( g === undefined && b === undefined ) { + if ( typeof HTMLCanvasElement === 'undefined' ) { - // r is THREE.Color, hex or string - return this.set( r ); + return image.src; } - return this.setRGB( r, g, b ); - - } + let canvas; - set( value ) { + if ( image instanceof HTMLCanvasElement ) { - if ( value && value.isColor ) { + canvas = image; - this.copy( value ); + } else { - } else if ( typeof value === 'number' ) { + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); - this.setHex( value ); + _canvas.width = image.width; + _canvas.height = image.height; - } else if ( typeof value === 'string' ) { + const context = _canvas.getContext( '2d' ); - this.setStyle( value ); + if ( image instanceof ImageData ) { - } + context.putImageData( image, 0, 0 ); - return this; + } else { - } + context.drawImage( image, 0, 0, image.width, image.height ); - setScalar( scalar ) { + } - this.r = scalar; - this.g = scalar; - this.b = scalar; + canvas = _canvas; - return this; + } - } + if ( canvas.width > 2048 || canvas.height > 2048 ) { - setHex( hex, colorSpace = SRGBColorSpace ) { + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); - hex = Math.floor( hex ); + return canvas.toDataURL( 'image/jpeg', 0.6 ); - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + return canvas.toDataURL( 'image/png' ); - return this; + } } - setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { - - this.r = r; - this.g = g; - this.b = b; + static sRGBToLinear( image ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - return this; + const canvas = createElementNS( 'canvas' ); - } + canvas.width = image.width; + canvas.height = image.height; - setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); - // h,s,l ranges are in 0.0 - 1.0 - h = euclideanModulo( h, 1 ); - s = clamp( s, 0, 1 ); - l = clamp( l, 0, 1 ); + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; - if ( s === 0 ) { + for ( let i = 0; i < data.length; i ++ ) { - this.r = this.g = this.b = l; + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; - } else { + } - const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - const q = ( 2 * l ) - p; + context.putImageData( imageData, 0, 0 ); - this.r = hue2rgb( q, p, h + 1 / 3 ); - this.g = hue2rgb( q, p, h ); - this.b = hue2rgb( q, p, h - 1 / 3 ); + return canvas; - } + } else if ( image.data ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + const data = image.data.slice( 0 ); - return this; + for ( let i = 0; i < data.length; i ++ ) { - } + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { - setStyle( style, colorSpace = SRGBColorSpace ) { + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); - function handleAlpha( string ) { + } else { - if ( string === undefined ) return; + // assuming float - if ( parseFloat( string ) < 1 ) { + data[ i ] = SRGBToLinear( data[ i ] ); - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + } } - } + return { + data: data, + width: image.width, + height: image.height + }; + } else { - let m; + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; - if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) { + } - // rgb / hsl + } - let color; - const name = m[ 1 ]; - const components = m[ 2 ]; +} - switch ( name ) { +let sourceId = 0; - case 'rgb': - case 'rgba': +class Source { - if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + constructor( data = null ) { - // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; + this.isSource = true; - ColorManagement.toWorkingColorSpace( this, colorSpace ); + Object.defineProperty( this, 'id', { value: sourceId ++ } ); - handleAlpha( color[ 4 ] ); + this.uuid = generateUUID(); - return this; + this.data = data; - } + this.version = 0; - if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + } - // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; + set needsUpdate( value ) { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + if ( value === true ) this.version ++; - handleAlpha( color[ 4 ] ); + } - return this; + toJSON( meta ) { - } + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - break; + if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { - case 'hsl': - case 'hsla': + return meta.images[ this.uuid ]; - if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + } - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - const h = parseFloat( color[ 1 ] ) / 360; - const s = parseFloat( color[ 2 ] ) / 100; - const l = parseFloat( color[ 3 ] ) / 100; + const output = { + uuid: this.uuid, + url: '' + }; - handleAlpha( color[ 4 ] ); + const data = this.data; - return this.setHSL( h, s, l, colorSpace ); + if ( data !== null ) { - } + let url; - break; + if ( Array.isArray( data ) ) { - } + // cube texture - } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { + url = []; - // hex color + for ( let i = 0, l = data.length; i < l; i ++ ) { - const hex = m[ 1 ]; - const size = hex.length; + if ( data[ i ].isDataTexture ) { - if ( size === 3 ) { + url.push( serializeImage( data[ i ].image ) ); - // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + url.push( serializeImage( data[ i ] ) ); - return this; + } - } else if ( size === 6 ) { + } - // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; + } else { - ColorManagement.toWorkingColorSpace( this, colorSpace ); + // texture - return this; + url = serializeImage( data ); } + output.url = url; + } - if ( style && style.length > 0 ) { + if ( ! isRootObject ) { - return this.setColorName( style, colorSpace ); + meta.images[ this.uuid ] = output; } - return this; + return output; } - setColorName( style, colorSpace = SRGBColorSpace ) { +} - // color keywords - const hex = _colorKeywords[ style.toLowerCase() ]; +function serializeImage( image ) { - if ( hex !== undefined ) { + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { - // red - this.setHex( hex, colorSpace ); + // default images + + return ImageUtils.getDataURL( image ); + + } else { + + if ( image.data ) { + + // images of DataTexture + + return { + data: Array.from( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; } else { - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; } - return this; - } - clone() { +} - return new this.constructor( this.r, this.g, this.b ); +let textureId = 0; - } +class Texture extends EventDispatcher { - copy( color ) { + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { - this.r = color.r; - this.g = color.g; - this.b = color.b; + super(); - return this; + this.isTexture = true; - } + Object.defineProperty( this, 'id', { value: textureId ++ } ); - copySRGBToLinear( color ) { + this.uuid = generateUUID(); - this.r = SRGBToLinear( color.r ); - this.g = SRGBToLinear( color.g ); - this.b = SRGBToLinear( color.b ); + this.name = ''; - return this; + this.source = new Source( image ); + this.mipmaps = []; - } + this.mapping = mapping; + this.channel = 0; - copyLinearToSRGB( color ) { + this.wrapS = wrapS; + this.wrapT = wrapT; - this.r = LinearToSRGB( color.r ); - this.g = LinearToSRGB( color.g ); - this.b = LinearToSRGB( color.b ); + this.magFilter = magFilter; + this.minFilter = minFilter; - return this; + this.anisotropy = anisotropy; - } + this.format = format; + this.internalFormat = null; + this.type = type; - convertSRGBToLinear() { + this.offset = new Vector2( 0, 0 ); + this.repeat = new Vector2( 1, 1 ); + this.center = new Vector2( 0, 0 ); + this.rotation = 0; - this.copySRGBToLinear( this ); + this.matrixAutoUpdate = true; + this.matrix = new Matrix3(); - return this; + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - } + if ( typeof colorSpace === 'string' ) { - convertLinearToSRGB() { + this.colorSpace = colorSpace; - this.copyLinearToSRGB( this ); + } else { // @deprecated, r152 - return this; + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace; - } + } - getHex( colorSpace = SRGBColorSpace ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + this.userData = {}; + + this.version = 0; + this.onUpdate = null; - return clamp( _rgb$1.r * 255, 0, 255 ) << 16 ^ clamp( _rgb$1.g * 255, 0, 255 ) << 8 ^ clamp( _rgb$1.b * 255, 0, 255 ) << 0; + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) } - getHexString( colorSpace = SRGBColorSpace ) { + get image() { - return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); + return this.source.data; } - getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { + set image( value = null ) { - // h,s,l ranges are in 0.0 - 1.0 + this.source.data = value; - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + } - const r = _rgb$1.r, g = _rgb$1.g, b = _rgb$1.b; + updateMatrix() { - const max = Math.max( r, g, b ); - const min = Math.min( r, g, b ); + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); - let hue, saturation; - const lightness = ( min + max ) / 2.0; + } - if ( min === max ) { + clone() { - hue = 0; - saturation = 0; + return new this.constructor().copy( this ); - } else { + } - const delta = max - min; + copy( source ) { - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + this.name = source.name; - switch ( max ) { + this.source = source.source; + this.mipmaps = source.mipmaps.slice( 0 ); - case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; - case g: hue = ( b - r ) / delta + 2; break; - case b: hue = ( r - g ) / delta + 4; break; + this.mapping = source.mapping; + this.channel = source.channel; - } + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; - hue /= 6; + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; - } + this.anisotropy = source.anisotropy; - target.h = hue; - target.s = saturation; - target.l = lightness; + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; - return target; + this.offset.copy( source.offset ); + this.repeat.copy( source.repeat ); + this.center.copy( source.center ); + this.rotation = source.rotation; - } + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy( source.matrix ); - getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.colorSpace = source.colorSpace; - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + this.userData = JSON.parse( JSON.stringify( source.userData ) ); - target.r = _rgb$1.r; - target.g = _rgb$1.g; - target.b = _rgb$1.b; + this.needsUpdate = true; - return target; + return this; } - getStyle( colorSpace = SRGBColorSpace ) { + toJSON( meta ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb$1 ), colorSpace ); + const isRootObject = ( meta === undefined || typeof meta === 'string' ); - if ( colorSpace !== SRGBColorSpace ) { + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). - return `color(${ colorSpace } ${ _rgb$1.r } ${ _rgb$1.g } ${ _rgb$1.b })`; + return meta.textures[ this.uuid ]; } - return `rgb(${( _rgb$1.r * 255 ) | 0},${( _rgb$1.g * 255 ) | 0},${( _rgb$1.b * 255 ) | 0})`; + const output = { - } + metadata: { + version: 4.6, + type: 'Texture', + generator: 'Texture.toJSON' + }, - offsetHSL( h, s, l ) { + uuid: this.uuid, + name: this.name, - this.getHSL( _hslA ); + image: this.source.toJSON( meta ).uuid, - _hslA.h += h; _hslA.s += s; _hslA.l += l; + mapping: this.mapping, + channel: this.channel, - this.setHSL( _hslA.h, _hslA.s, _hslA.l ); + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, - return this; + wrap: [ this.wrapS, this.wrapT ], - } + format: this.format, + internalFormat: this.internalFormat, + type: this.type, + colorSpace: this.colorSpace, - add( color ) { + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, - this.r += color.r; - this.g += color.g; - this.b += color.b; + flipY: this.flipY, - return this; + generateMipmaps: this.generateMipmaps, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment - } + }; - addColors( color1, color2 ) { + if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; + if ( ! isRootObject ) { - return this; + meta.textures[ this.uuid ] = output; - } + } - addScalar( s ) { + return output; - this.r += s; - this.g += s; - this.b += s; + } - return this; + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); } - sub( color ) { + transformUv( uv ) { - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); + if ( this.mapping !== UVMapping ) return uv; - return this; + uv.applyMatrix3( this.matrix ); - } + if ( uv.x < 0 || uv.x > 1 ) { - multiply( color ) { + switch ( this.wrapS ) { - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; + case RepeatWrapping: - return this; + uv.x = uv.x - Math.floor( uv.x ); + break; - } + case ClampToEdgeWrapping: - multiplyScalar( s ) { + uv.x = uv.x < 0 ? 0 : 1; + break; - this.r *= s; - this.g *= s; - this.b *= s; + case MirroredRepeatWrapping: - return this; + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { - } + uv.x = Math.ceil( uv.x ) - uv.x; - lerp( color, alpha ) { + } else { - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; + uv.x = uv.x - Math.floor( uv.x ); - return this; + } - } + break; - lerpColors( color1, color2, alpha ) { + } - this.r = color1.r + ( color2.r - color1.r ) * alpha; - this.g = color1.g + ( color2.g - color1.g ) * alpha; - this.b = color1.b + ( color2.b - color1.b ) * alpha; + } - return this; + if ( uv.y < 0 || uv.y > 1 ) { - } + switch ( this.wrapT ) { - lerpHSL( color, alpha ) { + case RepeatWrapping: - this.getHSL( _hslA ); - color.getHSL( _hslB ); + uv.y = uv.y - Math.floor( uv.y ); + break; - const h = lerp( _hslA.h, _hslB.h, alpha ); - const s = lerp( _hslA.s, _hslB.s, alpha ); - const l = lerp( _hslA.l, _hslB.l, alpha ); + case ClampToEdgeWrapping: - this.setHSL( h, s, l ); + uv.y = uv.y < 0 ? 0 : 1; + break; - return this; + case MirroredRepeatWrapping: - } + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - equals( c ) { + uv.y = Math.ceil( uv.y ) - uv.y; - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + } else { - } + uv.y = uv.y - Math.floor( uv.y ); - fromArray( array, offset = 0 ) { + } - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; + break; - return this; + } - } + } - toArray( array = [], offset = 0 ) { + if ( this.flipY ) { - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; + uv.y = 1 - uv.y; - return array; + } + + return uv; } - fromBufferAttribute( attribute, index ) { + set needsUpdate( value ) { - this.r = attribute.getX( index ); - this.g = attribute.getY( index ); - this.b = attribute.getZ( index ); + if ( value === true ) { - return this; + this.version ++; + this.source.needsUpdate = true; + + } } - toJSON() { + get encoding() { // @deprecated, r152 - return this.getHex(); + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; } - *[ Symbol.iterator ]() { + set encoding( encoding ) { // @deprecated, r152 - yield this.r; - yield this.g; - yield this.b; + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; } } -Color.NAMES = _colorKeywords; - -let _canvas; +Texture.DEFAULT_IMAGE = null; +Texture.DEFAULT_MAPPING = UVMapping; +Texture.DEFAULT_ANISOTROPY = 1; -class ImageUtils { +class Vector4 { - static getDataURL( image ) { + constructor( x = 0, y = 0, z = 0, w = 1 ) { - if ( /^data:/i.test( image.src ) ) { + Vector4.prototype.isVector4 = true; - return image.src; + this.x = x; + this.y = y; + this.z = z; + this.w = w; - } + } - if ( typeof HTMLCanvasElement == 'undefined' ) { + get width() { - return image.src; + return this.z; - } + } - let canvas; + set width( value ) { - if ( image instanceof HTMLCanvasElement ) { + this.z = value; - canvas = image; + } - } else { + get height() { - if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); + return this.w; - _canvas.width = image.width; - _canvas.height = image.height; + } - const context = _canvas.getContext( '2d' ); + set height( value ) { - if ( image instanceof ImageData ) { + this.w = value; - context.putImageData( image, 0, 0 ); + } - } else { + set( x, y, z, w ) { - context.drawImage( image, 0, 0, image.width, image.height ); + this.x = x; + this.y = y; + this.z = z; + this.w = w; - } + return this; - canvas = _canvas; + } - } + setScalar( scalar ) { - if ( canvas.width > 2048 || canvas.height > 2048 ) { + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; - console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); + return this; - return canvas.toDataURL( 'image/jpeg', 0.6 ); + } - } else { + setX( x ) { - return canvas.toDataURL( 'image/png' ); + this.x = x; - } + return this; } - static sRGBToLinear( image ) { + setY( y ) { - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + this.y = y; - const canvas = createElementNS( 'canvas' ); + return this; - canvas.width = image.width; - canvas.height = image.height; + } - const context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, image.width, image.height ); + setZ( z ) { - const imageData = context.getImageData( 0, 0, image.width, image.height ); - const data = imageData.data; + this.z = z; - for ( let i = 0; i < data.length; i ++ ) { + return this; - data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; + } - } + setW( w ) { - context.putImageData( imageData, 0, 0 ); + this.w = w; - return canvas; + return this; - } else if ( image.data ) { + } - const data = image.data.slice( 0 ); + setComponent( index, value ) { - for ( let i = 0; i < data.length; i ++ ) { + switch ( index ) { - if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + case 3: this.w = value; break; + default: throw new Error( 'index is out of range: ' + index ); - data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); + } - } else { + return this; - // assuming float + } - data[ i ] = SRGBToLinear( data[ i ] ); + getComponent( index ) { - } + switch ( index ) { - } + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + case 3: return this.w; + default: throw new Error( 'index is out of range: ' + index ); - return { - data: data, - width: image.width, - height: image.height - }; + } - } else { + } - console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); - return image; + clone() { - } + return new this.constructor( this.x, this.y, this.z, this.w ); } -} + copy( v ) { -class Source { + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; - constructor( data = null ) { + return this; - this.isSource = true; + } - this.uuid = generateUUID(); + add( v ) { - this.data = data; + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; - this.version = 0; + return this; } - set needsUpdate( value ) { + addScalar( s ) { - if ( value === true ) this.version ++; + this.x += s; + this.y += s; + this.z += s; + this.w += s; + + return this; } - toJSON( meta ) { + addVectors( a, b ) { - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; + this.w = a.w + b.w; - if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { + return this; - return meta.images[ this.uuid ]; + } - } + addScaledVector( v, s ) { - const output = { - uuid: this.uuid, - url: '' - }; + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; - const data = this.data; + return this; - if ( data !== null ) { + } - let url; + sub( v ) { - if ( Array.isArray( data ) ) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; - // cube texture + return this; - url = []; + } - for ( let i = 0, l = data.length; i < l; i ++ ) { + subScalar( s ) { - if ( data[ i ].isDataTexture ) { + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; - url.push( serializeImage( data[ i ].image ) ); + return this; - } else { + } - url.push( serializeImage( data[ i ] ) ); + subVectors( a, b ) { - } + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + this.w = a.w - b.w; - } + return this; - } else { + } - // texture + multiply( v ) { - url = serializeImage( data ); + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + this.w *= v.w; - } + return this; - output.url = url; + } - } + multiplyScalar( scalar ) { - if ( ! isRootObject ) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; - meta.images[ this.uuid ] = output; + return this; - } + } - return output; + applyMatrix4( m ) { + + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; + this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + + return this; } -} + divideScalar( scalar ) { -function serializeImage( image ) { + return this.multiplyScalar( 1 / scalar ); - if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || - ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || - ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + } - // default images + setAxisAngleFromQuaternion( q ) { - return ImageUtils.getDataURL( image ); + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - } else { + // q is assumed to be normalized - if ( image.data ) { + this.w = 2 * Math.acos( q.w ); - // images of DataTexture + const s = Math.sqrt( 1 - q.w * q.w ); - return { - data: Array.from( image.data ), - width: image.width, - height: image.height, - type: image.data.constructor.name - }; + if ( s < 0.0001 ) { + + this.x = 1; + this.y = 0; + this.z = 0; } else { - console.warn( 'THREE.Texture: Unable to serialize Texture.' ); - return {}; + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; } + return this; + } -} + setAxisAngleFromRotationMatrix( m ) { -let textureId = 0; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm -class Texture extends EventDispatcher { + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, encoding = LinearEncoding ) { + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - super(); + te = m.elements, - this.isTexture = true; + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; - Object.defineProperty( this, 'id', { value: textureId ++ } ); + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { - this.uuid = generateUUID(); + // singularity found + // first check for identity matrix which must have +1 for all terms + // in leading diagonal and zero in other terms - this.name = ''; + if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && + ( Math.abs( m13 + m31 ) < epsilon2 ) && + ( Math.abs( m23 + m32 ) < epsilon2 ) && + ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { - this.source = new Source( image ); - this.mipmaps = []; + // this singularity is identity matrix so angle = 0 - this.mapping = mapping; + this.set( 1, 0, 0, 0 ); - this.wrapS = wrapS; - this.wrapT = wrapT; + return this; // zero angle, arbitrary axis - this.magFilter = magFilter; - this.minFilter = minFilter; + } - this.anisotropy = anisotropy; + // otherwise this singularity is angle = 180 - this.format = format; - this.internalFormat = null; - this.type = type; + angle = Math.PI; - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); - this.center = new Vector2( 0, 0 ); - this.rotation = 0; - - this.matrixAutoUpdate = true; - this.matrix = new Matrix3(); - - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + const xx = ( m11 + 1 ) / 2; + const yy = ( m22 + 1 ) / 2; + const zz = ( m33 + 1 ) / 2; + const xy = ( m12 + m21 ) / 4; + const xz = ( m13 + m31 ) / 4; + const yz = ( m23 + m32 ) / 4; - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding; + if ( ( xx > yy ) && ( xx > zz ) ) { - this.userData = {}; + // m11 is the largest diagonal term - this.version = 0; - this.onUpdate = null; + if ( xx < epsilon ) { - this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not - this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) + x = 0; + y = 0.707106781; + z = 0.707106781; - } + } else { - get image() { + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; - return this.source.data; + } - } + } else if ( yy > zz ) { - set image( value ) { + // m22 is the largest diagonal term - this.source.data = value; + if ( yy < epsilon ) { - } + x = 0.707106781; + y = 0; + z = 0.707106781; - updateMatrix() { + } else { - this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; - } + } - clone() { + } else { - return new this.constructor().copy( this ); + // m33 is the largest diagonal term so base result on this - } + if ( zz < epsilon ) { - copy( source ) { + x = 0.707106781; + y = 0.707106781; + z = 0; - this.name = source.name; + } else { - this.source = source.source; - this.mipmaps = source.mipmaps.slice( 0 ); + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; - this.mapping = source.mapping; + } - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; + } - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; + this.set( x, y, z, angle ); - this.anisotropy = source.anisotropy; + return this; // return 180 deg rotation - this.format = source.format; - this.internalFormat = source.internalFormat; - this.type = source.type; + } - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; + // as we have reached here there are no singularities so we can handle normally - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + if ( Math.abs( s ) < 0.001 ) s = 1; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case - this.needsUpdate = true; + this.x = ( m32 - m23 ) / s; + this.y = ( m13 - m31 ) / s; + this.z = ( m21 - m12 ) / s; + this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); return this; } - toJSON( meta ) { - - const isRootObject = ( meta === undefined || typeof meta === 'string' ); - - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - - return meta.textures[ this.uuid ]; - - } - - const output = { - - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, + min( v ) { - uuid: this.uuid, - name: this.name, + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); + this.w = Math.min( this.w, v.w ); - image: this.source.toJSON( meta ).uuid, + return this; - mapping: this.mapping, + } - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, + max( v ) { - wrap: [ this.wrapS, this.wrapT ], + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); + this.w = Math.max( this.w, v.w ); - format: this.format, - type: this.type, - encoding: this.encoding, + return this; - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, + } - flipY: this.flipY, + clamp( min, max ) { - generateMipmaps: this.generateMipmaps, - premultiplyAlpha: this.premultiplyAlpha, - unpackAlignment: this.unpackAlignment + // assumes min < max, componentwise - }; + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); - if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; + return this; - if ( ! isRootObject ) { + } - meta.textures[ this.uuid ] = output; + clampScalar( minVal, maxVal ) { - } + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); + this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); - return output; + return this; } - dispose() { + clampLength( min, max ) { - this.dispatchEvent( { type: 'dispose' } ); + const length = this.length(); + + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); } - transformUv( uv ) { + floor() { - if ( this.mapping !== UVMapping ) return uv; + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); + this.w = Math.floor( this.w ); - uv.applyMatrix3( this.matrix ); + return this; - if ( uv.x < 0 || uv.x > 1 ) { + } - switch ( this.wrapS ) { + ceil() { - case RepeatWrapping: + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); + this.w = Math.ceil( this.w ); - uv.x = uv.x - Math.floor( uv.x ); - break; + return this; - case ClampToEdgeWrapping: + } - uv.x = uv.x < 0 ? 0 : 1; - break; + round() { - case MirroredRepeatWrapping: + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + this.w = Math.round( this.w ); - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + return this; - uv.x = Math.ceil( uv.x ) - uv.x; + } - } else { + roundToZero() { - uv.x = uv.x - Math.floor( uv.x ); + this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); + this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); + this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); + this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); - } + return this; - break; + } - } + negate() { - } + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + this.w = - this.w; - if ( uv.y < 0 || uv.y > 1 ) { + return this; - switch ( this.wrapT ) { + } - case RepeatWrapping: + dot( v ) { - uv.y = uv.y - Math.floor( uv.y ); - break; + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - case ClampToEdgeWrapping: + } - uv.y = uv.y < 0 ? 0 : 1; - break; + lengthSq() { - case MirroredRepeatWrapping: + return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + } - uv.y = Math.ceil( uv.y ) - uv.y; + length() { - } else { + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - uv.y = uv.y - Math.floor( uv.y ); + } - } + manhattanLength() { - break; + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - } + } - } + normalize() { - if ( this.flipY ) { + return this.divideScalar( this.length() || 1 ); - uv.y = 1 - uv.y; + } - } + setLength( length ) { - return uv; + return this.normalize().multiplyScalar( length ); } - set needsUpdate( value ) { - - if ( value === true ) { + lerp( v, alpha ) { - this.version ++; - this.source.needsUpdate = true; + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; + this.w += ( v.w - this.w ) * alpha; - } + return this; } -} - -Texture.DEFAULT_IMAGE = null; -Texture.DEFAULT_MAPPING = UVMapping; -Texture.DEFAULT_ANISOTROPY = 1; - -class Vector4 { - - constructor( x = 0, y = 0, z = 0, w = 1 ) { + lerpVectors( v1, v2, alpha ) { - Vector4.prototype.isVector4 = true; + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; + this.w = v1.w + ( v2.w - v1.w ) * alpha; - this.x = x; - this.y = y; - this.z = z; - this.w = w; + return this; } - get width() { + equals( v ) { - return this.z; + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); } - set width( value ) { - - this.z = value; - - } + fromArray( array, offset = 0 ) { - get height() { + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; - return this.w; + return this; } - set height( value ) { + toArray( array = [], offset = 0 ) { - this.w = value; + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; + + return array; } - set( x, y, z, w ) { + fromBufferAttribute( attribute, index ) { - this.x = x; - this.y = y; - this.z = z; - this.w = w; + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); return this; } - setScalar( scalar ) { + random() { - this.x = scalar; - this.y = scalar; - this.z = scalar; - this.w = scalar; + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); return this; } - setX( x ) { - - this.x = x; + *[ Symbol.iterator ]() { - return this; + yield this.x; + yield this.y; + yield this.z; + yield this.w; } - setY( y ) { +} - this.y = y; +/* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers +*/ +class WebGLRenderTarget extends EventDispatcher { - return this; + constructor( width = 1, height = 1, options = {} ) { - } + super(); - setZ( z ) { + this.isWebGLRenderTarget = true; - this.z = z; + this.width = width; + this.height = height; + this.depth = 1; - return this; + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; - } + this.viewport = new Vector4( 0, 0, width, height ); - setW( w ) { + const image = { width: width, height: height, depth: 1 }; - this.w = w; + if ( options.encoding !== undefined ) { - return this; + // @deprecated, r152 + warnOnce( 'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; - } + } - setComponent( index, value ) { + this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); + this.texture.isRenderTargetTexture = true; - switch ( index ) { + this.texture.flipY = false; + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - case 3: this.w = value; break; - default: throw new Error( 'index is out of range: ' + index ); + this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; + this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; - } + this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - return this; + this.samples = options.samples !== undefined ? options.samples : 0; } - getComponent( index ) { + setSize( width, height, depth = 1 ) { - switch ( index ) { + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - case 3: return this.w; - default: throw new Error( 'index is out of range: ' + index ); + this.width = width; + this.height = height; + this.depth = depth; + + this.texture.image.width = width; + this.texture.image.height = height; + this.texture.image.depth = depth; + + this.dispose(); } + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); + } clone() { - return new this.constructor( this.x, this.y, this.z, this.w ); + return new this.constructor().copy( this ); } - copy( v ) { + copy( source ) { - this.x = v.x; - this.y = v.y; - this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - return this; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - } + this.viewport.copy( source.viewport ); - add( v ) { + this.texture = source.texture.clone(); + this.texture.isRenderTargetTexture = true; - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; + // ensure image object is not shared, see #20328 - return this; + const image = Object.assign( {}, source.texture.image ); + this.texture.source = new Source( image ); - } + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - addScalar( s ) { + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - this.x += s; - this.y += s; - this.z += s; - this.w += s; + this.samples = source.samples; return this; } - addVectors( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - this.w = a.w + b.w; + dispose() { - return this; + this.dispatchEvent( { type: 'dispose' } ); } - addScaledVector( v, s ) { +} - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - this.w += v.w * s; +class DataArrayTexture extends Texture { - return this; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - } + super( null ); - sub( v ) { + this.isDataArrayTexture = true; - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; + this.image = { data, width, height, depth }; - return this; + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; - } + this.wrapR = ClampToEdgeWrapping; - subScalar( s ) { + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; - this.x -= s; - this.y -= s; - this.z -= s; - this.w -= s; + } - return this; +} - } +class WebGLArrayRenderTarget extends WebGLRenderTarget { - subVectors( a, b ) { + constructor( width = 1, height = 1, depth = 1 ) { - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - this.w = a.w - b.w; + super( width, height ); - return this; + this.isWebGLArrayRenderTarget = true; + + this.depth = depth; + + this.texture = new DataArrayTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; } - multiply( v ) { +} - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - this.w *= v.w; +class Data3DTexture extends Texture { - return this; + constructor( data = null, width = 1, height = 1, depth = 1 ) { - } + // We're going to add .setXXX() methods for setting properties later. + // Users can still set in DataTexture3D directly. + // + // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // texture.anisotropy = 16; + // + // See #14839 - multiplyScalar( scalar ) { + super( null ); - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; + this.isData3DTexture = true; - return this; + this.image = { data, width, height, depth }; + + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + + this.wrapR = ClampToEdgeWrapping; + + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; } - applyMatrix4( m ) { +} - const x = this.x, y = this.y, z = this.z, w = this.w; - const e = m.elements; +class WebGL3DRenderTarget extends WebGLRenderTarget { - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; - this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + constructor( width = 1, height = 1, depth = 1 ) { - return this; + super( width, height ); - } + this.isWebGL3DRenderTarget = true; - divideScalar( scalar ) { + this.depth = depth; - return this.multiplyScalar( 1 / scalar ); + this.texture = new Data3DTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; } - setAxisAngleFromQuaternion( q ) { +} - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm +class WebGLMultipleRenderTargets extends WebGLRenderTarget { - // q is assumed to be normalized + constructor( width = 1, height = 1, count = 1, options = {} ) { - this.w = 2 * Math.acos( q.w ); + super( width, height, options ); - const s = Math.sqrt( 1 - q.w * q.w ); + this.isWebGLMultipleRenderTargets = true; - if ( s < 0.0001 ) { + const texture = this.texture; - this.x = 1; - this.y = 0; - this.z = 0; + this.texture = []; - } else { + for ( let i = 0; i < count; i ++ ) { - this.x = q.x / s; - this.y = q.y / s; - this.z = q.z / s; + this.texture[ i ] = texture.clone(); + this.texture[ i ].isRenderTargetTexture = true; } - return this; - } - setAxisAngleFromRotationMatrix( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + setSize( width, height, depth = 1 ) { - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + if ( this.width !== width || this.height !== height || this.depth !== depth ) { - let angle, x, y, z; // variables for result - const epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + this.width = width; + this.height = height; + this.depth = depth; - te = m.elements, + for ( let i = 0, il = this.texture.length; i < il; i ++ ) { - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; + this.texture[ i ].image.width = width; + this.texture[ i ].image.height = height; + this.texture[ i ].image.depth = depth; - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { + } - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms + this.dispose(); - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + } - // this singularity is identity matrix so angle = 0 + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); - this.set( 1, 0, 0, 0 ); + return this; - return this; // zero angle, arbitrary axis + } - } + copy( source ) { - // otherwise this singularity is angle = 180 + this.dispose(); - angle = Math.PI; + this.width = source.width; + this.height = source.height; + this.depth = source.depth; - const xx = ( m11 + 1 ) / 2; - const yy = ( m22 + 1 ) / 2; - const zz = ( m33 + 1 ) / 2; - const xy = ( m12 + m21 ) / 4; - const xz = ( m13 + m31 ) / 4; - const yz = ( m23 + m32 ) / 4; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; - if ( ( xx > yy ) && ( xx > zz ) ) { + this.viewport.copy( source.viewport ); - // m11 is the largest diagonal term + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; - if ( xx < epsilon ) { + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); - x = 0; - y = 0.707106781; - z = 0.707106781; + this.texture.length = 0; - } else { + for ( let i = 0, il = source.texture.length; i < il; i ++ ) { - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; + this.texture[ i ] = source.texture[ i ].clone(); + this.texture[ i ].isRenderTargetTexture = true; - } + } - } else if ( yy > zz ) { + return this; - // m22 is the largest diagonal term + } - if ( yy < epsilon ) { +} - x = 0.707106781; - y = 0; - z = 0.707106781; +class Quaternion { - } else { + constructor( x = 0, y = 0, z = 0, w = 1 ) { - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; + this.isQuaternion = true; - } + this._x = x; + this._y = y; + this._z = z; + this._w = w; - } else { + } - // m33 is the largest diagonal term so base result on this + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - if ( zz < epsilon ) { + // fuzz-free, array-based Quaternion SLERP operation - x = 0.707106781; - y = 0.707106781; - z = 0; + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; - } else { + const x1 = src1[ srcOffset1 + 0 ], + y1 = src1[ srcOffset1 + 1 ], + z1 = src1[ srcOffset1 + 2 ], + w1 = src1[ srcOffset1 + 3 ]; - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; + if ( t === 0 ) { - } + dst[ dstOffset + 0 ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; + return; - } + } - this.set( x, y, z, angle ); + if ( t === 1 ) { - return this; // return 180 deg rotation + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; } - // as we have reached here there are no singularities so we can handle normally + if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { - let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + let s = 1 - t; + const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + dir = ( cos >= 0 ? 1 : - 1 ), + sqrSin = 1 - cos * cos; - if ( Math.abs( s ) < 0.001 ) s = 1; + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; - return this; + } - } + const tDir = t * dir; - min( v ) { + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - this.w = Math.min( this.w, v.w ); + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { - return this; + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - } + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; - max( v ) { + } - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - this.w = Math.max( this.w, v.w ); + } - return this; + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; } - clamp( min, max ) { + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { - // assumes min < max, componentwise + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; - return this; + dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; + dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; + dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; + dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; - } + return dst; - clampScalar( minVal, maxVal ) { + } - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); + get x() { - return this; + return this._x; } - clampLength( min, max ) { - - const length = this.length(); + set x( value ) { - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + this._x = value; + this._onChangeCallback(); } - floor() { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); + get y() { - return this; + return this._y; } - ceil() { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); + set y( value ) { - return this; + this._y = value; + this._onChangeCallback(); } - round() { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - this.w = Math.round( this.w ); + get z() { - return this; + return this._z; } - roundToZero() { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); + set z( value ) { - return this; + this._z = value; + this._onChangeCallback(); } - negate() { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - this.w = - this.w; + get w() { - return this; + return this._w; } - dot( v ) { + set w( value ) { - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + this._w = value; + this._onChangeCallback(); } - lengthSq() { - - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + set( x, y, z, w ) { - } + this._x = x; + this._y = y; + this._z = z; + this._w = w; - length() { + this._onChangeCallback(); - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); + return this; } - manhattanLength() { + clone() { - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + return new this.constructor( this._x, this._y, this._z, this._w ); } - normalize() { + copy( quaternion ) { - return this.divideScalar( this.length() || 1 ); + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; + + this._onChangeCallback(); + + return this; } - setLength( length ) { + setFromEuler( euler, update ) { - return this.normalize().multiplyScalar( length ); + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - } + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m - lerp( v, alpha ) { + const cos = Math.cos; + const sin = Math.sin; - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - this.w += ( v.w - this.w ) * alpha; + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); - return this; + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); - } + switch ( order ) { - lerpVectors( v1, v2, alpha ) { + case 'XYZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; - this.w = v1.w + ( v2.w - v1.w ) * alpha; + case 'YXZ': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - return this; + case 'ZXY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - } + case 'ZYX': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - equals( v ) { + case 'YZX': + this._x = s1 * c2 * c3 + c1 * s2 * s3; + this._y = c1 * s2 * c3 + s1 * c2 * s3; + this._z = c1 * c2 * s3 - s1 * s2 * c3; + this._w = c1 * c2 * c3 - s1 * s2 * s3; + break; - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); + case 'XZY': + this._x = s1 * c2 * c3 - c1 * s2 * s3; + this._y = c1 * s2 * c3 - s1 * c2 * s3; + this._z = c1 * c2 * s3 + s1 * s2 * c3; + this._w = c1 * c2 * c3 + s1 * s2 * s3; + break; - } + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); - fromArray( array, offset = 0 ) { + } - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; + if ( update !== false ) this._onChangeCallback(); return this; } - toArray( array = [], offset = 0 ) { + setFromAxisAngle( axis, angle ) { - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - return array; + // assumes axis is normalized - } + const halfAngle = angle / 2, s = Math.sin( halfAngle ); - fromBufferAttribute( attribute, index ) { + this._x = axis.x * s; + this._y = axis.y * s; + this._z = axis.z * s; + this._w = Math.cos( halfAngle ); - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); + this._onChangeCallback(); return this; } - random() { - - this.x = Math.random(); - this.y = Math.random(); - this.z = Math.random(); - this.w = Math.random(); + setFromRotationMatrix( m ) { - return this; + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - } + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - *[ Symbol.iterator ]() { + const te = m.elements, - yield this.x; - yield this.y; - yield this.z; - yield this.w; + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], - } + trace = m11 + m22 + m33; -} + if ( trace > 0 ) { -/* - In options, we can specify: - * Texture parameters for an auto-generated target texture - * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers -*/ -class WebGLRenderTarget extends EventDispatcher { + const s = 0.5 / Math.sqrt( trace + 1.0 ); - constructor( width = 1, height = 1, options = {} ) { + this._w = 0.25 / s; + this._x = ( m32 - m23 ) * s; + this._y = ( m13 - m31 ) * s; + this._z = ( m21 - m12 ) * s; - super(); + } else if ( m11 > m22 && m11 > m33 ) { - this.isWebGLRenderTarget = true; + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - this.width = width; - this.height = height; - this.depth = 1; + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; + } else if ( m22 > m33 ) { - this.viewport = new Vector4( 0, 0, width, height ); + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - const image = { width: width, height: height, depth: 1 }; + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; - this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - this.texture.isRenderTargetTexture = true; + } else { - this.texture.flipY = false; - this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; - this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; - this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; + const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; + this._w = ( m21 - m12 ) / s; + this._x = ( m13 + m31 ) / s; + this._y = ( m23 + m32 ) / s; + this._z = 0.25 * s; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; + } - this.samples = options.samples !== undefined ? options.samples : 0; + this._onChangeCallback(); + + return this; } - setSize( width, height, depth = 1 ) { + setFromUnitVectors( vFrom, vTo ) { - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + // assumes direction vectors vFrom and vTo are normalized - this.width = width; - this.height = height; - this.depth = depth; + let r = vFrom.dot( vTo ) + 1; - this.texture.image.width = width; - this.texture.image.height = height; - this.texture.image.depth = depth; + if ( r < Number.EPSILON ) { - this.dispose(); + // vFrom and vTo point in opposite directions - } + r = 0; - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - } + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; - clone() { + } else { - return new this.constructor().copy( this ); + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; - } + } - copy( source ) { + } else { - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 - this.viewport.copy( source.viewport ); + this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; + this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; + this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; + this._w = r; - this.texture = source.texture.clone(); - this.texture.isRenderTargetTexture = true; + } - // ensure image object is not shared, see #20328 + return this.normalize(); - const image = Object.assign( {}, source.texture.image ); - this.texture.source = new Source( image ); + } - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; + angleTo( q ) { - if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); + return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); - this.samples = source.samples; + } + + rotateTowards( q, step ) { + + const angle = this.angleTo( q ); + + if ( angle === 0 ) return this; + + const t = Math.min( 1, step / angle ); + + this.slerp( q, t ); return this; } - dispose() { + identity() { - this.dispatchEvent( { type: 'dispose' } ); + return this.set( 0, 0, 0, 1 ); } -} - -class DataArrayTexture extends Texture { + invert() { - constructor( data = null, width = 1, height = 1, depth = 1 ) { + // quaternion is assumed to have unit length - super( null ); + return this.conjugate(); - this.isDataArrayTexture = true; + } - this.image = { data, width, height, depth }; + conjugate() { - this.magFilter = NearestFilter; - this.minFilter = NearestFilter; + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; - this.wrapR = ClampToEdgeWrapping; + this._onChangeCallback(); - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; } -} + dot( v ) { -class WebGLArrayRenderTarget extends WebGLRenderTarget { + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - constructor( width = 1, height = 1, depth = 1 ) { + } - super( width, height ); + lengthSq() { - this.isWebGLArrayRenderTarget = true; + return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; - this.depth = depth; + } - this.texture = new DataArrayTexture( null, width, height, depth ); + length() { - this.texture.isRenderTargetTexture = true; + return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); } -} + normalize() { -class Data3DTexture extends Texture { + let l = this.length(); - constructor( data = null, width = 1, height = 1, depth = 1 ) { + if ( l === 0 ) { - // We're going to add .setXXX() methods for setting properties later. - // Users can still set in DataTexture3D directly. - // - // const texture = new THREE.DataTexture3D( data, width, height, depth ); - // texture.anisotropy = 16; - // - // See #14839 + this._x = 0; + this._y = 0; + this._z = 0; + this._w = 1; - super( null ); + } else { - this.isData3DTexture = true; + l = 1 / l; - this.image = { data, width, height, depth }; + this._x = this._x * l; + this._y = this._y * l; + this._z = this._z * l; + this._w = this._w * l; - this.magFilter = NearestFilter; - this.minFilter = NearestFilter; + } - this.wrapR = ClampToEdgeWrapping; + this._onChangeCallback(); - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; + return this; } -} - -class WebGL3DRenderTarget extends WebGLRenderTarget { - - constructor( width = 1, height = 1, depth = 1 ) { - - super( width, height ); + multiply( q ) { - this.isWebGL3DRenderTarget = true; + return this.multiplyQuaternions( this, q ); - this.depth = depth; + } - this.texture = new Data3DTexture( null, width, height, depth ); + premultiply( q ) { - this.texture.isRenderTargetTexture = true; + return this.multiplyQuaternions( q, this ); } -} - -class WebGLMultipleRenderTargets extends WebGLRenderTarget { + multiplyQuaternions( a, b ) { - constructor( width = 1, height = 1, count = 1, options = {} ) { + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - super( width, height, options ); + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - this.isWebGLMultipleRenderTargets = true; + this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; + this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; + this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; + this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - const texture = this.texture; + this._onChangeCallback(); - this.texture = []; + return this; - for ( let i = 0; i < count; i ++ ) { + } - this.texture[ i ] = texture.clone(); - this.texture[ i ].isRenderTargetTexture = true; + slerp( qb, t ) { - } + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); - } + const x = this._x, y = this._y, z = this._z, w = this._w; - setSize( width, height, depth = 1 ) { + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - if ( this.width !== width || this.height !== height || this.depth !== depth ) { + let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - this.width = width; - this.height = height; - this.depth = depth; + if ( cosHalfTheta < 0 ) { - for ( let i = 0, il = this.texture.length; i < il; i ++ ) { + this._w = - qb._w; + this._x = - qb._x; + this._y = - qb._y; + this._z = - qb._z; - this.texture[ i ].image.width = width; - this.texture[ i ].image.height = height; - this.texture[ i ].image.depth = depth; + cosHalfTheta = - cosHalfTheta; - } + } else { - this.dispose(); + this.copy( qb ); } - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); + if ( cosHalfTheta >= 1.0 ) { - return this; + this._w = w; + this._x = x; + this._y = y; + this._z = z; - } + return this; - copy( source ) { + } - this.dispose(); + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; - this.width = source.width; - this.height = source.height; - this.depth = source.depth; + if ( sqrSinHalfTheta <= Number.EPSILON ) { - this.viewport.set( 0, 0, this.width, this.height ); - this.scissor.set( 0, 0, this.width, this.height ); + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; + this.normalize(); + this._onChangeCallback(); - if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); + return this; - this.texture.length = 0; + } - for ( let i = 0, il = source.texture.length; i < il; i ++ ) { + const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); + const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); + const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, + ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - this.texture[ i ] = source.texture[ i ].clone(); - this.texture[ i ].isRenderTargetTexture = true; + this._w = ( w * ratioA + this._w * ratioB ); + this._x = ( x * ratioA + this._x * ratioB ); + this._y = ( y * ratioA + this._y * ratioB ); + this._z = ( z * ratioA + this._z * ratioB ); - } + this._onChangeCallback(); return this; } -} + slerpQuaternions( qa, qb, t ) { -class Quaternion { + return this.copy( qa ).slerp( qb, t ); - constructor( x = 0, y = 0, z = 0, w = 1 ) { + } - this.isQuaternion = true; + random() { - this._x = x; - this._y = y; - this._z = z; - this._w = w; + // Derived from http://planning.cs.uiuc.edu/node198.html + // Note, this source uses w, x, y, z ordering, + // so we swap the order below. - } + const u1 = Math.random(); + const sqrt1u1 = Math.sqrt( 1 - u1 ); + const sqrtu1 = Math.sqrt( u1 ); - static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + const u2 = 2 * Math.PI * Math.random(); - // fuzz-free, array-based Quaternion SLERP operation + const u3 = 2 * Math.PI * Math.random(); - let x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ]; + return this.set( + sqrt1u1 * Math.cos( u2 ), + sqrtu1 * Math.sin( u3 ), + sqrtu1 * Math.cos( u3 ), + sqrt1u1 * Math.sin( u2 ), + ); - const x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; + } - if ( t === 0 ) { + equals( quaternion ) { - dst[ dstOffset + 0 ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - return; + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - } + } - if ( t === 1 ) { + fromArray( array, offset = 0 ) { - dst[ dstOffset + 0 ] = x1; - dst[ dstOffset + 1 ] = y1; - dst[ dstOffset + 2 ] = z1; - dst[ dstOffset + 3 ] = w1; - return; + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; - } + this._onChangeCallback(); - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + return this; - let s = 1 - t; - const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; + } - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { + toArray( array = [], offset = 0 ) { - const sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; + return array; - } + } - const tDir = t * dir; + fromBufferAttribute( attribute, index ) { - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { + return this; - const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + } - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; + toJSON() { - } + return this.toArray(); - } + } - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; + _onChange( callback ) { - } + this._onChangeCallback = callback; - static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { + return this; - const x0 = src0[ srcOffset0 ]; - const y0 = src0[ srcOffset0 + 1 ]; - const z0 = src0[ srcOffset0 + 2 ]; - const w0 = src0[ srcOffset0 + 3 ]; + } - const x1 = src1[ srcOffset1 ]; - const y1 = src1[ srcOffset1 + 1 ]; - const z1 = src1[ srcOffset1 + 2 ]; - const w1 = src1[ srcOffset1 + 3 ]; + _onChangeCallback() {} - dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; - dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; - dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; - dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + *[ Symbol.iterator ]() { - return dst; + yield this._x; + yield this._y; + yield this._z; + yield this._w; } - get x() { +} - return this._x; +class Vector3 { - } + constructor( x = 0, y = 0, z = 0 ) { - set x( value ) { + Vector3.prototype.isVector3 = true; - this._x = value; - this._onChangeCallback(); + this.x = x; + this.y = y; + this.z = z; } - get y() { - - return this._y; + set( x, y, z ) { - } + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) - set y( value ) { + this.x = x; + this.y = y; + this.z = z; - this._y = value; - this._onChangeCallback(); + return this; } - get z() { + setScalar( scalar ) { - return this._z; + this.x = scalar; + this.y = scalar; + this.z = scalar; + + return this; } - set z( value ) { + setX( x ) { - this._z = value; - this._onChangeCallback(); + this.x = x; + + return this; } - get w() { + setY( y ) { - return this._w; + this.y = y; + + return this; } - set w( value ) { + setZ( z ) { - this._w = value; - this._onChangeCallback(); + this.z = z; + + return this; } - set( x, y, z, w ) { + setComponent( index, value ) { - this._x = x; - this._y = y; - this._z = z; - this._w = w; - - this._onChangeCallback(); - - return this; + switch ( index ) { - } + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + default: throw new Error( 'index is out of range: ' + index ); - clone() { + } - return new this.constructor( this._x, this._y, this._z, this._w ); + return this; } - copy( quaternion ) { + getComponent( index ) { - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; + switch ( index ) { - this._onChangeCallback(); + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + default: throw new Error( 'index is out of range: ' + index ); - return this; + } } - setFromEuler( euler, update ) { - - const x = euler._x, y = euler._y, z = euler._z, order = euler._order; - - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m - - const cos = Math.cos; - const sin = Math.sin; + clone() { - const c1 = cos( x / 2 ); - const c2 = cos( y / 2 ); - const c3 = cos( z / 2 ); + return new this.constructor( this.x, this.y, this.z ); - const s1 = sin( x / 2 ); - const s2 = sin( y / 2 ); - const s3 = sin( z / 2 ); + } - switch ( order ) { + copy( v ) { - case 'XYZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + this.x = v.x; + this.y = v.y; + this.z = v.z; - case 'YXZ': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this; - case 'ZXY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + } - case 'ZYX': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + add( v ) { - case 'YZX': - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - break; + this.x += v.x; + this.y += v.y; + this.z += v.z; - case 'XZY': - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - break; + return this; - default: - console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); + } - } + addScalar( s ) { - if ( update !== false ) this._onChangeCallback(); + this.x += s; + this.y += s; + this.z += s; return this; } - setFromAxisAngle( axis, angle ) { + addVectors( a, b ) { - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; - // assumes axis is normalized + return this; - const halfAngle = angle / 2, s = Math.sin( halfAngle ); + } - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); + addScaledVector( v, s ) { - this._onChangeCallback(); + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; return this; } - setFromRotationMatrix( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + sub( v ) { - const te = m.elements, + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], + return this; - trace = m11 + m22 + m33; + } - if ( trace > 0 ) { + subScalar( s ) { - const s = 0.5 / Math.sqrt( trace + 1.0 ); + this.x -= s; + this.y -= s; + this.z -= s; - this._w = 0.25 / s; - this._x = ( m32 - m23 ) * s; - this._y = ( m13 - m31 ) * s; - this._z = ( m21 - m12 ) * s; + return this; - } else if ( m11 > m22 && m11 > m33 ) { + } - const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); + subVectors( a, b ) { - this._w = ( m32 - m23 ) / s; - this._x = 0.25 * s; - this._y = ( m12 + m21 ) / s; - this._z = ( m13 + m31 ) / s; + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; - } else if ( m22 > m33 ) { + return this; - const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + } - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; + multiply( v ) { - } else { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; - const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + return this; - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; + } - } + multiplyScalar( scalar ) { - this._onChangeCallback(); + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; return this; } - setFromUnitVectors( vFrom, vTo ) { - - // assumes direction vectors vFrom and vTo are normalized - - let r = vFrom.dot( vTo ) + 1; + multiplyVectors( a, b ) { - if ( r < Number.EPSILON ) { + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; - // vFrom and vTo point in opposite directions + return this; - r = 0; + } - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + applyEuler( euler ) { - this._x = - vFrom.y; - this._y = vFrom.x; - this._z = 0; - this._w = r; + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - } else { + } - this._x = 0; - this._y = - vFrom.z; - this._z = vFrom.y; - this._w = r; + applyAxisAngle( axis, angle ) { - } + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - } else { + } - // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 + applyMatrix3( m ) { - this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; - this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; - this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; - this._w = r; + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - } + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; + this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - return this.normalize(); + return this; } - angleTo( q ) { + applyNormalMatrix( m ) { - return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); + return this.applyMatrix3( m ).normalize(); } - rotateTowards( q, step ) { - - const angle = this.angleTo( q ); + applyMatrix4( m ) { - if ( angle === 0 ) return this; + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - const t = Math.min( 1, step / angle ); + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - this.slerp( q, t ); + this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; + this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; + this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; return this; } - identity() { - - return this.set( 0, 0, 0, 1 ); + applyQuaternion( q ) { - } + const x = this.x, y = this.y, z = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - invert() { + // calculate quat * vector - // quaternion is assumed to have unit length + const ix = qw * x + qy * z - qz * y; + const iy = qw * y + qz * x - qx * z; + const iz = qw * z + qx * y - qy * x; + const iw = - qx * x - qy * y - qz * z; - return this.conjugate(); + // calculate result * inverse quat - } + this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; + this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; + this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - conjugate() { + return this; - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; + } - this._onChangeCallback(); + project( camera ) { - return this; + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); } - dot( v ) { + unproject( camera ) { - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); } - lengthSq() { + transformDirection( m ) { - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction - } + const x = this.x, y = this.y, z = this.z; + const e = m.elements; - length() { + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); + return this.normalize(); } - normalize() { + divide( v ) { - let l = this.length(); + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; - if ( l === 0 ) { + return this; - this._x = 0; - this._y = 0; - this._z = 0; - this._w = 1; + } - } else { + divideScalar( scalar ) { - l = 1 / l; + return this.multiplyScalar( 1 / scalar ); - this._x = this._x * l; - this._y = this._y * l; - this._z = this._z * l; - this._w = this._w * l; + } - } + min( v ) { - this._onChangeCallback(); + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); return this; } - multiply( q ) { + max( v ) { - return this.multiplyQuaternions( this, q ); + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); - } + return this; - premultiply( q ) { + } - return this.multiplyQuaternions( q, this ); + clamp( min, max ) { - } + // assumes min < max, componentwise - multiplyQuaternions( a, b ) { + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm + return this; - const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; + } - this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; + clampScalar( minVal, maxVal ) { - this._onChangeCallback(); + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); return this; } - slerp( qb, t ) { - - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - const x = this._x, y = this._y, z = this._z, w = this._w; + clampLength( min, max ) { - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ + const length = this.length(); - let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - if ( cosHalfTheta < 0 ) { + } - this._w = - qb._w; - this._x = - qb._x; - this._y = - qb._y; - this._z = - qb._z; + floor() { - cosHalfTheta = - cosHalfTheta; + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); - } else { + return this; - this.copy( qb ); + } - } + ceil() { - if ( cosHalfTheta >= 1.0 ) { + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); - this._w = w; - this._x = x; - this._y = y; - this._z = z; + return this; - return this; + } - } + round() { - const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); - if ( sqrSinHalfTheta <= Number.EPSILON ) { + return this; - const s = 1 - t; - this._w = s * w + t * this._w; - this._x = s * x + t * this._x; - this._y = s * y + t * this._y; - this._z = s * z + t * this._z; + } - this.normalize(); - this._onChangeCallback(); + roundToZero() { - return this; + this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); + this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); + this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - } + return this; - const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); - const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; + } - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); + negate() { - this._onChangeCallback(); + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; return this; } - slerpQuaternions( qa, qb, t ) { + dot( v ) { - return this.copy( qa ).slerp( qb, t ); + return this.x * v.x + this.y * v.y + this.z * v.z; } - random() { + // TODO lengthSquared? - // Derived from http://planning.cs.uiuc.edu/node198.html - // Note, this source uses w, x, y, z ordering, - // so we swap the order below. + lengthSq() { - const u1 = Math.random(); - const sqrt1u1 = Math.sqrt( 1 - u1 ); - const sqrtu1 = Math.sqrt( u1 ); + return this.x * this.x + this.y * this.y + this.z * this.z; - const u2 = 2 * Math.PI * Math.random(); + } - const u3 = 2 * Math.PI * Math.random(); + length() { - return this.set( - sqrt1u1 * Math.cos( u2 ), - sqrtu1 * Math.sin( u3 ), - sqrtu1 * Math.cos( u3 ), - sqrt1u1 * Math.sin( u2 ), - ); + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); } - equals( quaternion ) { + manhattanLength() { - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); } - fromArray( array, offset = 0 ) { - - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; - - this._onChangeCallback(); + normalize() { - return this; + return this.divideScalar( this.length() || 1 ); } - toArray( array = [], offset = 0 ) { - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; + setLength( length ) { - return array; + return this.normalize().multiplyScalar( length ); } - fromBufferAttribute( attribute, index ) { + lerp( v, alpha ) { - this._x = attribute.getX( index ); - this._y = attribute.getY( index ); - this._z = attribute.getZ( index ); - this._w = attribute.getW( index ); + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; return this; } - _onChange( callback ) { + lerpVectors( v1, v2, alpha ) { - this._onChangeCallback = callback; + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; return this; } - _onChangeCallback() {} - - *[ Symbol.iterator ]() { + cross( v ) { - yield this._x; - yield this._y; - yield this._z; - yield this._w; + return this.crossVectors( this, v ); } -} - -class Vector3 { - - constructor( x = 0, y = 0, z = 0 ) { - - Vector3.prototype.isVector3 = true; - - this.x = x; - this.y = y; - this.z = z; - - } - - set( x, y, z ) { - - if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) - - this.x = x; - this.y = y; - this.z = z; - - return this; - - } - - setScalar( scalar ) { - - this.x = scalar; - this.y = scalar; - this.z = scalar; - - return this; - - } - - setX( x ) { - - this.x = x; - - return this; - - } - - setY( y ) { - - this.y = y; - - return this; - - } - - setZ( z ) { - - this.z = z; - - return this; - - } - - setComponent( index, value ) { - - switch ( index ) { - - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - default: throw new Error( 'index is out of range: ' + index ); - - } - - return this; - - } - - getComponent( index ) { - - switch ( index ) { - - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - default: throw new Error( 'index is out of range: ' + index ); - - } - - } - - clone() { - - return new this.constructor( this.x, this.y, this.z ); - - } - - copy( v ) { - - this.x = v.x; - this.y = v.y; - this.z = v.z; - - return this; - - } - - add( v ) { - - this.x += v.x; - this.y += v.y; - this.z += v.z; - - return this; - - } - - addScalar( s ) { - - this.x += s; - this.y += s; - this.z += s; - - return this; - - } - - addVectors( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - - return this; - - } - - addScaledVector( v, s ) { - - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - - return this; - - } - - sub( v ) { - - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - - return this; - - } - - subScalar( s ) { - - this.x -= s; - this.y -= s; - this.z -= s; - - return this; - - } - - subVectors( a, b ) { - - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - - return this; - - } - - multiply( v ) { - - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - - return this; - - } - - multiplyScalar( scalar ) { - - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - - return this; - - } - - multiplyVectors( a, b ) { - - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; - - return this; - - } - - applyEuler( euler ) { - - return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); - - } - - applyAxisAngle( axis, angle ) { - - return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); - - } - - applyMatrix3( m ) { - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; - this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - - return this; - - } - - applyNormalMatrix( m ) { - - return this.applyMatrix3( m ).normalize(); - - } - - applyMatrix4( m ) { - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - - this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; - this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; - this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; - - return this; - - } - - applyQuaternion( q ) { - - const x = this.x, y = this.y, z = this.z; - const qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vector - - const ix = qw * x + qy * z - qz * y; - const iy = qw * y + qz * x - qx * z; - const iz = qw * z + qx * y - qy * x; - const iw = - qx * x - qy * y - qz * z; - - // calculate result * inverse quat - - this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; - this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; - this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - - return this; - - } - - project( camera ) { - - return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - - } - - unproject( camera ) { - - return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); - - } - - transformDirection( m ) { - - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction - - const x = this.x, y = this.y, z = this.z; - const e = m.elements; - - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - - return this.normalize(); - - } - - divide( v ) { - - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; - - return this; - - } - - divideScalar( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - } - - min( v ) { - - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - - return this; - - } - - max( v ) { - - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - - return this; - - } - - clamp( min, max ) { - - // assumes min < max, componentwise - - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - - return this; - - } - - clampScalar( minVal, maxVal ) { - - this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); - this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); - this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); - - return this; - - } - - clampLength( min, max ) { - - const length = this.length(); - - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - - } - - floor() { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - - return this; - - } - - ceil() { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - - return this; - - } - - round() { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - - return this; - - } - - roundToZero() { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - - return this; - - } - - negate() { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - - return this; - - } - - dot( v ) { - - return this.x * v.x + this.y * v.y + this.z * v.z; - - } - - // TODO lengthSquared? - - lengthSq() { - - return this.x * this.x + this.y * this.y + this.z * this.z; - - } - - length() { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - - } - - manhattanLength() { - - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); - - } - - normalize() { - - return this.divideScalar( this.length() || 1 ); - - } - - setLength( length ) { - - return this.normalize().multiplyScalar( length ); - - } - - lerp( v, alpha ) { - - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - - return this; - - } - - lerpVectors( v1, v2, alpha ) { - - this.x = v1.x + ( v2.x - v1.x ) * alpha; - this.y = v1.y + ( v2.y - v1.y ) * alpha; - this.z = v1.z + ( v2.z - v1.z ) * alpha; - - return this; - - } - - cross( v ) { - - return this.crossVectors( this, v ); - - } - - crossVectors( a, b ) { + crossVectors( a, b ) { const ax = a.x, ay = a.y, az = a.z; const bx = b.x, by = b.y, bz = b.z; @@ -4767,9 +4346,9 @@ class Vector3 { projectOnPlane( planeNormal ) { - _vector$c.copy( this ).projectOnVector( planeNormal ); + _vector$b.copy( this ).projectOnVector( planeNormal ); - return this.sub( _vector$c ); + return this.sub( _vector$b ); } @@ -4778,7 +4357,7 @@ class Vector3 { // reflect incident vector off plane orthogonal to normal // normal is assumed to have unit length - return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + return this.sub( _vector$b.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); } @@ -4898,6 +4477,16 @@ class Vector3 { } + setFromColor( c ) { + + this.x = c.r; + this.y = c.g; + this.z = c.b; + + return this; + + } + equals( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); @@ -4970,7 +4559,7 @@ class Vector3 { } -const _vector$c = /*@__PURE__*/ new Vector3(); +const _vector$b = /*@__PURE__*/ new Vector3(); const _quaternion$4 = /*@__PURE__*/ new Quaternion(); class Box3 { @@ -4995,66 +4584,28 @@ class Box3 { setFromArray( array ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = array.length; i < l; i += 3 ) { - - const x = array[ i ]; - const y = array[ i + 1 ]; - const z = array[ i + 2 ]; + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = array.length; i < il; i += 3 ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector$a.fromArray( array, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } setFromBufferAttribute( attribute ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = attribute.count; i < l; i ++ ) { - - const x = attribute.getX( i ); - const y = attribute.getY( i ); - const z = attribute.getZ( i ); + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = attribute.count; i < il; i ++ ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector$a.fromBufferAttribute( attribute, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } @@ -5075,7 +4626,7 @@ class Box3 { setFromCenterAndSize( center, size ) { - const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); + const halfSize = _vector$a.copy( size ).multiplyScalar( 0.5 ); this.min.copy( center ).sub( halfSize ); this.max.copy( center ).add( halfSize ); @@ -5170,46 +4721,63 @@ class Box3 { object.updateWorldMatrix( false, false ); - const geometry = object.geometry; + if ( object.boundingBox !== undefined ) { - if ( geometry !== undefined ) { + if ( object.boundingBox === null ) { - if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) { + object.computeBoundingBox(); - const position = geometry.attributes.position; - for ( let i = 0, l = position.count; i < l; i ++ ) { + } - _vector$b.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); - this.expandByPoint( _vector$b ); + _box$3.copy( object.boundingBox ); + _box$3.applyMatrix4( object.matrixWorld ); - } + this.union( _box$3 ); - } else { + } else { - if ( geometry.boundingBox === null ) { + const geometry = object.geometry; - geometry.computeBoundingBox(); + if ( geometry !== undefined ) { - } + if ( precise && geometry.attributes !== undefined && geometry.attributes.position !== undefined ) { - _box$3.copy( geometry.boundingBox ); - _box$3.applyMatrix4( object.matrixWorld ); + const position = geometry.attributes.position; + for ( let i = 0, l = position.count; i < l; i ++ ) { - this.union( _box$3 ); + _vector$a.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector$a ); - } + } - } + } else { - const children = object.children; + if ( geometry.boundingBox === null ) { - for ( let i = 0, l = children.length; i < l; i ++ ) { + geometry.computeBoundingBox(); - this.expandByObject( children[ i ], precise ); + } - } + _box$3.copy( geometry.boundingBox ); + _box$3.applyMatrix4( object.matrixWorld ); - return this; + this.union( _box$3 ); + + } + + } + + } + + const children = object.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + this.expandByObject( children[ i ], precise ); + + } + + return this; } @@ -5254,10 +4822,10 @@ class Box3 { intersectsSphere( sphere ) { // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, _vector$b ); + this.clampPoint( sphere.center, _vector$a ); // If that point is inside the sphere, the AABB and sphere intersect. - return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); + return _vector$a.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); } @@ -5369,17 +4937,23 @@ class Box3 { distanceToPoint( point ) { - const clampedPoint = _vector$b.copy( point ).clamp( this.min, this.max ); - - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector$a ).distanceTo( point ); } getBoundingSphere( target ) { - this.getCenter( target.center ); + if ( this.isEmpty() ) { + + target.makeEmpty(); + + } else { - target.radius = this.getSize( _vector$b ).length() * 0.5; + this.getCenter( target.center ); + + target.radius = this.getSize( _vector$a ).length() * 0.5; + + } return target; @@ -5455,7 +5029,7 @@ const _points = [ /*@__PURE__*/ new Vector3() ]; -const _vector$b = /*@__PURE__*/ new Vector3(); +const _vector$a = /*@__PURE__*/ new Vector3(); const _box$3 = /*@__PURE__*/ new Box3(); @@ -5741,7 +5315,7 @@ class Sphere { } -const _vector$a = /*@__PURE__*/ new Vector3(); +const _vector$9 = /*@__PURE__*/ new Vector3(); const _segCenter = /*@__PURE__*/ new Vector3(); const _segDir = /*@__PURE__*/ new Vector3(); const _diff = /*@__PURE__*/ new Vector3(); @@ -5779,7 +5353,7 @@ class Ray { at( t, target ) { - return target.copy( this.direction ).multiplyScalar( t ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, t ); } @@ -5793,7 +5367,7 @@ class Ray { recast( t ) { - this.origin.copy( this.at( t, _vector$a ) ); + this.origin.copy( this.at( t, _vector$9 ) ); return this; @@ -5811,7 +5385,7 @@ class Ray { } - return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); } @@ -5823,7 +5397,7 @@ class Ray { distanceSqToPoint( point ) { - const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); + const directionDistance = _vector$9.subVectors( point, this.origin ).dot( this.direction ); // point behind the ray @@ -5833,9 +5407,9 @@ class Ray { } - _vector$a.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + _vector$9.copy( this.origin ).addScaledVector( this.direction, directionDistance ); - return _vector$a.distanceToSquared( point ); + return _vector$9.distanceToSquared( point ); } @@ -5944,13 +5518,13 @@ class Ray { if ( optionalPointOnRay ) { - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); } if ( optionalPointOnSegment ) { - optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter ); + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); } @@ -5960,9 +5534,9 @@ class Ray { intersectSphere( sphere, target ) { - _vector$a.subVectors( sphere.center, this.origin ); - const tca = _vector$a.dot( this.direction ); - const d2 = _vector$a.dot( _vector$a ) - tca * tca; + _vector$9.subVectors( sphere.center, this.origin ); + const tca = _vector$9.dot( this.direction ); + const d2 = _vector$9.dot( _vector$9 ) - tca * tca; const radius2 = sphere.radius * sphere.radius; if ( d2 > radius2 ) return null; @@ -5975,8 +5549,8 @@ class Ray { // t1 = second intersect point - exit point on back of sphere const t1 = tca + thc; - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; // test to see if t0 is behind the ray: // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, @@ -6129,7 +5703,7 @@ class Ray { intersectsBox( box ) { - return this.intersectBox( box, _vector$a ) !== null; + return this.intersectBox( box, _vector$9 ) !== null; } @@ -6233,7 +5807,7 @@ class Ray { class Matrix4 { - constructor() { + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { Matrix4.prototype.isMatrix4 = true; @@ -6246,6 +5820,12 @@ class Matrix4 { ]; + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); + + } + } set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { @@ -6785,14 +6365,29 @@ class Matrix4 { makeTranslation( x, y, z ) { - this.set( + if ( x.isVector3 ) { - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + this.set( - ); + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 + + ); + + } return this; @@ -7088,7 +6683,7 @@ const _x = /*@__PURE__*/ new Vector3(); const _y = /*@__PURE__*/ new Vector3(); const _z = /*@__PURE__*/ new Vector3(); -const _matrix$1 = /*@__PURE__*/ new Matrix4(); +const _matrix = /*@__PURE__*/ new Matrix4(); const _quaternion$3 = /*@__PURE__*/ new Quaternion(); class Euler { @@ -7323,9 +6918,9 @@ class Euler { setFromQuaternion( q, order, update ) { - _matrix$1.makeRotationFromQuaternion( q ); + _matrix.makeRotationFromQuaternion( q ); - return this.setFromRotationMatrix( _matrix$1, order, update ); + return this.setFromRotationMatrix( _matrix, order, update ); } @@ -8142,7 +7737,7 @@ class Object3D extends EventDispatcher { }; output.metadata = { - version: 4.5, + version: 4.6, type: 'Object', generator: 'Object3D.toJSON' }; @@ -8166,6 +7761,7 @@ class Object3D extends EventDispatcher { object.layers = this.layers.mask; object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; @@ -8393,6 +7989,8 @@ class Object3D extends EventDispatcher { this.frustumCulled = source.frustumCulled; this.renderOrder = source.renderOrder; + this.animations = source.animations; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); if ( recursive === true ) { @@ -8428,6 +8026,8 @@ const _vap = /*@__PURE__*/ new Vector3(); const _vbp = /*@__PURE__*/ new Vector3(); const _vcp = /*@__PURE__*/ new Vector3(); +let warnedGetUV = false; + class Triangle { constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { @@ -8469,740 +8069,1399 @@ class Triangle { const dot11 = _v1$3.dot( _v1$3 ); const dot12 = _v1$3.dot( _v2$2 ); - const denom = ( dot00 * dot11 - dot01 * dot01 ); + const denom = ( dot00 * dot11 - dot01 * dot01 ); + + // collinear or singular triangle + if ( denom === 0 ) { + + // arbitrary location outside of triangle? + // not sure if this is the best idea, maybe should be returning undefined + return target.set( - 2, - 1, - 1 ); + + } + + const invDenom = 1 / denom; + const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + + // barycentric coordinates must always sum to 1 + return target.set( 1 - u - v, v, u ); + + } + + static containsPoint( point, a, b, c ) { + + this.getBarycoord( point, a, b, c, _v3$1 ); + + return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 ); + + } + + static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { // @deprecated, r151 + + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return this.getInterpolation( point, p1, p2, p3, uv1, uv2, uv3, target ); + + } + + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { + + this.getBarycoord( point, p1, p2, p3, _v3$1 ); + + target.setScalar( 0 ); + target.addScaledVector( v1, _v3$1.x ); + target.addScaledVector( v2, _v3$1.y ); + target.addScaledVector( v3, _v3$1.z ); + + return target; + + } + + static isFrontFacing( a, b, c, direction ) { + + _v0$1.subVectors( c, b ); + _v1$3.subVectors( a, b ); + + // strictly front facing + return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; + + } + + set( a, b, c ) { + + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); + + return this; + + } + + setFromPointsAndIndices( points, i0, i1, i2 ) { + + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); + + return this; + + } + + setFromAttributeAndIndices( attribute, i0, i1, i2 ) { + + this.a.fromBufferAttribute( attribute, i0 ); + this.b.fromBufferAttribute( attribute, i1 ); + this.c.fromBufferAttribute( attribute, i2 ); + + return this; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( triangle ) { + + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); + + return this; + + } + + getArea() { + + _v0$1.subVectors( this.c, this.b ); + _v1$3.subVectors( this.a, this.b ); + + return _v0$1.cross( _v1$3 ).length() * 0.5; + + } + + getMidpoint( target ) { + + return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); + + } + + getNormal( target ) { + + return Triangle.getNormal( this.a, this.b, this.c, target ); + + } + + getPlane( target ) { + + return target.setFromCoplanarPoints( this.a, this.b, this.c ); + + } + + getBarycoord( point, target ) { + + return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); + + } + + getUV( point, uv1, uv2, uv3, target ) { // @deprecated, r151 + + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return Triangle.getInterpolation( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + + } + + getInterpolation( point, v1, v2, v3, target ) { + + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); + + } + + containsPoint( point ) { + + return Triangle.containsPoint( point, this.a, this.b, this.c ); + + } + + isFrontFacing( direction ) { + + return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); + + } + + intersectsBox( box ) { + + return box.intersectsTriangle( this ); + + } + + closestPointToPoint( p, target ) { + + const a = this.a, b = this.b, c = this.c; + let v, w; + + // algorithm thanks to Real-Time Collision Detection by Christer Ericson, + // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., + // under the accompanying license; see chapter 5.1.5 for detailed explanation. + // basically, we're distinguishing which of the voronoi regions of the triangle + // the point lies in with the minimum amount of redundant computation. + + _vab.subVectors( b, a ); + _vac.subVectors( c, a ); + _vap.subVectors( p, a ); + const d1 = _vab.dot( _vap ); + const d2 = _vac.dot( _vap ); + if ( d1 <= 0 && d2 <= 0 ) { + + // vertex region of A; barycentric coords (1, 0, 0) + return target.copy( a ); + + } + + _vbp.subVectors( p, b ); + const d3 = _vab.dot( _vbp ); + const d4 = _vac.dot( _vbp ); + if ( d3 >= 0 && d4 <= d3 ) { + + // vertex region of B; barycentric coords (0, 1, 0) + return target.copy( b ); + + } + + const vc = d1 * d4 - d3 * d2; + if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { + + v = d1 / ( d1 - d3 ); + // edge region of AB; barycentric coords (1-v, v, 0) + return target.copy( a ).addScaledVector( _vab, v ); + + } + + _vcp.subVectors( p, c ); + const d5 = _vab.dot( _vcp ); + const d6 = _vac.dot( _vcp ); + if ( d6 >= 0 && d5 <= d6 ) { + + // vertex region of C; barycentric coords (0, 0, 1) + return target.copy( c ); + + } + + const vb = d5 * d2 - d1 * d6; + if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { + + w = d2 / ( d2 - d6 ); + // edge region of AC; barycentric coords (1-w, 0, w) + return target.copy( a ).addScaledVector( _vac, w ); + + } + + const va = d3 * d6 - d5 * d4; + if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { + + _vbc.subVectors( c, b ); + w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); + // edge region of BC; barycentric coords (0, 1-w, w) + return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC + + } + + // face region + const denom = 1 / ( va + vb + vc ); + // u = va * denom + v = vb * denom; + w = vc * denom; + + return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); + + } + + equals( triangle ) { + + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); + + } + +} + +let materialId = 0; + +class Material extends EventDispatcher { + + constructor() { + + super(); + + this.isMaterial = true; + + Object.defineProperty( this, 'id', { value: materialId ++ } ); + + this.uuid = generateUUID(); + + this.name = ''; + this.type = 'Material'; + + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; + + this.opacity = 1; + this.transparent = false; + + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; + + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; + + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; + + this.shadowSide = null; + + this.colorWrite = true; + + this.precision = null; // override the renderer's default precision for this material + + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; + + this.dithering = false; + + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.forceSinglePass = false; + + this.visible = true; + + this.toneMapped = true; + + this.userData = {}; + + this.version = 0; + + this._alphaTest = 0; + + } + + get alphaTest() { + + return this._alphaTest; + + } + + set alphaTest( value ) { + + if ( this._alphaTest > 0 !== value > 0 ) { + + this.version ++; + + } + + this._alphaTest = value; + + } + + onBuild( /* shaderobject, renderer */ ) {} + + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + + onBeforeCompile( /* shaderobject, renderer */ ) {} + + customProgramCacheKey() { + + return this.onBeforeCompile.toString(); + + } + + setValues( values ) { + + if ( values === undefined ) return; + + for ( const key in values ) { + + const newValue = values[ key ]; + + if ( newValue === undefined ) { + + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + continue; + + } + + const currentValue = this[ key ]; + + if ( currentValue === undefined ) { + + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + continue; + + } + + if ( currentValue && currentValue.isColor ) { + + currentValue.set( newValue ); + + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + + currentValue.copy( newValue ); + + } else { + + this[ key ] = newValue; + + } + + } + + } + + toJSON( meta ) { + + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( isRootObject ) { + + meta = { + textures: {}, + images: {} + }; + + } + + const data = { + metadata: { + version: 4.6, + type: 'Material', + generator: 'Material.toJSON' + } + }; + + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; + + if ( this.name !== '' ) data.name = this.name; + + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; + + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + + } + + if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; + if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; + if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; + + if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { + + data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; + + } + + if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { + + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; + + } + + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; + + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { + + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; + + } + + if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; + if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; + if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + + if ( this.lightMap && this.lightMap.isTexture ) { + + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; + + } + + if ( this.aoMap && this.aoMap.isTexture ) { + + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; + + } + + if ( this.bumpMap && this.bumpMap.isTexture ) { + + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; + + } + + if ( this.normalMap && this.normalMap.isTexture ) { + + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); + + } + + if ( this.displacementMap && this.displacementMap.isTexture ) { + + data.displacementMap = this.displacementMap.toJSON( meta ).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; + + } + + if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; + if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + + if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; + if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; + if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; + if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + + if ( this.envMap && this.envMap.isTexture ) { + + data.envMap = this.envMap.toJSON( meta ).uuid; + + if ( this.combine !== undefined ) data.combine = this.combine; + + } + + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + + if ( this.gradientMap && this.gradientMap.isTexture ) { + + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + + } + + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors ) data.vertexColors = true; + + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.transparent === true ) data.transparent = this.transparent; + + data.depthFunc = this.depthFunc; + data.depthTest = this.depthTest; + data.depthWrite = this.depthWrite; + data.colorWrite = this.colorWrite; + + data.stencilWrite = this.stencilWrite; + data.stencilWriteMask = this.stencilWriteMask; + data.stencilFunc = this.stencilFunc; + data.stencilRef = this.stencilRef; + data.stencilFuncMask = this.stencilFuncMask; + data.stencilFail = this.stencilFail; + data.stencilZFail = this.stencilZFail; + data.stencilZPass = this.stencilZPass; + + // rotation (SpriteMaterial) + if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; + + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + + if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; + + if ( this.dithering === true ) data.dithering = true; + + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; + if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass; + + if ( this.wireframe === true ) data.wireframe = this.wireframe; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + + if ( this.flatShading === true ) data.flatShading = this.flatShading; + + if ( this.visible === false ) data.visible = false; + + if ( this.toneMapped === false ) data.toneMapped = false; + + if ( this.fog === false ) data.fog = false; + + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + + // TODO: Copied from Object3D.toJSON + + function extractFromCache( cache ) { + + const values = []; + + for ( const key in cache ) { + + const data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + + return values; - // collinear or singular triangle - if ( denom === 0 ) { + } - // arbitrary location outside of triangle? - // not sure if this is the best idea, maybe should be returning undefined - return target.set( - 2, - 1, - 1 ); + if ( isRootObject ) { + + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; } - const invDenom = 1 / denom; - const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + return data; - // barycentric coordinates must always sum to 1 - return target.set( 1 - u - v, v, u ); + } + + clone() { + + return new this.constructor().copy( this ); } - static containsPoint( point, a, b, c ) { + copy( source ) { - this.getBarycoord( point, a, b, c, _v3$1 ); + this.name = source.name; - return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 ); + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; - } + this.opacity = source.opacity; + this.transparent = source.transparent; - static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; - this.getBarycoord( point, p1, p2, p3, _v3$1 ); + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; - target.set( 0, 0 ); - target.addScaledVector( uv1, _v3$1.x ); - target.addScaledVector( uv2, _v3$1.y ); - target.addScaledVector( uv3, _v3$1.z ); + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; - return target; + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; - } + if ( srcPlanes !== null ) { - static isFrontFacing( a, b, c, direction ) { + const n = srcPlanes.length; + dstPlanes = new Array( n ); - _v0$1.subVectors( c, b ); - _v1$3.subVectors( a, b ); + for ( let i = 0; i !== n; ++ i ) { - // strictly front facing - return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; + dstPlanes[ i ] = srcPlanes[ i ].clone(); - } + } - set( a, b, c ) { + } - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; - return this; + this.shadowSide = source.shadowSide; - } + this.colorWrite = source.colorWrite; - setFromPointsAndIndices( points, i0, i1, i2 ) { + this.precision = source.precision; - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; - return this; + this.dithering = source.dithering; - } + this.alphaTest = source.alphaTest; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.forceSinglePass = source.forceSinglePass; - setFromAttributeAndIndices( attribute, i0, i1, i2 ) { + this.visible = source.visible; - this.a.fromBufferAttribute( attribute, i0 ); - this.b.fromBufferAttribute( attribute, i1 ); - this.c.fromBufferAttribute( attribute, i2 ); + this.toneMapped = source.toneMapped; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); return this; } - clone() { + dispose() { - return new this.constructor().copy( this ); + this.dispatchEvent( { type: 'dispose' } ); } - copy( triangle ) { - - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); + set needsUpdate( value ) { - return this; + if ( value === true ) this.version ++; } - getArea() { - - _v0$1.subVectors( this.c, this.b ); - _v1$3.subVectors( this.a, this.b ); +} - return _v0$1.cross( _v1$3 ).length() * 0.5; +const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, + 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, + 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, + 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, + 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, + 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, + 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, + 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, + 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, + 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, + 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, + 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, + 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, + 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, + 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, + 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, + 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, + 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, + 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, + 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, + 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, + 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, + 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - } +const _hslA = { h: 0, s: 0, l: 0 }; +const _hslB = { h: 0, s: 0, l: 0 }; - getMidpoint( target ) { +function hue2rgb( p, q, t ) { - return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); + if ( t < 0 ) t += 1; + if ( t > 1 ) t -= 1; + if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; + if ( t < 1 / 2 ) return q; + if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); + return p; - } +} - getNormal( target ) { +class Color { - return Triangle.getNormal( this.a, this.b, this.c, target ); + constructor( r, g, b ) { - } + this.isColor = true; - getPlane( target ) { + this.r = 1; + this.g = 1; + this.b = 1; - return target.setFromCoplanarPoints( this.a, this.b, this.c ); + return this.set( r, g, b ); } - getBarycoord( point, target ) { + set( r, g, b ) { - return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); + if ( g === undefined && b === undefined ) { - } + // r is THREE.Color, hex or string - getUV( point, uv1, uv2, uv3, target ) { + const value = r; - return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + if ( value && value.isColor ) { - } + this.copy( value ); - containsPoint( point ) { + } else if ( typeof value === 'number' ) { - return Triangle.containsPoint( point, this.a, this.b, this.c ); + this.setHex( value ); - } + } else if ( typeof value === 'string' ) { - isFrontFacing( direction ) { + this.setStyle( value ); - return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); + } - } + } else { - intersectsBox( box ) { + this.setRGB( r, g, b ); - return box.intersectsTriangle( this ); + } + + return this; } - closestPointToPoint( p, target ) { + setScalar( scalar ) { - const a = this.a, b = this.b, c = this.c; - let v, w; + this.r = scalar; + this.g = scalar; + this.b = scalar; - // algorithm thanks to Real-Time Collision Detection by Christer Ericson, - // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., - // under the accompanying license; see chapter 5.1.5 for detailed explanation. - // basically, we're distinguishing which of the voronoi regions of the triangle - // the point lies in with the minimum amount of redundant computation. + return this; - _vab.subVectors( b, a ); - _vac.subVectors( c, a ); - _vap.subVectors( p, a ); - const d1 = _vab.dot( _vap ); - const d2 = _vac.dot( _vap ); - if ( d1 <= 0 && d2 <= 0 ) { + } - // vertex region of A; barycentric coords (1, 0, 0) - return target.copy( a ); + setHex( hex, colorSpace = SRGBColorSpace ) { - } + hex = Math.floor( hex ); - _vbp.subVectors( p, b ); - const d3 = _vab.dot( _vbp ); - const d4 = _vac.dot( _vbp ); - if ( d3 >= 0 && d4 <= d3 ) { + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; - // vertex region of B; barycentric coords (0, 1, 0) - return target.copy( b ); + ColorManagement.toWorkingColorSpace( this, colorSpace ); - } + return this; - const vc = d1 * d4 - d3 * d2; - if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { + } - v = d1 / ( d1 - d3 ); - // edge region of AB; barycentric coords (1-v, v, 0) - return target.copy( a ).addScaledVector( _vab, v ); + setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { - } + this.r = r; + this.g = g; + this.b = b; - _vcp.subVectors( p, c ); - const d5 = _vab.dot( _vcp ); - const d6 = _vac.dot( _vcp ); - if ( d6 >= 0 && d5 <= d6 ) { + ColorManagement.toWorkingColorSpace( this, colorSpace ); - // vertex region of C; barycentric coords (0, 0, 1) - return target.copy( c ); + return this; - } + } - const vb = d5 * d2 - d1 * d6; - if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { + setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { - w = d2 / ( d2 - d6 ); - // edge region of AC; barycentric coords (1-w, 0, w) - return target.copy( a ).addScaledVector( _vac, w ); + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp( s, 0, 1 ); + l = clamp( l, 0, 1 ); - } + if ( s === 0 ) { - const va = d3 * d6 - d5 * d4; - if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { + this.r = this.g = this.b = l; - _vbc.subVectors( c, b ); - w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); - // edge region of BC; barycentric coords (0, 1-w, w) - return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC + } else { + + const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); + const q = ( 2 * l ) - p; + + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); } - // face region - const denom = 1 / ( va + vb + vc ); - // u = va * denom - v = vb * denom; - w = vc * denom; + ColorManagement.toWorkingColorSpace( this, colorSpace ); - return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); + return this; } - equals( triangle ) { + setStyle( style, colorSpace = SRGBColorSpace ) { - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); + function handleAlpha( string ) { - } + if ( string === undefined ) return; -} + if ( parseFloat( string ) < 1 ) { -let materialId = 0; + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); -class Material extends EventDispatcher { + } - constructor() { + } - super(); - this.isMaterial = true; + let m; - Object.defineProperty( this, 'id', { value: materialId ++ } ); + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { - this.uuid = generateUUID(); + // rgb / hsl - this.name = ''; - this.type = 'Material'; + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; - this.blending = NormalBlending; - this.side = FrontSide; - this.vertexColors = false; + switch ( name ) { - this.opacity = 1; - this.transparent = false; + case 'rgb': + case 'rgba': - this.blendSrc = SrcAlphaFactor; - this.blendDst = OneMinusSrcAlphaFactor; - this.blendEquation = AddEquation; - this.blendSrcAlpha = null; - this.blendDstAlpha = null; - this.blendEquationAlpha = null; + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.depthFunc = LessEqualDepth; - this.depthTest = true; - this.depthWrite = true; + // rgb(255,0,0) rgba(255,0,0,0.5) - this.stencilWriteMask = 0xff; - this.stencilFunc = AlwaysStencilFunc; - this.stencilRef = 0; - this.stencilFuncMask = 0xff; - this.stencilFail = KeepStencilOp; - this.stencilZFail = KeepStencilOp; - this.stencilZPass = KeepStencilOp; - this.stencilWrite = false; + handleAlpha( color[ 4 ] ); - this.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; + return this.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); - this.shadowSide = null; + } - this.colorWrite = true; + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.precision = null; // override the renderer's default precision for this material + // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; + handleAlpha( color[ 4 ] ); - this.dithering = false; + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); - this.alphaToCoverage = false; - this.premultipliedAlpha = false; - this.forceSinglePass = false; + } - this.visible = true; + break; - this.toneMapped = true; + case 'hsl': + case 'hsla': - this.userData = {}; + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { - this.version = 0; + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - this._alphaTest = 0; + handleAlpha( color[ 4 ] ); - } + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); - get alphaTest() { + } - return this._alphaTest; + break; - } + default: - set alphaTest( value ) { + console.warn( 'THREE.Color: Unknown color model ' + style ); - if ( this._alphaTest > 0 !== value > 0 ) { + } - this.version ++; + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { - } + // hex color - this._alphaTest = value; + const hex = m[ 1 ]; + const size = hex.length; - } + if ( size === 3 ) { - onBuild( /* shaderobject, renderer */ ) {} + // #ff0 + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); - onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + } else if ( size === 6 ) { - onBeforeCompile( /* shaderobject, renderer */ ) {} + // #ff0000 + return this.setHex( parseInt( hex, 16 ), colorSpace ); - customProgramCacheKey() { + } else { - return this.onBeforeCompile.toString(); + console.warn( 'THREE.Color: Invalid hex color ' + style ); - } + } - setValues( values ) { + } else if ( style && style.length > 0 ) { - if ( values === undefined ) return; + return this.setColorName( style, colorSpace ); - for ( const key in values ) { + } - const newValue = values[ key ]; + return this; - if ( newValue === undefined ) { + } - console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' ); - continue; + setColorName( style, colorSpace = SRGBColorSpace ) { - } + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; - const currentValue = this[ key ]; + if ( hex !== undefined ) { - if ( currentValue === undefined ) { + // red + this.setHex( hex, colorSpace ); - console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' ); - continue; + } else { - } + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); - if ( currentValue && currentValue.isColor ) { + } - currentValue.set( newValue ); + return this; - } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + } - currentValue.copy( newValue ); + clone() { - } else { + return new this.constructor( this.r, this.g, this.b ); - this[ key ] = newValue; + } - } + copy( color ) { - } + this.r = color.r; + this.g = color.g; + this.b = color.b; + + return this; } - toJSON( meta ) { + copySRGBToLinear( color ) { - const isRootObject = ( meta === undefined || typeof meta === 'string' ); + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); - if ( isRootObject ) { + return this; - meta = { - textures: {}, - images: {} - }; + } - } + copyLinearToSRGB( color ) { - const data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' - } - }; + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); - // standard Material serialization - data.uuid = this.uuid; - data.type = this.type; + return this; - if ( this.name !== '' ) data.name = this.name; + } - if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + convertSRGBToLinear() { - if ( this.roughness !== undefined ) data.roughness = this.roughness; - if ( this.metalness !== undefined ) data.metalness = this.metalness; + this.copySRGBToLinear( this ); - if ( this.sheen !== undefined ) data.sheen = this.sheen; - if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); - if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; - if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); - if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + return this; - if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); - if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; - if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); - if ( this.shininess !== undefined ) data.shininess = this.shininess; - if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; - if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + } - if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + convertLinearToSRGB() { - data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + this.copyLinearToSRGB( this ); - } + return this; - if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + } - data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + getHex( colorSpace = SRGBColorSpace ) { - } + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color.b * 255, 0, 255 ) ); - data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; - data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + } - } + getHexString( colorSpace = SRGBColorSpace ) { - if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; - if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; - if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; + return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); + + } - if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { + getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { - data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; + // h,s,l ranges are in 0.0 - 1.0 - } + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { + const r = _color.r, g = _color.g, b = _color.b; - data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); - } + let hue, saturation; + const lightness = ( min + max ) / 2.0; - if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; - if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; - if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + if ( min === max ) { - if ( this.lightMap && this.lightMap.isTexture ) { + hue = 0; + saturation = 0; - data.lightMap = this.lightMap.toJSON( meta ).uuid; - data.lightMapIntensity = this.lightMapIntensity; + } else { - } + const delta = max - min; - if ( this.aoMap && this.aoMap.isTexture ) { + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - data.aoMap = this.aoMap.toJSON( meta ).uuid; - data.aoMapIntensity = this.aoMapIntensity; + switch ( max ) { - } + case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; + case g: hue = ( b - r ) / delta + 2; break; + case b: hue = ( r - g ) / delta + 4; break; - if ( this.bumpMap && this.bumpMap.isTexture ) { + } - data.bumpMap = this.bumpMap.toJSON( meta ).uuid; - data.bumpScale = this.bumpScale; + hue /= 6; } - if ( this.normalMap && this.normalMap.isTexture ) { + target.h = hue; + target.s = saturation; + target.l = lightness; - data.normalMap = this.normalMap.toJSON( meta ).uuid; - data.normalMapType = this.normalMapType; - data.normalScale = this.normalScale.toArray(); + return target; - } + } - if ( this.displacementMap && this.displacementMap.isTexture ) { + getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { - data.displacementMap = this.displacementMap.toJSON( meta ).uuid; - data.displacementScale = this.displacementScale; - data.displacementBias = this.displacementBias; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - } + target.r = _color.r; + target.g = _color.g; + target.b = _color.b; - if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; - if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + return target; - if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; - if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; - if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; - if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + } - if ( this.envMap && this.envMap.isTexture ) { + getStyle( colorSpace = SRGBColorSpace ) { - data.envMap = this.envMap.toJSON( meta ).uuid; + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - if ( this.combine !== undefined ) data.combine = this.combine; + const r = _color.r, g = _color.g, b = _color.b; + + if ( colorSpace !== SRGBColorSpace ) { + + // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; } - if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; - if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; - if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; - if ( this.gradientMap && this.gradientMap.isTexture ) { + } - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + offsetHSL( h, s, l ) { - } + this.getHSL( _hslA ); - if ( this.transmission !== undefined ) data.transmission = this.transmission; - if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; - if ( this.thickness !== undefined ) data.thickness = this.thickness; - if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; - if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; - if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + _hslA.h += h; _hslA.s += s; _hslA.l += l; - if ( this.size !== undefined ) data.size = this.size; - if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; - if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + this.setHSL( _hslA.h, _hslA.s, _hslA.l ); - if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.side !== FrontSide ) data.side = this.side; - if ( this.vertexColors ) data.vertexColors = true; + return this; - if ( this.opacity < 1 ) data.opacity = this.opacity; - if ( this.transparent === true ) data.transparent = this.transparent; + } - data.depthFunc = this.depthFunc; - data.depthTest = this.depthTest; - data.depthWrite = this.depthWrite; - data.colorWrite = this.colorWrite; + add( color ) { - data.stencilWrite = this.stencilWrite; - data.stencilWriteMask = this.stencilWriteMask; - data.stencilFunc = this.stencilFunc; - data.stencilRef = this.stencilRef; - data.stencilFuncMask = this.stencilFuncMask; - data.stencilFail = this.stencilFail; - data.stencilZFail = this.stencilZFail; - data.stencilZPass = this.stencilZPass; + this.r += color.r; + this.g += color.g; + this.b += color.b; - // rotation (SpriteMaterial) - if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; + return this; - if ( this.polygonOffset === true ) data.polygonOffset = true; - if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; - if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + } - if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; - if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; - if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; - if ( this.scale !== undefined ) data.scale = this.scale; + addColors( color1, color2 ) { - if ( this.dithering === true ) data.dithering = true; + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; - if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; - if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; - if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; - if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass; + return this; - if ( this.wireframe === true ) data.wireframe = this.wireframe; - if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; - if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; - if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + } - if ( this.flatShading === true ) data.flatShading = this.flatShading; + addScalar( s ) { - if ( this.visible === false ) data.visible = false; + this.r += s; + this.g += s; + this.b += s; - if ( this.toneMapped === false ) data.toneMapped = false; + return this; - if ( this.fog === false ) data.fog = false; + } - if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + sub( color ) { - // TODO: Copied from Object3D.toJSON + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); - function extractFromCache( cache ) { + return this; - const values = []; + } - for ( const key in cache ) { + multiply( color ) { - const data = cache[ key ]; - delete data.metadata; - values.push( data ); + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; - } + return this; - return values; + } - } + multiplyScalar( s ) { - if ( isRootObject ) { + this.r *= s; + this.g *= s; + this.b *= s; - const textures = extractFromCache( meta.textures ); - const images = extractFromCache( meta.images ); + return this; - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; + } - } + lerp( color, alpha ) { - return data; + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; + + return this; } - clone() { + lerpColors( color1, color2, alpha ) { - return new this.constructor().copy( this ); + this.r = color1.r + ( color2.r - color1.r ) * alpha; + this.g = color1.g + ( color2.g - color1.g ) * alpha; + this.b = color1.b + ( color2.b - color1.b ) * alpha; + + return this; } - copy( source ) { + lerpHSL( color, alpha ) { - this.name = source.name; + this.getHSL( _hslA ); + color.getHSL( _hslB ); - this.blending = source.blending; - this.side = source.side; - this.vertexColors = source.vertexColors; + const h = lerp( _hslA.h, _hslB.h, alpha ); + const s = lerp( _hslA.s, _hslB.s, alpha ); + const l = lerp( _hslA.l, _hslB.l, alpha ); - this.opacity = source.opacity; - this.transparent = source.transparent; + this.setHSL( h, s, l ); - this.blendSrc = source.blendSrc; - this.blendDst = source.blendDst; - this.blendEquation = source.blendEquation; - this.blendSrcAlpha = source.blendSrcAlpha; - this.blendDstAlpha = source.blendDstAlpha; - this.blendEquationAlpha = source.blendEquationAlpha; + return this; - this.depthFunc = source.depthFunc; - this.depthTest = source.depthTest; - this.depthWrite = source.depthWrite; + } - this.stencilWriteMask = source.stencilWriteMask; - this.stencilFunc = source.stencilFunc; - this.stencilRef = source.stencilRef; - this.stencilFuncMask = source.stencilFuncMask; - this.stencilFail = source.stencilFail; - this.stencilZFail = source.stencilZFail; - this.stencilZPass = source.stencilZPass; - this.stencilWrite = source.stencilWrite; + setFromVector3( v ) { - const srcPlanes = source.clippingPlanes; - let dstPlanes = null; + this.r = v.x; + this.g = v.y; + this.b = v.z; - if ( srcPlanes !== null ) { + return this; - const n = srcPlanes.length; - dstPlanes = new Array( n ); + } - for ( let i = 0; i !== n; ++ i ) { + applyMatrix3( m ) { - dstPlanes[ i ] = srcPlanes[ i ].clone(); + const r = this.r, g = this.g, b = this.b; + const e = m.elements; - } + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; - } + return this; - this.clippingPlanes = dstPlanes; - this.clipIntersection = source.clipIntersection; - this.clipShadows = source.clipShadows; + } - this.shadowSide = source.shadowSide; + equals( c ) { - this.colorWrite = source.colorWrite; + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); - this.precision = source.precision; + } - this.polygonOffset = source.polygonOffset; - this.polygonOffsetFactor = source.polygonOffsetFactor; - this.polygonOffsetUnits = source.polygonOffsetUnits; + fromArray( array, offset = 0 ) { - this.dithering = source.dithering; + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; - this.alphaTest = source.alphaTest; - this.alphaToCoverage = source.alphaToCoverage; - this.premultipliedAlpha = source.premultipliedAlpha; - this.forceSinglePass = source.forceSinglePass; + return this; - this.visible = source.visible; + } - this.toneMapped = source.toneMapped; + toArray( array = [], offset = 0 ) { - this.userData = JSON.parse( JSON.stringify( source.userData ) ); + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); return this; } - dispose() { + toJSON() { - this.dispatchEvent( { type: 'dispose' } ); + return this.getHex(); } - set needsUpdate( value ) { + *[ Symbol.iterator ]() { - if ( value === true ) this.version ++; + yield this.r; + yield this.g; + yield this.b; } } +const _color = /*@__PURE__*/ new Color(); + +Color.NAMES = _colorKeywords; + class MeshBasicMaterial extends Material { constructor( parameters ) { @@ -9279,7 +9538,176 @@ class MeshBasicMaterial extends Material { } -const _vector$9 = /*@__PURE__*/ new Vector3(); +// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + +const _tables = /*@__PURE__*/ _generateTables(); + +function _generateTables() { + + // float32 to float16 helpers + + const buffer = new ArrayBuffer( 4 ); + const floatView = new Float32Array( buffer ); + const uint32View = new Uint32Array( buffer ); + + const baseTable = new Uint32Array( 512 ); + const shiftTable = new Uint32Array( 512 ); + + for ( let i = 0; i < 256; ++ i ) { + + const e = i - 127; + + // very small number (0, -0) + + if ( e < - 27 ) { + + baseTable[ i ] = 0x0000; + baseTable[ i | 0x100 ] = 0x8000; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // small number (denorm) + + } else if ( e < - 14 ) { + + baseTable[ i ] = 0x0400 >> ( - e - 14 ); + baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; + shiftTable[ i ] = - e - 1; + shiftTable[ i | 0x100 ] = - e - 1; + + // normal number + + } else if ( e <= 15 ) { + + baseTable[ i ] = ( e + 15 ) << 10; + baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + // large number (Infinity, -Infinity) + + } else if ( e < 128 ) { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // stay (NaN, Infinity, -Infinity) + + } else { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + } + + } + + // float16 to float32 helpers + + const mantissaTable = new Uint32Array( 2048 ); + const exponentTable = new Uint32Array( 64 ); + const offsetTable = new Uint32Array( 64 ); + + for ( let i = 1; i < 1024; ++ i ) { + + let m = i << 13; // zero pad mantissa bits + let e = 0; // zero exponent + + // normalized + while ( ( m & 0x00800000 ) === 0 ) { + + m <<= 1; + e -= 0x00800000; // decrement exponent + + } + + m &= ~ 0x00800000; // clear leading 1 bit + e += 0x38800000; // adjust bias + + mantissaTable[ i ] = m | e; + + } + + for ( let i = 1024; i < 2048; ++ i ) { + + mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); + + } + + for ( let i = 1; i < 31; ++ i ) { + + exponentTable[ i ] = i << 23; + + } + + exponentTable[ 31 ] = 0x47800000; + exponentTable[ 32 ] = 0x80000000; + + for ( let i = 33; i < 63; ++ i ) { + + exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); + + } + + exponentTable[ 63 ] = 0xc7800000; + + for ( let i = 1; i < 64; ++ i ) { + + if ( i !== 32 ) { + + offsetTable[ i ] = 1024; + + } + + } + + return { + floatView: floatView, + uint32View: uint32View, + baseTable: baseTable, + shiftTable: shiftTable, + mantissaTable: mantissaTable, + exponentTable: exponentTable, + offsetTable: offsetTable + }; + +} + +// float32 to float16 + +function toHalfFloat( val ) { + + if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); + + val = clamp( val, - 65504, 65504 ); + + _tables.floatView[ 0 ] = val; + const f = _tables.uint32View[ 0 ]; + const e = ( f >> 23 ) & 0x1ff; + return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); + +} + +// float16 to float32 + +function fromHalfFloat( val ) { + + const m = val >> 10; + _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; + return _tables.floatView[ 0 ]; + +} + +const DataUtils = { + toHalfFloat: toHalfFloat, + fromHalfFloat: fromHalfFloat, +}; + +const _vector$8 = /*@__PURE__*/ new Vector3(); const _vector2$1 = /*@__PURE__*/ new Vector2(); class BufferAttribute { @@ -9378,10 +9806,10 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); - _vector$9.applyMatrix3( m ); + _vector$8.fromBufferAttribute( this, i ); + _vector$8.applyMatrix3( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9395,11 +9823,11 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.applyMatrix4( m ); + _vector$8.applyMatrix4( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9411,11 +9839,11 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.applyNormalMatrix( m ); + _vector$8.applyNormalMatrix( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9427,11 +9855,11 @@ class BufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$9.fromBufferAttribute( this, i ); + _vector$8.fromBufferAttribute( this, i ); - _vector$9.transformDirection( m ); + _vector$8.transformDirection( m ); - this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); } @@ -9619,27 +10047,25 @@ class BufferAttribute { } - // @deprecated - - copyColorsArray() { + copyColorsArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyColorsArray() was removed in r144.' ); } - copyVector2sArray() { + copyVector2sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector2sArray() was removed in r144.' ); } - copyVector3sArray() { + copyVector3sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector3sArray() was removed in r144.' ); } - copyVector4sArray() { + copyVector4sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector4sArray() was removed in r144.' ); @@ -9655,6 +10081,18 @@ class Int8BufferAttribute extends BufferAttribute { super( new Int8Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9665,6 +10103,18 @@ class Uint8BufferAttribute extends BufferAttribute { super( new Uint8Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9685,6 +10135,18 @@ class Int16BufferAttribute extends BufferAttribute { super( new Int16Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9695,6 +10157,18 @@ class Uint16BufferAttribute extends BufferAttribute { super( new Uint16Array( array ), itemSize, normalized ); + this.gpuType = FloatType; + + } + + copy( source ) { + + super.copy( source ); + + this.gpuType = source.gpuType; + + return this; + } } @@ -9729,6 +10203,146 @@ class Float16BufferAttribute extends BufferAttribute { } + getX( index ) { + + let x = fromHalfFloat( this.array[ index * this.itemSize ] ); + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; + + } + + setX( index, x ) { + + if ( this.normalized ) x = normalize( x, this.array ); + + this.array[ index * this.itemSize ] = toHalfFloat( x ); + + return this; + + } + + getY( index ) { + + let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; + + } + + setY( index, y ) { + + if ( this.normalized ) y = normalize( y, this.array ); + + this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); + + return this; + + } + + getZ( index ) { + + let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; + + } + + setZ( index, z ) { + + if ( this.normalized ) z = normalize( z, this.array ); + + this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); + + return this; + + } + + getW( index ) { + + let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; + + } + + setW( index, w ) { + + if ( this.normalized ) w = normalize( w, this.array ); + + this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); + + return this; + + } + + setXY( index, x, y ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + + return this; + + } + + setXYZ( index, x, y, z ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + + return this; + + } + + setXYZW( index, x, y, z, w ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + this.array[ index + 3 ] = toHalfFloat( w ); + + return this; + + } + } @@ -9759,7 +10373,7 @@ const _obj = /*@__PURE__*/ new Object3D(); const _offset = /*@__PURE__*/ new Vector3(); const _box$1 = /*@__PURE__*/ new Box3(); const _boxMorphTargets = /*@__PURE__*/ new Box3(); -const _vector$8 = /*@__PURE__*/ new Vector3(); +const _vector$7 = /*@__PURE__*/ new Vector3(); class BufferGeometry extends EventDispatcher { @@ -10068,11 +10682,11 @@ class BufferGeometry extends EventDispatcher { if ( this.morphTargetsRelative ) { - _vector$8.addVectors( this.boundingBox.min, _box$1.min ); - this.boundingBox.expandByPoint( _vector$8 ); + _vector$7.addVectors( this.boundingBox.min, _box$1.min ); + this.boundingBox.expandByPoint( _vector$7 ); - _vector$8.addVectors( this.boundingBox.max, _box$1.max ); - this.boundingBox.expandByPoint( _vector$8 ); + _vector$7.addVectors( this.boundingBox.max, _box$1.max ); + this.boundingBox.expandByPoint( _vector$7 ); } else { @@ -10139,11 +10753,11 @@ class BufferGeometry extends EventDispatcher { if ( this.morphTargetsRelative ) { - _vector$8.addVectors( _box$1.min, _boxMorphTargets.min ); - _box$1.expandByPoint( _vector$8 ); + _vector$7.addVectors( _box$1.min, _boxMorphTargets.min ); + _box$1.expandByPoint( _vector$7 ); - _vector$8.addVectors( _box$1.max, _boxMorphTargets.max ); - _box$1.expandByPoint( _vector$8 ); + _vector$7.addVectors( _box$1.max, _boxMorphTargets.max ); + _box$1.expandByPoint( _vector$7 ); } else { @@ -10165,9 +10779,9 @@ class BufferGeometry extends EventDispatcher { for ( let i = 0, il = position.count; i < il; i ++ ) { - _vector$8.fromBufferAttribute( position, i ); + _vector$7.fromBufferAttribute( position, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) ); } @@ -10182,16 +10796,16 @@ class BufferGeometry extends EventDispatcher { for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { - _vector$8.fromBufferAttribute( morphAttribute, j ); + _vector$7.fromBufferAttribute( morphAttribute, j ); if ( morphTargetsRelative ) { _offset.fromBufferAttribute( position, j ); - _vector$8.add( _offset ); + _vector$7.add( _offset ); } - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$7 ) ); } @@ -10468,11 +11082,9 @@ class BufferGeometry extends EventDispatcher { } - // @deprecated since r144 - - merge() { + merge() { // @deprecated, r144 - console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeBufferGeometries() instead.' ); + console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeGeometries() instead.' ); return this; } @@ -10483,11 +11095,11 @@ class BufferGeometry extends EventDispatcher { for ( let i = 0, il = normals.count; i < il; i ++ ) { - _vector$8.fromBufferAttribute( normals, i ); + _vector$7.fromBufferAttribute( normals, i ); - _vector$8.normalize(); + _vector$7.normalize(); - normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); + normals.setXYZ( i, _vector$7.x, _vector$7.y, _vector$7.z ); } @@ -10599,7 +11211,7 @@ class BufferGeometry extends EventDispatcher { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'BufferGeometry', generator: 'BufferGeometry.toJSON' } @@ -10815,10 +11427,6 @@ class BufferGeometry extends EventDispatcher { this.userData = source.userData; - // geometry generator parameters - - if ( source.parameters !== undefined ) this.parameters = Object.assign( {}, source.parameters ); - return this; } @@ -10831,9 +11439,10 @@ class BufferGeometry extends EventDispatcher { } -const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); -const _ray$2 = /*@__PURE__*/ new Ray(); -const _sphere$3 = /*@__PURE__*/ new Sphere(); +const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); +const _ray$3 = /*@__PURE__*/ new Ray(); +const _sphere$5 = /*@__PURE__*/ new Sphere(); +const _sphereHitAt = /*@__PURE__*/ new Vector3(); const _vA$1 = /*@__PURE__*/ new Vector3(); const _vB$1 = /*@__PURE__*/ new Vector3(); @@ -10846,6 +11455,10 @@ const _uvA$1 = /*@__PURE__*/ new Vector2(); const _uvB$1 = /*@__PURE__*/ new Vector2(); const _uvC$1 = /*@__PURE__*/ new Vector2(); +const _normalA = /*@__PURE__*/ new Vector3(); +const _normalB = /*@__PURE__*/ new Vector3(); +const _normalC = /*@__PURE__*/ new Vector3(); + const _intersectionPoint = /*@__PURE__*/ new Vector3(); const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); @@ -10960,12 +11573,6 @@ class Mesh extends Object3D { } - if ( this.isSkinnedMesh ) { - - this.boneTransform( index, target ); - - } - return target; } @@ -10978,34 +11585,56 @@ class Mesh extends Object3D { if ( material === undefined ) return; - // Checking boundingSphere distance to ray + // test with bounding sphere in world space if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - _sphere$3.copy( geometry.boundingSphere ); - _sphere$3.applyMatrix4( matrixWorld ); + _sphere$5.copy( geometry.boundingSphere ); + _sphere$5.applyMatrix4( matrixWorld ); - if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; + // check distance from ray origin to bounding sphere - // + _ray$3.copy( raycaster.ray ).recast( raycaster.near ); - _inverseMatrix$2.copy( matrixWorld ).invert(); - _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); + if ( _sphere$5.containsPoint( _ray$3.origin ) === false ) { + + if ( _ray$3.intersectSphere( _sphere$5, _sphereHitAt ) === null ) return; + + if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; + + } + + // convert ray to local space of mesh - // Check boundingBox before continuing + _inverseMatrix$3.copy( matrixWorld ).invert(); + _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); + + // test with bounding box in local space if ( geometry.boundingBox !== null ) { - if ( _ray$2.intersectsBox( geometry.boundingBox ) === false ) return; + if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; } + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$3 ); + + } + + _computeIntersections( raycaster, intersects, rayLocalSpace ) { + let intersection; + const geometry = this.geometry; + const material = this.material; + const index = geometry.index; const position = geometry.attributes.position; const uv = geometry.attributes.uv; - const uv2 = geometry.attributes.uv2; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; const groups = geometry.groups; const drawRange = geometry.drawRange; @@ -11029,7 +11658,7 @@ class Mesh extends Object3D { const b = index.getX( j + 1 ); const c = index.getX( j + 2 ); - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11054,7 +11683,7 @@ class Mesh extends Object3D { const b = index.getX( i + 1 ); const c = index.getX( i + 2 ); - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11087,7 +11716,7 @@ class Mesh extends Object3D { const b = j + 1; const c = j + 2; - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11112,7 +11741,7 @@ class Mesh extends Object3D { const b = i + 1; const c = i + 2; - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -11162,7 +11791,7 @@ function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point } -function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, uv2, a, b, c ) { +function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { object.getVertexPosition( a, _vA$1 ); object.getVertexPosition( b, _vB$1 ); @@ -11178,17 +11807,34 @@ function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, _uvB$1.fromBufferAttribute( uv, b ); _uvC$1.fromBufferAttribute( uv, c ); - intersection.uv = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); } - if ( uv2 ) { + if ( uv1 ) { - _uvA$1.fromBufferAttribute( uv2, a ); - _uvB$1.fromBufferAttribute( uv2, b ); - _uvC$1.fromBufferAttribute( uv2, c ); + _uvA$1.fromBufferAttribute( uv1, a ); + _uvB$1.fromBufferAttribute( uv1, b ); + _uvC$1.fromBufferAttribute( uv1, c ); - intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv2 = intersection.uv1; // @deprecated, r152 + + } + + if ( normal ) { + + _normalA.fromBufferAttribute( normal, a ); + _normalB.fromBufferAttribute( normal, b ); + _normalC.fromBufferAttribute( normal, c ); + + intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); + + if ( intersection.normal.dot( ray.direction ) > 0 ) { + + intersection.normal.multiplyScalar( - 1 ); + + } } @@ -11367,6 +12013,16 @@ class BoxGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); @@ -11396,7 +12052,16 @@ function cloneUniforms( src ) { property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion ) ) { - dst[ u ][ p ] = property.clone(); + if ( property.isRenderTargetTexture ) { + + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; + + } else { + + dst[ u ][ p ] = property.clone(); + + } } else if ( Array.isArray( property ) ) { @@ -11455,7 +12120,7 @@ function getUnlitUniformColorSpace( renderer ) { if ( renderer.getRenderTarget() === null ) { // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 - return renderer.outputEncoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; + return renderer.outputColorSpace; } @@ -11497,6 +12162,8 @@ class ShaderMaterial extends Material { this.lights = false; // set to use scene lights this.clipping = false; // set to use user-defined clipping planes + this.forceSinglePass = true; + this.extensions = { derivatives: false, // set to use derivatives fragDepth: false, // set to use fragment depth values @@ -11509,7 +12176,7 @@ class ShaderMaterial extends Material { this.defaultAttributeValues = { 'color': [ 1, 1, 1 ], 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] + 'uv1': [ 0, 0 ] }; this.index0AttributeName = undefined; @@ -11630,6 +12297,9 @@ class ShaderMaterial extends Material { data.vertexShader = this.vertexShader; data.fragmentShader = this.fragmentShader; + data.lights = this.lights; + data.clipping = this.clipping; + const extensions = {}; for ( const key in this.extensions ) { @@ -12043,12 +12713,12 @@ class CubeCamera extends Object3D { class CubeTexture extends Texture { - constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { images = images !== undefined ? images : []; mapping = mapping !== undefined ? mapping : CubeReflectionMapping; - super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCubeTexture = true; @@ -12081,7 +12751,15 @@ class WebGLCubeRenderTarget extends WebGLRenderTarget { const image = { width: size, height: size, depth: 1 }; const images = [ image, image, image, image, image, image ]; - this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( options.encoding !== undefined ) { + + // @deprecated, r152 + warnOnce( 'THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; + + } + + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, @@ -12101,7 +12779,7 @@ class WebGLCubeRenderTarget extends WebGLRenderTarget { fromEquirectangularTexture( renderer, texture ) { this.texture.type = texture.type; - this.texture.encoding = texture.encoding; + this.texture.colorSpace = texture.colorSpace; this.texture.generateMipmaps = texture.generateMipmaps; this.texture.minFilter = texture.minFilter; @@ -12306,7 +12984,7 @@ class Plane { projectPoint( point, target ) { - return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); } @@ -12338,7 +13016,7 @@ class Plane { } - return target.copy( direction ).multiplyScalar( t ).add( line.start ); + return target.copy( line.start ).addScaledVector( direction, t ); } @@ -12407,8 +13085,8 @@ class Plane { } -const _sphere$2 = /*@__PURE__*/ new Sphere(); -const _vector$7 = /*@__PURE__*/ new Vector3(); +const _sphere$4 = /*@__PURE__*/ new Sphere(); +const _vector$6 = /*@__PURE__*/ new Vector3(); class Frustum { @@ -12469,23 +13147,33 @@ class Frustum { intersectsObject( object ) { - const geometry = object.geometry; + if ( object.boundingSphere !== undefined ) { - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + + _sphere$4.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } else { + + const geometry = object.geometry; - _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - return this.intersectsSphere( _sphere$2 ); + _sphere$4.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } + + return this.intersectsSphere( _sphere$4 ); } intersectsSprite( sprite ) { - _sphere$2.center.set( 0, 0, 0 ); - _sphere$2.radius = 0.7071067811865476; - _sphere$2.applyMatrix4( sprite.matrixWorld ); + _sphere$4.center.set( 0, 0, 0 ); + _sphere$4.radius = 0.7071067811865476; + _sphere$4.applyMatrix4( sprite.matrixWorld ); - return this.intersectsSphere( _sphere$2 ); + return this.intersectsSphere( _sphere$4 ); } @@ -12521,11 +13209,11 @@ class Frustum { // corner at max distance - _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; - _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; - _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; + _vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x; + _vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y; + _vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z; - if ( plane.distanceToPoint( _vector$7 ) < 0 ) { + if ( plane.distanceToPoint( _vector$6 ) < 0 ) { return false; @@ -12637,7 +13325,7 @@ function WebGLAttributes( gl, capabilities ) { if ( array instanceof Float32Array ) { - type = 5126; + type = gl.FLOAT; } else if ( array instanceof Uint16Array ) { @@ -12645,7 +13333,7 @@ function WebGLAttributes( gl, capabilities ) { if ( isWebGL2 ) { - type = 5131; + type = gl.HALF_FLOAT; } else { @@ -12655,33 +13343,33 @@ function WebGLAttributes( gl, capabilities ) { } else { - type = 5123; + type = gl.UNSIGNED_SHORT; } } else if ( array instanceof Int16Array ) { - type = 5122; + type = gl.SHORT; } else if ( array instanceof Uint32Array ) { - type = 5125; + type = gl.UNSIGNED_INT; } else if ( array instanceof Int32Array ) { - type = 5124; + type = gl.INT; } else if ( array instanceof Int8Array ) { - type = 5120; + type = gl.BYTE; } else if ( array instanceof Uint8Array ) { - type = 5121; + type = gl.UNSIGNED_BYTE; } else if ( array instanceof Uint8ClampedArray ) { - type = 5121; + type = gl.UNSIGNED_BYTE; } else { @@ -12884,6 +13572,16 @@ class PlaneGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); @@ -12892,7 +13590,7 @@ class PlaneGeometry extends BufferGeometry { } -var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif"; +var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; @@ -12900,7 +13598,7 @@ var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTes var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; -var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; +var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; @@ -12908,11 +13606,11 @@ var begin_vertex = "vec3 transformed = vec3( position );"; var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; -var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\n\tvec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif"; +var bsdfs = "float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated"; var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif"; -var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; +var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif"; @@ -12930,7 +13628,7 @@ var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\ var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif"; -var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}"; +var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated"; var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; @@ -12938,9 +13636,9 @@ var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_I var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; -var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif"; +var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; -var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; +var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; @@ -12968,7 +13666,7 @@ var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying flo var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}"; -var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; +var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; @@ -12976,9 +13674,9 @@ var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert"; -var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; +var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; -var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, worldNormal );\n\t\t\t#endif\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\t#else\n\t\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec );\n\t\t\t#endif\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif"; +var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; @@ -12988,13 +13686,13 @@ var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; -var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; +var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tanisotropyV /= material.anisotropy;\n\tmaterial.anisotropy = saturate( material.anisotropy );\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x - tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x + tbn[ 0 ] * anisotropyV.y;\n#endif"; -var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; +var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; -var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && ( defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE ) )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; +var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometry.viewDir, geometry.normal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; @@ -13006,15 +13704,15 @@ var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_ var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif"; -var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; +var map_fragment = "#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, vMapUv );\n#endif"; var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; -var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; +var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; -var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; +var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; -var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; +var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; @@ -13026,9 +13724,9 @@ var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTar var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif"; -var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;"; +var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal, vNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 geometryNormal = normal;"; -var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; +var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; @@ -13036,19 +13734,19 @@ var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif"; -var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif"; +var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif"; var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif"; -var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif"; +var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif"; -var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif"; +var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif"; var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; -var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; +var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; -var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}"; +var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; @@ -13058,13 +13756,13 @@ var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_F var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif"; -var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; +var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; -var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; +var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; -var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; +var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; @@ -13078,35 +13776,29 @@ var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif"; -var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; +var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; -var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; - -var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif"; - -var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; +var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; -var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif"; +var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; -var uv_pars_vertex = "#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif"; +var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; -var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; +var uv_pars_fragment = "#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; -var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; +var uv_pars_vertex = "#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; -var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif"; - -var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif"; +var uv_vertex = "#ifdef USE_UV\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif"; var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; -const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; +const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}"; const vertex$g = "varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}"; @@ -13128,45 +13820,45 @@ const vertex$c = "varying vec3 vWorldDirection;\n#include \nvoid main() const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}"; -const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$a = "#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}"; const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; +const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; -const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; +const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; -const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; +const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; -const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; +const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}"; -const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$3 = "uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}"; const fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const vertex$2 = "#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; +const vertex$2 = "#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}"; -const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; +const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"; @@ -13275,9 +13967,6 @@ const ShaderChunk = { uv_pars_fragment: uv_pars_fragment, uv_pars_vertex: uv_pars_vertex, uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, worldpos_vertex: worldpos_vertex, background_vert: vertex$h, @@ -13328,10 +14017,11 @@ const UniformsLib = { opacity: { value: 1.0 }, map: { value: null }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() }, - uv2Transform: { value: /*@__PURE__*/ new Matrix3() }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } }, @@ -13339,6 +14029,7 @@ const UniformsLib = { specularmap: { specularMap: { value: null }, + specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -13355,26 +14046,23 @@ const UniformsLib = { aomap: { aoMap: { value: null }, - aoMapIntensity: { value: 1 } + aoMapIntensity: { value: 1 }, + aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, lightmap: { lightMap: { value: null }, - lightMapIntensity: { value: 1 } - - }, - - emissivemap: { - - emissiveMap: { value: null } + lightMapIntensity: { value: 1 }, + lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, bumpmap: { bumpMap: { value: null }, + bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, bumpScale: { value: 1 } }, @@ -13382,6 +14070,7 @@ const UniformsLib = { normalmap: { normalMap: { value: null }, + normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } }, @@ -13389,20 +14078,30 @@ const UniformsLib = { displacementmap: { displacementMap: { value: null }, + displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, displacementScale: { value: 1 }, displacementBias: { value: 0 } }, - roughnessmap: { + emissivemap: { - roughnessMap: { value: null } + emissiveMap: { value: null }, + emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, metalnessmap: { - metalnessMap: { value: null } + metalnessMap: { value: null }, + metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } + + }, + + roughnessmap: { + + roughnessMap: { value: null }, + roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -13509,6 +14208,7 @@ const UniformsLib = { scale: { value: 1.0 }, map: { value: null }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaTest: { value: 0 }, uvTransform: { value: /*@__PURE__*/ new Matrix3() } @@ -13521,9 +14221,10 @@ const UniformsLib = { center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, rotation: { value: 0.0 }, map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, - alphaTest: { value: 0 }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() } + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } } @@ -13829,33 +14530,47 @@ ShaderLib.physical = { { clearcoat: { value: 0 }, clearcoatMap: { value: null }, + clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalMap: { value: null }, + clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, clearcoatRoughness: { value: 0 }, clearcoatRoughnessMap: { value: null }, - clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, - clearcoatNormalMap: { value: null }, + clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescence: { value: 0 }, iridescenceMap: { value: null }, + iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescenceIOR: { value: 1.3 }, iridescenceThicknessMinimum: { value: 100 }, iridescenceThicknessMaximum: { value: 400 }, iridescenceThicknessMap: { value: null }, + iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheen: { value: 0 }, sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, sheenColorMap: { value: null }, + sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheenRoughness: { value: 1 }, sheenRoughnessMap: { value: null }, + sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmission: { value: 0 }, transmissionMap: { value: null }, + transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, transmissionSamplerMap: { value: null }, thickness: { value: 0 }, thicknessMap: { value: null }, + thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, attenuationDistance: { value: 0 }, attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, - specularIntensity: { value: 1 }, - specularIntensityMap: { value: null }, specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, specularColorMap: { value: null }, + specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, + anisotropyMap: { value: null }, + anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, } ] ), @@ -13890,26 +14605,35 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, } - // Ignore background in AR - // TODO: Reconsider this. + if ( background === null ) { - const xr = renderer.xr; - const session = xr.getSession && xr.getSession(); + setClear( clearColor, clearAlpha ); - if ( session && session.environmentBlendMode === 'additive' ) { + } else if ( background && background.isColor ) { - background = null; + setClear( background, 1 ); + forceClear = true; } - if ( background === null ) { + const xr = renderer.xr; + const environmentBlendMode = xr.getEnvironmentBlendMode(); - setClear( clearColor, clearAlpha ); + switch ( environmentBlendMode ) { - } else if ( background && background.isColor ) { + case 'opaque': + forceClear = true; + break; - setClear( background, 1 ); - forceClear = true; + case 'additive': + state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); + forceClear = true; + break; + + case 'alpha-blend': + state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); + forceClear = true; + break; } @@ -13965,7 +14689,7 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - boxMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + boxMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( currentBackground !== background || currentBackgroundVersion !== background.version || @@ -14021,7 +14745,7 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, planeMesh.material.uniforms.t2D.value = background; planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - planeMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + planeMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( background.matrixAutoUpdate === true ) { @@ -14093,7 +14817,7 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, function WebGLBindingStates( gl, extensions, attributes, capabilities ) { - const maxVertexAttributes = gl.getParameter( 34921 ); + const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' ); const vaoAvailable = capabilities.isWebGL2 || extension !== null; @@ -14143,7 +14867,7 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { if ( index !== null ) { - attributes.update( index, 34963 ); + attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); } @@ -14155,7 +14879,7 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { if ( index !== null ) { - gl.bindBuffer( 34963, attributes.get( index ).buffer ); + gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); } @@ -14408,9 +15132,9 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { } - function vertexAttribPointer( index, size, type, normalized, stride, offset ) { + function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { - if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) { + if ( integer === true ) { gl.vertexAttribIPointer( index, size, type, stride, offset ); @@ -14468,6 +15192,10 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { const type = attribute.type; const bytesPerElement = attribute.bytesPerElement; + // check for integer attributes (WebGL 2 only) + + const integer = ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ) ); + if ( geometryAttribute.isInterleavedBufferAttribute ) { const data = geometryAttribute.data; @@ -14498,7 +15226,7 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { } - gl.bindBuffer( 34962, buffer ); + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); for ( let i = 0; i < programAttribute.locationSize; i ++ ) { @@ -14508,7 +15236,8 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { type, normalized, stride * bytesPerElement, - ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement + ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, + integer ); } @@ -14539,7 +15268,7 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { } - gl.bindBuffer( 34962, buffer ); + gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); for ( let i = 0; i < programAttribute.locationSize; i ++ ) { @@ -14549,7 +15278,8 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { type, normalized, size * bytesPerElement, - ( size / programAttribute.locationSize ) * i * bytesPerElement + ( size / programAttribute.locationSize ) * i * bytesPerElement, + integer ); } @@ -14799,8 +15529,8 @@ function WebGLCapabilities( gl, extensions, parameters ) { if ( precision === 'highp' ) { - if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 && - gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) { + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { return 'highp'; @@ -14812,8 +15542,8 @@ function WebGLCapabilities( gl, extensions, parameters ) { if ( precision === 'mediump' ) { - if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 && - gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) { + if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && + gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { return 'mediump'; @@ -14825,7 +15555,7 @@ function WebGLCapabilities( gl, extensions, parameters ) { } - const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; + const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl.constructor.name === 'WebGL2RenderingContext'; let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; const maxPrecision = getMaxPrecision( precision ); @@ -14841,21 +15571,21 @@ function WebGLCapabilities( gl, extensions, parameters ) { const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; - const maxTextures = gl.getParameter( 34930 ); - const maxVertexTextures = gl.getParameter( 35660 ); - const maxTextureSize = gl.getParameter( 3379 ); - const maxCubemapSize = gl.getParameter( 34076 ); + const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); + const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); + const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); + const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); - const maxAttributes = gl.getParameter( 34921 ); - const maxVertexUniforms = gl.getParameter( 36347 ); - const maxVaryings = gl.getParameter( 36348 ); - const maxFragmentUniforms = gl.getParameter( 36349 ); + const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); + const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); + const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); + const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); const vertexTextures = maxVertexTextures > 0; const floatFragmentTextures = isWebGL2 || extensions.has( 'OES_texture_float' ); const floatVertexTextures = vertexTextures && floatFragmentTextures; - const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0; + const maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0; return { @@ -15360,23 +16090,13 @@ class PMREMGenerator { * and far planes ensure the scene is rendered in its entirety (the cubeCamera * is placed at the origin). */ - fromScene( scene, sigma = 0, near = 0.1, far = 100, cubeUVRenderTarget = null, pingPongRenderTarget = null ) { + fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { _oldTarget = this._renderer.getRenderTarget(); - if ( ! cubeUVRenderTarget ) { - - cubeUVRenderTarget = this._allocateTargets(); - - } - - if ( pingPongRenderTarget ) { - - this._pingPongRenderTarget = pingPongRenderTarget; - - } this._setSize( 256 ); + const cubeUVRenderTarget = this._allocateTargets(); cubeUVRenderTarget.depthBuffer = true; this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); @@ -15394,42 +16114,6 @@ class PMREMGenerator { } - prepareForRenderTarget ( cubeUVRenderTarget, pingPongRenderTarget = null, cubeSize = 256 ) { - this._setSize( cubeSize ); - const { _lodMax } = this; - ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); - const width = 3 * Math.max( this._cubeSize, 16 * 7 ); - const height = 4 * this._cubeSize; - this._blurMaterial = _getBlurShader( _lodMax, width, height ); - cubeUVRenderTarget.setSize( width, height ); - if (pingPongRenderTarget) { - pingPongRenderTarget.setSize( width, height); - } - } - - fromSceneToRenderTarget( scene, cubeUVRenderTarget, pingPongRenderTarget, sigma = 0, near = 0.1, far = 100 ) { - - _oldTarget = this._renderer.getRenderTarget(); - - this._pingPongRenderTarget = pingPongRenderTarget; - - this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); - if ( sigma > 0 ) { - - this._blur( cubeUVRenderTarget, 0, 0, sigma ); - - } - - this._applyPMREM( cubeUVRenderTarget ); - - this._renderer.setRenderTarget( _oldTarget ); - cubeUVRenderTarget.scissorTest = false; - _setViewport( cubeUVRenderTarget, 0, 0, cubeUVRenderTarget.width, cubeUVRenderTarget.height ); - - return cubeUVRenderTarget; - - } - /** * Generates a PMREM from an equirectangular texture, which can be either LDR * or HDR. The ideal input image size is 1k (1024 x 512), @@ -15561,7 +16245,7 @@ class PMREMGenerator { generateMipmaps: false, type: HalfFloatType, format: RGBAFormat, - encoding: LinearEncoding, + colorSpace: LinearSRGBColorSpace, depthBuffer: false }; @@ -16153,16 +16837,6 @@ function _getCommonVertexShader() { varying vec3 vOutputDirection; - mat3 getRotationMatrix(vec3 axis, float angle) { - axis = normalize(axis); - float s = sin(angle); - float c = cos(angle); - float oc = 1.0 - c; - - return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, - oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); - } // RH coordinate system; PMREM face-indexing convention vec3 getDirection( vec2 uv, float face ) { @@ -16198,8 +16872,7 @@ function _getCommonVertexShader() { direction.z *= -1.0; // ( u, v, -1 ) neg z } - mat3 rotationMatrix = getRotationMatrix(vec3(1.0, 0.0, 0.0), 1.57); - direction = rotationMatrix * direction; + return direction; } @@ -16455,6 +17128,18 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { } + for ( const name in geometry.morphAttributes ) { + + const array = geometry.morphAttributes[ name ]; + + for ( let i = 0, l = array.length; i < l; i ++ ) { + + attributes.remove( array[ i ] ); + + } + + } + geometry.removeEventListener( 'dispose', onGeometryDispose ); delete geometries[ geometry.id ]; @@ -16504,7 +17189,7 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { for ( const name in geometryAttributes ) { - attributes.update( geometryAttributes[ name ], 34962 ); + attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); } @@ -16518,7 +17203,7 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { for ( let i = 0, l = array.length; i < l; i ++ ) { - attributes.update( array[ i ], 34962 ); + attributes.update( array[ i ], gl.ARRAY_BUFFER ); } @@ -16714,23 +17399,23 @@ function WebGLInfo( gl ) { switch ( mode ) { - case 4: + case gl.TRIANGLES: render.triangles += instanceCount * ( count / 3 ); break; - case 1: + case gl.LINES: render.lines += instanceCount * ( count / 2 ); break; - case 3: + case gl.LINE_STRIP: render.lines += instanceCount * ( count - 1 ); break; - case 2: + case gl.LINE_LOOP: render.lines += instanceCount * count; break; - case 0: + case gl.POINTS: render.points += instanceCount * count; break; @@ -16744,7 +17429,6 @@ function WebGLInfo( gl ) { function reset() { - render.frame ++; render.calls = 0; render.triangles = 0; render.points = 0; @@ -16790,7 +17474,7 @@ function WebGLMorphtargets( gl, capabilities, textures ) { } - function update( object, geometry, material, program ) { + function update( object, geometry, program ) { const objectInfluences = object.morphTargetInfluences; @@ -17085,11 +17769,11 @@ function WebGLObjects( gl, geometries, attributes, info ) { } - attributes.update( object.instanceMatrix, 34962 ); + attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER ); if ( object.instanceColor !== null ) { - attributes.update( object.instanceColor, 34962 ); + attributes.update( object.instanceColor, gl.ARRAY_BUFFER ); } @@ -17169,6 +17853,7 @@ function WebGLObjects( gl, geometries, attributes, info ) { * */ + const emptyTexture = /*@__PURE__*/ new Texture(); const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); @@ -18202,7 +18887,7 @@ class WebGLUniforms { this.seq = []; this.map = {}; - const n = gl.getProgramParameter( program, 35718 ); + const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); for ( let i = 0; i < n; ++ i ) { @@ -18298,16 +18983,16 @@ function handleSource( string, errorLine ) { } -function getEncodingComponents( encoding ) { +function getEncodingComponents( colorSpace ) { - switch ( encoding ) { + switch ( colorSpace ) { - case LinearEncoding: + case LinearSRGBColorSpace: return [ 'Linear', '( value )' ]; - case sRGBEncoding: + case SRGBColorSpace: return [ 'sRGB', '( value )' ]; default: - console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding ); + console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); return [ 'Linear', '( value )' ]; } @@ -18316,7 +19001,7 @@ function getEncodingComponents( encoding ) { function getShaderErrors( gl, shader, type ) { - const status = gl.getShaderParameter( shader, 35713 ); + const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); const errors = gl.getShaderInfoLog( shader ).trim(); if ( status && errors === '' ) return ''; @@ -18338,9 +19023,9 @@ function getShaderErrors( gl, shader, type ) { } -function getTexelEncodingFunction( functionName, encoding ) { +function getTexelEncodingFunction( functionName, colorSpace ) { - const components = getEncodingComponents( encoding ); + const components = getEncodingComponents( colorSpace ); return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; } @@ -18384,7 +19069,7 @@ function getToneMappingFunction( functionName, toneMapping ) { function generateExtensions( parameters ) { const chunks = [ - ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', + ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.normalMapTangentSpace || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '', ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '', ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : '' @@ -18416,7 +19101,7 @@ function fetchAttributeLocations( gl, program ) { const attributes = {}; - const n = gl.getProgramParameter( program, 35721 ); + const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); for ( let i = 0; i < n; i ++ ) { @@ -18424,9 +19109,9 @@ function fetchAttributeLocations( gl, program ) { const name = info.name; let locationSize = 1; - if ( info.type === 35674 ) locationSize = 2; - if ( info.type === 35675 ) locationSize = 3; - if ( info.type === 35676 ) locationSize = 4; + if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2; + if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3; + if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4; // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); @@ -18692,6 +19377,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { prefixVertex = [ + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -18705,6 +19393,10 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { prefixFragment = [ customExtensions, + + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -18721,6 +19413,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, @@ -18728,21 +19421,22 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', - - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', @@ -18751,11 +19445,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -18765,14 +19457,52 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', + + // + + parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', + parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', + parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', + parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', + parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', + parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', + parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', + parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', + + parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', + parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', + + parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', + + parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', + parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', + parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', + + parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', + parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', + + parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', + parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', + + parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', + parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', + parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', + + parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', + parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', + + // parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', @@ -18792,6 +19522,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -18819,6 +19551,24 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { 'attribute vec3 normal;', 'attribute vec2 uv;', + '#ifdef USE_UV1', + + ' attribute vec2 uv1;', + + '#endif', + + '#ifdef USE_UV2', + + ' attribute vec2 uv2;', + + '#endif', + + '#ifdef USE_UV3', + + ' attribute vec2 uv3;', + + '#endif', + '#ifdef USE_TANGENT', ' attribute vec4 tangent;', @@ -18870,18 +19620,20 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { '\n' ].filter( filterEmptyLine ).join( '\n' ); + prefixFragment = [ customExtensions, generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', @@ -18894,11 +19646,14 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', @@ -18910,8 +19665,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -18919,20 +19675,21 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', - parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', @@ -18946,7 +19703,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', - parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -18963,7 +19720,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.opaque ? '#define OPAQUE' : '', ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below - getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ), + getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', @@ -18973,14 +19730,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { } - if ( renderer.onShaderBeforeResolve ) { - - const ret = renderer.onShaderBeforeResolve( vertexShader, fragmentShader, parameters ); - vertexShader = ret.vertexShader; - fragmentShader = ret.fragmentShader; - - } - vertexShader = resolveIncludes( vertexShader ); vertexShader = replaceLightNums( vertexShader, parameters ); vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); @@ -19023,21 +19772,14 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { } - let vertexGlsl = versionString + prefixVertex + vertexShader; - let fragmentGlsl = versionString + prefixFragment + fragmentShader; - - if ( renderer.onShaderBeforeCompile ) { + const vertexGlsl = versionString + prefixVertex + vertexShader; + const fragmentGlsl = versionString + prefixFragment + fragmentShader; - const ret = renderer.onShaderBeforeCompile( vertexGlsl, fragmentGlsl, parameters ); - vertexGlsl = ret.vertexShader; - fragmentGlsl = ret.fragmentShader; - - } // console.log( '*VERTEX*', vertexGlsl ); // console.log( '*FRAGMENT*', fragmentGlsl ); - const glVertexShader = WebGLShader( gl, 35633, vertexGlsl ); - const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl ); + const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); + const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); gl.attachShader( program, glVertexShader ); gl.attachShader( program, glFragmentShader ); @@ -19067,20 +19809,30 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { let runnable = true; let haveDiagnostics = true; - if ( gl.getProgramParameter( program, 35714 ) === false ) { + if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { runnable = false; - const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); - const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + if ( typeof renderer.debug.onShaderError === 'function' ) { - console.error( - 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + - 'VALIDATE_STATUS ' + gl.getProgramParameter( program, 35715 ) + '\n\n' + - 'Program Info Log: ' + programLog + '\n' + - vertexErrors + '\n' + - fragmentErrors - ); + renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); + + } else { + + // default error reporting + + const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); + + } } else if ( programLog !== '' ) { @@ -19174,6 +19926,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { // + this.type = parameters.shaderType; this.name = parameters.shaderName; this.id = programIdCount ++; this.cacheKey = cacheKey; @@ -19315,9 +20068,10 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const _customShaders = new WebGLShaderCache(); const programs = []; - const isWebGL2 = capabilities.isWebGL2; + const IS_WEBGL2 = capabilities.isWebGL2; const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; - const vertexTextures = capabilities.vertexTextures; + const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; + let precision = capabilities.precision; const shaderIDs = { @@ -19338,6 +20092,14 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities SpriteMaterial: 'sprite' }; + function getChannel( value ) { + + if ( value === 0 ) return 'uv'; + + return `uv${ value }`; + + } + function getParameters( material, lights, shadows, scene, object ) { const fog = scene.fog; @@ -19401,16 +20163,65 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const currentRenderTarget = renderer.getRenderTarget(); - const useAlphaTest = material.alphaTest > 0; - const useClearcoat = material.clearcoat > 0; - const useIridescence = material.iridescence > 0; + const IS_INSTANCEDMESH = object.isInstancedMesh === true; + + const HAS_MAP = !! material.map; + const HAS_MATCAP = !! material.matcap; + const HAS_ENVMAP = !! envMap; + const HAS_AOMAP = !! material.aoMap; + const HAS_LIGHTMAP = !! material.lightMap; + const HAS_BUMPMAP = !! material.bumpMap; + const HAS_NORMALMAP = !! material.normalMap; + const HAS_DISPLACEMENTMAP = !! material.displacementMap; + const HAS_EMISSIVEMAP = !! material.emissiveMap; + + const HAS_METALNESSMAP = !! material.metalnessMap; + const HAS_ROUGHNESSMAP = !! material.roughnessMap; + + const HAS_ANISOTROPY = material.anisotropy > 0; + const HAS_CLEARCOAT = material.clearcoat > 0; + const HAS_IRIDESCENCE = material.iridescence > 0; + const HAS_SHEEN = material.sheen > 0; + const HAS_TRANSMISSION = material.transmission > 0; + + const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; + + const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; + const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; + const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; + + const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; + const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; + + const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; + const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; + + const HAS_SPECULARMAP = !! material.specularMap; + const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; + const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; + + const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; + const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; + + const HAS_GRADIENTMAP = !! material.gradientMap; + + const HAS_ALPHAMAP = !! material.alphaMap; + + const HAS_ALPHATEST = material.alphaTest > 0; + + const HAS_EXTENSIONS = !! material.extensions; + + const HAS_ATTRIBUTE_UV1 = !! geometry.attributes.uv1; + const HAS_ATTRIBUTE_UV2 = !! geometry.attributes.uv2; + const HAS_ATTRIBUTE_UV3 = !! geometry.attributes.uv3; const parameters = { - isWebGL2: isWebGL2, + isWebGL2: IS_WEBGL2, shaderID: shaderID, - shaderName: material.type, + shaderType: material.type, + shaderName: material.name, vertexShader: vertexShader, fragmentShader: fragmentShader, @@ -19424,72 +20235,115 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities precision: precision, - instancing: object.isInstancedMesh === true, - instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + instancing: IS_INSTANCEDMESH, + instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, - supportsVertexTextures: vertexTextures, - outputEncoding: ( currentRenderTarget === null ) ? renderer.outputEncoding : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding ), - map: !! material.map, - matcap: !! material.matcap, - envMap: !! envMap, - envMapMode: envMap && envMap.mapping, + supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, + outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), + + map: HAS_MAP, + matcap: HAS_MATCAP, + envMap: HAS_ENVMAP, + envMapMode: HAS_ENVMAP && envMap.mapping, envMapCubeUVHeight: envMapCubeUVHeight, - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, - tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, - - decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ), - - clearcoat: useClearcoat, - clearcoatMap: useClearcoat && !! material.clearcoatMap, - clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap, - clearcoatNormalMap: useClearcoat && !! material.clearcoatNormalMap, - - iridescence: useIridescence, - iridescenceMap: useIridescence && !! material.iridescenceMap, - iridescenceThicknessMap: useIridescence && !! material.iridescenceThicknessMap, - - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - specularIntensityMap: !! material.specularIntensityMap, - specularColorMap: !! material.specularColorMap, + aoMap: HAS_AOMAP, + lightMap: HAS_LIGHTMAP, + bumpMap: HAS_BUMPMAP, + normalMap: HAS_NORMALMAP, + displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + emissiveMap: HAS_EMISSIVEMAP, - opaque: material.transparent === false && material.blending === NormalBlending, + normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, + normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, - alphaMap: !! material.alphaMap, - alphaTest: useAlphaTest, + metalnessMap: HAS_METALNESSMAP, + roughnessMap: HAS_ROUGHNESSMAP, - gradientMap: !! material.gradientMap, + anisotropy: HAS_ANISOTROPY, + anisotropyMap: HAS_ANISOTROPYMAP, - sheen: material.sheen > 0, - sheenColorMap: !! material.sheenColorMap, - sheenRoughnessMap: !! material.sheenRoughnessMap, + clearcoat: HAS_CLEARCOAT, + clearcoatMap: HAS_CLEARCOATMAP, + clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, + clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, - transmission: material.transmission > 0, - transmissionMap: !! material.transmissionMap, - thicknessMap: !! material.thicknessMap, + iridescence: HAS_IRIDESCENCE, + iridescenceMap: HAS_IRIDESCENCEMAP, + iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, + + sheen: HAS_SHEEN, + sheenColorMap: HAS_SHEEN_COLORMAP, + sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, + + specularMap: HAS_SPECULARMAP, + specularColorMap: HAS_SPECULAR_COLORMAP, + specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, + + transmission: HAS_TRANSMISSION, + transmissionMap: HAS_TRANSMISSIONMAP, + thicknessMap: HAS_THICKNESSMAP, + + gradientMap: HAS_GRADIENTMAP, + + opaque: material.transparent === false && material.blending === NormalBlending, + + alphaMap: HAS_ALPHAMAP, + alphaTest: HAS_ALPHATEST, combine: material.combine, - vertexTangents: ( !! material.normalMap && !! geometry.attributes.tangent ), + // + + mapUv: HAS_MAP && getChannel( material.map.channel ), + aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), + lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), + bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), + normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), + displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), + emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), + + metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), + roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), + + anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), + + clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), + clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), + clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), + + iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), + iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), + + sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), + sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), + + specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), + specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), + specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), + + transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), + thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), + + alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), + + // + + vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), vertexColors: material.vertexColors, vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, - vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || !! material.displacementMap || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheenColorMap || !! material.sheenRoughnessMap, - uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || material.transmission > 0 || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || material.sheen > 0 || !! material.sheenColorMap || !! material.sheenRoughnessMap ) && !! material.displacementMap, + vertexUv1s: HAS_ATTRIBUTE_UV1, + vertexUv2s: HAS_ATTRIBUTE_UV2, + vertexUv3s: HAS_ATTRIBUTE_UV3, + + pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), fog: !! fog, useFog: material.fog === true, fogExp2: ( fog && fog.isFogExp2 ), - flatShading: !! material.flatShading, + flatShading: material.flatShading === true, - sizeAttenuation: material.sizeAttenuation, + sizeAttenuation: material.sizeAttenuation === true, logarithmicDepthBuffer: logarithmicDepthBuffer, skinning: object.isSkinnedMesh === true, @@ -19521,30 +20375,28 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities shadowMapType: renderer.shadowMap.type, toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, + useLegacyLights: renderer.useLegacyLights, premultipliedAlpha: material.premultipliedAlpha, doubleSided: material.side === DoubleSide, flipSided: material.side === BackSide, - useDepthPacking: !! material.depthPacking, + useDepthPacking: material.depthPacking >= 0, depthPacking: material.depthPacking || 0, index0AttributeName: material.index0AttributeName, - extensionDerivatives: material.extensions && material.extensions.derivatives, - extensionFragDepth: material.extensions && material.extensions.fragDepth, - extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, - extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, - - rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ), - rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ), - rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ), + extensionDerivatives: HAS_EXTENSIONS && material.extensions.derivatives === true, + extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true, + extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true, + extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true, - customProgramCacheKey: material.customProgramCacheKey(), + rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ), + rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ), + rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ), - extraProgramCacheKey: renderer.extraProgramCacheKey + customProgramCacheKey: material.customProgramCacheKey() }; @@ -19582,18 +20434,12 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities getProgramCacheKeyParameters( array, parameters ); getProgramCacheKeyBooleans( array, parameters ); - array.push( renderer.outputEncoding ); + array.push( renderer.outputColorSpace ); } array.push( parameters.customProgramCacheKey ); - if ( renderer.extraProgramCacheKey ) { - - array.push( renderer.extraProgramCacheKey ); - - } - return array.join(); } @@ -19601,11 +20447,33 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities function getProgramCacheKeyParameters( array, parameters ) { array.push( parameters.precision ); - array.push( parameters.outputEncoding ); + array.push( parameters.outputColorSpace ); array.push( parameters.envMapMode ); array.push( parameters.envMapCubeUVHeight ); + array.push( parameters.mapUv ); + array.push( parameters.alphaMapUv ); + array.push( parameters.lightMapUv ); + array.push( parameters.aoMapUv ); + array.push( parameters.bumpMapUv ); + array.push( parameters.normalMapUv ); + array.push( parameters.displacementMapUv ); + array.push( parameters.emissiveMapUv ); + array.push( parameters.metalnessMapUv ); + array.push( parameters.roughnessMapUv ); + array.push( parameters.anisotropyMapUv ); + array.push( parameters.clearcoatMapUv ); + array.push( parameters.clearcoatNormalMapUv ); + array.push( parameters.clearcoatRoughnessMapUv ); + array.push( parameters.iridescenceMapUv ); + array.push( parameters.iridescenceThicknessMapUv ); + array.push( parameters.sheenColorMapUv ); + array.push( parameters.sheenRoughnessMapUv ); + array.push( parameters.specularMapUv ); + array.push( parameters.specularColorMapUv ); + array.push( parameters.specularIntensityMapUv ); + array.push( parameters.transmissionMapUv ); + array.push( parameters.thicknessMapUv ); array.push( parameters.combine ); - array.push( parameters.vertexUvs ); array.push( parameters.fogExp2 ); array.push( parameters.sizeAttenuation ); array.push( parameters.morphTargetsCount ); @@ -19640,64 +20508,34 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 2 ); if ( parameters.instancingColor ) _programLayers.enable( 3 ); - if ( parameters.map ) - _programLayers.enable( 4 ); if ( parameters.matcap ) - _programLayers.enable( 5 ); + _programLayers.enable( 4 ); if ( parameters.envMap ) + _programLayers.enable( 5 ); + if ( parameters.normalMapObjectSpace ) _programLayers.enable( 6 ); - if ( parameters.lightMap ) + if ( parameters.normalMapTangentSpace ) _programLayers.enable( 7 ); - if ( parameters.aoMap ) + if ( parameters.clearcoat ) _programLayers.enable( 8 ); - if ( parameters.emissiveMap ) + if ( parameters.iridescence ) _programLayers.enable( 9 ); - if ( parameters.bumpMap ) + if ( parameters.alphaTest ) _programLayers.enable( 10 ); - if ( parameters.normalMap ) + if ( parameters.vertexColors ) _programLayers.enable( 11 ); - if ( parameters.objectSpaceNormalMap ) + if ( parameters.vertexAlphas ) _programLayers.enable( 12 ); - if ( parameters.tangentSpaceNormalMap ) + if ( parameters.vertexUv1s ) _programLayers.enable( 13 ); - if ( parameters.clearcoat ) + if ( parameters.vertexUv2s ) _programLayers.enable( 14 ); - if ( parameters.clearcoatMap ) + if ( parameters.vertexUv3s ) _programLayers.enable( 15 ); - if ( parameters.clearcoatRoughnessMap ) + if ( parameters.vertexTangents ) _programLayers.enable( 16 ); - if ( parameters.clearcoatNormalMap ) + if ( parameters.anisotropy ) _programLayers.enable( 17 ); - if ( parameters.iridescence ) - _programLayers.enable( 18 ); - if ( parameters.iridescenceMap ) - _programLayers.enable( 19 ); - if ( parameters.iridescenceThicknessMap ) - _programLayers.enable( 20 ); - if ( parameters.displacementMap ) - _programLayers.enable( 21 ); - if ( parameters.specularMap ) - _programLayers.enable( 22 ); - if ( parameters.roughnessMap ) - _programLayers.enable( 23 ); - if ( parameters.metalnessMap ) - _programLayers.enable( 24 ); - if ( parameters.gradientMap ) - _programLayers.enable( 25 ); - if ( parameters.alphaMap ) - _programLayers.enable( 26 ); - if ( parameters.alphaTest ) - _programLayers.enable( 27 ); - if ( parameters.vertexColors ) - _programLayers.enable( 28 ); - if ( parameters.vertexAlphas ) - _programLayers.enable( 29 ); - if ( parameters.vertexUvs ) - _programLayers.enable( 30 ); - if ( parameters.vertexTangents ) - _programLayers.enable( 31 ); - if ( parameters.uvsVertexOnly ) - _programLayers.enable( 32 ); array.push( _programLayers.mask ); _programLayers.disableAll(); @@ -19722,7 +20560,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 8 ); if ( parameters.shadowMapEnabled ) _programLayers.enable( 9 ); - if ( parameters.physicallyCorrectLights ) + if ( parameters.useLegacyLights ) _programLayers.enable( 10 ); if ( parameters.doubleSided ) _programLayers.enable( 11 ); @@ -19732,26 +20570,14 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 13 ); if ( parameters.dithering ) _programLayers.enable( 14 ); - if ( parameters.specularIntensityMap ) + if ( parameters.transmission ) _programLayers.enable( 15 ); - if ( parameters.specularColorMap ) + if ( parameters.sheen ) _programLayers.enable( 16 ); - if ( parameters.transmission ) + if ( parameters.opaque ) _programLayers.enable( 17 ); - if ( parameters.transmissionMap ) + if ( parameters.pointsUvs ) _programLayers.enable( 18 ); - if ( parameters.thicknessMap ) - _programLayers.enable( 19 ); - if ( parameters.sheen ) - _programLayers.enable( 20 ); - if ( parameters.sheenColorMap ) - _programLayers.enable( 21 ); - if ( parameters.sheenRoughnessMap ) - _programLayers.enable( 22 ); - if ( parameters.decodeVideoTexture ) - _programLayers.enable( 23 ); - if ( parameters.opaque ) - _programLayers.enable( 24 ); array.push( _programLayers.mask ); @@ -20330,7 +21156,7 @@ function WebGLLights( extensions, capabilities ) { const matrix4 = new Matrix4(); const matrix42 = new Matrix4(); - function setup( lights, physicallyCorrectLights ) { + function setup( lights, useLegacyLights ) { let r = 0, g = 0, b = 0; @@ -20352,7 +21178,7 @@ function WebGLLights( extensions, capabilities ) { lights.sort( shadowCastingAndTexturingLightsFirst ); // artist-friendly light intensity scaling factor - const scaleFactor = ( physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1; for ( let i = 0, l = lights.length; i < l; i ++ ) { @@ -20720,9 +21546,9 @@ function WebGLRenderState( extensions, capabilities ) { } - function setupLights( physicallyCorrectLights ) { + function setupLights( useLegacyLights ) { - lights.setup( lightsArray, physicallyCorrectLights ); + lights.setup( lightsArray, useLegacyLights ); } @@ -20857,10 +21683,6 @@ class MeshDistanceMaterial extends Material { this.type = 'MeshDistanceMaterial'; - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; - this.map = null; this.alphaMap = null; @@ -20877,10 +21699,6 @@ class MeshDistanceMaterial extends Material { super.copy( source ); - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; - this.map = source.map; this.alphaMap = source.alphaMap; @@ -20954,6 +21772,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { this.needsUpdate = false; this.type = PCFShadowMap; + let _previousType = this.type; this.render = function ( lights, scene, camera ) { @@ -20974,6 +21793,11 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { _state.buffers.depth.setTest( true ); _state.setScissorTest( false ); + // check for shadow map type changes + + const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); + const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); + // render depth map for ( let i = 0, il = lights.length; i < il; i ++ ) { @@ -21018,10 +21842,16 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } - if ( shadow.map === null ) { + if ( shadow.map === null || toVSM === true || fromVSM === true ) { const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; + if ( shadow.map !== null ) { + + shadow.map.dispose(); + + } + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); shadow.map.texture.name = light.name + '.shadowMap'; @@ -21067,6 +21897,8 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } + _previousType = this.type; + scope.needsUpdate = false; _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); @@ -21113,7 +21945,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } - function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) { + function getDepthMaterial( object, material, light, type ) { let result = null; @@ -21191,9 +22023,8 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { - result.referencePosition.setFromMatrixPosition( light.matrixWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; + const materialProperties = _renderer.properties.get( result ); + materialProperties.light = light; } @@ -21227,7 +22058,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { if ( groupMaterial && groupMaterial.visible ) { - const depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); @@ -21237,7 +22068,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } else if ( material.visible ) { - const depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, material, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); @@ -21336,11 +22167,11 @@ function WebGLState( gl, extensions, capabilities ) { if ( depthTest ) { - enable( 2929 ); + enable( gl.DEPTH_TEST ); } else { - disable( 2929 ); + disable( gl.DEPTH_TEST ); } @@ -21365,47 +22196,47 @@ function WebGLState( gl, extensions, capabilities ) { case NeverDepth: - gl.depthFunc( 512 ); + gl.depthFunc( gl.NEVER ); break; case AlwaysDepth: - gl.depthFunc( 519 ); + gl.depthFunc( gl.ALWAYS ); break; case LessDepth: - gl.depthFunc( 513 ); + gl.depthFunc( gl.LESS ); break; case LessEqualDepth: - gl.depthFunc( 515 ); + gl.depthFunc( gl.LEQUAL ); break; case EqualDepth: - gl.depthFunc( 514 ); + gl.depthFunc( gl.EQUAL ); break; case GreaterEqualDepth: - gl.depthFunc( 518 ); + gl.depthFunc( gl.GEQUAL ); break; case GreaterDepth: - gl.depthFunc( 516 ); + gl.depthFunc( gl.GREATER ); break; case NotEqualDepth: - gl.depthFunc( 517 ); + gl.depthFunc( gl.NOTEQUAL ); break; default: - gl.depthFunc( 515 ); + gl.depthFunc( gl.LEQUAL ); } @@ -21467,11 +22298,11 @@ function WebGLState( gl, extensions, capabilities ) { if ( stencilTest ) { - enable( 2960 ); + enable( gl.STENCIL_TEST ); } else { - disable( 2960 ); + disable( gl.STENCIL_TEST ); } @@ -21593,11 +22424,11 @@ function WebGLState( gl, extensions, capabilities ) { let currentPolygonOffsetFactor = null; let currentPolygonOffsetUnits = null; - const maxTextures = gl.getParameter( 35661 ); + const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); let lineWidthAvailable = false; let version = 0; - const glVersion = gl.getParameter( 7938 ); + const glVersion = gl.getParameter( gl.VERSION ); if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { @@ -21614,24 +22445,32 @@ function WebGLState( gl, extensions, capabilities ) { let currentTextureSlot = null; let currentBoundTextures = {}; - const scissorParam = gl.getParameter( 3088 ); - const viewportParam = gl.getParameter( 2978 ); + const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); + const viewportParam = gl.getParameter( gl.VIEWPORT ); const currentScissor = new Vector4().fromArray( scissorParam ); const currentViewport = new Vector4().fromArray( viewportParam ); - function createTexture( type, target, count ) { + function createTexture( type, target, count, dimensions ) { const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. const texture = gl.createTexture(); gl.bindTexture( type, texture ); - gl.texParameteri( type, 10241, 9728 ); - gl.texParameteri( type, 10240, 9728 ); + gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); for ( let i = 0; i < count; i ++ ) { - gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data ); + if ( isWebGL2 && ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) ) { + + gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } else { + + gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } } @@ -21640,8 +22479,15 @@ function WebGLState( gl, extensions, capabilities ) { } const emptyTextures = {}; - emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 ); - emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 ); + emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); + emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); + + if ( isWebGL2 ) { + + emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); + emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); + + } // init @@ -21649,12 +22495,12 @@ function WebGLState( gl, extensions, capabilities ) { depthBuffer.setClear( 1 ); stencilBuffer.setClear( 0 ); - enable( 2929 ); + enable( gl.DEPTH_TEST ); depthBuffer.setFunc( LessEqualDepth ); setFlipSided( false ); setCullFace( CullFaceBack ); - enable( 2884 ); + enable( gl.CULL_FACE ); setBlending( NoBlending ); @@ -21692,17 +22538,17 @@ function WebGLState( gl, extensions, capabilities ) { if ( isWebGL2 ) { - // 36009 is equivalent to 36160 + // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER - if ( target === 36009 ) { + if ( target === gl.DRAW_FRAMEBUFFER ) { - currentBoundFramebuffers[ 36160 ] = framebuffer; + currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; } - if ( target === 36160 ) { + if ( target === gl.FRAMEBUFFER ) { - currentBoundFramebuffers[ 36009 ] = framebuffer; + currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; } @@ -21737,11 +22583,11 @@ function WebGLState( gl, extensions, capabilities ) { const textures = renderTarget.texture; - if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== 36064 ) { + if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { for ( let i = 0, il = textures.length; i < il; i ++ ) { - drawBuffers[ i ] = 36064 + i; + drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; } @@ -21753,9 +22599,9 @@ function WebGLState( gl, extensions, capabilities ) { } else { - if ( drawBuffers[ 0 ] !== 36064 ) { + if ( drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { - drawBuffers[ 0 ] = 36064; + drawBuffers[ 0 ] = gl.COLOR_ATTACHMENT0; needsUpdate = true; @@ -21765,9 +22611,9 @@ function WebGLState( gl, extensions, capabilities ) { } else { - if ( drawBuffers[ 0 ] !== 1029 ) { + if ( drawBuffers[ 0 ] !== gl.BACK ) { - drawBuffers[ 0 ] = 1029; + drawBuffers[ 0 ] = gl.BACK; needsUpdate = true; @@ -21809,15 +22655,15 @@ function WebGLState( gl, extensions, capabilities ) { } const equationToGL = { - [ AddEquation ]: 32774, - [ SubtractEquation ]: 32778, - [ ReverseSubtractEquation ]: 32779 + [ AddEquation ]: gl.FUNC_ADD, + [ SubtractEquation ]: gl.FUNC_SUBTRACT, + [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT }; if ( isWebGL2 ) { - equationToGL[ MinEquation ] = 32775; - equationToGL[ MaxEquation ] = 32776; + equationToGL[ MinEquation ] = gl.MIN; + equationToGL[ MaxEquation ] = gl.MAX; } else { @@ -21833,17 +22679,17 @@ function WebGLState( gl, extensions, capabilities ) { } const factorToGL = { - [ ZeroFactor ]: 0, - [ OneFactor ]: 1, - [ SrcColorFactor ]: 768, - [ SrcAlphaFactor ]: 770, - [ SrcAlphaSaturateFactor ]: 776, - [ DstColorFactor ]: 774, - [ DstAlphaFactor ]: 772, - [ OneMinusSrcColorFactor ]: 769, - [ OneMinusSrcAlphaFactor ]: 771, - [ OneMinusDstColorFactor ]: 775, - [ OneMinusDstAlphaFactor ]: 773 + [ ZeroFactor ]: gl.ZERO, + [ OneFactor ]: gl.ONE, + [ SrcColorFactor ]: gl.SRC_COLOR, + [ SrcAlphaFactor ]: gl.SRC_ALPHA, + [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, + [ DstColorFactor ]: gl.DST_COLOR, + [ DstAlphaFactor ]: gl.DST_ALPHA, + [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, + [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, + [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, + [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA }; function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { @@ -21852,7 +22698,7 @@ function WebGLState( gl, extensions, capabilities ) { if ( currentBlendingEnabled === true ) { - disable( 3042 ); + disable( gl.BLEND ); currentBlendingEnabled = false; } @@ -21863,7 +22709,7 @@ function WebGLState( gl, extensions, capabilities ) { if ( currentBlendingEnabled === false ) { - enable( 3042 ); + enable( gl.BLEND ); currentBlendingEnabled = true; } @@ -21874,7 +22720,7 @@ function WebGLState( gl, extensions, capabilities ) { if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { - gl.blendEquation( 32774 ); + gl.blendEquation( gl.FUNC_ADD ); currentBlendEquation = AddEquation; currentBlendEquationAlpha = AddEquation; @@ -21886,19 +22732,19 @@ function WebGLState( gl, extensions, capabilities ) { switch ( blending ) { case NormalBlending: - gl.blendFuncSeparate( 1, 771, 1, 771 ); + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); break; case AdditiveBlending: - gl.blendFunc( 1, 1 ); + gl.blendFunc( gl.ONE, gl.ONE ); break; case SubtractiveBlending: - gl.blendFuncSeparate( 0, 769, 0, 1 ); + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); break; case MultiplyBlending: - gl.blendFuncSeparate( 0, 768, 0, 770 ); + gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); break; default: @@ -21912,19 +22758,19 @@ function WebGLState( gl, extensions, capabilities ) { switch ( blending ) { case NormalBlending: - gl.blendFuncSeparate( 770, 771, 1, 771 ); + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); break; case AdditiveBlending: - gl.blendFunc( 770, 1 ); + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); break; case SubtractiveBlending: - gl.blendFuncSeparate( 0, 769, 0, 1 ); + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); break; case MultiplyBlending: - gl.blendFunc( 0, 768 ); + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); break; default: @@ -21983,8 +22829,8 @@ function WebGLState( gl, extensions, capabilities ) { function setMaterial( material, frontFaceCW ) { material.side === DoubleSide - ? disable( 2884 ) - : enable( 2884 ); + ? disable( gl.CULL_FACE ) + : enable( gl.CULL_FACE ); let flipSided = ( material.side === BackSide ); if ( frontFaceCW ) flipSided = ! flipSided; @@ -22013,8 +22859,8 @@ function WebGLState( gl, extensions, capabilities ) { setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); material.alphaToCoverage === true - ? enable( 32926 ) - : disable( 32926 ); + ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) + : disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); } @@ -22026,11 +22872,11 @@ function WebGLState( gl, extensions, capabilities ) { if ( flipSided ) { - gl.frontFace( 2304 ); + gl.frontFace( gl.CW ); } else { - gl.frontFace( 2305 ); + gl.frontFace( gl.CCW ); } @@ -22044,21 +22890,21 @@ function WebGLState( gl, extensions, capabilities ) { if ( cullFace !== CullFaceNone ) { - enable( 2884 ); + enable( gl.CULL_FACE ); if ( cullFace !== currentCullFace ) { if ( cullFace === CullFaceBack ) { - gl.cullFace( 1029 ); + gl.cullFace( gl.BACK ); } else if ( cullFace === CullFaceFront ) { - gl.cullFace( 1028 ); + gl.cullFace( gl.FRONT ); } else { - gl.cullFace( 1032 ); + gl.cullFace( gl.FRONT_AND_BACK ); } @@ -22066,7 +22912,7 @@ function WebGLState( gl, extensions, capabilities ) { } else { - disable( 2884 ); + disable( gl.CULL_FACE ); } @@ -22090,7 +22936,7 @@ function WebGLState( gl, extensions, capabilities ) { if ( polygonOffset ) { - enable( 32823 ); + enable( gl.POLYGON_OFFSET_FILL ); if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { @@ -22103,7 +22949,7 @@ function WebGLState( gl, extensions, capabilities ) { } else { - disable( 32823 ); + disable( gl.POLYGON_OFFSET_FILL ); } @@ -22113,11 +22959,11 @@ function WebGLState( gl, extensions, capabilities ) { if ( scissorTest ) { - enable( 3089 ); + enable( gl.SCISSOR_TEST ); } else { - disable( 3089 ); + disable( gl.SCISSOR_TEST ); } @@ -22127,7 +22973,7 @@ function WebGLState( gl, extensions, capabilities ) { function activeTexture( webglSlot ) { - if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1; + if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; if ( currentTextureSlot !== webglSlot ) { @@ -22144,7 +22990,7 @@ function WebGLState( gl, extensions, capabilities ) { if ( currentTextureSlot === null ) { - webglSlot = 33984 + maxTextures - 1; + webglSlot = gl.TEXTURE0 + maxTextures - 1; } else { @@ -22406,43 +23252,43 @@ function WebGLState( gl, extensions, capabilities ) { // reset state - gl.disable( 3042 ); - gl.disable( 2884 ); - gl.disable( 2929 ); - gl.disable( 32823 ); - gl.disable( 3089 ); - gl.disable( 2960 ); - gl.disable( 32926 ); + gl.disable( gl.BLEND ); + gl.disable( gl.CULL_FACE ); + gl.disable( gl.DEPTH_TEST ); + gl.disable( gl.POLYGON_OFFSET_FILL ); + gl.disable( gl.SCISSOR_TEST ); + gl.disable( gl.STENCIL_TEST ); + gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); - gl.blendEquation( 32774 ); - gl.blendFunc( 1, 0 ); - gl.blendFuncSeparate( 1, 0, 1, 0 ); + gl.blendEquation( gl.FUNC_ADD ); + gl.blendFunc( gl.ONE, gl.ZERO ); + gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO ); gl.colorMask( true, true, true, true ); gl.clearColor( 0, 0, 0, 0 ); gl.depthMask( true ); - gl.depthFunc( 513 ); + gl.depthFunc( gl.LESS ); gl.clearDepth( 1 ); gl.stencilMask( 0xffffffff ); - gl.stencilFunc( 519, 0, 0xffffffff ); - gl.stencilOp( 7680, 7680, 7680 ); + gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff ); + gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ); gl.clearStencil( 0 ); - gl.cullFace( 1029 ); - gl.frontFace( 2305 ); + gl.cullFace( gl.BACK ); + gl.frontFace( gl.CCW ); gl.polygonOffset( 0, 0 ); - gl.activeTexture( 33984 ); + gl.activeTexture( gl.TEXTURE0 ); - gl.bindFramebuffer( 36160, null ); + gl.bindFramebuffer( gl.FRAMEBUFFER, null ); if ( isWebGL2 === true ) { - gl.bindFramebuffer( 36009, null ); - gl.bindFramebuffer( 36008, null ); + gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); + gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null ); } @@ -22679,7 +23525,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, encoding, forceLinearEncoding = false ) { + function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { if ( isWebGL2 === false ) return glFormat; @@ -22693,35 +23539,35 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, let internalFormat = glFormat; - if ( glFormat === 6403 ) { + if ( glFormat === _gl.RED ) { - if ( glType === 5126 ) internalFormat = 33326; - if ( glType === 5131 ) internalFormat = 33325; - if ( glType === 5121 ) internalFormat = 33321; + if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; } - if ( glFormat === 33319 ) { + if ( glFormat === _gl.RG ) { - if ( glType === 5126 ) internalFormat = 33328; - if ( glType === 5131 ) internalFormat = 33327; - if ( glType === 5121 ) internalFormat = 33323; + if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; } - if ( glFormat === 6408 ) { + if ( glFormat === _gl.RGBA ) { - if ( glType === 5126 ) internalFormat = 34836; - if ( glType === 5131 ) internalFormat = 34842; - if ( glType === 5121 ) internalFormat = ( encoding === sRGBEncoding && forceLinearEncoding === false ) ? 35907 : 32856; - if ( glType === 32819 ) internalFormat = 32854; - if ( glType === 32820 ) internalFormat = 32855; + if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; + if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( colorSpace === SRGBColorSpace && forceLinearTransfer === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; + if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; } - if ( internalFormat === 33325 || internalFormat === 33326 || - internalFormat === 33327 || internalFormat === 33328 || - internalFormat === 34842 || internalFormat === 34836 ) { + if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F || + internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || + internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) { extensions.get( 'EXT_color_buffer_float' ); @@ -22763,11 +23609,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) { - return 9728; + return _gl.NEAREST; } - return 9729; + return _gl.LINEAR; } @@ -22970,7 +23816,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, array.push( texture.premultiplyAlpha ); array.push( texture.flipY ); array.push( texture.unpackAlignment ); - array.push( texture.encoding ); + array.push( texture.colorSpace ); return array.join(); @@ -23005,7 +23851,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - state.bindTexture( 3553, textureProperties.__webglTexture, 33984 + slot ); + state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); } @@ -23020,7 +23866,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - state.bindTexture( 35866, textureProperties.__webglTexture, 33984 + slot ); + state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); } @@ -23035,7 +23881,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - state.bindTexture( 32879, textureProperties.__webglTexture, 33984 + slot ); + state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); } @@ -23050,50 +23896,61 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - state.bindTexture( 34067, textureProperties.__webglTexture, 33984 + slot ); + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); } const wrappingToGL = { - [ RepeatWrapping ]: 10497, - [ ClampToEdgeWrapping ]: 33071, - [ MirroredRepeatWrapping ]: 33648 + [ RepeatWrapping ]: _gl.REPEAT, + [ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE, + [ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT }; const filterToGL = { - [ NearestFilter ]: 9728, - [ NearestMipmapNearestFilter ]: 9984, - [ NearestMipmapLinearFilter ]: 9986, + [ NearestFilter ]: _gl.NEAREST, + [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST, + [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR, - [ LinearFilter ]: 9729, - [ LinearMipmapNearestFilter ]: 9985, - [ LinearMipmapLinearFilter ]: 9987 + [ LinearFilter ]: _gl.LINEAR, + [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST, + [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR + }; + + const compareToGL = { + [ NeverCompare ]: _gl.NEVER, + [ AlwaysCompare ]: _gl.ALWAYS, + [ LessCompare ]: _gl.LESS, + [ LessEqualCompare ]: _gl.LEQUAL, + [ EqualCompare ]: _gl.EQUAL, + [ GreaterEqualCompare ]: _gl.GEQUAL, + [ GreaterCompare ]: _gl.GREATER, + [ NotEqualCompare ]: _gl.NOTEQUAL }; function setTextureParameters( textureType, texture, supportsMips ) { if ( supportsMips ) { - _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] ); - _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); - if ( textureType === 32879 || textureType === 35866 ) { + if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { - _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] ); } - _gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] ); - _gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] ); + _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] ); } else { - _gl.texParameteri( textureType, 10242, 33071 ); - _gl.texParameteri( textureType, 10243, 33071 ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); - if ( textureType === 32879 || textureType === 35866 ) { + if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { - _gl.texParameteri( textureType, 32882, 33071 ); + _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, _gl.CLAMP_TO_EDGE ); } @@ -23103,8 +23960,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) ); - _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); + _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { @@ -23114,6 +23971,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + if ( texture.compareFunction ) { + + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); + + } + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); @@ -23216,36 +24080,36 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, function uploadTexture( textureProperties, texture, slot ) { - let textureType = 3553; + let textureType = _gl.TEXTURE_2D; - if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = 35866; - if ( texture.isData3DTexture ) textureType = 32879; + if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; + if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; const forceUpload = initTexture( textureProperties, texture ); const source = texture.source; - state.bindTexture( textureType, textureProperties.__webglTexture, 33984 + slot ); + state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); const sourceProperties = properties.get( source ); if ( source.version !== sourceProperties.__version || forceUpload === true ) { - state.activeTexture( 33984 + slot ); + state.activeTexture( _gl.TEXTURE0 + slot ); - _gl.pixelStorei( 37440, texture.flipY ); - _gl.pixelStorei( 37441, texture.premultiplyAlpha ); - _gl.pixelStorei( 3317, texture.unpackAlignment ); - _gl.pixelStorei( 37443, 0 ); + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); + _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE ); const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) === false; let image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize ); image = verifyColorSpace( texture, image ); const supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ); + glFormat = utils.convert( texture.format, texture.colorSpace ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); setTextureParameters( textureType, texture, supportsMips ); @@ -23260,25 +24124,25 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // populate depth texture with dummy data - glInternalFormat = 6402; + glInternalFormat = _gl.DEPTH_COMPONENT; if ( isWebGL2 ) { if ( texture.type === FloatType ) { - glInternalFormat = 36012; + glInternalFormat = _gl.DEPTH_COMPONENT32F; } else if ( texture.type === UnsignedIntType ) { - glInternalFormat = 33190; + glInternalFormat = _gl.DEPTH_COMPONENT24; } else if ( texture.type === UnsignedInt248Type ) { - glInternalFormat = 35056; + glInternalFormat = _gl.DEPTH24_STENCIL8; } else { - glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D + glInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D } @@ -23294,7 +24158,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // validation checks for WebGL 1 - if ( texture.format === DepthFormat && glInternalFormat === 6402 ) { + if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) { // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT @@ -23310,11 +24174,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) { + if ( texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) { // Depth stencil textures need the DEPTH_STENCIL internal format // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - glInternalFormat = 34041; + glInternalFormat = _gl.DEPTH_STENCIL; // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. @@ -23336,11 +24200,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texStorage2D( 3553, 1, glInternalFormat, image.width, image.height ); + state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); } else { - state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); } @@ -23356,7 +24220,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage && allocateMemory ) { - state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); } @@ -23366,11 +24230,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); } else { - state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); } @@ -23384,15 +24248,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( allocateMemory ) { - state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); } - state.texSubImage2D( 3553, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); } else { - state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); } @@ -23404,7 +24268,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage && allocateMemory ) { - state.texStorage3D( 35866, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); } @@ -23418,11 +24282,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.compressedTexSubImage3D( 35866, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); + state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); } else { - state.compressedTexImage3D( 35866, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); + state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); } @@ -23436,11 +24300,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage3D( 35866, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); } else { - state.texImage3D( 35866, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); + state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); } @@ -23452,7 +24316,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage && allocateMemory ) { - state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); } @@ -23466,11 +24330,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.compressedTexSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); + state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); } else { - state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); } @@ -23484,11 +24348,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); } else { - state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); } @@ -23504,15 +24368,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( allocateMemory ) { - state.texStorage3D( 35866, levels, glInternalFormat, image.width, image.height, image.depth ); + state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth ); } - state.texSubImage3D( 35866, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); + state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); } else { - state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); + state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); } @@ -23522,15 +24386,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( allocateMemory ) { - state.texStorage3D( 32879, levels, glInternalFormat, image.width, image.height, image.depth ); + state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth ); } - state.texSubImage3D( 32879, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); + state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); } else { - state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); + state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); } @@ -23540,7 +24404,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); } else { @@ -23548,7 +24412,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, for ( let i = 0; i < levels; i ++ ) { - state.texImage2D( 3553, i, glInternalFormat, width, height, 0, glFormat, glType, null ); + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null ); width >>= 1; height >>= 1; @@ -23571,7 +24435,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage && allocateMemory ) { - state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); } @@ -23581,11 +24445,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 3553, i, 0, 0, glFormat, glType, mipmap ); + state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap ); } else { - state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap ); + state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap ); } @@ -23599,15 +24463,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( allocateMemory ) { - state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height ); + state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); } - state.texSubImage2D( 3553, 0, 0, 0, glFormat, glType, image ); + state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image ); } else { - state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image ); + state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image ); } @@ -23638,18 +24502,18 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const forceUpload = initTexture( textureProperties, texture ); const source = texture.source; - state.bindTexture( 34067, textureProperties.__webglTexture, 33984 + slot ); + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); const sourceProperties = properties.get( source ); if ( source.version !== sourceProperties.__version || forceUpload === true ) { - state.activeTexture( 33984 + slot ); + state.activeTexture( _gl.TEXTURE0 + slot ); - _gl.pixelStorei( 37440, texture.flipY ); - _gl.pixelStorei( 37441, texture.premultiplyAlpha ); - _gl.pixelStorei( 3317, texture.unpackAlignment ); - _gl.pixelStorei( 37443, 0 ); + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); + _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, _gl.NONE ); const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); @@ -23674,15 +24538,15 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const image = cubeImage[ 0 ], supportsMips = isPowerOfTwo$1( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ), + glFormat = utils.convert( texture.format, texture.colorSpace ), glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); let levels = getMipLevels( texture, image, supportsMips ); - setTextureParameters( 34067, texture, supportsMips ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips ); let mipmaps; @@ -23690,7 +24554,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage && allocateMemory ) { - state.texStorage2D( 34067, levels, glInternalFormat, image.width, image.height ); + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height ); } @@ -23708,11 +24572,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.compressedTexSubImage2D( 34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); + state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); } else { - state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); + state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); } @@ -23726,11 +24590,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); } else { - state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); } @@ -23752,7 +24616,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( mipmaps.length > 0 ) levels ++; - state.texStorage2D( 34067, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height ); + state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height ); } @@ -23762,11 +24626,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 34069 + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); } else { - state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); } @@ -23777,11 +24641,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 34069 + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); } else { - state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); } @@ -23791,11 +24655,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 34069 + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); } else { - state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); } @@ -23805,11 +24669,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useTexStorage ) { - state.texSubImage2D( 34069 + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); + state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); } else { - state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); + state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); } @@ -23824,7 +24688,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { // We assume images for cube map have the same size. - generateMipmap( 34067 ); + generateMipmap( _gl.TEXTURE_CUBE_MAP ); } @@ -23843,14 +24707,14 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) { - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const renderTargetProperties = properties.get( renderTarget ); if ( ! renderTargetProperties.__hasExternalTextures ) { - if ( textureTarget === 32879 || textureTarget === 35866 ) { + if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null ); @@ -23862,19 +24726,19 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - state.bindFramebuffer( 36160, framebuffer ); + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); - } else if ( textureTarget === 3553 || ( textureTarget >= 34069 && textureTarget <= 34074 ) ) { // see #24753 + } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 - _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 ); } - state.bindFramebuffer( 36160, null ); + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); } @@ -23882,11 +24746,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Setup storage for internal depth/stencil buffers and bind to correct framebuffer function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { - _gl.bindRenderbuffer( 36161, renderbuffer ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { - let glInternalFormat = 33189; + let glInternalFormat = _gl.DEPTH_COMPONENT16; if ( isMultisample || useMultisampledRTT( renderTarget ) ) { @@ -23896,11 +24760,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( depthTexture.type === FloatType ) { - glInternalFormat = 36012; + glInternalFormat = _gl.DEPTH_COMPONENT32F; } else if ( depthTexture.type === UnsignedIntType ) { - glInternalFormat = 33190; + glInternalFormat = _gl.DEPTH_COMPONENT24; } @@ -23910,21 +24774,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); } else { - _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); } } else { - _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); } - _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { @@ -23932,20 +24796,20 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { - _gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height ); } else if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, 35056, renderTarget.width, renderTarget.height ); + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height ); } else { - _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); } - _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); } else { @@ -23955,22 +24819,22 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const texture = textures[ i ]; - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const samples = getRenderTargetSamples( renderTarget ); if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { - _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); } else if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); } else { - _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); } @@ -23978,7 +24842,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - _gl.bindRenderbuffer( 36161, null ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); } @@ -23988,7 +24852,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); - state.bindFramebuffer( 36160, framebuffer ); + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { @@ -24016,11 +24880,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 36096, 3553, webglDepthTexture, 0, samples ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); } else { - _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); } @@ -24028,11 +24892,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( useMultisampledRTT( renderTarget ) ) { - multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 33306, 3553, webglDepthTexture, 0, samples ); + multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); } else { - _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); } @@ -24064,7 +24928,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, for ( let i = 0; i < 6; i ++ ) { - state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); @@ -24072,7 +24936,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); @@ -24080,7 +24944,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - state.bindFramebuffer( 36160, null ); + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); } @@ -24091,7 +24955,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( colorTexture !== undefined ) { - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, 36064, 3553 ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); } @@ -24181,26 +25045,26 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer(); renderTargetProperties.__webglColorRenderbuffer = []; - state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); for ( let i = 0; i < textures.length; i ++ ) { const texture = textures[ i ]; renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); - _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, renderTarget.isXRRenderTarget === true ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); const samples = getRenderTargetSamples( renderTarget ); - _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); + _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); } - _gl.bindRenderbuffer( 36161, null ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); if ( renderTarget.depthBuffer ) { @@ -24209,7 +25073,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - state.bindFramebuffer( 36160, null ); + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); } @@ -24219,18 +25083,18 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( isCube ) { - state.bindTexture( 34067, textureProperties.__webglTexture ); - setTextureParameters( 34067, texture, supportsMips ); + state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips ); for ( let i = 0; i < 6; i ++ ) { - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, 36064, 34069 + i ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i ); } if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { - generateMipmap( 34067 ); + generateMipmap( _gl.TEXTURE_CUBE_MAP ); } @@ -24245,13 +25109,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const attachment = textures[ i ]; const attachmentProperties = properties.get( attachment ); - state.bindTexture( 3553, attachmentProperties.__webglTexture ); - setTextureParameters( 3553, attachment, supportsMips ); - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, 36064 + i, 3553 ); + state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture ); + setTextureParameters( _gl.TEXTURE_2D, attachment, supportsMips ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D ); if ( textureNeedsGenerateMipmaps( attachment, supportsMips ) ) { - generateMipmap( 3553 ); + generateMipmap( _gl.TEXTURE_2D ); } @@ -24261,13 +25125,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - let glTextureType = 3553; + let glTextureType = _gl.TEXTURE_2D; if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { if ( isWebGL2 ) { - glTextureType = renderTarget.isWebGL3DRenderTarget ? 32879 : 35866; + glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; } else { @@ -24279,7 +25143,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, state.bindTexture( glTextureType, textureProperties.__webglTexture ); setTextureParameters( glTextureType, texture, supportsMips ); - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType ); + setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType ); if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { @@ -24313,7 +25177,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { - const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553; + const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; const webglTexture = properties.get( texture ).__webglTexture; state.bindTexture( target, webglTexture ); @@ -24333,9 +25197,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [ renderTarget.texture ]; const width = renderTarget.width; const height = renderTarget.height; - let mask = 16384; + let mask = _gl.COLOR_BUFFER_BIT; const invalidationArray = []; - const depthStyle = renderTarget.stencilBuffer ? 33306 : 36096; + const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; const renderTargetProperties = properties.get( renderTarget ); const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true ); @@ -24344,22 +25208,22 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, for ( let i = 0; i < textures.length; i ++ ) { - state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); - _gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, null ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); - state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer ); - _gl.framebufferTexture2D( 36009, 36064 + i, 3553, null, 0 ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); } } - state.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer ); - state.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer ); + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); for ( let i = 0; i < textures.length; i ++ ) { - invalidationArray.push( 36064 + i ); + invalidationArray.push( _gl.COLOR_ATTACHMENT0 + i ); if ( renderTarget.depthBuffer ) { @@ -24371,63 +25235,63 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( ignoreDepthValues === false ) { - if ( renderTarget.depthBuffer ) mask |= 256; - if ( renderTarget.stencilBuffer ) mask |= 1024; + if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; + if ( renderTarget.stencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT; } if ( isMultipleRenderTargets ) { - _gl.framebufferRenderbuffer( 36008, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); + _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); } if ( ignoreDepthValues === true ) { - _gl.invalidateFramebuffer( 36008, [ depthStyle ] ); - _gl.invalidateFramebuffer( 36009, [ depthStyle ] ); + _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, [ depthStyle ] ); + _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); } if ( isMultipleRenderTargets ) { const webglTexture = properties.get( textures[ i ] ).__webglTexture; - _gl.framebufferTexture2D( 36009, 36064, 3553, webglTexture, 0 ); + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); } - _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 ); + _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); if ( supportsInvalidateFramebuffer ) { - _gl.invalidateFramebuffer( 36008, invalidationArray ); + _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArray ); } } - state.bindFramebuffer( 36008, null ); - state.bindFramebuffer( 36009, null ); + state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments if ( isMultipleRenderTargets ) { for ( let i = 0; i < textures.length; i ++ ) { - state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); - _gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); const webglTexture = properties.get( textures[ i ] ).__webglTexture; - state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer ); - _gl.framebufferTexture2D( 36009, 36064 + i, 3553, webglTexture, 0 ); + state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); + _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 ); } } - state.bindFramebuffer( 36009, renderTargetProperties.__webglMultisampledFramebuffer ); + state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); } @@ -24464,17 +25328,17 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, function verifyColorSpace( texture, image ) { - const encoding = texture.encoding; + const colorSpace = texture.colorSpace; const format = texture.format; const type = texture.type; - if ( texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat ) return image; + if ( texture.isCompressedTexture === true || texture.format === _SRGBAFormat ) return image; - if ( encoding !== LinearEncoding ) { + if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { // sRGB - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { if ( isWebGL2 === false ) { @@ -24511,7 +25375,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding ); + console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); } @@ -24544,24 +25408,24 @@ function WebGLUtils( gl, extensions, capabilities ) { const isWebGL2 = capabilities.isWebGL2; - function convert( p, encoding = null ) { + function convert( p, colorSpace = NoColorSpace ) { let extension; - if ( p === UnsignedByteType ) return 5121; - if ( p === UnsignedShort4444Type ) return 32819; - if ( p === UnsignedShort5551Type ) return 32820; + if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; + if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; + if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; - if ( p === ByteType ) return 5120; - if ( p === ShortType ) return 5122; - if ( p === UnsignedShortType ) return 5123; - if ( p === IntType ) return 5124; - if ( p === UnsignedIntType ) return 5125; - if ( p === FloatType ) return 5126; + if ( p === ByteType ) return gl.BYTE; + if ( p === ShortType ) return gl.SHORT; + if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; + if ( p === IntType ) return gl.INT; + if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; + if ( p === FloatType ) return gl.FLOAT; if ( p === HalfFloatType ) { - if ( isWebGL2 ) return 5131; + if ( isWebGL2 ) return gl.HALF_FLOAT; extension = extensions.get( 'OES_texture_half_float' ); @@ -24577,12 +25441,12 @@ function WebGLUtils( gl, extensions, capabilities ) { } - if ( p === AlphaFormat ) return 6406; - if ( p === RGBAFormat ) return 6408; - if ( p === LuminanceFormat ) return 6409; - if ( p === LuminanceAlphaFormat ) return 6410; - if ( p === DepthFormat ) return 6402; - if ( p === DepthStencilFormat ) return 34041; + if ( p === AlphaFormat ) return gl.ALPHA; + if ( p === RGBAFormat ) return gl.RGBA; + if ( p === LuminanceFormat ) return gl.LUMINANCE; + if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; + if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; + if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; // WebGL 1 sRGB fallback @@ -24604,17 +25468,17 @@ function WebGLUtils( gl, extensions, capabilities ) { // WebGL2 formats. - if ( p === RedFormat ) return 6403; - if ( p === RedIntegerFormat ) return 36244; - if ( p === RGFormat ) return 33319; - if ( p === RGIntegerFormat ) return 33320; - if ( p === RGBAIntegerFormat ) return 36249; + if ( p === RedFormat ) return gl.RED; + if ( p === RedIntegerFormat ) return gl.RED_INTEGER; + if ( p === RGFormat ) return gl.RG; + if ( p === RGIntegerFormat ) return gl.RG_INTEGER; + if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; // S3TC if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); @@ -24699,8 +25563,8 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; - if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + if ( p === RGB_ETC2_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; } else { @@ -24722,20 +25586,20 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; - if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; - if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; - if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; - if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; - if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; - if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; - if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; - if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; - if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; - if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; - if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; - if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; - if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; + if ( p === RGBA_ASTC_4x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; } else { @@ -24753,7 +25617,7 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + if ( p === RGBA_BPTC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; } else { @@ -24788,7 +25652,7 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( p === UnsignedInt248Type ) { - if ( isWebGL2 ) return 34042; + if ( isWebGL2 ) return gl.UNSIGNED_INT_24_8; extension = extensions.get( 'WEBGL_depth_texture' ); @@ -25010,6 +25874,7 @@ class WebXRController { joint.matrix.fromArray( jointPose.transform.matrix ); joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); + joint.matrixWorldNeedsUpdate = true; joint.jointRadius = jointPose.radius; } @@ -25058,6 +25923,7 @@ class WebXRController { grip.matrix.fromArray( gripPose.transform.matrix ); grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + grip.matrixWorldNeedsUpdate = true; if ( gripPose.linearVelocity ) { @@ -25102,6 +25968,7 @@ class WebXRController { targetRay.matrix.fromArray( inputPose.transform.matrix ); targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + targetRay.matrixWorldNeedsUpdate = true; if ( inputPose.linearVelocity ) { @@ -25204,8 +26071,30 @@ class DepthTexture extends Texture { this.flipY = false; this.generateMipmaps = false; + this.compareFunction = null; + + } + + + copy( source ) { + + super.copy( source ); + + this.compareFunction = source.compareFunction; + + return this; + } + toJSON( meta ) { + + const data = super.toJSON( meta ); + + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; + + return data; + + } } @@ -25218,6 +26107,7 @@ class WebXRManager extends EventDispatcher { const scope = this; let session = null; + let framebufferScaleFactor = 1.0; let referenceSpace = null; @@ -25238,11 +26128,10 @@ class WebXRManager extends EventDispatcher { const controllers = []; const controllerInputSources = []; - const planes = new Set(); - const planesLastChangedTimes = new Map(); - // + let userCamera = null; + const cameraL = new PerspectiveCamera(); cameraL.layers.enable( 1 ); cameraL.viewport = new Vector4(); @@ -25253,20 +26142,28 @@ class WebXRManager extends EventDispatcher { const cameras = [ cameraL, cameraR ]; - const cameraVR = new ArrayCamera(); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + const cameraXR = new ArrayCamera(); + cameraXR.layers.enable( 1 ); + cameraXR.layers.enable( 2 ); let _currentDepthNear = null; let _currentDepthFar = null; // - this.cameraAutoUpdate = true; + this.cameraAutoUpdate = true; // @deprecated, r153 this.enabled = false; this.isPresenting = false; + this.getCamera = function () {}; // @deprecated, r153 + + this.setUserCamera = function ( value ) { + + userCamera = value; + + }; + this.getController = function ( index ) { let controller = controllers[ index ]; @@ -25328,6 +26225,7 @@ class WebXRManager extends EventDispatcher { if ( controller !== undefined ) { + controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); controller.dispatchEvent( { type: event.type, data: event.inputSource } ); } @@ -25467,7 +26365,7 @@ class WebXRManager extends EventDispatcher { const layerInit = { antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true, - alpha: attributes.alpha, + alpha: true, depth: attributes.depth, stencil: attributes.stencil, framebufferScaleFactor: framebufferScaleFactor @@ -25483,7 +26381,7 @@ class WebXRManager extends EventDispatcher { { format: RGBAFormat, type: UnsignedByteType, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, stencilBuffer: attributes.stencil } ); @@ -25496,14 +26394,14 @@ class WebXRManager extends EventDispatcher { if ( attributes.depth ) { - glDepthFormat = attributes.stencil ? 35056 : 33190; + glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; } const projectionlayerInit = { - colorFormat: 32856, + colorFormat: gl.RGBA8, depthFormat: glDepthFormat, scaleFactor: framebufferScaleFactor }; @@ -25522,7 +26420,7 @@ class WebXRManager extends EventDispatcher { type: UnsignedByteType, depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), stencilBuffer: attributes.stencil, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, samples: attributes.antialias ? 4 : 0 } ); @@ -25549,6 +26447,16 @@ class WebXRManager extends EventDispatcher { }; + this.getEnvironmentBlendMode = function () { + + if ( session !== null ) { + + return session.environmentBlendMode; + + } + + }; + function onInputSourcesChange( event ) { // Notify disconnected @@ -25672,6 +26580,7 @@ class WebXRManager extends EventDispatcher { const bottom2 = bottomFov * far / far2 * near2; camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); } @@ -25691,31 +26600,37 @@ class WebXRManager extends EventDispatcher { } - this.updateCamera = function ( camera ) { + this.updateCameraXR = function ( camera ) { - if ( session === null ) return; + if ( session === null ) return camera; + + if ( userCamera ) { + + camera = userCamera; + + } - cameraVR.near = cameraR.near = cameraL.near = camera.near; - cameraVR.far = cameraR.far = cameraL.far = camera.far; + cameraXR.near = cameraR.near = cameraL.near = camera.near; + cameraXR.far = cameraR.far = cameraL.far = camera.far; - if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { + if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { // Note that the new renderState won't apply until the next frame. See #18320 session.updateRenderState( { - depthNear: cameraVR.near, - depthFar: cameraVR.far + depthNear: cameraXR.near, + depthFar: cameraXR.far } ); - _currentDepthNear = cameraVR.near; - _currentDepthFar = cameraVR.far; + _currentDepthNear = cameraXR.near; + _currentDepthFar = cameraXR.far; } const parent = camera.parent; - const cameras = cameraVR.cameras; + const cameras = cameraXR.cameras; - updateCamera( cameraVR, parent ); + updateCamera( cameraXR, parent ); for ( let i = 0; i < cameras.length; i ++ ) { @@ -25723,42 +26638,70 @@ class WebXRManager extends EventDispatcher { } - cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale ); + // update projection matrix for proper view frustum culling - // update user camera and its children + if ( cameras.length === 2 ) { - camera.matrix.copy( cameraVR.matrix ); - camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + setProjectionFromUnion( cameraXR, cameraL, cameraR ); - const children = camera.children; + } else { - for ( let i = 0, l = children.length; i < l; i ++ ) { + // assume single camera setup (AR) - children[ i ].updateMatrixWorld( true ); + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); } - // update projection matrix for proper view frustum culling + // update user camera and its children - if ( cameras.length === 2 ) { + if ( userCamera ) { - setProjectionFromUnion( cameraVR, cameraL, cameraR ); + updateUserCamera( cameraXR, parent ); + + } + + return cameraXR; + + }; + + function updateUserCamera( cameraXR, parent ) { + + const camera = userCamera; + + if ( parent === null ) { + + camera.matrix.copy( cameraXR.matrixWorld ); } else { - // assume single camera setup (AR) + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); + + } + + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); + + const children = camera.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + children[ i ].updateMatrixWorld( true ); } - }; + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); - this.getCamera = function () { + if ( camera.isPerspectiveCamera ) { - return cameraVR; + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; - }; + } + + } this.getFoveation = function () { @@ -25793,12 +26736,6 @@ class WebXRManager extends EventDispatcher { }; - this.getPlanes = function () { - - return planes; - - }; - // Animation Loop let onAnimationFrameCallback = null; @@ -25819,14 +26756,14 @@ class WebXRManager extends EventDispatcher { } - let cameraVRNeedsUpdate = false; + let cameraXRNeedsUpdate = false; - // check if it's necessary to rebuild cameraVR's camera list + // check if it's necessary to rebuild cameraXR's camera list - if ( views.length !== cameraVR.cameras.length ) { + if ( views.length !== cameraXR.cameras.length ) { - cameraVR.cameras.length = 0; - cameraVRNeedsUpdate = true; + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; } @@ -25871,18 +26808,21 @@ class WebXRManager extends EventDispatcher { } camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); if ( i === 0 ) { - cameraVR.matrix.copy( camera.matrix ); + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); } - if ( cameraVRNeedsUpdate === true ) { + if ( cameraXRNeedsUpdate === true ) { - cameraVR.cameras.push( camera ); + cameraXR.cameras.push( camera ); } @@ -25909,60 +26849,7 @@ class WebXRManager extends EventDispatcher { if ( frame.detectedPlanes ) { - scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } ); - - let planesToRemove = null; - - for ( const plane of planes ) { - - if ( ! frame.detectedPlanes.has( plane ) ) { - - if ( planesToRemove === null ) { - - planesToRemove = []; - - } - - planesToRemove.push( plane ); - - } - - } - - if ( planesToRemove !== null ) { - - for ( const plane of planesToRemove ) { - - planes.delete( plane ); - planesLastChangedTimes.delete( plane ); - scope.dispatchEvent( { type: 'planeremoved', data: plane } ); - - } - - } - - for ( const plane of frame.detectedPlanes ) { - - if ( ! planes.has( plane ) ) { - - planes.add( plane ); - planesLastChangedTimes.set( plane, frame.lastChangedTime ); - scope.dispatchEvent( { type: 'planeadded', data: plane } ); - - } else { - - const lastKnownTime = planesLastChangedTimes.get( plane ); - - if ( plane.lastChangedTime > lastKnownTime ) { - - planesLastChangedTimes.set( plane, plane.lastChangedTime ); - scope.dispatchEvent( { type: 'planechanged', data: plane } ); - - } - - } - - } + scope.dispatchEvent( { type: 'planesdetected', data: frame } ); } @@ -25988,6 +26875,18 @@ class WebXRManager extends EventDispatcher { function WebGLMaterials( renderer, properties ) { + function refreshTransformUniform( map, uniform ) { + + if ( map.matrixAutoUpdate === true ) { + + map.updateMatrix(); + + } + + uniform.value.copy( map.matrix ); + + } + function refreshFogUniforms( uniforms, fog ) { fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); @@ -26105,25 +27004,56 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.bumpMap ) { uniforms.bumpMap.value = material.bumpMap; + + refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); + uniforms.bumpScale.value = material.bumpScale; - if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; + + if ( material.side === BackSide ) { + + uniforms.bumpScale.value *= - 1; + + } + + } + + if ( material.normalMap ) { + + uniforms.normalMap.value = material.normalMap; + + refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); + + uniforms.normalScale.value.copy( material.normalScale ); + + if ( material.side === BackSide ) { + + uniforms.normalScale.value.negate(); + + } } if ( material.displacementMap ) { uniforms.displacementMap.value = material.displacementMap; + + refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); + uniforms.displacementScale.value = material.displacementScale; uniforms.displacementBias.value = material.displacementBias; @@ -26133,13 +27063,7 @@ function WebGLMaterials( renderer, properties ) { uniforms.emissiveMap.value = material.emissiveMap; - } - - if ( material.normalMap ) { - - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); - if ( material.side === BackSide ) uniforms.normalScale.value.negate(); + refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); } @@ -26147,6 +27071,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.specularMap.value = material.specularMap; + refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26174,10 +27100,12 @@ function WebGLMaterials( renderer, properties ) { uniforms.lightMap.value = material.lightMap; // artist-friendly light intensity scaling factor - const scaleFactor = ( renderer.physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( renderer.useLegacyLights === true ) ? Math.PI : 1; uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; + refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); + } if ( material.aoMap ) { @@ -26185,175 +27113,27 @@ function WebGLMaterials( renderer, properties ) { uniforms.aoMap.value = material.aoMap; uniforms.aoMapIntensity.value = material.aoMapIntensity; - } - - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. displacementMap map - // 4. normal map - // 5. bump map - // 6. roughnessMap map - // 7. metalnessMap map - // 8. alphaMap map - // 9. emissiveMap map - // 10. clearcoat map - // 11. clearcoat normal map - // 12. clearcoat roughnessMap map - // 13. iridescence map - // 14. iridescence thickness map - // 15. specular intensity map - // 16. specular tint map - // 17. transmission map - // 18. thickness map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.specularMap ) { - - uvScaleMap = material.specularMap; - - } else if ( material.displacementMap ) { - - uvScaleMap = material.displacementMap; - - } else if ( material.normalMap ) { - - uvScaleMap = material.normalMap; - - } else if ( material.bumpMap ) { - - uvScaleMap = material.bumpMap; - - } else if ( material.roughnessMap ) { - - uvScaleMap = material.roughnessMap; - - } else if ( material.metalnessMap ) { - - uvScaleMap = material.metalnessMap; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } else if ( material.emissiveMap ) { - - uvScaleMap = material.emissiveMap; - - } else if ( material.clearcoatMap ) { - - uvScaleMap = material.clearcoatMap; - - } else if ( material.clearcoatNormalMap ) { - - uvScaleMap = material.clearcoatNormalMap; - - } else if ( material.clearcoatRoughnessMap ) { - - uvScaleMap = material.clearcoatRoughnessMap; - - } else if ( material.iridescenceMap ) { - - uvScaleMap = material.iridescenceMap; - - } else if ( material.iridescenceThicknessMap ) { - - uvScaleMap = material.iridescenceThicknessMap; - - } else if ( material.specularIntensityMap ) { - - uvScaleMap = material.specularIntensityMap; - - } else if ( material.specularColorMap ) { - - uvScaleMap = material.specularColorMap; - - } else if ( material.transmissionMap ) { - - uvScaleMap = material.transmissionMap; - - } else if ( material.thicknessMap ) { - - uvScaleMap = material.thicknessMap; - - } else if ( material.sheenColorMap ) { - - uvScaleMap = material.sheenColorMap; - - } else if ( material.sheenRoughnessMap ) { - - uvScaleMap = material.sheenRoughnessMap; - - } - - if ( uvScaleMap !== undefined ) { - - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { - - uvScaleMap = uvScaleMap.texture; - - } - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); + refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); } - // uv repeat and offset setting priorities for uv2 - // 1. ao map - // 2. light map - - let uv2ScaleMap; - - if ( material.aoMap ) { - - uv2ScaleMap = material.aoMap; - - } else if ( material.lightMap ) { - - uv2ScaleMap = material.lightMap; - - } - - if ( uv2ScaleMap !== undefined ) { - - // backwards compatibility - if ( uv2ScaleMap.isWebGLRenderTarget ) { - - uv2ScaleMap = uv2ScaleMap.texture; + } - } + function refreshUniformsLine( uniforms, material ) { - if ( uv2ScaleMap.matrixAutoUpdate === true ) { + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - uv2ScaleMap.updateMatrix(); + if ( material.map ) { - } + uniforms.map.value = material.map; - uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix ); + refreshTransformUniform( material.map, uniforms.mapTransform ); } } - function refreshUniformsLine( uniforms, material ) { - - uniforms.diffuse.value.copy( material.color ); - uniforms.opacity.value = material.opacity; - - } - function refreshUniformsDash( uniforms, material ) { uniforms.dashSize.value = material.dashSize; @@ -26373,12 +27153,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.uvTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26387,34 +27171,6 @@ function WebGLMaterials( renderer, properties ) { } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsSprites( uniforms, material ) { @@ -26427,12 +27183,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -26441,34 +27201,6 @@ function WebGLMaterials( renderer, properties ) { } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsPhong( uniforms, material ) { @@ -26490,18 +27222,23 @@ function WebGLMaterials( renderer, properties ) { function refreshUniformsStandard( uniforms, material ) { - uniforms.roughness.value = material.roughness; uniforms.metalness.value = material.metalness; - if ( material.roughnessMap ) { + if ( material.metalnessMap ) { - uniforms.roughnessMap.value = material.roughnessMap; + uniforms.metalnessMap.value = material.metalnessMap; + + refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); } - if ( material.metalnessMap ) { + uniforms.roughness.value = material.roughness; - uniforms.metalnessMap.value = material.metalnessMap; + if ( material.roughnessMap ) { + + uniforms.roughnessMap.value = material.roughnessMap; + + refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); } @@ -26530,12 +27267,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.sheenColorMap.value = material.sheenColorMap; + refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); + } if ( material.sheenRoughnessMap ) { uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; + refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); + } } @@ -26549,19 +27290,26 @@ function WebGLMaterials( renderer, properties ) { uniforms.clearcoatMap.value = material.clearcoatMap; + refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); + } if ( material.clearcoatRoughnessMap ) { uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; + refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); + } if ( material.clearcoatNormalMap ) { - uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; + refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); + + uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); + if ( material.side === BackSide ) { uniforms.clearcoatNormalScale.value.negate(); @@ -26583,12 +27331,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.iridescenceMap.value = material.iridescenceMap; + refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); + } if ( material.iridescenceThicknessMap ) { uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; + refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); + } } @@ -26603,6 +27355,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.transmissionMap.value = material.transmissionMap; + refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); + } uniforms.thickness.value = material.thickness; @@ -26611,6 +27365,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.thicknessMap.value = material.thicknessMap; + refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); + } uniforms.attenuationDistance.value = material.attenuationDistance; @@ -26618,19 +27374,37 @@ function WebGLMaterials( renderer, properties ) { } - uniforms.specularIntensity.value = material.specularIntensity; - uniforms.specularColor.value.copy( material.specularColor ); + if ( material.anisotropy > 0 ) { - if ( material.specularIntensityMap ) { + uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - uniforms.specularIntensityMap.value = material.specularIntensityMap; + if ( material.anisotropyMap ) { + + uniforms.anisotropyMap.value = material.anisotropyMap; + + refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); + + } } + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy( material.specularColor ); + if ( material.specularColorMap ) { uniforms.specularColorMap.value = material.specularColorMap; + refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); + + } + + if ( material.specularIntensityMap ) { + + uniforms.specularIntensityMap.value = material.specularIntensityMap; + + refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); + } } @@ -26647,9 +27421,11 @@ function WebGLMaterials( renderer, properties ) { function refreshUniformsDistance( uniforms, material ) { - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; + const light = properties.get( material ).light; + + uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); + uniforms.nearDistance.value = light.shadow.camera.near; + uniforms.farDistance.value = light.shadow.camera.far; } @@ -26666,7 +27442,7 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { let updateList = {}; let allocatedBindingPoints = []; - const maxBindingPoints = ( capabilities.isWebGL2 ) ? gl.getParameter( 35375 ) : 0; // binding points are global whereas block indices are per shader program + const maxBindingPoints = ( capabilities.isWebGL2 ) ? gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ) : 0; // binding points are global whereas block indices are per shader program function bind( uniformsGroup, program ) { @@ -26720,10 +27496,10 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { const size = uniformsGroup.__size; const usage = uniformsGroup.usage; - gl.bindBuffer( 35345, buffer ); - gl.bufferData( 35345, size, usage ); - gl.bindBuffer( 35345, null ); - gl.bindBufferBase( 35345, bindingPointIndex, buffer ); + gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); + gl.bufferData( gl.UNIFORM_BUFFER, size, usage ); + gl.bindBuffer( gl.UNIFORM_BUFFER, null ); + gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer ); return buffer; @@ -26754,7 +27530,7 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { const uniforms = uniformsGroup.uniforms; const cache = uniformsGroup.__cache; - gl.bindBuffer( 35345, buffer ); + gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); for ( let i = 0, il = uniforms.length; i < il; i ++ ) { @@ -26779,7 +27555,7 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { if ( typeof value === 'number' ) { uniform.__data[ 0 ] = value; - gl.bufferSubData( 35345, offset + arrayOffset, uniform.__data ); + gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data ); } else if ( value.isMatrix3 ) { @@ -26808,13 +27584,13 @@ function WebGLUniformsGroups( gl, info, capabilities, state ) { } - gl.bufferSubData( 35345, offset, uniform.__data ); + gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data ); } } - gl.bindBuffer( 35345, null ); + gl.bindBuffer( gl.UNIFORM_BUFFER, null ); } @@ -27079,2206 +27855,2374 @@ function createCanvasElement() { } -function WebGLRenderer( parameters = {} ) { +class WebGLRenderer { - this.isWebGLRenderer = true; + constructor( parameters = {} ) { - const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(), - _context = parameters.context !== undefined ? parameters.context : null, + const { + canvas = createCanvasElement(), + context = null, + depth = true, + stencil = true, + alpha = false, + antialias = false, + premultipliedAlpha = true, + preserveDrawingBuffer = false, + powerPreference = 'default', + failIfMajorPerformanceCaveat = false, + } = parameters; - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, - _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', - _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; + this.isWebGLRenderer = true; - let _alpha; + let _alpha; - if ( _context !== null ) { + if ( context !== null ) { - _alpha = _context.getContextAttributes().alpha; + _alpha = context.getContextAttributes().alpha; - } else { + } else { - _alpha = parameters.alpha !== undefined ? parameters.alpha : false; + _alpha = alpha; - } + } - let currentRenderList = null; - let currentRenderState = null; + const uintClearColor = new Uint32Array( 4 ); + const intClearColor = new Int32Array( 4 ); - // render() can be called from within a callback triggered by another render. - // We track this so that the nested render call gets its list and state isolated from the parent render call. + let currentRenderList = null; + let currentRenderState = null; - const renderListStack = []; - const renderStateStack = []; + // render() can be called from within a callback triggered by another render. + // We track this so that the nested render call gets its list and state isolated from the parent render call. - // public properties + const renderListStack = []; + const renderStateStack = []; - this.domElement = _canvas; + // public properties - // Debug configuration container - this.debug = { + this.domElement = canvas; - /** - * Enables error checking and reporting when shader programs are being compiled - * @type {boolean} - */ - checkShaderErrors: true - }; + // Debug configuration container + this.debug = { - // clearing + /** + * Enables error checking and reporting when shader programs are being compiled + * @type {boolean} + */ + checkShaderErrors: true, + /** + * Callback for custom error reporting. + * @type {?Function} + */ + onShaderError: null + }; - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; + // clearing - // scene graph + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; - this.sortObjects = true; + // scene graph - // user-defined clipping + this.sortObjects = true; - this.clippingPlanes = []; - this.localClippingEnabled = false; + // user-defined clipping - // physically based shading + this.clippingPlanes = []; + this.localClippingEnabled = false; - this.outputEncoding = LinearEncoding; + // physically based shading - // physical lights + this.outputColorSpace = SRGBColorSpace; - this.physicallyCorrectLights = false; + // physical lights - // tone mapping + this.useLegacyLights = true; - this.toneMapping = NoToneMapping; - this.toneMappingExposure = 1.0; + // tone mapping - // internal properties + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; - const _this = this; + // internal properties - let _isContextLost = false; + const _this = this; - // internal state cache + let _isContextLost = false; - let _currentActiveCubeFace = 0; - let _currentActiveMipmapLevel = 0; - let _currentRenderTarget = null; - let _currentMaterialId = - 1; + // internal state cache - let _currentCamera = null; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = - 1; - const _currentViewport = new Vector4(); - const _currentScissor = new Vector4(); - let _currentScissorTest = null; + let _currentCamera = null; - // + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; - let _width = _canvas.width; - let _height = _canvas.height; + const _currentClearColor = new Color( 0x000000 ); + let _currentClearAlpha = 0; - let _pixelRatio = 1; - let _opaqueSort = null; - let _transparentSort = null; + // - const _viewport = new Vector4( 0, 0, _width, _height ); - const _scissor = new Vector4( 0, 0, _width, _height ); - let _scissorTest = false; + let _width = canvas.width; + let _height = canvas.height; - // frustum + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; - const _frustum = new Frustum(); + const _viewport = new Vector4( 0, 0, _width, _height ); + const _scissor = new Vector4( 0, 0, _width, _height ); + let _scissorTest = false; - // clipping + // frustum - let _clippingEnabled = false; - let _localClippingEnabled = false; + const _frustum = new Frustum(); - // transmission + // clipping - let _transmissionRenderTarget = null; + let _clippingEnabled = false; + let _localClippingEnabled = false; - // camera matrices cache + // transmission - const _projScreenMatrix = new Matrix4(); + let _transmissionRenderTarget = null; - const _vector2 = new Vector2(); - const _vector3 = new Vector3(); + // camera matrices cache - const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; + const _projScreenMatrix = new Matrix4(); - function getTargetPixelRatio() { + const _vector2 = new Vector2(); + const _vector3 = new Vector3(); - return _currentRenderTarget === null ? _pixelRatio : 1; + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; - } + function getTargetPixelRatio() { - // initialize + return _currentRenderTarget === null ? _pixelRatio : 1; - let _gl = _context; + } + + // initialize - function getContext( contextNames, contextAttributes ) { + let _gl = context; - for ( let i = 0; i < contextNames.length; i ++ ) { + function getContext( contextNames, contextAttributes ) { - const contextName = contextNames[ i ]; - const context = _canvas.getContext( contextName, contextAttributes ); - if ( context !== null ) return context; + for ( let i = 0; i < contextNames.length; i ++ ) { + + const contextName = contextNames[ i ]; + const context = canvas.getContext( contextName, contextAttributes ); + if ( context !== null ) return context; + + } + + return null; } - return null; + try { - } + const contextAttributes = { + alpha: true, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + powerPreference, + failIfMajorPerformanceCaveat, + }; - try { + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); - const contextAttributes = { - alpha: true, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer, - powerPreference: _powerPreference, - failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat - }; + // event listeners must be registered before WebGL context is created, see #12753 + canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + + if ( _gl === null ) { - // OffscreenCanvas does not have setAttribute, see #22811 - if ( 'setAttribute' in _canvas ) _canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); + const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; - // event listeners must be registered before WebGL context is created, see #12753 - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + if ( _this.isWebGL1Renderer === true ) { - if ( _gl === null ) { + contextNames.shift(); + + } - const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; + _gl = getContext( contextNames, contextAttributes ); - if ( _this.isWebGL1Renderer === true ) { + if ( _gl === null ) { + + if ( getContext( contextNames ) ) { + + throw new Error( 'Error creating WebGL context with your selected attributes.' ); + + } else { - contextNames.shift(); + throw new Error( 'Error creating WebGL context.' ); + + } + + } } - _gl = getContext( contextNames, contextAttributes ); + if ( _gl instanceof WebGLRenderingContext ) { // @deprecated, r153 - if ( _gl === null ) { + console.warn( 'THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.' ); - if ( getContext( contextNames ) ) { + } - throw new Error( 'Error creating WebGL context with your selected attributes.' ); + // Some experimental-webgl implementations do not have getShaderPrecisionFormat - } else { + if ( _gl.getShaderPrecisionFormat === undefined ) { - throw new Error( 'Error creating WebGL context.' ); + _gl.getShaderPrecisionFormat = function () { - } + return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + + }; } + } catch ( error ) { + + console.error( 'THREE.WebGLRenderer: ' + error.message ); + throw error; + } - // Some experimental-webgl implementations do not have getShaderPrecisionFormat + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; - if ( _gl.getShaderPrecisionFormat === undefined ) { + let background, morphtargets, bufferRenderer, indexedBufferRenderer; - _gl.getShaderPrecisionFormat = function () { + let utils, bindingStates, uniformsGroups; - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + function initGLContext() { - }; + extensions = new WebGLExtensions( _gl ); + + capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + + extensions.init( capabilities ); + + utils = new WebGLUtils( _gl, extensions, capabilities ); + + state = new WebGLState( _gl, extensions, capabilities ); + + info = new WebGLInfo( _gl ); + properties = new WebGLProperties(); + textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); + cubemaps = new WebGLCubeMaps( _this ); + cubeuvmaps = new WebGLCubeUVMaps( _this ); + attributes = new WebGLAttributes( _gl, capabilities ); + bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); + geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); + objects = new WebGLObjects( _gl, geometries, attributes, info ); + morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); + clipping = new WebGLClipping( properties ); + programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); + materials = new WebGLMaterials( _this, properties ); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates( extensions, capabilities ); + background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + shadowMap = new WebGLShadowMap( _this, objects, capabilities ); + uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); + + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); + + info.programs = programCache.programs; + + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.shadowMap = shadowMap; + _this.state = state; + _this.info = info; } - } catch ( error ) { + initGLContext(); + + // xr - console.error( 'THREE.WebGLRenderer: ' + error.message ); - throw error; + const xr = new WebXRManager( _this, _gl ); - } + this.xr = xr; + + // API + + this.getContext = function () { + + return _gl; + + }; + + this.getContextAttributes = function () { + + return _gl.getContextAttributes(); + + }; + + this.forceContextLoss = function () { + + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.loseContext(); + + }; + + this.forceContextRestore = function () { + + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); + + }; + + this.getPixelRatio = function () { + + return _pixelRatio; + + }; + + this.setPixelRatio = function ( value ) { + + if ( value === undefined ) return; + + _pixelRatio = value; + + this.setSize( _width, _height, false ); + + }; + + this.getSize = function ( target ) { + + return target.set( _width, _height ); + + }; + + this.setSize = function ( width, height, updateStyle = true ) { + + if ( xr.isPresenting ) { + + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; + + } + + _width = width; + _height = height; + + canvas.width = Math.floor( width * _pixelRatio ); + canvas.height = Math.floor( height * _pixelRatio ); + + if ( updateStyle === true ) { + + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; + + } + + this.setViewport( 0, 0, width, height ); + + }; + + this.getDrawingBufferSize = function ( target ) { + + return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + + }; + + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - let extensions, capabilities, state, info; - let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; - let programCache, materials, renderLists, renderStates, clipping, shadowMap; + _width = width; + _height = height; - let background, morphtargets, bufferRenderer, indexedBufferRenderer; + _pixelRatio = pixelRatio; - let utils, bindingStates, uniformsGroups; + canvas.width = Math.floor( width * pixelRatio ); + canvas.height = Math.floor( height * pixelRatio ); - function initGLContext() { + this.setViewport( 0, 0, width, height ); - extensions = new WebGLExtensions( _gl ); + }; - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + this.getCurrentViewport = function ( target ) { - extensions.init( capabilities ); + return target.copy( _currentViewport ); - utils = new WebGLUtils( _gl, extensions, capabilities ); + }; - state = new WebGLState( _gl, extensions, capabilities ); + this.getViewport = function ( target ) { - info = new WebGLInfo(); - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); - cubemaps = new WebGLCubeMaps( _this ); - cubeuvmaps = new WebGLCubeUVMaps( _this ); - attributes = new WebGLAttributes( _gl, capabilities ); - bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); - geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); - objects = new WebGLObjects( _gl, geometries, attributes, info ); - morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); - clipping = new WebGLClipping( properties ); - programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); - materials = new WebGLMaterials( _this, properties ); - renderLists = new WebGLRenderLists(); - renderStates = new WebGLRenderStates( extensions, capabilities ); - background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, _premultipliedAlpha ); - shadowMap = new WebGLShadowMap( _this, objects, capabilities ); - uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); + return target.copy( _viewport ); - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); + }; - info.programs = programCache.programs; + this.setViewport = function ( x, y, width, height ) { - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.shadowMap = shadowMap; - _this.state = state; - _this.info = info; + if ( x.isVector4 ) { - } + _viewport.set( x.x, x.y, x.z, x.w ); - initGLContext(); + } else { - // xr + _viewport.set( x, y, width, height ); - const xr = new WebXRManager( _this, _gl ); + } - this.xr = xr; + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); - // API + }; - this.getContext = function () { + this.getScissor = function ( target ) { - return _gl; + return target.copy( _scissor ); - }; + }; - this.getContextAttributes = function () { + this.setScissor = function ( x, y, width, height ) { - return _gl.getContextAttributes(); + if ( x.isVector4 ) { - }; + _scissor.set( x.x, x.y, x.z, x.w ); - this.forceContextLoss = function () { + } else { - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.loseContext(); + _scissor.set( x, y, width, height ); - }; + } - this.forceContextRestore = function () { + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.restoreContext(); + }; - }; + this.getScissorTest = function () { - this.getPixelRatio = function () { + return _scissorTest; - return _pixelRatio; + }; - }; + this.setScissorTest = function ( boolean ) { - this.setPixelRatio = function ( value ) { + state.setScissorTest( _scissorTest = boolean ); - if ( value === undefined ) return; + }; - _pixelRatio = value; + this.setOpaqueSort = function ( method ) { - this.setSize( _width, _height, false ); + _opaqueSort = method; - }; + }; - this.getSize = function ( target ) { + this.setTransparentSort = function ( method ) { - return target.set( _width, _height ); + _transparentSort = method; - }; + }; - this.setSize = function ( width, height, updateStyle ) { + // Clearing - if ( xr.isPresenting ) { + this.getClearColor = function ( target ) { - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; + return target.copy( background.getClearColor() ); - } + }; - _width = width; - _height = height; + this.setClearColor = function () { - _canvas.width = Math.floor( width * _pixelRatio ); - _canvas.height = Math.floor( height * _pixelRatio ); + background.setClearColor.apply( background, arguments ); - if ( updateStyle !== false ) { + }; - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; + this.getClearAlpha = function () { - } + return background.getClearAlpha(); - this.setViewport( 0, 0, width, height ); + }; - }; + this.setClearAlpha = function () { - this.getDrawingBufferSize = function ( target ) { + background.setClearAlpha.apply( background, arguments ); - return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + }; - }; + this.clear = function ( color = true, depth = true, stencil = true ) { - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + let bits = 0; - _width = width; - _height = height; + if ( color ) { - _pixelRatio = pixelRatio; + // check if we're trying to clear an integer target + let isIntegerFormat = false; + if ( _currentRenderTarget !== null ) { - _canvas.width = Math.floor( width * pixelRatio ); - _canvas.height = Math.floor( height * pixelRatio ); + const targetFormat = _currentRenderTarget.texture.format; + isIntegerFormat = targetFormat === RGBAIntegerFormat || + targetFormat === RGIntegerFormat || + targetFormat === RedIntegerFormat; - this.setViewport( 0, 0, width, height ); + } - }; + // use the appropriate clear functions to clear the target if it's a signed + // or unsigned integer target + if ( isIntegerFormat ) { - this.getCurrentViewport = function ( target ) { + const targetType = _currentRenderTarget.texture.type; + const isUnsignedType = targetType === UnsignedByteType || + targetType === UnsignedIntType || + targetType === UnsignedShortType || + targetType === UnsignedInt248Type || + targetType === UnsignedShort4444Type || + targetType === UnsignedShort5551Type; - return target.copy( _currentViewport ); + const clearColor = background.getClearColor(); + const a = background.getClearAlpha(); + const r = clearColor.r; + const g = clearColor.g; + const b = clearColor.b; - }; + const __webglFramebuffer = properties.get( _currentRenderTarget ).__webglFramebuffer; - this.getViewport = function ( target ) { + if ( isUnsignedType ) { - return target.copy( _viewport ); + uintClearColor[ 0 ] = r; + uintClearColor[ 1 ] = g; + uintClearColor[ 2 ] = b; + uintClearColor[ 3 ] = a; + _gl.clearBufferuiv( _gl.COLOR, __webglFramebuffer, uintClearColor ); - }; + } else { - this.setViewport = function ( x, y, width, height ) { + intClearColor[ 0 ] = r; + intClearColor[ 1 ] = g; + intClearColor[ 2 ] = b; + intClearColor[ 3 ] = a; + _gl.clearBufferiv( _gl.COLOR, __webglFramebuffer, intClearColor ); - if ( x.isVector4 ) { + } - _viewport.set( x.x, x.y, x.z, x.w ); + } else { - } else { + bits |= _gl.COLOR_BUFFER_BIT; - _viewport.set( x, y, width, height ); + } - } + } - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); + if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( stencil ) bits |= _gl.STENCIL_BUFFER_BIT; - }; + _gl.clear( bits ); - this.getScissor = function ( target ) { + }; - return target.copy( _scissor ); + this.clearColor = function () { - }; + this.clear( true, false, false ); - this.setScissor = function ( x, y, width, height ) { + }; - if ( x.isVector4 ) { + this.clearDepth = function () { - _scissor.set( x.x, x.y, x.z, x.w ); + this.clear( false, true, false ); - } else { + }; - _scissor.set( x, y, width, height ); + this.clearStencil = function () { - } + this.clear( false, false, true ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); + }; - }; + // - this.getScissorTest = function () { + this.dispose = function () { - return _scissorTest; + canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - }; + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); - this.setScissorTest = function ( boolean ) { + xr.dispose(); - state.setScissorTest( _scissorTest = boolean ); + xr.removeEventListener( 'sessionstart', onXRSessionStart ); + xr.removeEventListener( 'sessionend', onXRSessionEnd ); - }; + if ( _transmissionRenderTarget ) { - this.setOpaqueSort = function ( method ) { + _transmissionRenderTarget.dispose(); + _transmissionRenderTarget = null; - _opaqueSort = method; + } - }; + animation.stop(); - this.setTransparentSort = function ( method ) { + }; - _transparentSort = method; + // Events - }; + function onContextLost( event ) { - // Clearing + event.preventDefault(); - this.getClearColor = function ( target ) { + console.log( 'THREE.WebGLRenderer: Context Lost.' ); - return target.copy( background.getClearColor() ); + _isContextLost = true; - }; + } - this.setClearColor = function () { + function onContextRestore( /* event */ ) { - background.setClearColor.apply( background, arguments ); + console.log( 'THREE.WebGLRenderer: Context Restored.' ); - }; + _isContextLost = false; - this.getClearAlpha = function () { + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; - return background.getClearAlpha(); + initGLContext(); - }; + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; - this.setClearAlpha = function () { + } - background.setClearAlpha.apply( background, arguments ); + function onContextCreationError( event ) { - }; + console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); - this.clear = function ( color = true, depth = true, stencil = true ) { + } - let bits = 0; + function onMaterialDispose( event ) { - if ( color ) bits |= 16384; - if ( depth ) bits |= 256; - if ( stencil ) bits |= 1024; + const material = event.target; - _gl.clear( bits ); + material.removeEventListener( 'dispose', onMaterialDispose ); - }; + deallocateMaterial( material ); - this.clearColor = function () { + } - this.clear( true, false, false ); + // Buffer deallocation - }; + function deallocateMaterial( material ) { - this.clearDepth = function () { + releaseMaterialProgramReferences( material ); - this.clear( false, true, false ); + properties.remove( material ); - }; + } - this.clearStencil = function () { - this.clear( false, false, true ); + function releaseMaterialProgramReferences( material ) { - }; + const programs = properties.get( material ).programs; - // + if ( programs !== undefined ) { - this.dispose = function () { + programs.forEach( function ( program ) { - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + programCache.releaseProgram( program ); - renderLists.dispose(); - renderStates.dispose(); - properties.dispose(); - cubemaps.dispose(); - cubeuvmaps.dispose(); - objects.dispose(); - bindingStates.dispose(); - uniformsGroups.dispose(); - programCache.dispose(); + } ); - xr.dispose(); + if ( material.isShaderMaterial ) { - xr.removeEventListener( 'sessionstart', onXRSessionStart ); - xr.removeEventListener( 'sessionend', onXRSessionEnd ); + programCache.releaseShaderCache( material ); - if ( _transmissionRenderTarget ) { + } - _transmissionRenderTarget.dispose(); - _transmissionRenderTarget = null; + } } - animation.stop(); + // Buffer rendering - }; + this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { - // Events + if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) - function onContextLost( event ) { + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); - event.preventDefault(); + const program = setProgram( camera, scene, geometry, material, object ); - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + state.setMaterial( material, frontFaceCW ); - _isContextLost = true; + // - } + let index = geometry.index; + let rangeFactor = 1; - function onContextRestore( /* event */ ) { + if ( material.wireframe === true ) { - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + index = geometries.getWireframeAttribute( geometry ); + rangeFactor = 2; - _isContextLost = false; + } - const infoAutoReset = info.autoReset; - const shadowMapEnabled = shadowMap.enabled; - const shadowMapAutoUpdate = shadowMap.autoUpdate; - const shadowMapNeedsUpdate = shadowMap.needsUpdate; - const shadowMapType = shadowMap.type; + // - initGLContext(); + const drawRange = geometry.drawRange; + const position = geometry.attributes.position; - info.autoReset = infoAutoReset; - shadowMap.enabled = shadowMapEnabled; - shadowMap.autoUpdate = shadowMapAutoUpdate; - shadowMap.needsUpdate = shadowMapNeedsUpdate; - shadowMap.type = shadowMapType; + let drawStart = drawRange.start * rangeFactor; + let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; - } + if ( group !== null ) { - function onContextCreationError( event ) { + drawStart = Math.max( drawStart, group.start * rangeFactor ); + drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); - console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); + } - } + if ( index !== null ) { - function onMaterialDispose( event ) { + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, index.count ); - const material = event.target; + } else if ( position !== undefined && position !== null ) { - material.removeEventListener( 'dispose', onMaterialDispose ); + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, position.count ); - deallocateMaterial( material ); + } - } + const drawCount = drawEnd - drawStart; - // Buffer deallocation + if ( drawCount < 0 || drawCount === Infinity ) return; - function deallocateMaterial( material ) { + // - releaseMaterialProgramReferences( material ); + bindingStates.setup( object, material, program, geometry, index ); - properties.remove( material ); + let attribute; + let renderer = bufferRenderer; - } + if ( index !== null ) { + attribute = attributes.get( index ); - function releaseMaterialProgramReferences( material ) { + renderer = indexedBufferRenderer; + renderer.setIndex( attribute ); - const programs = properties.get( material ).programs; + } - if ( programs !== undefined ) { + // - programs.forEach( function ( program ) { + if ( object.isMesh ) { - programCache.releaseProgram( program ); + if ( material.wireframe === true ) { - } ); + state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); + renderer.setMode( _gl.LINES ); - if ( material.isShaderMaterial ) { + } else { - programCache.releaseShaderCache( material ); + renderer.setMode( _gl.TRIANGLES ); - } + } - } + } else if ( object.isLine ) { - } + let lineWidth = material.linewidth; - // Buffer rendering + if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { + state.setLineWidth( lineWidth * getTargetPixelRatio() ); - if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) + if ( object.isLineSegments ) { - const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + renderer.setMode( _gl.LINES ); - const program = setProgram( camera, scene, geometry, material, object ); + } else if ( object.isLineLoop ) { - state.setMaterial( material, frontFaceCW ); + renderer.setMode( _gl.LINE_LOOP ); - // + } else { - let index = geometry.index; - let rangeFactor = 1; + renderer.setMode( _gl.LINE_STRIP ); - if ( material.wireframe === true ) { + } - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; + } else if ( object.isPoints ) { - } + renderer.setMode( _gl.POINTS ); - // + } else if ( object.isSprite ) { - const drawRange = geometry.drawRange; - const position = geometry.attributes.position; + renderer.setMode( _gl.TRIANGLES ); - let drawStart = drawRange.start * rangeFactor; - let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; + } - if ( group !== null ) { + if ( object.isInstancedMesh ) { - drawStart = Math.max( drawStart, group.start * rangeFactor ); - drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); + renderer.renderInstances( drawStart, drawCount, object.count ); - } + } else if ( geometry.isInstancedBufferGeometry ) { - if ( index !== null ) { + const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; + const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, index.count ); + renderer.renderInstances( drawStart, drawCount, instanceCount ); - } else if ( position !== undefined && position !== null ) { + } else { - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, position.count ); + renderer.render( drawStart, drawCount ); - } + } - const drawCount = drawEnd - drawStart; + }; - if ( drawCount < 0 || drawCount === Infinity ) return; + // Compile - // + this.compile = function ( scene, camera ) { - bindingStates.setup( object, material, program, geometry, index ); + function prepare( material, scene, object ) { - let attribute; - let renderer = bufferRenderer; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - if ( index !== null ) { + material.side = BackSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - attribute = attributes.get( index ); + material.side = FrontSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); + material.side = DoubleSide; - } + } else { - // + getProgram( material, scene, object ); - if ( object.isMesh ) { + } - if ( material.wireframe === true ) { + } - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( 1 ); + currentRenderState = renderStates.get( scene ); + currentRenderState.init(); - } else { + renderStateStack.push( currentRenderState ); - renderer.setMode( 4 ); + scene.traverseVisible( function ( object ) { - } + if ( object.isLight && object.layers.test( camera.layers ) ) { - } else if ( object.isLine ) { + currentRenderState.pushLight( object ); - let lineWidth = material.linewidth; + if ( object.castShadow ) { - if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material + currentRenderState.pushShadow( object ); - state.setLineWidth( lineWidth * getTargetPixelRatio() ); + } - if ( object.isLineSegments ) { + } - renderer.setMode( 1 ); + } ); - } else if ( object.isLineLoop ) { + currentRenderState.setupLights( _this.useLegacyLights ); - renderer.setMode( 2 ); + scene.traverse( function ( object ) { - } else { + const material = object.material; - renderer.setMode( 3 ); + if ( material ) { - } + if ( Array.isArray( material ) ) { - } else if ( object.isPoints ) { + for ( let i = 0; i < material.length; i ++ ) { - renderer.setMode( 0 ); + const material2 = material[ i ]; - } else if ( object.isSprite ) { + prepare( material2, scene, object ); - renderer.setMode( 4 ); + } - } + } else { - if ( object.isInstancedMesh ) { + prepare( material, scene, object ); - renderer.renderInstances( drawStart, drawCount, object.count ); + } - } else if ( geometry.isInstancedBufferGeometry ) { + } - const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; - const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); + } ); - renderer.renderInstances( drawStart, drawCount, instanceCount ); + renderStateStack.pop(); + currentRenderState = null; - } else { + }; - renderer.render( drawStart, drawCount ); + // Animation Loop - } + let onAnimationFrameCallback = null; - }; + function onAnimationFrame( time ) { - // Compile + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); - this.compile = function ( scene, camera ) { + } - function prepare( material, scene, object ) { + function onXRSessionStart() { - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + animation.stop(); - material.side = BackSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + } - material.side = FrontSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + function onXRSessionEnd() { - material.side = DoubleSide; + animation.start(); - } else { + } - getProgram( material, scene, object ); + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); - } + if ( typeof self !== 'undefined' ) animation.setContext( self ); - } + this.setAnimationLoop = function ( callback ) { - currentRenderState = renderStates.get( scene ); - currentRenderState.init(); + onAnimationFrameCallback = callback; + xr.setAnimationLoop( callback ); - renderStateStack.push( currentRenderState ); + ( callback === null ) ? animation.stop() : animation.start(); - scene.traverseVisible( function ( object ) { + }; - if ( object.isLight && object.layers.test( camera.layers ) ) { + xr.addEventListener( 'sessionstart', onXRSessionStart ); + xr.addEventListener( 'sessionend', onXRSessionEnd ); - currentRenderState.pushLight( object ); + // Rendering - if ( object.castShadow ) { + this.render = function ( scene, camera ) { - currentRenderState.pushShadow( object ); + if ( camera !== undefined && camera.isCamera !== true ) { - } + console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + return; } - } ); + if ( _isContextLost === true ) return; - currentRenderState.setupLights( _this.physicallyCorrectLights ); + // update scene graph - scene.traverse( function ( object ) { + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); - const material = object.material; + // update camera matrices and frustum - if ( material ) { + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - if ( Array.isArray( material ) ) { + if ( xr.enabled === true && xr.isPresenting === true ) { - for ( let i = 0; i < material.length; i ++ ) { + camera = xr.updateCameraXR( camera ); // use XR camera for rendering - const material2 = material[ i ]; + } - prepare( material2, scene, object ); + // + if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); - } + currentRenderState = renderStates.get( scene, renderStateStack.length ); + currentRenderState.init(); - } else { + renderStateStack.push( currentRenderState ); - prepare( material, scene, object ); + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix ); - } + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); - } + currentRenderList = renderLists.get( scene, renderListStack.length ); + currentRenderList.init(); - } ); + renderListStack.push( currentRenderList ); - renderStateStack.pop(); - currentRenderState = null; + projectObject( scene, camera, 0, _this.sortObjects ); - }; + currentRenderList.finish(); - // Animation Loop + if ( _this.sortObjects === true ) { - let onAnimationFrameCallback = null; + currentRenderList.sort( _opaqueSort, _transparentSort ); - function onAnimationFrame( time ) { + } - if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); + // - } + if ( _clippingEnabled === true ) clipping.beginShadows(); - function onXRSessionStart() { + const shadowsArray = currentRenderState.state.shadowsArray; - animation.stop(); + shadowMap.render( shadowsArray, scene, camera ); - } + if ( _clippingEnabled === true ) clipping.endShadows(); - function onXRSessionEnd() { + // - animation.start(); + if ( this.info.autoReset === true ) this.info.reset(); - } + this.info.render.frame ++; - const animation = new WebGLAnimation(); - animation.setAnimationLoop( onAnimationFrame ); + // - if ( typeof self !== 'undefined' ) animation.setContext( self ); + background.render( currentRenderList, scene ); - this.setAnimationLoop = function ( callback ) { + // render scene - onAnimationFrameCallback = callback; - xr.setAnimationLoop( callback ); + currentRenderState.setupLights( _this.useLegacyLights ); - ( callback === null ) ? animation.stop() : animation.start(); + if ( camera.isArrayCamera ) { - }; + const cameras = camera.cameras; - xr.addEventListener( 'sessionstart', onXRSessionStart ); - xr.addEventListener( 'sessionend', onXRSessionEnd ); + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - // Rendering + const camera2 = cameras[ i ]; - this.render = function ( scene, camera ) { + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - if ( camera !== undefined && camera.isCamera !== true ) { + } - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; + } else { - } + renderScene( currentRenderList, scene, camera ); - if ( _isContextLost === true ) return; + } - // update scene graph + // - if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); + if ( _currentRenderTarget !== null ) { - // update camera matrices and frustum + // resolve multisample renderbuffers to a single-sample texture if necessary - if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); + textures.updateMultisampleRenderTarget( _currentRenderTarget ); - if ( xr.enabled === true && xr.isPresenting === true ) { + // Generate mipmap if we're using any kind of mipmap filtering - if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); + textures.updateRenderTargetMipmap( _currentRenderTarget ); - camera = xr.getCamera(); // use XR camera for rendering + } - } + // - // - if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); + if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); - currentRenderState = renderStates.get( scene, renderStateStack.length ); - currentRenderState.init(); + // _gl.finish(); - renderStateStack.push( currentRenderState ); + bindingStates.resetDefaultState(); + _currentMaterialId = - 1; + _currentCamera = null; - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromProjectionMatrix( _projScreenMatrix ); + renderStateStack.pop(); - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); + if ( renderStateStack.length > 0 ) { - currentRenderList = renderLists.get( scene, renderListStack.length ); - currentRenderList.init(); + currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; - renderListStack.push( currentRenderList ); + } else { - projectObject( scene, camera, 0, _this.sortObjects ); + currentRenderState = null; - currentRenderList.finish(); + } - if ( _this.sortObjects === true ) { + renderListStack.pop(); - currentRenderList.sort( _opaqueSort, _transparentSort ); + if ( renderListStack.length > 0 ) { - } + currentRenderList = renderListStack[ renderListStack.length - 1 ]; - // + } else { - if ( _clippingEnabled === true ) clipping.beginShadows(); + currentRenderList = null; - const shadowsArray = currentRenderState.state.shadowsArray; + } - shadowMap.render( shadowsArray, scene, camera ); + }; - if ( _clippingEnabled === true ) clipping.endShadows(); + function projectObject( object, camera, groupOrder, sortObjects ) { - // + if ( object.visible === false ) return; - if ( this.info.autoReset === true ) this.info.reset(); + const visible = object.layers.test( camera.layers ); - // + if ( visible ) { - background.render( currentRenderList, scene ); + if ( object.isGroup ) { - // render scene + groupOrder = object.renderOrder; - currentRenderState.setupLights( _this.physicallyCorrectLights ); + } else if ( object.isLOD ) { - if ( camera.isArrayCamera ) { + if ( object.autoUpdate === true ) object.update( camera ); - const cameras = camera.cameras; + } else if ( object.isLight ) { - for ( let i = 0, l = cameras.length; i < l; i ++ ) { + currentRenderState.pushLight( object ); - const camera2 = cameras[ i ]; + if ( object.castShadow ) { - renderScene( currentRenderList, scene, camera2, camera2.viewport ); + currentRenderState.pushShadow( object ); - } + } - } else { + } else if ( object.isSprite ) { - renderScene( currentRenderList, scene, camera ); + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - } + if ( sortObjects ) { - // + _vector3.setFromMatrixPosition( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - if ( _currentRenderTarget !== null ) { + } - // resolve multisample renderbuffers to a single-sample texture if necessary + const geometry = objects.update( object ); + const material = object.material; - textures.updateMultisampleRenderTarget( _currentRenderTarget ); + if ( material.visible ) { - // Generate mipmap if we're using any kind of mipmap filtering + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); - textures.updateRenderTargetMipmap( _currentRenderTarget ); + } - } + } - // + } else if ( object.isMesh || object.isLine || object.isPoints ) { - if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - // _gl.finish(); + if ( object.isSkinnedMesh ) { - bindingStates.resetDefaultState(); - _currentMaterialId = - 1; - _currentCamera = null; + // update skeleton only once in a frame - renderStateStack.pop(); + if ( object.skeleton.frame !== info.render.frame ) { - if ( renderStateStack.length > 0 ) { + object.skeleton.update(); + object.skeleton.frame = info.render.frame; - currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; + } - } else { + } - currentRenderState = null; + const geometry = objects.update( object ); + const material = object.material; - } + if ( sortObjects ) { - renderListStack.pop(); + if ( object.boundingSphere !== undefined ) { - if ( renderListStack.length > 0 ) { + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + _vector3.copy( object.boundingSphere.center ); - currentRenderList = renderListStack[ renderListStack.length - 1 ]; + } else { - } else { + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _vector3.copy( geometry.boundingSphere.center ); - currentRenderList = null; + } - } + _vector3 + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); - }; + } - function projectObject( object, camera, groupOrder, sortObjects ) { + if ( Array.isArray( material ) ) { - if ( object.visible === false ) return; + const groups = geometry.groups; - const visible = object.layers.test( camera.layers ); + for ( let i = 0, l = groups.length; i < l; i ++ ) { - if ( visible ) { + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; - if ( object.isGroup ) { + if ( groupMaterial && groupMaterial.visible ) { - groupOrder = object.renderOrder; + currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); - } else if ( object.isLOD ) { + } - if ( object.autoUpdate === true ) object.update( camera ); + } - } else if ( object.isLight ) { + } else if ( material.visible ) { - currentRenderState.pushLight( object ); + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); - if ( object.castShadow ) { + } - currentRenderState.pushShadow( object ); + } } - } else if ( object.isSprite ) { + } - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + const children = object.children; - if ( sortObjects ) { + for ( let i = 0, l = children.length; i < l; i ++ ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + projectObject( children[ i ], camera, groupOrder, sortObjects ); - } + } - const geometry = objects.update( object ); - const material = object.material; + } - if ( material.visible ) { + function renderScene( currentRenderList, scene, camera, viewport ) { - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; + const transparentObjects = currentRenderList.transparent; - } + currentRenderState.setupLightsView( camera ); - } + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - } else if ( object.isMesh || object.isLine || object.isPoints ) { + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - if ( object.isSkinnedMesh ) { + if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); - // update skeleton only once in a frame + if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); + if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); + if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); - if ( object.skeleton.frame !== info.render.frame ) { + // Ensure depth buffer writing is enabled so it can be cleared on next render - object.skeleton.update(); - object.skeleton.frame = info.render.frame; + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); - } + state.setPolygonOffset( false ); - } + } - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { - if ( sortObjects ) { + const isWebGL2 = capabilities.isWebGL2; - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + if ( _transmissionRenderTarget === null ) { - } + _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { + generateMipmaps: true, + type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: ( isWebGL2 && antialias === true ) ? 4 : 0 + } ); - const geometry = objects.update( object ); - const material = object.material; + // debug - if ( Array.isArray( material ) ) { + /* + const geometry = new PlaneGeometry(); + const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); - const groups = geometry.groups; + const mesh = new Mesh( geometry, material ); + scene.add( mesh ); + */ - for ( let i = 0, l = groups.length; i < l; i ++ ) { + } - const group = groups[ i ]; - const groupMaterial = material[ group.materialIndex ]; + _this.getDrawingBufferSize( _vector2 ); - if ( groupMaterial && groupMaterial.visible ) { + if ( isWebGL2 ) { - currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); + _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); - } + } else { - } + _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); - } else if ( material.visible ) { + } - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + // - } + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget( _transmissionRenderTarget ); - } + _this.getClearColor( _currentClearColor ); + _currentClearAlpha = _this.getClearAlpha(); + if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); - } + _this.clear(); - } + // Turn off the features which can affect the frag color for opaque objects pass. + // Otherwise they are applied twice in opaque objects pass and transmission objects pass. + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; - const children = object.children; + renderObjects( opaqueObjects, scene, camera ); - for ( let i = 0, l = children.length; i < l; i ++ ) { + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - projectObject( children[ i ], camera, groupOrder, sortObjects ); + let renderTargetNeedsUpdate = false; - } + for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { - } + const renderItem = transmissiveObjects[ i ]; - function renderScene( currentRenderList, scene, camera, viewport ) { + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = renderItem.material; + const group = renderItem.group; - const opaqueObjects = currentRenderList.opaque; - const transmissiveObjects = currentRenderList.transmissive; - const transparentObjects = currentRenderList.transparent; + if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { - currentRenderState.setupLightsView( camera ); + const currentSide = material.side; - if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); + material.side = BackSide; + material.needsUpdate = true; - if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, scene, camera ); + renderObject( object, scene, camera, geometry, material, group ); - if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); + material.side = currentSide; + material.needsUpdate = true; - if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); - if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); - if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); + renderTargetNeedsUpdate = true; - // Ensure depth buffer writing is enabled so it can be cleared on next render + } - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); + } - state.setPolygonOffset( false ); + if ( renderTargetNeedsUpdate === true ) { - } + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - function renderTransmissionPass( opaqueObjects, scene, camera ) { + } - const isWebGL2 = capabilities.isWebGL2; + _this.setRenderTarget( currentRenderTarget ); - if ( _transmissionRenderTarget === null ) { + _this.setClearColor( _currentClearColor, _currentClearAlpha ); - _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { - generateMipmaps: true, - type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, - minFilter: LinearMipmapLinearFilter, - samples: ( isWebGL2 && _antialias === true ) ? 4 : 0 - } ); + _this.toneMapping = currentToneMapping; } - _this.getDrawingBufferSize( _vector2 ); - - if ( isWebGL2 ) { + function renderObjects( renderList, scene, camera ) { - _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - } else { + for ( let i = 0, l = renderList.length; i < l; i ++ ) { - _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); + const renderItem = renderList[ i ]; - } + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = overrideMaterial === null ? renderItem.material : overrideMaterial; + const group = renderItem.group; - // + if ( object.layers.test( camera.layers ) ) { - const currentRenderTarget = _this.getRenderTarget(); - _this.setRenderTarget( _transmissionRenderTarget ); - _this.clear(); + renderObject( object, scene, camera, geometry, material, group ); - // Turn off the features which can affect the frag color for opaque objects pass. - // Otherwise they are applied twice in opaque objects pass and transmission objects pass. - const currentToneMapping = _this.toneMapping; - _this.toneMapping = NoToneMapping; + } - renderObjects( opaqueObjects, scene, camera ); + } - _this.toneMapping = currentToneMapping; + } - textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); - textures.updateRenderTargetMipmap( _transmissionRenderTarget ); + function renderObject( object, scene, camera, geometry, material, group ) { - _this.setRenderTarget( currentRenderTarget ); + object.onBeforeRender( _this, scene, camera, geometry, material, group ); - } + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - function renderObjects( renderList, scene, camera ) { + material.onBeforeRender( _this, scene, camera, geometry, object, group ); - const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - for ( let i = 0, l = renderList.length; i < l; i ++ ) { + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - const renderItem = renderList[ i ]; + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - const object = renderItem.object; - const geometry = renderItem.geometry; - const material = overrideMaterial === null ? renderItem.material : overrideMaterial; - const group = renderItem.group; + material.side = DoubleSide; - if ( object.layers.test( camera.layers ) ) { + } else { - renderObject( object, scene, camera, geometry, material, group ); + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); } + object.onAfterRender( _this, scene, camera, geometry, material, group ); + } - } + function getProgram( material, scene, object ) { - function renderObject( object, scene, camera, geometry, material, group ) { + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + const materialProperties = properties.get( material ); - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; - material.onBeforeRender( _this, scene, camera, geometry, object, group ); + const lightsStateVersion = lights.state.version; - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); + const programCacheKey = programCache.getProgramCacheKey( parameters ); - material.side = BackSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + let programs = materialProperties.programs; - material.side = FrontSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - material.side = DoubleSide; + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); - } else { + if ( programs === undefined ) { - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + // new material - } + material.addEventListener( 'dispose', onMaterialDispose ); - object.onAfterRender( _this, scene, camera, geometry, material, group ); + programs = new Map(); + materialProperties.programs = programs; - } + } - function getProgram( material, scene, object ) { + let program = programs.get( programCacheKey ); - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + if ( program !== undefined ) { - const materialProperties = properties.get( material ); + // early out if program and light state is identical - const lights = currentRenderState.state.lights; - const shadowsArray = currentRenderState.state.shadowsArray; + if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { - const lightsStateVersion = lights.state.version; + updateCommonMaterialProperties( material, parameters ); - const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); - const programCacheKey = programCache.getProgramCacheKey( parameters ); + return program; - let programs = materialProperties.programs; + } - // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change + } else { - materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; - materialProperties.fog = scene.fog; - materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + parameters.uniforms = programCache.getUniforms( material ); - if ( programs === undefined ) { + material.onBuild( object, parameters, _this ); - // new material + material.onBeforeCompile( parameters, _this ); - material.addEventListener( 'dispose', onMaterialDispose ); + program = programCache.acquireProgram( parameters, programCacheKey ); + programs.set( programCacheKey, program ); - programs = new Map(); - materialProperties.programs = programs; + materialProperties.uniforms = parameters.uniforms; - } + } - let program = programs.get( programCacheKey ); + const uniforms = materialProperties.uniforms; - if ( program !== undefined ) { + if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { - // early out if program and light state is identical + uniforms.clippingPlanes = clipping.uniform; - if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { + } - updateCommonMaterialProperties( material, parameters ); + updateCommonMaterialProperties( material, parameters ); - return program; + // store the light setup it was created for - } + materialProperties.needsLights = materialNeedsLights( material ); + materialProperties.lightsStateVersion = lightsStateVersion; - } else { + if ( materialProperties.needsLights ) { + + // wire up the material to this renderer's lighting state - parameters.uniforms = programCache.getUniforms( material ); + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.lightProbe.value = lights.state.probe; + uniforms.directionalLights.value = lights.state.directional; + uniforms.directionalLightShadows.value = lights.state.directionalShadow; + uniforms.spotLights.value = lights.state.spot; + uniforms.spotLightShadows.value = lights.state.spotShadow; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.ltc_1.value = lights.state.rectAreaLTC1; + uniforms.ltc_2.value = lights.state.rectAreaLTC2; + uniforms.pointLights.value = lights.state.point; + uniforms.pointLightShadows.value = lights.state.pointShadow; + uniforms.hemisphereLights.value = lights.state.hemi; - material.onBuild( object, parameters, _this ); + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; + uniforms.spotLightMap.value = lights.state.spotLightMap; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + // TODO (abelnation): add area lights shadow info to uniforms + + } - material.onBeforeCompile( parameters, _this ); + const progUniforms = program.getUniforms(); + const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); - program = programCache.acquireProgram( parameters, programCacheKey ); - programs.set( programCacheKey, program ); + materialProperties.currentProgram = program; + materialProperties.uniformsList = uniformsList; - materialProperties.uniforms = parameters.uniforms; + return program; } - const uniforms = materialProperties.uniforms; + function updateCommonMaterialProperties( material, parameters ) { - if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { + const materialProperties = properties.get( material ); - uniforms.clippingPlanes = clipping.uniform; + materialProperties.outputColorSpace = parameters.outputColorSpace; + materialProperties.instancing = parameters.instancing; + materialProperties.skinning = parameters.skinning; + materialProperties.morphTargets = parameters.morphTargets; + materialProperties.morphNormals = parameters.morphNormals; + materialProperties.morphColors = parameters.morphColors; + materialProperties.morphTargetsCount = parameters.morphTargetsCount; + materialProperties.numClippingPlanes = parameters.numClippingPlanes; + materialProperties.numIntersection = parameters.numClipIntersection; + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; } - updateCommonMaterialProperties( material, parameters ); + function setProgram( camera, scene, geometry, material, object ) { - // store the light setup it was created for + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - materialProperties.needsLights = materialNeedsLights( material ); - materialProperties.lightsStateVersion = lightsStateVersion; + textures.resetTextureUnits(); - if ( materialProperties.needsLights ) { + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); + const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); + const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; + const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); + const morphTargets = !! geometry.morphAttributes.position; + const morphNormals = !! geometry.morphAttributes.normal; + const morphColors = !! geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; - // wire up the material to this renderer's lighting state + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.lightProbe.value = lights.state.probe; - uniforms.directionalLights.value = lights.state.directional; - uniforms.directionalLightShadows.value = lights.state.directionalShadow; - uniforms.spotLights.value = lights.state.spot; - uniforms.spotLightShadows.value = lights.state.spotShadow; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.ltc_1.value = lights.state.rectAreaLTC1; - uniforms.ltc_2.value = lights.state.rectAreaLTC2; - uniforms.pointLights.value = lights.state.point; - uniforms.pointLightShadows.value = lights.state.pointShadow; - uniforms.hemisphereLights.value = lights.state.hemi; + const materialProperties = properties.get( material ); + const lights = currentRenderState.state.lights; - uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; - uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; - uniforms.spotShadowMap.value = lights.state.spotShadowMap; - uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; - uniforms.spotLightMap.value = lights.state.spotLightMap; - uniforms.pointShadowMap.value = lights.state.pointShadowMap; - uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; - // TODO (abelnation): add area lights shadow info to uniforms + if ( _clippingEnabled === true ) { - } + if ( _localClippingEnabled === true || camera !== _currentCamera ) { - const progUniforms = program.getUniforms(); - const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); + const useCache = + camera === _currentCamera && + material.id === _currentMaterialId; - materialProperties.currentProgram = program; - materialProperties.uniformsList = uniformsList; + // we might want to call this function with some ClippingGroup + // object instead of the material, once it becomes feasible + // (#8465, #8379) + clipping.setState( material, camera, useCache ); - return program; + } - } + } - function updateCommonMaterialProperties( material, parameters ) { + // - const materialProperties = properties.get( material ); + let needsProgramChange = false; - materialProperties.outputEncoding = parameters.outputEncoding; - materialProperties.instancing = parameters.instancing; - materialProperties.skinning = parameters.skinning; - materialProperties.morphTargets = parameters.morphTargets; - materialProperties.morphNormals = parameters.morphNormals; - materialProperties.morphColors = parameters.morphColors; - materialProperties.morphTargetsCount = parameters.morphTargetsCount; - materialProperties.numClippingPlanes = parameters.numClippingPlanes; - materialProperties.numIntersection = parameters.numClipIntersection; - materialProperties.vertexAlphas = parameters.vertexAlphas; - materialProperties.vertexTangents = parameters.vertexTangents; - materialProperties.toneMapping = parameters.toneMapping; - materialProperties.extraProgramCacheKey = parameters.extraProgramCacheKey; + if ( material.version === materialProperties.__version ) { - } + if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { - function setProgram( camera, scene, geometry, material, object ) { + needsProgramChange = true; - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + } else if ( materialProperties.outputColorSpace !== colorSpace ) { - textures.resetTextureUnits(); + needsProgramChange = true; - const fog = scene.fog; - const environment = material.isMeshStandardMaterial ? scene.environment : null; - const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding ); - const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); - const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; - const vertexTangents = !! material.normalMap && !! geometry.attributes.tangent; - const morphTargets = !! geometry.morphAttributes.position; - const morphNormals = !! geometry.morphAttributes.normal; - const morphColors = !! geometry.morphAttributes.color; - const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; + } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + needsProgramChange = true; - const materialProperties = properties.get( material ); - const lights = currentRenderState.state.lights; + } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { - const extraProgramCacheKey = _this.extraProgramCacheKey; + needsProgramChange = true; - if ( _clippingEnabled === true ) { + } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { - if ( _localClippingEnabled === true || camera !== _currentCamera ) { + needsProgramChange = true; - const useCache = - camera === _currentCamera && - material.id === _currentMaterialId; + } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - clipping.setState( material, camera, useCache ); + needsProgramChange = true; - } + } else if ( materialProperties.envMap !== envMap ) { - } + needsProgramChange = true; - // + } else if ( material.fog === true && materialProperties.fog !== fog ) { - let needsProgramChange = false; + needsProgramChange = true; - if ( material.version === materialProperties.__version ) { + } else if ( materialProperties.numClippingPlanes !== undefined && + ( materialProperties.numClippingPlanes !== clipping.numPlanes || + materialProperties.numIntersection !== clipping.numIntersection ) ) { - if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { - } else if ( materialProperties.outputEncoding !== encoding ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.vertexTangents !== vertexTangents ) { - } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.morphTargets !== morphTargets ) { - } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.morphNormals !== morphNormals ) { - } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.morphColors !== morphColors ) { - } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.toneMapping !== toneMapping ) { - } else if ( materialProperties.envMap !== envMap ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { - } else if ( material.fog === true && materialProperties.fog !== fog ) { + needsProgramChange = true; - needsProgramChange = true; + } - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== clipping.numPlanes || - materialProperties.numIntersection !== clipping.numIntersection ) ) { + } else { needsProgramChange = true; + materialProperties.__version = material.version; - } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { + } - needsProgramChange = true; + // - } else if ( materialProperties.vertexTangents !== vertexTangents ) { + let program = materialProperties.currentProgram; - needsProgramChange = true; + if ( needsProgramChange === true ) { - } else if ( materialProperties.morphTargets !== morphTargets ) { + program = getProgram( material, scene, object ); - needsProgramChange = true; + } - } else if ( materialProperties.morphNormals !== morphNormals ) { + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; - needsProgramChange = true; + const p_uniforms = program.getUniforms(), + m_uniforms = materialProperties.uniforms; - } else if ( materialProperties.morphColors !== morphColors ) { + if ( state.useProgram( program.program ) ) { - needsProgramChange = true; + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; - } else if ( materialProperties.toneMapping !== toneMapping ) { + } - needsProgramChange = true; + if ( material.id !== _currentMaterialId ) { - } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { + _currentMaterialId = material.id; - needsProgramChange = true; + refreshMaterial = true; - } else if ( extraProgramCacheKey !== materialProperties.extraProgramCacheKey ) { + } - needsProgramChange = true; + if ( refreshProgram || _currentCamera !== camera ) { - } + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); - } else { + if ( capabilities.logarithmicDepthBuffer ) { - needsProgramChange = true; - materialProperties.__version = material.version; + p_uniforms.setValue( _gl, 'logDepthBufFC', + 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); - } + } - // + if ( _currentCamera !== camera ) { - let program = materialProperties.currentProgram; + _currentCamera = camera; - if ( needsProgramChange === true ) { + // lighting uniforms depend on the camera so enforce an update + // now, in case this material supports lights - or later, when + // the next material that does gets activated: - program = getProgram( material, scene, object ); + refreshMaterial = true; // set to true on material change + refreshLights = true; // remains set until update done - } + } - let refreshProgram = false; - let refreshMaterial = false; - let refreshLights = false; + // load material specific uniforms + // (shader material also gets them for the sake of genericity) - const p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.uniforms; + if ( material.isShaderMaterial || + material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshStandardMaterial || + material.envMap ) { - if ( state.useProgram( program.program ) ) { + const uCamPos = p_uniforms.map.cameraPosition; - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; + if ( uCamPos !== undefined ) { - } + uCamPos.setValue( _gl, + _vector3.setFromMatrixPosition( camera.matrixWorld ) ); - if ( material.id !== _currentMaterialId ) { + } - _currentMaterialId = material.id; + } - refreshMaterial = true; + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial ) { - } + p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); - if ( refreshProgram || _currentCamera !== camera ) { + } - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial || + material.isShadowMaterial || + object.isSkinnedMesh ) { - if ( capabilities.logarithmicDepthBuffer ) { + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + } } - if ( _currentCamera !== camera ) { + // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures + // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures - _currentCamera = camera; + if ( object.isSkinnedMesh ) { - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: + p_uniforms.setOptional( _gl, object, 'bindMatrix' ); + p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done + const skeleton = object.skeleton; - } + if ( skeleton ) { - // load material specific uniforms - // (shader material also gets them for the sake of genericity) + if ( capabilities.floatVertexTextures ) { - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshStandardMaterial || - material.envMap ) { + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); - const uCamPos = p_uniforms.map.cameraPosition; + p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); + p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); - if ( uCamPos !== undefined ) { + } else { + + console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + } } } - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial ) { + const morphAttributes = geometry.morphAttributes; + + if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { - p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); + morphtargets.update( object, geometry, program ); } - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.isShadowMaterial || - object.isSkinnedMesh ) { + if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); } - } + // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 - // skinning and morph target uniforms must be set even if material didn't change - // auto-setting of texture unit for bone and morph texture must go before other textures - // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures + if ( material.isMeshGouraudMaterial && material.envMap !== null ) { - if ( object.isSkinnedMesh ) { + m_uniforms.envMap.value = envMap; - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); + m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - const skeleton = object.skeleton; + } - if ( skeleton ) { + if ( refreshMaterial ) { - if ( capabilities.floatVertexTextures ) { + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); + if ( materialProperties.needsLights ) { - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); + // the current material requires lighting info - } else { + // note: all lighting uniforms are always set correctly + // they simply reference the renderer's state for their + // values + // + // use the current material's .needsUpdate flags to set + // the GL state when required - console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); + markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); } - } - - } - - const morphAttributes = geometry.morphAttributes; + // refresh uniforms common to several materials - if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { + if ( fog && material.fog === true ) { - morphtargets.update( object, geometry, material, program ); + materials.refreshFogUniforms( m_uniforms, fog ); - } + } - if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { + materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); - materialProperties.receiveShadow = object.receiveShadow; - p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - } + } - // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 + if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { - if ( material.isMeshGouraudMaterial && material.envMap !== null ) { + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + material.uniformsNeedUpdate = false; - m_uniforms.envMap.value = envMap; + } - m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; + if ( material.isSpriteMaterial ) { - } + p_uniforms.setValue( _gl, 'center', object.center ); - if ( refreshMaterial ) { + } - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); + // common matrices - if ( materialProperties.needsLights ) { + p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); + p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - // the current material requires lighting info + // UBOs - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); + const groups = material.uniformsGroups; - } + for ( let i = 0, l = groups.length; i < l; i ++ ) { - // refresh uniforms common to several materials + if ( capabilities.isWebGL2 ) { - if ( fog && material.fog === true ) { + const group = groups[ i ]; - materials.refreshFogUniforms( m_uniforms, fog ); + uniformsGroups.update( group, program ); + uniformsGroups.bind( group, program ); - } + } else { - materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); + console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + } - } + } - if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { + } - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - material.uniformsNeedUpdate = false; + return program; } - if ( material.isSpriteMaterial ) { + // If uniforms are marked as clean, they don't need to be loaded to the GPU. - p_uniforms.setValue( _gl, 'center', object.center ); + function markUniformsLightsNeedsUpdate( uniforms, value ) { - } - - // common matrices + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + uniforms.directionalLights.needsUpdate = value; + uniforms.directionalLightShadows.needsUpdate = value; + uniforms.pointLights.needsUpdate = value; + uniforms.pointLightShadows.needsUpdate = value; + uniforms.spotLights.needsUpdate = value; + uniforms.spotLightShadows.needsUpdate = value; + uniforms.rectAreaLights.needsUpdate = value; + uniforms.hemisphereLights.needsUpdate = value; - // UBOs + } - if ( material.isShaderMaterial || material.isRawShaderMaterial ) { + function materialNeedsLights( material ) { - const groups = material.uniformsGroups; + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + material.isMeshStandardMaterial || material.isShadowMaterial || + ( material.isShaderMaterial && material.lights === true ); - for ( let i = 0, l = groups.length; i < l; i ++ ) { + } - if ( capabilities.isWebGL2 ) { + this.getActiveCubeFace = function () { - const group = groups[ i ]; + return _currentActiveCubeFace; - uniformsGroups.update( group, program ); - uniformsGroups.bind( group, program ); + }; - } else { + this.getActiveMipmapLevel = function () { - console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); + return _currentActiveMipmapLevel; - } + }; - } + this.getRenderTarget = function () { - } + return _currentRenderTarget; - return program; + }; - } + this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { - // If uniforms are marked as clean, they don't need to be loaded to the GPU. + properties.get( renderTarget.texture ).__webglTexture = colorTexture; + properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; - function markUniformsLightsNeedsUpdate( uniforms, value ) { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; - uniforms.ambientLightColor.needsUpdate = value; - uniforms.lightProbe.needsUpdate = value; + if ( renderTargetProperties.__hasExternalTextures ) { - uniforms.directionalLights.needsUpdate = value; - uniforms.directionalLightShadows.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.pointLightShadows.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.spotLightShadows.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; - } + if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { - function materialNeedsLights( material ) { + // The multisample_render_to_texture extension doesn't work properly if there + // are midframe flushes and an external depth buffer. Disable use of the extension. + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { - return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || - material.isMeshStandardMaterial || material.isShadowMaterial || - ( material.isShaderMaterial && material.lights === true ); + console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); + renderTargetProperties.__useRenderToTexture = false; - } + } - this.getActiveCubeFace = function () { + } - return _currentActiveCubeFace; + } - }; + }; - this.getActiveMipmapLevel = function () { + this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { - return _currentActiveMipmapLevel; + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; - }; + }; - this.getRenderTarget = function () { + this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { - return _currentRenderTarget; + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; - }; + let useDefaultFramebuffer = true; + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; - this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { + if ( renderTarget ) { - properties.get( renderTarget.texture ).__webglTexture = colorTexture; - properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; + const renderTargetProperties = properties.get( renderTarget ); - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__hasExternalTextures = true; + if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { - if ( renderTargetProperties.__hasExternalTextures ) { + // We need to make sure to rebind the framebuffer. + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); + useDefaultFramebuffer = false; - renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; + } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { - if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { + textures.setupRenderTarget( renderTarget ); - // The multisample_render_to_texture extension doesn't work properly if there - // are midframe flushes and an external depth buffer. Disable use of the extension. - if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { + } else if ( renderTargetProperties.__hasExternalTextures ) { - console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); - renderTargetProperties.__useRenderToTexture = false; + // Color and depth texture must be rebound in order for the swapchain to update. + textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); } - } - - } - - }; + const texture = renderTarget.texture; - this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { + if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__webglFramebuffer = defaultFramebuffer; - renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; + isRenderTarget3D = true; - }; + } - this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { + const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - _currentRenderTarget = renderTarget; - _currentActiveCubeFace = activeCubeFace; - _currentActiveMipmapLevel = activeMipmapLevel; + if ( renderTarget.isWebGLCubeRenderTarget ) { - let useDefaultFramebuffer = true; - let framebuffer = null; - let isCube = false; - let isRenderTarget3D = false; + framebuffer = __webglFramebuffer[ activeCubeFace ]; + isCube = true; - if ( renderTarget ) { + } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { - const renderTargetProperties = properties.get( renderTarget ); + framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; - if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { + } else { - // We need to make sure to rebind the framebuffer. - state.bindFramebuffer( 36160, null ); - useDefaultFramebuffer = false; + framebuffer = __webglFramebuffer; - } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { + } - textures.setupRenderTarget( renderTarget ); + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; - } else if ( renderTargetProperties.__hasExternalTextures ) { + } else { - // Color and depth texture must be rebound in order for the swapchain to update. - textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); + _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); + _currentScissorTest = _scissorTest; } - const texture = renderTarget.texture; + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { - isRenderTarget3D = true; + state.drawBuffers( renderTarget, framebuffer ); } - const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); - if ( renderTarget.isWebGLCubeRenderTarget ) { + if ( isCube ) { - framebuffer = __webglFramebuffer[ activeCubeFace ]; - isCube = true; + const textureProperties = properties.get( renderTarget.texture ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); - } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { + } else if ( isRenderTarget3D ) { - framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; + const textureProperties = properties.get( renderTarget.texture ); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); - } else { + } - framebuffer = __webglFramebuffer; + _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings - } + }; - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; + this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - } else { + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); - _currentScissorTest = _scissorTest; + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; - } + } - const framebufferBound = state.bindFramebuffer( 36160, framebuffer ); + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - state.drawBuffers( renderTarget, framebuffer ); + framebuffer = framebuffer[ activeCubeFaceIndex ]; - } + } - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); + if ( framebuffer ) { - if ( isCube ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - const textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); + try { - } else if ( isRenderTarget3D ) { + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - const textureProperties = properties.get( renderTarget.texture ); - const layer = activeCubeFace || 0; - _gl.framebufferTextureLayer( 36160, 36064, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { - } + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + return; - _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings + } - }; + const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) + ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox + ! halfFloatSupportedByExt ) { - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + return; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; + } - } + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - let framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - framebuffer = framebuffer[ activeCubeFaceIndex ]; + } - } + } finally { - if ( framebuffer ) { + // restore framebuffer of current render target if necessary - state.bindFramebuffer( 36160, framebuffer ); + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - try { + } - const texture = renderTarget.texture; - const textureFormat = texture.format; - const textureType = texture.type; + } - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) { + }; - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; + this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { - } + const levelScale = Math.pow( 2, - level ); + const width = Math.floor( texture.image.width * levelScale ); + const height = Math.floor( texture.image.height * levelScale ); - const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); + textures.setTexture2D( texture, 0 ); - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! halfFloatSupportedByExt ) { + _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; + state.unbindTexture(); - } + }; - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + const width = srcTexture.image.width; + const height = srcTexture.image.height; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); + textures.setTexture2D( dstTexture, 0 ); - } + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - } finally { + if ( srcTexture.isDataTexture ) { - // restore framebuffer of current render target if necessary + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); - const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; - state.bindFramebuffer( 36160, framebuffer ); + } else { - } + if ( srcTexture.isCompressedTexture ) { - } + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); - }; + } else { - this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); - const levelScale = Math.pow( 2, - level ); - const width = Math.floor( texture.image.width * levelScale ); - const height = Math.floor( texture.image.height * levelScale ); + } - textures.setTexture2D( texture, 0 ); + } - _gl.copyTexSubImage2D( 3553, level, 0, 0, position.x, position.y, width, height ); + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); - state.unbindTexture(); + state.unbindTexture(); - }; + }; - this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { + this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { - const width = srcTexture.image.width; - const height = srcTexture.image.height; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); + if ( _this.isWebGL1Renderer ) { - textures.setTexture2D( dstTexture, 0 ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); + return; - // As another texture upload may have changed pixelStorei - // parameters, make sure they are correct for the dstTexture - _gl.pixelStorei( 37440, dstTexture.flipY ); - _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( 3317, dstTexture.unpackAlignment ); + } - if ( srcTexture.isDataTexture ) { + const width = sourceBox.max.x - sourceBox.min.x + 1; + const height = sourceBox.max.y - sourceBox.min.y + 1; + const depth = sourceBox.max.z - sourceBox.min.z + 1; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; - _gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); + if ( dstTexture.isData3DTexture ) { - } else { + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; - if ( srcTexture.isCompressedTexture ) { + } else if ( dstTexture.isDataArrayTexture ) { - _gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; } else { - _gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; } - } - - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 ); + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - state.unbindTexture(); + const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - }; + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; - this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); - if ( _this.isWebGL1Renderer ) { + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); - return; + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); - } + } else { - const width = sourceBox.max.x - sourceBox.min.x + 1; - const height = sourceBox.max.y - sourceBox.min.y + 1; - const depth = sourceBox.max.z - sourceBox.min.z + 1; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); - let glTarget; + if ( srcTexture.isCompressedArrayTexture ) { - if ( dstTexture.isData3DTexture ) { + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); + _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); - textures.setTexture3D( dstTexture, 0 ); - glTarget = 32879; + } else { - } else if ( dstTexture.isDataArrayTexture ) { + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); - textures.setTexture2DArray( dstTexture, 0 ); - glTarget = 35866; + } - } else { + } - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); - return; + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); - } + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); - _gl.pixelStorei( 37440, dstTexture.flipY ); - _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( 3317, dstTexture.unpackAlignment ); + state.unbindTexture(); - const unpackRowLen = _gl.getParameter( 3314 ); - const unpackImageHeight = _gl.getParameter( 32878 ); - const unpackSkipPixels = _gl.getParameter( 3316 ); - const unpackSkipRows = _gl.getParameter( 3315 ); - const unpackSkipImages = _gl.getParameter( 32877 ); + }; - const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; + this.initTexture = function ( texture ) { - _gl.pixelStorei( 3314, image.width ); - _gl.pixelStorei( 32878, image.height ); - _gl.pixelStorei( 3316, sourceBox.min.x ); - _gl.pixelStorei( 3315, sourceBox.min.y ); - _gl.pixelStorei( 32877, sourceBox.min.z ); + if ( texture.isCubeTexture ) { - if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { + textures.setTextureCube( texture, 0 ); - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); + } else if ( texture.isData3DTexture ) { - } else { + textures.setTexture3D( texture, 0 ); - if ( srcTexture.isCompressedArrayTexture ) { + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); - _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); + textures.setTexture2DArray( texture, 0 ); } else { - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); + textures.setTexture2D( texture, 0 ); } - } - - _gl.pixelStorei( 3314, unpackRowLen ); - _gl.pixelStorei( 32878, unpackImageHeight ); - _gl.pixelStorei( 3316, unpackSkipPixels ); - _gl.pixelStorei( 3315, unpackSkipRows ); - _gl.pixelStorei( 32877, unpackSkipImages ); - - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); + state.unbindTexture(); - state.unbindTexture(); + }; - }; + this.resetState = function () { - this.initTexture = function ( texture ) { + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; - if ( texture.isCubeTexture ) { + state.reset(); + bindingStates.reset(); - textures.setTextureCube( texture, 0 ); + }; - } else if ( texture.isData3DTexture ) { + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { - textures.setTexture3D( texture, 0 ); + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); - } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + } - textures.setTexture2DArray( texture, 0 ); + } - } else { + get physicallyCorrectLights() { // @deprecated, r150 - textures.setTexture2D( texture, 0 ); + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + return ! this.useLegacyLights; - } + } - state.unbindTexture(); + set physicallyCorrectLights( value ) { // @deprecated, r150 - }; + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + this.useLegacyLights = ! value; - this.resetState = function () { + } - _currentActiveCubeFace = 0; - _currentActiveMipmapLevel = 0; - _currentRenderTarget = null; + get outputEncoding() { // @deprecated, r152 - state.reset(); - bindingStates.reset(); + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + return this.outputColorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; - }; + } - if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + set outputEncoding( encoding ) { // @deprecated, r152 - __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + this.outputColorSpace = encoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; } @@ -29411,16 +30355,14 @@ class Scene extends Object3D { } - // @deprecated - - get autoUpdate() { + get autoUpdate() { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); return this.matrixWorldAutoUpdate; } - set autoUpdate( value ) { + set autoUpdate( value ) { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); this.matrixWorldAutoUpdate = value; @@ -29570,7 +30512,7 @@ class InterleavedBuffer { } -const _vector$6 = /*@__PURE__*/ new Vector3(); +const _vector$5 = /*@__PURE__*/ new Vector3(); class InterleavedBufferAttribute { @@ -29610,11 +30552,11 @@ class InterleavedBufferAttribute { for ( let i = 0, l = this.data.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.applyMatrix4( m ); + _vector$5.applyMatrix4( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -29626,11 +30568,11 @@ class InterleavedBufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.applyNormalMatrix( m ); + _vector$5.applyNormalMatrix( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -29642,11 +30584,11 @@ class InterleavedBufferAttribute { for ( let i = 0, l = this.count; i < l; i ++ ) { - _vector$6.fromBufferAttribute( this, i ); + _vector$5.fromBufferAttribute( this, i ); - _vector$6.transformDirection( m ); + _vector$5.transformDirection( m ); - this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); + this.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z ); } @@ -30066,7 +31008,7 @@ class Sprite extends Object3D { distance: distance, point: _intersectPoint.clone(), - uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), + uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), face: null, object: this @@ -30329,8 +31271,13 @@ const _basePosition = /*@__PURE__*/ new Vector3(); const _skinIndex = /*@__PURE__*/ new Vector4(); const _skinWeight = /*@__PURE__*/ new Vector4(); -const _vector$5 = /*@__PURE__*/ new Vector3(); -const _matrix = /*@__PURE__*/ new Matrix4(); +const _vector3 = /*@__PURE__*/ new Vector3(); +const _matrix4 = /*@__PURE__*/ new Matrix4(); +const _vertex = /*@__PURE__*/ new Vector3(); + +const _sphere$3 = /*@__PURE__*/ new Sphere(); +const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _ray$2 = /*@__PURE__*/ new Ray(); class SkinnedMesh extends Mesh { @@ -30346,6 +31293,57 @@ class SkinnedMesh extends Mesh { this.bindMatrix = new Matrix4(); this.bindMatrixInverse = new Matrix4(); + this.boundingBox = null; + this.boundingSphere = null; + + } + + computeBoundingBox() { + + const geometry = this.geometry; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + this.boundingBox.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + this.boundingSphere.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); + + } + } copy( source, recursive ) { @@ -30358,10 +31356,58 @@ class SkinnedMesh extends Mesh { this.skeleton = source.skeleton; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } + raycast( raycaster, intersects ) { + + const material = this.material; + const matrixWorld = this.matrixWorld; + + if ( material === undefined ) return; + + // test with bounding sphere in world space + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$3.copy( this.boundingSphere ); + _sphere$3.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; + + // convert ray to local space of skinned mesh + + _inverseMatrix$2.copy( matrixWorld ).invert(); + _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); + + // test with bounding box in local space + + if ( this.boundingBox !== null ) { + + if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; + + } + + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$2 ); + + } + + getVertexPosition( index, target ) { + + super.getVertexPosition( index, target ); + + this.applyBoneTransform( index, target ); + + return target; + + } + bind( skeleton, bindMatrix ) { this.skeleton = skeleton; @@ -30435,7 +31481,7 @@ class SkinnedMesh extends Mesh { } - boneTransform( index, target ) { + applyBoneTransform( index, vector ) { const skeleton = this.skeleton; const geometry = this.geometry; @@ -30443,9 +31489,9 @@ class SkinnedMesh extends Mesh { _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - _basePosition.copy( target ).applyMatrix4( this.bindMatrix ); + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); - target.set( 0, 0, 0 ); + vector.set( 0, 0, 0 ); for ( let i = 0; i < 4; i ++ ) { @@ -30455,18 +31501,26 @@ class SkinnedMesh extends Mesh { const boneIndex = _skinIndex.getComponent( i ); - _matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - target.addScaledVector( _vector$5.copy( _basePosition ).applyMatrix4( _matrix ), weight ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); } } - return target.applyMatrix4( this.bindMatrixInverse ); + return vector.applyMatrix4( this.bindMatrixInverse ); } + boneTransform( index, vector ) { // @deprecated, r151 + + console.warn( 'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' ); + return this.applyBoneTransform( index, vector ); + + } + + } class Bone extends Object3D { @@ -30485,9 +31539,9 @@ class Bone extends Object3D { class DataTexture extends Texture { - constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding ) { + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isDataTexture = true; @@ -30743,7 +31797,7 @@ class Skeleton { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Skeleton', generator: 'Skeleton.toJSON' }, @@ -30813,8 +31867,10 @@ const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); const _instanceIntersects = []; +const _box3 = /*@__PURE__*/ new Box3(); const _identity = /*@__PURE__*/ new Matrix4(); const _mesh = /*@__PURE__*/ new Mesh(); +const _sphere$2 = /*@__PURE__*/ new Sphere(); class InstancedMesh extends Mesh { @@ -30829,7 +31885,8 @@ class InstancedMesh extends Mesh { this.count = count; - this.frustumCulled = false; + this.boundingBox = null; + this.boundingSphere = null; for ( let i = 0; i < count; i ++ ) { @@ -30839,6 +31896,68 @@ class InstancedMesh extends Mesh { } + computeBoundingBox() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + this.boundingBox.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingBox.union( _box3 ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + if ( geometry.boundingSphere === null ) { + + geometry.computeBoundingSphere(); + + } + + this.boundingSphere.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingSphere.union( _sphere$2 ); + + } + + } + copy( source, recursive ) { super.copy( source, recursive ); @@ -30849,6 +31968,9 @@ class InstancedMesh extends Mesh { this.count = source.count; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } @@ -30875,6 +31997,17 @@ class InstancedMesh extends Mesh { if ( _mesh.material === undefined ) return; + // test with bounding sphere first + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$2.copy( this.boundingSphere ); + _sphere$2.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return; + + // now test each instance + for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { // calculate the world matrix for each instance @@ -30948,6 +32081,8 @@ class LineBasicMaterial extends Material { this.color = new Color( 0xffffff ); + this.map = null; + this.linewidth = 1; this.linecap = 'round'; this.linejoin = 'round'; @@ -30965,6 +32100,8 @@ class LineBasicMaterial extends Material { this.color.copy( source.color ); + this.map = source.map; + this.linewidth = source.linewidth; this.linecap = source.linecap; this.linejoin = source.linejoin; @@ -31509,14 +32646,12 @@ class VideoTexture extends Texture { class FramebufferTexture extends Texture { - constructor( width, height, format ) { + constructor( width, height ) { super( { width, height } ); this.isFramebufferTexture = true; - this.format = format; - this.magFilter = NearestFilter; this.minFilter = NearestFilter; @@ -31530,9 +32665,9 @@ class FramebufferTexture extends Texture { class CompressedTexture extends Texture { - constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCompressedTexture = true; @@ -31967,7 +33102,7 @@ class Curve { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Curve', generator: 'Curve.toJSON' } @@ -32673,13 +33808,15 @@ class LineCurve extends Curve { } - getTangent( t, optionalTarget ) { + getTangent( t, optionalTarget = new Vector2() ) { - const tangent = optionalTarget || new Vector2(); + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); - tangent.copy( this.v2 ).sub( this.v1 ).normalize(); + } - return tangent; + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); } @@ -32756,6 +33893,19 @@ class LineCurve3 extends Curve { return this.getPoint( u, optionalTarget ); } + + getTangent( t, optionalTarget = new Vector3() ) { + + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); + + } + + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); + + } + copy( source ) { super.copy( source ); @@ -33630,6 +34780,16 @@ class LatheGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); @@ -33743,6 +34903,16 @@ class CircleGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); @@ -34012,6 +35182,16 @@ class CylinderGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); @@ -34343,6 +35523,16 @@ class PolyhedronGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); @@ -34546,6 +35736,16 @@ class EdgesGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } class Shape extends Path { @@ -35544,6 +36744,7 @@ function addContour( vertices, contour ) { * } */ + class ExtrudeGeometry extends BufferGeometry { constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) { @@ -35686,7 +36887,7 @@ class ExtrudeGeometry extends BufferGeometry { if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); - return vec.clone().multiplyScalar( size ).add( pt ); + return pt.clone().addScaledVector( vec, size ); } @@ -36193,6 +37394,16 @@ class ExtrudeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -36491,6 +37702,16 @@ class RingGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); @@ -36625,6 +37846,16 @@ class ShapeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -36725,11 +37956,11 @@ class SphereGeometry extends BufferGeometry { let uOffset = 0; - if ( iy == 0 && thetaStart == 0 ) { + if ( iy === 0 && thetaStart === 0 ) { uOffset = 0.5 / widthSegments; - } else if ( iy == heightSegments && thetaEnd == Math.PI ) { + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { uOffset = - 0.5 / widthSegments; @@ -36791,6 +38022,16 @@ class SphereGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); @@ -36927,6 +38168,16 @@ class TorusGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); @@ -37079,6 +38330,16 @@ class TorusKnotGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); @@ -37246,6 +38507,16 @@ class TubeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); @@ -37382,6 +38653,16 @@ class WireframeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } function isUniqueEdge( start, end, edges ) { @@ -37610,6 +38891,9 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { this.type = 'MeshPhysicalMaterial'; + this.anisotropyRotation = 0; + this.anisotropyMap = null; + this.clearcoatMap = null; this.clearcoatRoughness = 0.0; this.clearcoatRoughnessMap = null; @@ -37653,30 +38937,31 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { this.specularColor = new Color( 1, 1, 1 ); this.specularColorMap = null; - this._sheen = 0.0; + this._anisotropy = 0; this._clearcoat = 0; this._iridescence = 0; + this._sheen = 0.0; this._transmission = 0; this.setValues( parameters ); } - get sheen() { + get anisotropy() { - return this._sheen; + return this._anisotropy; } - set sheen( value ) { + set anisotropy( value ) { - if ( this._sheen > 0 !== value > 0 ) { + if ( this._anisotropy > 0 !== value > 0 ) { this.version ++; } - this._sheen = value; + this._anisotropy = value; } @@ -37716,6 +39001,24 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { } + get sheen() { + + return this._sheen; + + } + + set sheen( value ) { + + if ( this._sheen > 0 !== value > 0 ) { + + this.version ++; + + } + + this._sheen = value; + + } + get transmission() { return this._transmission; @@ -37745,6 +39048,10 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { }; + this.anisotropy = source.anisotropy; + this.anisotropyRotation = source.anisotropyRotation; + this.anisotropyMap = source.anisotropyMap; + this.clearcoat = source.clearcoat; this.clearcoatMap = source.clearcoatMap; this.clearcoatRoughness = source.clearcoatRoughness; @@ -38616,17 +39923,16 @@ function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targe } -var AnimationUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, +const AnimationUtils = { arraySlice: arraySlice, convertArray: convertArray, - flattenJSON: flattenJSON, - getKeyframeOrder: getKeyframeOrder, isTypedArray: isTypedArray, - makeClipAdditive: makeClipAdditive, + getKeyframeOrder: getKeyframeOrder, sortedArray: sortedArray, - subclip: subclip -}); + flattenJSON: flattenJSON, + subclip: subclip, + makeClipAdditive: makeClipAdditive +}; /** * Abstract base class of interpolants over parametric samples. @@ -40977,7 +42283,11 @@ class DataTextureLoader extends Loader { texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - if ( texData.encoding !== undefined ) { + if ( texData.colorSpace !== undefined ) { + + texture.colorSpace = texData.colorSpace; + + } else if ( texData.encoding !== undefined ) { // @deprecated, r152 texture.encoding = texData.encoding; @@ -42026,6 +43336,8 @@ class MaterialLoader extends Loader { if ( json.thickness !== undefined ) material.thickness = json.thickness; if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); + if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; + if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; if ( json.fog !== undefined ) material.fog = json.fog; if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; if ( json.blending !== undefined ) material.blending = json.blending; @@ -42154,6 +43466,9 @@ class MaterialLoader extends Loader { } + if ( json.lights !== undefined ) material.lights = json.lights; + if ( json.clipping !== undefined ) material.clipping = json.clipping; + // for PointsMaterial if ( json.size !== undefined ) material.size = json.size; @@ -42226,6 +43541,8 @@ class MaterialLoader extends Loader { if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); + if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); + if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); @@ -42827,7 +44144,7 @@ class ObjectLoader extends Loader { geometry.uuid = data.uuid; if ( data.name !== undefined ) geometry.name = data.name; - if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData; + if ( data.userData !== undefined ) geometry.userData = data.userData; geometries[ data.uuid ] = geometry; @@ -43169,6 +44486,7 @@ class ObjectLoader extends Loader { if ( data.name !== undefined ) texture.name = data.name; if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); + if ( data.channel !== undefined ) texture.channel = data.channel; if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); @@ -43183,8 +44501,10 @@ class ObjectLoader extends Loader { } if ( data.format !== undefined ) texture.format = data.format; + if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; if ( data.type !== undefined ) texture.type = data.type; - if ( data.encoding !== undefined ) texture.encoding = data.encoding; + if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; + if ( data.encoding !== undefined ) texture.encoding = data.encoding; // @deprecated, r152 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); @@ -43195,6 +44515,7 @@ class ObjectLoader extends Loader { if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; + if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; if ( data.userData !== undefined ) texture.userData = data.userData; @@ -43493,6 +44814,8 @@ class ObjectLoader extends Loader { } + if ( data.up !== undefined ) object.up.fromArray( data.up ); + if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; @@ -43764,25 +45087,31 @@ class AudioLoader extends Loader { onLoad( audioBuffer ); - } ); + }, handleError ); } catch ( e ) { - if ( onError ) { + handleError( e ); - onError( e ); + } - } else { + }, onProgress, onError ); - console.error( e ); + function handleError( e ) { - } + if ( onError ) { - scope.manager.itemError( url ); + onError( e ); + + } else { + + console.error( e ); } - }, onProgress, onError ); + scope.manager.itemError( url ); + + } } @@ -47883,6 +49212,7 @@ function intersectObject( object, raycaster, intersects, recursive ) { * The azimuthal angle (theta) is measured from the positive z-axis. */ + class Spherical { constructor( radius = 1, phi = 0, theta = 0 ) { @@ -48179,8 +49509,7 @@ class Box2 { distanceToPoint( point ) { - const clampedPoint = _vector$4.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector$4 ).distanceTo( point ); } @@ -48189,6 +49518,8 @@ class Box2 { this.min.max( box.min ); this.max.min( box.max ); + if ( this.isEmpty() ) this.makeEmpty(); + return this; } @@ -49832,179 +51163,7 @@ class ShapePath { } -// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - -const _tables = /*@__PURE__*/ _generateTables(); - -function _generateTables() { - - // float32 to float16 helpers - - const buffer = new ArrayBuffer( 4 ); - const floatView = new Float32Array( buffer ); - const uint32View = new Uint32Array( buffer ); - - const baseTable = new Uint32Array( 512 ); - const shiftTable = new Uint32Array( 512 ); - - for ( let i = 0; i < 256; ++ i ) { - - const e = i - 127; - - // very small number (0, -0) - - if ( e < - 27 ) { - - baseTable[ i ] = 0x0000; - baseTable[ i | 0x100 ] = 0x8000; - shiftTable[ i ] = 24; - shiftTable[ i | 0x100 ] = 24; - - // small number (denorm) - - } else if ( e < - 14 ) { - - baseTable[ i ] = 0x0400 >> ( - e - 14 ); - baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; - shiftTable[ i ] = - e - 1; - shiftTable[ i | 0x100 ] = - e - 1; - - // normal number - - } else if ( e <= 15 ) { - - baseTable[ i ] = ( e + 15 ) << 10; - baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; - shiftTable[ i ] = 13; - shiftTable[ i | 0x100 ] = 13; - - // large number (Infinity, -Infinity) - - } else if ( e < 128 ) { - - baseTable[ i ] = 0x7c00; - baseTable[ i | 0x100 ] = 0xfc00; - shiftTable[ i ] = 24; - shiftTable[ i | 0x100 ] = 24; - - // stay (NaN, Infinity, -Infinity) - - } else { - - baseTable[ i ] = 0x7c00; - baseTable[ i | 0x100 ] = 0xfc00; - shiftTable[ i ] = 13; - shiftTable[ i | 0x100 ] = 13; - - } - - } - - // float16 to float32 helpers - - const mantissaTable = new Uint32Array( 2048 ); - const exponentTable = new Uint32Array( 64 ); - const offsetTable = new Uint32Array( 64 ); - - for ( let i = 1; i < 1024; ++ i ) { - - let m = i << 13; // zero pad mantissa bits - let e = 0; // zero exponent - - // normalized - while ( ( m & 0x00800000 ) === 0 ) { - - m <<= 1; - e -= 0x00800000; // decrement exponent - - } - - m &= ~ 0x00800000; // clear leading 1 bit - e += 0x38800000; // adjust bias - - mantissaTable[ i ] = m | e; - - } - - for ( let i = 1024; i < 2048; ++ i ) { - - mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); - - } - - for ( let i = 1; i < 31; ++ i ) { - - exponentTable[ i ] = i << 23; - - } - - exponentTable[ 31 ] = 0x47800000; - exponentTable[ 32 ] = 0x80000000; - - for ( let i = 33; i < 63; ++ i ) { - - exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); - - } - - exponentTable[ 63 ] = 0xc7800000; - - for ( let i = 1; i < 64; ++ i ) { - - if ( i !== 32 ) { - - offsetTable[ i ] = 1024; - - } - - } - - return { - floatView: floatView, - uint32View: uint32View, - baseTable: baseTable, - shiftTable: shiftTable, - mantissaTable: mantissaTable, - exponentTable: exponentTable, - offsetTable: offsetTable - }; - -} - -// float32 to float16 - -function toHalfFloat( val ) { - - if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); - - val = clamp( val, - 65504, 65504 ); - - _tables.floatView[ 0 ] = val; - const f = _tables.uint32View[ 0 ]; - const e = ( f >> 23 ) & 0x1ff; - return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); - -} - -// float16 to float32 - -function fromHalfFloat( val ) { - - const m = val >> 10; - _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; - return _tables.floatView[ 0 ]; - -} - -var DataUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, - fromHalfFloat: fromHalfFloat, - toHalfFloat: toHalfFloat -}); - -// r144 - -class BoxBufferGeometry extends BoxGeometry { +class BoxBufferGeometry extends BoxGeometry { // @deprecated, r144 constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) { @@ -50016,9 +51175,7 @@ class BoxBufferGeometry extends BoxGeometry { } -// r144 - -class CapsuleBufferGeometry extends CapsuleGeometry { +class CapsuleBufferGeometry extends CapsuleGeometry { // @deprecated, r144 constructor( radius, length, capSegments, radialSegments ) { @@ -50029,9 +51186,7 @@ class CapsuleBufferGeometry extends CapsuleGeometry { } -// r144 - -class CircleBufferGeometry extends CircleGeometry { +class CircleBufferGeometry extends CircleGeometry { // @deprecated, r144 constructor( radius, segments, thetaStart, thetaLength ) { @@ -50042,9 +51197,7 @@ class CircleBufferGeometry extends CircleGeometry { } -// r144 - -class ConeBufferGeometry extends ConeGeometry { +class ConeBufferGeometry extends ConeGeometry { // @deprecated, r144 constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -50055,9 +51208,7 @@ class ConeBufferGeometry extends ConeGeometry { } -// r144 - -class CylinderBufferGeometry extends CylinderGeometry { +class CylinderBufferGeometry extends CylinderGeometry { // @deprecated, r144 constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -50068,9 +51219,7 @@ class CylinderBufferGeometry extends CylinderGeometry { } -// r144 - -class DodecahedronBufferGeometry extends DodecahedronGeometry { +class DodecahedronBufferGeometry extends DodecahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50081,9 +51230,7 @@ class DodecahedronBufferGeometry extends DodecahedronGeometry { } -// r144 - -class ExtrudeBufferGeometry extends ExtrudeGeometry { +class ExtrudeBufferGeometry extends ExtrudeGeometry { // @deprecated, r144 constructor( shapes, options ) { @@ -50094,9 +51241,7 @@ class ExtrudeBufferGeometry extends ExtrudeGeometry { } -// r144 - -class IcosahedronBufferGeometry extends IcosahedronGeometry { +class IcosahedronBufferGeometry extends IcosahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50107,9 +51252,7 @@ class IcosahedronBufferGeometry extends IcosahedronGeometry { } -// r144 - -class LatheBufferGeometry extends LatheGeometry { +class LatheBufferGeometry extends LatheGeometry { // @deprecated, r144 constructor( points, segments, phiStart, phiLength ) { @@ -50120,9 +51263,7 @@ class LatheBufferGeometry extends LatheGeometry { } -// r144 - -class OctahedronBufferGeometry extends OctahedronGeometry { +class OctahedronBufferGeometry extends OctahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50133,9 +51274,7 @@ class OctahedronBufferGeometry extends OctahedronGeometry { } -// r144 - -class PlaneBufferGeometry extends PlaneGeometry { +class PlaneBufferGeometry extends PlaneGeometry { // @deprecated, r144 constructor( width, height, widthSegments, heightSegments ) { @@ -50146,9 +51285,7 @@ class PlaneBufferGeometry extends PlaneGeometry { } -// r144 - -class PolyhedronBufferGeometry extends PolyhedronGeometry { +class PolyhedronBufferGeometry extends PolyhedronGeometry { // @deprecated, r144 constructor( vertices, indices, radius, detail ) { @@ -50159,9 +51296,7 @@ class PolyhedronBufferGeometry extends PolyhedronGeometry { } -// r144 - -class RingBufferGeometry extends RingGeometry { +class RingBufferGeometry extends RingGeometry { // @deprecated, r144 constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { @@ -50172,9 +51307,7 @@ class RingBufferGeometry extends RingGeometry { } -// r144 - -class ShapeBufferGeometry extends ShapeGeometry { +class ShapeBufferGeometry extends ShapeGeometry { // @deprecated, r144 constructor( shapes, curveSegments ) { @@ -50185,9 +51318,7 @@ class ShapeBufferGeometry extends ShapeGeometry { } -// r144 - -class SphereBufferGeometry extends SphereGeometry { +class SphereBufferGeometry extends SphereGeometry { // @deprecated, r144 constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { @@ -50198,9 +51329,7 @@ class SphereBufferGeometry extends SphereGeometry { } -// r144 - -class TetrahedronBufferGeometry extends TetrahedronGeometry { +class TetrahedronBufferGeometry extends TetrahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -50211,9 +51340,7 @@ class TetrahedronBufferGeometry extends TetrahedronGeometry { } -// r144 - -class TorusBufferGeometry extends TorusGeometry { +class TorusBufferGeometry extends TorusGeometry { // @deprecated, r144 constructor( radius, tube, radialSegments, tubularSegments, arc ) { @@ -50224,9 +51351,7 @@ class TorusBufferGeometry extends TorusGeometry { } -// r144 - -class TorusKnotBufferGeometry extends TorusKnotGeometry { +class TorusKnotBufferGeometry extends TorusKnotGeometry { // @deprecated, r144 constructor( radius, tube, tubularSegments, radialSegments, p, q ) { @@ -50237,9 +51362,7 @@ class TorusKnotBufferGeometry extends TorusKnotGeometry { } -// r144 - -class TubeBufferGeometry extends TubeGeometry { +class TubeBufferGeometry extends TubeGeometry { // @deprecated, r144 constructor( path, tubularSegments, radius, radialSegments, closed ) { @@ -50272,4 +51395,4 @@ if ( typeof window !== 'undefined' ) { } -export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleBufferGeometry, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedTexture, CompressedTextureLoader, ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderBufferGeometry, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeBufferGeometry, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, Float64BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheBufferGeometry, LatheGeometry, Layers, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, Path, PerspectiveCamera, Plane, PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingBufferGeometry, RingGeometry, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, Scene, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronBufferGeometry, TetrahedronGeometry, Texture, TextureLoader, TorusBufferGeometry, TorusGeometry, TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeBufferGeometry, TubeGeometry, TwoPassDoubleSide, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL1Renderer, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, _SRGBAFormat, sRGBEncoding }; +export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleBufferGeometry, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedTexture, CompressedTextureLoader, ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderBufferGeometry, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeBufferGeometry, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, Float64BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheBufferGeometry, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, Path, PerspectiveCamera, Plane, PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingBufferGeometry, RingGeometry, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, Scene, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronBufferGeometry, TetrahedronGeometry, Texture, TextureLoader, TorusBufferGeometry, TorusGeometry, TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeBufferGeometry, TubeGeometry, TwoPassDoubleSide, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL1Renderer, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, _SRGBAFormat, sRGBEncoding }; diff --git a/build/three.module.min.js b/build/three.module.min.js new file mode 100644 index 00000000000000..b79a4dda7c1a11 --- /dev/null +++ b/build/three.module.min.js @@ -0,0 +1,6 @@ +/** + * @license + * Copyright 2010-2023 Three.js Authors + * SPDX-License-Identifier: MIT + */ +const t="153dev",e={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},n={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},i=0,r=1,s=2,a=3,o=0,l=1,c=2,h=3,u=0,d=1,p=2,m=2,f=0,g=1,v=2,_=3,y=4,x=5,M=100,S=101,b=102,E=103,T=104,w=200,A=201,R=202,C=203,P=204,L=205,I=206,U=207,N=208,D=209,O=210,F=0,B=1,z=2,H=3,k=4,V=5,G=6,W=7,X=0,j=1,q=2,Y=0,Z=1,J=2,K=3,$=4,Q=5,tt=300,et=301,nt=302,it=303,rt=304,st=306,at=1e3,ot=1001,lt=1002,ct=1003,ht=1004,ut=1004,dt=1005,pt=1005,mt=1006,ft=1007,gt=1007,vt=1008,_t=1008,yt=1009,xt=1010,Mt=1011,St=1012,bt=1013,Et=1014,Tt=1015,wt=1016,At=1017,Rt=1018,Ct=1020,Pt=1021,Lt=1023,It=1024,Ut=1025,Nt=1026,Dt=1027,Ot=1028,Ft=1029,Bt=1030,zt=1031,Ht=1033,kt=33776,Vt=33777,Gt=33778,Wt=33779,Xt=35840,jt=35841,qt=35842,Yt=35843,Zt=36196,Jt=37492,Kt=37496,$t=37808,Qt=37809,te=37810,ee=37811,ne=37812,ie=37813,re=37814,se=37815,ae=37816,oe=37817,le=37818,ce=37819,he=37820,ue=37821,de=36492,pe=36283,me=36284,fe=36285,ge=36286,ve=2200,_e=2201,ye=2202,xe=2300,Me=2301,Se=2302,be=2400,Ee=2401,Te=2402,we=2500,Ae=2501,Re=0,Ce=1,Pe=2,Le=3e3,Ie=3001,Ue=3200,Ne=3201,De=0,Oe=1,Fe="",Be="srgb",ze="srgb-linear",He="display-p3",ke=0,Ve=7680,Ge=7681,We=7682,Xe=7683,je=34055,qe=34056,Ye=5386,Ze=512,Je=513,Ke=514,$e=515,Qe=516,tn=517,en=518,nn=519,rn=512,sn=513,an=514,on=515,ln=516,cn=517,hn=518,un=519,dn=35044,pn=35048,mn=35040,fn=35045,gn=35049,vn=35041,_n=35046,yn=35050,xn=35042,Mn="100",Sn="300 es",bn=1035;class En{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[t]&&(n[t]=[]),-1===n[t].indexOf(e)&&n[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[t]&&-1!==n[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const n=this._listeners[t];if(void 0!==n){const t=n.indexOf(e);-1!==t&&n.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const n=e.slice(0);for(let e=0,i=n.length;e>8&255]+Tn[t>>16&255]+Tn[t>>24&255]+"-"+Tn[255&e]+Tn[e>>8&255]+"-"+Tn[e>>16&15|64]+Tn[e>>24&255]+"-"+Tn[63&n|128]+Tn[n>>8&255]+"-"+Tn[n>>16&255]+Tn[n>>24&255]+Tn[255&i]+Tn[i>>8&255]+Tn[i>>16&255]+Tn[i>>24&255]).toLowerCase()}function Pn(t,e,n){return Math.max(e,Math.min(n,t))}function Ln(t,e){return(t%e+e)%e}function In(t,e,n){return(1-n)*t+n*e}function Un(t){return 0==(t&t-1)&&0!==t}function Nn(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))}function Dn(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))}function On(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return t/4294967295;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int32Array:return Math.max(t/2147483647,-1);case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function Fn(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return Math.round(4294967295*t);case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int32Array:return Math.round(2147483647*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}const Bn={DEG2RAD:An,RAD2DEG:Rn,generateUUID:Cn,clamp:Pn,euclideanModulo:Ln,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:In,damp:function(t,e,n,i){return In(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(Ln(t,2*e)-e)},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(wn=t);let e=wn+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*An},radToDeg:function(t){return t*Rn},isPowerOfTwo:Un,ceilPowerOfTwo:Nn,floorPowerOfTwo:Dn,setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-e)/2);switch(r){case"XYX":t.set(o*h,l*u,l*d,o*c);break;case"YZY":t.set(l*d,o*h,l*u,o*c);break;case"ZXZ":t.set(l*u,l*d,o*h,o*c);break;case"XZX":t.set(o*h,l*m,l*p,o*c);break;case"YXY":t.set(l*p,o*h,l*m,o*c);break;case"ZYZ":t.set(l*m,l*p,o*h,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Fn,denormalize:On};class zn{constructor(t=0,e=0){zn.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Pn(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Hn{constructor(t,e,n,i,r,s,a,o,l){Hn.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l)}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,c[7]=s,c[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],v=i[1],_=i[4],y=i[7],x=i[2],M=i[5],S=i[8];return r[0]=s*m+a*v+o*x,r[3]=s*f+a*_+o*M,r[6]=s*g+a*y+o*S,r[1]=l*m+c*v+h*x,r[4]=l*f+c*_+h*M,r[7]=l*g+c*y+h*S,r[2]=u*m+d*v+p*x,r[5]=u*f+d*_+p*M,r[8]=u*g+d*y+p*S,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8];return e*s*c-e*a*l-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=c*s-a*l,u=a*o-c*r,d=l*r-s*o,p=e*h+n*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=h*m,t[1]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(kn.makeScale(t,e)),this}rotate(t){return this.premultiply(kn.makeRotation(-t)),this}translate(t,e){return this.premultiply(kn.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const kn=new Hn;function Vn(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const Gn={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function Wn(t,e){return new Gn[t](e)}function Xn(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}const jn={};function qn(t){t in jn||(jn[t]=!0,console.warn(t))}function Yn(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function Zn(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}const Jn=(new Hn).fromArray([.8224621,.0331941,.0170827,.177538,.9668058,.0723974,-1e-7,1e-7,.9105199]),Kn=(new Hn).fromArray([1.2249401,-.0420569,-.0196376,-.2249404,1.0420571,-.0786361,1e-7,0,1.0982735]);const $n={[ze]:t=>t,[Be]:t=>t.convertSRGBToLinear(),[He]:function(t){return t.convertSRGBToLinear().applyMatrix3(Kn)}},Qn={[ze]:t=>t,[Be]:t=>t.convertLinearToSRGB(),[He]:function(t){return t.applyMatrix3(Jn).convertLinearToSRGB()}},ti={enabled:!0,get legacyMode(){return console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),!this.enabled},set legacyMode(t){console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),this.enabled=!t},get workingColorSpace(){return ze},set workingColorSpace(t){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(t,e,n){if(!1===this.enabled||e===n||!e||!n)return t;const i=$n[e],r=Qn[n];if(void 0===i||void 0===r)throw new Error(`Unsupported color space conversion, "${e}" to "${n}".`);return r(i(t))},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)}};let ei;class ni{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===ei&&(ei=Xn("canvas")),ei.width=t.width,ei.height=t.height;const n=ei.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=ei}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=Xn("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const i=n.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==tt)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case at:t.x=t.x-Math.floor(t.x);break;case ot:t.x=t.x<0?0:1;break;case lt:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case at:t.y=t.y-Math.floor(t.y);break;case ot:t.y=t.y<0?0:1;break;case lt:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}get encoding(){return qn("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace===Be?Ie:Le}set encoding(t){qn("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace=t===Ie?Be:Fe}}oi.DEFAULT_IMAGE=null,oi.DEFAULT_MAPPING=tt,oi.DEFAULT_ANISOTROPY=1;class li{constructor(t=0,e=0,n=0,i=1){li.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+s[15]*r,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,n,i,r;const s=.01,a=.1,o=t.elements,l=o[0],c=o[4],h=o[8],u=o[1],d=o[5],p=o[9],m=o[2],f=o[6],g=o[10];if(Math.abs(c-u)o&&t>v?tv?o=0?1:-1,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;if(o=o*t+u*r,l=l*t+d*r,c=c*t+p*r,h=h*t+m*r,t===1-a){const t=1/Math.sqrt(o*o+l*l+c*c+h*h);o*=t,l*=t,c*=t,h*=t}}t[e]=o,t[e+1]=l,t[e+2]=c,t[e+3]=h}static multiplyQuaternionsFlat(t,e,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+3],h=r[s],u=r[s+1],d=r[s+2],p=r[s+3];return t[e]=a*p+c*h+o*d-l*u,t[e+1]=o*p+c*u+l*h-a*d,t[e+2]=l*p+c*d+a*u-o*h,t[e+3]=c*p-a*h-o*u-l*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e){const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/2),p=o(r/2);switch(s){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+s)}return!1!==e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+a+h;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(c-o)*t,this._y=(r-l)*t,this._z=(s-i)*t}else if(n>a&&n>h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Pn(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*t._y+r*t._z;if(a<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,a=-a):this.copy(t),a>=1)return this._w=s,this._x=n,this._y=i,this._z=r,this;const o=1-a*a;if(o<=Number.EPSILON){const t=1-e;return this._w=t*s+e*this._w,this._x=t*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this._onChangeCallback(),this}const l=Math.sqrt(o),c=Math.atan2(l,a),h=Math.sin((1-e)*c)/l,u=Math.sin(e*c)/l;return this._w=s*h+this._w*u,this._x=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=Math.random(),e=Math.sqrt(1-t),n=Math.sqrt(t),i=2*Math.PI*Math.random(),r=2*Math.PI*Math.random();return this.set(e*Math.cos(i),n*Math.sin(r),n*Math.cos(r),e*Math.sin(i))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class gi{constructor(t=0,e=0,n=0){gi.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&&(n=this.z),this.x=t,this.y=e,this.z=n,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(_i.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(_i.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=o*e+s*i-a*n,c=o*n+a*e-r*i,h=o*i+r*n-s*e,u=-r*e-s*n-a*i;return this.x=l*o+u*-r+c*-a-h*-s,this.y=c*o+u*-s+h*-r-l*-a,this.z=h*o+u*-a+l*-s-c*-r,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Math.max(t.x,Math.min(e.x,this.x)),this.y=Math.max(t.y,Math.min(e.y,this.y)),this.z=Math.max(t.z,Math.min(e.z,this.z)),this}clampScalar(t,e){return this.x=Math.max(t,Math.min(e,this.x)),this.y=Math.max(t,Math.min(e,this.y)),this.z=Math.max(t,Math.min(e,this.z)),this}clampLength(t,e){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return vi.copy(this).projectOnVector(t),this.sub(vi)}reflect(t){return this.sub(vi.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Pn(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=2*(Math.random()-.5),e=Math.random()*Math.PI*2,n=Math.sqrt(1-t**2);return this.x=n*Math.cos(e),this.y=n*Math.sin(e),this.z=t,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const vi=new gi,_i=new fi;class yi{constructor(t=new gi(1/0,1/0,1/0),e=new gi(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,n=t.length;ethis.max.x||t.ythis.max.y||t.zthis.max.z)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y||t.max.zthis.max.z)}intersectsSphere(t){return this.clampPoint(t.center,Mi),Mi.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Ci),Pi.subVectors(this.max,Ci),bi.subVectors(t.a,Ci),Ei.subVectors(t.b,Ci),Ti.subVectors(t.c,Ci),wi.subVectors(Ei,bi),Ai.subVectors(Ti,Ei),Ri.subVectors(bi,Ti);let e=[0,-wi.z,wi.y,0,-Ai.z,Ai.y,0,-Ri.z,Ri.y,wi.z,0,-wi.x,Ai.z,0,-Ai.x,Ri.z,0,-Ri.x,-wi.y,wi.x,0,-Ai.y,Ai.x,0,-Ri.y,Ri.x,0];return!!Ui(e,bi,Ei,Ti,Pi)&&(e=[1,0,0,0,1,0,0,0,1],!!Ui(e,bi,Ei,Ti,Pi)&&(Li.crossVectors(wi,Ai),e=[Li.x,Li.y,Li.z],Ui(e,bi,Ei,Ti,Pi)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Mi).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(Mi).length()),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(xi[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),xi[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),xi[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),xi[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),xi[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),xi[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),xi[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),xi[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(xi)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const xi=[new gi,new gi,new gi,new gi,new gi,new gi,new gi,new gi],Mi=new gi,Si=new yi,bi=new gi,Ei=new gi,Ti=new gi,wi=new gi,Ai=new gi,Ri=new gi,Ci=new gi,Pi=new gi,Li=new gi,Ii=new gi;function Ui(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){Ii.fromArray(t,s);const a=r.x*Math.abs(Ii.x)+r.y*Math.abs(Ii.y)+r.z*Math.abs(Ii.z),o=e.dot(Ii),l=n.dot(Ii),c=i.dot(Ii);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const Ni=new yi,Di=new gi,Oi=new gi;class Fi{constructor(t=new gi,e=-1){this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):Ni.setFromPoints(t).getCenter(n);let i=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;Di.subVectors(t,this.center);const e=Di.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.addScaledVector(Di,n/t),this.radius+=n}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Oi.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Di.copy(t.center).add(Oi)),this.expandByPoint(Di.copy(t.center).sub(Oi))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Bi=new gi,zi=new gi,Hi=new gi,ki=new gi,Vi=new gi,Gi=new gi,Wi=new gi;class Xi{constructor(t=new gi,e=new gi(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,Bi)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=Bi.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(Bi.copy(this.origin).addScaledVector(this.direction,e),Bi.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){zi.copy(t).add(e).multiplyScalar(.5),Hi.copy(e).sub(t).normalize(),ki.copy(this.origin).sub(zi);const r=.5*t.distanceTo(e),s=-this.direction.dot(Hi),a=ki.dot(this.direction),o=-ki.dot(Hi),l=ki.lengthSq(),c=Math.abs(1-s*s);let h,u,d,p;if(c>0)if(h=s*o-a,u=s*a-o,p=r*c,h>=0)if(u>=-p)if(u<=p){const t=1/c;h*=t,u*=t,d=h*(h+s*u+2*a)+u*(s*h+u+2*o)+l}else u=r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u=-r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;else u<=-p?(h=Math.max(0,-(-s*r+a)),u=h>0?-r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l):u<=p?(h=0,u=Math.min(Math.max(-r,-o),r),d=u*(u+2*o)+l):(h=Math.max(0,-(s*r+a)),u=h>0?r:Math.min(Math.max(-r,-o),r),d=-h*h+u*(u+2*o)+l);else u=s>0?-r:r,h=Math.max(0,-(s*u+a)),d=-h*h+u*(u+2*o)+l;return n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(zi).addScaledVector(Hi,u),d}intersectSphere(t,e){Bi.subVectors(t.center,this.origin);const n=Bi.dot(this.direction),i=Bi.dot(Bi)-n*n,r=t.radius*t.radius;if(i>r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return o<0?null:a<0?this.at(o,e):this.at(a,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let n,i,r,s,a,o;const l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(t.min.x-u.x)*l),c>=0?(r=(t.min.y-u.y)*c,s=(t.max.y-u.y)*c):(r=(t.max.y-u.y)*c,s=(t.min.y-u.y)*c),n>s||r>i?null:((r>n||isNaN(n))&&(n=r),(s=0?(a=(t.min.z-u.z)*h,o=(t.max.z-u.z)*h):(a=(t.max.z-u.z)*h,o=(t.min.z-u.z)*h),n>o||a>i?null:((a>n||n!=n)&&(n=a),(o=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,Bi)}intersectTriangle(t,e,n,i,r){Vi.subVectors(e,t),Gi.subVectors(n,t),Wi.crossVectors(Vi,Gi);let s,a=this.direction.dot(Wi);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}ki.subVectors(this.origin,t);const o=s*this.direction.dot(Gi.crossVectors(ki,Gi));if(o<0)return null;const l=s*this.direction.dot(Vi.cross(ki));if(l<0)return null;if(o+l>a)return null;const c=-s*ki.dot(Wi);return c<0?null:this.at(c/a,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class ji{constructor(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){ji.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f)}set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){const g=this.elements;return g[0]=t,g[4]=e,g[8]=n,g[12]=i,g[1]=r,g[5]=s,g[9]=a,g[13]=o,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=m,g[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new ji).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/qi.setFromMatrixColumn(t,0).length(),r=1/qi.setFromMatrixColumn(t,1).length(),s=1/qi.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*a,e[5]=s*c,e[9]=r-t*a,e[2]=-s*l,e[6]=a,e[10]=s*o}else if("ZYX"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=-h,e[8]=l*c,e[1]=t*h+r,e[5]=s*c,e[9]=n*h-i,e[2]=i*h-n,e[6]=a*c,e[10]=r*h+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(Zi,t,Ji)}lookAt(t,e,n){const i=this.elements;return Qi.subVectors(t,e),0===Qi.lengthSq()&&(Qi.z=1),Qi.normalize(),Ki.crossVectors(n,Qi),0===Ki.lengthSq()&&(1===Math.abs(n.z)?Qi.x+=1e-4:Qi.z+=1e-4,Qi.normalize(),Ki.crossVectors(n,Qi)),Ki.normalize(),$i.crossVectors(Qi,Ki),i[0]=Ki.x,i[4]=$i.x,i[8]=Qi.x,i[1]=Ki.y,i[5]=$i.y,i[9]=Qi.y,i[2]=Ki.z,i[6]=$i.z,i[10]=Qi.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],v=n[3],_=n[7],y=n[11],x=n[15],M=i[0],S=i[4],b=i[8],E=i[12],T=i[1],w=i[5],A=i[9],R=i[13],C=i[2],P=i[6],L=i[10],I=i[14],U=i[3],N=i[7],D=i[11],O=i[15];return r[0]=s*M+a*T+o*C+l*U,r[4]=s*S+a*w+o*P+l*N,r[8]=s*b+a*A+o*L+l*D,r[12]=s*E+a*R+o*I+l*O,r[1]=c*M+h*T+u*C+d*U,r[5]=c*S+h*w+u*P+d*N,r[9]=c*b+h*A+u*L+d*D,r[13]=c*E+h*R+u*I+d*O,r[2]=p*M+m*T+f*C+g*U,r[6]=p*S+m*w+f*P+g*N,r[10]=p*b+m*A+f*L+g*D,r[14]=p*E+m*R+f*I+g*O,r[3]=v*M+_*T+y*C+x*U,r[7]=v*S+_*w+y*P+x*N,r[11]=v*b+_*A+y*L+x*D,r[15]=v*E+_*R+y*I+x*O,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],n=t[4],i=t[8],r=t[12],s=t[1],a=t[5],o=t[9],l=t[13],c=t[2],h=t[6],u=t[10],d=t[14];return t[3]*(+r*o*h-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*o*c)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=t[2],r=t[3],s=t[4],a=t[5],o=t[6],l=t[7],c=t[8],h=t[9],u=t[10],d=t[11],p=t[12],m=t[13],f=t[14],g=t[15],v=h*f*l-m*u*l+m*o*d-a*f*d-h*o*g+a*u*g,_=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,y=c*m*l-p*h*l+p*a*d-s*m*d-c*a*g+s*h*g,x=p*h*o-c*m*o-p*a*u+s*m*u+c*a*f-s*h*f,M=e*v+n*_+i*y+r*x;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const S=1/M;return t[0]=v*S,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*S,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*S,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*S,t[4]=_*S,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*S,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*S,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*S,t[8]=y*S,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*S,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*S,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*S,t[12]=x*S,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*S,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*S,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*S,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=this.elements,r=e._x,s=e._y,a=e._z,o=e._w,l=r+r,c=s+s,h=a+a,u=r*l,d=r*c,p=r*h,m=s*c,f=s*h,g=a*h,v=o*l,_=o*c,y=o*h,x=n.x,M=n.y,S=n.z;return i[0]=(1-(m+g))*x,i[1]=(d+y)*x,i[2]=(p-_)*x,i[3]=0,i[4]=(d-y)*M,i[5]=(1-(u+g))*M,i[6]=(f+v)*M,i[7]=0,i[8]=(p+_)*S,i[9]=(f-v)*S,i[10]=(1-(u+m))*S,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=qi.set(i[0],i[1],i[2]).length();const s=qi.set(i[4],i[5],i[6]).length(),a=qi.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],Yi.copy(this);const o=1/r,l=1/s,c=1/a;return Yi.elements[0]*=o,Yi.elements[1]*=o,Yi.elements[2]*=o,Yi.elements[4]*=l,Yi.elements[5]*=l,Yi.elements[6]*=l,Yi.elements[8]*=c,Yi.elements[9]*=c,Yi.elements[10]*=c,e.setFromRotationMatrix(Yi),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s){const a=this.elements,o=2*r/(e-t),l=2*r/(n-i),c=(e+t)/(e-t),h=(n+i)/(n-i),u=-(s+r)/(s-r),d=-2*s*r/(s-r);return a[0]=o,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=h,a[13]=0,a[2]=0,a[6]=0,a[10]=u,a[14]=d,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,n,i,r,s){const a=this.elements,o=1/(e-t),l=1/(n-i),c=1/(s-r),h=(e+t)*o,u=(n+i)*l,d=(s+r)*c;return a[0]=2*o,a[4]=0,a[8]=0,a[12]=-h,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-u,a[2]=0,a[6]=0,a[10]=-2*c,a[14]=-d,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const qi=new gi,Yi=new ji,Zi=new gi(0,0,0),Ji=new gi(1,1,1),Ki=new gi,$i=new gi,Qi=new gi,tr=new ji,er=new fi;class nr{constructor(t=0,e=0,n=0,i=nr.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(Pn(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-c,d),this._z=Math.atan2(-s,r)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-Pn(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(a,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-h,r),this._z=0);break;case"ZXY":this._x=Math.asin(Pn(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-h,d),this._z=Math.atan2(-s,l)):(this._y=0,this._z=Math.atan2(o,r));break;case"ZYX":this._y=Math.asin(-Pn(h,-1,1)),Math.abs(h)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,r)):(this._x=0,this._z=Math.atan2(-s,l));break;case"YZX":this._z=Math.asin(Pn(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-c,l),this._y=Math.atan2(-h,r)):(this._x=0,this._y=Math.atan2(a,d));break;case"XZY":this._z=Math.asin(-Pn(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(u,l),this._y=Math.atan2(a,r)):(this._x=Math.atan2(-c,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return tr.makeRotationFromQuaternion(t),this.setFromRotationMatrix(tr,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return er.setFromEuler(this),this.setFromQuaternion(er,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}nr.DEFAULT_ORDER="XYZ";class ir{constructor(){this.mask=1}set(t){this.mask=(1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0&&(n=n.concat(r))}return n}getWorldPosition(t){return this.updateWorldMatrix(!0,!1),t.setFromMatrixPosition(this.matrixWorld)}getWorldQuaternion(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(cr,t,hr),t}getWorldScale(t){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(cr,ur,t),t}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(e[8],e[9],e[10]).normalize()}raycast(){}traverse(t){t(this);const e=this.children;for(let n=0,i=e.length;n0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const n=e.shapes;if(Array.isArray(n))for(let e=0,i=n.length;e0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(n.geometries=e),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),a.length>0&&(n.images=a),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations,this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){_r.subVectors(i,e),yr.subVectors(n,e),xr.subVectors(t,e);const s=_r.dot(_r),a=_r.dot(yr),o=_r.dot(xr),l=yr.dot(yr),c=yr.dot(xr),h=s*l-a*a;if(0===h)return r.set(-2,-1,-1);const u=1/h,d=(l*o-a*c)*u,p=(s*c-a*o)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,n,i){return this.getBarycoord(t,e,n,i,Mr),Mr.x>=0&&Mr.y>=0&&Mr.x+Mr.y<=1}static getUV(t,e,n,i,r,s,a,o){return!1===Rr&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),Rr=!0),this.getInterpolation(t,e,n,i,r,s,a,o)}static getInterpolation(t,e,n,i,r,s,a,o){return this.getBarycoord(t,e,n,i,Mr),o.setScalar(0),o.addScaledVector(r,Mr.x),o.addScaledVector(s,Mr.y),o.addScaledVector(a,Mr.z),o}static isFrontFacing(t,e,n,i){return _r.subVectors(n,e),yr.subVectors(t,e),_r.cross(yr).dot(i)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return _r.subVectors(this.c,this.b),yr.subVectors(this.a,this.b),.5*_r.cross(yr).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Cr.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Cr.getBarycoord(t,this.a,this.b,this.c,e)}getUV(t,e,n,i,r){return!1===Rr&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),Rr=!0),Cr.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}getInterpolation(t,e,n,i,r){return Cr.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return Cr.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Cr.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;Sr.subVectors(i,n),br.subVectors(r,n),Tr.subVectors(t,n);const o=Sr.dot(Tr),l=br.dot(Tr);if(o<=0&&l<=0)return e.copy(n);wr.subVectors(t,i);const c=Sr.dot(wr),h=br.dot(wr);if(c>=0&&h<=c)return e.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(n).addScaledVector(Sr,s);Ar.subVectors(t,r);const d=Sr.dot(Ar),p=br.dot(Ar);if(p>=0&&d<=p)return e.copy(r);const m=d*l-o*p;if(m<=0&&l>=0&&p<=0)return a=l/(l-p),e.copy(n).addScaledVector(br,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return Er.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(Er,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(Sr,s).addScaledVector(br,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}let Pr=0;class Lr extends En{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:Pr++}),this.uuid=Cn(),this.name="",this.type="Material",this.blending=g,this.side=u,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.blendSrc=P,this.blendDst=L,this.blendEquation=M,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=H,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=Ve,this.stencilZFail=Ve,this.stencilZPass=Ve,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.forceSinglePass=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(t){this._alphaTest>0!=t>0&&this.version++,this._alphaTest=t}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[e]=n:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),void 0!==this.anisotropy&&(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==g&&(n.blending=this.blending),this.side!==u&&(n.side=this.side),this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=this.transparent),n.depthFunc=this.depthFunc,n.depthTest=this.depthTest,n.depthWrite=this.depthWrite,n.colorWrite=this.colorWrite,n.stencilWrite=this.stencilWrite,n.stencilWriteMask=this.stencilWriteMask,n.stencilFunc=this.stencilFunc,n.stencilRef=this.stencilRef,n.stencilFuncMask=this.stencilFuncMask,n.stencilFail=this.stencilFail,n.stencilZFail=this.stencilZFail,n.stencilZPass=this.stencilZPass,void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaToCoverage&&(n.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.forceSinglePass&&(n.forceSinglePass=this.forceSinglePass),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=this.flatShading),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(n.textures=e),r.length>0&&(n.images=r)}return n}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}}const Ir={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Ur={h:0,s:0,l:0},Nr={h:0,s:0,l:0};function Dr(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}class Or{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(void 0===e&&void 0===n){const e=t;e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Be){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,ti.toWorkingColorSpace(this,e),this}setRGB(t,e,n,i=ti.workingColorSpace){return this.r=t,this.g=e,this.b=n,ti.toWorkingColorSpace(this,i),this}setHSL(t,e,n,i=ti.workingColorSpace){if(t=Ln(t,1),e=Pn(e,0,1),n=Pn(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=Dr(r,i,t+1/3),this.g=Dr(r,i,t),this.b=Dr(r,i,t-1/3)}return ti.toWorkingColorSpace(this,i),this}setStyle(t,e=Be){function n(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const s=i[1],a=i[2];switch(s){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(n,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=Be){const n=Ir[t.toLowerCase()];return void 0!==n?this.setHex(n,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=Yn(t.r),this.g=Yn(t.g),this.b=Yn(t.b),this}copyLinearToSRGB(t){return this.r=Zn(t.r),this.g=Zn(t.g),this.b=Zn(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Be){return ti.fromWorkingColorSpace(Fr.copy(this),t),65536*Math.round(Pn(255*Fr.r,0,255))+256*Math.round(Pn(255*Fr.g,0,255))+Math.round(Pn(255*Fr.b,0,255))}getHexString(t=Be){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=ti.workingColorSpace){ti.fromWorkingColorSpace(Fr.copy(this),e);const n=Fr.r,i=Fr.g,r=Fr.b,s=Math.max(n,i,r),a=Math.min(n,i,r);let o,l;const c=(a+s)/2;if(a===s)o=0,l=0;else{const t=s-a;switch(l=c<=.5?t/(s+a):t/(2-s-a),s){case n:o=(i-r)/t+(i>-e-14,i[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(i[t]=e+15<<10,i[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[256|t]=64512,r[t]=13,r[256|t]=13)}const s=new Uint32Array(2048),a=new Uint32Array(64),o=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,n=0;for(;0==(8388608&e);)e<<=1,n-=8388608;e&=-8388609,n+=947912704,s[t]=e|n}for(let t=1024;t<2048;++t)s[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)a[t]=t<<23;a[31]=1199570944,a[32]=2147483648;for(let t=33;t<63;++t)a[t]=2147483648+(t-32<<23);a[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(o[t]=1024);return{floatView:e,uint32View:n,baseTable:i,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}function kr(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=Pn(t,-65504,65504),zr.floatView[0]=t;const e=zr.uint32View[0],n=e>>23&511;return zr.baseTable[n]+((8388607&e)>>zr.shiftTable[n])}function Vr(t){const e=t>>10;return zr.uint32View[0]=zr.mantissaTable[zr.offsetTable[e]+(1023&t)]+zr.exponentTable[e],zr.floatView[0]}const Gr={toHalfFloat:kr,fromHalfFloat:Vr},Wr=new gi,Xr=new zn;class jr{constructor(t,e,n=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=n,this.usage=dn,this.updateRange={offset:0,count:-1},this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&&(t[n]=e[n]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e0&&(i[e]=s,r=!0)}r&&(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const s=this.groups;s.length>0&&(t.data.groups=JSON.parse(JSON.stringify(s)));const a=this.boundingSphere;return null!==a&&(t.data.boundingSphere={center:a.center.toArray(),radius:a.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const n=t.index;null!==n&&this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t(t.far-t.near)**2)return}us.copy(r).invert(),ds.copy(t.ray).applyMatrix4(us),null!==n.boundingBox&&!1===ds.intersectsBox(n.boundingBox)||this._computeIntersections(t,e,ds)}}_computeIntersections(t,e,n){let i;const r=this.geometry,s=this.material,a=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==a)if(Array.isArray(s))for(let r=0,o=u.length;rn.far?null:{distance:c,point:As.clone(),object:t}}(t,e,n,i,fs,gs,vs,ws);if(h){r&&(xs.fromBufferAttribute(r,o),Ms.fromBufferAttribute(r,l),Ss.fromBufferAttribute(r,c),h.uv=Cr.getInterpolation(ws,fs,gs,vs,xs,Ms,Ss,new zn)),s&&(xs.fromBufferAttribute(s,o),Ms.fromBufferAttribute(s,l),Ss.fromBufferAttribute(s,c),h.uv1=Cr.getInterpolation(ws,fs,gs,vs,xs,Ms,Ss,new zn),h.uv2=h.uv1),a&&(bs.fromBufferAttribute(a,o),Es.fromBufferAttribute(a,l),Ts.fromBufferAttribute(a,c),h.normal=Cr.getInterpolation(ws,fs,gs,vs,bs,Es,Ts,new gi),h.normal.dot(i.direction)>0&&h.normal.multiplyScalar(-1));const t={a:o,b:l,c:c,normal:new gi,materialIndex:0};Cr.getNormal(fs,gs,vs,t.normal),h.face=t}return h}class Ps extends hs{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const _=s/f,y=p/g,x=s/2,M=p/2,S=m/2,b=f+1,E=g+1;let T=0,w=0;const A=new gi;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.z),h.push(o/f),h.push(1-s/g),T+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const t in this.extensions)!0===this.extensions[t]&&(n[t]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class Os extends vr{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new ji,this.projectionMatrix=new ji,this.projectionMatrixInverse=new ji}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this}getWorldDirection(t){this.updateWorldMatrix(!0,!1);const e=this.matrixWorld.elements;return t.set(-e[8],-e[9],-e[10]).normalize()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}class Fs extends Os{constructor(t=50,e=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*Rn*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*An*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*Rn*Math.atan(Math.tan(.5*An*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(t,e,n,i,r,s){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*An*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const Bs=-90;class zs extends vr{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n;const i=new Fs(Bs,1,t,e);i.layers=this.layers,i.up.set(0,1,0),i.lookAt(1,0,0),this.add(i);const r=new Fs(Bs,1,t,e);r.layers=this.layers,r.up.set(0,1,0),r.lookAt(-1,0,0),this.add(r);const s=new Fs(Bs,1,t,e);s.layers=this.layers,s.up.set(0,0,-1),s.lookAt(0,1,0),this.add(s);const a=new Fs(Bs,1,t,e);a.layers=this.layers,a.up.set(0,0,1),a.lookAt(0,-1,0),this.add(a);const o=new Fs(Bs,1,t,e);o.layers=this.layers,o.up.set(0,1,0),o.lookAt(0,0,1),this.add(o);const l=new Fs(Bs,1,t,e);l.layers=this.layers,l.up.set(0,1,0),l.lookAt(0,0,-1),this.add(l)}update(t,e){null===this.parent&&this.updateMatrixWorld();const n=this.renderTarget,[i,r,s,a,o,l]=this.children,c=t.getRenderTarget(),h=t.toneMapping,u=t.xr.enabled;t.toneMapping=Y,t.xr.enabled=!1;const d=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0),t.render(e,i),t.setRenderTarget(n,1),t.render(e,r),t.setRenderTarget(n,2),t.render(e,s),t.setRenderTarget(n,3),t.render(e,a),t.setRenderTarget(n,4),t.render(e,o),n.texture.generateMipmaps=d,t.setRenderTarget(n,5),t.render(e,l),t.setRenderTarget(c),t.toneMapping=h,t.xr.enabled=u,n.texture.needsPMREMUpdate=!0}}class Hs extends oi{constructor(t,e,n,i,r,s,a,o,l,c){super(t=void 0!==t?t:[],e=void 0!==e?e:et,n,i,r,s,a,o,l,c),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class ks extends ci{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},i=[n,n,n,n,n,n];void 0!==e.encoding&&(qn("THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace."),e.colorSpace=e.encoding===Ie?Be:Fe),this.texture=new Hs(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:mt}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new Ps(5,5,5),r=new Ds({name:"CubemapFromEquirect",uniforms:Ls(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:d,blending:f});r.uniforms.tEquirect.value=e;const s=new Rs(i,r),a=e.minFilter;e.minFilter===vt&&(e.minFilter=mt);return new zs(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}const Vs=new gi,Gs=new gi,Ws=new Hn;class Xs{constructor(t=new gi(1,0,0),e=0){this.isPlane=!0,this.normal=t,this.constant=e}set(t,e){return this.normal.copy(t),this.constant=e,this}setComponents(t,e,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=Vs.subVectors(n,e).cross(Gs.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,t),this}copy(t){return this.normal.copy(t.normal),this.constant=t.constant,this}normalize(){const t=1/this.normal.length();return this.normal.multiplyScalar(t),this.constant*=t,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(t){return this.normal.dot(t)+this.constant}distanceToSphere(t){return this.distanceToPoint(t.center)-t.radius}projectPoint(t,e){return e.copy(t).addScaledVector(this.normal,-this.distanceToPoint(t))}intersectLine(t,e){const n=t.delta(Vs),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const n=e||Ws.getNormalMatrix(t),i=this.coplanarPoint(Vs).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const js=new Fi,qs=new gi;class Ys{constructor(t=new Xs,e=new Xs,n=new Xs,i=new Xs,r=new Xs,s=new Xs){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t){const e=this.planes,n=t.elements,i=n[0],r=n[1],s=n[2],a=n[3],o=n[4],l=n[5],c=n[6],h=n[7],u=n[8],d=n[9],p=n[10],m=n[11],f=n[12],g=n[13],v=n[14],_=n[15];return e[0].setComponents(a-i,h-o,m-u,_-f).normalize(),e[1].setComponents(a+i,h+o,m+u,_+f).normalize(),e[2].setComponents(a+r,h+l,m+d,_+g).normalize(),e[3].setComponents(a-r,h-l,m-d,_-g).normalize(),e[4].setComponents(a-s,h-c,m-p,_-v).normalize(),e[5].setComponents(a+s,h+c,m+p,_+v).normalize(),this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&&t.computeBoundingSphere(),js.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&&e.computeBoundingSphere(),js.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(js)}intersectsSprite(t){return js.center.set(0,0,0),js.radius=.7071067811865476,js.applyMatrix4(t.matrixWorld),this.intersectsSphere(js)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(n)0?t.max.x:t.min.x,qs.y=i.normal.y>0?t.max.y:t.min.y,qs.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(qs)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function Zs(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==n&&(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function Js(t,e){const n=e.isWebGL2,i=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),i.get(t)},remove:function(e){e.isInterleavedBufferAttribute&&(e=e.data);const n=i.get(e);n&&(t.deleteBuffer(n.buffer),i.delete(e))},update:function(e,r){if(e.isGLBufferAttribute){const t=i.get(e);return void((!t||t.version 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tanisotropyV /= material.anisotropy;\n\tmaterial.anisotropy = saturate( material.anisotropy );\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x - tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x + tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometry.viewDir, geometry.normal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, vMapUv );\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal, vNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",output_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},Qs={common:{diffuse:{value:new Or(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new Hn},alphaMap:{value:null},alphaMapTransform:{value:new Hn},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new Hn}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new Hn}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new Hn}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new Hn},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new Hn},normalScale:{value:new zn(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new Hn},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new Hn}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new Hn}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new Hn}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Or(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Or(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new Hn},alphaTest:{value:0},uvTransform:{value:new Hn}},sprite:{diffuse:{value:new Or(16777215)},opacity:{value:1},center:{value:new zn(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new Hn},alphaMap:{value:null},alphaMapTransform:{value:new Hn},alphaTest:{value:0}}},ta={basic:{uniforms:Is([Qs.common,Qs.specularmap,Qs.envmap,Qs.aomap,Qs.lightmap,Qs.fog]),vertexShader:$s.meshbasic_vert,fragmentShader:$s.meshbasic_frag},lambert:{uniforms:Is([Qs.common,Qs.specularmap,Qs.envmap,Qs.aomap,Qs.lightmap,Qs.emissivemap,Qs.bumpmap,Qs.normalmap,Qs.displacementmap,Qs.fog,Qs.lights,{emissive:{value:new Or(0)}}]),vertexShader:$s.meshlambert_vert,fragmentShader:$s.meshlambert_frag},phong:{uniforms:Is([Qs.common,Qs.specularmap,Qs.envmap,Qs.aomap,Qs.lightmap,Qs.emissivemap,Qs.bumpmap,Qs.normalmap,Qs.displacementmap,Qs.fog,Qs.lights,{emissive:{value:new Or(0)},specular:{value:new Or(1118481)},shininess:{value:30}}]),vertexShader:$s.meshphong_vert,fragmentShader:$s.meshphong_frag},standard:{uniforms:Is([Qs.common,Qs.envmap,Qs.aomap,Qs.lightmap,Qs.emissivemap,Qs.bumpmap,Qs.normalmap,Qs.displacementmap,Qs.roughnessmap,Qs.metalnessmap,Qs.fog,Qs.lights,{emissive:{value:new Or(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:$s.meshphysical_vert,fragmentShader:$s.meshphysical_frag},toon:{uniforms:Is([Qs.common,Qs.aomap,Qs.lightmap,Qs.emissivemap,Qs.bumpmap,Qs.normalmap,Qs.displacementmap,Qs.gradientmap,Qs.fog,Qs.lights,{emissive:{value:new Or(0)}}]),vertexShader:$s.meshtoon_vert,fragmentShader:$s.meshtoon_frag},matcap:{uniforms:Is([Qs.common,Qs.bumpmap,Qs.normalmap,Qs.displacementmap,Qs.fog,{matcap:{value:null}}]),vertexShader:$s.meshmatcap_vert,fragmentShader:$s.meshmatcap_frag},points:{uniforms:Is([Qs.points,Qs.fog]),vertexShader:$s.points_vert,fragmentShader:$s.points_frag},dashed:{uniforms:Is([Qs.common,Qs.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:$s.linedashed_vert,fragmentShader:$s.linedashed_frag},depth:{uniforms:Is([Qs.common,Qs.displacementmap]),vertexShader:$s.depth_vert,fragmentShader:$s.depth_frag},normal:{uniforms:Is([Qs.common,Qs.bumpmap,Qs.normalmap,Qs.displacementmap,{opacity:{value:1}}]),vertexShader:$s.meshnormal_vert,fragmentShader:$s.meshnormal_frag},sprite:{uniforms:Is([Qs.sprite,Qs.fog]),vertexShader:$s.sprite_vert,fragmentShader:$s.sprite_frag},background:{uniforms:{uvTransform:{value:new Hn},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:$s.background_vert,fragmentShader:$s.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:$s.backgroundCube_vert,fragmentShader:$s.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:$s.cube_vert,fragmentShader:$s.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:$s.equirect_vert,fragmentShader:$s.equirect_frag},distanceRGBA:{uniforms:Is([Qs.common,Qs.displacementmap,{referencePosition:{value:new gi},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:$s.distanceRGBA_vert,fragmentShader:$s.distanceRGBA_frag},shadow:{uniforms:Is([Qs.lights,Qs.fog,{color:{value:new Or(0)},opacity:{value:1}}]),vertexShader:$s.shadow_vert,fragmentShader:$s.shadow_frag}};ta.physical={uniforms:Is([ta.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new Hn},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new Hn},clearcoatNormalScale:{value:new zn(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new Hn},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new Hn},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new Hn},sheen:{value:0},sheenColor:{value:new Or(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new Hn},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new Hn},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new Hn},transmissionSamplerSize:{value:new zn},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new Hn},attenuationDistance:{value:0},attenuationColor:{value:new Or(0)},specularColor:{value:new Or(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new Hn},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new Hn},anisotropyVector:{value:new zn},anisotropyMap:{value:null},anisotropyMapTransform:{value:new Hn}}]),vertexShader:$s.meshphysical_vert,fragmentShader:$s.meshphysical_frag};const ea={r:0,b:0,g:0};function na(t,e,n,i,r,s,a){const o=new Or(0);let l,c,h=!0===s?0:1,p=null,m=0,f=null;function g(e,n){e.getRGB(ea,Us(t)),i.buffers.color.setClear(ea.r,ea.g,ea.b,n,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),h=e,g(o,h)},getClearAlpha:function(){return h},setClearAlpha:function(t){h=t,g(o,h)},render:function(s,v){let _=!1,y=!0===v.isScene?v.background:null;if(y&&y.isTexture){y=(v.backgroundBlurriness>0?n:e).get(y)}switch(null===y?g(o,h):y&&y.isColor&&(g(y,1),_=!0),t.xr.getEnvironmentBlendMode()){case"opaque":_=!0;break;case"additive":i.buffers.color.setClear(0,0,0,1,a),_=!0;break;case"alpha-blend":i.buffers.color.setClear(0,0,0,0,a),_=!0}(t.autoClear||_)&&t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil),y&&(y.isCubeTexture||y.mapping===st)?(void 0===c&&(c=new Rs(new Ps(1,1,1),new Ds({name:"BackgroundCubeMaterial",uniforms:Ls(ta.backgroundCube.uniforms),vertexShader:ta.backgroundCube.vertexShader,fragmentShader:ta.backgroundCube.fragmentShader,side:d,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(c)),c.material.uniforms.envMap.value=y,c.material.uniforms.flipEnvMap.value=y.isCubeTexture&&!1===y.isRenderTargetTexture?-1:1,c.material.uniforms.backgroundBlurriness.value=v.backgroundBlurriness,c.material.uniforms.backgroundIntensity.value=v.backgroundIntensity,c.material.toneMapped=y.colorSpace!==Be,p===y&&m===y.version&&f===t.toneMapping||(c.material.needsUpdate=!0,p=y,m=y.version,f=t.toneMapping),c.layers.enableAll(),s.unshift(c,c.geometry,c.material,0,0,null)):y&&y.isTexture&&(void 0===l&&(l=new Rs(new Ks(2,2),new Ds({name:"BackgroundMaterial",uniforms:Ls(ta.background.uniforms),vertexShader:ta.background.vertexShader,fragmentShader:ta.background.fragmentShader,side:u,depthTest:!1,depthWrite:!1,fog:!1})),l.geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(l)),l.material.uniforms.t2D.value=y,l.material.uniforms.backgroundIntensity.value=v.backgroundIntensity,l.material.toneMapped=y.colorSpace!==Be,!0===y.matrixAutoUpdate&&y.updateMatrix(),l.material.uniforms.uvTransform.value.copy(y.matrix),p===y&&m===y.version&&f===t.toneMapping||(l.material.needsUpdate=!0,p=y,m=y.version,f=t.toneMapping),l.layers.enableAll(),s.unshift(l,l.geometry,l.material,0,0,null))}}}function ia(t,e,n,i){const r=t.getParameter(t.MAX_VERTEX_ATTRIBS),s=i.isWebGL2?null:e.get("OES_vertex_array_object"),a=i.isWebGL2||null!==s,o={},l=p(null);let c=l,h=!1;function u(e){return i.isWebGL2?t.bindVertexArray(e):s.bindVertexArrayOES(e)}function d(e){return i.isWebGL2?t.deleteVertexArray(e):s.deleteVertexArrayOES(e)}function p(t){const e=[],n=[],i=[];for(let t=0;t=0){const n=r[e];let i=s[e];if(void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;a++}}return c.attributesNum!==a||c.index!==i}(r,y,d,x),M&&function(t,e,n,i){const r={},s=e.attributes;let a=0;const o=n.getAttributes();for(const e in o){if(o[e].location>=0){let n=s[e];void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[e]=i,a++}}c.attributes=r,c.attributesNum=a,c.index=i}(r,y,d,x)}else{const t=!0===l.wireframe;c.geometry===y.id&&c.program===d.id&&c.wireframe===t||(c.geometry=y.id,c.program=d.id,c.wireframe=t,M=!0)}null!==x&&n.update(x,t.ELEMENT_ARRAY_BUFFER),(M||h)&&(h=!1,function(r,s,a,o){if(!1===i.isWebGL2&&(r.isInstancedMesh||o.isInstancedBufferGeometry)&&null===e.get("ANGLE_instanced_arrays"))return;m();const l=o.attributes,c=a.getAttributes(),h=s.defaultAttributeValues;for(const e in c){const s=c[e];if(s.location>=0){let a=l[e];if(void 0===a&&("instanceMatrix"===e&&r.instanceMatrix&&(a=r.instanceMatrix),"instanceColor"===e&&r.instanceColor&&(a=r.instanceColor)),void 0!==a){const e=a.normalized,l=a.itemSize,c=n.get(a);if(void 0===c)continue;const h=c.buffer,u=c.type,d=c.bytesPerElement,p=!0===i.isWebGL2&&(u===t.INT||u===t.UNSIGNED_INT||a.gpuType===bt);if(a.isInterleavedBufferAttribute){const n=a.data,i=n.stride,c=a.offset;if(n.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.HIGH_FLOAT).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(t.VERTEX_SHADER,t.MEDIUM_FLOAT).precision>0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}const s="undefined"!=typeof WebGL2RenderingContext&&"WebGL2RenderingContext"===t.constructor.name;let a=void 0!==n.precision?n.precision:"highp";const o=r(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=s||e.has("WEBGL_draw_buffers"),c=!0===n.logarithmicDepthBuffer,h=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),u=t.getParameter(t.MAX_VERTEX_TEXTURE_IMAGE_UNITS),d=t.getParameter(t.MAX_TEXTURE_SIZE),p=t.getParameter(t.MAX_CUBE_MAP_TEXTURE_SIZE),m=t.getParameter(t.MAX_VERTEX_ATTRIBS),f=t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS),g=t.getParameter(t.MAX_VARYING_VECTORS),v=t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS),_=u>0,y=s||e.has("OES_texture_float");return{isWebGL2:s,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==i)return i;if(!0===e.has("EXT_texture_filter_anisotropic")){const n=e.get("EXT_texture_filter_anisotropic");i=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else i=0;return i},getMaxPrecision:r,precision:a,logarithmicDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:m,maxVertexUniforms:f,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:_,floatFragmentTextures:y,floatVertexTextures:_&&y,maxSamples:s?t.getParameter(t.MAX_SAMPLES):0}}function aa(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new Xs,o=new Hn,l={value:null,needsUpdate:!1};function c(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);e.numPlanes=i,e.numIntersection=0}();else{const t=s?0:i,e=4*t;let r=m.clippingState||null;l.value=r,r=c(u,o,e,h);for(let t=0;t!==e;++t)r[t]=n[t];m.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=t}}}function oa(t){let e=new WeakMap;function n(t,e){return e===it?t.mapping=et:e===rt&&(t.mapping=nt),t}function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture&&!1===r.isRenderTargetTexture){const s=r.mapping;if(s===it||s===rt){if(e.has(r)){return n(e.get(r).texture,r.mapping)}{const s=r.image;if(s&&s.height>0){const a=new ks(s.height/2);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",i),n(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class la extends Os{constructor(t=-1,e=1,n=1,i=-1,r=.1,s=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=t,this.right=e,this.top=n,this.bottom=i,this.near=r,this.far=s,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.left=t.left,this.right=t.right,this.top=t.top,this.bottom=t.bottom,this.near=t.near,this.far=t.far,this.zoom=t.zoom,this.view=null===t.view?null:Object.assign({},t.view),this}setViewOffset(t,e,n,i,r,s){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=s,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=(this.right-this.left)/(2*this.zoom),e=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-e;if(null!==this.view&&this.view.enabled){const t=(this.right-this.left)/this.view.fullWidth/this.zoom,e=(this.top-this.bottom)/this.view.fullHeight/this.zoom;r+=t*this.view.offsetX,s=r+t*this.view.width,a-=e*this.view.offsetY,o=a-e*this.view.height}this.projectionMatrix.makeOrthographic(r,s,a,o,this.near,this.far),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.zoom=this.zoom,e.object.left=this.left,e.object.right=this.right,e.object.top=this.top,e.object.bottom=this.bottom,e.object.near=this.near,e.object.far=this.far,null!==this.view&&(e.object.view=Object.assign({},this.view)),e}}const ca=4,ha=[.125,.215,.35,.446,.526,.582],ua=20,da=new la,pa=new Or;let ma=null;const fa=(1+Math.sqrt(5))/2,ga=1/fa,va=[new gi(1,1,1),new gi(-1,1,1),new gi(1,1,-1),new gi(-1,1,-1),new gi(0,fa,ga),new gi(0,fa,-ga),new gi(ga,0,fa),new gi(-ga,0,fa),new gi(fa,ga,0),new gi(-fa,ga,0)];class _a{constructor(t){this._renderer=t,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(t,e=0,n=.1,i=100){ma=this._renderer.getRenderTarget(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,i,r),e>0&&this._blur(r,0,0,e),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(t,e=null){return this._fromTexture(t,e)}fromCubemap(t,e=null){return this._fromTexture(t,e)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=Sa(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=Ma(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(t){this._lodMax=Math.floor(Math.log2(t)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let t=0;tt-ca?o=ha[a-t+ca-1]:0===a&&(o=0),i.push(o);const l=1/(s-2),c=-l,h=1+l,u=[c,c,h,c,h,h,c,c,h,h,c,h],d=6,p=6,m=3,f=2,g=1,v=new Float32Array(m*p*d),_=new Float32Array(f*p*d),y=new Float32Array(g*p*d);for(let t=0;t2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];v.set(i,m*p*t),_.set(u,f*p*t);const r=[t,t,t,t,t,t];y.set(r,g*p*t)}const x=new hs;x.setAttribute("position",new jr(v,m)),x.setAttribute("uv",new jr(_,f)),x.setAttribute("faceIndex",new jr(y,g)),e.push(x),r>ca&&r--}return{lodPlanes:e,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(t,e,n){const i=new Float32Array(ua),r=new gi(0,1,0),s=new Ds({name:"SphericalGaussianBlur",defines:{n:ua,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:ba(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:f,depthTest:!1,depthWrite:!1});return s}(i,t,e)}return i}_compileMaterial(t){const e=new Rs(this._lodPlanes[0],t);this._renderer.compile(e,da)}_sceneToCubeUV(t,e,n,i){const r=new Fs(90,1,e,n),s=[1,-1,1,1,1,1],a=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,c=o.toneMapping;o.getClearColor(pa),o.toneMapping=Y,o.autoClear=!1;const h=new Br({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1}),u=new Rs(new Ps,h);let p=!1;const m=t.background;m?m.isColor&&(h.color.copy(m),t.background=null,p=!0):(h.color.copy(pa),p=!0);for(let e=0;e<6;e++){const n=e%3;0===n?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===n?(r.up.set(0,0,s[e]),r.lookAt(0,a[e],0)):(r.up.set(0,s[e],0),r.lookAt(0,0,a[e]));const l=this._cubeSize;xa(i,n*l,e>2?l:0,l,l),o.setRenderTarget(i),p&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=m}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===et||t.mapping===nt;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=Sa()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=Ma());const r=i?this._cubemapMaterial:this._equirectMaterial,s=new Rs(this._lodPlanes[0],r);r.uniforms.envMap.value=t;const a=this._cubeSize;xa(e,0,0,3*a,2*a),n.setRenderTarget(e),n.render(s,da)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;for(let e=1;eua&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to ${ua}`);const f=[];let g=0;for(let t=0;tv-ca?i-v+ca:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(e),o.render(c,da)}}function ya(t,e,n){const i=new ci(t,e,n);return i.texture.mapping=st,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function xa(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function Ma(){return new Ds({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:ba(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:f,depthTest:!1,depthWrite:!1})}function Sa(){return new Ds({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:ba(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:f,depthTest:!1,depthWrite:!1})}function ba(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function Ea(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const s=r.mapping,a=s===it||s===rt,o=s===et||s===nt;if(a||o){if(r.isRenderTargetTexture&&!0===r.needsPMREMUpdate){r.needsPMREMUpdate=!1;let i=e.get(r);return null===n&&(n=new _a(t)),i=a?n.fromEquirectangular(r,i):n.fromCubemap(r,i),e.set(r,i),i.texture}if(e.has(r))return e.get(r).texture;{const s=r.image;if(a&&s&&s.height>0||o&&s&&function(t){let e=0;const n=6;for(let i=0;ie.maxTextureSize&&(m=Math.ceil(p/e.maxTextureSize),p=e.maxTextureSize);const f=new Float32Array(p*m*4*r),g=new hi(f,p,m,r);g.type=Tt,g.needsUpdate=!0;const v=4*d;for(let e=0;e0)return t;const r=e*n;let s=Fa[r];if(void 0===s&&(s=new Float32Array(r),Fa[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function Ga(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n":" "} ${r}: ${n[t]}`)}return i.join("\n")}(t.getShaderSource(e),i)}return r}function ko(t,e){const n=function(t){switch(t){case ze:return["Linear","( value )"];case Be:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",t),["Linear","( value )"]}}(e);return"vec4 "+t+"( vec4 value ) { return LinearTo"+n[0]+n[1]+"; }"}function Vo(t,e){let n;switch(e){case Z:n="Linear";break;case J:n="Reinhard";break;case K:n="OptimizedCineon";break;case $:n="ACESFilmic";break;case Q:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),n="Linear"}return"vec3 "+t+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}function Go(t){return""!==t}function Wo(t,e){const n=e.numSpotLightShadows+e.numSpotLightMaps-e.numSpotLightShadowsWithMaps;return t.replace(/NUM_DIR_LIGHTS/g,e.numDirLights).replace(/NUM_SPOT_LIGHTS/g,e.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,e.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,e.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,e.numPointLights).replace(/NUM_HEMI_LIGHTS/g,e.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,e.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,e.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,e.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,e.numPointLightShadows)}function Xo(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const jo=/^[ \t]*#include +<([\w\d./]+)>/gm;function qo(t){return t.replace(jo,Yo)}function Yo(t,e){const n=$s[e];if(void 0===n)throw new Error("Can not resolve #include <"+e+">");return qo(n)}const Zo=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function Jo(t){return t.replace(Zo,Ko)}function Ko(t,e,n,i){let r="";for(let t=parseInt(e);t0&&(y+="\n"),x=[g,"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v].filter(Go).join("\n"),x.length>0&&(x+="\n")):(y=[$o(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors&&n.isWebGL2?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0&&n.isWebGL2?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.useLegacyLights?"#define LEGACY_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Go).join("\n"),x=[g,$o(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.envMap?"#define "+m:"",f?"#define CUBEUV_TEXEL_WIDTH "+f.texelWidth:"",f?"#define CUBEUV_TEXEL_HEIGHT "+f.texelHeight:"",f?"#define CUBEUV_MAX_MIP "+f.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.useLegacyLights?"#define LEGACY_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",n.toneMapping!==Y?"#define TONE_MAPPING":"",n.toneMapping!==Y?$s.tonemapping_pars_fragment:"",n.toneMapping!==Y?Vo("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",$s.encodings_pars_fragment,ko("linearToOutputTexel",n.outputColorSpace),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Go).join("\n")),a=qo(a),a=Wo(a,n),a=Xo(a,n),o=qo(o),o=Wo(o,n),o=Xo(o,n),a=Jo(a),o=Jo(o),n.isWebGL2&&!0!==n.isRawShaderMaterial&&(M="#version 300 es\n",y=["precision mediump sampler2DArray;","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+y,x=["#define varying in",n.glslVersion===Sn?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===Sn?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+x);const S=M+y+a,b=M+x+o,E=Bo(r,r.VERTEX_SHADER,S),T=Bo(r,r.FRAGMENT_SHADER,b);if(r.attachShader(_,E),r.attachShader(_,T),void 0!==n.index0AttributeName?r.bindAttribLocation(_,0,n.index0AttributeName):!0===n.morphTargets&&r.bindAttribLocation(_,0,"position"),r.linkProgram(_),t.debug.checkShaderErrors){const e=r.getProgramInfoLog(_).trim(),n=r.getShaderInfoLog(E).trim(),i=r.getShaderInfoLog(T).trim();let s=!0,a=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(s=!1,"function"==typeof t.debug.onShaderError)t.debug.onShaderError(r,_,E,T);else{const t=Ho(r,E,"vertex"),n=Ho(r,T,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nProgram Info Log: "+e+"\n"+t+"\n"+n)}else""!==e?console.warn("THREE.WebGLProgram: Program Info Log:",e):""!==n&&""!==i||(a=!1);a&&(this.diagnostics={runnable:s,programLog:e,vertexShader:{log:n,prefix:y},fragmentShader:{log:i,prefix:x}})}let w,A;return r.deleteShader(E),r.deleteShader(T),this.getUniforms=function(){return void 0===w&&(w=new Fo(r,_)),w},this.getAttributes=function(){return void 0===A&&(A=function(t,e){const n={},i=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES);for(let r=0;r0,Z=s.clearcoat>0,J=s.iridescence>0,K=s.sheen>0,$=s.transmission>0,Q=q&&!!s.anisotropyMap,tt=Z&&!!s.clearcoatMap,et=Z&&!!s.clearcoatNormalMap,nt=Z&&!!s.clearcoatRoughnessMap,it=J&&!!s.iridescenceMap,rt=J&&!!s.iridescenceThicknessMap,at=K&&!!s.sheenColorMap,ot=K&&!!s.sheenRoughnessMap,lt=!!s.specularMap,ct=!!s.specularColorMap,ht=!!s.specularIntensityMap,ut=$&&!!s.transmissionMap,dt=$&&!!s.thicknessMap,pt=!!s.gradientMap,mt=!!s.alphaMap,ft=s.alphaTest>0,gt=!!s.extensions,vt=!!S.attributes.uv1,_t=!!S.attributes.uv2,yt=!!S.attributes.uv3;return{isWebGL2:h,shaderID:w,shaderType:s.type,shaderName:s.name,vertexShader:C,fragmentShader:P,defines:s.defines,customVertexShaderID:L,customFragmentShaderID:I,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:f,instancing:D,instancingColor:D&&null!==x.instanceColor,supportsVertexTextures:m,outputColorSpace:null===N?t.outputColorSpace:!0===N.isXRRenderTarget?N.texture.colorSpace:ze,map:O,matcap:F,envMap:B,envMapMode:B&&E.mapping,envMapCubeUVHeight:T,aoMap:z,lightMap:H,bumpMap:k,normalMap:V,displacementMap:m&&G,emissiveMap:W,normalMapObjectSpace:V&&s.normalMapType===Oe,normalMapTangentSpace:V&&s.normalMapType===De,metalnessMap:X,roughnessMap:j,anisotropy:q,anisotropyMap:Q,clearcoat:Z,clearcoatMap:tt,clearcoatNormalMap:et,clearcoatRoughnessMap:nt,iridescence:J,iridescenceMap:it,iridescenceThicknessMap:rt,sheen:K,sheenColorMap:at,sheenRoughnessMap:ot,specularMap:lt,specularColorMap:ct,specularIntensityMap:ht,transmission:$,transmissionMap:ut,thicknessMap:dt,gradientMap:pt,opaque:!1===s.transparent&&s.blending===g,alphaMap:mt,alphaTest:ft,combine:s.combine,mapUv:O&&_(s.map.channel),aoMapUv:z&&_(s.aoMap.channel),lightMapUv:H&&_(s.lightMap.channel),bumpMapUv:k&&_(s.bumpMap.channel),normalMapUv:V&&_(s.normalMap.channel),displacementMapUv:G&&_(s.displacementMap.channel),emissiveMapUv:W&&_(s.emissiveMap.channel),metalnessMapUv:X&&_(s.metalnessMap.channel),roughnessMapUv:j&&_(s.roughnessMap.channel),anisotropyMapUv:Q&&_(s.anisotropyMap.channel),clearcoatMapUv:tt&&_(s.clearcoatMap.channel),clearcoatNormalMapUv:et&&_(s.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:nt&&_(s.clearcoatRoughnessMap.channel),iridescenceMapUv:it&&_(s.iridescenceMap.channel),iridescenceThicknessMapUv:rt&&_(s.iridescenceThicknessMap.channel),sheenColorMapUv:at&&_(s.sheenColorMap.channel),sheenRoughnessMapUv:ot&&_(s.sheenRoughnessMap.channel),specularMapUv:lt&&_(s.specularMap.channel),specularColorMapUv:ct&&_(s.specularColorMap.channel),specularIntensityMapUv:ht&&_(s.specularIntensityMap.channel),transmissionMapUv:ut&&_(s.transmissionMap.channel),thicknessMapUv:dt&&_(s.thicknessMap.channel),alphaMapUv:mt&&_(s.alphaMap.channel),vertexTangents:!!S.attributes.tangent&&(V||q),vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!S.attributes.color&&4===S.attributes.color.itemSize,vertexUv1s:vt,vertexUv2s:_t,vertexUv3s:yt,pointsUvs:!0===x.isPoints&&!!S.attributes.uv&&(O||mt),fog:!!M,useFog:!0===s.fog,fogExp2:M&&M.isFogExp2,flatShading:!0===s.flatShading,sizeAttenuation:!0===s.sizeAttenuation,logarithmicDepthBuffer:u,skinning:!0===x.isSkinnedMesh,morphTargets:void 0!==S.morphAttributes.position,morphNormals:void 0!==S.morphAttributes.normal,morphColors:void 0!==S.morphAttributes.color,morphTargetsCount:R,morphTextureStride:U,numDirLights:o.directional.length,numPointLights:o.point.length,numSpotLights:o.spot.length,numSpotLightMaps:o.spotLightMap.length,numRectAreaLights:o.rectArea.length,numHemiLights:o.hemi.length,numDirLightShadows:o.directionalShadowMap.length,numPointLightShadows:o.pointShadowMap.length,numSpotLightShadows:o.spotShadowMap.length,numSpotLightShadowsWithMaps:o.numSpotLightShadowsWithMaps,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&c.length>0,shadowMapType:t.shadowMap.type,toneMapping:s.toneMapped?t.toneMapping:Y,useLegacyLights:t.useLegacyLights,premultipliedAlpha:s.premultipliedAlpha,doubleSided:s.side===p,flipSided:s.side===d,useDepthPacking:s.depthPacking>=0,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionDerivatives:gt&&!0===s.extensions.derivatives,extensionFragDepth:gt&&!0===s.extensions.fragDepth,extensionDrawBuffers:gt&&!0===s.extensions.drawBuffers,extensionShaderTextureLOD:gt&&!0===s.extensions.shaderTextureLOD,rendererExtensionFragDepth:h||i.has("EXT_frag_depth"),rendererExtensionDrawBuffers:h||i.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:h||i.has("EXT_shader_texture_lod"),customProgramCacheKey:s.customProgramCacheKey()}},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.customVertexShaderID),n.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputColorSpace),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.mapUv),t.push(e.alphaMapUv),t.push(e.lightMapUv),t.push(e.aoMapUv),t.push(e.bumpMapUv),t.push(e.normalMapUv),t.push(e.displacementMapUv),t.push(e.emissiveMapUv),t.push(e.metalnessMapUv),t.push(e.roughnessMapUv),t.push(e.anisotropyMapUv),t.push(e.clearcoatMapUv),t.push(e.clearcoatNormalMapUv),t.push(e.clearcoatRoughnessMapUv),t.push(e.iridescenceMapUv),t.push(e.iridescenceThicknessMapUv),t.push(e.sheenColorMapUv),t.push(e.sheenRoughnessMapUv),t.push(e.specularMapUv),t.push(e.specularColorMapUv),t.push(e.specularIntensityMapUv),t.push(e.transmissionMapUv),t.push(e.thicknessMapUv),t.push(e.combine),t.push(e.fogExp2),t.push(e.sizeAttenuation),t.push(e.morphTargetsCount),t.push(e.morphAttributeCount),t.push(e.numDirLights),t.push(e.numPointLights),t.push(e.numSpotLights),t.push(e.numSpotLightMaps),t.push(e.numHemiLights),t.push(e.numRectAreaLights),t.push(e.numDirLightShadows),t.push(e.numPointLightShadows),t.push(e.numSpotLightShadows),t.push(e.numSpotLightShadowsWithMaps),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(n,e),function(t,e){o.disableAll(),e.isWebGL2&&o.enable(0);e.supportsVertexTextures&&o.enable(1);e.instancing&&o.enable(2);e.instancingColor&&o.enable(3);e.matcap&&o.enable(4);e.envMap&&o.enable(5);e.normalMapObjectSpace&&o.enable(6);e.normalMapTangentSpace&&o.enable(7);e.clearcoat&&o.enable(8);e.iridescence&&o.enable(9);e.alphaTest&&o.enable(10);e.vertexColors&&o.enable(11);e.vertexAlphas&&o.enable(12);e.vertexUv1s&&o.enable(13);e.vertexUv2s&&o.enable(14);e.vertexUv3s&&o.enable(15);e.vertexTangents&&o.enable(16);e.anisotropy&&o.enable(17);t.push(o.mask),o.disableAll(),e.fog&&o.enable(0);e.useFog&&o.enable(1);e.flatShading&&o.enable(2);e.logarithmicDepthBuffer&&o.enable(3);e.skinning&&o.enable(4);e.morphTargets&&o.enable(5);e.morphNormals&&o.enable(6);e.morphColors&&o.enable(7);e.premultipliedAlpha&&o.enable(8);e.shadowMapEnabled&&o.enable(9);e.useLegacyLights&&o.enable(10);e.doubleSided&&o.enable(11);e.flipSided&&o.enable(12);e.useDepthPacking&&o.enable(13);e.dithering&&o.enable(14);e.transmission&&o.enable(15);e.sheen&&o.enable(16);e.opaque&&o.enable(17);e.pointsUvs&&o.enable(18);t.push(o.mask)}(n,e),n.push(t.outputColorSpace)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=v[t.type];let n;if(e){const t=ta[e];n=Ns.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=c.length;t0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n1&&n.sort(t||sl),i.length>1&&i.sort(e||al),r.length>1&&r.sort(e||al)}}}function ll(){let t=new WeakMap;return{get:function(e,n){const i=t.get(e);let r;return void 0===i?(r=new ol,t.set(e,[r])):n>=i.length?(r=new ol,i.push(r)):r=i[n],r},dispose:function(){t=new WeakMap}}}function cl(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":n={direction:new gi,color:new Or};break;case"SpotLight":n={position:new gi,direction:new gi,color:new Or,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new gi,color:new Or,distance:0,decay:0};break;case"HemisphereLight":n={direction:new gi,skyColor:new Or,groundColor:new Or};break;case"RectAreaLight":n={color:new Or,position:new gi,halfWidth:new gi,halfHeight:new gi}}return t[e.id]=n,n}}}let hl=0;function ul(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function dl(t,e){const n=new cl,i=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":case"SpotLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new zn};break;case"PointLight":n={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new zn,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0};for(let t=0;t<9;t++)r.probe.push(new gi);const s=new gi,a=new ji,o=new ji;return{setup:function(s,a){let o=0,l=0,c=0;for(let t=0;t<9;t++)r.probe[t].set(0,0,0);let h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,_=0,y=0;s.sort(ul);const x=!0===a?Math.PI:1;for(let t=0,e=s.length;t0&&(e.isWebGL2||!0===t.has("OES_texture_float_linear")?(r.rectAreaLTC1=Qs.LTC_FLOAT_1,r.rectAreaLTC2=Qs.LTC_FLOAT_2):!0===t.has("OES_texture_half_float_linear")?(r.rectAreaLTC1=Qs.LTC_HALF_1,r.rectAreaLTC2=Qs.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),r.ambient[0]=o,r.ambient[1]=l,r.ambient[2]=c;const M=r.hash;M.directionalLength===h&&M.pointLength===u&&M.spotLength===d&&M.rectAreaLength===p&&M.hemiLength===m&&M.numDirectionalShadows===f&&M.numPointShadows===g&&M.numSpotShadows===v&&M.numSpotMaps===_||(r.directional.length=h,r.spot.length=d,r.rectArea.length=p,r.point.length=u,r.hemi.length=m,r.directionalShadow.length=f,r.directionalShadowMap.length=f,r.pointShadow.length=g,r.pointShadowMap.length=g,r.spotShadow.length=v,r.spotShadowMap.length=v,r.directionalShadowMatrix.length=f,r.pointShadowMatrix.length=g,r.spotLightMatrix.length=v+_-y,r.spotLightMap.length=_,r.numSpotLightShadowsWithMaps=y,M.directionalLength=h,M.pointLength=u,M.spotLength=d,M.rectAreaLength=p,M.hemiLength=m,M.numDirectionalShadows=f,M.numPointShadows=g,M.numSpotShadows=v,M.numSpotMaps=_,r.version=hl++)},setupView:function(t,e){let n=0,i=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=s.length?(a=new pl(t,e),s.push(a)):a=s[r],a},dispose:function(){n=new WeakMap}}}class fl extends Lr{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class gl extends Lr{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function vl(t,e,n){let i=new Ys;const r=new zn,s=new zn,a=new li,o=new fl({depthPacking:Ne}),c=new gl,m={},g=n.maxTextureSize,v={[u]:d,[d]:u,[p]:p},_=new Ds({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new zn},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),y=_.clone();y.defines.HORIZONTAL_PASS=1;const x=new hs;x.setAttribute("position",new jr(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const M=new Rs(x,_),S=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=l;let b=this.type;function E(n,i){const s=e.update(M);_.defines.VSM_SAMPLES!==n.blurSamples&&(_.defines.VSM_SAMPLES=n.blurSamples,y.defines.VSM_SAMPLES=n.blurSamples,_.needsUpdate=!0,y.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new ci(r.x,r.y)),_.uniforms.shadow_pass.value=n.map.texture,_.uniforms.resolution.value=n.mapSize,_.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,s,_,M,null),y.uniforms.shadow_pass.value=n.mapPass.texture,y.uniforms.resolution.value=n.mapSize,y.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,s,y,M,null)}function T(e,n,i,r){let s=null;const a=!0===i.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(void 0!==a)s=a;else if(s=!0===i.isPointLight?c:o,t.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const t=s.uuid,e=n.uuid;let i=m[t];void 0===i&&(i={},m[t]=i);let r=i[e];void 0===r&&(r=s.clone(),i[e]=r),s=r}if(s.visible=n.visible,s.wireframe=n.wireframe,s.side=r===h?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:v[n.side],s.alphaMap=n.alphaMap,s.alphaTest=n.alphaTest,s.map=n.map,s.clipShadows=n.clipShadows,s.clippingPlanes=n.clippingPlanes,s.clipIntersection=n.clipIntersection,s.displacementMap=n.displacementMap,s.displacementScale=n.displacementScale,s.displacementBias=n.displacementBias,s.wireframeLinewidth=n.wireframeLinewidth,s.linewidth=n.linewidth,!0===i.isPointLight&&!0===s.isMeshDistanceMaterial){t.properties.get(s).light=i}return s}function w(n,r,s,a,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&o===h)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const i=e.update(n),r=n.material;if(Array.isArray(r)){const e=i.groups;for(let l=0,c=e.length;lg||r.y>g)&&(r.x>g&&(s.x=Math.floor(g/f.x),r.x=s.x*f.x,u.mapSize.x=s.x),r.y>g&&(s.y=Math.floor(g/f.y),r.y=s.y*f.y,u.mapSize.y=s.y)),null===u.map||!0===p||!0===m){const t=this.type!==h?{minFilter:ct,magFilter:ct}:{};null!==u.map&&u.map.dispose(),u.map=new ci(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const v=u.getViewportCount();for(let t=0;t=1):-1!==dt.indexOf("OpenGL ES")&&(ut=parseFloat(/^OpenGL ES (\d)/.exec(dt)[1]),ht=ut>=2);let pt=null,mt={};const ft=t.getParameter(t.SCISSOR_BOX),gt=t.getParameter(t.VIEWPORT),vt=(new li).fromArray(ft),_t=(new li).fromArray(gt);function yt(e,n,i,r){const s=new Uint8Array(4),o=t.createTexture();t.bindTexture(e,o),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let o=0;oi||t.height>i)&&(r=i/Math.max(t.width,t.height)),r<1||!0===e){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const i=e?Dn:Math.floor,s=i(r*t.width),a=i(r*t.height);void 0===f&&(f=_(s,a));const o=n?_(s,a):f;o.width=s,o.height=a;return o.getContext("2d").drawImage(t,0,0,s,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+t.width+"x"+t.height+") to ("+s+"x"+a+")."),o}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+t.width+"x"+t.height+")."),t}return t}function x(t){return Un(t.width)&&Un(t.height)}function M(t,e){return t.generateMipmaps&&e&&t.minFilter!==ct&&t.minFilter!==mt}function S(e){t.generateMipmap(e)}function b(n,i,r,s,a=!1){if(!1===o)return i;if(null!==n){if(void 0!==t[n])return t[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let l=i;return i===t.RED&&(r===t.FLOAT&&(l=t.R32F),r===t.HALF_FLOAT&&(l=t.R16F),r===t.UNSIGNED_BYTE&&(l=t.R8)),i===t.RG&&(r===t.FLOAT&&(l=t.RG32F),r===t.HALF_FLOAT&&(l=t.RG16F),r===t.UNSIGNED_BYTE&&(l=t.RG8)),i===t.RGBA&&(r===t.FLOAT&&(l=t.RGBA32F),r===t.HALF_FLOAT&&(l=t.RGBA16F),r===t.UNSIGNED_BYTE&&(l=s===Be&&!1===a?t.SRGB8_ALPHA8:t.RGBA8),r===t.UNSIGNED_SHORT_4_4_4_4&&(l=t.RGBA4),r===t.UNSIGNED_SHORT_5_5_5_1&&(l=t.RGB5_A1)),l!==t.R16F&&l!==t.R32F&&l!==t.RG16F&&l!==t.RG32F&&l!==t.RGBA16F&&l!==t.RGBA32F||e.get("EXT_color_buffer_float"),l}function E(t,e,n){return!0===M(t,n)||t.isFramebufferTexture&&t.minFilter!==ct&&t.minFilter!==mt?Math.log2(Math.max(e.width,e.height))+1:void 0!==t.mipmaps&&t.mipmaps.length>0?t.mipmaps.length:t.isCompressedTexture&&Array.isArray(t.image)?e.mipmaps.length:1}function T(e){return e===ct||e===ht||e===dt?t.NEAREST:t.LINEAR}function w(t){const e=t.target;e.removeEventListener("dispose",w),function(t){const e=i.get(t);if(void 0===e.__webglInit)return;const n=t.source,r=g.get(n);if(r){const i=r[e.__cacheKey];i.usedTimes--,0===i.usedTimes&&R(t),0===Object.keys(r).length&&g.delete(n)}i.remove(t)}(e),e.isVideoTexture&&m.delete(e)}function A(e){const n=e.target;n.removeEventListener("dispose",A),function(e){const n=e.texture,r=i.get(e),s=i.get(n);void 0!==s.__webglTexture&&(t.deleteTexture(s.__webglTexture),a.memory.textures--);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++)t.deleteFramebuffer(r.__webglFramebuffer[e]),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer[e]);else{if(t.deleteFramebuffer(r.__webglFramebuffer),r.__webglDepthbuffer&&t.deleteRenderbuffer(r.__webglDepthbuffer),r.__webglMultisampledFramebuffer&&t.deleteFramebuffer(r.__webglMultisampledFramebuffer),r.__webglColorRenderbuffer)for(let e=0;e0&&s.__version!==e.version){const t=e.image;if(null===t)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==t.complete)return void O(s,e,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(t.TEXTURE_2D,s.__webglTexture,t.TEXTURE0+r)}const L={[at]:t.REPEAT,[ot]:t.CLAMP_TO_EDGE,[lt]:t.MIRRORED_REPEAT},I={[ct]:t.NEAREST,[ht]:t.NEAREST_MIPMAP_NEAREST,[dt]:t.NEAREST_MIPMAP_LINEAR,[mt]:t.LINEAR,[ft]:t.LINEAR_MIPMAP_NEAREST,[vt]:t.LINEAR_MIPMAP_LINEAR},U={[rn]:t.NEVER,[un]:t.ALWAYS,[sn]:t.LESS,[on]:t.LEQUAL,[an]:t.EQUAL,[hn]:t.GEQUAL,[ln]:t.GREATER,[cn]:t.NOTEQUAL};function N(n,s,a){if(a?(t.texParameteri(n,t.TEXTURE_WRAP_S,L[s.wrapS]),t.texParameteri(n,t.TEXTURE_WRAP_T,L[s.wrapT]),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,L[s.wrapR]),t.texParameteri(n,t.TEXTURE_MAG_FILTER,I[s.magFilter]),t.texParameteri(n,t.TEXTURE_MIN_FILTER,I[s.minFilter])):(t.texParameteri(n,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(n,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,t.CLAMP_TO_EDGE),s.wrapS===ot&&s.wrapT===ot||console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),t.texParameteri(n,t.TEXTURE_MAG_FILTER,T(s.magFilter)),t.texParameteri(n,t.TEXTURE_MIN_FILTER,T(s.minFilter)),s.minFilter!==ct&&s.minFilter!==mt&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),s.compareFunction&&(t.texParameteri(n,t.TEXTURE_COMPARE_MODE,t.COMPARE_REF_TO_TEXTURE),t.texParameteri(n,t.TEXTURE_COMPARE_FUNC,U[s.compareFunction])),!0===e.has("EXT_texture_filter_anisotropic")){const a=e.get("EXT_texture_filter_anisotropic");if(s.magFilter===ct)return;if(s.minFilter!==dt&&s.minFilter!==vt)return;if(s.type===Tt&&!1===e.has("OES_texture_float_linear"))return;if(!1===o&&s.type===wt&&!1===e.has("OES_texture_half_float_linear"))return;(s.anisotropy>1||i.get(s).__currentAnisotropy)&&(t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy)}}function D(e,n){let i=!1;void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",w));const r=n.source;let s=g.get(r);void 0===s&&(s={},g.set(r,s));const o=function(t){const e=[];return e.push(t.wrapS),e.push(t.wrapT),e.push(t.wrapR||0),e.push(t.magFilter),e.push(t.minFilter),e.push(t.anisotropy),e.push(t.internalFormat),e.push(t.format),e.push(t.type),e.push(t.generateMipmaps),e.push(t.premultiplyAlpha),e.push(t.flipY),e.push(t.unpackAlignment),e.push(t.colorSpace),e.join()}(n);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,i=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&R(n)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return i}function O(e,r,a){let l=t.TEXTURE_2D;(r.isDataArrayTexture||r.isCompressedArrayTexture)&&(l=t.TEXTURE_2D_ARRAY),r.isData3DTexture&&(l=t.TEXTURE_3D);const c=D(e,r),u=r.source;n.bindTexture(l,e.__webglTexture,t.TEXTURE0+a);const d=i.get(u);if(u.version!==d.__version||!0===c){n.activeTexture(t.TEXTURE0+a),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,r.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,r.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,t.NONE);const e=function(t){return!o&&(t.wrapS!==ot||t.wrapT!==ot||t.minFilter!==ct&&t.minFilter!==mt)}(r)&&!1===x(r.image);let i=y(r.image,e,!1,h);i=V(r,i);const p=x(i)||o,m=s.convert(r.format,r.colorSpace);let f,g=s.convert(r.type),v=b(r.internalFormat,m,g,r.colorSpace);N(l,r,p);const _=r.mipmaps,T=o&&!0!==r.isVideoTexture,w=void 0===d.__version||!0===c,A=E(r,i,p);if(r.isDepthTexture)v=t.DEPTH_COMPONENT,o?v=r.type===Tt?t.DEPTH_COMPONENT32F:r.type===Et?t.DEPTH_COMPONENT24:r.type===Ct?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT16:r.type===Tt&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),r.format===Nt&&v===t.DEPTH_COMPONENT&&r.type!==St&&r.type!==Et&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=Et,g=s.convert(r.type)),r.format===Dt&&v===t.DEPTH_COMPONENT&&(v=t.DEPTH_STENCIL,r.type!==Ct&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=Ct,g=s.convert(r.type))),w&&(T?n.texStorage2D(t.TEXTURE_2D,1,v,i.width,i.height):n.texImage2D(t.TEXTURE_2D,0,v,i.width,i.height,0,m,g,null));else if(r.isDataTexture)if(_.length>0&&p){T&&w&&n.texStorage2D(t.TEXTURE_2D,A,v,_[0].width,_[0].height);for(let e=0,i=_.length;e>=1,r>>=1}}else if(_.length>0&&p){T&&w&&n.texStorage2D(t.TEXTURE_2D,A,v,_[0].width,_[0].height);for(let e=0,i=_.length;e=t.TEXTURE_CUBE_MAP_POSITIVE_X&&l<=t.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&t.framebufferTexture2D(t.FRAMEBUFFER,o,l,i.get(a).__webglTexture,0),n.bindFramebuffer(t.FRAMEBUFFER,null)}function B(e,n,i){if(t.bindRenderbuffer(t.RENDERBUFFER,e),n.depthBuffer&&!n.stencilBuffer){let r=t.DEPTH_COMPONENT16;if(i||k(n)){const e=n.depthTexture;e&&e.isDepthTexture&&(e.type===Tt?r=t.DEPTH_COMPONENT32F:e.type===Et&&(r=t.DEPTH_COMPONENT24));const i=H(n);k(n)?d.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,i,r,n.width,n.height):t.renderbufferStorageMultisample(t.RENDERBUFFER,i,r,n.width,n.height)}else t.renderbufferStorage(t.RENDERBUFFER,r,n.width,n.height);t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.RENDERBUFFER,e)}else if(n.depthBuffer&&n.stencilBuffer){const r=H(n);i&&!1===k(n)?t.renderbufferStorageMultisample(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):k(n)?d.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,r,t.DEPTH24_STENCIL8,n.width,n.height):t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,n.width,n.height),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,e)}else{const e=!0===n.isWebGLMultipleRenderTargets?n.texture:[n.texture];for(let r=0;r0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function V(t,n){const i=t.colorSpace,r=t.format,s=t.type;return!0===t.isCompressedTexture||t.format===bn||i!==ze&&i!==Fe&&(i===Be?!1===o?!0===e.has("EXT_sRGB")&&r===Lt?(t.format=bn,t.minFilter=mt,t.generateMipmaps=!1):n=ni.sRGBToLinear(n):r===Lt&&s===yt||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",i)),n}this.allocateTextureUnit=function(){const t=C;return t>=l&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+l),C+=1,t},this.resetTextureUnits=function(){C=0},this.setTexture2D=P,this.setTexture2DArray=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?O(s,e,r):n.bindTexture(t.TEXTURE_2D_ARRAY,s.__webglTexture,t.TEXTURE0+r)},this.setTexture3D=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?O(s,e,r):n.bindTexture(t.TEXTURE_3D,s.__webglTexture,t.TEXTURE0+r)},this.setTextureCube=function(e,r){const a=i.get(e);e.version>0&&a.__version!==e.version?function(e,r,a){if(6!==r.image.length)return;const l=D(e,r),h=r.source;n.bindTexture(t.TEXTURE_CUBE_MAP,e.__webglTexture,t.TEXTURE0+a);const u=i.get(h);if(h.version!==u.__version||!0===l){n.activeTexture(t.TEXTURE0+a),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,r.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,r.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,t.NONE);const e=r.isCompressedTexture||r.image[0].isCompressedTexture,i=r.image[0]&&r.image[0].isDataTexture,d=[];for(let t=0;t<6;t++)d[t]=e||i?i?r.image[t].image:r.image[t]:y(r.image[t],!1,!0,c),d[t]=V(r,d[t]);const p=d[0],m=x(p)||o,f=s.convert(r.format,r.colorSpace),g=s.convert(r.type),v=b(r.internalFormat,f,g,r.colorSpace),_=o&&!0!==r.isVideoTexture,T=void 0===u.__version||!0===l;let w,A=E(r,p,m);if(N(t.TEXTURE_CUBE_MAP,r,m),e){_&&T&&n.texStorage2D(t.TEXTURE_CUBE_MAP,A,v,p.width,p.height);for(let e=0;e<6;e++){w=d[e].mipmaps;for(let i=0;i0&&A++,n.texStorage2D(t.TEXTURE_CUBE_MAP,A,v,d[0].width,d[0].height));for(let e=0;e<6;e++)if(i){_?n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,0,0,d[e].width,d[e].height,f,g,d[e].data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,v,d[e].width,d[e].height,0,f,g,d[e].data);for(let i=0;i0&&!1===k(e)){const i=d?l:[l];c.__webglMultisampledFramebuffer=t.createFramebuffer(),c.__webglColorRenderbuffer=[],n.bindFramebuffer(t.FRAMEBUFFER,c.__webglMultisampledFramebuffer);for(let n=0;n0&&!1===k(e)){const r=e.isWebGLMultipleRenderTargets?e.texture:[e.texture],s=e.width,a=e.height;let o=t.COLOR_BUFFER_BIT;const l=[],c=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,h=i.get(e),u=!0===e.isWebGLMultipleRenderTargets;if(u)for(let e=0;eo+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:t.handedness,target:this})):!l.inputState.pinching&&a<=o-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:t.handedness,target:this}))}else null!==o&&t.gripSpace&&(r=e.getPose(t.gripSpace,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1));null!==a&&(i=e.getPose(t.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),a.matrixWorldNeedsUpdate=!0,i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(bl)))}return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const n=new Sl;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}class Tl extends oi{constructor(t,e,n,i,r,s,a,o,l,c){if((c=void 0!==c?c:Nt)!==Nt&&c!==Dt)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===n&&c===Nt&&(n=Et),void 0===n&&c===Dt&&(n=Ct),super(null,i,r,s,a,o,c,n,l),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==a?a:ct,this.minFilter=void 0!==o?o:ct,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(t){return super.copy(t),this.compareFunction=t.compareFunction,this}toJSON(t){const e=super.toJSON(t);return null!==this.compareFunction&&(e.compareFunction=this.compareFunction),e}}class wl extends En{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const m=e.getContextAttributes();let f=null,g=null;const v=[],_=[];let y=null;const x=new Fs;x.layers.enable(1),x.viewport=new li;const M=new Fs;M.layers.enable(2),M.viewport=new li;const S=[x,M],b=new Ml;b.layers.enable(1),b.layers.enable(2);let E=null,T=null;function w(t){const e=_.indexOf(t.inputSource);if(-1===e)return;const n=v[e];void 0!==n&&(n.update(t.inputSource,t.frame,l||s),n.dispatchEvent({type:t.type,data:t.inputSource}))}function A(){i.removeEventListener("select",w),i.removeEventListener("selectstart",w),i.removeEventListener("selectend",w),i.removeEventListener("squeeze",w),i.removeEventListener("squeezestart",w),i.removeEventListener("squeezeend",w),i.removeEventListener("end",A),i.removeEventListener("inputsourceschange",R);for(let t=0;t=0&&(_[i]=null,v[i].disconnect(n))}for(let e=0;e=_.length){_.push(n),i=t;break}if(null===_[t]){_[t]=n,i=t;break}}if(-1===i)break}const r=v[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getCamera=function(){},this.setUserCamera=function(t){y=t},this.getController=function(t){let e=v[t];return void 0===e&&(e=new El,v[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=v[t];return void 0===e&&(e=new El,v[t]=e),e.getGripSpace()},this.getHand=function(t){let e=v[t];return void 0===e&&(e=new El,v[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){a=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||s},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(f=t.getRenderTarget(),i.addEventListener("select",w),i.addEventListener("selectstart",w),i.addEventListener("selectend",w),i.addEventListener("squeeze",w),i.addEventListener("squeezestart",w),i.addEventListener("squeezeend",w),i.addEventListener("end",A),i.addEventListener("inputsourceschange",R),!0!==m.xrCompatible&&await e.makeXRCompatible(),void 0===i.renderState.layers||!1===t.capabilities.isWebGL2){const n={antialias:void 0!==i.renderState.layers||m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,e,n),i.updateRenderState({baseLayer:d}),g=new ci(d.framebufferWidth,d.framebufferHeight,{format:Lt,type:yt,colorSpace:t.outputColorSpace,stencilBuffer:m.stencil})}else{let n=null,s=null,a=null;m.depth&&(a=m.stencil?e.DEPTH24_STENCIL8:e.DEPTH_COMPONENT24,n=m.stencil?Dt:Nt,s=m.stencil?Ct:Et);const o={colorFormat:e.RGBA8,depthFormat:a,scaleFactor:r};h=new XRWebGLBinding(i,e),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),g=new ci(u.textureWidth,u.textureHeight,{format:Lt,type:yt,depthTexture:new Tl(u.textureWidth,u.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:m.stencil,colorSpace:t.outputColorSpace,samples:m.antialias?4:0});t.properties.get(g).__ignoreDepthValues=u.ignoreDepthValues}g.isXRRenderTarget=!0,this.setFoveation(o),l=null,s=await i.requestReferenceSpace(a),U.setContext(i),U.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode};const C=new gi,P=new gi;function L(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.updateCameraXR=function(t){if(null===i)return t;y&&(t=y),b.near=M.near=x.near=t.near,b.far=M.far=x.far=t.far,E===b.near&&T===b.far||(i.updateRenderState({depthNear:b.near,depthFar:b.far}),E=b.near,T=b.far);const e=t.parent,n=b.cameras;L(b,e);for(let t=0;t0&&(i.alphaTest.value=r.alphaTest);const s=e.get(r).envMap;if(s&&(i.envMap.value=s,i.flipEnvMap.value=s.isCubeTexture&&!1===s.isRenderTargetTexture?-1:1,i.reflectivity.value=r.reflectivity,i.ior.value=r.ior,i.refractionRatio.value=r.refractionRatio),r.lightMap){i.lightMap.value=r.lightMap;const e=!0===t.useLegacyLights?Math.PI:1;i.lightMapIntensity.value=r.lightMapIntensity*e,n(r.lightMap,i.lightMapTransform)}r.aoMap&&(i.aoMap.value=r.aoMap,i.aoMapIntensity.value=r.aoMapIntensity,n(r.aoMap,i.aoMapTransform))}return{refreshFogUniforms:function(e,n){n.color.getRGB(e.fogColor.value,Us(t)),n.isFog?(e.fogNear.value=n.near,e.fogFar.value=n.far):n.isFogExp2&&(e.fogDensity.value=n.density)},refreshMaterialUniforms:function(t,r,s,a,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(t,r):r.isMeshToonMaterial?(i(t,r),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,r)):r.isMeshPhongMaterial?(i(t,r),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,r)):r.isMeshStandardMaterial?(i(t,r),function(t,i){t.metalness.value=i.metalness,i.metalnessMap&&(t.metalnessMap.value=i.metalnessMap,n(i.metalnessMap,t.metalnessMapTransform));t.roughness.value=i.roughness,i.roughnessMap&&(t.roughnessMap.value=i.roughnessMap,n(i.roughnessMap,t.roughnessMapTransform));const r=e.get(i).envMap;r&&(t.envMapIntensity.value=i.envMapIntensity)}(t,r),r.isMeshPhysicalMaterial&&function(t,e,i){t.ior.value=e.ior,e.sheen>0&&(t.sheenColor.value.copy(e.sheenColor).multiplyScalar(e.sheen),t.sheenRoughness.value=e.sheenRoughness,e.sheenColorMap&&(t.sheenColorMap.value=e.sheenColorMap,n(e.sheenColorMap,t.sheenColorMapTransform)),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap,n(e.sheenRoughnessMap,t.sheenRoughnessMapTransform)));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap,n(e.clearcoatMap,t.clearcoatMapTransform)),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap,n(e.clearcoatRoughnessMap,t.clearcoatRoughnessMapTransform)),e.clearcoatNormalMap&&(t.clearcoatNormalMap.value=e.clearcoatNormalMap,n(e.clearcoatNormalMap,t.clearcoatNormalMapTransform),t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),e.side===d&&t.clearcoatNormalScale.value.negate()));e.iridescence>0&&(t.iridescence.value=e.iridescence,t.iridescenceIOR.value=e.iridescenceIOR,t.iridescenceThicknessMinimum.value=e.iridescenceThicknessRange[0],t.iridescenceThicknessMaximum.value=e.iridescenceThicknessRange[1],e.iridescenceMap&&(t.iridescenceMap.value=e.iridescenceMap,n(e.iridescenceMap,t.iridescenceMapTransform)),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap,n(e.iridescenceThicknessMap,t.iridescenceThicknessMapTransform)));e.transmission>0&&(t.transmission.value=e.transmission,t.transmissionSamplerMap.value=i.texture,t.transmissionSamplerSize.value.set(i.width,i.height),e.transmissionMap&&(t.transmissionMap.value=e.transmissionMap,n(e.transmissionMap,t.transmissionMapTransform)),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap,n(e.thicknessMap,t.thicknessMapTransform)),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));e.anisotropy>0&&(t.anisotropyVector.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation)),e.anisotropyMap&&(t.anisotropyMap.value=e.anisotropyMap,n(e.anisotropyMap,t.anisotropyMapTransform)));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap,n(e.specularColorMap,t.specularColorMapTransform));e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap,n(e.specularIntensityMap,t.specularIntensityMapTransform))}(t,r,o)):r.isMeshMatcapMaterial?(i(t,r),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,r)):r.isMeshDepthMaterial?i(t,r):r.isMeshDistanceMaterial?(i(t,r),function(t,n){const i=e.get(n).light;t.referencePosition.value.setFromMatrixPosition(i.matrixWorld),t.nearDistance.value=i.shadow.camera.near,t.farDistance.value=i.shadow.camera.far}(t,r)):r.isMeshNormalMaterial?i(t,r):r.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform))}(t,r),r.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,r)):r.isPointsMaterial?function(t,e,i,r){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*r,e.map&&(t.map.value=e.map,n(e.map,t.uvTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r,s,a):r.isSpriteMaterial?function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.rotation.value=e.rotation,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r):r.isShadowMaterial?(t.color.value.copy(r.color),t.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function Rl(t,e,n,i){let r={},s={},a=[];const o=n.isWebGL2?t.getParameter(t.MAX_UNIFORM_BUFFER_BINDINGS):0;function l(t,e,n){const i=t.value;if(void 0===n[e]){if("number"==typeof i)n[e]=i;else{const t=Array.isArray(i)?i:[i],r=[];for(let e=0;e0){r=n%i;0!==r&&i-r-a.boundary<0&&(n+=i-r,s.__offset=n)}n+=a.storage}r=n%i,r>0&&(n+=i-r);t.__size=n,t.__cache={}}(n),d=function(e){const n=function(){for(let t=0;t0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,p=!!n.morphAttributes.color,m=i.toneMapped?S.toneMapping:Y,f=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,g=void 0!==f?f.length:0,v=nt.get(i),_=y.state.lights;if(!0===G&&(!0===W||t!==R)){const e=t===R&&i.id===A;pt.setState(i,t,e)}let x=!1;i.version===v.__version?v.needsLights&&v.lightsStateVersion!==_.state.version||v.outputColorSpace!==o||r.isInstancedMesh&&!1===v.instancing?x=!0:r.isInstancedMesh||!0!==v.instancing?r.isSkinnedMesh&&!1===v.skinning?x=!0:r.isSkinnedMesh||!0!==v.skinning?v.envMap!==l||!0===i.fog&&v.fog!==s?x=!0:void 0===v.numClippingPlanes||v.numClippingPlanes===pt.numPlanes&&v.numIntersection===pt.numIntersection?(v.vertexAlphas!==c||v.vertexTangents!==h||v.morphTargets!==u||v.morphNormals!==d||v.morphColors!==p||v.toneMapping!==m||!0===Q.isWebGL2&&v.morphTargetsCount!==g)&&(x=!0):x=!0:x=!0:x=!0:(x=!0,v.__version=i.version);let M=v.currentProgram;!0===x&&(M=Kt(i,e,r));let b=!1,E=!1,T=!1;const C=M.getUniforms(),P=v.uniforms;tt.useProgram(M.program)&&(b=!0,E=!0,T=!0);i.id!==A&&(A=i.id,E=!0);if(b||R!==t){if(C.setValue(It,"projectionMatrix",t.projectionMatrix),Q.logarithmicDepthBuffer&&C.setValue(It,"logDepthBufFC",2/(Math.log(t.far+1)/Math.LN2)),R!==t&&(R=t,E=!0,T=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshStandardMaterial||i.envMap){const e=C.map.cameraPosition;void 0!==e&&e.setValue(It,Z.setFromMatrixPosition(t.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&C.setValue(It,"isOrthographic",!0===t.isOrthographicCamera),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.isShadowMaterial||r.isSkinnedMesh)&&C.setValue(It,"viewMatrix",t.matrixWorldInverse)}if(r.isSkinnedMesh){C.setOptional(It,r,"bindMatrix"),C.setOptional(It,r,"bindMatrixInverse");const t=r.skeleton;t&&(Q.floatVertexTextures?(null===t.boneTexture&&t.computeBoneTexture(),C.setValue(It,"boneTexture",t.boneTexture,it),C.setValue(It,"boneTextureSize",t.boneTextureSize)):console.warn("THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required."))}const L=n.morphAttributes;(void 0!==L.position||void 0!==L.normal||void 0!==L.color&&!0===Q.isWebGL2)&>.update(r,n,M);(E||v.receiveShadow!==r.receiveShadow)&&(v.receiveShadow=r.receiveShadow,C.setValue(It,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(P.envMap.value=l,P.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);E&&(C.setValue(It,"toneMappingExposure",S.toneMappingExposure),v.needsLights&&(U=T,(I=P).ambientLightColor.needsUpdate=U,I.lightProbe.needsUpdate=U,I.directionalLights.needsUpdate=U,I.directionalLightShadows.needsUpdate=U,I.pointLights.needsUpdate=U,I.pointLightShadows.needsUpdate=U,I.spotLights.needsUpdate=U,I.spotLightShadows.needsUpdate=U,I.rectAreaLights.needsUpdate=U,I.hemisphereLights.needsUpdate=U),s&&!0===i.fog&&ht.refreshFogUniforms(P,s),ht.refreshMaterialUniforms(P,i,O,D,X),Fo.upload(It,v.uniformsList,P,it));var I,U;i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(Fo.upload(It,v.uniformsList,P,it),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&C.setValue(It,"center",r.center);if(C.setValue(It,"modelViewMatrix",r.modelViewMatrix),C.setValue(It,"normalMatrix",r.normalMatrix),C.setValue(It,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const t=i.uniformsGroups;for(let e=0,n=t.length;e0&&function(t,e,n,i){const r=Q.isWebGL2;null===X&&(X=new ci(1,1,{generateMipmaps:!0,type:$.has("EXT_color_buffer_half_float")?wt:yt,minFilter:vt,samples:r&&!0===o?4:0}));S.getDrawingBufferSize(q),r?X.setSize(q.x,q.y):X.setSize(Dn(q.x),Dn(q.y));const s=S.getRenderTarget();S.setRenderTarget(X),S.getClearColor(I),U=S.getClearAlpha(),U<1&&S.setClearColor(16777215,.5);S.clear();const a=S.toneMapping;S.toneMapping=Y,Zt(t,n,i),it.updateMultisampleRenderTarget(X),it.updateRenderTargetMipmap(X);let l=!1;for(let t=0,r=e.length;t0&&Zt(r,e,n),s.length>0&&Zt(s,e,n),a.length>0&&Zt(a,e,n),tt.buffers.depth.setTest(!0),tt.buffers.depth.setMask(!0),tt.buffers.color.setMask(!0),tt.setPolygonOffset(!1)}function Zt(t,e,n){const i=!0===e.isScene?e.overrideMaterial:null;for(let r=0,s=t.length;r0?M[M.length-1]:null,x.pop(),_=x.length>0?x[x.length-1]:null},this.getActiveCubeFace=function(){return E},this.getActiveMipmapLevel=function(){return T},this.getRenderTarget=function(){return w},this.setRenderTargetTextures=function(t,e,n){nt.get(t.texture).__webglTexture=e,nt.get(t.depthTexture).__webglTexture=n;const i=nt.get(t);i.__hasExternalTextures=!0,i.__hasExternalTextures&&(i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===$.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(t,e){const n=nt.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){w=t,E=e,T=n;let i=!0,r=null,s=!1,a=!1;if(t){const n=nt.get(t);void 0!==n.__useDefaultFramebuffer?(tt.bindFramebuffer(It.FRAMEBUFFER,null),i=!1):void 0===n.__webglFramebuffer?it.setupRenderTarget(t):n.__hasExternalTextures&&it.rebindTextures(t,nt.get(t.texture).__webglTexture,nt.get(t.depthTexture).__webglTexture);const o=t.texture;(o.isData3DTexture||o.isDataArrayTexture||o.isCompressedArrayTexture)&&(a=!0);const l=nt.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=l[e],s=!0):r=Q.isWebGL2&&t.samples>0&&!1===it.useMultisampledRTT(t)?nt.get(t).__webglMultisampledFramebuffer:l,C.copy(t.viewport),P.copy(t.scissor),L=t.scissorTest}else C.copy(z).multiplyScalar(O).floor(),P.copy(H).multiplyScalar(O).floor(),L=k;if(tt.bindFramebuffer(It.FRAMEBUFFER,r)&&Q.drawBuffers&&i&&tt.drawBuffers(t,r),tt.viewport(C),tt.scissor(P),tt.setScissorTest(L),s){const i=nt.get(t.texture);It.framebufferTexture2D(It.FRAMEBUFFER,It.COLOR_ATTACHMENT0,It.TEXTURE_CUBE_MAP_POSITIVE_X+e,i.__webglTexture,n)}else if(a){const i=nt.get(t.texture),r=e||0;It.framebufferTextureLayer(It.FRAMEBUFFER,It.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}A=-1},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=nt.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){tt.bindFramebuffer(It.FRAMEBUFFER,o);try{const a=t.texture,o=a.format,l=a.type;if(o!==Lt&&Mt.convert(o)!==It.getParameter(It.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");const c=l===wt&&($.has("EXT_color_buffer_half_float")||Q.isWebGL2&&$.has("EXT_color_buffer_float"));if(!(l===yt||Mt.convert(l)===It.getParameter(It.IMPLEMENTATION_COLOR_READ_TYPE)||l===Tt&&(Q.isWebGL2||$.has("OES_texture_float")||$.has("WEBGL_color_buffer_float"))||c))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&It.readPixels(e,n,i,r,Mt.convert(o),Mt.convert(l),s)}finally{const t=null!==w?nt.get(w).__webglFramebuffer:null;tt.bindFramebuffer(It.FRAMEBUFFER,t)}}},this.copyFramebufferToTexture=function(t,e,n=0){const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),s=Math.floor(e.image.height*i);it.setTexture2D(e,0),It.copyTexSubImage2D(It.TEXTURE_2D,n,0,0,t.x,t.y,r,s),tt.unbindTexture()},this.copyTextureToTexture=function(t,e,n,i=0){const r=e.image.width,s=e.image.height,a=Mt.convert(n.format),o=Mt.convert(n.type);it.setTexture2D(n,0),It.pixelStorei(It.UNPACK_FLIP_Y_WEBGL,n.flipY),It.pixelStorei(It.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),It.pixelStorei(It.UNPACK_ALIGNMENT,n.unpackAlignment),e.isDataTexture?It.texSubImage2D(It.TEXTURE_2D,i,t.x,t.y,r,s,a,o,e.image.data):e.isCompressedTexture?It.compressedTexSubImage2D(It.TEXTURE_2D,i,t.x,t.y,e.mipmaps[0].width,e.mipmaps[0].height,a,e.mipmaps[0].data):It.texSubImage2D(It.TEXTURE_2D,i,t.x,t.y,a,o,e.image),0===i&&n.generateMipmaps&&It.generateMipmap(It.TEXTURE_2D),tt.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n,i,r=0){if(S.isWebGL1Renderer)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");const s=t.max.x-t.min.x+1,a=t.max.y-t.min.y+1,o=t.max.z-t.min.z+1,l=Mt.convert(i.format),c=Mt.convert(i.type);let h;if(i.isData3DTexture)it.setTexture3D(i,0),h=It.TEXTURE_3D;else{if(!i.isDataArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");it.setTexture2DArray(i,0),h=It.TEXTURE_2D_ARRAY}It.pixelStorei(It.UNPACK_FLIP_Y_WEBGL,i.flipY),It.pixelStorei(It.UNPACK_PREMULTIPLY_ALPHA_WEBGL,i.premultiplyAlpha),It.pixelStorei(It.UNPACK_ALIGNMENT,i.unpackAlignment);const u=It.getParameter(It.UNPACK_ROW_LENGTH),d=It.getParameter(It.UNPACK_IMAGE_HEIGHT),p=It.getParameter(It.UNPACK_SKIP_PIXELS),m=It.getParameter(It.UNPACK_SKIP_ROWS),f=It.getParameter(It.UNPACK_SKIP_IMAGES),g=n.isCompressedTexture?n.mipmaps[0]:n.image;It.pixelStorei(It.UNPACK_ROW_LENGTH,g.width),It.pixelStorei(It.UNPACK_IMAGE_HEIGHT,g.height),It.pixelStorei(It.UNPACK_SKIP_PIXELS,t.min.x),It.pixelStorei(It.UNPACK_SKIP_ROWS,t.min.y),It.pixelStorei(It.UNPACK_SKIP_IMAGES,t.min.z),n.isDataTexture||n.isData3DTexture?It.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g.data):n.isCompressedArrayTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),It.compressedTexSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,g.data)):It.texSubImage3D(h,r,e.x,e.y,e.z,s,a,o,l,c,g),It.pixelStorei(It.UNPACK_ROW_LENGTH,u),It.pixelStorei(It.UNPACK_IMAGE_HEIGHT,d),It.pixelStorei(It.UNPACK_SKIP_PIXELS,p),It.pixelStorei(It.UNPACK_SKIP_ROWS,m),It.pixelStorei(It.UNPACK_SKIP_IMAGES,f),0===r&&i.generateMipmaps&&It.generateMipmap(h),tt.unbindTexture()},this.initTexture=function(t){t.isCubeTexture?it.setTextureCube(t,0):t.isData3DTexture?it.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?it.setTexture2DArray(t,0):it.setTexture2D(t,0),tt.unbindTexture()},this.resetState=function(){E=0,T=0,w=null,tt.reset(),bt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get physicallyCorrectLights(){return console.warn("THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),!this.useLegacyLights}set physicallyCorrectLights(t){console.warn("THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),this.useLegacyLights=!t}get outputEncoding(){return console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace===Be?Ie:Le}set outputEncoding(t){console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace=t===Ie?Be:ze}}class Ll extends Pl{}Ll.prototype.isWebGL1Renderer=!0;class Il{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new Or(t),this.density=e}clone(){return new Il(this.color,this.density)}toJSON(){return{type:"FogExp2",color:this.color.getHex(),density:this.density}}}class Ul{constructor(t,e=1,n=1e3){this.isFog=!0,this.name="",this.color=new Or(t),this.near=e,this.far=n}clone(){return new Ul(this.color,this.near,this.far)}toJSON(){return{type:"Fog",color:this.color.getHex(),near:this.near,far:this.far}}}class Nl extends vr{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e}get autoUpdate(){return console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate}set autoUpdate(t){console.warn("THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144."),this.matrixWorldAutoUpdate=t}}class Dl{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=dn,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=Cn()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:Hl.clone(),uv:Cr.getInterpolation(Hl,jl,ql,Yl,Zl,Jl,Kl,new zn),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function Ql(t,e,n,i,r,s){Gl.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(Wl.x=s*Gl.x-r*Gl.y,Wl.y=r*Gl.x+s*Gl.y):Wl.copy(Gl),t.copy(e),t.x+=Wl.x,t.y+=Wl.y,t.applyMatrix4(Xl)}const tc=new gi,ec=new gi;class nc extends vr{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,n=e.length;t0){let n,i;for(n=1,i=e.length;n0){tc.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(tc);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){tc.setFromMatrixPosition(t.matrixWorld),ec.setFromMatrixPosition(this.matrixWorld);const n=tc.distanceTo(ec)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;io)continue;u.applyMatrix4(this.matrixWorld);const s=t.ray.origin.distanceTo(u);st.far||e.push({distance:s,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}else{for(let n=Math.max(0,s.start),i=Math.min(m.count,s.start+s.count)-1;no)continue;u.applyMatrix4(this.matrixWorld);const i=t.ray.origin.distanceTo(u);it.far||e.push({distance:i,point:h.clone().applyMatrix4(this.matrixWorld),index:n,face:null,faceIndex:null,object:this})}}}updateMorphTargets(){const t=this.geometry.morphAttributes,e=Object.keys(t);if(e.length>0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}class Xc extends oi{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isVideoTexture=!0,this.minFilter=void 0!==s?s:mt,this.magFilter=void 0!==r?r:mt,this.generateMipmaps=!1;const c=this;"requestVideoFrameCallback"in t&&t.requestVideoFrameCallback((function e(){c.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1==="requestVideoFrameCallback"in t&&t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class jc extends oi{constructor(t,e){super({width:t,height:e}),this.isFramebufferTexture=!0,this.magFilter=ct,this.minFilter=ct,this.generateMipmaps=!1,this.needsUpdate=!0}}class qc extends oi{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Yc extends qc{constructor(t,e,n,i,r,s){super(t,e,n,r,s),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=ot}}class Zc extends oi{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}}class Jc{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)}getPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPoint(n/t));return e}getSpacedPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPointAt(n/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o<=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a<0)o=i+1;else{if(!(a>0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i<0&&(i=0),r>1&&(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new zn:new gi);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new gi,i=[],r=[],s=[],a=new gi,o=new ji;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new gi)}r[0]=new gi,s[0]=new gi;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c<=l&&(l=c,n.set(1,0,0)),h<=l&&(l=h,n.set(0,1,0)),u<=l&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),s[e]=s[e-1].clone(),a.crossVectors(i[e-1],i[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(Pn(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(Pn(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let n=1;n<=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,normals:r,binormals:s}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.6,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class Kc extends Jc{constructor(t=0,e=0,n=1,i=1,r=0,s=2*Math.PI,a=!1,o=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e){const n=e||new zn,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(l)/r)+1)*r:0===c&&l===r-1&&(l=r-2,c=1),this.closed||l>0?a=i[(l-1)%r]:(th.subVectors(i[0],i[1]).add(i[0]),a=th);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2i.length-2?i.length-1:s+1],h=i[s>i.length-3?i.length-1:s+2];return n.set(sh(a,o.x,l.x,c.x,h.x),sh(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const t=i[r]-n,s=this.curves[r],a=s.getLength(),o=0===a?0:1-t/a;return s.getPointAt(o,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let n=0,i=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=t.curves.length;e0){const t=l.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(l);const c=l.getPoint(1);return this.currentPoint.copy(c),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class _h extends hs{constructor(t=[new zn(0,-.5),new zn(.5,0),new zn(0,.5)],e=12,n=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:n,phiLength:i},e=Math.floor(e),i=Pn(i,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new gi,u=new zn,d=new gi,p=new gi,m=new gi;let f=0,g=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,m.copy(d),d.normalize(),o.push(d.x,d.y,d.z);break;case t.length-1:o.push(m.x,m.y,m.z);break;default:f=t[e+1].x-t[e].x,g=t[e+1].y-t[e].y,d.x=1*g,d.y=-f,d.z=0*g,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),o.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=n+r*c*i,p=Math.sin(d),m=Math.cos(d);for(let n=0;n<=t.length-1;n++){h.x=t[n].x*p,h.y=t[n].y,h.z=t[n].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=n/(t.length-1),a.push(u.x,u.y);const i=o[3*n+0]*p,c=o[3*n+1],d=o[3*n+0]*m;l.push(i,c,d)}}for(let n=0;n0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new es(h,3)),this.setAttribute("normal",new es(u,3)),this.setAttribute("uv",new es(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Mh(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Sh extends Mh{constructor(t=1,e=1,n=32,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new Sh(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class bh extends hs{constructor(t=[],e=[],n=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i<=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t<=l;t++)s[i][t]=0===t&&i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),n<.2&&(s[t+2]+=1),i<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new es(r,3)),this.setAttribute("normal",new es(r.slice(),3)),this.setAttribute("uv",new es(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new bh(t.vertices,t.indices,t.radius,t.details)}}class Eh extends bh{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new Eh(t.radius,t.detail)}}const Th=new gi,wh=new gi,Ah=new gi,Rh=new Cr;class Ch extends hs{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(An*e),s=t.getIndex(),a=t.getAttribute("position"),o=s?s.count:a.count,l=[0,0,0],c=["a","b","c"],h=new Array(3),u={},d=[];for(let t=0;t80*n){o=c=t[0],l=h=t[1];for(let e=n;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return Nh(s,a,n,o,l,p,0),a};function Ih(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s0)for(s=e;s=e;s-=i)a=Qh(s,t[s],t[s+1],a);return a&&qh(a,a.next)&&(tu(a),a=a.next),a}function Uh(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!qh(i,i.next)&&0!==jh(i.prev,i,i.next))i=i.next;else{if(tu(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function Nh(t,e,n,i,r,s,a){if(!t)return;!a&&s&&function(t,e,n,i){let r=t;do{0===r.z&&(r.z=Vh(r.x,r.y,e,n,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e0||l>0&&i;)0!==o&&(0===l||!i||n.z<=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a>1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Oh(t,i,r,s):Dh(t))e.push(o.i/n|0),e.push(t.i/n|0),e.push(l.i/n|0),tu(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Nh(t=Fh(Uh(t),e,n),e,n,i,r,s,2):2===a&&Bh(t,e,n,i,r,s):Nh(Uh(t),e,n,i,r,s,1);break}}function Dh(t){const e=t.prev,n=t,i=t.next;if(jh(e,n,i)>=0)return!1;const r=e.x,s=n.x,a=i.x,o=e.y,l=n.y,c=i.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=i.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&Wh(r,o,s,l,a,c,m.x,m.y)&&jh(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Oh(t,e,n,i){const r=t.prev,s=t,a=t.next;if(jh(r,s,a)>=0)return!1;const o=r.x,l=s.x,c=a.x,h=r.y,u=s.y,d=a.y,p=ol?o>c?o:c:l>c?l:c,g=h>u?h>d?h:d:u>d?u:d,v=Vh(p,m,e,n,i),_=Vh(f,g,e,n,i);let y=t.prevZ,x=t.nextZ;for(;y&&y.z>=v&&x&&x.z<=_;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Wh(o,h,l,u,c,d,y.x,y.y)&&jh(y.prev,y,y.next)>=0)return!1;if(y=y.prevZ,x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Wh(o,h,l,u,c,d,x.x,x.y)&&jh(x.prev,x,x.next)>=0)return!1;x=x.nextZ}for(;y&&y.z>=v;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Wh(o,h,l,u,c,d,y.x,y.y)&&jh(y.prev,y,y.next)>=0)return!1;y=y.prevZ}for(;x&&x.z<=_;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Wh(o,h,l,u,c,d,x.x,x.y)&&jh(x.prev,x,x.next)>=0)return!1;x=x.nextZ}return!0}function Fh(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!qh(r,s)&&Yh(r,i,i.next,s)&&Kh(r,s)&&Kh(s,r)&&(e.push(r.i/n|0),e.push(i.i/n|0),e.push(s.i/n|0),tu(i),tu(i.next),i=t=s),i=i.next}while(i!==t);return Uh(i)}function Bh(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&Xh(a,t)){let o=$h(a,t);return a=Uh(a,a.next),o=Uh(o,o.next),Nh(a,e,n,i,r,s,0),void Nh(o,e,n,i,r,s,0)}t=t.next}a=a.next}while(a!==t)}function zh(t,e){return t.x-e.x}function Hh(t,e){const n=function(t,e){let n,i=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=i.y&&a>=i.next.y&&i.next.y!==i.y){const t=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=s&&t>r&&(r=t,n=i.x=i.x&&i.x>=l&&s!==i.x&&Wh(an.x||i.x===n.x&&kh(n,i)))&&(n=i,u=h)),i=i.next}while(i!==o);return n}(t,e);if(!n)return e;const i=$h(n,t);return Uh(i,i.next),Uh(n,n.next)}function kh(t,e){return jh(t.prev,t,e.prev)<0&&jh(e.next,t,t.next)<0}function Vh(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-n)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function Gh(t){let e=t,n=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(i-o)>=(n-a)*(e-o)&&(n-a)*(s-o)>=(r-a)*(i-o)}function Xh(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&Yh(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(Kh(t,e)&&Kh(e,t)&&function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y>s!=n.next.y>s&&n.next.y!==n.y&&r<(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)&&(jh(t.prev,t,e.prev)||jh(t,e.prev,e))||qh(t,e)&&jh(t.prev,t,t.next)>0&&jh(e.prev,e,e.next)>0)}function jh(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function qh(t,e){return t.x===e.x&&t.y===e.y}function Yh(t,e,n,i){const r=Jh(jh(t,e,n)),s=Jh(jh(t,e,i)),a=Jh(jh(n,i,t)),o=Jh(jh(n,i,e));return r!==s&&a!==o||(!(0!==r||!Zh(t,n,e))||(!(0!==s||!Zh(t,i,e))||(!(0!==a||!Zh(n,t,i))||!(0!==o||!Zh(n,e,i)))))}function Zh(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function Jh(t){return t>0?1:t<0?-1:0}function Kh(t,e){return jh(t.prev,t,t.next)<0?jh(t,e,t.next)>=0&&jh(t,t.prev,e)>=0:jh(t,e,t.prev)<0||jh(t,t.next,e)<0}function $h(t,e){const n=new eu(t.i,t.x,t.y),i=new eu(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function Qh(t,e,n,i){const r=new eu(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function tu(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function eu(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class nu{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function ru(t,e){for(let n=0;nNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g<=2)return new zn(i,r);s=Math.sqrt(g/2)}else{let t=!1;a>Number.EPSILON?l>Number.EPSILON&&(t=!0):a<-Number.EPSILON?l<-Number.EPSILON&&(t=!0):Math.sign(o)===Math.sign(c)&&(t=!0),t?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new zn(i/s,r/s)}const L=[];for(let t=0,e=w.length,n=e-1,i=t+1;t=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=w.length;t=0;){const i=n;let r=n-1;r<0&&(r=t.length-1);for(let t=0,n=o+2*p;t0)&&d.push(e,r,l),(t!==n-1||o0!=t>0&&this.version++,this._anisotropy=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get sheen(){return this._sheen}set sheen(t){this._sheen>0!=t>0&&this.version++,this._sheen=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class bu extends Lr{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Or(16777215),this.specular=new Or(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Or(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=De,this.normalScale=new zn(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=X,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Eu extends Lr{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Or(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Or(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=De,this.normalScale=new zn(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class Tu extends Lr{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=De,this.normalScale=new zn(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class wu extends Lr{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Or(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Or(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=De,this.normalScale=new zn(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.combine=X,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Au extends Lr{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Or(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=De,this.normalScale=new zn(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Ru extends Ac{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function Cu(t,e,n){return Lu(t)?new t.constructor(t.subarray(e,void 0!==n?n:t.length)):t.slice(e,n)}function Pu(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Lu(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Iu(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n}function Uu(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r}function Nu(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&&void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&&(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&&(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&&(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)}const Du={arraySlice:Cu,convertArray:Pu,isTypedArray:Lu,getKeyframeOrder:Iu,sortedArray:Uu,flattenJSON:Nu,subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=i)){l.push(e.times[t]);for(let n=0;ns.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*l+o,e=t+l-o;d=Cu(i.values,t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=Cu(t.resultBuffer,e,n)}if("quaternion"===r){(new fi).fromArray(d).normalize().conjugate().toArray(d)}const p=a.times.length;for(let t=0;t=r)break t;{const a=e[1];t=r)break e}s=n,n=0}}for(;n>>1;te;)--s;if(++s,0!==r||s!==i){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=Cu(n,r,s),this.values=Cu(this.values,r*t,s*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==s&&s>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,s),t=!1;break}s=i}if(void 0!==i&&Lu(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,n),t=!1;break}}return t}optimize(){const t=Cu(this.times),e=Cu(this.values),n=this.getValueSize(),i=this.getInterpolation()===Se,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=Cu(t,0,s),this.values=Cu(e,0,s*n)):(this.times=t,this.values=e),this}clone(){const t=Cu(this.times,0),e=Cu(this.values,0),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}Hu.prototype.TimeBufferType=Float32Array,Hu.prototype.ValueBufferType=Float32Array,Hu.prototype.DefaultInterpolation=Me;class ku extends Hu{}ku.prototype.ValueTypeName="bool",ku.prototype.ValueBufferType=Array,ku.prototype.DefaultInterpolation=xe,ku.prototype.InterpolantFactoryMethodLinear=void 0,ku.prototype.InterpolantFactoryMethodSmooth=void 0;class Vu extends Hu{}Vu.prototype.ValueTypeName="color";class Gu extends Hu{}Gu.prototype.ValueTypeName="number";class Wu extends Ou{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)fi.slerpFlat(r,0,s,l-a,s,l,o);return r}}class Xu extends Hu{InterpolantFactoryMethodLinear(t){return new Wu(this.times,this.values,this.getValueSize(),t)}}Xu.prototype.ValueTypeName="quaternion",Xu.prototype.DefaultInterpolation=Me,Xu.prototype.InterpolantFactoryMethodSmooth=void 0;class ju extends Hu{}ju.prototype.ValueTypeName="string",ju.prototype.ValueBufferType=Array,ju.prototype.DefaultInterpolation=xe,ju.prototype.InterpolantFactoryMethodLinear=void 0,ju.prototype.InterpolantFactoryMethodSmooth=void 0;class qu extends Hu{}qu.prototype.ValueTypeName="vector";class Yu{constructor(t,e=-1,n,i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=Cn(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(Zu(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(Hu.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];Nu(n,s,a,i),0!==s.length&&r.push(new t(e,s,a))}},i=[],r=t.name||"default",s=t.fps||30,a=t.blendMode;let o=t.length||-1;const l=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==td[t])return void td[t].push({onLoad:e,onProgress:n,onError:i});td[t]=[],td[t].push({onLoad:e,onProgress:n,onError:i});const s=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),a=this.mimeType,o=this.responseType;fetch(s).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const n=td[t],i=e.body.getReader(),r=e.headers.get("Content-Length")||e.headers.get("X-File-Size"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t{switch(o){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,a)));case"json":return t.json();default:if(void 0===a)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(a),n=e&&e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(n);return t.arrayBuffer().then((t=>i.decode(t)))}}})).then((e=>{Ju.add(t,e);const n=td[t];delete td[t];for(let t=0,i=n.length;t{const n=td[t];if(void 0===n)throw this.manager.itemError(t),e;delete td[t];for(let t=0,i=n.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class id extends Qu{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new nd(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=[];for(let n=0;n0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=n(r.value);break;case"c":i.uniforms[e].value=(new Or).setHex(r.value);break;case"v2":i.uniforms[e].value=(new zn).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new gi).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new li).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new Hn).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new ji).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&&(i.lights=t.lights),void 0!==t.clipping&&(i.clipping=t.clipping),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=n(t.map)),void 0!==t.matcap&&(i.matcap=n(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new zn).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=n(t.envMap)),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new zn).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(i.iridescenceMap=n(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(i.iridescenceThicknessMap=n(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=n(t.thicknessMap)),void 0!==t.anisotropyMap&&(i.anisotropyMap=n(t.anisotropyMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:yu,SpriteMaterial:Bl,RawShaderMaterial:xu,ShaderMaterial:Ds,PointsMaterial:Bc,MeshPhysicalMaterial:Su,MeshStandardMaterial:Mu,MeshPhongMaterial:bu,MeshToonMaterial:Eu,MeshNormalMaterial:Tu,MeshLambertMaterial:wu,MeshDepthMaterial:fl,MeshDistanceMaterial:gl,MeshBasicMaterial:Br,MeshMatcapMaterial:Au,LineDashedMaterial:Ru,LineBasicMaterial:Ac,Material:Lr}[t]}}class Cd{static decodeText(t){if("undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;n0){const n=new Ku(e);r=new sd(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e0){i=new sd(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let n=t;n=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){fi.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;fi.multiplyQuaternionsFlat(t,s,t,e,t,n),fi.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const op="\\[\\]\\.:\\/",lp=new RegExp("["+op+"]","g"),cp="[^"+op+"]",hp="[^"+op.replace("\\.","")+"]",up=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",cp)+/(WCOD+)?/.source.replace("WCOD",hp)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",cp)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",cp)+"$"),dp=["material","materials","bones","map"];class pp{constructor(t,e,n){this.path=e,this.parsedPath=n||pp.parseTrackName(e),this.node=pp.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&&t.isAnimationObjectGroup?new pp.Composite(t,e,n):new pp(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(lp,"")}static parseTrackName(t){const e=up.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=n.nodeName.substring(i+1);-1!==dp.indexOf(t)&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return n}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i=r){const s=r++,c=t[s];e[c.uuid]=l,t[l]=c,e[o]=s,t[s]=a;for(let t=0,e=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.length;let r=this.nCachedObjects_,s=t.length;for(let a=0,o=arguments.length;a!==o;++a){const o=arguments[a].uuid,l=e[o];if(void 0!==l)if(delete e[o],l0&&(e[a.uuid]=l),t[l]=a,t.pop();for(let t=0,e=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new pp(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}}class fp{constructor(t,e,n=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=n,this.blendMode=i;const r=e.tracks,s=r.length,a=new Array(s),o={endingStart:be,endingEnd:be};for(let t=0;t!==s;++t){const e=r[t].createInterpolant(null);a[t]=e,e.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(s),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,n){if(t.fadeOut(e),this.fadeIn(e),n){const n=this._clip.duration,i=t._clip.duration,r=i/n,s=n/i;t.warp(1,r,e),this.warp(s,1,e)}return this}crossFadeTo(t,e,n){return t.crossFadeFrom(this,e,n)}stopFading(){const t=this._weightInterpolant;return null!==t&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,n){const i=this._mixer,r=i.time,s=this.timeScale;let a=this._timeScaleInterpolant;null===a&&(a=i._lendControlInterpolant(),this._timeScaleInterpolant=a);const o=a.parameterPositions,l=a.sampleValues;return o[0]=r,o[1]=r+n,l[0]=t/s,l[1]=e/s,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,n,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*n;i<0||0===n?e=0:(this._startTime=null,e=n*i)}e*=this._updateTimeScale(t);const s=this._updateTime(e),a=this._updateWeight(t);if(a>0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===Ae)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&&1==(1&r)?e-i:i;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,s)):this._setEndings(0===this.repetitions,!0,s)),i>=e||i<0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===a){const e=t<0;this._setEndings(e,!e,s)}else this._setEndings(!1,!1,s);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:n})}}else this.time=i;if(s&&1==(1&r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=Ee,i.endingEnd=Ee):(i.endingStart=t?this.zeroSlopeAtStart?Ee:be:Te,i.endingEnd=e?this.zeroSlopeAtEnd?Ee:be:Te)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&&(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}const gp=new Float32Array(1);class vp extends En{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,s=t._propertyBindings,a=t._interpolants,o=n.uuid,l=this._bindingsByRootAndName;let c=l[o];void 0===c&&(c={},l[o]=c);for(let t=0;t!==r;++t){const r=i[t],l=r.name;let h=c[l];if(void 0!==h)++h.referenceCount,s[t]=h;else{if(h=s[t],void 0!==h){null===h._cacheIndex&&(++h.referenceCount,this._addInactiveBinding(h,o,l));continue}const i=e&&e._propertyBindings[t].binding.parsedPath;h=new ap(pp.create(n,l,i),r.ValueTypeName,r.getValueSize()),++h.referenceCount,this._addInactiveBinding(h,o,l),s[t]=h}a[t].resultBuffer=h.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,n,e)}const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==n.useCount++&&(this._lendBinding(n),n.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&&e=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,t,r,s)}const a=this._bindings,o=this._nActiveBindings;for(let t=0;t!==o;++t)a[t].apply(s);return this}setTime(t){this.time=0;for(let t=0;tthis.max.x||t.ythis.max.y)}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return!(t.max.xthis.max.x||t.max.ythis.max.y)}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Rp).distanceTo(t)}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const Pp=new gi,Lp=new gi;class Ip{constructor(t=new gi,e=new gi){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Pp.subVectors(t,this.start),Lp.subVectors(this.end,this.start);const n=Lp.dot(Lp);let i=Lp.dot(Pp)/n;return e&&(i=Pn(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return this.delta(n).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&&t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const Up=new gi;class Np extends vr{constructor(t,e){super(),this.light=t,this.matrix=t.matrixWorld,this.matrixAutoUpdate=!1,this.color=e,this.type="SpotLightHelper";const n=new hs,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let t=0,e=1,n=32;t1)for(let n=0;n.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{sm.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(sm,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}class cm extends Oc{constructor(t=1){const e=[0,0,0,t,0,0,0,0,0,0,t,0,0,0,0,0,0,t],n=new hs;n.setAttribute("position",new es(e,3)),n.setAttribute("color",new es([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(n,new Ac({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(t,e,n){const i=new Or,r=this.geometry.attributes.color.array;return i.set(t),i.toArray(r,0),i.toArray(r,3),i.set(e),i.toArray(r,6),i.toArray(r,9),i.set(n),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class hm{constructor(){this.type="ShapePath",this.color=new Or,this.subPaths=[],this.currentPath=null}moveTo(t,e){return this.currentPath=new vh,this.subPaths.push(this.currentPath),this.currentPath.moveTo(t,e),this}lineTo(t,e){return this.currentPath.lineTo(t,e),this}quadraticCurveTo(t,e,n,i){return this.currentPath.quadraticCurveTo(t,e,n,i),this}bezierCurveTo(t,e,n,i,r,s){return this.currentPath.bezierCurveTo(t,e,n,i,r,s),this}splineThru(t){return this.currentPath.splineThru(t),this}toShapes(t){function e(t,e){const n=e.length;let i=!1;for(let r=n-1,s=0;sNumber.EPSILON){if(l<0&&(n=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x<=t.x&&t.x<=n.x||n.x<=t.x&&t.x<=a.x)return!0}}return i}const n=nu.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,s,a;const o=[];if(1===i.length)return s=i[0],a=new Ph,a.curves=s.curves,o.push(a),o;let l=!n(i[0].getPoints());l=t?!l:l;const c=[],h=[];let u,d,p=[],m=0;h[m]=void 0,p[m]=[];for(let e=0,a=i.length;e1){let t=!1,n=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t[property:Boolean enabled]

يؤدي تعيين *enabled* إلى *false* إلى تعطيل هذا الإجراء ، بحيث لا يكون له أي تأثير. الافتراضي هو *true*.

- عند إعادة تمكين الإجراء ، يستمر الرسم المتحرك من وقته الحالي [page:.time time] (الإعداد *enabled* إلى *false* لا يعيد تعيين الإجراء).

+ عند إعادة تمكين الإجراء ، يستمر الرسم المتحرك من وقته الحالي [page:.time time] (العدد *enabled* إلى *false* لا يعيد تعيين الإجراء).

ملاحظة: لا يؤدي إعداد *enabled* إلى *true* إلى إعادة تشغيل الرسوم المتحركة تلقائيًا. سيؤدي ضبط *enabled* إلى *true* إلى إعادة تشغيل الرسوم المتحركة فورًا فقط إذا تم استيفاء الشرط التالي: [page:.paused paused] تحتوي قيمة *false* ، لم يتم إلغاء تنشيط هذا الإجراء في هذه الأثناء (بتنفيذ أمر [page:.stop stop] أو [page:.reset reset]) ، وليس [page:.weight weight] أو [page:.timeScale timeScale] يساوي 0. diff --git a/docs/api/ar/cameras/OrthographicCamera.html b/docs/api/ar/cameras/OrthographicCamera.html new file mode 100644 index 00000000000000..790ec7818ba2b7 --- /dev/null +++ b/docs/api/ar/cameras/OrthographicCamera.html @@ -0,0 +1,141 @@ + + + + + + + + + + [page:Object3D] → [page:Camera] → + +

[name]

+

+ كاميرا تستخدم + [link:https://en.wikipedia.org/wiki/Orthographic_projection الإسقاط المجسمي].

+ + في هذا النمط من الإسقاط، يبقى حجم الجسم + ثابتاً في الصورة المُرسَمَة بغض النظر عن مسافته من الكاميرا.

+ + يمكن أن يكون هذا مفيداً لتصوير المشاهد ثنائية الأبعاد وعناصر واجهة المستخدم، وغيرها من + الأشياء. +

+ +

مثال للكود

+ + const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 ); + scene.add( camera ); + + +

أمثلة (Examples)

+

+ [example:webgl_camera camera ]
+ [example:webgl_interactive_cubes_ortho interactive / cubes / ortho ]
+ [example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic]
+ [example:webgl_postprocessing_advanced postprocessing / advanced ]
+ [example:webgl_postprocessing_dof2 postprocessing / dof2 ]
+ [example:webgl_postprocessing_godrays postprocessing / godrays ]
+ [example:webgl_rtt rtt ]
+ [example:webgl_shadowmap shadowmap ] +

+ +

المنشئ (Constructor)

+

[name]( [param:Number left], [param:Number right], [param:Number top], [param:Number bottom], [param:Number near], [param:Number far] )

+

+ left — سطح الهرم الأيسر.
+ right — سطح الهرم الأيمن.
+ top — سطح الهرم العلوي.
+ bottom — سطح الهرم السفلي.
+ near — سطح الهرم الأمامي.
+ far — سطح الهرم الخلفي.

+ + معًا، تحدد هذه العناصر هرم العرض للكاميرا. + [link:https://en.wikipedia.org/wiki/Viewing_frustum هرم الرؤية]. +

+ +

الخصائص (Properties)

+

+ انظر إلى صفحة [page:Camera] الأساسية للحصول على الخصائص الشائعة.
+ يرجى ملاحظة أنه بعد إجراء تغييرات على معظم هذه الخصائص، يجب عليك استدعاء + [page:OrthographicCamera.updateProjectionMatrix .updateProjectionMatrix] + لجعل التغييرات سارية المفعول. +

+ +

[property:Float bottom]

+

سطح الهرم السفلي للكاميرا.

+ +

[property:Float far]

+

+ سطح الهرم الخلفي للكاميرا. العدد الافتراضي هو `2000`.

+يجب أن يكون أكبر من القيمة الحالية لسطح الهرم الأمامي [page:.near near]. +

+ +

[property:Boolean isOrthographicCamera]

+

علامة للقراءة فقط للتحقق مما إذا كان الكائن المعطى من النوع [name].

+ +

[property:Float left]

+

سطح الهرم الأيسر للكاميرا.

+ +

[property:Float near]

+

+ سطح الهرم الأمامي للكاميرا. العدد الافتراضي هو `0.1`.

+ النطاق الصحيح هو بين `0` وقيمة الهرم الخلفي [page:.far far]. يرجى ملاحظة أنه، على عكس الـ [page:PerspectiveCamera]، + يمثل الصفر قيمة صالحة لسطح الهرم الأمامي في OrthographicCamera. +

+ +

[property:Float right]

+

سطح الهرم الأيمن للكاميرا.

+ +

[property:Float top]

+

سطح الهرم العلوي للكاميرا.

+ +

[property:Object view]

+

+ `يتم تعيينها بواسطة [page:OrthographicCamera.setViewOffset setViewOffset]. العدد الافتراضي هو + `null`. +

+ +

[property:number zoom]

+

تُستخدم للحصول على قيمة عامل التكبير أو تعيينها للكاميرا. العدد الافتراضي هو `1`

+ +

الوظائف (Methods)

+

راجع صفحة [page:Camera] الأساسية للحصول على الأساليب الشائعة.

+ +

[method:undefined setViewOffset]( [param:Float fullWidth], [param:Float fullHeight], [param:Float x], [param:Float y], [param:Float width], [param:Float height] )

+

+ fullWidth — العرض الكامل لإعداد العرض المتعدد.
+ fullHeight — الارتفاع الكامل لإعداد العرض المتعدد.
+ x — الإزاحة الأفقية للكاميرا الفرعية.
+ y — الإزاحة العمودية للكاميرا الفرعية.
+ width — عرض الكاميرا الفرعية.
+ height — ارتفاع الكاميرا الفرعية.

+ + يُعيّن إزاحة في + [link:https://en.wikipedia.org/wiki/Viewing_frustum هرم الرؤية] + أكبر. هذا مفيد لإعدادات النوافذ المتعددة أو إعدادات الشاشات / الأجهزة المتعددة. + لمثال حول كيفية استخدامها، انظر [page:PerspectiveCamera.setViewOffset PerspectiveCamera]. +

+ +

[method:undefined clearViewOffset]()

+

تزيل أي إزاحة تم تعيينها بواسطة طريقة .setViewOffset.

+ +

[method:undefined updateProjectionMatrix]()

+

+ تحديث مصفوفة إسقاط الكاميرا. يجب استدعاؤها بعد أي تغيير في + المعلمات. +

+ +

[method:Object toJSON]([param:Object meta])

+

+ meta -- كائن يحتوي على بيانات وصفية مثل الخامات أو الصور في الأجزاء + الفرعية للكائنات.
+ تحويل الكاميرا إلى تنسيق three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene] +

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/cameras/PerspectiveCamera.html b/docs/api/ar/cameras/PerspectiveCamera.html new file mode 100644 index 00000000000000..a200a311f7a17f --- /dev/null +++ b/docs/api/ar/cameras/PerspectiveCamera.html @@ -0,0 +1,219 @@ +!DOCTYPE html> + + + + + + + + + [page:Object3D] → [page:Camera] → + +

[name]

+

+ كاميرا تستخدم تصوير منظوري + [link:https://en.wikipedia.org/wiki/Perspective_(graphical) Perspective Projection]. + تم تصميم هذا الوضع لمحاكاة الطريقة التي يرى بها العين البشرية. + وهو أكثر أنماط التصوير استخدامًا لإظهار مشهد ثلاثي الأبعاد. +

+ +

مثال للكود

+ + + const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 ); + scene.add( camera ); + + +

أمثلة (Examples)

+

+ [example:webgl_animation_skinning_blending animation / skinning / blending]
+ [example:webgl_animation_skinning_morph animation / skinning / morph ]
+ [example:webgl_effects_stereo effects / stereo ]
+ [example:webgl_interactive_cubes interactive / cubes ]
+ [example:webgl_loader_collada_skinning loader / collada / skinning ] +

+ +

المنشئ (Constructor)

+ +

[name]( [param:Number fov], [param:Number aspect], [param:Number near], [param:Number far] )

+

+ fov — زاوية مجال الرؤية الرأسية للكاميرا.
+ aspect — نسبة العرض إلى الارتفاع للكاميرا.
+ near — سطح الهرم الأمامي للكاميرا.
+ far — سطح الهرم الخلفي للكاميرا.

+ معًا، يحدد هذه العناصر هرم الرؤية للكاميرا. + [link:https://en.wikipedia.org/wiki/Viewing_frustum هرم الرؤية] +

+ +

الخصائص (Properties)

+

+ يرجى الرجوع إلى صفحة [page:Camera] الأساسية للحصول على الخصائص الشائعة.
+ يرجى ملاحظة أنه بعد إجراء تغييرات على معظم هذه الخصائص، ستحتاج + إلى استدعاء [page:PerspectiveCamera.updateProjectionMatrix .updateProjectionMatrix] لجعل التغييرات سارية المفعول. +

+ +

[property:Float aspect]

+

+ نسبة العرض إلى الارتفاع لسطح الهرم الرؤية (frustum) للكاميرا، وعادةً ما يكون العرض الخاص باللوحة السينمائية / الشاشة مقسومًا على ارتفاعها. + العدد الافتراضي هو `1` (لوحة سينمائية مربعة). +

+ +

[property:Float far]

+

+ سطح الهرم الخلفي لسطح الرؤية (frustum) للكاميرا. العدد الافتراضي هو `2000`.

+ يجب أن يكون أكبر من القيمة الحالية لسطح الهرم الأمامي [page:.near near]. +

+ +

[property:Float filmGauge]

+

+ حجم الفيلم المستخدم للمحور الأكبر. العدد الافتراضي هو 35 (ملم). + لا يؤثر هذا المعلم على مصفوفة الإسقاط إلا إذا تم تعيين + .filmOffset إلى قيمة غير صفر. +

+ +

[property:Float filmOffset]

+

+ الإزاحة الأفقية غير المركزة في نفس وحدة `.filmGauge`. العدد الافتراضي هو + `0`. +

+ +

[property:Float focus]

+

+ مسافة الكائن المستخدمة لتحقيق تأثيرات الإسقاط المتزامن والعمق الحقيقي. + هذا المعلم لا يؤثر على مصفوفة الإسقاط إلا إذا تم استخدام [page:StereoCamera]. + العدد الافتراضي هو `10`. +

+ +

[property:Float fov]

+

+ زاوية مجال الرؤية الرأسية لسطح الهرم الرؤية (frustum) للكاميرا، من أسفل الرؤية إلى أعلى الرؤية، بالدرجات. + العدد الافتراضي هو `50`. +

+ +

[property:Boolean isPerspectiveCamera]

+

علامة تحقق للتحقق مما إذا كان الكائن المعطى من نوع [name]. هذه العلامة لا يمكن تعديلها.

+ +

[property:Float near]

+

+ سطح الهرم الأمامي لسطح الرؤية (frustum) للكاميرا. + العدد الافتراضي هو `0.1`.

+ النطاق الصحيح هو أكبر من `0` وأقل من القيمة الحالية لسطح الهرم الخلفي [page:.far far]. + يرجى ملاحظة أنه، على عكس الكاميرا المسطحة + [page:OrthographicCamera]، القيمة `0` ليست قيمة صالحة لسطح الهرم الأمامي لكاميرا من نوع PerspectiveCamera. +

+ +

[property:Object view]

+

+ مواصفات نافذة هرم الرؤية (frustum) أو `null`. + يتم تعيين هذا باستخدام طريقة [page:PerspectiveCamera.setViewOffset .setViewOffset] + ويتم مسحها باستخدام [page:PerspectiveCamera.clearViewOffset .clearViewOffset]. +

+ +

[property:number zoom]

+

يتم الحصول على قيمة عامل التكبير أو تعيينها للكاميرا. العدد الافتراضي هو `1`.

+ +

الوظائف (Methods)

+

يرجى الرجوع إلى صفحة [page:Camera] الأساسية للحصول على الأساليب الشائعة.

+ +

[method:undefined clearViewOffset]()

+

تزيل أي إزاحة تم تعيينها باستخدام طريقة [page:PerspectiveCamera.setViewOffset .setViewOffset].

+ +

[method:Float getEffectiveFOV]()

+

تُرجع زاوية مجال الرؤية الرأسية الحالية بالدرجات باعتبار .zoom.

+ +

[method:Float getFilmHeight]()

+

+ تُرجع ارتفاع الصورة على الفيلم. إذا كان + .aspect أقل من الواحد (تنسيق صورة عمودي)، فإن النتيجة تساوي .filmGauge. +

+ +

[method:Float getFilmWidth]()

+

+ تُرجع عرض الصورة على الفيلم. إذا كان + .aspect أكبر من أو يساوي الواحد (تنسيق صورة أفقي)، فإن النتيجة تساوي .filmGauge. +

+ +

[method:Float getFocalLength]()

+

+ تُرجع البعد البؤري للـ .fov الحالي بالنسبة لـ .filmGauge. +

+ +

[method:undefined setFocalLength]( [param:Float focalLength] )

+

+ يتم تعيين الـ FOV بواسطة البعد البؤري بالنسبة لـ + .filmGauge الحالي لـ[page:PerspectiveCamera].

+ بشكل افتراضي، يتم تحديد البعد البؤري للكاميرا بحجم 35 مم (إطار كامل). +

+ +

[method:undefined setViewOffset]( [param:Float fullWidth], [param:Float fullHeight], [param:Float x], [param:Float y], [param:Float width], [param:Float height] )

+

+ fullWidth — العرض الكامل لإعداد العرض المتعدد
+ fullHeight — الارتفاع الكامل لإعداد العرض المتعدد
+ x — الإزاحة الأفقية للكاميرا الفرعية
+ y — الإزاحة الرأسية للكاميرا الفرعية
+ width — عرض الكاميرا الفرعية
+ height — ارتفاع الكاميرا الفرعية +

+ +

+ يضبط الإزاحة في هرم الرؤية الأكبر. + هذا مفيد لإعدادات النوافذ المتعددة أو إعدادات متعددة الشاشات/الأجهزة. +

+ +

+ على سبيل المثال، إذا كان لديك 3x2 شاشة + وكانت كل شاشة 1920x1080 وكانت الشاشات في شبكة مثل هذه:
+

+ +
++---+---+---+
+| A | B | C |
++---+---+---+
+| D | E | F |
++---+---+---+
+		
+ + فمن أجل كل شاشة، ستقوم بالاستدعاء بهذا الشكل:
+ + const w = 1920; +const h = 1080; +const fullWidth = w * 3; +const fullHeight = h * 2; + +// A +camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); +// B +camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); +// C +camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); +// D +camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); +// E +camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); +// F +camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); + + +

يرجى ملاحظة أنه لا يوجد سبب لأن تكون الشاشات بحجم متساوٍ أو متوضعة على شكل شبكة. يمكن توزيعها بأي شكل يناسب الاحتياجات المحددة.

+ +

[method:undefined updateProjectionMatrix]()

+

+ يقوم بتحديث مصفوفة الإسقاط الخاصة بالكاميرا، ويجب استدعاءها بعد أي تغيير في + المعاملات. +

+ +

[method:Object toJSON]([param:Object meta])

+

+ meta -- كائن يحتوي على بيانات وصفية مثل القوام أو الصور في الكائنات + الفرعية.
+ يمكن تحويل الكاميرا إلى تنسيق three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. +

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + + diff --git a/docs/api/ar/cameras/StereoCamera.html b/docs/api/ar/cameras/StereoCamera.html new file mode 100644 index 00000000000000..a735dc28778ffa --- /dev/null +++ b/docs/api/ar/cameras/StereoCamera.html @@ -0,0 +1,59 @@ + + + + + + + + + +

[name]

+ +

+ كاميرات بتأثير مزدوج [page:PerspectiveCamera] تستخدم لتحقيق تأثيرات مثل + [link:https://en.wikipedia.org/wiki/Anaglyph_3D 3D Anaglyph] أو + [link:https://en.wikipedia.org/wiki/parallax_barrier Parallax Barrier]. +

+ +

أمثلة (Examples)

+

+ [example:webgl_effects_anaglyph effects / anaglyph ]
+ [example:webgl_effects_parallaxbarrier effects / parallaxbarrier ]
+ [example:webgl_effects_stereo effects / stereo ] +

+ +

المنشئ (Constructor)

+

[name]( )

+ +

الخصائص (Properties)

+ +

[property:Float aspect]

+

العدد الافتراضي هو `1`.

+ +

[property:Float eyeSep]

+

العدد الافتراضي هو `0.064`.

+ +

[property:PerspectiveCamera cameraL]

+

+ الكاميرا اليسرى. يتم إضافتها إلى [page:Layers layer 1] - يجب أن يتم إضافة الكائنات التي يتم عرضها + بالكاميرا اليسرى إلى هذه الطبقة أيضًا. +

+ +

[property:PerspectiveCamera cameraR]

+

+ الكاميرا اليمنى. يتم إضافتها إلى [page:Layers layer 2] - يجب أن يتم إضافة الكائنات التي يتم عرضها + بالكاميرا اليمنى إلى هذه الطبقة أيضًا. +

+ +

الوظائف (Methods)

+ +

[method:undefined update]( [param:PerspectiveCamera camera] )

+

يقوم بتحديث الكاميرات الاستريو بناءً على الكاميرا الممررة كمعامل.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/constants/Animation.html b/docs/api/ar/constants/Animation.html new file mode 100644 index 00000000000000..565bedb6848b64 --- /dev/null +++ b/docs/api/ar/constants/Animation.html @@ -0,0 +1,46 @@ + + + + + + + + + +

Animation Constants

+ +

وضعيات التكرار (Loop Modes)

+ + +THREE.LoopOnce +THREE.LoopRepeat +THREE.LoopPingPong + + +

وضعيات التداخل (Interpolation Modes)

+ +THREE.InterpolateDiscrete +THREE.InterpolateLinear +THREE.InterpolateSmooth + + +

وضعيات النهاية (Ending Modes)

+ +THREE.ZeroCurvatureEnding +THREE.ZeroSlopeEnding +THREE.WrapAroundEnding + + +

وضعيات الدمج للرسوم المتحركة (Animation Blend Modes)

+ +THREE.NormalAnimationBlendMode +THREE.AdditiveAnimationBlendMode + + +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + diff --git a/docs/api/ar/constants/BufferAttributeUsage.html b/docs/api/ar/constants/BufferAttributeUsage.html new file mode 100644 index 00000000000000..e3579832efb0e5 --- /dev/null +++ b/docs/api/ar/constants/BufferAttributeUsage.html @@ -0,0 +1,52 @@ + + + + + + + + + +

ثوابت استخدام بيانات الذاكرة المؤقتة (Buffer Attribute Usage Constants)

+ +

+ يمكن استخدام الثوابت التي تحدد طريقة استخدام بيانات الذاكرة المؤقتة للهيكل الهندسي لتعطي تلميحاً لواجهة برمجة التطبيقات API بشأن كيفية استخدام بيانات الذاكرة المؤقتة لتحسين الأداء. +

+ +

مثال للكود

+ + + const geometry = new THREE.BufferGeometry(); + const positionAttribute = new THREE.BufferAttribute( array, 3 , false ); + positionAttribute.setUsage( THREE.DynamicDrawUsage ); + geometry.setAttribute( 'position', positionAttribute ); + + +

أمثلة (Examples)

+

[example:webgl_buffergeometry_drawrange materials / buffergeometry / drawrange ]

+ +

استخدام الهيكل الهندسي

+ + THREE.StaticDrawUsage + THREE.DynamicDrawUsage + THREE.StreamDrawUsage + + THREE.StaticReadUsage + THREE.DynamicReadUsage + THREE.StreamReadUsage + + THREE.StaticCopyUsage + THREE.DynamicCopyUsage + THREE.StreamCopyUsage + + + للحصول على معلومات أكثر تفصيلاً حول كل هذه الثوابت، يرجى الرجوع إلى + [link:https://www.khronos.org/opengl/wiki/Buffer_Object#Buffer_Object_Usage هذا الدليل الخاص بـ OpenGL]. + +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + diff --git a/docs/api/ar/constants/Core.html b/docs/api/ar/constants/Core.html new file mode 100644 index 00000000000000..c9c16ad69ba2ac --- /dev/null +++ b/docs/api/ar/constants/Core.html @@ -0,0 +1,65 @@ + + + + + + + + + +

الثوابت الأساسية (Core Constants)

+ +

رقم النسخة (Revision Number)

+ + +THREE.REVISION + + +
+ رقم النسخة الحالي لـ three.js هو [link:https://github.com/mrdoob/three.js/releases رقم الإصدار]. +
+ +

مساحات الألوان (Color Spaces)

+ +THREE.NoColorSpace = "" +THREE.SRGBColorSpace = "srgb" +THREE.LinearSRGBColorSpace = "srgb-linear" + +

+ [page:NoColorSpace]ﻻ يحدد مساحة الألوان بشكل عام. ويستخدم عادة للقواميس الخاصة بالألوان المتوسطة، مثل الخرائط العادية، وخرائط التصلب، وخرائط اللمعان، وخرائط الظل، والبيانات غير اللونية الأخرى. +

+

+ [page:SRGBColorSpace] ("srgb") يشير إلى مساحة الألوان التي تم تعريفها بواسطة المعايير الرئيسية Rec. 709، ونقطة الأبيض D65، والوظائف اللاخطية لنقل sRGB. وهو المساحة الافتراضية للألوان في CSS، ويتم العثور عليها في العديد من الباليتات اللونية وأدوات اختيار الألوان. وعادةً ما تكون الألوان المعبر عنها بالتعبير الست عشري أو CSS في مساحة الألوان sRGB. +

+ +

+ [page:LinearSRGBColorSpace] ("srgb-linear") يشير إلى مساحة الألوان sRGB (أعلاه) مع وظائف نقل النقل الخطي. وهي المساحة الافتراضية للألوان في three.js، وتستخدم طوال معظم عملية العرض. وتكون مكونات RGB التي توجد في مواد three.js والشواهد (shaders) في مساحة الألوان Linear-sRGB. + +

للمزيد من المعلومات حول الخلفية والاستخدام، يرجى الرجوع إلى "إدارة الألوان".

+ +

أزرار الماوس (Mouse Buttons)

+ +THREE.MOUSE.LEFT +THREE.MOUSE.MIDDLE +THREE.MOUSE.RIGHT +THREE.MOUSE.ROTATE +THREE.MOUSE.DOLLY +THREE.MOUSE.PAN + +

+ تحمل الثوابت LEFT و ROTATE نفس القيمة الأساسية. كذلك الثوابت MIDDLE و DOLLY تحملان نفس القيمة الأساسية. وتحمل الثوابت RIGHT و PAN نفس القيمة الأساسية. +

+ +

إجراءات اللمس (Touch Actions)

+ +THREE.TOUCH.ROTATE THREE.TOUCH.PAN THREE.TOUCH.DOLLY_PAN +THREE.TOUCH.DOLLY_ROTATE + + +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + diff --git a/docs/api/ar/constants/CustomBlendingEquations.html b/docs/api/ar/constants/CustomBlendingEquations.html new file mode 100644 index 00000000000000..8b1ee8591cb63c --- /dev/null +++ b/docs/api/ar/constants/CustomBlendingEquations.html @@ -0,0 +1,68 @@ + + + + + + + + + +

ثوابت معادلات الدمج المخصصة (Custom Blending Equation Constants)

+ +

+ تعمل هذه الثوابت مع جميع أنواع المواد. يتم تعيين وضع الدمج للمادة أولاً إلى THREE.CustomBlending، ثم تعيين معادلة الدمج المطلوبة وعامل المصدر وعامل الوجهة. +

+ +

مثال للكود

+ + + const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); + material.blending = THREE.CustomBlending; + material.blendEquation = THREE.AddEquation; //default + material.blendSrc = THREE.SrcAlphaFactor; //default + material.blendDst = THREE.OneMinusSrcAlphaFactor; //default + + +

أمثلة (Examples)

+

+ [example:webgl_materials_blending_custom materials / blending / custom ] + +

+ +

معادلات الدمج (Blending Equations)

+ + THREE.AddEquation + THREE.SubtractEquation + THREE.ReverseSubtractEquation + THREE.MinEquation + THREE.MaxEquation + + +

عوامل المصدر (Source Factors)

+ + THREE.ZeroFactor + THREE.OneFactor + THREE.SrcColorFactor + THREE.OneMinusSrcColorFactor + THREE.SrcAlphaFactor + THREE.OneMinusSrcAlphaFactor + THREE.DstAlphaFactor + THREE.OneMinusDstAlphaFactor + THREE.DstColorFactor + THREE.OneMinusDstColorFactor + THREE.SrcAlphaSaturateFactor + + +

عوامل الوجهة (Destination Factors)

+

+ جميع عوامل المصدر صالحة كعوامل وجهة، باستثناء + THREE.SrcAlphaSaturateFactor +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + diff --git a/docs/api/ar/constants/Materials.html b/docs/api/ar/constants/Materials.html new file mode 100644 index 00000000000000..c030eb0c4c9982 --- /dev/null +++ b/docs/api/ar/constants/Materials.html @@ -0,0 +1,153 @@ + + + + + + + + + +

ثوابت المواد الخام (Material Constants)

+ +

+ تحدد هذه الثوابت الخصائص المشتركة بين جميع أنواع المواد الخام، باستثناء عمليات تجميع القوام الخاصة التي تنطبق فقط على + [page:MeshBasicMaterial.combine MeshBasicMaterial]، + [page:MeshLambertMaterial.combine MeshLambertMaterial] و + [page:MeshPhongMaterial.combine MeshPhongMaterial].
+

+ +

الجانب (Side)

+ + THREE.FrontSide + THREE.BackSide + THREE.DoubleSide + + +

+ تحدد الجانب الذي سيتم عرضه للوجوه، سواءً الوجه الأمامي، الوجه الخلفي، أو كلاهما. الإعداد الافتراضي هو الوجه الأمامي. +

+ +

وضعية الدمج (Blending Mode)

+ + THREE.NoBlending + THREE.NormalBlending + THREE.AdditiveBlending + THREE.SubtractiveBlending + THREE.MultiplyBlending + THREE.CustomBlending + + +

+ تحكم هذه الثوابت في معادلات الدمج بين المصدر والوجهة للألوان والألفا التي يتم إرسالها من المواد إلى WebGLRenderer للاستخدام بواسطة WebGL. + [page:Constant NormalBlending] هي الإعداد الافتراضي. ويجب تعيين [page:Constant CustomBlending] لاستخدام [page:CustomBlendingEquation Custom Blending Equations]. + راجع مثال [example:webgl_materials_blending materials / blending]. +

+ +

وضعية العمق (Depth Mode)

+ + THREE.NeverDepth + THREE.AlwaysDepth + THREE.EqualDepth + THREE.LessDepth + THREE.LessEqualDepth + THREE.GreaterEqualDepth + THREE.GreaterDepth + THREE.NotEqualDepth + +

+ تحدد وظيفة العمق التي تستخدمها المواد لمقارنة عمق بيكسلات الإدخال مع قيمة العمق الحالية في الذاكرة المؤقتة للعمق. إذا كانت نتيجة المقارنة صحيحة، فسيتم رسم البكسل.
+ [page:Materials NeverDepth] لن يتم رسم أي بكسل.
+ [page:Materials AlwaysDepth] سيتم رسم كل البكسلات.
+ [page:Materials EqualDepth] سيتم رسم البكسل إذا كان عمق البكسل المدخل مساوٍ لعمق الذاكرة المؤقتة الحالي.
+ [page:Materials LessDepth] سيتم رسم البكسل إذا كان عمق البكسل المدخل أقل من عمق الذاكرة المؤقتة الحالي.
+ [page:Materials LessEqualDepth] هي الإعداد الافتراضي وسيتم رسم البكسل إذا كان عمق البكسل المدخل أقل من أو يساوي عمق الذاكرة المؤقتة الحالي.
+ [page:Materials GreaterEqualDepth] سيتم رسم البكسل إذا كان عمق البكسل المدخل أكبر من أو يساوي عمق الذاكرة المؤقتة الحالي.
+ [page:Materials GreaterDepth] سيتم رسم البكسل إذا كان عمق البكسل المدخل أكبر من عمق الذاكرة المؤقتة الحالي.
+ [page:Materials NotEqualDepth] سيتم رسم البكسل إذا كان عمقالبكسل المدخل لا يساوي عمق الذاكرة المؤقتة الحالي.
+

+ +

عمليات تجميع القوام الخاصة بالقوام (Texture Combine Operations)

+ + THREE.MultiplyOperation + THREE.MixOperation + THREE.AddOperation + + +

+ تحدد هذه الثوابت كيفية دمج لون سطح الكائن مع خريطة البيئة (إذا كانت متاحة) في [page:MeshBasicMaterial.combine MeshBasicMaterial]، + [page:MeshLambertMaterial.combine MeshLambertMaterial] + و [page:MeshPhongMaterial.combine MeshPhongMaterial].
+ [page:Constant MultiplyOperation] هي الإعداد الافتراضي وتقوم بضرب لون خريطة البيئة بلون سطح الكائن.
+ [page:Constant MixOperation] تستخدم معامل الانعكاسية لدمج اللونين.
+ [page:Constant AddOperation] تقوم بجمع اللونين. +

+ +

دوال القالب (Stencil Functions)

+ + THREE.NeverStencilFunc + THREE.LessStencilFunc + THREE.EqualStencilFunc + THREE.LessEqualStencilFunc + THREE.GreaterStencilFunc + THREE.NotEqualStencilFunc + THREE.GreaterEqualStencilFunc + THREE.AlwaysStencilFunc + +

+ تحدد الدالة التي يستخدمها المادة لتحديد ما إذا كان يجب أن تنفذ عملية القالب أم لا.
+ [page:Materials NeverStencilFunc] لن يعود بقيمة صحيحة أبدًا.
+ [page:Materials LessStencilFunc] سيعود بقيمة صحيحة إذا كانت قيمة المرجع الختمية أقل من القيمة الحالية للختم.
+ [page:Materials EqualStencilFunc] سيعود بقيمة صحيحة إذا كانت قيمة المرجع الختمية تساوي القيمة الحالية للختم.
+ [page:Materials LessEqualStencilFunc] سيعود بقيمة صحيحة إذا كانت قيمة المرجع الختمية أقل من أو تساوي القيمة الحالية للختم.
+ [page:Materials GreaterStencilFunc] سيعود بقيمة صحيحة إذا كانت قيمة المرجع الختمية أكبر من القيمة الحالية للختم.
+ [page:Materials NotEqualStencilFunc] سيعود بقيمة صحيحة إذا كانت قيمة المرجع الختمية لا تساوي القيمة الحالية للختم.
+ [page:Materials GreaterEqualStencilFunc] سيعود بقيمة صحيحة إذا كانت قيمة المرجع الختمية أكبر من أو تساوي القيمة الحالية للختم.
+ [page:Materials AlwaysStencilFunc] سيعود بقيمة صحيحة دائمًا.
+

+ +

عمليات القالب (Stencil Operations)

+ + THREE.ZeroStencilOp + THREE.KeepStencilOp + THREE.ReplaceStencilOp + THREE.IncrementStencilOp + THREE.DecrementStencilOp + THREE.IncrementWrapStencilOp + THREE.DecrementWrapStencilOp + THREE.InvertStencilOp + +

+ تحدد العملية التي ستقوم بها المادة على ختم البيكسل في الختم إذا مرت الدالة الختمية المقدمة.
+ [page:Materials ZeroStencilOp] سيضبط قيمة الختم على الصفر.
+ [page:Materials KeepStencilOp] لن يقوم بتغيير قيمة الختم الحالية.
+ [page:Materials ReplaceStencilOp] سيقوم بتبديل قيمة الختم بقيمة المرجع الختمية المحددة.
+ [page:Materials IncrementStencilOp] سيزيد قيمة الختم الحالية بمقدار `1`.
+ [page:Materials DecrementStencilOp] سينقص قيمة الختم الحالية بمقدار `1`.
+ [page:Materials IncrementWrapStencilOp] سيزيد قيمة الختم الحالية بمقدار `1`. إذا زادت القيمة بعد ذلك عن `255`، فستضبط على `0`.
+ [page:Materials DecrementWrapStencilOp] سينقص قيمة الختم الحالية بمقدار `1`. إذا انخفضت القيمة بعد ذلك أقل من `0`، فستضبط على `255`.
+ [page:Materials InvertStencilOp] سيقوم بتنفيذ عملية انعكاس بتشكيلة الختم الحالية.
+

+ +

نوع خريطة العرض الطبيعي (Normal map type)

+ + THREE.TangentSpaceNormalMap + THREE.ObjectSpaceNormalMap + + +

+ تحدد نوع خريطة العرض الطبيعي. لـTangentSpaceNormalMap، المعلومات ذات الصلة بالسطح الأساسي. أما بالنسبة لـ ObjectSpaceNormalMap، المعلومات ذات الصلة باتجاه الكائن. الإعداد الافتراضي هو [page:Constant TangentSpaceNormalMap]. +

+ +

إصدار GLSL

+ + THREE.GLSL1 + THREE.GLSL3 + + +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + diff --git a/docs/api/ar/constants/Renderer.html b/docs/api/ar/constants/Renderer.html new file mode 100644 index 00000000000000..86809a183f85a2 --- /dev/null +++ b/docs/api/ar/constants/Renderer.html @@ -0,0 +1,67 @@ + + + + + + + + + +

ثوابت WebGLRenderer

+ +

أنماط قطع الوجه (Cull Face Modes)

+ + THREE.CullFaceNone + THREE.CullFaceBack + THREE.CullFaceFront + THREE.CullFaceFrontBack + +

+ [page:constant CullFaceNone] تعطيل قطع الوجه.
+ [page:constant CullFaceBack] قطع الوجوه الخلفية (الافتراضي).
+ [page:constant CullFaceFront] قطع الوجوه الأمامية.
+ [page:constant CullFaceFrontBack] قطع كلا الوجوه الأمامية والخلفية. +

+ +

أنواع الظلال (Shadow Types)

+ + THREE.BasicShadowMap + THREE.PCFShadowMap + THREE.PCFSoftShadowMap + THREE.VSMShadowMap + +

+ هذه الخيارات تحدد خاصية [page:WebGLRenderer.shadowMap.type shadowMap.type] في WebGLRenderer.

+ [page:constant BasicShadowMap] يعطي خرائط ظل غير مصفاة - الأسرع ، ولكن الأقل جودة.
+ [page:constant PCFShadowMap] يصفي خرائط الظل باستخدام خوارزمية + Percentage-Closer Filtering (PCF) (افتراضي).
+ [page:constant PCFSoftShadowMap] يصفي خرائط الظل باستخدام خوارزمية + Percentage-Closer Filtering (PCF) مع أفضل الظلال الناعمة + خاصةً عند استخدام خرائط ظل بدقة منخفضة.
+ [page:constant VSMShadowMap] يصفي خرائط الظل باستخدام خوارزمية Variance Shadow + Map (VSM). عند استخدام VSMShadowMap ، سيقوم جميع مستقبلات الظل بإلقاء الظلال أيضًا. +

+ + +

Tone Mapping

+ + THREE.NoToneMapping + THREE.LinearToneMapping + THREE.ReinhardToneMapping + THREE.CineonToneMapping + THREE.ACESFilmicToneMapping + THREE.CustomToneMapping + +

+ هذه الخيارات تحدد خاصية [page:WebGLRenderer.toneMapping toneMapping] في WebGLRenderer. يتم استخدام هذا لتقريب مظهر نطاق الإضاءة العالي (HDR) على الوسط الذي يحتوي على نطاق إضاءة منخفض على شاشة الكمبيوتر القياسية أو شاشة الجوال. +

+

+ THREE.LinearToneMapping، THREE.ReinhardToneMapping، THREE.CineonToneMapping و THREE.ACESFilmicToneMapping هي تنفيذات مدمجة لتقريب مظهر نطاق الإضاءة العالي (HDR). يتوقع THREE.CustomToneMapping تنفيذًا مخصصًا عن طريق تعديل شفرة GLSL لبرنامج تظليل مقطع المواد. راجع [example:webgl_tonemapping WebGL / tonemapping] مثالًا. +

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + diff --git a/docs/api/ar/constants/Textures.html b/docs/api/ar/constants/Textures.html new file mode 100644 index 00000000000000..72545495fc89cb --- /dev/null +++ b/docs/api/ar/constants/Textures.html @@ -0,0 +1,614 @@ + + + + + + + + + +

ثوابت القوام (Texture Constants)

+ +

أوضاع التعيين (Mapping Modes)

+ + THREE.UVMapping + THREE.CubeReflectionMapping + THREE.CubeRefractionMapping + THREE.EquirectangularReflectionMapping + THREE.EquirectangularRefractionMapping + THREE.CubeUVReflectionMapping + + +

+ هذه تحدد وضع تعيين القوام.
+ [page:Constant UVMapping] هو الافتراضي ، ويقوم بتعيين القوام باستخدام إحداثيات UV للشبكة.

+ الباقي يحدد أنواع تعيين البيئة.

+ [page:Constant CubeReflectionMapping] و [page:Constant CubeRefractionMapping] للاستخدام مع [page:CubeTexture CubeTexture] ، + والتي تتكون من ستة قوام ، واحد لكل وجه من النرد. + [page:Constant CubeReflectionMapping] هو الافتراضي لـ + [page:CubeTexture CubeTexture].

+ [page:Constant EquirectangularReflectionMapping] و [page:Constant EquirectangularRefractionMapping] للاستخدام مع خريطة بيئة مستطيلة + . يسمى أيضًا خريطة lat-long ، قوام مستطيل + يمثل عرض 360 درجة على طول خط المركز الأفقي ، وعرض 180 درجة على طول المحور الرأسي ، مع حواف الأعلى والأسفل من + الصورة المقابلة للقطبين الشمال والجنوب من مجال معين + كروية.

+ راجع المثال [example:webgl_materials_envmaps materials / envmaps]. +

+ +

أوضاع التغليف (Wrapping Modes)

+ + THREE.RepeatWrapping + THREE.ClampToEdgeWrapping + THREE.MirroredRepeatWrapping + +

+ هذه تحدد خصائص [page:Texture.wrapS wrapS] و [page:Texture.wrapT wrapT] للقوام ، التي تحدد التغليف الأفقي والرأسي للقوام.

+ مع [page:constant RepeatWrapping] ستتكرر القوام ببساطة إلى ما لانهاية.

+ [page:constant ClampToEdgeWrapping] هو الافتراضي. يمتد بكسل آخر من القوام إلى حافة الشبكة.

+ مع [page:constant MirroredRepeatWrapping] ستتكرر القوام إلى ما لانهاية ، مع عكس كل تكرار. +

+ +

مرشحات التكبير (Magnification Filters)

+ + THREE.NearestFilter + THREE.LinearFilter + + +

+ للاستخدام مع خاصية [page:Texture.magFilter magFilter] للقوام ، + هذه تحدد وظيفة تكبير القوام المستخدمة عندما يتم تعيين البكسل المتعين + إلى منطقة أقل من أو تساوي عنصر قوام واحد (texel).

+ + [page:constant NearestFilter] يعيد قيمة عنصر القوام + الأقرب (في مسافة مانهاتن) إلى الإحداثيات المحددة للقوام. +

+ + [page:constant LinearFilter] هو الافتراضي ويعيد المتوسط ​​المرجح + للعناصر الأربعة من القوام التي هي الأقرب إلى الإحداثيات المحددة + للقوام ، ويمكن أن يشمل عناصر ملفوفة أو مكررة من أجزاء أخرى + من قوام ، اعتمادًا على قيم [page:Texture.wrapS wrapS] + و [page:Texture.wrapT wrapT] ، وعلى التعيين الدقيق. +

+ +

مرشحات التصغير (Minification Filters)

+ + THREE.NearestFilter + THREE.NearestMipmapNearestFilter + THREE.NearestMipmapLinearFilter + THREE.LinearFilter + THREE.LinearMipmapNearestFilter + THREE.LinearMipmapLinearFilter + + +

+ للاستخدام مع خاصية [page:Texture.minFilter minFilter] للقوام ، + هذه تحدد وظيفة تصغير القوام المستخدمة كلما كانت البكسل المتعين + يتطابق مع منطقة أكبر من عنصر قوام واحد (texel).

+ + بالإضافة إلى [page:constant NearestFilter] و [page:constant LinearFilter] ، يمكن استخدام الأربع وظائف التالية لـ + التصغير:

+ + [page:constant NearestMipmapNearestFilter] يختار mipmap الذي + يطابق حجم البكسل المتعين بشكل أكثر تطابقًا ويستخدم + معيار [page:constant NearestFilter] (ال texel الأقرب إلى المركز + من البكسل) لإنتاج قيمة قوام.

+ + [page:constant NearestMipmapLinearFilter] يختار mipmaps اثنان + يطابق حجم البكسل المتعين بشكل أكثر تطابقًا ويستخدم + معيار [page:constant NearestFilter] لإنتاج قيمة قوام من + كل mipmap. قيمة القوام النهائية هى متوسط ​​مرجح من هذه القيمتين.

+ + [page:constant LinearMipmapNearestFilter] يختار mipmap الذي + يطابق حجم البكسل المتعين بشكل أكثر تطابقًا ويستخدم + معيار [page:constant LinearFilter] (المتوسط ​​المرجح لأربعة `texels`) + التي هي الأقرب إلى مركز البكسل) لإنتاج قيمة قوام.

+ + [page:constant LinearMipmapLinearFilter] هو الافتراضي ويلتقط mipmaps اثنان + يطابق حجم البكسل المتعين بشكل أكثر تطابقًا ويلتقط [page:constant LinearFilter] + معاير لإنتاج قيمة قوام من كل mipmap. قيمة القوام النهائية هى متوسط ​​مرجح من + هذه القيمتين. + + انظر إلى المثال [example:webgl_materials_texture_filters materials / texture / filters]. +

+ +

الأنواع (Types)

+ + THREE.UnsignedByteType + THREE.ByteType + THREE.ShortType + THREE.UnsignedShortType + THREE.IntType + THREE.UnsignedIntType + THREE.FloatType + THREE.HalfFloatType + THREE.UnsignedShort4444Type + THREE.UnsignedShort5551Type + THREE.UnsignedInt248Type + +

+ للاستخدام مع خاصية [page:Texture.type type] للقوام ، التي يجب + أن تتوافق مع التنسيق الصحيح. انظر أدناه للحصول على التفاصيل.

+ + [page:constant UnsignedByteType] هو الافتراضي. +

+ +

التنسيقات (Formats)

+ + THREE.AlphaFormat + THREE.RedFormat + THREE.RedIntegerFormat + THREE.RGFormat + THREE.RGIntegerFormat + THREE.RGBAFormat + THREE.RGBAIntegerFormat + THREE.LuminanceFormat + THREE.LuminanceAlphaFormat + THREE.DepthFormat + THREE.DepthStencilFormat + +

+ للاستخدام مع خاصية [page:Texture.format format] للقوام ، هذه + تحدد كيفية قراءة عناصر قوام ثنائي الأبعاد ، أو `texels` ، بواسطة المظللات.

+ + [page:constant AlphaFormat] يتجاهل المكونات الحمراء والخضراء والزرقاء + ويقرأ فقط المكون الألفا.

+ + [page:constant RedFormat] يتجاهل المكونات الخضراء والزرقاء ويقرأ + فقط المكون الأحمر. (يمكن استخدامه فقط مع سياق WebGL 2). +

+ + [page:constant RedIntegerFormat] يتجاهل المكونات الخضراء والزرقاء + ويقرأ فقط المكون الأحمر. يتم قراءة `texels` كأعداد صحيحة بدلاً من + نقطة عائمة. (يمكن استخدامه فقط مع سياق WebGL 2). +

+ + [page:constant RGFormat] يتجاهل المكونات الألفا والزرقاء ويقرأ + المكونات الحمراء والخضراء. (يمكن استخدامه فقط مع سياق WebGL 2). +

+ + [page:constant RGIntegerFormat] يتجاهل المكونات الألفا والزرقاء + ويقرأ المكونات الحمراء والخضراء. يتم قراءة `texels` كأعداد صحيحة بدلاً من + نقطة عائمة. (يمكن استخدامه فقط مع سياق WebGL 2). +

+ + [page:constant RGBAFormat] هو الافتراضي ويلتقط المكونات الحمراء والخضراء والزرقاء + والألفا.

+ + [page:constant RGBAIntegerFormat] هو الافتراضي ويلتقط المكونات الحمراء والخضراء ، + الزرقاء والألفا. يتم قراءة `texels` كأعداد صحيحة بدلاً من + نقطة عائمة. (يمكن استخدامه فقط مع سياق WebGL 2). +

+ + [page:constant LuminanceFormat] يقرأ كل عنصر كمكون إضاءة واحد + . يتم تحويله بعد ذلك إلى نقطة عائمة ، ويتم تثبيته في + النطاق [0،1] ، ثم يتم تجميعه في عنصر RGBA عن طريق وضع + قيمة الإضاءة في القنوات الحمراء والخضراء والزرقاء ، وإرفاق `1.0` بـ + قناة الألفا.

+ + [page:constant LuminanceAlphaFormat] يقرأ كل عنصر كـ + مزدوج إضاءة / ألفا. يحدث نفس العملية كما هو الحال في [page:constant LuminanceFormat] ، باستثناء أن قناة الألفا قد تحتوي على قيم غير + `1.0`.

+ + [page:constant DepthFormat] يقرأ كل عنصر كقيمة عمق واحدة ، + يتحول إلى نقطة عائمة ، ويتم تثبيته في النطاق [0،1]. هذا هو + الافتراضي لـ [page:DepthTexture DepthTexture].

+ + [page:constant DepthStencilFormat] يقرأ كل عنصر هو زوج من العمق + وقيم المسح. يتم تفسير مكون العمق من الزوج كما هو مذكور في + [page:constant DepthFormat]. يتم تفسير مكون المسح بناءً على + التنسيق الداخلي للعمق + المسح. +

+ + لاحظ أنه يجب أن يكون للقوام نوع [page:Texture.type type] صحيحًا + كما هو مذكور أعلاه. انظر + [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D] للحصول على التفاصيل. +

+ +

تنسيقات القوام المضغوطة DDS / ST3C

+ + THREE.RGB_S3TC_DXT1_Format + THREE.RGBA_S3TC_DXT1_Format + THREE.RGBA_S3TC_DXT3_Format + THREE.RGBA_S3TC_DXT5_Format + +

+ للاستخدام مع خاصية [page:Texture.format format] لـ [page:CompressedTexture CompressedTexture] ، + هذه تتطلب دعمًا للتمديد + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/ WEBGL_compressed_texture_s3tc].

+ + هناك أربعة [link:https://en.wikipedia.org/wiki/S3_Texture_Compression تنسيقات S3TC] + متاحة عبر هذا التمديد. هذه هي:
+ [page:constant RGB_S3TC_DXT1_Format]: صورة مضغوطة بتنسيق DXT1 في تنسيق صورة RGB. +
+ [page:constant RGBA_S3TC_DXT1_Format]: صورة مضغوطة بتنسيق DXT1 في تنسيق صورة RGB + مع قيمة ألفا بسيطة تشغيل / إيقاف.
+ [page:constant RGBA_S3TC_DXT3_Format]: صورة مضغوطة بتنسيق DXT3 في تنسيق صورة RGBA. + مقارنة بقوام RGBA 32 بت ، يوفر ضغطًا 4: 1.
+ [page:constant RGBA_S3TC_DXT5_Format]: صورة مضغوطة بتنسيق DXT5 في تنسيق صورة RGBA. + كما يوفر ضغطًا 4: 1 ، ولكن يختلف عن ضغط DXT3 في كيفية ضغط الألفا.
+

+ +

تنسيقات القوام المضغوط PVRTC

+ + THREE.RGB_PVRTC_4BPPV1_Format + THREE.RGB_PVRTC_2BPPV1_Format + THREE.RGBA_PVRTC_4BPPV1_Format + THREE.RGBA_PVRTC_2BPPV1_Format + +

+ للاستخدام مع خاصية [page:Texture.format format] لـ [page:CompressedTexture CompressedTexture] ، + هذه تتطلب دعمًا للتمديد + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/ WEBGL_compressed_texture_pvrtc].
+ عادةً ما يكون PVRTC متاحًا فقط على الأجهزة المحمولة التي تحتوي على شرائح PowerVR ، + والتي هي في الغالب أجهزة Apple.

+ + هناك أربعة [link:https://en.wikipedia.org/wiki/PVRTC تنسيقات PVRTC] + متاحة عبر هذا التمديد. هذه هي:
+ [page:constant RGB_PVRTC_4BPPV1_Format]: ضغط RGB في وضع 4 بت. + كتلة واحدة لكل 4×4 بكسل.
+ [page:constant RGB_PVRTC_2BPPV1_Format]: ضغط RGB في وضع 2 بت. + كتلة واحدة لكل 8×4 بكسل.
+ [page:constant RGBA_PVRTC_4BPPV1_Format]: ضغط RGBA في وضع 4 بت. + كتلة واحدة لكل 4×4 بكسل.
+ [page:constant RGBA_PVRTC_2BPPV1_Format]: ضغط RGBA في وضع 2 بت. + كتلة واحدة لكل 8×4 بكسل.
+

+ + +

تنسيق القوام المضغوط ETC

+ + THREE.RGB_ETC1_Format + THREE.RGB_ETC2_Format + THREE.RGBA_ETC2_EAC_Format + +

+ للاستخدام مع خاصية [page:Texture.format format] لـ [page:CompressedTexture CompressedTexture] ، + هذه تتطلب دعمًا للتمديد + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/ WEBGL_compressed_texture_etc1] (ETC1) أو + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc/ WEBGL_compressed_texture_etc] (ETC2).

+

+ +

تنسيق القوام المضغوط ASTC

+ + THREE.RGBA_ASTC_4x4_Format + THREE.RGBA_ASTC_5x4_Format + THREE.RGBA_ASTC_5x5_Format + THREE.RGBA_ASTC_6x5_Format + THREE.RGBA_ASTC_6x6_Format + THREE.RGBA_ASTC_8x5_Format + THREE.RGBA_ASTC_8x6_Format + THREE.RGBA_ASTC_8x8_Format + THREE.RGBA_ASTC_10x5_Format + THREE.RGBA_ASTC_10x6_Format + THREE.RGBA_ASTC_10x8_Format + THREE.RGBA_ASTC_10x10_Format + THREE.RGBA_ASTC_12x10_Format + THREE.RGBA_ASTC_12x12_Format + +

+ للاستخدام مع خاصية [page:Texture.format format] لـ [page:CompressedTexture CompressedTexture] ، + هذه تتطلب دعمًا للتمديد + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_astc/ WEBGL_compressed_texture_astc].

+

+ +

تنسيق القوام المضغوط BPTC

+ + THREE.RGBA_BPTC_Format + +

+ للاستخدام مع خاصية [page:Texture.format format] لـ [page:CompressedTexture CompressedTexture] ، + هذه تتطلب دعمًا للتمديد + [link:https://www.khronos.org/registry/webgl/extensions/EXT_texture_compression_bptc/ EXT_texture_compression_bptc].

+

+ +

وظائف مقارنة القوام (Texture Comparison functions)

+ + THREE.NeverCompare + THREE.LessCompare + THREE.EqualCompare + THREE.LessEqualCompare + THREE.GreaterCompare + THREE.NotEqualCompare + THREE.GreaterEqualCompare + THREE.AlwaysCompare + + +

التنسيقات الداخلية (Internal Formats)

+ + 'ALPHA' + 'RGB' + 'RGBA' + 'LUMINANCE' + 'LUMINANCE_ALPHA' + 'RED_INTEGER' + 'R8' + 'R8_SNORM' + 'R8I' + 'R8UI' + 'R16I' + 'R16UI' + 'R16F' + 'R32I' + 'R32UI' + 'R32F' + 'RG8' + 'RG8_SNORM' + 'RG8I' + 'RG8UI' + 'RG16I' + 'RG16UI' + 'RG16F' + 'RG32I' + 'RG32UI' + 'RG32F' + 'RGB565' + 'RGB8' + 'RGB8_SNORM' + 'RGB8I' + 'RGB8UI' + 'RGB16I' + 'RGB16UI' + 'RGB16F' + 'RGB32I' + 'RGB32UI' + 'RGB32F' + 'RGB9_E5' + 'SRGB8' + 'R11F_G11F_B10F' + 'RGBA4' + 'RGBA8' + 'RGBA8_SNORM' + 'RGBA8I' + 'RGBA8UI' + 'RGBA16I' + 'RGBA16UI' + 'RGBA16F' + 'RGBA32I' + 'RGBA32UI' + 'RGBA32F' + 'RGB5_A1' + 'RGB10_A2' + 'RGB10_A2UI' + 'SRGB8_ALPHA8' + 'DEPTH_COMPONENT16' + 'DEPTH_COMPONENT24' + 'DEPTH_COMPONENT32F' + 'DEPTH24_STENCIL8' + 'DEPTH32F_STENCIL8' + + +

+ تنبيه: تغيير التنسيق الداخلي للقوام سيؤثر فقط على + القوام عند استخدام سياق WebGL 2.

+ + للاستخدام مع خاصية [page:Texture.internalFormat internalFormat] للقوام ، + هذه تحدد كيفية تخزين عناصر قوام ، أو `texels` ، + على وحدة معالجة الرسومات.

+ + [page:constant R8] يخزن المكون الأحمر على 8 بت.

+ + [page:constant R8_SNORM] يخزن المكون الأحمر على 8 بت. المكون + يتم تخزينه كمعيار.

+ + [page:constant R8I] يخزن المكون الأحمر على 8 بت. المكون هو + يتم تخزينه كعدد صحيح.

+ + [page:constant R8UI] يخزن المكون الأحمر على 8 بت. المكون هو + يتم تخزينه كعدد صحيح غير موقع.

+ + [page:constant R16I] يخزن المكون الأحمر على 16 بت. المكون هو + يتم تخزينه كعدد صحيح.

+ + [page:constant R16UI] يخزن المكون الأحمر على 16 بت. المكون + يتم تخزينه كعدد صحيح غير موقع.

+ + [page:constant R16F] يخزن المكون الأحمر على 16 بت. المكون هو + يتم تخزينه كعائمة نقطية.

+ + [page:constant R32I] يخزن المكون الأحمر على 32 بت. المكون هو + يتم تخزينه كعدد صحيح.

+ + [page:constant R32UI] يخزن المكون الأحمر على 32 بت. المكون + يتم تخزينه كعدد صحيح غير موقع.

+ + [page:constant R32F] يخزن المكون الأحمر على 32 بت. المكون هو + يتم تخزينه كعائمة نقطية.

+ + [page:constant RG8] يخزن المكونات الحمراء والخضراء على 8 بت لكل منهما.

+ + [page:constant RG8_SNORM] يخزن المكونات الحمراء والخضراء على 8 بت + لكل منهما. يتم تخزين كل مكون كمعيار. +

+ + [page:constant RG8I] يخزن المكونات الحمراء والخضراء على 8 بت لكل منهما. + يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RG8UI] يخزن المكونات الحمراء والخضراء على 8 بت لكل منهما. + يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RG16I] يخزن المكونات الحمراء والخضراء على 16 بت لكل منهما. + يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RG16UI] يخزن المكونات الحمراء والخضراء على 16 بت + لكل منهما. يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RG16F] يخزن المكونات الحمراء والخضراء على 16 بت لكل منهما. + يتم تخزين كل مكون كعائمة نقطية. +

+ + [page:constant RG32I] يخزن المكونات الحمراء والخضراء على 32 بت لكل منهما. + يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RG32UI] يخزن المكونات الحمراء والخضراء على 32 بت. + يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RG32F] يخزن المكونات الحمراء والخضراء على 32 بت. + يتم تخزين كل مكون كعدد عائم. +

+ + [page:constant RGB8] يخزن المكونات الحمراء والخضراء والزرقاء على 8 بت + لكل منهما. [page:constant RGB8_SNORM] يخزن المكونات الحمراء والخضراء والزرقاء + على 8 بت لكل منهما. يتم تخزين كل مكون كمعيار. +

+ + [page:constant RGB8I] يخزن المكونات الحمراء والخضراء والزرقاء على 8 بت + لكل منهما. يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RGB8UI] يخزن المكونات الحمراء والخضراء والزرقاء على 8 + بت لكل منهما. يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RGB16I] يخزن المكونات الحمراء والخضراء والزرقاء على 16 + بت لكل منهما. يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RGB16UI] يخزن المكونات الحمراء والخضراء والزرقاء على 16 + بت لكل منهما. يتم تخزيน كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RGB16F] يخزن المكونات الحمراء والخضراء والزرقاء على 16 + بت لكل منهما. يتم تخزين كل مكون كعدد عائم +

+ + [page:constant RGB32I] يخزن المكونات الحمراء والخضراء والزرقاء على 32 + بت لكل منهما. يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RGB32UI] يخزن المكونات الحمراء والخضراء والزرقاء على 32 + بت لكل منهما. يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RGB32F] يخزن المكونات الحمراء والخضراء والزرقاء على 32 + بت لكل منهما. يتم تخزين كل مكون كعدد عائم. +

+ + [page:constant R11F_G11F_B10F] يخزن المكونات الحمراء والخضراء والزرقاء + على التوالي على 11 بت ، 11 بت ، و 10 بت. يتم تخزين كل مكون كعدد عائم. +

+ + [page:constant RGB565] يخزن المكونات الحمراء والخضراء والزرقاء + على التوالي على 5 بت ، 6 بت ، و 5 بت.

+ + [page:constant RGB9_E5] يخزن المكونات الحمراء والخضراء والزرقاء على 9 + بت لكل منهما.

+ + [page:constant RGBA8] يخزن المكونات الحمراء والخضراء والزرقاء وألفا على + 8 بت لكل منهما.

+ + [page:constant RGBA8_SNORM] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 8 بت. يتم تخزين كل مكون كمعيار. +

+ + [page:constant RGBA8I] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 8 بت لكل منهما. يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RGBA8UI] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 8 بت. يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RGBA16I] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 16 بت. يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RGBA16UI] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 16 بت. يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RGBA16F] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 16 بت. يتم تخزين كل مكون كعدد عائم. +

+ + [page:constant RGBA32I] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 32 بت. يتم تخزين كل مكون كعدد صحيح. +

+ + [page:constant RGBA32UI] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 32 بت. يتم تخزين كل مكون كعدد صحيح غير موقع. +

+ + [page:constant RGBA32F] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 32 بت. يتم تخزين كل مكون كعدد عائم. +

+ + [page:constant RGB5_A1] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على التوالي على 5 بت ، 5 بت ، 5 بت ، و 1 بت.

+ + [page:constant RGB10_A2] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على التوالي على 10 بت ، 10 بت ، 10 بت و 2 بت.

+ + [page:constant RGB10_A2UI] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على التوالي على 10 بت ، 10 بت ، 10 بت و 2 بت. يتم تخزين كل + مكون كعدد صحيح غير موقع. +

+ + [page:constant SRGB8] يخزن المكونات الحمراء والخضراء والزرقاء على 8 بت + لكل منهما.

+ + [page:constant SRGB8_ALPHA8] يخزن المكونات الحمراء والخضراء والزرقاء وألفا + على 8 بت لكل منهما.

+ + [page:constant DEPTH_COMPONENT16] يخزن مكون العمق على 16 بت.

+ + [page:constant DEPTH_COMPONENT24] يخزن مكون العمق على 24 بت.

+ + [page:constant DEPTH_COMPONENT32F] يخزن مكون العمق على 32 بت. + يتم تخزين المكون كعدد عائم.

+ + [page:constant DEPTH24_STENCIL8] يخزن مكوان العمق ، ومكوان الإستانسيل + على التوالي على 24 بت و 8 بت. يتم تخزين مكوان الإستانسيل كعدد صحيح غير موقع. +

+ + [page:constant DEPTH32F_STENCIL8] يخزن مكوان العمق ، ومكوان الإستانسيل + على التوالي على 32 بت و 8 بت. يتم تخزين مكوان العمق كعدد عائم ، ومكوان الإستانسيل كعدد صحيح غير موقع. +

+ + لاحظ أنه يجب أن تحظى المادة المستهلكة للصورة (texture) بـ [page:Texture.type type] + صحيحة، فضلاً عن [page:Texture.format format]. اطَّلِعْ عَلى + [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D], and + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texImage3D WebGL2RenderingContext.texImage3D], لِلْحُصُولِ عَلىْ تَفَاصِيلَ أَكْثَرَ حَولَ + إِجْهِادِ [page:Texture.format format], + [page:Texture.internalFormat internalFormat], and [page:Texture.type type].

+ + لِلْحُصُولِ عَلىْ مَعْلُوْمَاتَ أَشْمَلَ حَولَ التَّشْكِيلَاتِ الدَّاخِلِيَّةِ، يُمْكِنُ أَيْضا أَ نْ تُشِيرُ إِلَى + [link:https://www.khronos.org/registry/webgl/specs/latest/2.0/ WebGL2 Specification] and to the + [link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0 Specification]. +

+ +

تعبئة العمق (Depth Packing)

+ + THREE.BasicDepthPacking + THREE.RGBADepthPacking + +

+ للاستخدام مع خاصية [page:MeshDepthMaterial.depthPacking depthPacking] + لـ `MeshDepthMaterial`. +

+ +

مساحة اللون (Color Space)

+ + THREE.NoColorSpace = "" + THREE.SRGBColorSpace = "srgb" + THREE.LinearSRGBColorSpace = "srgb-linear" + +

+ يستخدم لتحديد مساحة اللون للصور (ومساحة اللون الناتجة من + المُصَوِّر).

+ + إذا تم تغيير نوع مساحة اللون بعد استخدام الصورة بالفعل + بواسطة مادة ، ستحتاج إلى تعيين [page:Material.needsUpdate Material.needsUpdate] إلى `true` لإعادة تجميع المادة.

+

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + diff --git a/docs/api/ar/core/BufferAttribute.html b/docs/api/ar/core/BufferAttribute.html new file mode 100644 index 00000000000000..df84f43e8394bc --- /dev/null +++ b/docs/api/ar/core/BufferAttribute.html @@ -0,0 +1,235 @@ + + + + + + + + + +

[name]

+ +

+ تخزن هذه الفئة بيانات لسمة (مثل مواضع الرأس ، ومؤشرات الوجه ، والمعايير ، والألوان ، والأشعة فوق البنفسجية ، وأي سمات مخصصة) المرتبطة + مع [page:BufferGeometry] ، مما يسمح بتمرير البيانات بشكل أكثر كفاءة + إلى وحدة معالجة الرسومات. انظر تلك الصفحة للحصول على التفاصيل ومثال على الاستخدام. عند العمل + مع بيانات مثل المتجهات ، قد تكون طرق المساعد .fromBufferAttribute(attribute, index) + على [page:Vector2.fromBufferAttribute Vector2]، + [page:Vector3.fromBufferAttribute Vector3]، + [page:Vector4.fromBufferAttribute Vector4]، و + [page:Color.fromBufferAttribute Color] قد تكون مفيدة. +

+ +

المنشئ (Constructor)

+

[name]([param:TypedArray array]، [param:Integer itemSize]، [param:Boolean normalized])

+

+ [page:TypedArray array] - يجب أن يكون + [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/TypedArray TypedArray]. يستخدم لإنشاء المخزن المؤقت.
+ يجب أن يحتوي هذا المصفوفة على + + itemSize * numVertices + + عناصر ، حيث numVertices هو عدد الرؤوس في المرتبطة + [page:BufferGemetry BufferGeometry].

+ + [page:Integer itemSize] - عدد قيم المصفوفة التي يجب + ترتبط برأس معين. على سبيل المثال ، إذا كانت هذه السمة هي + تخزين متجه من 3 مكونات (مثل الموضع أو الطبيعي أو اللون) ، فإن + itemSize يجب أن يكون 3. +

+ + [page:Boolean normalized] - (اختياري) ينطبق على البيانات الصحيحة فقط. + يشير إلى كيفية تعيين البيانات الأساسية في المخزن المؤقت إلى القيم في + كود GLSL. على سبيل المثال ، إذا كان [page:TypedArray array] هو نسخة من + UInt16Array ، و [page:Boolean normalized] صحيحًا ، فإن القиم `0 - + +65535` في بيانات المصفوفة ستُخرج إلى 0.0f - +1.0f في GLSL + attribute. ستُخرج Int16Array (signed) من -32768 - +32767 إلى -1.0f + - +1.0f. إذا كان [page:Boolean normalized] خطأً ، فستكون القيم + تحول إلى floats دون تعديل ، أي 32767 يصبح 32767.0f. +

+ +

الخصائص (Properties)

+ +

[property:TypedArray array]

+

ال[page:TypedArray array] التي تحمل البيانات المخزنة في المخزن المؤقت.

+ +

[property:Integer count]

+

+ يخزن طول [page:BufferAttribute.array array] مقسومًا على + [page:BufferAttribute.itemSize itemSize].

+ + إذا كان المخزن يخزن متجهًا من 3 مكونات (مثل الموضع أو الطبيعي أو اللون) ، فسيحسب عدد هذه المتجهات المخزنة. +

+ +

[property:Boolean isBufferAttribute]

+

علامة للقراءة فقط للتحقق مما إذا كان الكائن المعطى من نوع [name].

+ +

[property:Integer itemSize]

+

+ طول المتجهات التي يتم تخزينها في + [page:BufferAttribute.array array]. +

+ +

[property:String name]

+

اسم اختياري لهذا الحدث من السمة. الافتراضي هو سلسلة فارغة.

+ +

[property:Boolean needsUpdate]

+

+ علامة للإشارة إلى أن هذه السمة قد تغيرت ويجب إعادة إرسالها إلى + وحدة معالجة الرسومات. قم بتعيين هذا على true عند تعديل قيمة المصفوفة.

+ + تعيين هذا على true يزيد أيضًا من [page:BufferAttribute.version version]. +

+ +

[property:Boolean normalized]

+

+ يشير إلى كيفية تعيين البيانات الأساسية في المخزن المؤقت إلى القيم في + كود GLSL. راجع المُنشئ أعلاه للحصول على التفاصيل. +

+ +

[property:Function onUploadCallback]

+

+ دالة رد اتصال يتم تنفيذها بعد أن قام Renderer بنقل + بيانات مصفوفة السمة إلى وحدة معالجة الرسومات. +

+ +

[property:Object updateRange]

+

+ كائن يحتوي على:
+ [page:Integer offset]: الافتراضية هي `0`. الموضع الذي يجب أن يبدأ فيه + التحديث.
+ [page:Integer count]: الافتراضية هي `-1` ، وهذا يعني عدم استخدام التحديث + المدى.

+ + يمكن استخدام هذا لتحديث بعض مكونات المتجهات المخزنة فقط (على سبيل المثال ، فقط المكوِّن المرتبط باللون). +

+ +

[property:Usage usage]

+

+ يحدد نمط الاستخدام المقصود لمخزن البيانات لأغراض التحسين + . يتوافق مع معلمة `usage` من + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData](). الافتراضي هو [page:BufferAttributeUsage StaticDrawUsage]. راجع الاستخدام [page:BufferAttributeUsage constants] لجميع + القيم الممكنة.

+ + ملاحظة: بعد الاستخدام الأولي للمخزن المؤقت ، لا يمكن تغيير استخدامه. + بدلاً من ذلك ، قم بإنشاء نسخة جديدة وتعيين الاستخدام المطلوب قبل التالي + جعل. +

+ +

[property:Integer version]

+

+ رقم إصدار ، يزداد كل مرة + [page:BufferAttribute.needsUpdate needsUpdate] يتم تعيين خاصية على true. +

+ +

الوظائف (Methods)

+ +

[method:this applyMatrix3]([param:Matrix3 m])

+

+ تطبق المصفوفة [page:Matrix3 m] على كل عنصر Vector3 من هذا + BufferAttribute. +

+ +

[method:this applyMatrix4]([param:Matrix4 m])

+

+ تطبق المصفوفة [page:Matrix4 m] على كل عنصر Vector3 من هذا + BufferAttribute. +

+ +

[method:this applyNormalMatrix]([param:Matrix3 m])

+

+ تطبق المصفوفة الطبيعية [page:Matrix3 m] على كل عنصر Vector3 من هذا + BufferAttribute. +

+ +

[method:this transformDirection]([param:Matrix4 m])

+

+ تطبق المصفوفة [page:Matrix4 m] على كل عنصر Vector3 من هذا + BufferAttribute ، مع تفسير العناصر كمتجهات اتجاه. +

+ +

[method:BufferAttribute clone]()

+

إرجاع نسخة من هذه bufferAttribute.

+ +

[method:this copy]([param:BufferAttribute bufferAttribute])

+

ينسخ BufferAttribute آخر إلى هذه BufferAttribute.

+ +

[method:this copyArray](array)

+

+ انسخ المصفوفة المعطاة هنا (والتي يمكن أن تكون مصفوفة عادية أو TypedArray) إلى + [page:BufferAttribute.array array].

+ + انظر + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set TypedArray.set] للحصول على ملاحظات حول المتطلبات إذا كان يتم نسخ TypedArray. +

+ +

[method:this copyAt]([param:Integer index1]، [param:BufferAttribute bufferAttribute]، [param:Integer index2])

+

انسخ متجهًا من bufferAttribute[index2] إلى [page:BufferAttribute.array array][index1].

+ +

[method:Number getX]([param:Integer index])

+

يعيد مكون x من المتجه في المؤشر المحدد.

+ +

[method:Number getY]([param:Integer index])

+

يعيد مكون y من المتجه في المؤشر المحدد.

+ +

[method:Number getZ]([param:Integer index])

+

يعيد مكون z من المتجه في المؤشر المحدد.

+ +

[method:Number getW]([param:Integer index])

+

يعيد مكون w من المتجه في المؤشر المحدد.

+ +

[method:this onUpload]([param:Function callback])

+

+ يضع قيمة خاصية onUploadCallback.

+ + في [example:webgl_buffergeometry WebGL / Buffergeometry] يتم استخدام هذا + لتحرير الذاكرة بعد نقل المخزن إلى وحدة معالجة الرسومات. +

+ +

[method:this set]([param:Array value]، [param:Integer offset])

+

+ value - [page:Array] أو [page:TypedArray] لنسخ القيم منه. +
+ offset - (اختياري) فهرس [page:BufferAttribute.array array] في + الذي يجب البدء في النسخ.

+ + المكالمات + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set TypedArray.set]([page:Array value]، [page:Integer offset]) على + [page:BufferAttribute.array array].

+ + على وجه الخصوص ، انظر تلك الصفحة للحصول على متطلبات [page:Array value] كونها + [page:TypedArray]. +

+ +

[method:this setUsage]([param:Usage value])

+

+ قم بتعيين [page:BufferAttribute.usage usage] إلى value. راجع الاستخدام + [page:BufferAttributeUsage constants] لجميع قيم الإدخال الممكنة. +

+ + ملاحظة: بعد الاستخدام الأولي للمخزن المؤقت ، لا يمكن تغيير استخدامه. + بدلاً من ذلك ، قم بإنشاء نسخة جديدة وتعيين الاستخدام المطلوب قبل التالي + جعل. +

+ +

[method:this setX]([param:Integer index], [param:Float x])

+

تضبط مكون x من المتجه في المؤشر المحدد.

+ +

[method:this setY]([param:Integer index], [param:Float y])

+

تضبط مكون y من المتجه في المؤشر المحدد.

+ +

[method:this setZ]([param:Integer index], [param:Float z])

+

تضبط مكون z من المتجه في المؤشر المحدد.

+ +

[method:this setW]([param:Integer index], [param:Float w])

+

تضبط مكون w من المتجه في المؤشر المحдد.

+ +

[method:this setXY]([param:Integer index], [param:Float x], [param:Float y])

+

تضبط مكونات x و y من المتجه في + +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/BufferGeometry.html b/docs/api/ar/core/BufferGeometry.html new file mode 100644 index 00000000000000..28c9b868acd1d2 --- /dev/null +++ b/docs/api/ar/core/BufferGeometry.html @@ -0,0 +1,366 @@ + + + + + + + + + +

[name]

+ +

+ تمثيل شبكة ، خط ، أو هندسة نقطية. يتضمن مواقع الرأس ، ومؤشرات الوجه ، والمعايير ، والألوان ، والأشعة فوق البنفسجية ، والسمات المخصصة + داخل المخازن المؤقتة ، مما يقلل من تكلفة تمرير كل هذه البيانات إلى وحدة معالجة الرسومات. +

+

+ لقراءة وتحرير البيانات في سمات BufferGeometry ، راجع + [page:BufferAttribute] التوثيق. +

+ +

مثال للكود

+ + + const geometry = new THREE.BufferGeometry(); + + // إنشاء شكل مربع بسيط. نحن نكرر الأعلى الأيسر والأسفل الأيمن + // الرؤوس لأن كل رأس يحتاج إلى الظهور مرة واحدة لكل مثلث. + const vertices = new Float32Array( [ + -1.0, -1.0, 1.0, // v0 + 1.0, -1.0, 1.0, // v1 + 1.0, 1.0, 1.0, // v2 + + 1.0, 1.0, 1.0, // v3 + -1.0, 1.0, 1.0, // v4 + -1.0, -1.0, 1.0 // v5 + ] ); + + // itemSize = 3 لأنه يوجد 3 قيم (مكونات) لكل رأس + geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); + const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); + const mesh = new THREE.Mesh( geometry, material ); + + +

مثال للكود (Index)

+ + + const geometry = new THREE.BufferGeometry(); + + const vertices = new Float32Array( [ + -1.0, -1.0, 1.0, // v0 + 1.0, -1.0, 1.0, // v1 + 1.0, 1.0, 1.0, // v2 + -1.0, 1.0, 1.0, // v3 + ] ); + + const indices = [ + 0, 1, 2, + 2, 3, 0, + ]; + + geometry.setIndex( indices ); + geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); + + const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); + const mesh = new THREE.Mesh( geometry, material ); + + +

أمثلة (Examples)

+

+ [example:webgl_buffergeometry شبكة بوجوه غير مفهرسة]
+ [example:webgl_buffergeometry_indexed شبكة بوجوه مفهرسة]
+ [example:webgl_buffergeometry_lines خطوط]
+ [example:webgl_buffergeometry_lines_indexed خطوط مفهرسة]
+ [example:webgl_buffergeometry_custom_attributes_particles جزيئات]
+ [example:webgl_buffergeometry_rawshader محركات الظل الخام] +

+ +

المنشئ (Constructor)

+ +

[name]()

+
+ ينشئ هذا [name] جديدًا. كما يضبط العديد من الخصائص على قيمة افتراضية + قيمة. +
+ +

الخصائص (Properties)

+ +

[property:Object attributes]

+

+ يحتوي هذا الخريطة القائمة على الهوية على اسم السمة المراد تعيينها وكقيمة + [page:BufferAttribute buffer] لتعيينه. بدلاً من الوصول إلى هذا + الملكية مباشرة ، استخدم [page:.setAttribute] و [page:.getAttribute] ل + الوصول إلى سمات هذه الهندسة. +

+ +

[property:Box3 boundingBox]

+

+ مربع التحديد لـ bufferGeometry ، والذي يمكن حسابه بـ + [page:.computeBoundingBox](). الافتراضي هو `null`. +

+ +

[property:Sphere boundingSphere]

+

+ كرة التحديد لـ bufferGeometry ، والتي يمكن حسابها بـ + [page:.computeBoundingSphere](). الافتراضي هو `null`. +

+ +

[property:Object drawRange]

+

+ يحدد جزء الهندسة المراد عرضه. يجب عدم تعيين هذا + مباشرة ، بدلاً من ذلك استخدم [page:.setDrawRange]. الافتراضي هو + + { start: 0, count: Infinity } + + بالنسبة لـ BufferGeometry غير المفهرس ، count هو عدد القمم التي يتم عرضها. + بالنسبة لـ BufferGeometry المفهرس ، count هو عدد المؤشرات التي يتم عرضها. +

+ +

[property:Array groups]

+ +

+ قسم الهندسة إلى مجموعات ، كل منها سيتم عرضه في + مكالمة WebGL رسم منفصلة. هذا يسمح باستخدام مجموعة من المواد + مع الهندسة.

+ + كل مجموعة هي كائن من الشكل: + + { start: Integer, count: Integer, materialIndex: Integer } + + حيث يحدد start العنصر الأول في هذه المكالمة - الأول + رأس للهندسة غير المفهرسة ، وإلا فإن المثلث الأول فهرس. عد + يحدد كم عدد القمم (أو المؤشرات) المضمنة ، و materialIndex + يحدد فهرس مجموعة المواد للاستخدام.

+ + استخدم [page:.addGroup] لإضافة مجموعات ، بدلاً من تعديل هذا المصفوفة + مباشرة.

+ + يجب أن ينتمي كل رأس وفهرس إلى مجموعة واحدة فقط - يجب ألا تشترك المجموعات + قمم أو مؤشرات ، ويجب ألا تترك القمم أو المؤشرات غير المستخدمة. +

+ + + +

[property:Integer id]

+

رقم فريد لهذا الحال bufferGeometry.

+ +

[property:BufferAttribute index]

+

+ يتيح إعادة استخدام القمم عبر مثلثات متعددة ؛ هذا هو + يسمى باستخدام "المثلثات المفهرسة". يرتبط كل مثلث بـ + مؤشرات ثلاث قمم. لذلك تخزن هذه السمة فهرس + كل رأس لكل وجه ثلاثي الأضلاع. إذا لم يتم تعيين هذه السمة ، فإن + [page:WebGLRenderer renderer] يفترض أن كل ثلاثة مواقع متجاورة + تمثل مثلثًا واحدًا. الافتراضي هو `null`. +

+ +

[property:Boolean isBufferGeometry]

+

علامة للقراءة فقط للتحقق مما إذا كان الكائن المحدد من نوع [name].

+ +

[property:Object morphAttributes]

+

+ خريطة قائمة على [page:BufferAttribute]s التي تحمل تفاصيل هندسة المورف + الأهداف.
+ ملاحظة: بمجرد عرض الهندسة ، لا يمكن تغيير بيانات سمة المورف + يتغير. سيتعين عليك الاتصال [page:.dispose]() ، وإنشاء جديد + نسخة من [name]. +

+ +

[property:Boolean morphTargetsRelative]

+

+ يستخدم للتحكم في سلوك هدف المورف ؛ عند تعيينه على true ، المورف + يتم التعامل مع بيانات الهدف كإزاحات نسبية ، بدلاً من كـ + المواقع / المعايير المطلقة. الافتراضي هو `false`. +

+ +

[property:String name]

+

+ اسم اختياري لهذه الحالة bufferGeometry. الافتراضي هو فارغ + سلسلة. +

+ +

[property:Object userData]

+

+ كائن يمكن استخدامه لتخزين بيانات مخصصة حول BufferGeometry. + يجب ألا يحتوي على مراجع للوظائف حيث لن يتم استنساخها. +

+ +

[property:String uuid]

+

+ [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] من + هذه الحالة كائن. يتم تعيين هذا تلقائيًا ولا يجب أن يكون + تحرير. +

+ +

الوظائف (Methods)

+ +

+ [page:EventDispatcher EventDispatcher] الطرق متوفرة على هذا + صف. +

+ +

[method:undefined addGroup]([param:Integer start]، [param:Integer count]، [param:Integer materialIndex])

+

+ يضيف مجموعة إلى هذه الهندسة ؛ انظر [page:BufferGeometry.groups groups] + خاصية للحصول على التفاصيل. +

+ +

[method:this applyMatrix4]([param:Matrix4 matrix])

+

تطبق تحويل المصفوفة على الهندسة.

+ +

[method:this applyQuaternion]([param:Quaternion quaternion])

+

يطبق التدوير الممثل بالرباعي على الهندسة.

+ +

[method:this center] ()

+

مركز الهندسة بناءً على مربع التحديد.

+ +

[method:undefined clearGroups]( )

+

يمسح جميع المجموعات.

+ +

[method:BufferGeometry clone]()

+

ينشئ نسخة من هذا BufferGeometry.

+ +

[method:undefined computeBoundingBox]()

+

+ يحسب مربع التحديد للهندسة ، ويحدث [page:.boundingBox] + سمة.
+ لا يتم حساب مربعات التحديد افتراضيًا. يجب حسابها بشكل صريح + حساب ، وإلا كانت `null`. +

+ +

[method:undefined computeBoundingSphere]()

+

+ يحسب كرة التحديد للهندسة ، ويحدث [page:.boundingSphere] + سمة.
+ لا تتم حساب كرات التحديد افتراضيًا. يجب حسابها بشكل صريح + حساب ، وإلا كانت `null`. +

+ +

[method:undefined computeTangents]()

+

+ يحسب ويضيف سمة مماسية لهذه الهندسة.
+ الحساب مدعوم فقط للهندسات المفهرسة وإذا تم تعريف الوضعية ، + الطبيعية ، والأشعة فوق البنفسجية. عند استخدام خريطة طبيعية للفضاء المماس + خريطة ، تفضل خوارزمية MikkTSpace المقدمة من قبل + [page:BufferGeometryUtils.computeMikkTSpaceTangents] بدلاً من ذلك. +

+ +

[method:undefined computeVertexNormals]()

+

تحسب قمم الأوجه للبيانات القمية المعطاة. بالنسبة للهندسات المفهرسة ، يضبط الأسلوب كل قمة عادية لتكون متوسط ​​أوجه الوجه التي تشارك هذه القمة. + بالنسبة للهندسات غير المفهرسة ، لا تتشارك القمم ، ويضبط الأسلوب كل قمة عادية لتكون نفس وجه الوجه.

+ +

[method:this copy]( [param:BufferGeometry bufferGeometry] )

+

ينسخ BufferGeometry آخر إلى هذا BufferGeometry.

+ +

[method:BufferAttribute deleteAttribute]( [param:String name] )

+

تحذف [page:BufferAttribute attribute] بالاسم المحدد.

+ +

[method:undefined dispose]()

+

+ يطلق الموارد المتعلقة بوحدة معالجة الرسومات التي تم تخصيصها من قبل هذا المثيل. اتصل بهذا + الأسلوب كلما لم يعد هذا المثيل مستخدمًا في تطبيقك. +

+ +

[method:BufferAttribute getAttribute]( [param:String name] )

+

يرجع [page:BufferAttribute attribute] بالاسم المحدد.

+ +

[method:BufferAttribute getIndex] ()

+

يرجع [page:.index] buffer.

+ +

[method:Boolean hasAttribute]( [param:String name] )

+

يعود `true` إذا كانت السمة بالاسم المحدد موجودة.

+ +

[method:this lookAt] ( [param:Vector3 vector] )

+

+ vector - نقطة عالمية للنظر إليها.

+ + يدور الهندسة لمواجهة نقطة في الفضاء. يتم هذا عادةً كـ + عملية واحدة ، وليس أثناء حلقة. استخدم [page:Object3D.lookAt] لـ + الاستخدام النموذجي للشبكة في الوقت الفعلي. +

+ +

[method:undefined normalizeNormals]()

+

+ سيكون كل متجه طبيعي في هندسة بقوة 1. هذا سوف + تصحح الإضاءة على سطوح الهندسة. +

+ +

[method:this rotateX] ( [param:Float radians] )

+

+ قم بتدوير الهندسة حول المحور X. يتم هذا عادةً كعملية واحدة + عملية ، وليس أثناء حلقة. استخدم [page:Object3D.rotation] لـ + تدوير شبكة نموذجية في الوقت الفعلي. +

+ +

[method:this rotateY] ( [param:Float radians] )

+

+ قم بتدوير الهندسة حول المحور Y. يتم هذا عادةً كعملية واحدة + عملية ، وليس أثناء حلقة. استخدم [page:Object3D.rotation] لـ + تدوير شبكة نموذجية في الوقت الفعلي. +

+ +

[method:this rotateZ] ( [param:Float radians] )

+

+ قم بتدوير الهندسة حول المحور Z. يتم هذا عادةً كعملية واحدة + عملية ، وليس أثناء حلقة. استخدم [page:Object3D.rotation] لـ + تدوير شبكة نموذجية في الوقت الفعلي. +

+ +

[method:this scale] ( [param:Float x], [param:Float y], [param:Float z] )

+

+ قم بتغيير حجم بيانات الهندسة. يتم هذا عادةً كعملية واحدة ، + وليس أثناء حلقة. استخدام [page:Object3D.scale] لـ + تغيير حجم شبكات نموذجية في الوقت الفعلي. +

+ +

[method:this setAttribute]( [param:String name], [param:BufferAttribute attribute] )

+

+ يضع سمة لهذه الهندسة. استخدام هذا بدلاً من خصائص + الملكية ، لأن خريطة قائمة داخلية من [page:.attributes] + يتم صيانته لتسريع التكرار على السمات. +

+ +

[method:undefined setDrawRange] ( [param:Integer start], [param:Integer count] )

+

+ قم بتعيين خاصية [page:.drawRange]. بالنسبة لـ BufferGeometry غير المفهرس ، count + هو عدد القمم التي يتم عرضها. بالنسبة لـ BufferGeometry المفهرس ، count هو + عدد المؤشرات التي يتم عرضها. +

+ +

[method:this setFromPoints] ( [param:Array points] )

+

تضبط سمات هذا BufferGeometry من مصفوفة من النقاط.

+ +

[method:this setIndex] ( [param:BufferAttribute index] )

+

ضبط buffer [page:.index].

+ +

[method:Object toJSON]()

+

+ قُم بتحويل هندسة buffer إلى three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. +

+ +

[method:BufferGeometry toNonIndexed]()

+

إرجاع إصدار غير مفهرس من BufferGeometry المفهرس.

+ +

[method:this translate] ( [param:Float x], [param:Float y], [param:Float z] )

+

+ قُم بترجمة الهندسة. يتم هذا عادةً كعملية واحدة ، + وليس أثناء حلقة. استخدم [page:Object3D.position] لـ + ترجمة شبكات نموذجية في الوقت الفعلي. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/Clock.html b/docs/api/ar/core/Clock.html new file mode 100644 index 00000000000000..2f0bb57fdbcbc7 --- /dev/null +++ b/docs/api/ar/core/Clock.html @@ -0,0 +1,93 @@ + + + + + + + + + +

[name]

+ +

+ كائن لتتبع الوقت. يستخدم هذا + [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now] إذا كان متاحًا، وإلا فإنه يعود إلى + دقة أقل + [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now]. +

+ +

المنشئ (Constructor)

+ +

[name]( [param:Boolean autoStart] )

+

+ autoStart — (اختياري) ما إذا كان يجب تشغيل الساعة تلقائيًا عندما + [page:.getDelta]() يتم استدعاؤه لأول مرة. الافتراضي هو `true`. +

+ +

الخصائص (Properties)

+ +

[property:Boolean autoStart]

+

+ إذا تم تعيينه، يبدأ الساعة تلقائيًا عندما يتم استدعاء [page:.getDelta]() + لأول مرة. الافتراضي هو `true`. +

+ +

[property:Float startTime]

+

+ يحمل الوقت الذي تم فيه استدعاء طريقة [page:Clock.start start] للساعة + آخر مرة. الافتراضي هو `0`. +

+ +

[property:Float oldTime]

+

+ يحمل الوقت الذي تم فيه استدعاء طرق [page:Clock.start start], + [page:.getElapsedTime]() أو [page:.getDelta]() للساعة آخر مرة. + الافتراضي هو `0`. +

+ +

[property:Float elapsedTime]

+

+ يتبع المجموع الكلي للوقت الذي كانت تعمل فيه الساعة. الافتراضي هو + `0`. +

+ +

[property:Boolean running]

+

ما إذا كانت الساعة تعمل أم لا. الافتراضي هو `false`.

+ +

الوظائف (Methods)

+ +

[method:undefined start]()

+

+ يبدأ الساعة. كما يضبط [page:.startTime] و [page:.oldTime] على + الوقت الحالي، ويضبط [page:.elapsedTime] على `0` و [page:.running] على + `true`. +

+ +

[method:undefined stop]()

+

+ يوقف الساعة ويضبط [page:Clock.oldTime oldTime] على الوقت الحالي. +

+ +

[method:Float getElapsedTime]()

+

+ احصل على المجموع الكلي للثواني التي مرت منذ بدء تشغيل الساعة وضبط [page:.oldTime] على + الوقت الحالي.
+ إذا كان [page:.autoStart] هو `true` والساعة لا تعمل، فإنه يبدأ أيضًا + ساعة. +

+ +

[method:Float getDelta]()

+

+ احصل على المجموع الكلي للثواني التي مرت منذ ضبط [page:.oldTime] وضبط + [page:.oldTime] على الوقت الحالي.
+ إذا كان [page:.autoStart] هو `true` والساعة لا تعمل، فإنه يبدأ أيضًа + ساعة. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/EventDispatcher.html b/docs/api/ar/core/EventDispatcher.html new file mode 100644 index 00000000000000..200ed6c377d7bd --- /dev/null +++ b/docs/api/ar/core/EventDispatcher.html @@ -0,0 +1,74 @@ + + + + + + + + + +

[name]

+ +

+ أحداث JavaScript للكائنات المخصصة.
+ [link:https://github.com/mrdoob/eventdispatcher.js EventDispatcher على GitHub] +

+ +

مثال الكود

+ + + // إضافة الأحداث إلى كائن مخصص + class Car extends EventDispatcher { + start() { + this.dispatchEvent( { type: 'start', message: 'vroom vroom!' } ); + } + }; + + // استخدام الأحداث مع الكائن المخصص + const car = new Car(); + car.addEventListener( 'start', function ( event ) { + alert( event.message ); + } ); + + car.start(); + + +

المنشئ (Constructor)

+ +

[name]()

+

ينشئ كائن EventDispatcher.

+ +

الوظائف (Methods)

+ +

[method:undefined addEventListener]( [param:String type], [param:Function listener] )

+

+ type - نوع الحدث الذي يتم الاستماع إليه.
+ listener - الدالة التي يتم استدعاؤها عند إطلاق الحدث. +

+

يضيف مستمعًا إلى نوع حدث.

+ +

[method:Boolean hasEventListener]( [param:String type], [param:Function listener] )

+

+ type - نوع الحدث الذي يتم الاستماع إليه.
+ listener - الدالة التي يتم استدعاؤها عند إطلاق الحدث. +

+

يتحقق مما إذا كان المستمع قد تمت إضافته إلى نوع حدث.

+ +

[method:undefined removeEventListener]( [param:String type], [param:Function listener] )

+

+ type - نوع المستمع الذي يتم إزالته.
+ listener - دالة المستمع التي يتم إزالتها. +

+

يزيل مستمعًا من نوع حدث.

+ +

[method:undefined dispatchEvent]( [param:Object event] )

+

event - الحدث الذي يتم إطلاقه.

+

إطلاق نوع حدث.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/GLBufferAttribute.html b/docs/api/ar/core/GLBufferAttribute.html new file mode 100644 index 00000000000000..b3858642e2ea33 --- /dev/null +++ b/docs/api/ar/core/GLBufferAttribute.html @@ -0,0 +1,118 @@ + + + + + + + + + +

[name]

+ +

+ لا يقوم هذا الفئة السمة المخزنة بإنشاء VBO. بدلاً من ذلك، يستخدم + أي VBO يتم تمريره في المُنشئ ويمكن تغييره لاحقًا عبر خاصية + `buffer`.

+ من الضروري تمرير معلمات إضافية جنبًا إلى جنب مع VBO. هذه هي: GL + context، نوع البيانات GL، عدد المكونات لكل رأس، عدد البايتات لكل + مكون، وعدد الرؤوس.

+ أكثر حالات الاستخدام شيوعًا لهذه الفئة هي عندما يتداخل نوع من + حسابات GPGPU أو حتى ينتج VBOs المعنية. +

+ +

المنشئ (Constructor)

+

[name]( [param:WebGLBuffer buffer], [param:GLenum type], [param:Integer itemSize], [param:Integer elementSize], [param:Integer count] )

+

+ `buffer` — يجب أن يكون + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer]. +
+ `type` — واحد من + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types أنواع بيانات WebGL]. +
+ `itemSize` — عدد قيم المصفوفة التي يجب ربطها برأس معين. على سبيل + المثال، إذا كانت هذه السمة تخزن متجهًا ثلاثي الأبعاد (مثل الموضع، + الطبيعي، أو اللون)، فيجب أن يكون itemSize هو 3. +
+ `elementSize` — 1، 2 أو 4. الحجم المقابل (بالبايت) للمعلمة "type" + المعطاة. +

+ +
    +
  • gl.FLOAT: 4
  • +
  • gl.UNSIGNED_SHORT: 2
  • +
  • gl.SHORT: 2
  • +
  • gl.UNSIGNED_INT: 4
  • +
  • gl.INT: 4
  • +
  • gl.BYTE: 1
  • +
  • gl.UNSIGNED_BYTE: 1
  • +
+

`count` — عدد الرؤوس المتوقع في VBO.

+ +

الخصائص (Properties)

+ +

[property:WebGLBuffer buffer]

+

+ نسخة + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer] الحالية. +

+ +

[property:Integer count]

+

عدد الرؤوس المتوقع في VBO.

+ +

[property:Boolean isGLBufferAttribute]

+

للقراءة فقط. دائمًا `true`.

+ +

[property:Integer itemSize]

+

كم عدد القيم التي تشكل كل عنصر (رأس).

+ +

[property:Integer elementSize]

+

+ يخزن الحجم المقابل بالبايت لقيمة خاصية `type` الحالية. +

+

انظر أعلاه (المُنشئ) لقائمة بأحجام الأنواع المعروفة.

+ +

[property:String name]

+

+ اسم اختياري لهذه الحالة من السمة. الافتراضي هو سلسلة فارغة. +

+ +

[property:GLenum type]

+

+ [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types نوع بيانات WebGL] يصف محتوى VBO الأساسي. +

+

+ قم بتعيين هذه الخاصية معًا مع `elementSize`. الطريقة المستحسنة هي + باستخدام طريقة `setType`. +

+ +

الوظائف (Methods)

+ +

[method:this setBuffer]( buffer )

+

تضبط خاصية `buffer`.

+ +

[method:this setType]( type, elementSize )

+

تضبط كلاً من خصائص `type` و `elementSize`.

+ +

[method:this setItemSize]( itemSize )

+

تضبط خاصية `itemSize`.

+ +

[method:this setCount]( count )

+

تضبط خاصية `count`.

+ +

[property:Integer version]

+

+ رقم إصدار، يزاد كل مرة يتم فيها تعيين خاصية needsUpdate على true. +

+ +

[property:Boolean needsUpdate]

+

+ الافتراضي هو `false`. تعيين هذا إلى true يزاد + [page:GLBufferAttribute.version version]. +

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/InstancedBufferAttribute.html b/docs/api/ar/core/InstancedBufferAttribute.html new file mode 100644 index 00000000000000..d5b36337370852 --- /dev/null +++ b/docs/api/ar/core/InstancedBufferAttribute.html @@ -0,0 +1,37 @@ + + + + + + + + + + [page:BufferAttribute] → + +

[name]

+

نسخة مثيلة من [page:BufferAttribute].

+ +

المنشئ (Constructor)

+

[name]( [param:TypedArray array], [param:Integer itemSize], [param:Boolean normalized], [param:Number meshPerAttribute] )

+ +

الخصائص (Properties)

+

انظر [page:BufferAttribute] للخصائص الموروثة.

+ +

[property:Number meshPerAttribute]

+

+ يحدد مدى تكرار قيمة هذه السمة المخزنة. قيمة واحدة تعني أن كل قيمة من + السمة المثيلة يتم استخدامها لمثيل واحد. قيمتان تعني أن كل قيمة يتم + استخدامها لمثيلين متتاليين (وهكذا). الافتراضي هو `1`. +

+ +

الوظائف (Methods)

+

انظر [page:BufferAttribute] للطُرق الموروثة.

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + + diff --git a/docs/api/ar/core/InstancedBufferGeometry.html b/docs/api/ar/core/InstancedBufferGeometry.html new file mode 100644 index 00000000000000..8049a661a3381e --- /dev/null +++ b/docs/api/ar/core/InstancedBufferGeometry.html @@ -0,0 +1,39 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+

نسخة مثيلة من [page:BufferGeometry].

+ +

المنشئ (Constructor)

+

[name]( )

+ +

الخصائص (Properties)

+

انظر [page:BufferGeometry] للخصائص الموروثة.

+ +

[property:Number instanceCount]

+

الافتراضي هو `Infinity`.

+ +

[property:Boolean isInstancedBufferGeometry]

+

علامة للقراءة فقط للتحقق مما إذا كان الكائن المعطى هو من نوع [name].

+ +

الوظائف (Methods)

+

انظر [page:BufferGeometry] للطُرق الموروثة.

+ +

[method:this copy]( [param:InstancedBufferGeometry source] )

+

ينسخ [name] المعطى إلى هذه الحالة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/InstancedInterleavedBuffer.html b/docs/api/ar/core/InstancedInterleavedBuffer.html new file mode 100644 index 00000000000000..5571c6313cef91 --- /dev/null +++ b/docs/api/ar/core/InstancedInterleavedBuffer.html @@ -0,0 +1,33 @@ + + + + + + + + + + [page:InterleavedBuffer] → + +

[name]

+

نسخة مثيلة من [page:InterleavedBuffer].

+ +

المنشئ (Constructor)

+

[name]( [param:TypedArray array], [param:Integer itemSize], [param:Number meshPerAttribute] )

+ +

الخصائص (Properties)

+

انظر [page:InterleavedBuffer] للخصائص الموروثة.

+ +

[property:Number meshPerAttribute]

+

الافتراضي هو `1`.

+ +

الوظائف (Methods)

+

انظر [page:InterleavedBuffer] للطُرق الموروثة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/InterleavedBuffer.html b/docs/api/ar/core/InterleavedBuffer.html new file mode 100644 index 00000000000000..46c830d018c46a --- /dev/null +++ b/docs/api/ar/core/InterleavedBuffer.html @@ -0,0 +1,119 @@ + + + + + + + + + +

[name]

+

+ "متداخل" يعني أن العديد من السمات، ربما من أنواع مختلفة، + (على سبيل المثال، الموضع، الطبيعي، uv، اللون) معبأة في مصفوفة واحدة. +

+ يمكن العثور على مقدمة في المصفوفات المتداخلة هنا: + [link:https://blog.tojicode.com/2011/05/interleaved-array-basics.html أساسيات المصفوفات المتداخلة] +

+ +

أمثلة (Examples)

+

+ [example:webgl_buffergeometry_points_interleaved webgl / buffergeometry / points / interleaved] +

+ +

المنشئ (Constructor)

+

[name]( [param:TypedArray array], [param:Integer stride] )

+

+ [page:TypedArray array] -- مصفوفة مكتوبة بذاكرة مشتركة. يخزن بيانات + الهندسة.
+ [page:Integer stride] -- عدد عناصر المصفوفة المكتوبة لكل رأس. +

+ +

الخصائص (Properties)

+ +

[property:Array array]

+

مصفوفة مكتوبة بذاكرة مشتركة. يخزن بيانات الهندسة.

+ +

[property:Integer stride]

+

عدد عناصر المصفوفة المكتوبة لكل رأس.

+ +

[property:Integer count]

+

يعطي إجمالي عدد العناصر في المصفوفة.

+ +

[property:Object updateRange]

+

+ كائن يحتوي على إزاحة وعدد.
+ - [page:Number offset]: الافتراضي هو `0`.
+ - [page:Number count]: الافتراضي هو `-1`.
+

+ +

[property:String uuid]

+

+ [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] من + هذه الحالة. يتم تعيين هذا تلقائيًا، لذلك لا يجب تحريره. +

+ +

[property:Integer version]

+

+ رقم إصدار، يزاد كل مرة يتم فيها تعيين خاصية needsUpdate على true. +

+ +

[property:Boolean needsUpdate]

+

+ الافتراضي هو `false`. تعيين هذا إلى true يزاد + [page:InterleavedBuffer.version version]. +

+ +

[property:Usage usage]

+

+ يحدد نمط الاستخدام المقصود لمخزن البيانات لأغراض التحسين. يتوافق مع + المعلمة `usage` من + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData](). +

+ +

الوظائف (Methods)

+ +

[method:this copy]( [param:InterleavedBuffer source] )

+

ينسخ [name] آخر إلى هذه [name].

+ +

[method:this copyAt]( [param:Integer index1], [param:InterleavedBuffer attribute], [param:Integer index2] )

+

+ ينسخ البيانات من `attribute[index2]` إلى [page:InterleavedBuffer.array array][index1]. +

+ +

[method:this set]( [param:TypedArray value], [param:Integer offset] )

+

+ value - المصفوفة (المكتوبة) المصدر.
+ offset - الإزاحة في المصفوفة الهدف التي يجب البدء فيها بكتابة القيم + من المصفوفة المصدر. الافتراضي هو `0`.

+ + يخزن قيمًا متعددة في المخزن، قراءة قيم الإدخال من + مصفوفة محددة. +

+ +

[method:InterleavedBuffer clone]( [param:Object data] )

+

+ data - يحمل هذا الكائن مصفوفات ذاكرة مشتركة مطلوبة لنسخ هندسات + بسمات متداخلة بشكل صحيح.

+ + ينشئ نسخة من هذه [name]. +

+ +

[method:this setUsage] ( [param:Usage value] )

+

ضبط [page:InterleavedBuffer.usage usage] على value.

+ +

[method:Object toJSON]( [param:Object data] )

+

+ data - يحمل هذا الكائن مصفوفات ذاكرة مشتركة مطلوبة لتسلسل هندسات + بسمات متداخلة بشكل صحيح.

+ + يسلسل هذه [name]. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/InterleavedBufferAttribute.html b/docs/api/ar/core/InterleavedBufferAttribute.html new file mode 100644 index 00000000000000..d976cb28deef21 --- /dev/null +++ b/docs/api/ar/core/InterleavedBufferAttribute.html @@ -0,0 +1,117 @@ + + + + + + + + + +

[name]

+ +

+ +

المنشئ (Constructor)

+

[name]( [param:InterleavedBuffer interleavedBuffer], [param:Integer itemSize], [param:Integer offset], [param:Boolean normalized] )

+ +

الخصائص (Properties)

+ +

[property:InterleavedBuffer data]

+

+ نسخة [page:InterleavedBuffer InterleavedBuffer] الممررة في + المُنشئ. +

+ +

[property:TypedArray array]

+

قيمة [page:InterleavedBufferAttribute.data data].array.

+ +

[property:Integer count]

+

+ قيمة [page:InterleavedBufferAttribute.data data].count. إذا كان + المخزن يخزن عنصرًا ثلاثي الأبعاد (مثل الموضع، الطبيعي، أو + اللون)، فسيحسب عدد هذه العناصر المخزنة. +

+ +

[property:Boolean isInterleavedBufferAttribute]

+

علامة للقراءة فقط للتحقق مما إذا كان الكائن المعطى هو من نوع [name].

+ +

[property:Integer itemSize]

+

كم عدد القيم التي تشكل كل عنصر.

+ +

[property:String name]

+

+ اسم اختياري لهذه الحالة من السمة. الافتراضي هو سلسلة فارغة. +

+ +

[property:Boolean needsUpdate]

+

+ الافتراضي هو `false`. تعيين هذا إلى `true` سيرسل المخزن المتداخل + بأكمله (وليس فقط بيانات السمة المحددة) إلى GPU مرة أخرى. +

+ +

[property:Boolean normalized]

+

الافتراضي هو `false`.

+ +

[property:Integer offset]

+

الإزاحة في المصفوفة الأساسية حيث يبدأ عنصر.

+ +

الوظائف (Methods)

+ +

[method:this applyMatrix4]( [param:Matrix4 m] )

+

+ يطبق مصفوفة [page:Matrix4 m] على كل عنصر Vector3 من هذه + InterleavedBufferAttribute. +

+ +

[method:this applyNormalMatrix]( [param:Matrix3 m] )

+

+ يطبق مصفوفة الطبيعي [page:Matrix3 m] على كل عنصر Vector3 من هذه + InterleavedBufferAttribute. +

+ +

[method:this transformDirection]( [param:Matrix4 m] )

+

+ يطبق مصفوفة [page:Matrix4 m] على كل عنصر Vector3 من هذه + InterleavedBufferAttribute، تفسير العناصر كمتجهات اتجاه. +

+ +

[method:Number getX]( [param:Integer index] )

+

يعيد مكون x للعنصر في المؤشر المعطى.

+ +

[method:Number getY]( [param:Integer index] )

+

يعيد مكون y للعنصر في المؤشر المعطى.

+ +

[method:Number getZ]( [param:Integer index] )

+

يعيد مكون z للعنصر في المؤشر المعطى.

+ +

[method:Number getW]( [param:Integer index] )

+

يعيد مكون w للعنصر في المؤشر المعطى.

+ +

[method:this setX]( [param:Integer index], [param:Float x] )

+

يضبط مكون x للعنصر في المؤشر المعطى.

+ +

[method:this setY]( [param:Integer index], [param:Float y] )

+

يضبط مكون y للعنصر في المؤشر المعطى.

+ +

[method:this setZ]( [param:Integer index], [param:Float z] )

+

يضبط مكون z للعنصر في المؤشر المعطى.

+ +

[method:this setW]( [param:Integer index], [param:Float w] )

+

يضبط مكون w للعنصر في المؤشر المعطى.

+ +

[method:this setXY]( [param:Integer index], [param:Float x], [param:Float y] )

+

يضبط مكونات x و y للعنصر في المؤشر المعطى.

+ +

[method:this setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] )

+

يضبط مكونات x و y و z للعنصر في المؤشر المعطى.

+ +

[method:this setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] )

+

يضبط مكونات x و y و z و w للعنصر في المؤشر المعطى.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/Layers.html b/docs/api/ar/core/Layers.html new file mode 100644 index 00000000000000..f221c65fcce206 --- /dev/null +++ b/docs/api/ar/core/Layers.html @@ -0,0 +1,100 @@ + + + + + + + + + +

[name]

+ +

+ كائن [page:Layers] يعين [page:Object3D] إلى 1 أو أكثر من 32 + طبقة مرقمة من `0` إلى `31` - يتم تخزين الطبقات داخليًا كـ + [link:https://en.wikipedia.org/wiki/Mask_(computing) قناع بت]، وافتراضيًا + كل Object3Ds عضو في الطبقة 0.

+ + يمكن استخدام هذا للتحكم في الرؤية - يجب أن يشترك كائن في طبقة مع + [page:Camera camera] ليكون مرئيًا عندما يتم عرض هذه الكاميرا + المعروضة.

+ + جميع الفئات التي ترث من [page:Object3D] لديها + [page:Object3D.layers] خاصية وهي نسخة من هذه الفئة. +

+ +

أمثلة (Examples)

+ +

[example:webgl_layers WebGL / layers]

+ +

المنشئ (Constructor)

+ +

[name]()

+

إنشاء كائن طبقات جديد، مع تعيين العضوية في البداية إلى الطبقة 0.

+ +

الخصائص (Properties)

+ +

[property:Integer mask]

+

+ قناع بت يخزن أي من الطبقات الـ 32 التي يكون هذا الكائن طبقات حاليًا + عضوًا فيه. +

+ +

الوظائف (Methods)

+ +

[method:undefined disable]( [param:Integer layer] )

+

+ layer - عدد صحيح من 0 إلى 31.

+ + إزالة عضوية هذه `layer`. +

+ +

[method:undefined enable]( [param:Integer layer] )

+

+ layer - عدد صحيح من 0 إلى 31.

+ + إضافة عضوية هذه `layer`. +

+ +

[method:undefined set]( [param:Integer layer] )

+

+ layer - عدد صحيح من 0 إلى 31.

+ + تعيين العضوية إلى `layer`، وإزالة العضوية من جميع الطبقات الأخرى. +

+ +

[method:Boolean test]( [param:Layers layers] )

+

+ layers - كائن طبقات

+ + يعود بـ true إذا كان هذا وكائن `layers` الممرر لديهما على الأقل واحدة + طبقة مشتركة. +

+ +

[method:Boolean isEnabled]( [param:Integer layer] )

+

+ layer - عدد صحيح من 0 إلى 31.

+ + يعود بـ true إذا تم تمكين الطبقة المعطاة. +

+ +

[method:undefined toggle]( [param:Integer layer] )

+

+ layer - عدد صحيح من 0 إلى 31.

+ + تبديل عضوية `layer`. +

+ +

[method:undefined enableAll]()

+

إضافة عضوية لجميع الطبقات.

+ +

[method:undefined disableAll]()

+

إزالة العضوية من جميع الطبقات.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/Object3D.html b/docs/api/ar/core/Object3D.html new file mode 100644 index 00000000000000..8b32b786cdd516 --- /dev/null +++ b/docs/api/ar/core/Object3D.html @@ -0,0 +1,570 @@ + + + + + + + + + +

[name]

+ +

+ هذه هي الفئة الأساسية لمعظم الكائنات في three.js وتوفر مجموعة من + الخصائص والطُرق للتلاعب بالكائنات في المساحة ثلاثية الأبعاد.

+ + لاحظ أن هذا يمكن استخدامه لتجميع الكائنات عبر طريقة [page:.add]( object ) التي تضيف الكائن كطفل، ومع ذلك فمن الأفضل + استخدام [page:Group] لهذا. +

+ +

المنشئ (Constructor)

+ +

[name]()

+

المُنشئ لا يأخذ أي وسائط.

+ +

الخصائص (Properties)

+ +

[property:AnimationClip animations]

+

مصفوفة بمقاطع الرسوم المتحركة للكائن.

+ +

[property:Boolean castShadow]

+

ما إذا كان يتم عرض الكائن في خريطة الظل. الافتراضي هو `false`.

+ +

[property:Array children]

+

+ مصفوفة بأطفال الكائن. انظر [page:Group] للحصول على معلومات حول + تجميع الكائنات يدويًا. +

+ +

[property:Material customDepthMaterial]

+

+ مادة عمق مخصصة للاستخدام عند التقديم إلى خريطة العمق. يمكن استخدامه فقط + في سياق المشابك. عند رمي الظل مع + [page:DirectionalLight] أو [page:SpotLight]، إذا كنت تعدل + مواضع رأس في شادر رأس يجب تحديد customDepthMaterial مخصص + لظلال صحيحة. الافتراضي هو `undefined`. +

+ +

[property:Material customDistanceMaterial]

+

+ نفس [page:.customDepthMaterial customDepthMaterial]، ولكن يستخدم مع + [page:PointLight]. الافتراضي هو `undefined`. +

+ +

[property:Boolean frustumCulled]

+

+ عند تعيين هذا، يتحقق في كل إطار ما إذا كان الكائن في مخروط + الكاميرا قبل تقديم الكائن. إذا تم تعيينه على `false` يتم تقديم الكائن + في كل إطار حتى لو لم يكن في مخروط الكاميرا. + الافتراضي هو `true`. +

+ +

[property:Integer id]

+

readonly – رقم فريد لهذه الحالة من الكائن.

+ +

[property:Boolean isObject3D]

+

علامة للقراءة فقط للتحقق مما إذا كان الكائن المعطى هو من نوع [name].

+ +

[property:Layers layers]

+

+ عضوية طبقة الكائن. الكائن مرئي فقط إذا كان لديه + على الأقل طبقة واحدة مشتركة مع [page:Camera] قيد الاستخدام. يمكن استخدام هذه الخاصية أيضًا لتصفية + كائنات غير مرغوب فيها في اختبارات التقاطع بالأشعة + عند استخدام [page:Raycaster]. +

+ +

[property:Matrix4 matrix]

+

مصفوفة التحول المحلية.

+ +

[property:Boolean matrixAutoUpdate]

+

+ عند تعيين هذا، يحسب مصفوفة الموضع، (الدوران أو + quaternion) والحجم في كل إطار وأيضًا يعيد حساب خصائص matrixWorld + . الافتراضي هو [page:Object3D.DEFAULT_MATRIX_AUTO_UPDATE] (true). +

+ +

[property:Matrix4 matrixWorld]

+

+ التحول العالمي للكائن. إذا لم يكن لدى Object3D أي والد، فإنه + مطابق للتحول المحلي [page:.matrix]. +

+ +

[property:Boolean matrixWorldAutoUpdate]

+

+ إذا تم تعيينه، فإن المقدم يتحقق في كل إطار ما إذا كان الكائن و + أطفاله يحتاجون إلى تحديثات المصفوفة. عندما لا يكون كذلك، فعليك الحفاظ على جميع + المصفوفات في الكائن وأطفاله بنفسك. الافتراضي هو + [page:Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE] (true). +

+ +

[property:Boolean matrixWorldNeedsUpdate]

+

+ عند تعيين هذا، يحسب matrixWorld في ذلك الإطار ويعيد + هذه الخاصية إلى false. الافتراضي هو `false`. +

+ +

[property:Matrix4 modelViewMatrix]

+

+ يتم تمرير هذا إلى الشادر ويستخدم لحساب موضع + الكائن. +

+ +

[property:String name]

+

+ اسم اختياري للكائن (لا يحتاج إلى أن يكون فريدًا). الافتراضي هو + سلسلة فارغة. +

+ +

[property:Matrix3 normalMatrix]

+

+ يتم تمرير هذا إلى الشادر ويستخدم لحساب الإضاءة لـ + الكائن. هو نقل معكوس من المصفوفة 3x3 العلوية اليسرى + من مصفوفة modelViewMatrix لهذا الكائن.

+ + سبب هذه المصفوفة الخاصة هو أن استخدام ببساطة + modelViewMatrix قد يؤدي إلى طول غير وحدة من normals (على التحجيم) + أو في اتجاه غير عمودي (على التحجيم غير الموحد).

+ + من ناحية أخرى، جزء الترجمة من modelViewMatrix غير + ذات صلة بحساب normals. وبالتالي فإن Matrix3 كافية. +

+ +

[property:Function onAfterRender]

+

+ رد اتصال اختياري يتم تنفيذه مباشرة بعد تقديم كائن ثلاثي الأبعاد + . يتم استدعاء هذه الوظيفة بالمعلمات التالية: renderer, + scene, camera, geometry, material, group. +

+

+ يرجى ملاحظة أن هذا الرد الاتصال يتم تنفيذه فقط لـ `renderable` 3D + كائنات. معنى كائنات ثلاثية الأبعاد التي تحدد مظهرها المرئي مع + الهندسة والمواد مثل نسخ [page:Mesh]، [page:Line]، + [page:Points] أو [page:Sprite]. نسخ من [page:Object3D]، [page:Group] + أو [page:Bone] ليست قابلة للتقديم وبالتالي لا يتم تنفيذ هذا الرد الاتصال + لمثل هذه الكائنات. +

+ +

[property:Function onBeforeRender]

+

+ رد اتصال اختياري يتم تنفيذه مباشرة قبل تقديم كائن ثلاثي الأبعاد + . يتم استدعاء هذه الوظيفة بالمعلمات التالية: renderer, + scene, camera, geometry, material, group. +

+

+ يرجى ملاحظة أن هذا الرد الاتصال يتم تنفيذه فقط لـ `renderable` 3D + كائنات. معنى كائنات ثلاثية الأبعاد التي تحدد مظهرها المرئي مع + الهندسة والمواد مثل نسخ [page:Mesh]، [page:Line]، + [page:Points] أو [page:Sprite]. نسخ من [page:Object3D]، [page:Group] + أو [page:Bone] ليست قابلة للتقديم وبالتالي لا يتم تنفيذ هذا الرد الاتصال + لمثل هذه الكائنات. +

+ +

[property:Object3D parent]

+

+ والد كائن في [link:https://en.wikipedia.org/wiki/Scene_graph scene graph]. يمكن أن يكون لكائن واحد على الأكثر واحد. +

+ +

[property:Vector3 position]

+

+ A [page:Vector3] يمثل الموضع المحلي للكائن. الافتراضي هو `(0, + 0, 0)`. +

+ +

[property:Quaternion quaternion]

+

دوران المحلية للكائن كـ [page:Quaternion Quaternion].

+ +

[property:Boolean receiveShadow]

+

ما إذا كان المادة تتلقى الظلال. الافتراضي هو `false`.

+ +

[property:Number renderOrder]

+

+ يسمح هذا القيمة بتجاوز ترتيب التصيير الافتراضي لـ + [link:https://en.wikipedia.org/wiki/Scene_graph scene graph] objects على الرغم من أن الأشياء المعتمة والشفافة لا تزال مرتبة + بشكل مستقل. عند تعيين هذه الخاصية لمثيل [page:Group Group]، سيتم فرز جميع الكائنات النسل وتقديمها معًا. + الترتيب من أدنى إلى أعلى renderOrder. القيمة الافتراضية هي `0`. +

+ +

[property:Euler rotation]

+

+ دوران المحلي للكائن (انظر + [link:https://en.wikipedia.org/wiki/Euler_angles Euler angles])، في + شعاع. +

+ +

[property:Vector3 scale]

+

مقياس المحلي للكائن. الافتراضي هو [page:Vector3]( 1, 1, 1 ).

+ +

[property:Vector3 up]

+

+ يستخدم هذا بواسطة [page:.lookAt lookAt] method، على سبيل المثال، إلى + تحديد توجه النتيجة.
+ الافتراضي هو [page:Object3D.DEFAULT_UP] - أي `( 0, 1, 0 )`. +

+ +

[property:Object userData]

+

+ كائن يمكن استخدامه لتخزين بيانات مخصصة حول Object3D. يجب ألا يحتوي على مراجع إلى وظائف كونها لن تكون مستنسخة. +

+ +

[property:String uuid]

+

+ [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] من + هذه المثيلة كائن. يتم تعيين هذا تلقائيًا، لذلك يجب عدم تحريره. +

+ +

[property:Boolean visible]

+

الكائن يحصل على التصيير إذا كان `true`. الافتراضي هو `true`.

+ +

الخصائص الثابتة (Static Properties)

+

+ يتم تعريف الخصائص والطرق الثابتة لكل فئة بدلاً من كل + مثيل لتلك الفئة. هذا يعني أن تغيير + [page:Object3D.DEFAULT_UP] أو [page:Object3D.DEFAULT_MATRIX_AUTO_UPDATE] + سيغير قيم [page:.up up] و [page:.matrixAutoUpdate matrixAutoUpdate] لـ `كل` مثيل من Object3D (أو الفئات المشتقة) + تم إنشاؤه بعد إجراء التغيير (لن يتأثر Object3Ds المنشأ بالفعل). +

+ +

[property:Vector3 DEFAULT_UP]

+

+ اتجاه [page:.up up] الافتراضي للكائنات، يستخدم أيضًا كموقع افتراضي + لـ [page:DirectionalLight]، [page:HemisphereLight] و + [page:Spotlight] (الذي يخلق أضواء تشرق من الأعلى إلى الأسفل).
+ مضبوط على ( 0, 1, 0 ) بشكل افتراضي. +

+ +

[property:Boolean DEFAULT_MATRIX_AUTO_UPDATE]

+

+ العدد الافتراضي لـ [page:.matrixAutoUpdate matrixAutoUpdate] لـ + Object3Ds المنشأة حديثًا.
+

+ +

[property:Boolean DEFAULT_MATRIX_WORLD_AUTO_UPDATE]

+

+ العدد الافتراضي لـ [page:.matrixWorldAutoUpdate + matrixWorldAutoUpdate] لـ Object3Ds المنشأة حديثًا.
+

+ +

الوظائف (Methods)

+ +

+ طرق [page:EventDispatcher EventDispatcher] متاحة على هذه + فئة. +

+ +

[method:this add]( [param:Object3D object], ... )

+

+ يضيف `object` كطفل لهذا الكائن. يمكن إضافة عدد غير محدود من الكائنات. سيتم إزالة أي والد حالي على كائن ممرر هنا، نظرًا لأنه يمكن أن يكون للكائن والد واحد على الأكثر.

+ + راجع [page:Group] للحصول على معلومات حول تجميع الكائنات يدويًا. +

+ +

[method:undefined applyMatrix4]( [param:Matrix4 matrix] )

+

+ يطبق تحويل المصفوفة على الكائن ويحدث موقع الكائن ودورانه ومقياسه. +

+ +

[method:this applyQuaternion]( [param:Quaternion quaternion] )

+

يطبق الدوران الممثل بالرباعي على الكائن.

+ +

[method:this attach]( [param:Object3D object] )

+

+ يضيف `object` كطفل لهذا، مع الحفاظ على تحويل العالم للكائن. +

+ ملاحظة: هذه الطريقة لا تدعم رسومات المشهد التي تحتوي على + نقاط غير متساوية في الحجم (s). +

+ +

[method:Object3D clone]( [param:Boolean recursive] )

+

+ recursive -- إذا كان صحيحًا، فإن نسل الكائن يتم استنساخه أيضًا. الافتراضي + صحيح.

+ + يعود بنسخة من هذا الكائن واختياريًا جميع النسل. +

+ +

[method:this copy]( [param:Object3D object], [param:Boolean recursive] )

+

+ recursive -- إذا كان صحيحًا، فإن نسل الكائن يتم نسخه أيضًا. الافتراضي + صحيح.

+ + نسخ الكائن المعطى في هذا الكائن. ملاحظة: لا يتم نسخ مستمعو الأحداث و + التعليمات البرمجية المعرفة من قبل المستخدم ([page:.onAfterRender] و [page:.onBeforeRender]). +

+ +

[method:Object3D getObjectById]( [param:Integer id] )

+

+ id -- رقم فريد لمثيل الكائن

+ + يبحث في كائن وأطفاله، بدءًا من الكائن + نفسه، ويرجع أول مطابقة مع id.
+ لاحظ أنه يتم تعيين المعرفات بالترتيب التاريخي: 1، 2، 3، ...، + زيادة بواحد لكل كائن جديد. +

+ +

[method:Object3D getObjectByName]( [param:String name] )

+

+ name -- سلسلة للمطابقة مع خصائص Object3D.name للأطفال. +

+ + يبحث في كائن وأطفاله، بدءًا من الكائن + نفسه، ويرجع أول مطابقة مع اسم.
+ لاحظ أنه بالنسبة لمعظم الكائنات، يكون الاسم سلسلة فارغة بشكل افتراضي. سوف + ستضطر إلى تعيينه يدويًا للاستفادة من هذه الطريقة. +

+ +

[method:Object3D getObjectByProperty]( [param:String name], [param:Any value] )

+

+ name -- اسم الخاصية التي يتم البحث عنها.
+ value -- قيمة الخاصية المعطاة.

+ + يبحث في كائن وأطفاله، بدءًا من الكائن + نفسه، ويرجع أول مع خاصية تطابق القيمة + معطى. +

+ +

[method:Object3D getObjectsByProperty]( [param:String name], [param:Any value] )

+

+ name -- اسم الخاصية التي يتم البحث عنها.
+ value -- قيمة الخاصية المعطاة.

+ + يبحث في كائن وأطفاله، بدءًا من الكائن + نفسه، ويرجع جميع الكائنات مع خاصية تطابق القيمة + معطى. +

+ +

[method:Vector3 getWorldPosition]( [param:Vector3 target] )

+

+ [page:Vector3 target] — سيتم نسخ النتيجة في هذا Vector3. +

+ + يعود بمتجه يمثل موقع الكائن في الفضاء العالمي. +

+ +

[method:Quaternion getWorldQuaternion]( [param:Quaternion target] )

+

+ [page:Quaternion target] — سيتم نسخ النتيجة في هذا Quaternion. +

+ + يعود برباعي يمثل دوران الكائن في الفضاء العالمي. +

+ +

[method:Vector3 getWorldScale]( [param:Vector3 target] )

+

+ [page:Vector3 target] — سيتم نسخ النتيجة في هذا Vector3. +

+ + يعود بمتجه من عوامل التحجيم المطبقة على الكائن لكل + محور في الفضاء العالمي. +

+ +

[method:Vector3 getWorldDirection]( [param:Vector3 target] )

+

+ [page:Vector3 target] — سيتم نسخ النتيجة في هذا Vector3. +

+ + يعود بمتجه يمثل اتجاه محور z الموجب للكائن في + الفضاء العالمي. +

+ +

[method:Vector3 localToWorld]( [param:Vector3 vector] )

+

+ vector - متجه يمثل موقعًا في هذا المساحة المحلية للكائن.

+ + يحول المتجه من مساحة هذا الكائن المحلية إلى الفضاء العالمي. +

+ +

[method:undefined lookAt]( [param:Vector3 vector] )
+ [method:undefined lookAt]( [param:Float x], [param:Float y], [param:Float z] ) +

+

+ vector - متجه يمثل موقعًا في الفضاء العالمي.

+ اختياريًا، [page:.x x]، [page:.y y] و [page:.z z] مكونات من + موقع الفضاء العالمي.

+ + يدور الكائن لمواجهة نقطة في الفضاء العالمي.

+ + هذه الطريقة لا تدعم كائنات تحتوي على + والد (والدين) غير متساوي (ين) في الحجم. +

+ +

[method:undefined raycast]( [param:Raycaster raycaster], [param:Array intersects] )

+

+ طريقة فارغة (فارغة) للحصول على تقاطعات بين شعاع صب وهذا + كائن. تطبق فئات فرعية مثل [page:Mesh]، [page:Line]، و [page:Points] + هذه الطريقة من أجل استخدام التصوير بالأشعة. +

+ +

[method:this remove]( [param:Object3D object], ... )

+

+ يزيل `object` كطفل لهذا الكائن. يمكن إزالة عدد غير محدود من الكائنات + قد تم إزالته. +

+ +

[method:this removeFromParent]()

+

يزيل هذا الكائن من والده الحالي.

+ +

[method:this clear]()

+

يزيل جميع كائنات الأطفال.

+ +

[method:this rotateOnAxis]( [param:Vector3 axis], [param:Float angle] )

+

+ axis -- متجه معتدل في المساحة المحلية.
+ angle -- الزاوية بالراديان.

+ + قم بتدوير كائن على طول محور في المساحة المحلية. يفترض أن يكون المحور + معتدل. +

+ +

[method:this rotateOnWorldAxis]( [param:Vector3 axis], [param:Float angle])

+

+ axis -- متجه معتدل في المساحة العالمية.
+ angle -- الزاوية بالراديان.

+ + قم بتدوير كائن على طول محور في المساحة العالمية. يفترض أن يكون المحور + معتدل. تفترض طريقة عدم وجود والد دوران. +

+ +

[method:this rotateX]( [param:Float rad] )

+

+ rad - الزاوية للتدوير بالراديان.

+ + يدور الكائن حول محور x في المساحة المحلية. +

+ +

[method:this rotateY]( [param:Float rad] )

+

+ rad - الزاوية للتدوير بالراديان.

+ + يدور الكائن حول محور y في المساحة المحلية. +

+ +

[method:this rotateZ]( [param:Float rad] )

+

+ rad - الزاوية للتدوير بالراديان.

+ + يدور الكائن حول محور z في المساحة المحلية. +

+ +

[method:undefined setRotationFromAxisAngle]( [param:Vector3 axis], [param:Float angle] )

+

+ axis -- متجه معتدل في المساحة المحلية.
+ angle -- زاوية بالراديان

+ + يستدعي [page:Quaternion.setFromAxisAngle setFromAxisAngle]( [page:Float axis], [page:Float angle] ) على [page:.quaternion]. +

+ +

[method:undefined setRotationFromEuler]( [param:Euler euler] )

+

+ euler -- زاوية أويلر تحدد كمية الدوران.
+ + يستدعي [page:Quaternion.setRotationFromEuler setRotationFromEuler]( + [page:Euler euler]) على [page:.quaternion]. +

+ +

[method:undefined setRotationFromMatrix]( [param:Matrix4 m] )

+

+ m -- قم بتدوير الرباعي بمكون الدوران من المصفوفة.
+ + يستدعي [page:Quaternion.setFromRotationMatrix setFromRotationMatrix]( + [page:Matrix4 m]) على [page:.quaternion].

+ + لاحظ أن هذا يفترض أن الـ 3x3 العلوي من m هو مصفوفة دوران نقية + (أي غير مقاس). +

+ +

[method:undefined setRotationFromQuaternion]( [param:Quaternion q] )

+

+ q -- رباعي معتدل.

+ + نسخ الرباعي المعطى في [page:.quaternion]. +

+ +

[method:Object toJSON]( [param:Object meta] )

+

+ meta -- كائن يحتوي على بيانات تعريفية مثل المواد أو القوام أو الصور + للكائن.
+ قم بتحويل الكائن إلى three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. +

+ +

[method:this translateOnAxis]( [param:Vector3 axis], [param:Float distance] )

+

+ axis -- متجه معتدل في المساحة المحلية.
+ distance -- المسافة التي يتم ترجمتها.

+ + قم بترجمة كائن بمسافة على طول محور في المساحة المحلية. يفترض أن يكون المحور + معتدل. +

+ +

[method:this translateX]( [param:Float distance] )

+

يترجم الكائن على طول محور x في المساحة المحلية بوحدات `distance`.

+ +

[method:this translateY]( [param:Float distance] )

+

يترجم الكائن على طول محور y في المساحة المحلية بوحدات `distance`.

+ +

[method:this translateZ]( [param:Float distance] )

+

يترجم الكائن على طول محور z في المساحة المحلية بوحدات `distance`.

+ +

[method:undefined traverse]( [param:Function callback] )

+

+ callback - وظيفة مع كأول وسيطة كائن object3D.

+ + ينفذ رد الاتصال على هذا الكائن وجميع النسل.
+ ملاحظة: يُفضل عدم تعديل رسم المشهد داخل رد الاتصال. +

+ +

[method:undefined traverseVisible]( [param:Function callback] )

+

+ callback - وظيفة مع كأول وسيطة كائن object3D.

+ + مثل traverse، ولكن سيتم تنفيذ رد الاتصال فقط للكائنات المرئية. + لا يتم اجتياز نسل الكائنات غير المرئية.
+ ملاحظة: يُفضل عدم تعديل رسم المشهد داخل رد الاتصال. +

+ +

[method:undefined traverseAncestors]( [param:Function callback] )

+

+ callback - وظيفة مع كأول وسيطة كائن object3D.

+ + ينفذ رد الاتصال على جميع الأجداد.
+ ملاحظة: يُفضل عدم تعديل رسم المشهد داخل رد الاتصال. +

+ +

[method:undefined updateMatrix]()

+

يحدث التحويل المحلي.

+ +

[method:undefined updateMatrixWorld]( [param:Boolean force] )

+

+ force - منطقي يمكن استخدامه لتجاوز + [page:.matrixWorldAutoUpdate]، لإعادة حساب مصفوفة العالم لـ + الكائن والنسل في الإطار الحالي. مفيد إذا لم تتمكن من الانتظار + المصور لتحديثه في الإطار التالي (باستخدام + [page:.matrixWorldAutoUpdate] مضبوط على `true`).

+ + يحدث التحويل العالمي للكائن ونسله إذا كان + تحتاج مصفوفة العالم إلى تحديث ([page:.matrixWorldNeedsUpdate] مضبوط على true) أو + إذا تم تعيين معلمة `force` على `true`. +

+ +

[method:undefined updateWorldMatrix]( [param:Boolean updateParents], [param:Boolean updateChildren] )

+

+ updateParents - يحدث تحويل العالم للأجداد بشكل متكرر.
+ updateChildren - يحدث تحويل العالم للنسل بشكل متكرر.

+ + يحدث التحويل العالمي للكائن. +

+ +

[method:Vector3 worldToLocal]( [param:Vector3 vector] )

+

+ vector - متجه يمثل موقعًا في الفضاء العالمي.

+ + يحول المتجه من المساحة العالمية إلى المساحة المحلية لهذا الكائن. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/Raycaster.html b/docs/api/ar/core/Raycaster.html new file mode 100644 index 00000000000000..fac2fc314386b9 --- /dev/null +++ b/docs/api/ar/core/Raycaster.html @@ -0,0 +1,230 @@ + + + + + + + + + +

[name]

+ +

+ تم تصميم هذه الفئة للمساعدة في + [link:https://en.wikipedia.org/wiki/Ray_casting raycasting]. يتم استخدام Raycasting + لاختيار الماوس (العمل على معرفة الكائنات في المساحة ثلاثية الأبعاد التي يكون عليها الماوس + فوق) من بين أشياء أخرى. +

+ +

مثال الكود

+ + const raycaster = new THREE.Raycaster(); + const pointer = new THREE.Vector2(); + + function onPointerMove( event ) { + + // حساب موضع المؤشر في إحداثيات الجهاز المعتدلة + // (-1 إلى +1) لكلا المكونين + + pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1; + pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + + } + + function render() { + + // تحديث شعاع التقاط مع الكاميرا وموضع المؤشر + raycaster.setFromCamera( pointer, camera ); + + // حساب الكائنات المتقاطعة مع شعاع التقاط + const intersects = raycaster.intersectObjects( scene.children ); + + for ( let i = 0; i < intersects.length; i ++ ) { + + intersects[ i ].object.material.color.set( 0xff0000 ); + + } + + renderer.render( scene, camera ); + + } + + window.addEventListener( 'pointermove', onPointerMove ); + + window.requestAnimationFrame(render); + + + +

أمثلة (Examples)

+ +

+ [example:webgl_interactive_cubes Raycasting to a Mesh]
+ [example:webgl_interactive_cubes_ortho Raycasting to a Mesh in using an OrthographicCamera]
+ [example:webgl_interactive_buffergeometry Raycasting to a Mesh with BufferGeometry]
+ [example:webgl_instancing_raycast Raycasting to a InstancedMesh]
+ [example:webgl_interactive_lines Raycasting to a Line]
+ [example:webgl_interactive_raycasting_points Raycasting to Points]
+ [example:webgl_geometry_terrain_raycast Terrain raycasting]
+ [example:webgl_interactive_voxelpainter Raycasting to paint voxels]
+ [example:webgl_raycaster_texture Raycast to a Texture] +

+ +

المنشئ (Constructor)

+ +

[name]( [param:Vector3 origin], [param:Vector3 direction], [param:Float near], [param:Float far] )

+

+ [page:Vector3 origin] — متجه المنشأ الذي يلقي منه الشعاع.
+ [page:Vector3 direction] — متجه الاتجاه الذي يعطي اتجاهًا + للشعاع. يجب تعديله.
+ [page:Float near] — جميع النتائج المرتجعة أبعد من قريب. قريب + لا يمكن أن يكون سلبيًا. القيمة الافتراضية هي 0.
+ [page:Float far] — جميع النتائج المرتجعة أقرب من بعيد. بعيد لا يمكن + أقل من قريب. القيمة الافتراضية هي Infinity. +

+

هذا يخلق كائن raycaster جديد.

+ +

الخصائص (Properties)

+ +

[property:Float far]

+

+ عامل بعيد للraycaster. هذه القيمة تشير إلى الكائنات التي يمكن + تجاهلها بناءً على المسافة. هذه القيمة لا يجب أن تكون سلبية و + يجب أن تكون أكبر من خاصية قريب. +

+ +

[property:Float near]

+

+ عامل قريب للraycaster. هذه القيمة تشير إلى الكائنات التي يمكن + تجاهلها بناءً على المسافة. هذه القيمة لا يجب أن تكون سلبية و + يجب أن تكون أصغر من خاصية بعيد. +

+ +

[property:Camera camera]

+

+ الكاميرا المستخدمة عند التصوير بالأشعة ضد كائنات تعتمد على المشهد مثل + كائنات billboarded مثل [page:Sprites]. يمكن تعيين هذا الحقل يدويًا أو + يتم تعيينه عند استدعاء "setFromCamera". افتراضات إلى null. +

+ +

[property:Layers layers]

+

+ يستخدم من قبل [name] لتجاهل كائنات 3D بشكل اختياري عند إجراء + اختبارات التقاطع. يضمن المثال التالي للكود أن كائنات 3D فقط على طبقة `1` ستحظى باحترام من قِبَل المثيل من [name]. + + + raycaster.layers.set( 1 ); + object.layers.enable( 1 ); + +

+ +

[property:Object params]

+

+ كائن به الخصائص التالية: + + + { + Mesh: {}, + Line: { threshold: 1 }, + LOD: {}, + Points: { threshold: 1 }, + Sprite: {} + } + + + حيث threshold هو دقة raycaster عند التقاط + كائنات، في وحدات العالم. +

+ +

[property:Ray ray]

+

ال[Page:Ray] المستخدم للتصوير بالأشعة.

+ +

الوظائف (Methods)

+ +

[method:undefined set]( [param:Vector3 origin], [param:Vector3 direction])

+

+ [page:Vector3 origin] — متجه المنشأ الذي يلقي منه الشعاع.
+ [page:Vector3 direction] — متجه الاتجاه المعتدل الذي يعطي + اتجاه للشعاع. +

+

+ يحدث الشعاع بمنشأ واتجاه جديد. يرجى ملاحظة أن هذا + الطريقة تنسخ فقط القيم من الوسائط. +

+ +

[method:undefined setFromCamera]( [param:Vector2 coords], [param:Camera camera] )

+

+ [page:Vector2 coords] — إحداثيات 2D للماوس، في تعديل جهاز + إحداثيات (NDC) --- يجب أن تكون مكونات X و Y بين -1 و 1.
+ [page:Camera camera] — الكاميرا التي يجب أن ينبثق منها الشعاع +

+

يحدث الشعاع بمنشأ واتجاه جديد.

+ +

[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )

+

+ [page:Object3D object] — الكائن للتحقق من التقاطع مع + شعاع.
+ [page:Boolean recursive] — إذا كان صحيحًا، فإنه يتحقق أيضًا من جميع الأجداد. + وإلا فإنه يتحقق فقط من التقاطع مع الكائن. الافتراضي صحيح.
+ [page:Array optionalTarget] — (اختياري) هدف لتعيين النتيجة. + وإلا تم تجسيد جديد لـ [page:Array]. إذا تم تعيينه، يجب عليك مسح هذا + array قبل كل استدعاء (أي ، array.length = 0;). +

+

+ يتحقق من جميع التقاطع بين الشعاع والكائن مع أو بدون + نسل. يتم إرجاع التقاطعات مرتبة حسب المسافة، أولًا أولًا. + يتم إرجاع مصفوفة من التقاطعات ... +

+ [ { distance, point, face, faceIndex, object }, ... ] +

+ [page:Float distance] – المسافة بين مصدر الشعاع و + التقاطع
+ [page:Vector3 point] – نقطة التقاطع، في إحداثيات العالم
+ [page:Object face] – وجه التقاطع
+ [page:Integer faceIndex] – فهرس الوجه المتقاطع
+ [page:Object3D object] – الكائن المتقاطع
+ [page:Vector2 uv] - إحداثيات U,V في نقطة التقاطع
+ [page:Vector2 uv1] - مجموعة ثانية من إحداثيات U,V في نقطة + التقاطع
+ [page:Vector3 normal] - متجه عادي متداخل في نقطة + التقاطع
+ [page:Integer instanceId] – رقم فهرس الحالة حيث يتقاطع الشعاع + يتقاطع InstancedMesh +

+

+ `Raycaster` يفوض إلى [page:Object3D.raycast raycast] طريقة + كائن مار، عند تقييم ما إذا كان الشعاع يتقاطع مع الكائن أم لا + ليس. هذا يسمح لـ [page:Mesh meshes] بالرد بشكل مختلف على تصوير الأشعة + من [page:Line lines] و [page:Points pointclouds]. +

+

+ *ملاحظة* أنه بالنسبة للشبكات، يجب أن تكون الوجوه موجهة نحو مصدر + [page:.ray ray] من أجل اكتشافها؛ تقاطعات الشعاع المارة + من خلال الجزء الخلفي من وجه لن يتم اكتشافه. للتصوير بالأشعة ضد كلا + وجوه كائن، سترغب في تعيين خصائص [page:Mesh.material material] + [page:Material.side side] إلى `THREE.DoubleSide`. +

+ +

[method:Array intersectObjects]( [param:Array objects], [param:Boolean recursive], [param:Array optionalTarget] )

+

+ [page:Array objects] — الكائنات للتحقق من التقاطع مع + شعاع.
+ [page:Boolean recursive] — إذا كان صحيحًا، فإنه يتحقق أيضًا من جميع نسل + كائنات. وإلا فإنه يتحقق فقط من التقاطع مع الكائنات. افتراضي + صحيح.
+ [page:Array optionalTarget] — (اختياري) هدف لتعيين النتيجة. + وإلا تم تجسيد جديد لـ [page:Array]. إذا تم تعيينه، يجب عليك مسح هذا + array قبل كل استدعاء (أي ، array.length = 0;). +

+

+ يتحقق من جميع التقاطع بين الشعاع والكائنات مع أو بدون + نسل. يتم إرجاع التقاطعات مرتبة حسب المسافة، أولًا أولًا. التقاطات هي من نفس الشكل كما تلك المرتجعة بواسطة + [page:.intersectObject]. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/Uniform.html b/docs/api/ar/core/Uniform.html new file mode 100644 index 00000000000000..9fed55636e93a1 --- /dev/null +++ b/docs/api/ar/core/Uniform.html @@ -0,0 +1,274 @@ + + + + + + + + + +

[name]

+ +

+ الموحدات هي متغيرات GLSL عالمية. يتم تمريرها إلى برامج الشادر. +

+ +

مثال الكود

+

+ عند إعلان موحد من [page:ShaderMaterial]، يتم إعلانه بواسطة + القيمة أو بالكائن. +

+ + uniforms: { + time: { value: 1.0 }, + resolution: new Uniform( new Vector2() ) + }; + + +

أنواع الموحدات (Uniform types)

+

+ يجب أن يكون لكل موحد خاصية `value`. يجب أن يتوافق نوع القيمة + مع نوع المتغير الموحد في كود GLSL كما + محدد لأنواع GLSL البدائية في الجدول أدناه. موحد + الهياكل والمصفوفات مدعومة أيضًا. يجب تحديد مصفوفات GLSL من نوع بدائي + إما كمصفوفة من كائنات THREE المقابلة أو + كمصفوفة مسطحة تحتوي على بيانات جميع الكائنات. بعبارة أخرى؛ + يجب عدم تمثيل المتغيرات البدائية في GLSL في المصفوفات بواسطة المصفوفات. هذه القاعدة + لا تطبق ترانزيتيفًا. يجب أن تكون مصفوفة من مصفوفات `vec2`، كل منها بطول + خمسة متجهات، يجب أن تكون مصفوفة من المصفوفات، من خمسة [page:Vector2] + كائنات أو عشرة `number`s. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Uniform types +
GLSL typeJavaScript type
int[page:Number]
uint (WebGL 2)[page:Number]
float[page:Number]
bool[page:Boolean]
bool[page:Number]
vec2[page:Vector2 THREE.Vector2]
vec2[page:Float32Array Float32Array] (*)
vec2[page:Array Array] (*)
vec3[page:Vector3 THREE.Vector3]
vec3[page:Color THREE.Color]
vec3[page:Float32Array Float32Array] (*)
vec3[page:Array Array] (*)
vec4[page:Vector4 THREE.Vector4]
vec4[page:Quaternion THREE.Quaternion]
vec4[page:Float32Array Float32Array] (*)
vec4[page:Array Array] (*)
mat2[page:Float32Array Float32Array] (*)
mat2[page:Array Array] (*)
mat3[page:Matrix3 THREE.Matrix3]
mat3[page:Float32Array Float32Array] (*)
mat3[page:Array Array] (*)
mat4[page:Matrix4 THREE.Matrix4]
mat4[page:Float32Array Float32Array] (*)
mat4[page:Array Array] (*)
ivec2, bvec2[page:Float32Array Float32Array] (*)
ivec2, bvec2[page:Array Array] (*)
ivec3, bvec3[page:Int32Array Int32Array] (*)
ivec3, bvec3[page:Array Array] (*)
ivec4, bvec4[page:Int32Array Int32Array] (*)
ivec4, bvec4[page:Array Array] (*)
sampler2D[page:Texture THREE.Texture]
samplerCube[page:CubeTexture THREE.CubeTexture]
+ +

+ (*) نفس الشيء بالنسبة لمصفوفة (الأبعاد الداخلية) من نفس نوع GLSL، + تحتوي على مكونات جميع المتجهات أو المصفوفات في المصفوفة. +

+ +

الزي المنظم (Structured Uniforms)

+ +

+ في بعض الأحيان ترغب في تنظيم الزي كـ `structs` في كود الشيدر الخاص بك. + يجب استخدام النمط التالي حتى يتمكن `three.js` من معالجة + بيانات الزي المنظمة. +

+ + uniforms = { + data: { + value: { + position: new Vector3(), + direction: new Vector3( 0, 0, 1 ) + } + } + }; + + يمكن تعيين هذا التعريف على كود GLSL التالي: + + struct Data { + vec3 position; + vec3 direction; + }; + uniform Data data; + + +

الزي المنظم مع المصفوفات (Structured Uniforms with Arrays)

+ +

+ من الممكن أيضًا إدارة `structs` في المصفوفات. تبدو صياغة هذه الحالة + الاستخدام كما يلي: +

+ + const entry1 = { + position: new Vector3(), + direction: new Vector3( 0, 0, 1 ) + }; + const entry2 = { + position: new Vector3( 1, 1, 1 ), + direction: new Vector3( 0, 1, 0 ) + }; + + uniforms = { + data: { + value: [ entry1, entry2 ] + } + }; + + يمكن تعيين هذا التعريف على كود GLSL التالي: + + struct Data { + vec3 position; + vec3 direction; + }; + uniform Data data[ 2 ]; + + +

المنشئ (Constructor)

+ +

[name]( [param:Object value] )

+

+ value -- كائن يحتوي على القيمة لإعداد الزى. يجب أن يكون نوعه + واحدًا من أنواع الزى المذكورة أعلاه. +

+ +

الخصائص (Properties)

+ +

[property:Object value]

+

القيمة الحالية للزى.

+ +

الوظائف (Methods)

+ +

[method:Uniform clone]()

+

+ يعود بنسخة من هذا الزى.
+ إذا كانت خاصية قيمة الزى هى [page:Object] مع طريقة clone()، + يتم استخدام هذا، وإلا يتم نسخ القيمة عن طريق التعيين. تتشارك قيم المصفوفات بين [page:Uniform]s المنسوخة. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/core/bufferAttributeTypes/BufferAttributeTypes.html b/docs/api/ar/core/bufferAttributeTypes/BufferAttributeTypes.html new file mode 100644 index 00000000000000..5dd15b69668050 --- /dev/null +++ b/docs/api/ar/core/bufferAttributeTypes/BufferAttributeTypes.html @@ -0,0 +1,61 @@ + + + + + + + + + + [page:BufferAttribute] → + +

BufferAttribute Types

+ +

+ تتوفر في three.js تسعة أنواع من [page:BufferAttribute]. + تتوافق هذه الموجودات مع [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#Syntax Typed Arrays] في JavaScript. +

+ + + THREE.Float64BufferAttribute + THREE.Float32BufferAttribute + THREE.Float16BufferAttribute + THREE.Uint32BufferAttribute + THREE.Int32BufferAttribute + THREE.Uint16BufferAttribute + THREE.Int16BufferAttribute + THREE.Uint8ClampedBufferAttribute + THREE.Uint8BufferAttribute + THREE.Int8BufferAttribute + + +

المنشئ (Constructor)

+ +

يتم استدعاء كل من الأعلاف بنفس الطريقة.

+ +

+ TypedBufferAttribute( [param:Array_or_Integer array], [param:Integer itemSize], [param:Boolean normalized] ) +

+

+ array -- يمكن أن يكون هذا مصفوفة مكتوبة أو غير مكتوبة، أو طول الصحيح. سيتم تحويل قيمة المصفوفة إلى النوع المحدد. إذا تم توفير طول، فسيتم إنشاء TypedArray جديد، والذي سيتم تهيئته بجميع العناصر بقيم صفر.

+ + itemSize -- عدد القيم التي يجب أن ترتبط بنقطة فريدة.

+ + normalized -- (اختياري) يشير إلى كيفية تطابق البيانات الأساسية في الذاكرة المؤقتة مع القيم الموجودة في رمز GLSL. +

+ +

الخصائص (Properties)

+ +

انظر صفحة [page:BufferAttribute] للخصائص الموروثة.

+ +

الوظائف (Methods)

+ +

انظر صفحة [page:BufferAttribute] للأساليب الموروثة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/core/BufferAttribute.js src/core/BufferAttribute.js] +

+ + diff --git a/docs/api/ar/extras/DataUtils.html b/docs/api/ar/extras/DataUtils.html new file mode 100644 index 00000000000000..94f5b4c19b81b8 --- /dev/null +++ b/docs/api/ar/extras/DataUtils.html @@ -0,0 +1,36 @@ + + + + + + + + + +

[name]

+ +

فئة تحتوي على دوال مساعدة للبيانات.

+ +

الوظائف (Methods)

+ +

[method:Number toHalfFloat]( [param:Number val] )

+

+ val -- قيمة عائمة بدقة مفردة.

+ + يعود بقيمة عائمة نصف الدقة من القيمة العائمة بدقة مفردة المعطاة. +

+ +

[method:Number fromHalfFloat]( [param:Number val] )

+

+ val -- قيمة عائمة نصف الدقة.

+ + يعود بقيمة عائمة بدقة مفردة من القيمة العائمة نصف الدقة المعطاة. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/Earcut.html b/docs/api/ar/extras/Earcut.html new file mode 100644 index 00000000000000..b95ec1b4bf2c32 --- /dev/null +++ b/docs/api/ar/extras/Earcut.html @@ -0,0 +1,33 @@ + + + + + + + + + +

[name]

+ +

+ تنفيذ لخوارزمية تثليث المضلع earcut. الكود هو نقل من [link:https://github.com/mapbox/earcut mapbox/earcut]. +

+ +

الوظائف (Methods)

+ +

[method:Array triangulate]( data, holeIndices, dim )

+

+ data -- مصفوفة مسطحة من إحداثيات الرأس.
+ holeIndices -- مصفوفة من فهارس الثقوب إن وجدت.
+ dim -- عدد الإحداثيات لكل رأس في المصفوفة الإدخال.

+ + يثلث التعريف الشكل المعطى عن طريق إرجاع مصفوفة من المثلثات. يتم تعريف المثلث بثلاثة أعداد صحيحة متتالية تمثل فهارس الرأس. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/ImageUtils.html b/docs/api/ar/extras/ImageUtils.html new file mode 100644 index 00000000000000..3c11c74627bcb3 --- /dev/null +++ b/docs/api/ar/extras/ImageUtils.html @@ -0,0 +1,42 @@ + + + + + + + + + +

[name]

+ +

فئة تحتوي على دوال مساعدة للصور.

+ +

الوظائف (Methods)

+ +

+ [method:String getDataURL]( [param:HTMLCanvasElement image] | + [param:HTMLImageElement image] | [param:ImageBitmap image] ) +

+

+ image -- كائن الصورة.

+ + يعود بـ URI بيانات يحتوي على تمثيل للصورة المعطاة. +

+ +

+ [method:Object sRGBToLinear]( [param:HTMLCanvasElement image] | + [param:HTMLImageElement image] | [param:ImageBitmap image] ) +

+

+ image -- كائن الصورة.

+ + يحول بيانات الصورة sRGB المعطاة إلى مساحة اللون الخطية. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/PMREMGenerator.html b/docs/api/ar/extras/PMREMGenerator.html new file mode 100644 index 00000000000000..1be5d31fd919cb --- /dev/null +++ b/docs/api/ar/extras/PMREMGenerator.html @@ -0,0 +1,111 @@ + + + + + + + + + +

[name]

+ +

+ تولد هذه الفئة خريطة بيئة إشعاعية محددة مسبقًا ومتدرجة (PMREM) من نسيج بيئة cubeMap. يسمح هذا بالوصول السريع إلى مستويات مختلفة من التشويش بناءً على خشونة المادة. على عكس سلسلة mipmap التقليدية ، فإنها تنخفض فقط إلى مستوى LOD_MIN (أعلاه) ، ثم تنشئ "mips" إضافية مُصفاة حتى أكثر في نفس دقة LOD_MIN ، المرتبطة بمستويات خشونة أعلى. بهذه الطريقة نحافظ على الدقة لتداخل الإضاءة المنتشرة بسلاسة مع تحديد حسابات العينات.

+ + ملاحظة: يعتمد خشونة [page:MeshStandardMaterial] الأدنى على حجم النسيج المقدم. إذا كانت عملية التصيير لديك أبعادًا صغيرة أو كانت الأجزاء اللامعة لديها الكثير من التقوس ، فقد لا تزال قادرًا على التخلص من حجم نسيج أصغر. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
حجم النسيج (texture size)الخشونة الدنيا (minimum roughness)
160.21
320.15
640.11
1280.076
2560.054
5120.038
10240.027
+ +

المنشئ (Constructor)

+ +

[name]( [param:WebGLRenderer renderer] )

+

ينشئ هذا المنشئ [name] جديدًا.

+ +

الوظائف (Methods)

+ +

+ [method:WebGLRenderTarget fromScene]( [param:Scene scene], [param:Number sigma], [param:Number near], [param:Number far] ) +

+

+ [page:Scene scene] - المشهد المعطى.
+ [page:Number sigma] - (اختياري) يحدد نصف قطر التشويش بالراديان ليتم تطبيقه على المشهد قبل إنشاء PMREM. الافتراضي هو `0`.
+ [page:Number near] - (اختياري) قيمة السطح القريب. الافتراضي هو `0.1`.
+ [page:Number far] - (اختياري) قيمة السطح البعيد. الافتراضي هو `100`.

+ + يولد PMREM من مشهد معطى ، والذي يمكن أن يكون أسرع من استخدام صورة إذا كانت عرض النطاق الترددي للشبكة منخفضة. تضمن الأسطح القريبة والبعيدة الاختيارية عرض المشهد بأكمله (يتم وضع cubeCamera في المنشأ). +

+ +

+ [method:WebGLRenderTarget fromEquirectangular]( [param:Texture equirectangular] ) +

+

+ [page:Texture equirectangular] - نسيج equirectangular.

+ + يولد PMREM من نسيج equirectangular. +

+ +

+ [method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] ) +

+

+ [page:CubeTexture cubemap] - نسيج cubemap.

+ + يولد PMREM من نسيج cubemap. +

+ +

[method:undefined compileCubemapShader]()

+

+ يجمع مسبقًا شادر cubemap. يمكنك الحصول على بدء تشغيل أسرع عن طريق استدعاء هذه الطريقة أثناء جلب شبكة نسيجك لزيادة التزامن. +

+ +

[method:undefined compileEquirectangularShader]()

+

+ يجمع مسبقًا شادر equirectangular. يمكنك الحصول على بدء تشغيل أسرع عن طريق استدعاء هذه الطريقة أثناء جلب شبكة نسيجك لزيادة التزامن. +

+ +

[method:undefined dispose]()

+

+ يحرر الموارد المتعلقة بوحدة معالجة الرسومات التي تم تخصيصها من قبل هذه الحالة. استدعِ هذه الطريقة كلما لم يعُد هذا المثيل مستخدمًا في تطبيقك. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/ShapeUtils.html b/docs/api/ar/extras/ShapeUtils.html new file mode 100644 index 00000000000000..f6b63425ee775b --- /dev/null +++ b/docs/api/ar/extras/ShapeUtils.html @@ -0,0 +1,52 @@ + + + + + + + + + +

[name]

+ +

+ فئة تحتوي على دوال مساعدة للأشكال.

+ + لاحظ أن هذه كلها دوال خطية لذلك يجب حسابها بشكل منفصل لمكونات x و y (و z و w إذا كانت موجودة) من متجه. +

+ +

الوظائف (Methods)

+ +

[method:Number area]( contour )

+

+ contour -- مضلع 2D. مصفوفة من THREE.Vector2()

+ + حساب مساحة مضلع (2D) المحيط. +

+ +

[method:Boolean isClockWise]( pts )

+

+ pts -- نقاط تحدد مضلع 2D

+ + لاحظ أن هذه هي دالة خطية لذلك يجب حسابها بشكل منفصل لمكونات x و y من المضلع.

+ + يستخدم داخليًا بواسطة [page:Path Path] و [page:ExtrudeGeometry ExtrudeGeometry] و [page:ShapeGeometry ShapeGeometry]. +

+ +

[method:Array triangulateShape]( contour, holes )

+

+ contour -- مضلع 2D. مصفوفة من [page:Vector2].
+ holes -- مصفوفة تحتوي على مصفوفات من [page:Vector2]s. كل مصفوفة + تمثل تعريف ثقب واحد.

+ + يستخدم داخليًا بواسطة [page:ExtrudeGeometry ExtrudeGeometry] و + [page:ShapeGeometry ShapeGeometry] لحساب الوجوه في الأشكال التي بها ثقوب. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/core/Curve.html b/docs/api/ar/extras/core/Curve.html new file mode 100644 index 00000000000000..b000e7ef505276 --- /dev/null +++ b/docs/api/ar/extras/core/Curve.html @@ -0,0 +1,131 @@ + + + + + + + + + +

[name]

+ +

+ فئة أساسية مجردة لإنشاء كائن [name] يحتوي على طرق للإدراج. لمجموعة من [name]s انظر [page:CurvePath]. +

+ +

المنشئ (Constructor)

+ +

[name]()

+ +

ينشئ هذا المُنشئ [name] جديدًا.

+ +

الخصائص (Properties)

+ +

[property:Integer arcLengthDivisions]

+

+ يحدد هذا القيمة عدد الشعبات عند حساب طول الشطر التراكمي للمنحنى عبر [page:.getLengths]. لضمان + الدقة عند استخدام طرق مثل [page:.getSpacedPoints]، يوصى بزيادة [page:.arcLengthDivisions] إذا كان المنحنى كبيرًا جدًا. الافتراضي هو 200. +

+ +

الوظائف (Methods)

+ +

[method:Vector getPoint]( [param:Float t], [param:Vector optionalTarget] )

+

+ [page:Float t] - موقع على المنحنى. يجب أن يكون في النطاق [0، 1]. +
+ [page:Vector optionalTarget] - (اختياري) إذا تم تحديده، سيتم نسخ النتيجة في هذا الفيكتور، وإلا سيتم إنشاء فيكتور جديد. +

+ + يعود بفيكتور لموقع معين على المنحنى. +

+ +

[method:Vector getPointAt]( [param:Float u], [param:Vector optionalTarget] )

+

+ [page:Float u] - موقع على المنحنى وفقًا لطول القوس. يجب أن يكون في النطاق [0، 1].
+ [page:Vector optionalTarget] - (اختياري) إذا تم تحديده، سيتم نسخ النتيجة في هذا الفيكتور، وإلا سيتم إنشاء فيكتور جديد. +

+ + يعود بفيكتور لموقع معين على المنحنى وفقًا لطول القوس. +

+ +

[method:Array getPoints]( [param:Integer divisions] )

+

+ divisions - عدد الأجزاء التي يتم تقسيم المنحنى إليها. الافتراضي هو `5`.

+ + يعود بمجموعة من divisions + 1 نقطة باستخدام getPoint( t ). +

+ +

[method:Array getSpacedPoints]( [param:Integer divisions] )

+

+ divisions - عدد الأجزاء التي يتم تقسيم المнحنى إليها. الافتراضي هو `5`.

+ + يعود بمجموعة من divisions + 1 نقطة متساوية المسافات باستخدام getPointAt( u ). +

+ +

[method:Float getLength]()

+

احصل على إجمالي طول قوس المنحنى.

+ +

[method:Array getLengths]( [param:Integer divisions] )

+

احصل على قائمة بطول الشرائح التراكمية.

+ +

[method:undefined updateArcLengths]()

+

+ تحديث ذاكرة التخزين المؤقت للمسافة الشريطية التراكمية. يجب استدعاء الطريقة + في كل مرة يتم فيها تغيير معلمات المنحنى. إذا كان المنحنى المحدث جزءًا من + منحنى مكون مثل [page:CurvePath]، يجب + استدعاء [page:.updateArcLengths]() على المنحنى المكوَّن أيضًا. +

+ +

[method:Float getUtoTmapping]( [param:Float u], [param:Float distance] )

+

+ بالنظر إلى u في النطاق (0 .. 1) ، يعود [page:Float t] أيضًا في النطاق + (0 .. 1). يمكن استخدام u و t لإعطائك نقاط هي + متساوية البعد من نهايات المنحنى ، باستخدام [page:.getPoint]. +

+ +

[method:Vector getTangent]( [param:Float t], [param:Vector optionalTarget] )

+

+ [page:Float t] - موضع على المنحنى. يجب أن يكون في النطاق [0، 1]. +
+ [page:Vector optionalTarget] - (اختياري) إذا تم تحديده ، سيتم + نسخ النتيجة في هذا Vector ، وإلا سيتم إنشاء Vector جديد. +

+ + يعود بمتجه وحدة مماس على t. إذا لم يكن المنحنى المشتق + تطبيق تفريعه المماس ، سيتم استخدام نقطتين صغيرتين delta بعيدًا للعثور على التدرج الذي يبدو أنه يعطي تقريبًا معقولًا. +

+ +

[method:Vector getTangentAt]( [param:Float u], [param:Vector optionalTarget] )

+

+ [page:Float u] - موقع على المنحنى وفقًا لطول القوس. يجب أن يكون في النطاق [0، 1]. + + [page:Vector optionalTarget] - (اختياري) إذا تم تحديده، سيتم نسخ النتيجة في هذا الفيكتور، وإلا سيتم إنشاء فيكتور جديد. + + يعود الميل في نقطة تبعد مسافة متساوية عن طرفي المنحنى من النقطة المعطاة في [page:.getTangent]. +

+ +

[method:Object computeFrenetFrames]( [param:Integer segments], [param:Boolean closed] )

+

+ إنشاء Frenet Frames. يتطلب تعريف منحى في فضاء 3D. مستخدم + في هَیْأَات مثل [page:TubeGeometry] أو [page:ExtrudeGeometry]. +

+ +

[method:Curve clone]()

+

إنشاء نسخة من هذه الحالة.

+ +

[method:this copy]( [param:Curve source] )

+

يلصق كائن [name] آخر إلى هذه الحالة.

+ +

[method:Object toJSON]()

+

يرجع كائن JSON لتمثيل هذه الحالة.

+ +

[method:this fromJSON]( [param:Object json] )

+

يلصق البيانات من كائن JSON المعطى إلى هذه الحالة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/core/CurvePath.html b/docs/api/ar/extras/core/CurvePath.html new file mode 100644 index 00000000000000..c4a0492b2c0c68 --- /dev/null +++ b/docs/api/ar/extras/core/CurvePath.html @@ -0,0 +1,72 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ فئة أساسية مجردة تمتد [page:Curve]. مسار المنحنى هو مجرد + مصفوفة من المنحنيات المتصلة، ولكنها تحتفظ بواجهة برمجة التطبيقات الخاصة بالمنحنى. +

+ +

المنشئ (Constructor)

+ +

[name]()

+

لا يأخذ المُنشئ أي معلمات.

+ +

الخصائص (Properties)

+

انظر فئة [page:Curve] الأساسية للخصائص المشتركة.

+ +

[property:Array curves]

+

مصفوفة من [page:Curve Curves].

+ +

[property:Boolean autoClose]

+

ما إذا كان يجب إغلاق المسار تلقائيًا أم لا.

+ +

الوظائف (Methods)

+

انظر فئة [page:Curve] الأساسية للأساليب المشتركة.

+ +

[method:undefined add]( [param:Curve curve] )

+

إضافة منحى إلى مصفوفة [page:.curves].

+ +

[method:undefined closePath]()

+

يضيف [page:LineCurve lineCurve] لإغلاق المسار.

+ +

[method:Array getCurveLengths]()

+

+ الحصول على قائمة بطول القطع التراكمية للمنحنيات في مصفوفة [page:.curves]. +

+ +

[method:Array getPoints]( [param:Integer divisions] )

+

+ divisions -- عدد قطع التقسيم إلى المنحنى. الافتراضي هو + `12`.

+ + يعود بمصفوفة من النقاط التي تمثل تسلسل منحنيات. يُعرِّف معلم `division` + عدد القطع التي يتم تقسيم كل منحى إليها. ومع ذلك، لأغراض التحسين والجودة، + يعتمد دقة العينات الفعلية لكل منحى على نوعه. على سبيل المثال، بالنسبة + لـ[page:LineCurve]، يكون عدد النقاط المُستَرَجَعَ دائمًا 2 فقط. +

+ +

[method:Array getSpacedPoints]( [param:Integer divisions] )

+

+ divisions -- عدد قطع التقسيم إلى المنحنى. الافتراضي هو + `40`.

+ + يعود بمجموعة من divisions + 1 نقط متساوية المسافات باستخدام getPointAt( u ). +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/core/Interpolations.html b/docs/api/ar/extras/core/Interpolations.html new file mode 100644 index 00000000000000..72dd219da6eb38 --- /dev/null +++ b/docs/api/ar/extras/core/Interpolations.html @@ -0,0 +1,52 @@ + + + + + + + + + +

[name]

+ +

+ يحتوي [name] على دوال الشريط وبيزيه المستخدمة داخليًا من قبل + فئات المنحنى الخرسانية. +

+ +

الوظائف (Methods)

+ +

[method:Float CatmullRom]( [param:Float t], [param:Float p0], [param:Float p1], [param:Float p2], [param:Float p3] )

+

+ t -- وزن التداخل.
+ p0، p1، p2، p3 -- النقاط التي تُعرِّف منحى الشريط.

+ + يُستخدم داخليًا بواسطة [page:SplineCurve SplineCurve]. +

+ +

[method:Float QuadraticBezier]( [param:Float t], [param:Float p0], [param:Float p1], [param:Float p2] )

+

+ t -- وزن التداخل.
+ p0، p1، p2 -- نقاط البدء والتحكم والنهاية التي تُعرِّف المنحى.

+ + يُستخدم داخليًا بواسطة [page:QuadraticBezierCurve3 QuadraticBezierCurve3] و + [page:QuadraticBezierCurve QuadraticBezierCurve]. +

+ +

[method:Float CubicBezier]( [param:Float t], [param:Float p0], [param:Float p1], [param:Float p2], [param:Float p3] )

+

+ t -- وزن التداخل.
+ p0، p1، p2، p3 -- نقاط البدء والتحكم (مرتين) والنهاية التي تُعرِّف + المنحى.

+ + يُستخدم داخليًا بواسطة [page:CubicBezierCurve3 CubicBezierCurve3] و + [page:CubicBezierCurve CubicBezierCurve]. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/core/Path.html b/docs/api/ar/extras/core/Path.html new file mode 100644 index 00000000000000..ec199c6530c17f --- /dev/null +++ b/docs/api/ar/extras/core/Path.html @@ -0,0 +1,160 @@ + + + + + + + + + + [page:Curve] → [page:CurvePath] → + +

[name]

+ +

+ تمثيل مسار ثنائي الأبعاد. توفر الفئة طرقًا لإنشاء مسارات + ومحيطات الأشكال ثنائية الأبعاد المشابهة لواجهة برمجة التطبيقات Canvas 2D. +

+ +

مثال الكود

+ + + const path = new THREE.Path(); + + path.lineTo( 0, 0.8 ); + path.quadraticCurveTo( 0, 1, 0.2, 1 ); + path.lineTo( 1, 1 ); + + const points = path.getPoints(); + + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + const material = new THREE.LineBasicMaterial( { color: 0xffffff } ); + + const line = new THREE.Line( geometry, material ); + scene.add( line ); + + +

المنشئ (Constructor)

+ +

[name]( [param:Array points] )

+

+ points -- (اختياري) مصفوفة من [page:Vector2 Vector2s].

+ + يُنشئ مسارًا من النقاط. يُعرِّف النقطة الأولى الإزاحة، ثُم + يتم إضافة النقاط المتتالية إلى مصفوفة [page:CurvePath.curves curves] كـ + [page:LineCurve LineCurves].

+ + إذا لم يتم تحديد أي نقاط، يتم إنشاء مسار فارغ ويتم تعيين + [page:.currentPoint] على المنشأ. +

+ +

الخصائص (Properties)

+

انظر فئة [page:CurvePath] الأساسية للخصائص المشتركة.

+ +

[property:Vector2 currentPoint]

+

+ الإزاحة الحالية للمسار. سيبدأ أي [page:Curve] جديد يتم إضافته + هنا. +

+ +

الوظائف (Methods)

+

انظر فئة [page:CurvePath] الأساسية للأساليب المشتركة.

+ +

[method:this absarc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise] )

+

+ x، y -- مركز القوس المطلق.
+ radius -- نصف قطر القوس.
+ startAngle -- زاوية البدء بالراديان.
+ endAngle -- زاوية النهاية بالراديان.
+ clockwise -- تدوير القوس في اتجاه عقارب الساعة. يعتمد على `false`.

+ + يضيف [page:EllipseCurve EllipseCurve] مُوضَعًا مطلقًا إلى + المسار. +

+ +

[method:this absellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )

+

+ x، y -- مركز القطع الناقص المطلق.
+ xRadius -- نصف قطر القطع الناقص في المحور x.
+ yRadius -- نصف قطر القطع الناقص في المحور y.
+ startAngle -- زاوية البدء بالراديان.
+ endAngle -- زاوية النهاية بالراديان.
+ clockwise -- تدوير القطع الناقص في اتجاه عقارب الساعة. يعتمد على false.
+ rotation -- زاوية دوران القطع الناقص بالراديان، عكس اتجاه عقارب + من المحور X الموجب. اختياري، يعتمد على 0.

+ + يضيف [page:EllipseCurve EllipseCurve] مُوضَعًا مطلقًا إلى + المسار. +

+ +

[method:this arc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise] )

+

+ x، y -- مركز القوس المُزَوَّد من آخر استدعاء.
+ radius -- نصف قطر القوس.
+ startAngle -- زاوية البدء بالراديان.
+ endAngle -- زاوية النهاية بالراديان.
+ clockwise -- تدوير القوس في اتجاه عقارب الساعة. يعتمد على `false`.

+ + يضيف [page:EllipseCurve EllipseCurve] إلى المسار، مُوضَعًا نسبيًا + إلى [page:.currentPoint]. +

+ +

[method:this bezierCurveTo]( [param:Float cp1X], [param:Float cp1Y], [param:Float cp2X], [param:Float cp2Y], [param:Float x], [param:Float y] )

+

+ يُنشئ منحى بيزيه من [page:.currentPoint] مع (cp1X، cp1Y) + و(cp2X، cp2Y) كنقاط تحكم ويُحدِّث [page:.currentPoint] إلى x + و y. +

+ +

[method:this ellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )

+

+ x، y -- مركز القطع الناقص المُزَوَّد من آخر استدعاء.
+ xRadius -- نصف قطر القطع الناقص في المحور x.
+ yRadius -- نصف قطر القطع الناقص في المحور y.
+ startAngle -- زاوية البدء بالراديان.
+ endAngle -- زاوية النهاية بالراديان.
+ clockwise -- تدوير القطع الناقص في اتجاه عقارب الساعة. يعتمد على `false`.
+ rotation -- زاوية دوران القطع الناقص بالراديان، عكس اتجاه عقارب + من المحور X الموجب. اختياري، يعتمد على `0`.

+ + يضيف [page:EllipseCurve EllipseCurve] إلى المسار، مُوضَعًا نسبيًا + إلى [page:.currentPoint]. +

+ +

[method:this lineTo]( [param:Float x], [param:Float y] )

+

+ يُربِط [page:LineCurve] من [page:.currentPoint] إلى x، y على + المسار. +

+ +

[method:this moveTo]( [param:Float x], [param:Float y] )

+

تحريك [page:.currentPoint] إلى x، y.

+ +

[method:this quadraticCurveTo]( [param:Float cpX], [param:Float cpY], [param:Float x], [param:Float y] )

+

+ يُنشئ منحى رباعي من [page:.currentPoint] مع cpX و cpY كـ + نقطة تحكم ويُحدِّث [page:.currentPoint] إلى x و y. +

+ +

[method:this setFromPoints]( [param:Array vector2s] )

+

+ points -- مصفوفة من [page:Vector2 Vector2s].

+ + يتم إضافة النقاط إلى مصفوفة [page:CurvePath.curves curves] كـ + [page:LineCurve LineCurves]. +

+ +

[method:this splineThru] ( [param:Array points] )

+

+ points - مصفوفة من [page:Vector2 Vector2s]

+ + يُربِط منحى جديدًا من نوع SplineCurve على المسار. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/core/Shape.html b/docs/api/ar/extras/core/Shape.html new file mode 100644 index 00000000000000..00da599de05a1c --- /dev/null +++ b/docs/api/ar/extras/core/Shape.html @@ -0,0 +1,104 @@ + + + + + + + + + + [page:Curve] → [page:CurvePath] → [page:Path] → + +

[name]

+ +

+ يعرف شكل طائرة 2d تعسفي باستخدام مسارات مع ثقوبات اختيارية. يمكن استخدامه مع [page:ExtrudeGeometry]، [page:ShapeGeometry]، للحصول على نقاط، أو للحصول على وجوه مثلثة. +

+ +

مثال الكود

+ + + const heartShape = new THREE.Shape(); + + heartShape.moveTo( 25, 25 ); + heartShape.bezierCurveTo( 25, 25, 20, 0, 0, 0 ); + heartShape.bezierCurveTo( - 30, 0, - 30, 35, - 30, 35 ); + heartShape.bezierCurveTo( - 30, 55, - 10, 77, 25, 95 ); + heartShape.bezierCurveTo( 60, 77, 80, 55, 80, 35 ); + heartShape.bezierCurveTo( 80, 35, 80, 0, 50, 0 ); + heartShape.bezierCurveTo( 35, 0, 25, 25, 25, 25 ); + + const extrudeSettings = { + depth: 8, + bevelEnabled: true, + bevelSegments: 2, + steps: 2, + bevelSize: 1, + bevelThickness: 1 + }; + + const geometry = new THREE.ExtrudeGeometry( heartShape, extrudeSettings ); + + const mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial() ); + + +

أمثلة (Examples)

+ +

+ [example:webgl_geometry_shapes geometry / shapes ]
+ [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ] +

+ +

المنشئ (Constructor)

+ +

[name]( [param:Array points] )

+

+ points -- (اختياري) مصفوفة من [page:Vector2 Vector2s].

+ + ينشئ شكل من النقاط. يحدد النقطة الأولى الإزاحة، ثم يتم إضافة النقاط المتعاقبة إلى مصفوفة [page:CurvePath.curves curves] كـ + [page:LineCurve LineCurves].

+ + إذا لم يتم تحديد أي نقاط، يتم إنشاء شكل فارغ ويتم تعيين + [page:.currentPoint] على المنشأ. +

+ +

الخصائص (Properties)

+

انظر فئة [page:Path] الأساسية للخصائص المشتركة.

+ +

[property:String uuid]

+

+ [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] من + هذه الحالة. يتم تعيين هذا تلقائيًا، لذلك لا يجب تحريره. +

+ +

[property:Array holes]

+

مصفوفة من [page:Path paths] التي تحدد الثقوب في الشكل.

+ +

الطرق (Methods)

+

انظر فئة [page:Path] الأساسية للطرق المشتركة.

+ +

[method:Array extractPoints]( [param:Integer divisions] )

+

+ divisions -- دقة النتيجة.

+ + استدعاء [page:Curve.getPoints getPoints] على الشكل ومصفوفة [page:.holes] + ، وإرجاع كائن من الشكل: + { shape holes } + حيث shape و holes هما مصفوفات من [page:Vector2 Vector2s]. +

+ +

[method:Array getPointsHoles]( [param:Integer divisions] )

+

+ divisions -- دقة النتيجة.

+ + احصل على مصفوفة من [page:Vector2 Vector2s] التي تمثل الثقوب في + الشكل. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/core/ShapePath.html b/docs/api/ar/extras/core/ShapePath.html new file mode 100644 index 00000000000000..477a5ce54233a9 --- /dev/null +++ b/docs/api/ar/extras/core/ShapePath.html @@ -0,0 +1,93 @@ + + + + + + + + + +

[name]

+ +

+ يتم استخدام هذه الفئة لتحويل سلسلة من الأشكال إلى مصفوفة من + [page:Path]s، على سبيل المثال شكل SVG إلى مسار (انظر المثال أدناه). +

+ +

المنشئ (Constructor)

+ +

[name]( )

+

+ ينشئ ShapePath جديد. على عكس [page:Path]، لا تتم مرور أي نقاط كما + يتم تصميم ShapePath ليتم إنشاؤه بعد الإنشاء. +

+ +

الخصائص (Properties)

+ +

[property:Array subPaths]

+

مصفوفة من [page:Path]s.

+ +

[property:Array currentPath]

+

[page:Path] الحالي الذي يتم إنشاؤه.

+ +

[property:Color color]

+

[page:Color] من الشكل، بشكل افتراضي مضبوط على الأبيض (0xffffff).

+ +

الطرق (Methods)

+ +

[method:this moveTo]( [param:Float x], [param:Float y] )

+

+ يبدأ [page:Path] جديد ويستدعي [page:Path.moveTo]( x, y ) على ذلك + [page:Path]. كما يشير [page:ShapePath.currentPath currentPath] إلى ذلك + [page:Path]. +

+ +

[method:this lineTo]( [param:Float x], [param:Float y] )

+

+ هذا ينشئ خطًا من إزاحة [page:ShapePath.currentPath currentPath] + إلى X و Y ويحدث الإزاحة إلى X و Y. +

+ +

+ [method:this quadraticCurveTo]( [param:Float cpX], [param:Float cpY], [param:Float x], [param:Float y] ) +

+

+ هذا ينشئ منحنى ثنائي الحدود من إزاحة [page:ShapePath.currentPath currentPath] + إلى x و y مع cpX و cpY كنقطة تحكم و + يحدث إزاحة [page:ShapePath.currentPath currentPath] + إلى x و y. +

+ + +

+ [method:this bezierCurveTo]( [param:Float cp1X], [param:Float cp1Y], [param:Float cp2X], [param:Float cp2Y], [param:Float x], [param:Float y] ) +

+

+ هذا ينشئ منحنى بيزيه من إزاحة [page:ShapePath.currentPath currentPath] + إلى x و y مع cp1X و cp1Y و cp2X و cp2Y كنقاط تحكم + ويحدث إزاحة [page:ShapePath.currentPath currentPath] + إلى x و y. +

+ +

[method:this splineThru] ( [param:Array points] )

+

points - مصفوفة من [page:Vector2]s

+

+ يربط [page:SplineCurve] جديد على [page:ShapePath.currentPath currentPath]. +

+ +

[method:Array toShapes]( [param:Boolean isCCW] )

+

isCCW -- يغير كيفية إنشاء الأشكال الصلبة والثقوب

+

+ يحول مصفوفة [page:ShapePath.subPaths subPaths] إلى مصفوفة من + الأشكال. بشكل افتراضي، يتم تعريف الأشكال الصلبة باتجاه عقارب الساعة (CW) ويتم تعريف الثقوب بعكس اتجاه عقارب الساعة (CCW). إذا تم تعيين isCCW على true، فإن هذه + مقلوب. +
+

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/extras/core/ShapePath.js src/extras/core/ShapePath.js] +

+ + diff --git a/docs/api/ar/extras/curves/ArcCurve.html b/docs/api/ar/extras/curves/ArcCurve.html new file mode 100644 index 00000000000000..9ee7d0ab7704a7 --- /dev/null +++ b/docs/api/ar/extras/curves/ArcCurve.html @@ -0,0 +1,24 @@ + + + + + + + + + + [page:Curve] → [page:EllipseCurve] → + +

[name]

+ +

اسم مستعار لـ [page:EllipseCurve].

+ +

الخصائص (Properties)

+

راجع فئة [page:EllipseCurve] للحصول على الخصائص المشتركة.

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/CatmullRomCurve3.html b/docs/api/ar/extras/curves/CatmullRomCurve3.html new file mode 100644 index 00000000000000..acb5a3bf1a9de6 --- /dev/null +++ b/docs/api/ar/extras/curves/CatmullRomCurve3.html @@ -0,0 +1,84 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ قم بإنشاء منحنى شريط 3d ناعم من سلسلة من النقاط باستخدام + [link:https://en.wikipedia.org/wiki/Centripetal_Catmull-Rom_spline Catmull-Rom] خوارزمية. +

+ +

مثال الكود

+ + + // إنشاء حلقة مغلقة متموجة + const curve = new THREE.CatmullRomCurve3( [ + new THREE.Vector3( -10, 0, 10 ), + new THREE.Vector3( -5, 5, 5 ), + new THREE.Vector3( 0, 0, 0 ), + new THREE.Vector3( 5, -5, 5 ), + new THREE.Vector3( 10, 0, 10 ) + ] ); + + const points = curve.getPoints( 50 ); + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + + const material = new THREE.LineBasicMaterial( { color: 0xff0000 } ); + + // إنشاء الكائن النهائي لإضافته إلى المشهد + const curveObject = new THREE.Line( geometry, material ); + + +

أمثلة (Examples)

+ +

+ [example:webgl_geometry_extrude_splines WebGL / geometry / extrude / splines] +

+ +

المنشئ (Constructor)

+ +

+ [name]( [param:Array points], [param:Boolean closed], [param:String curveType], [param:Float tension] ) +

+

+ points – مصفوفة من نقاط [page:Vector3]
+ closed – ما إذا كان المنحنى مغلقًا. الافتراضي هو `false`.
+ curveType – نوع المنحنى. الافتراضي هو `centripetal`.
+ tension – توتر المنحنى. الافتراضي هو `0.5`. +

+ +

الخصائص (Properties)

+

راجع فئة [page:Curve] الأساسية للحصول على الخصائص المشتركة.

+ +

[property:Array points]

+

+ مصفوفة من نقاط [page:Vector3] التي تحدد المنحنى. يحتاج على الأقل إلى دخولين. +

+ +

[property:Boolean closed]

+

سيعود المنحنى إلى نفسه عندما يكون هذا صحيحًا.

+ +

[property:String curveType]

+

القيم الممكنة هي `centripetal` و `chordal` و `catmullrom`.

+ +

[property:Float tension]

+

عندما يكون [page:.curveType] هو `catmullrom` ، يعرف توتر catmullrom.

+ +

الوظائف (Methods)

+

راجع فئة [page:Curve] الأساسية للحصول على طرق مشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/CubicBezierCurve.html b/docs/api/ar/extras/curves/CubicBezierCurve.html new file mode 100644 index 00000000000000..8f1f089cf9eca5 --- /dev/null +++ b/docs/api/ar/extras/curves/CubicBezierCurve.html @@ -0,0 +1,79 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ قم بإنشاء منحنى بيزيه مكعب 2d ناعم + cubic bezier curve ، محدد بنقطة البداية ونقطة النهاية ونقطتي تحكم. +

+ +

مثال الكود

+ + + const curve = new THREE.CubicBezierCurve( + new THREE.Vector2( -10, 0 ), + new THREE.Vector2( -5, 15 ), + new THREE.Vector2( 20, 15 ), + new THREE.Vector2( 10, 0 ) + ); + + const points = curve.getPoints( 50 ); + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + + const material = new THREE.LineBasicMaterial( { color: 0xff0000 } ); + + // إنشاء الكائن النهائي لإضافته إلى المشهد + const curveObject = new THREE.Line( geometry, material ); + + +

المنشئ (Constructor)

+ +

+ [name] ( [param:Vector2 v0], [param:Vector2 v1], [param:Vector2 v2], + [param:Vector2 v3] ) +

+

+ [page:Vector2 v0] – نقطة البداية.
+ [page:Vector2 v1] – نقطة التحكم الأولى.
+ [page:Vector2 v2] – نقطة التحكم الثانية.
+ [page:Vector2 v3] – نقطة النهاية. +

+ +

الخصائص (Properties)

+

راجع فئة [page:Curve] الأساسية للحصول على الخصائص المشتركة.

+ +

[property:Vector2 v0]

+

نقطة البداية.

+ +

[property:Vector2 v1]

+

نقطة التحكم الأولى.

+ +

[property:Vector2 v2]

+

نقطة التحكم الثانية.

+ +

[property:Vector2 v3]

+

نقطة النهاية.

+ +

الوظائف (Methods)

+

راجع فئة [page:Curve] الأساسية للحصول على طرق مشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/CubicBezierCurve3.html b/docs/api/ar/extras/curves/CubicBezierCurve3.html new file mode 100644 index 00000000000000..a0c3e5d53ab48c --- /dev/null +++ b/docs/api/ar/extras/curves/CubicBezierCurve3.html @@ -0,0 +1,80 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ قم بإنشاء منحنى بيزيه مكعب 3d ناعم + cubic bezier curve ، محدد بنقطة البداية ونقطة النهاية ونقطتي تحكم. +

+ +

مثال الكود

+ + + const curve = new THREE.CubicBezierCurve3( + new THREE.Vector3( -10, 0, 0 ), + new THREE.Vector3( -5, 15, 0 ), + new THREE.Vector3( 20, 15, 0 ), + new THREE.Vector3( 10, 0, 0 ) + ); + + const points = curve.getPoints( 50 ); + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + + const material = new THREE.LineBasicMaterial( { color: 0xff0000 } ); + + // إنشاء الكائن النهائي لإضافته إلى المشهد + const curveObject = new THREE.Line( geometry, material ); + + + +

المنشئ (Constructor)

+ +

+ [name]( [param:Vector3 v0], [param:Vector3 v1], [param:Vector3 v2], + [param:Vector3 v3] ) +

+

+ [page:Vector3 v0] – نقطة البداية.
+ [page:Vector3 v1] – نقطة التحكم الأولى.
+ [page:Vector3 v2] – نقطة التحكم الثانية.
+ [page:Vector3 v3] – نقطة النهاية. +

+ +

الخصائص (Properties)

+

راجع فئة [page:Curve] الأساسية للحصول على الخصائص المشتركة.

+ +

[property:Vector3 v0]

+

نقطة البداية.

+ +

[property:Vector3 v1]

+

نقطة التحكم الأولى.

+ +

[property:Vector3 v2]

+

نقطة التحكم الثانية.

+ +

[property:Vector3 v3]

+

نقطة النهاية.

+ +

الوظائف (Methods)

+

راجع فئة [page:Curve] الأساسية للحصول على طرق مشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/EllipseCurve.html b/docs/api/ar/extras/curves/EllipseCurve.html new file mode 100644 index 00000000000000..c89f158dce1ab1 --- /dev/null +++ b/docs/api/ar/extras/curves/EllipseCurve.html @@ -0,0 +1,104 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ ينشئ منحنى 2d على شكل بيضاوي. يؤدي تعيين [page:Number xRadius] مساويًا لـ [page:Number yRadius] إلى الحصول على دائرة. +

+ +

مثال الكود

+ + + const curve = new THREE.EllipseCurve( + 0, 0, // ax, aY + 10, 10, // xRadius, yRadius + 0, 2 * Math.PI, // aStartAngle, aEndAngle + false, // aClockwise + 0 // aRotation + ); + + const points = curve.getPoints( 50 ); + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + + const material = new THREE.LineBasicMaterial( { color: 0xff0000 } ); + + // إنشاء الكائن النهائي لإضافته إلى المشهد + const ellipse = new THREE.Line( geometry, material ); + + +

المنشئ (Constructor)

+ +

+ [name]( [param:Float aX], [param:Float aY], [param:Float xRadius], + [param:Float yRadius], [param:Radians aStartAngle], [param:Radians aEndAngle], [param:Boolean aClockwise], [param:Radians aRotation] ) +

+

+ [page:Float aX] – مركز X للبيضاوي. الافتراضي هو `0`.
+ [page:Float aY] – مركز Y للبيضاوي. الافتراضي هو `0`.
+ [page:Float xRadius] – نصف قطر البيضاوي في اتجاه x. + الافتراضي هو `1`.
+ [page:Float yRadius] – نصف قطر البيضاوي في اتجاه y. + الافتراضي هو `1`.
+ [page:Radians aStartAngle] – زاوية بدء المنحنى بالراديان + بدءًا من المحور X الموجب. الافتراضي هو `0`.
+ [page:Radians aEndAngle] – زاوية نهاية المنحنى بالراديان بدءًا + من المحور X الموجب. الافتراضي هو `2 x Math.PI`.
+ [page:Boolean aClockwise] – ما إذا كان يتم رسم البيضاوي في اتجاه عقارب الساعة. + الافتراضي هو `false`.
+ [page:Radians aRotation] – زاوية دوران البيضاوي بالراديان ، + عكس اتجاه عقارب الساعة من المحور X الموجب (اختياري). الافتراضي هو `0`.

+

+ +

الخصائص (Properties)

+

راجع فئة [page:Curve] الأساسية للحصول على الخصائص المشتركة.

+ +

[property:Float aX]

+

مركز X للبيضاوي.

+ +

[property:Float aY]

+

مركز Y للبيضاوي.

+ +

[property:Radians xRadius]

+

نصف قطر البيضاوي في اتجاه x.

+ +

[property:Radians yRadius]

+

نصف قطر البيضاوي في اتجاه y.

+ +

[property:Float aStartAngle]

+

+ زاوية بدء المنحنى بالراديان بدءًا من المنتصف الأمام. +

+ +

[property:Float aEndAngle]

+

+ زاوية نهاية المنحنى بالراديان بدءًا من المنتصف الأمام. +

+ +

[property:Boolean aClockwise]

+

ما إذا كان يتم رسم البيضاوي في اتجاه عقارب الساعة.

+ +

[property:Float aRotation]

+

+ زاوية دوران البيضاوي بالراديان ، عكس اتجاه عقارب الساعة من + المحور X الموجب (aRotation). الافتراضية هى `0`. +

+ +

الوظائف (Methods)

+

راجع فئة [page:Curve] الأساسية للحصول على طرق مشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/LineCurve.html b/docs/api/ar/extras/curves/LineCurve.html new file mode 100644 index 00000000000000..f6f4beeb37d904 --- /dev/null +++ b/docs/api/ar/extras/curves/LineCurve.html @@ -0,0 +1,42 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

منحنى يمثل قطعة خطية 2d.

+ +

المنشئ (Constructor)

+ +

[name]( [param:Vector2 v1], [param:Vector2 v2] )

+

+ [page:Vector2 v1] – نقطة البداية.
+ [page:Vector2 v2] - نقطة النهاية. +

+ +

الخصائص (Properties)

+

راجع فئة [page:Curve] الأساسية للحصول على الخصائص المشتركة.

+ +

[property:Vector2 v1]

+

نقطة البداية.

+ +

[property:Vector2 v2]

+

نقطة النهاية

+ +

الوظائف (Methods)

+

راجع فئة [page:Curve] الأساسية للحصول على طرق مشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/LineCurve3.html b/docs/api/ar/extras/curves/LineCurve3.html new file mode 100644 index 00000000000000..fe2a14f34b7769 --- /dev/null +++ b/docs/api/ar/extras/curves/LineCurve3.html @@ -0,0 +1,42 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

منحنى يمثل قطعة خطية 3d.

+ +

المنشئ (Constructor)

+ +

[name]( [param:Vector3 v1], [param:Vector3 v2] )

+

+ [page:Vector3 v1] – نقطة البداية.
+ [page:Vector3 v2] - نقطة النهاية. +

+ +

الخصائص (Properties)

+

راجع فئة [page:Curve] الأساسية للحصول على الخصائص المشتركة.

+ +

[property:Vector3 v1]

+

نقطة البداية.

+ +

[property:Vector3 v2]

+

نقطة النهاية.

+ +

الوظائف (Methods)

+

راجع فئة [page:Curve] الأساسية للحصول على طرق مشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/QuadraticBezierCurve.html b/docs/api/ar/extras/curves/QuadraticBezierCurve.html new file mode 100644 index 00000000000000..b5bf0bee30b107 --- /dev/null +++ b/docs/api/ar/extras/curves/QuadraticBezierCurve.html @@ -0,0 +1,73 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ قم بإنشاء منحنى بيزيه ثنائي الأبعاد ناعم + رباعي، محدد بنقطة البداية ونقطة النهاية ونقطة تحكم واحدة. +

+ +

مثال الكود

+ + + const curve = new THREE.QuadraticBezierCurve( + new THREE.Vector2( -10, 0 ), + new THREE.Vector2( 20, 15 ), + new THREE.Vector2( 10, 0 ) + ); + + const points = curve.getPoints( 50 ); + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + + const material = new THREE.LineBasicMaterial( { color: 0xff0000 } ); + + // إنشاء الكائن النهائي لإضافته إلى المشهد + const curveObject = new THREE.Line( geometry, material ); + + +

المنشئ (Constructor)

+ +

+ [name]( [param:Vector2 v0], [param:Vector2 v1], [param:Vector2 v2] ) +

+

+ [page:Vector2 v0] – نقطة البداية.
+ [page:Vector2 v1] – نقطة التحكم.
+ [page:Vector2 v2] – نقطة النهاية. +

+ +

الخصائص (Properties)

+

انظر إلى قاعدة [page:Curve] للخصائص المشتركة.

+ +

[property:Vector2 v0]

+

نقطة البداية.

+ +

[property:Vector2 v1]

+

نقطة التحكم.

+ +

[property:Vector2 v2]

+

نقطة النهاية.

+ +

الخصائص (Properties)

+

انظر إلى الفئة الأساسية [page:Curve] للحصول على الطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/QuadraticBezierCurve3.html b/docs/api/ar/extras/curves/QuadraticBezierCurve3.html new file mode 100644 index 00000000000000..2c0b282109b376 --- /dev/null +++ b/docs/api/ar/extras/curves/QuadraticBezierCurve3.html @@ -0,0 +1,73 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ قم بإنشاء منحنى بيزيه ثلاثي الأبعاد ناعم + رباعي، محدد بنقطة البداية ونقطة النهاية ونقطة تحكم واحدة. +

+ +

مثال الكود

+ + + const curve = new THREE.QuadraticBezierCurve3( + new THREE.Vector3( -10, 0, 0 ), + new THREE.Vector3( 20, 15, 0 ), + new THREE.Vector3( 10, 0, 0 ) + ); + + const points = curve.getPoints( 50 ); + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + + const material = new THREE.LineBasicMaterial( { color: 0xff0000 } ); + + // إنشاء الكائن النهائي لإضافته إلى المشهد + const curveObject = new THREE.Line( geometry, material ); + + +

المنشئ (Constructor)

+ +

+ [name]( [param:Vector3 v0], [param:Vector3 v1], [param:Vector3 v2] ) +

+

+ [page:Vector3 v0] – نقطة البداية
+ [page:Vector3 v1] – نقطة التحكم الوسطى
+ [page:Vector3 v2] – نقطة النهاية
+

+ +

الخصائص (Properties)

+

انظر إلى قاعدة [page:Curve] للخصائص المشتركة.

+ +

[property:Vector3 v0]

+

نقطة البداية.

+ +

[property:Vector3 v1]

+

نقطة التحكم.

+ +

[property:Vector3 v2]

+

نقطة النهاية.

+ +

الوظائف (Methods)

+

انظر إلى قاعدة [page:Curve] للأساليب المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/extras/curves/SplineCurve.html b/docs/api/ar/extras/curves/SplineCurve.html new file mode 100644 index 00000000000000..dfbc0b35ddfb89 --- /dev/null +++ b/docs/api/ar/extras/curves/SplineCurve.html @@ -0,0 +1,60 @@ + + + + + + + + + + [page:Curve] → + +

[name]

+ +

+ قم بإنشاء منحنى سبلاين ثنائي الأبعاد ناعم من سلسلة من النقاط. يستخدم هذا داخليًا + [page:Interpolations.CatmullRom] لإنشاء المنحنى. +

+ +

مثال الكود

+ + + // إنشاء موجة شبيهة بالجيب + const curve = new THREE.SplineCurve( [ + new THREE.Vector2( -10, 0 ), + new THREE.Vector2( -5, 5 ), + new THREE.Vector2( 0, 0 ), + new THREE.Vector2( 5, -5 ), + new THREE.Vector2( 10, 0 ) + ] ); + + const points = curve.getPoints( 50 ); + const geometry = new THREE.BufferGeometry().setFromPoints( points ); + + const material = new THREE.LineBasicMaterial( { color: 0xff0000 } ); + + // إنشاء الكائن النهائي لإضافته إلى المشهد + const splineObject = new THREE.Line( geometry, material ); + + +

المنشئ (Constructor)

+ +

[name]( [param:Array points] )

+

points – مصفوفة من نقاط [page:Vector2] التي تحدد المنحنى.

+ +

الخصائص (Properties)

+

انظر إلى قاعدة [page:Curve] للخصائص المشتركة.

+ +

[property:Array points]

+

مصفوفة من نقاط [page:Vector2] التي تحدد المنحنى.

+ +

الوظائف (Methods)

+

انظر إلى قاعدة [page:Curve] للأساليب المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/BoxGeometry.html b/docs/api/ar/geometries/BoxGeometry.html new file mode 100644 index 00000000000000..484592bde9dbef --- /dev/null +++ b/docs/api/ar/geometries/BoxGeometry.html @@ -0,0 +1,99 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ [name] هي فئة هندسية لمكعب مستطيل مع 'العرض' المحدد ، + 'الارتفاع' و 'العمق'. عند الإنشاء ، يتم توسيط المكعب على الأصل ، + مع كل حافة موازية لأحد المحاور. +

+ + + + + +

مثال الكود

+ + +const geometry = new THREE.BoxGeometry( 1, 1, 1 ); +const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); +const cube = new THREE.Mesh( geometry, material ); +scene.add( cube ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float width], [param:Float height], [param:Float depth], + [param:Integer widthSegments], [param:Integer heightSegments], + [param:Integer depthSegments]) +

+

+ width — العرض؛ أي طول الحواف الموازية لمحور X. + اختياري؛ الافتراضي هو 1. +
+ height — الارتفاع؛ أي طول الحواف الموازية لمحور Y. + اختياري؛ الافتراضي هو 1. +
+ depth — العمق؛ أي طول الحواف الموازية لمحور Z. + اختياري؛ الافتراضي هو 1. +
+ widthSegments — عدد الوجوه المستطيلة المقسمة على طول عرض + الجانب. اختياري؛ الافتراضي هو 1. +
+ heightSegments — عدد الوجوه المستطيلة المقسمة على طول ارتفاع + الجانب. اختياري؛ الافتراضي هو 1. +
+ depthSegments — عدد الوجوه المستطيلة المقسمة على طول عمق + الجانب. اختياري؛ الافتراضي هو 1. +
+

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ + +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/CapsuleGeometry.html b/docs/api/ar/geometries/CapsuleGeometry.html new file mode 100644 index 00000000000000..f87ff2b0e98d01 --- /dev/null +++ b/docs/api/ar/geometries/CapsuleGeometry.html @@ -0,0 +1,79 @@ + + + + + + + + + + [page:BufferGeometry] → [page:LatheGeometry] → + +

[name]

+ +

+ [name] هي فئة هندسة لكبسولة بأشعة وارتفاع محدد. يتم بناؤها باستخدام مخرطة. +

+ + + + + +

مثال الكود

+ + + const geometry = new THREE.CapsuleGeometry( 1, 1, 4, 8 ); + const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); + const capsule = new THREE.Mesh( geometry, material ); scene.add( capsule ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float radius], [param:Float length], [param:Integer capSubdivisions], [param:Integer radialSegments]) +

+

+ radius — نصف قطر الكبسولة. اختياري؛ الافتراضي هو 1.
+ length — طول القسم الأوسط. اختياري؛ الافتراضي هو 1.
+ capSegments — عدد قطاعات المنحنى المستخدمة لبناء الأغطية. اختياري؛ + الافتراضي هو 4.
+ radialSegments — عدد الوجوه المقسمة حول محيط + الكبسولة. اختياري؛ الافتراضي هو 8.
+

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/CircleGeometry.html b/docs/api/ar/geometries/CircleGeometry.html new file mode 100644 index 00000000000000..3b8e2c48b489e5 --- /dev/null +++ b/docs/api/ar/geometries/CircleGeometry.html @@ -0,0 +1,78 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ [name] هو شكل بسيط من الهندسة الإقليدية. يتم بناؤه من عدد من الشرائح المثلثية التي تتجه حول نقطة مركزية وتمتد إلى أبعد ما يمكن من نصف قطر معين. يتم بناؤه عكس اتجاه عقارب الساعة من زاوية بدء وزاوية مركزية معينة. يمكن أيضًا استخدامه لإنشاء مضلعات منتظمة، حيث يحدد عدد الشرائح عدد الجوانب. +

+ + + + + +

مثال الكود

+ + +const geometry = new THREE.CircleGeometry( 5, 32 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const circle = new THREE.Mesh( geometry, material ); scene.add( circle ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float radius], [param:Integer segments], [param:Float thetaStart], [param:Float thetaLength]) +

+

+ radius — نصف قطر الدائرة، الافتراضي = 1.
+ segments — عدد الشرائح (المثلثات)، الحد الأدنى = 3، الافتراضي = 32.
+ thetaStart — زاوية البدء للشريحة الأولى، الافتراضي = 0 (موقع الساعة + الثالثة).
+ thetaLength — الزاوية المركزية، وغالبًا ما تسمى ثيتا، للقطاع الدائري. الافتراضي هو 2 * Pi، مما يجعله دائرة كاملة. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/ConeGeometry.html b/docs/api/ar/geometries/ConeGeometry.html new file mode 100644 index 00000000000000..e9ec6c422f0e8b --- /dev/null +++ b/docs/api/ar/geometries/ConeGeometry.html @@ -0,0 +1,79 @@ + + + + + + + + + + [page:BufferGeometry] → [page:CylinderGeometry] → + +

[name]

+ +

فئة لإنشاء هندسة المخروط.

+ + + + + +

مثال الكود + + + const geometry = new THREE.ConeGeometry( 5, 20, 32 ); + const material = new THREE.MeshBasicMaterial( {color: 0xffff00} ); + const cone = new THREE.Mesh(geometry, material ); scene.add( cone ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float radius], [param:Float height], [param:Integer radialSegments], [param:Integer heightSegments], [param:Boolean openEnded], [param:Float thetaStart], [param:Float thetaLength]) +

+

+ radius — نصف قطر قاعدة المخروط. الافتراضي هو 1.
+ height — ارتفاع المخروط. الافتراضي هو 1.
+ radialSegments — عدد الوجوه المقسمة حول محيط + المخروط. الافتراضي هو 32
+ heightSegments — عدد صفوف الوجوه على طول ارتفاع المخروط. + الافتراضي هو 1.
+ openEnded — مؤشر منطقي يشير إلى ما إذا كانت قاعدة المخروط مفتوحة أو + مغلقة. الافتراضي هو false، أي مغلق.
+ thetaStart — زاوية البدء للشريحة الأولى، الافتراضي = 0 (موقع الساعة + الثالثة).
+ thetaLength — الزاوية المركزية، وغالبًا ما تسمى ثيتا، للقطاع الدائري. الافتراضي هو 2 * Pi، مما يجعله مخروطًا كاملاً. +

+ +

الخصائص (Properties)

+

انظر فئة [page:CylinderGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:CylinderGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/CylinderGeometry.html b/docs/api/ar/geometries/CylinderGeometry.html new file mode 100644 index 00000000000000..ecf1cc8098dc0d --- /dev/null +++ b/docs/api/ar/geometries/CylinderGeometry.html @@ -0,0 +1,84 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

فئة لإنشاء هندسة الأسطوانة.

+ + + + + +

مثال الكود

+ + + const geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 ); + const material = new THREE.MeshBasicMaterial( {color: 0xffff00} ); + const cylinder = new THREE.Mesh( geometry, material ); scene.add( cylinder ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float radiusTop], [param:Float radiusBottom], [param:Float height], [param:Integer radialSegments], [param:Integer heightSegments], + [param:Boolean openEnded], [param:Float thetaStart], [param:Float thetaLength]) +

+

+ radiusTop — نصف قطر الأسطوانة في الأعلى. الافتراضي هو 1.
+ radiusBottom — نصف قطر الأسطوانة في الأسفل. الافتراضي هو 1.
+ height — ارتفاع الأسطوانة. الافتراضي هو 1.
+ radialSegments — عدد الوجوه المقسمة حول محيط + الأسطوانة. الافتراضي هو 32
+ heightSegments — عدد صفوف الوجوه على طول ارتفاع الأسطوانة. + الافتراضي هو 1.
+ openEnded — مؤشر منطقي يشير إلى ما إذا كانت طرفي الأسطوانة مفتوحة + أو مغلقة. الافتراضي هو false، أي مغلق.
+ thetaStart — زاوية البدء للشريحة الأولى، الافتراضي = 0 (موقع الساعة + الثالثة).
+ thetaLength — الزاوية المركزية، وغالبًا ما تسمى ثيتا، للقطاع الدائري. الافتراضي هو 2 * Pi، مما يجعله أسطوانة كاملة. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/DodecahedronGeometry.html b/docs/api/ar/geometries/DodecahedronGeometry.html new file mode 100644 index 00000000000000..8919492245861f --- /dev/null +++ b/docs/api/ar/geometries/DodecahedronGeometry.html @@ -0,0 +1,64 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] + +

[name]

+ +

فئة لإنشاء هندسات الدوديكاهيدرون.

+ + + + + +

المنشئ (Constructor)

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — نصف قطر الدوديكاهيدرون. الافتراضي هو 1.
+ detail — الافتراضي هو 0. تعيين هذه القيمة إلى قيمة أكبر من 0 يضيف + الرؤوس مما يجعله لم يعد دوديكاهيدرون. +

+ +

الخصائص (Properties)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/EdgesGeometry.html b/docs/api/ar/geometries/EdgesGeometry.html new file mode 100644 index 00000000000000..9e138ec93ebe36 --- /dev/null +++ b/docs/api/ar/geometries/EdgesGeometry.html @@ -0,0 +1,61 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ يمكن استخدام هذا ككائن مساعد لعرض حواف + [page:BufferGeometry geometry]. +

+ +

مثال الكود

+ + +const geometry = new THREE.BoxGeometry( 100, 100, 100 ); +const edges = new THREE.EdgesGeometry( geometry ); +const line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial( { color: 0xffffff } ) ); +scene.add( line ); + + +

أمثلة (Examples)

+

[example:webgl_helpers helpers]

+ +

المنشئ (Constructor)

+ +

+ [name]( [param:BufferGeometry geometry], [param:Integer thresholdAngle] ) +

+

+ geometry — أي كائن هندسة.
+ thresholdAngle — يتم عرض الحافة فقط إذا كانت الزاوية (بالدرجات) + بين معايير الوجه للوجوه الملحقة تتجاوز هذه القيمة. + الافتراضي = 1 درجة. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/ExtrudeGeometry.html b/docs/api/ar/geometries/ExtrudeGeometry.html new file mode 100644 index 00000000000000..f2220bae0aa2eb --- /dev/null +++ b/docs/api/ar/geometries/ExtrudeGeometry.html @@ -0,0 +1,131 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

ينشئ هندسة مُبثوقة من شكل المسار.

+ + + + + +

مثال الكود

+ + + const length = 12, width = 8; + + const shape = new THREE.Shape(); + shape.moveTo( 0,0 ); + shape.lineTo( 0, width ); + shape.lineTo( length, width ); + shape.lineTo( length, 0 ); + shape.lineTo( 0, 0 ); + + const extrudeSettings = { + steps: 2, + depth: 16, + bevelEnabled: true, + bevelThickness: 1, + bevelSize: 1, + bevelOffset: 0, + bevelSegments: 1 + }; + + const geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings ); + const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + const mesh = new THREE.Mesh( geometry, material ) ; + scene.add( mesh ); + + +

المنشئ (Constructor)

+ +

[name]([param:Array shapes], [param:Object options])

+

+ shapes — شكل أو مصفوفة من الأشكال.
+ options — كائن يمكن أن يحتوي على المعلمات التالية. +

+ +
    +
  • + curveSegments — int. عدد النقاط على المنحنيات. الافتراضي هو 12. +
  • +
  • + steps — int. عدد النقاط المستخدمة لتقسيم الشرائح على طول + عمق المنحنى المبثوق. الافتراضي هو 1. +
  • +
  • depth — float. عمق لإبعاد الشكل. الافتراضي هو 1.
  • +
  • + bevelEnabled — bool. تطبيق التجعيد على الشكل. الافتراضي هو true. +
  • +
  • + bevelThickness — float. مدى اختراق التجعيد في الشكل الأصلي. + الافتراضي هو 0.2. +
  • +
  • + bevelSize — float. المسافة من مخطط الشكل التي يمتد فيها التجعيد. + الافتراضي هو bevelThickness - 0.1. +
  • +
  • + bevelOffset — float. المسافة من مخطط الشكل التي يبدأ فيها التجعيد. + الافتراضي هو 0. +
  • +
  • bevelSegments — int. عدد طبقات التجعيد. الافتراضي هو 3.
  • +
  • + extrudePath — THREE.Curve. مسار منحنى ثلاثي الأبعاد يجب أن يتم إبعاد + الشكل على طوله. لا يتم دعم التجعيد لإبعاد المسار. +
  • +
  • UVGenerator — Object. كائن يوفر وظائف مولد UV
  • +
+ +

هذا الكائن يبعد شكل ثنائي الأبعاد إلى هندسة ثلاثية الأبعاد.

+ +

+ عند إنشاء شبكة بهذه الهندسة، إذا كنت ترغب في استخدام مادة منفصلة لوجهها + وجوانبها المبثوقة، يمكنك استخدام مصفوفة من المواد. سيتم تطبيق المادة + الأولى على الوجه؛ سيتم تطبيق المادة الثانية على الجانب. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/IcosahedronGeometry.html b/docs/api/ar/geometries/IcosahedronGeometry.html new file mode 100644 index 00000000000000..b5f614de126983 --- /dev/null +++ b/docs/api/ar/geometries/IcosahedronGeometry.html @@ -0,0 +1,64 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] → +

[name]

+ +

فئة لإنشاء هندسة الإيكوساهيدرون.

+ + + + + +

المنشئ (Constructor)

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — الافتراضي هو 1.
+ detail — الافتراضي هو 0. تعيين هذه القيمة إلى قيمة أكبر من 0 يضيف المزيد + من الرؤوس مما يجعله لم يعد إيكوساهيدرون. عندما يكون التفصيل أكبر من + 1، فهو عبارة عن كرة بشكل فعال. +

+ +

الخصائص (Properties)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن يحتوي على خاصية لكل من معلمات المنشئ. أي تعديل بعد التجسيد لا يغير + الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/LatheGeometry.html b/docs/api/ar/geometries/LatheGeometry.html new file mode 100644 index 00000000000000..277a66b345e05c --- /dev/null +++ b/docs/api/ar/geometries/LatheGeometry.html @@ -0,0 +1,83 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ ينشئ شبكات مع تماثل محوري مثل الفازات. يدور الخراطة حول المحور Y. +

+ + + + +

مثال الكود

+ + + const points = []; + for ( let i = 0; i < 10; i ++ ) { + points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) ); + } + const geometry = new THREE.LatheGeometry( points ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); + const lathe = new THREE.Mesh( geometry, material ); + scene.add( lathe ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Array points], [param:Integer segments], [param:Float + phiStart], [param:Float phiLength]) +

+

+ points — مصفوفة من Vector2s. يجب أن يكون الإحداثي x لكل نقطة أكبر من الصفر. الافتراضي هو مصفوفة مع (0، -0.5) ، (0.5، 0) و (0، 0.5) التي تنشئ شكل الماس البسيط.
+ segments — عدد قطاعات المحيط التي يتم إنشاؤها. الافتراضي هو + 12.
+ phiStart — الزاوية الابتدائية بالراديان. الافتراضي هو 0.
+ phiLength — المدى الرادياني (0 إلى 2PI) للقسم الملتوي 2PI هو مخرطة مغلقة ، أقل من 2PI هو جزء. الافتراضي هو 2PI. +

+

هذا ينشئ [name] بناءً على المعلمات.

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/OctahedronGeometry.html b/docs/api/ar/geometries/OctahedronGeometry.html new file mode 100644 index 00000000000000..ba51aa9dde7caf --- /dev/null +++ b/docs/api/ar/geometries/OctahedronGeometry.html @@ -0,0 +1,61 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] → +

[name]

+ +

فئة لإنشاء هندسة الأوكتاهيدرون.

+ + + + +

المنشئ (Constructor)

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — نصف قطر الثماني. الافتراضي هو 1.
+ detail — الافتراضي هو 0. تعيين هذه القيمة إلى قيمة أكبر من الصفر يضيف + الرؤوس مما يجعله لم يعد ثمانيًا. +

+ +

الخصائص (Properties)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/PlaneGeometry.html b/docs/api/ar/geometries/PlaneGeometry.html new file mode 100644 index 00000000000000..19d94dda3802b4 --- /dev/null +++ b/docs/api/ar/geometries/PlaneGeometry.html @@ -0,0 +1,75 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

فئة لإنشاء هندسات الطائرة.

+ + + + +

مثال الكود

+ + +const geometry = new THREE.PlaneGeometry( 1, 1 ); +const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} ); +const plane = new THREE.Mesh( geometry, material ); +scene.add( plane ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float width], [param:Float height], [param:Integer + widthSegments], [param:Integer heightSegments]) +

+

+ width — العرض على طول المحور X. الافتراضي هو 1.
+ height — الارتفاع على طول المحور Y. الافتراضي هو 1.
+ widthSegments — اختياري. الافتراضي هو 1.
+ heightSegments — اختياري. الافتراضي هو 1. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/PolyhedronGeometry.html b/docs/api/ar/geometries/PolyhedronGeometry.html new file mode 100644 index 00000000000000..ebb06670182f0f --- /dev/null +++ b/docs/api/ar/geometries/PolyhedronGeometry.html @@ -0,0 +1,68 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ متعدد الأوجه هو صلب في ثلاثة أبعاد مع وجوه مسطحة. ستأخذ هذه الفئة مصفوفة من الرؤوس ، وتعرضها على كرة ، ثم تقسمها إلى المستوى المطلوب من التفاصيل. يتم استخدام هذه الفئة بواسطة [page:DodecahedronGeometry] ، [page:IcosahedronGeometry] ، [page:OctahedronGeometry] ، و [page:TetrahedronGeometry] لإنشاء هندساتهم المعنية. +

+ +

Code Example

+ +const verticesOfCube = [ + -1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1, + -1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1, +]; + +const indicesOfFaces = [ + 2,1,0, 0,3,2, + 0,4,7, 7,3,0, + 0,1,5, 5,4,0, + 1,2,6, 6,5,1, + 2,3,7, 7,6,2, + 4,5,6, 6,7,4 +]; + +const geometry = new THREE.PolyhedronGeometry( verticesOfCube, indicesOfFaces, 6, 2 ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Array vertices], [param:Array indices], [param:Float radius], [param:Integer detail]) +

+

+ vertices — [page:Array] من النقاط على شكل [1،1،1، -1، -1، -1، ...] +
+ indices — [page:Array] من الفهارس التي تشكل وجوه الشكل + [0،1،2، 2،3،0، ...]
+ radius — [page:Float] - نصف قطر الشكل النهائي
+ detail — [page:Integer] - عدد المستويات لتقسيم الهندسة. كلما كان التفصيل أكثر ، كان الشكل أكثر نعومة. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/RingGeometry.html b/docs/api/ar/geometries/RingGeometry.html new file mode 100644 index 00000000000000..315c34bea2187d --- /dev/null +++ b/docs/api/ar/geometries/RingGeometry.html @@ -0,0 +1,74 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

فئة لإنشاء هندسة حلقة ثنائية الأبعاد.

+ + + + +

Code Example

+ + + const geometry = new THREE.RingGeometry( 1, 5, 32 ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } ); + const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float innerRadius], [param:Float outerRadius], + [param:Integer thetaSegments], [param:Integer phiSegments], [param:Float thetaStart], [param:Float thetaLength]) +

+

+ innerRadius — الافتراضي هو 0.5.
+ outerRadius — الافتراضي هو 1.
+ thetaSegments — عدد القطاعات. يعني الرقم الأعلى أن الحلقة ستكون + أكثر دائرية. الحد الأدنى هو 3. الافتراضي هو 32.
+ phiSegments — الحد الأدنى هو 1. الافتراضي هو 1.
+ thetaStart — زاوية البدء. الافتراضي هو 0.
+ thetaLength — زاوية مركزية. الافتراضي هو Math.PI * 2. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/ShapeGeometry.html b/docs/api/ar/geometries/ShapeGeometry.html new file mode 100644 index 00000000000000..a3f1238151b3a4 --- /dev/null +++ b/docs/api/ar/geometries/ShapeGeometry.html @@ -0,0 +1,87 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ ينشئ هندسة متعددة الأضلاع من جانب واحد من شكل واحد أو أكثر من المسارات. +

+ + + + + +

Code Example

+ + + const x = 0, y = 0; + + const heartShape = new THREE.Shape(); + + heartShape.moveTo( x + 5, y + 5 ); + heartShape.bezierCurveTo( x + 5, y + 5, x + 4, y, x, y ); + heartShape.bezierCurveTo( x - 6, y, x - 6, y + 7,x - 6, y + 7 ); + heartShape.bezierCurveTo( x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19 ); + heartShape.bezierCurveTo( x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7 ); + heartShape.bezierCurveTo( x + 16, y + 7, x + 16, y, x + 10, y ); + heartShape.bezierCurveTo( x + 7, y, x + 5, y + 5, x + 5, y + 5 ); + + const geometry = new THREE.ShapeGeometry( heartShape ); + const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + const mesh = new THREE.Mesh( geometry, material ) ; + scene.add( mesh ); + + +

المنشئ (Constructor)

+ +

[name]([param:Array shapes], [param:Integer curveSegments])

+

+ shapes — [page:Array] من الأشكال أو [page:Shape shape] واحد. الافتراضي هو + شكل مثلث واحد.
+ curveSegments - [page:Integer] - عدد القطاعات لكل شكل. الافتراضي هو + 12. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/SphereGeometry.html b/docs/api/ar/geometries/SphereGeometry.html new file mode 100644 index 00000000000000..edaeccdcdc21c6 --- /dev/null +++ b/docs/api/ar/geometries/SphereGeometry.html @@ -0,0 +1,87 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

فئة لإنشاء هندسات الكرة.

+ + + + +

مثال الكود

+ + +const geometry = new THREE.SphereGeometry( 15, 32, 16 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const sphere = new THREE.Mesh( geometry, material ); scene.add( sphere ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float radius], [param:Integer widthSegments], [param:Integer heightSegments], [param:Float phiStart], [param:Float phiLength], + [param:Float thetaStart], [param:Float thetaLength]) +

+ +

+ radius — نصف قطر الكرة. الافتراضي هو 1.
+ widthSegments — عدد القطاعات الأفقية. القيمة الدنيا هي 3 ، والافتراضي هو + 32.
+ heightSegments — عدد القطاعات العمودية. القيمة الدنيا هي 2 ، والافتراضي هو + 16.
+ phiStart — حدد زاوية البدء الأفقية. الافتراضي هو 0.
+ phiLength — حدد حجم زاوية المسح الأفقية. الافتراضي هو Math.PI * + 2.
+ thetaStart — حدد زاوية البدء العمودية. الافتراضي هو 0.
+ thetaLength — حدد حجم زاوية المسح العمودية. الافتراضي هو Math.PI.
+

+ +

+ يتم إنشاء الهندسة عن طريق التمرير وحساب قمم حول المحور Y + (المسح الأفقي) والمحور Z (المسح العمودي). وبالتالي ، يمكن إنشاء كرات ناقصة (شبيهة بـ `'شرائح كروية'`) من خلال استخدام قيم مختلفة من phiStart و phiLength و thetaStart و thetaLength ، لتحديد النقاط التي نبدأ فيها (أو ننهي) حساب تلك + قمم. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/TetrahedronGeometry.html b/docs/api/ar/geometries/TetrahedronGeometry.html new file mode 100644 index 00000000000000..7b67c06b69eb21 --- /dev/null +++ b/docs/api/ar/geometries/TetrahedronGeometry.html @@ -0,0 +1,62 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] → + +

[name]

+ +

فئة لإنشاء هندسات التيتراهيدرون.

+ + + + +

المنشئ (Constructor)

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — نصف قطر المنشور الرباعي. الافتراضي هو 1.
+ detail — الافتراضي هو 0. تعيين هذه القيمة إلى قيمة أكبر من 0 يضيف + الرؤوس مما يجعله لم يعد منشورًا رباعيًا. +

+ +

الخصائص (Properties)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:PolyhedronGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/TorusGeometry.html b/docs/api/ar/geometries/TorusGeometry.html new file mode 100644 index 00000000000000..20159e4594959b --- /dev/null +++ b/docs/api/ar/geometries/TorusGeometry.html @@ -0,0 +1,75 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

فئة لإنشاء هندسات التوروس.

+ + + + +

مثال الكود

+ + +const geometry = new THREE.TorusGeometry( 10, 3, 16, 100 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const torus = new THREE.Mesh( geometry, material ); scene.add( torus ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float radius], [param:Float tube], [param:Integer radialSegments], [param:Integer tubularSegments], [param:Float arc]) +

+

+ radius - نصف قطر الدائرة ، من مركز الدائرة إلى مركز + الأنبوب. الافتراضي هو 1.
+ tube — نصف قطر الأنبوب. الافتراضي هو 0.4.
+ radialSegments — الافتراضي هو 12
+ tubularSegments — الافتراضي هو 48.
+ arc — زاوية مركزية. الافتراضي هو Math.PI * 2. +

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/TorusKnotGeometry.html b/docs/api/ar/geometries/TorusKnotGeometry.html new file mode 100644 index 00000000000000..94c9ad3e343dc5 --- /dev/null +++ b/docs/api/ar/geometries/TorusKnotGeometry.html @@ -0,0 +1,84 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ ينشئ عقدة دائرية ، والتي يتم تحديد شكلها الخاص من خلال زوج من الأعداد الصحيحة المتباينة ، p و q. إذا لم يكن p و q متباينين ، فسيكون النتيجة رابط دائري. +

+ + + + +

مثال الكود

+ + +const geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const torusKnot = new THREE.Mesh( geometry, material ); scene.add( torusKnot ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Float radius], [param:Float tube], [param:Integer tubularSegments], [param:Integer radialSegments], [param:Integer p], + [param:Integer q]) +

+
    +
  • radius - نصف قطر الدائرة. الافتراضي هو 1.
  • +
  • tube — نصف قطر الأنبوب. الافتراضي هو 0.4.
  • +
  • tubularSegments — الافتراضي هو 64.
  • +
  • radialSegments — الافتراضي هو 8.
  • +
  • + p — هذه القيمة تحدد ، عدد مرات التفاف الهندسة حول محورها + التناظر الدوار. الافتراضي هو 2. +
  • +
  • + q — هذه القيمة تحدد ، عدد مرات التفاف الهندسة حول دائرة في داخل + الدائرة. الافتراضي هو 3. +
  • +
+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/TubeGeometry.html b/docs/api/ar/geometries/TubeGeometry.html new file mode 100644 index 00000000000000..4edc3b10bbe797 --- /dev/null +++ b/docs/api/ar/geometries/TubeGeometry.html @@ -0,0 +1,103 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

ينشئ أنبوبًا يُبثق على طول منحنى ثلاثي الأبعاد.

+ + + + + +

مثال الكود

+ + + class CustomSinCurve extends THREE.Curve { + + constructor( scale = 1 ) { + super(); + this.scale = scale; + } + + getPoint( t, optionalTarget = new THREE.Vector3() ) { + + const tx = t * 3 - 1.5; + const ty = Math.sin( 2 * Math.PI * t ); + const tz = 0; + + return optionalTarget.set( tx, ty, tz ).multiplyScalar( this.scale ); + } + } + + const path = new CustomSinCurve( 10 ); + const geometry = new THREE.TubeGeometry( path, 20, 2, 8, false ); + const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + const mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + +

المنشئ (Constructor)

+ +

+ [name]([param:Curve path], [param:Integer tubularSegments], [param:Float radius], [param:Integer radialSegments], [param:Boolean closed]) +

+

+ path — [page:Curve] - مسار ثلاثي الأبعاد يرث من فئة [page:Curve] الأساسية + . الافتراضي هو منحنى بيزير رباعي.
+ tubularSegments — [page:Integer] - عدد القطاعات التي تشكل + الأنبوب. الافتراضي هو `64`.
+ radius — [page:Float] - نصف قطر الأنبوب. الافتراضي هو `1`.
+ radialSegments — [page:Integer] - عدد القطاعات التي تشكل + المقطع العرضي. الافتراضي هو `8`.
+ closed — [page:Boolean] هل الأنبوب مفتوح أم مغلق. الافتراضي هو `false`.
+

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

[property:Object parameters]

+

+ كائن به خاصية لكل من معلمات المُنشئ. أي تعديل بعد التجسيد لا يغير الهندسة. +

+ +

[property:Array tangents]

+

مصفوفة من المماسات [page:Vector3]

+ +

[property:Array normals]

+

مصفوفة من المعايير [page:Vector3]

+ +

[property:Array binormals]

+

مصفوفة من المعايير المزدوجة [page:Vector3]

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ar/geometries/WireframeGeometry.html b/docs/api/ar/geometries/WireframeGeometry.html new file mode 100644 index 00000000000000..52425aaa8c3a9c --- /dev/null +++ b/docs/api/ar/geometries/WireframeGeometry.html @@ -0,0 +1,54 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ يمكن استخدام هذا ككائن مساعد لعرض [page:BufferGeometry geometry] كإطار سلكي. +

+ +

مثال الكود

+ + + const geometry = new THREE.SphereGeometry( 100, 100, 100 ); + + const wireframe = new THREE.WireframeGeometry( geometry ); + + const line = new THREE.LineSegments( wireframe ); + line.material.depthTest = false; + line.material.opacity = 0.25; + line.material.transparent = true; + + scene.add( line ); + + +

أمثلة (Examples)

+ +

[example:webgl_helpers helpers]

+ +

المنشئ (Constructor)

+ +

[name]( [param:BufferGeometry geometry] )

+

geometry — أي كائن هندسي.

+ +

الخصائص (Properties)

+

انظر فئة [page:BufferGeometry] الأساسية للخصائص المشتركة.

+ +

الطرق (Methods)

+

انظر فئة [page:BufferGeometry] الأساسية للطرق المشتركة.

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/en/Template.html b/docs/api/en/Template.html index 23b3d0534aa6eb..69186ac1b774c1 100644 --- a/docs/api/en/Template.html +++ b/docs/api/en/Template.html @@ -13,25 +13,18 @@

[name]

todo

-

Example

todo -

Constructor

[name]([param:Number todo])

-

-

Properties

[property:Number todo]

-

- todo -

- +

todo

Methods

@@ -39,7 +32,6 @@

[method:undefined todo]()

todo

todo

-

Source

diff --git a/docs/api/en/animation/AnimationAction.html b/docs/api/en/animation/AnimationAction.html index 006065b733d81e..a2ca9e65896672 100644 --- a/docs/api/en/animation/AnimationAction.html +++ b/docs/api/en/animation/AnimationAction.html @@ -10,91 +10,104 @@

[name]

- AnimationActions schedule the performance of the animations which are stored in - [page:AnimationClip AnimationClips].

+ AnimationActions schedule the performance of the animations which are + stored in [page:AnimationClip AnimationClips].

Note: Most of AnimationAction's methods can be chained.

- For an overview of the different elements of the three.js animation system see the - "Animation System" article in the "Next Steps" section of the manual. + For an overview of the different elements of the three.js animation system + see the "Animation System" article in the "Next Steps" section of the + manual.

-

Constructor

- -

[name]( [param:AnimationMixer mixer], [param:AnimationClip clip], [param:Object3D localRoot] )

+

+ [name]( [param:AnimationMixer mixer], [param:AnimationClip clip], + [param:Object3D localRoot] ) +

- [page:AnimationMixer mixer] - the `AnimationMixer` that is controlled by this action.
- [page:AnimationClip clip] - the `AnimationClip` that holds the animation data for this action.
- [page:Object3D localRoot] - the root object on which this action is performed.
- [page:Number blendMode] - defines how the animation is blended/combined when two or more animations are simultaneously played.

+ [page:AnimationMixer mixer] - the `AnimationMixer` that is controlled by + this action.
+ [page:AnimationClip clip] - the `AnimationClip` that holds the animation + data for this action.
+ [page:Object3D localRoot] - the root object on which this action is + performed.
+ [page:Number blendMode] - defines how the animation is blended/combined + when two or more animations are simultaneously played.

- Note: Instead of calling this constructor directly you should instantiate an AnimationAction with - [page:AnimationMixer.clipAction] since this method provides caching for better performance. + Note: Instead of calling this constructor directly you should instantiate + an AnimationAction with [page:AnimationMixer.clipAction] since this method + provides caching for better performance.

-

Properties

[property:Number blendMode]

- Defines how the animation is blended/combined when two or more animations are simultaneously played. - Valid values are *NormalAnimationBlendMode* (default) and *AdditiveAnimationBlendMode*. + Defines how the animation is blended/combined when two or more animations + are simultaneously played. Valid values are *NormalAnimationBlendMode* + (default) and *AdditiveAnimationBlendMode*.

[property:Boolean clampWhenFinished]

- If `clampWhenFinished` is set to true the animation will automatically be [page:.paused paused] - on its last frame.

+ If `clampWhenFinished` is set to true the animation will automatically be + [page:.paused paused] on its last frame.

- If `clampWhenFinished` is set to false, [page:.enabled enabled] will automatically be switched - to false when the last loop of the action has finished, so that this action has no further - impact.

+ If `clampWhenFinished` is set to false, [page:.enabled enabled] will + automatically be switched to false when the last loop of the action has + finished, so that this action has no further impact.

Default is false.

- Note: `clampWhenFinished` has no impact if the action is interrupted (it has only an effect if - its last loop has really finished). + Note: `clampWhenFinished` has no impact if the action is interrupted (it + has only an effect if its last loop has really finished).

[property:Boolean enabled]

- Setting `enabled` to `false` disables this action, so that it has no impact. Default is `true`.

+ Setting `enabled` to `false` disables this action, so that it has no + impact. Default is `true`.

- When the action is re-enabled, the animation continues from its current [page:.time time] - (setting `enabled` to `false` doesn't reset the action).

+ When the action is re-enabled, the animation continues from its current + [page:.time time] (setting `enabled` to `false` doesn't reset the + action).

- Note: Setting `enabled` to `true` doesn’t automatically restart the animation. Setting `enabled` - to `true` will only restart the animation immediately if the following condition is fulfilled: - [page:.paused paused] is `false`, this action has not been deactivated in the meantime (by - executing a [page:.stop stop] or [page:.reset reset] command), and neither [page:.weight weight] - nor [page:.timeScale timeScale] is `0`. + Note: Setting `enabled` to `true` doesn’t automatically restart the + animation. Setting `enabled` to `true` will only restart the animation + immediately if the following condition is fulfilled: [page:.paused paused] + is `false`, this action has not been deactivated in the meantime (by + executing a [page:.stop stop] or [page:.reset reset] command), and neither + [page:.weight weight] nor [page:.timeScale timeScale] is `0`.

[property:Number loop]

The looping mode (can be changed with [page:.setLoop setLoop]). Default is - [page:Animation THREE.LoopRepeat] (with an infinite number of [page:.repetitions repetitions])

+ [page:Animation THREE.LoopRepeat] (with an infinite number of + [page:.repetitions repetitions])

Must be one of these constants:

[page:Animation THREE.LoopOnce] - playing the clip once,
- [page:Animation THREE.LoopRepeat] - playing the clip with the chosen number of `repetitions`, - each time jumping from the end of the clip directly to its beginning,
- [page:Animation THREE.LoopPingPong] - playing the clip with the chosen number of `repetitions`, - alternately playing forward and backward. + [page:Animation THREE.LoopRepeat] - playing the clip with the chosen + number of `repetitions`, each time jumping from the end of the clip + directly to its beginning,
+ [page:Animation THREE.LoopPingPong] - playing the clip with the chosen + number of `repetitions`, alternately playing forward and backward.

[property:Boolean paused]

- Setting `paused` to `true` pauses the execution of the action by setting the effective time scale - to `0`. Default is `false`.

+ Setting `paused` to `true` pauses the execution of the action by setting + the effective time scale to `0`. Default is `false`.

[property:Number repetitions]

- The number of repetitions of the performed [page:AnimationClip] over the course of this action. - Can be set via [page:.setLoop setLoop]. Default is `Infinity`.

+ The number of repetitions of the performed [page:AnimationClip] over the + course of this action. Can be set via [page:.setLoop setLoop]. Default is + `Infinity`.

Setting this number has no effect, if the [page:.loop loop mode] is set to [page:Animation THREE.LoopOnce].

@@ -103,93 +116,102 @@

[property:Number time]

The local time of this action (in seconds, starting with `0`).

- The value gets clamped or wrapped to `0...clip.duration` (according to the loop state). It can be - scaled relatively to the global mixer time by changing [page:.timeScale timeScale] (using - [page:.setEffectiveTimeScale setEffectiveTimeScale] or [page:.setDuration setDuration]).
+ The value gets clamped or wrapped to `0...clip.duration` (according to the + loop state). It can be scaled relatively to the global mixer time by + changing [page:.timeScale timeScale] (using [page:.setEffectiveTimeScale setEffectiveTimeScale] or [page:.setDuration setDuration]).

[property:Number timeScale]

- Scaling factor for the [page:.time time]. A value of `0` causes the animation to pause. Negative - values cause the animation to play backwards. Default is `1`.

+ Scaling factor for the [page:.time time]. A value of `0` causes the + animation to pause. Negative values cause the animation to play backwards. + Default is `1`.

Properties/methods concerning `timeScale` (respectively `time`) are: [page:.getEffectiveTimeScale getEffectiveTimeScale], [page:.halt halt], [page:.paused paused], [page:.setDuration setDuration], - [page:.setEffectiveTimeScale setEffectiveTimeScale], - [page:.stopWarping stopWarping], - [page:.syncWith syncWith], + [page:.setEffectiveTimeScale setEffectiveTimeScale], + [page:.stopWarping stopWarping], + [page:.syncWith syncWith], [page:.warp warp].

[property:Number weight]

- The degree of influence of this action (in the interval `[0, 1]`). Values between `0` (no impact) - and 1 (full impact) can be used to blend between several actions. Default is `1`.

- Properties/methods concerning `weight` are: - [page:.crossFadeFrom crossFadeFrom], - [page:.crossFadeTo crossFadeTo], + The degree of influence of this action (in the interval `[0, 1]`). Values + between `0` (no impact) and 1 (full impact) can be used to blend between + several actions. Default is `1`.

+ Properties/methods concerning `weight` are: + [page:.crossFadeFrom crossFadeFrom], + [page:.crossFadeTo crossFadeTo], [page:.enabled enabled], [page:.fadeIn fadeIn], - [page:.fadeOut fadeOut], - [page:.getEffectiveWeight getEffectiveWeight], + [page:.fadeOut fadeOut], + [page:.getEffectiveWeight getEffectiveWeight], [page:.setEffectiveWeight setEffectiveWeight], [page:.stopFading stopFading].

[property:Boolean zeroSlopeAtEnd]

- Enables smooth interpolation without separate clips for start, loop and end. Default is `true`. + Enables smooth interpolation without separate clips for start, loop and + end. Default is `true`.

[property:Boolean zeroSlopeAtStart]

- Enables smooth interpolation without separate clips for start, loop and end. Default is `true`. + Enables smooth interpolation without separate clips for start, loop and + end. Default is `true`.

-

Methods

- -

[method:this crossFadeFrom]( [param:AnimationAction fadeOutAction], [param:Number durationInSeconds], [param:Boolean warpBoolean] )

+

+ [method:this crossFadeFrom]( [param:AnimationAction fadeOutAction], [param:Number durationInSeconds], [param:Boolean warpBoolean] ) +

- Causes this action to [page:.fadeIn fade in], fading out another action simultaneously, within - the passed time interval. This method can be chained.

- - If warpBoolean is true, additional [page:.warp warping] (gradually changes of the time scales) - will be applied.

+ Causes this action to [page:.fadeIn fade in], fading out another action + simultaneously, within the passed time interval. This method can be + chained.

- Note: Like with `fadeIn`/`fadeOut`, the fading starts/ends with a weight of 1. + If warpBoolean is true, additional [page:.warp warping] (gradually changes + of the time scales) will be applied.

+ Note: Like with `fadeIn`/`fadeOut`, the fading starts/ends with a weight + of 1.

-

[method:this crossFadeTo]( [param:AnimationAction fadeInAction], [param:Number durationInSeconds], [param:Boolean warpBoolean] )

+

+ [method:this crossFadeTo]( [param:AnimationAction fadeInAction], [param:Number durationInSeconds], [param:Boolean warpBoolean] ) +

- Causes this action to [page:.fadeOut fade out], fading in another action simultaneously, within - the passed time interval. This method can be chained.

- If warpBoolean is true, additional [page:.warp warping] (gradually changes of the time scales) - will be applied.

+ Causes this action to [page:.fadeOut fade out], fading in another action + simultaneously, within the passed time interval. This method can be + chained.

+ If warpBoolean is true, additional [page:.warp warping] (gradually changes + of the time scales) will be applied.

- Note: Like with `fadeIn`/`fadeOut`, the fading starts/ends with a weight of 1. + Note: Like with `fadeIn`/`fadeOut`, the fading starts/ends with a weight + of 1.

[method:this fadeIn]( [param:Number durationInSeconds] )

- Increases the [page:.weight weight] of this action gradually from `0` to `1`, within the passed time - interval. This method can be chained. + Increases the [page:.weight weight] of this action gradually from `0` to + `1`, within the passed time interval. This method can be chained.

[method:this fadeOut]( [param:Number durationInSeconds] )

- Decreases the [page:.weight weight] of this action gradually from `1` to `0`, within the passed time - interval. This method can be chained. + Decreases the [page:.weight weight] of this action gradually from `1` to + `0`, within the passed time interval. This method can be chained.

[method:Number getEffectiveTimeScale]()

- Returns the effective time scale (considering the current states of warping and - [page:.paused paused]). + Returns the effective time scale (considering the current states of + warping and [page:.paused paused]).

[method:Number getEffectiveWeight]()

@@ -199,114 +221,117 @@

[method:Number getEffectiveWeight]()

[method:AnimationClip getClip]()

-

- Returns the clip which holds the animation data for this action. -

+

Returns the clip which holds the animation data for this action.

[method:AnimationMixer getMixer]()

-

- Returns the mixer which is responsible for playing this action. -

+

Returns the mixer which is responsible for playing this action.

[method:Object3D getRoot]()

-

- Returns the root object on which this action is performed. -

+

Returns the root object on which this action is performed.

[method:this halt]( [param:Number durationInSeconds] )

- Decelerates this animation's speed to `0` by decreasing [page:.timeScale timeScale] gradually - (starting from its current value), within the passed time interval. This method can be chained. + Decelerates this animation's speed to `0` by decreasing [page:.timeScale timeScale] gradually (starting from its current value), within the passed + time interval. This method can be chained.

[method:Boolean isRunning]()

Returns true if the action’s [page:.time time] is currently running.

- In addition to being activated in the mixer (see [page:.isScheduled isScheduled]) the following conditions must be fulfilled: - [page:.paused paused] is equal to false, [page:.enabled enabled] is equal to true, - [page:.timeScale timeScale] is different from `0`, and there is no scheduling for a delayed start - ([page:.startAt startAt]).

+ In addition to being activated in the mixer (see [page:.isScheduled isScheduled]) the following conditions must be fulfilled: [page:.paused paused] is equal to false, [page:.enabled enabled] is equal to true, + [page:.timeScale timeScale] is different from `0`, and there is no + scheduling for a delayed start ([page:.startAt startAt]).

- Note: `isRunning` being true doesn’t necessarily mean that the animation can actually be seen. - This is only the case, if [page:.weight weight] is additionally set to a non-zero value. + Note: `isRunning` being true doesn’t necessarily mean that the animation + can actually be seen. This is only the case, if [page:.weight weight] is + additionally set to a non-zero value.

[method:Boolean isScheduled]()

Returns true, if this action is activated in the mixer.

- Note: This doesn’t necessarily mean that the animation is actually running (compare the additional - conditions for [page:.isRunning isRunning]). + Note: This doesn’t necessarily mean that the animation is actually running + (compare the additional conditions for [page:.isRunning isRunning]).

[method:this play]()

Tells the mixer to activate the action. This method can be chained.

- Note: Activating this action doesn’t necessarily mean that the animation starts immediately: - If the action had already finished before (by reaching the end of its last loop), or if a time - for a delayed start has been set (via [page:.startAt startAt]), a [page:.reset reset] must be - executed first. Some other settings ([page:.paused paused]=true, [page:.enabled enabled]=false, - [page:.weight weight]=0, [page:.timeScale timeScale]=0) can prevent the animation from playing, - too. + Note: Activating this action doesn’t necessarily mean that the animation + starts immediately: If the action had already finished before (by reaching + the end of its last loop), or if a time for a delayed start has been set + (via [page:.startAt startAt]), a [page:.reset reset] must be executed + first. Some other settings ([page:.paused paused]=true, [page:.enabled enabled]=false, [page:.weight weight]=0, [page:.timeScale timeScale]=0) + can prevent the animation from playing, too.

[method:this reset]()

Resets the action. This method can be chained.

- This method sets [page:.paused paused] to false, [page:.enabled enabled] to true, - [page:.time time] to `0`, interrupts any scheduled fading and warping, and removes the internal - loop count and scheduling for delayed starting.

+ This method sets [page:.paused paused] to false, [page:.enabled enabled] + to true, [page:.time time] to `0`, interrupts any scheduled fading and + warping, and removes the internal loop count and scheduling for delayed + starting.

- Note: .`reset` is always called by [page:.stop stop], but .`reset` doesn’t call .`stop` itself. - This means: If you want both, resetting and stopping, don’t call .`reset`; call .`stop` instead. + Note: .`reset` is always called by [page:.stop stop], but .`reset` doesn’t + call .`stop` itself. This means: If you want both, resetting and stopping, + don’t call .`reset`; call .`stop` instead.

[method:this setDuration]( [param:Number durationInSeconds] )

- Sets the duration for a single loop of this action (by adjusting [page:.timeScale timeScale] - and stopping any scheduled warping). This method can be chained. + Sets the duration for a single loop of this action (by adjusting + [page:.timeScale timeScale] and stopping any scheduled warping). This + method can be chained.

[method:this setEffectiveTimeScale]( [param:Number timeScale] )

- Sets the [page:.timeScale timeScale] and stops any scheduled warping. This method can be chained.

+ Sets the [page:.timeScale timeScale] and stops any scheduled warping. This + method can be chained.

- If [page:.paused paused] is false, the effective time scale (an internal property) will also be set - to this value; otherwise the effective time scale (directly affecting the animation at - this moment) will be set to `0`.

+ If [page:.paused paused] is false, the effective time scale (an internal + property) will also be set to this value; otherwise the effective time + scale (directly affecting the animation at this moment) will be set to + `0`.

- Note: .`paused` will not be switched to `true` automatically, if .`timeScale` is set to `0` by - this method. + Note: .`paused` will not be switched to `true` automatically, if + .`timeScale` is set to `0` by this method.

[method:this setEffectiveWeight]( [param:Number weight] )

- Sets the [page:.weight weight] and stops any scheduled fading. This method can be chained.

+ Sets the [page:.weight weight] and stops any scheduled fading. This method + can be chained.

- If [page:.enabled enabled] is true, the effective weight (an internal property) will also be set - to this value; otherwise the effective weight (directly affecting the animation at this moment) - will be set to `0`.

+ If [page:.enabled enabled] is true, the effective weight (an internal + property) will also be set to this value; otherwise the effective weight + (directly affecting the animation at this moment) will be set to `0`.

- Note: .`enabled` will not be switched to `false` automatically, if .`weight` is set to `0` by - this method. + Note: .`enabled` will not be switched to `false` automatically, if + .`weight` is set to `0` by this method.

-

[method:this setLoop]( [param:Number loopMode], [param:Number repetitions] )

+

+ [method:this setLoop]( [param:Number loopMode], [param:Number repetitions]) +

- Sets the [page:.loop loop mode] and the number of [page:.repetitions repetitions]. This method - can be chained. + Sets the [page:.loop loop mode] and the number of [page:.repetitions repetitions]. This method can be chained.

[method:this startAt]( [param:Number startTimeInSeconds] )

- Defines the time for a delayed start (usually passed as [page:AnimationMixer.time] + - deltaTimeInSeconds). This method can be chained.

+ Defines the time for a delayed start (usually passed as + [page:AnimationMixer.time] + deltaTimeInSeconds). This method can be + chained.

- Note: The animation will only start at the given time, if .`startAt` is chained with - [page:.play play], or if the action has already been activated in the mixer (by a previous - call of .`play`, without stopping or resetting it in the meantime). + Note: The animation will only start at the given time, if .`startAt` is + chained with [page:.play play], or if the action has already been + activated in the mixer (by a previous call of .`play`, without stopping or + resetting it in the meantime).

[method:this stop]()

@@ -321,43 +346,47 @@

[method:this stop]()

[method:this stopFading]()

- Stops any scheduled [page:.fadeIn fading] which is applied to this action. This method can be - chained. + Stops any scheduled [page:.fadeIn fading] which is applied to this action. + This method can be chained.

[method:this stopWarping]()

- Stops any scheduled [page:.warp warping] which is applied to this action. This method can be - chained. + Stops any scheduled [page:.warp warping] which is applied to this action. + This method can be chained.

[method:this syncWith]( [param:AnimationAction otherAction] )

- Synchronizes this action with the passed other action. This method can be chained.

+ Synchronizes this action with the passed other action. This method can be + chained.

- Synchronizing is done by setting this action’s [page:.time time] and [page:.timeScale timeScale] values - to the corresponding values of the other action (stopping any scheduled warping).

+ Synchronizing is done by setting this action’s [page:.time time] and + [page:.timeScale timeScale] values to the corresponding values of the + other action (stopping any scheduled warping).

- Note: Future changes of the other action's `time` and `timeScale` will not be detected. + Note: Future changes of the other action's `time` and `timeScale` will not + be detected.

-

[method:this warp]( [param:Number startTimeScale], [param:Number endTimeScale], [param:Number durationInSeconds] )

+

+ [method:this warp]( [param:Number startTimeScale], [param:Number endTimeScale], [param:Number durationInSeconds] ) +

Changes the playback speed, within the passed time interval, by modifying - [page:.timeScale timeScale] gradually from `startTimeScale` to `endTimeScale`. This method can - be chained. + [page:.timeScale timeScale] gradually from `startTimeScale` to + `endTimeScale`. This method can be chained.

-

Events

-

- There are two events indicating when a single loop of the action respectively the entire action has finished. You can react to them with: + There are two events indicating when a single loop of the action + respectively the entire action has finished. You can react to them with:

- mixer.addEventListener( 'loop', function( e ) { …} ); // properties of e: type, action and loopDelta - mixer.addEventListener( 'finished', function( e ) { …} ); // properties of e: type, action and direction + mixer.addEventListener( 'loop', function( e ) { …} ); // properties of e: type, action and loopDelta + mixer.addEventListener( 'finished', function( e ) { …} ); // properties of e: type, action and direction

Source

diff --git a/docs/api/en/animation/AnimationClip.html b/docs/api/en/animation/AnimationClip.html index 389eeb4dcbdaa3..5ca2318547da9c 100644 --- a/docs/api/en/animation/AnimationClip.html +++ b/docs/api/en/animation/AnimationClip.html @@ -10,30 +10,33 @@

[name]

- An [name] is a reusable set of keyframe tracks which represent an animation.

- - For an overview of the different elements of the three.js animation system see the - "Animation System" article in the "Next Steps" section of the manual. + An [name] is a reusable set of keyframe tracks which represent an + animation.

+ For an overview of the different elements of the three.js animation system + see the "Animation System" article in the "Next Steps" section of the + manual.

-

Constructor

- -

[name]( [param:String name], [param:Number duration], [param:Array tracks] )

+

+ [name]( [param:String name], [param:Number duration], [param:Array tracks] ) +

[page:String name] - a name for this clip.
- [page:Number duration] - the duration of this clip (in seconds). If a negative value is passed, - the duration will be calculated from the passed `tracks` array.
+ [page:Number duration] - the duration of this clip (in seconds). If a + negative value is passed, the duration will be calculated from the passed + `tracks` array.
[page:Array tracks] - an array of [page:KeyframeTrack KeyframeTracks].
- [page:Number blendMode] - defines how the animation is blended/combined when two or more animations are simultaneously played.

- - - Note: Instead of instantiating an AnimationClip directly with the constructor, you can use one - of its static methods to create AnimationClips: from JSON ([page:.parse parse]), from morph - target sequences ([page:.CreateFromMorphTargetSequence CreateFromMorphTargetSequence], - [page:.CreateClipsFromMorphTargetSequences CreateClipsFromMorphTargetSequences]) or from - animation hierarchies ([page:.parseAnimation parseAnimation]) - if your model doesn't already + [page:Number blendMode] - defines how the animation is blended/combined + when two or more animations are simultaneously played.

+ + Note: Instead of instantiating an AnimationClip directly with the + constructor, you can use one of its static methods to create + AnimationClips: from JSON ([page:.parse parse]), from morph target + sequences ([page:.CreateFromMorphTargetSequence CreateFromMorphTargetSequence], + [page:.CreateClipsFromMorphTargetSequences CreateClipsFromMorphTargetSequences]) or from animation hierarchies + ([page:.parseAnimation parseAnimation]) - if your model doesn't already hold AnimationClips in its geometry's animations array.

@@ -41,14 +44,15 @@

Properties

[property:Number blendMode]

- Defines how the animation is blended/combined when two or more animations are simultaneously played. - Valid values are *NormalAnimationBlendMode* (default) and *AdditiveAnimationBlendMode*. + Defines how the animation is blended/combined when two or more animations + are simultaneously played. Valid values are *NormalAnimationBlendMode* + (default) and *AdditiveAnimationBlendMode*.

[property:Number duration]

- The duration of this clip (in seconds). This can be calculated from the [page:.tracks tracks] - array via [page:.resetDuration resetDuration]. + The duration of this clip (in seconds). This can be calculated from the + [page:.tracks tracks] array via [page:.resetDuration resetDuration].

[property:String name]

@@ -58,95 +62,87 @@

[property:String name]

[property:Array tracks]

- An array containing a [page:KeyframeTrack] for each property that are animated by this clip. + An array containing a [page:KeyframeTrack] for each property that are + animated by this clip.

[property:String uuid]

- The [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this clip instance. - It gets automatically assigned and shouldn't be edited. + The [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] + of this clip instance. It gets automatically assigned and shouldn't be + edited.

-

Methods

-

[method:AnimationClip clone]()

-

- Returns a copy of this clip. -

+

Returns a copy of this clip.

[method:this optimize]()

- Optimizes each track by removing equivalent sequential keys (which are common in morph target - sequences). + Optimizes each track by removing equivalent sequential keys (which are + common in morph target sequences).

[method:this resetDuration]()

- Sets the [page:.duration duration] of the clip to the duration of its longest - [page:KeyframeTrack]. + Sets the [page:.duration duration] of the clip to the duration of its + longest [page:KeyframeTrack].

[method:Object toJSON]()

-

- Returns a JSON object representing the serialized animation clip. -

+

Returns a JSON object representing the serialized animation clip.

[method:this trim]()

-

- Trims all tracks to the clip's duration. -

+

Trims all tracks to the clip's duration.

[method:Boolean validate]()

- Performs minimal validation on each track in the clip. Returns true if all tracks are valid. + Performs minimal validation on each track in the clip. Returns true if all + tracks are valid.

-

Static Methods

[method:Array CreateClipsFromMorphTargetSequences]( [param:String name], [param:Array morphTargetSequence], [param:Number fps], [param:Boolean noLoop] )

- Returns an array of new AnimationClips created from the morph - target sequences of a geometry, trying to sort morph target names into animation-group-based - patterns like "Walk_001, Walk_002, Run_001, Run_002 ...". + Returns an array of new AnimationClips created from the morph target + sequences of a geometry, trying to sort morph target names into + animation-group-based patterns like "Walk_001, Walk_002, Run_001, Run_002...".

-

[method:AnimationClip CreateFromMorphTargetSequence]( [param:String name], [param:Array morphTargetSequence], [param:Number fps], [param:Boolean noLoop] )

+

[method:AnimationClip CreateFromMorphTargetSequence]( [param:String name], [param:Array morphTargetSequence], [param:Number fps], [param:Boolean noLoop] ) +

- Returns a new AnimationClip from the passed morph targets array of a geometry, taking a name and the number of frames per second.

+ Returns a new AnimationClip from the passed morph targets array of a + geometry, taking a name and the number of frames per second.

- Note: The fps parameter is required, but the animation speed can be overridden in an - `AnimationAction` via [page:AnimationAction.setDuration animationAction.setDuration]. + Note: The fps parameter is required, but the animation speed can be + overridden in an `AnimationAction` via [page:AnimationAction.setDuration animationAction.setDuration].

-

[method:AnimationClip findByName]( [param:Object objectOrClipArray], [param:String name] )

+

[method:AnimationClip findByName]( [param:Object objectOrClipArray], [param:String name] ) +

- Searches for an AnimationClip by name, taking as its first parameter either an array of - AnimationClips, or a mesh or geometry that contains an array named "animations". + Searches for an AnimationClip by name, taking as its first parameter + either an array of AnimationClips, or a mesh or geometry that contains an + array named "animations".

[method:AnimationClip parse]( [param:Object json] )

-

- Parses a JSON representation of a clip and returns an AnimationClip. -

+

Parses a JSON representation of a clip and returns an AnimationClip.

-

[method:AnimationClip parseAnimation]( [param:Object animation], [param:Array bones] )

-

- Parses the animation.hierarchy format and returns an AnimationClip. -

+

+ [method:AnimationClip parseAnimation]( [param:Object animation], [param:Array bones] ) +

+

Parses the animation.hierarchy format and returns an AnimationClip.

[method:Object toJSON]( [param:AnimationClip clip] )

-

- Takes an AnimationClip and returns a JSON object. -

- +

Takes an AnimationClip and returns a JSON object.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/AnimationMixer.html b/docs/api/en/animation/AnimationMixer.html index 8a2405830b4004..b9b6d9b0be3a03 100644 --- a/docs/api/en/animation/AnimationMixer.html +++ b/docs/api/en/animation/AnimationMixer.html @@ -10,107 +10,110 @@

[name]

- The AnimationMixer is a player for animations on a particular object in the scene. When - multiple objects in the scene are animated independently, one AnimationMixer may be used for - each object.

+ The AnimationMixer is a player for animations on a particular object in + the scene. When multiple objects in the scene are animated independently, + one AnimationMixer may be used for each object.

- For an overview of the different elements of the three.js animation system see the - "Animation System" article in the "Next Steps" section of the manual. + For an overview of the different elements of the three.js animation system + see the "Animation System" article in the "Next Steps" section of the + manual.

-

Constructor

-

[name]( [param:Object3D rootObject] )

- [page:Object3D rootObject] - the object whose animations shall be played by this mixer.
+ [page:Object3D rootObject] - the object whose animations shall be played + by this mixer.

-

Properties

-

[property:Number time]

- The global mixer time (in seconds; starting with `0` on the mixer's creation). + The global mixer time (in seconds; starting with `0` on the mixer's + creation).

[property:Number timeScale]

A scaling factor for the global [page:.time mixer time].

- Note: Setting the mixer's timeScale to `0` and later back to `1` is a possibility to pause/unpause - all actions that are controlled by this mixer. + Note: Setting the mixer's timeScale to `0` and later back to `1` is a + possibility to pause/unpause all actions that are controlled by this + mixer.

-

Methods

- -

[method:AnimationAction clipAction]([param:AnimationClip clip], [param:Object3D optionalRoot])

+

[method:AnimationAction clipAction]([param:AnimationClip clip], [param:Object3D optionalRoot]) +

- Returns an [page:AnimationAction] for the passed clip, optionally using a root object different - from the mixer's default root. The first parameter can be either an [page:AnimationClip] object - or the name of an AnimationClip.

- - If an action fitting the clip and root parameters doesn't yet exist, it will be created by - this method. Calling this method several times with the same clip and root parameters always - returns the same clip instance. + Returns an [page:AnimationAction] for the passed clip, optionally using a + root object different from the mixer's default root. The first parameter + can be either an [page:AnimationClip] object or the name of an + AnimationClip.

+ + If an action fitting the clip and root parameters doesn't yet exist, it + will be created by this method. Calling this method several times with the + same clip and root parameters always returns the same clip instance.

-

[method:AnimationAction existingAction]([param:AnimationClip clip], [param:Object3D optionalRoot])

+

[method:AnimationAction existingAction]([param:AnimationClip clip], [param:Object3D optionalRoot]) +

- Returns an existing [page:AnimationAction] for the passed clip, optionally using a root object - different from the mixer's default root.

+ Returns an existing [page:AnimationAction] for the passed clip, optionally + using a root object different from the mixer's default root.

- The first parameter can be either an [page:AnimationClip] object or the name of an AnimationClip. + The first parameter can be either an [page:AnimationClip] object or the + name of an AnimationClip.

[method:Object3D getRoot]()

-

- Returns this mixer's root object. -

+

Returns this mixer's root object.

[method:this stopAllAction]()

-

- Deactivates all previously scheduled actions on this mixer. -

+

Deactivates all previously scheduled actions on this mixer.

-

[method:this update]([param:Number deltaTimeInSeconds])

+

[method:this update]([param:Number deltaTimeInSeconds])

Advances the global mixer time and updates the animation.

This is usually done in the render loop, passing [page:Clock.getDelta clock.getDelta] scaled by the mixer's [page:.timeScale timeScale].

-

[method:this setTime]([param:Number timeInSeconds])

+

[method:this setTime]([param:Number timeInSeconds])

- Sets the global mixer to a specific time and updates the animation accordingly.

+ Sets the global mixer to a specific time and updates the animation + accordingly.

- This is useful when you need to jump to an exact time in an animation. The input parameter will be scaled by the mixer's [page:.timeScale timeScale]. + This is useful when you need to jump to an exact time in an animation. The + input parameter will be scaled by the mixer's [page:.timeScale timeScale].

[method:undefined uncacheClip]([param:AnimationClip clip])

- Deallocates all memory resources for a clip. Before using this method make sure to call [page:AnimationAction.stop]() for all related actions. + Deallocates all memory resources for a clip. Before using this method make + sure to call [page:AnimationAction.stop]() for all related actions.

-

[method:undefined uncacheRoot]([param:Object3D root])

+

[method:undefined uncacheRoot]([param:Object3D root])

- Deallocates all memory resources for a root object. Before using this method make sure to call [page:AnimationAction.stop]() for all related actions. + Deallocates all memory resources for a root object. Before using this + method make sure to call [page:AnimationAction.stop]() for all related + actions.

-

[method:undefined uncacheAction]([param:AnimationClip clip], [param:Object3D optionalRoot])

+

[method:undefined uncacheAction]([param:AnimationClip clip], [param:Object3D optionalRoot]) +

- Deallocates all memory resources for an action. Before using this method make sure to call [page:AnimationAction.stop]() to deactivate the action. + Deallocates all memory resources for an action. Before using this method + make sure to call [page:AnimationAction.stop]() to deactivate the action.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/AnimationObjectGroup.html b/docs/api/en/animation/AnimationObjectGroup.html index 251fb1d3571108..4699fe4cecd7b7 100644 --- a/docs/api/en/animation/AnimationObjectGroup.html +++ b/docs/api/en/animation/AnimationObjectGroup.html @@ -9,81 +9,82 @@

[name]

-

A group of objects that receives a shared animation state.

+

+ A group of objects that receives a shared animation state.

- For an overview of the different elements of the three.js animation system see the - "Animation System" article in the "Next Steps" section of the manual. + For an overview of the different elements of the three.js animation system + see the "Animation System" article in the "Next Steps" section of the + manual.

Usage:

- Add objects you would otherwise pass as 'root' to the constructor or the [page:AnimationMixer.clipAction clipAction] - method of [page:AnimationMixer AnimationMixer] and instead pass this object as 'root'.

+ Add objects you would otherwise pass as 'root' to the constructor or the + [page:AnimationMixer.clipAction clipAction] method of [page:AnimationMixer AnimationMixer] and instead pass this object as 'root'.

- Note that objects of this class appear as one object to the mixer, - so cache control of the individual objects must be done on the group. + Note that objects of this class appear as one object to the mixer, so + cache control of the individual objects must be done on the group.

-

Limitations

- The animated properties must be compatible among all objects in the group.

+ The animated properties must be compatible among all objects in the + group.

- A single property can either be controlled through a target group or directly, but not both. + A single property can either be controlled through a target group or + directly, but not both.

-

Constructor

-

[name]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ... )

+

+ [name]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ...) +

- [page:Object obj] - an arbitrary number of meshes that share the same animation state. + [page:Object obj] - an arbitrary number of meshes that share the same + animation state.

Properties

[property:Boolean isAnimationObjectGroup]

-

- Read-only flag to check if a given object is of type [name]. -

- +

Read-only flag to check if a given object is of type [name].

[property:Object stats]

- An object that contains some informations of this `AnimationObjectGroup` (total number, number - in use, number of bindings per object) + An object that contains some informations of this `AnimationObjectGroup` + (total number, number in use, number of bindings per object)

[property:String uuid]

- The [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this - `AnimationObjectGroup`. It gets automatically assigned and shouldn't be edited. + The [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] + of this `AnimationObjectGroup`. It gets automatically assigned and + shouldn't be edited.

-

Methods

+

[method:undefined add]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ... ) +

+

Adds an arbitrary number of objects to this `AnimationObjectGroup`.

-

[method:undefined add]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ... )

-

- Adds an arbitrary number of objects to this `AnimationObjectGroup`. -

- -

[method:undefined remove]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ... )

+

[method:undefined remove]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ... ) +

Removes an arbitrary number of objects from this `AnimationObjectGroup`.

-

[method:undefined uncache]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ... )

+

[method:undefined uncache]( [param:Object obj1], [param:Object obj2], [param:Object obj3], ... ) +

- Deallocates all memory resources for the passed objects of this `AnimationObjectGroup`. + Deallocates all memory resources for the passed objects of this + `AnimationObjectGroup`.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/AnimationUtils.html b/docs/api/en/animation/AnimationUtils.html index dc484dd9855988..f29efdb7f6434e 100644 --- a/docs/api/en/animation/AnimationUtils.html +++ b/docs/api/en/animation/AnimationUtils.html @@ -10,56 +10,40 @@

[name]

- An object with various functions to assist with animations, used internally. + An object with various functions to assist with animations, used + internally.

-

Methods

-

[method:Array arraySlice]( array, from, to )

- This is the same as Array.prototype.slice, but also works on typed arrays. + This is the same as Array.prototype.slice, but also works on typed arrays.

[method:Array convertArray]( array, type, forceClone )

-

- Converts an array to a specific type. -

+

Converts an array to a specific type.

[method:Array flattenJSON]( jsonKeys, times, values, valuePropertyName )

-

- Used for parsing AOS keyframe formats. -

+

Used for parsing AOS keyframe formats.

[method:Array getKeyframeOrder]( times )

-

- Returns an array by which times and values can be sorted. -

+

Returns an array by which times and values can be sorted.

[method:Boolean isTypedArray]( object )

-

- Returns `true` if the object is a typed array. -

+

Returns `true` if the object is a typed array.

[method:AnimationClip makeClipAdditive]( [param:AnimationClip targetClip], [param:Number referenceFrame], [param:AnimationClip referenceClip], [param:Number fps] )

-

- Converts the keyframes of the given animation clip to an additive format. -

+

Converts the keyframes of the given animation clip to an additive format.

[method:Array sortedArray]( values, stride, order )

-

- Sorts the array previously returned by [page:AnimationUtils.getKeyframeOrder getKeyframeOrder]. -

+

Sorts the array previously returned by [page:AnimationUtils.getKeyframeOrder getKeyframeOrder].

[method:AnimationClip subclip]( [param:AnimationClip clip], [param:String name], [param:Number startFrame], [param:Number endFrame], [param:Number fps] )

-

- Creates a new clip, containing only the segment of the original clip between the given frames. -

- -

Source

+

Creates a new clip, containing only the segment of the original clip between the given frames.

+

Source

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/KeyframeTrack.html b/docs/api/en/animation/KeyframeTrack.html index bc2b4660a35d7a..257def54b0a9da 100644 --- a/docs/api/en/animation/KeyframeTrack.html +++ b/docs/api/en/animation/KeyframeTrack.html @@ -7,43 +7,47 @@ -

[name]

- A KeyframeTrack is a timed sequence of [link:https://en.wikipedia.org/wiki/Key_frame keyframes], - which are composed of lists of times and related values, and which are used to animate a - specific property of an object. + A KeyframeTrack is a timed sequence of + [link:https://en.wikipedia.org/wiki/Key_frame keyframes], which are + composed of lists of times and related values, and which are used to + animate a specific property of an object.

- For an overview of the different elements of the three.js animation system see the - "Animation System" article in the "Next Steps" section of the manual. + For an overview of the different elements of the three.js animation system + see the "Animation System" article in the "Next Steps" section of the + manual.

In contrast to the animation hierarchy of the - [link:https://github.com/mrdoob/three.js/wiki/JSON-Model-format-3 JSON model format] a - `KeyframeTrack` doesn't store its single keyframes as objects in a "keys" array (holding the - times and the values for each frame together in one place). + [link:https://github.com/mrdoob/three.js/wiki/JSON-Model-format-3 JSON model format] a `KeyframeTrack` doesn't store its single keyframes as + objects in a "keys" array (holding the times and the values for each frame + together in one place).

- Instead of this there are always two arrays in a `KeyframeTrack`: the [page:.times times] array - stores the time values for all keyframes of this track in sequential order, and the - [page:.values values] array contains the corresponding changing values of the animated property. + Instead of this there are always two arrays in a `KeyframeTrack`: the + [page:.times times] array stores the time values for all keyframes of this + track in sequential order, and the [page:.values values] array contains + the corresponding changing values of the animated property.

- A single value, belonging to a certain point of time, can not only be a simple number, but (for - example) a vector (if a position is animated) or a quaternion (if a rotation is animated). For - this reason the values array (which is a flat array, too) might be three or four times as long as the + A single value, belonging to a certain point of time, can not only be a + simple number, but (for example) a vector (if a position is animated) or a + quaternion (if a rotation is animated). For this reason the values array + (which is a flat array, too) might be three or four times as long as the times array.

- Corresponding to the different possible types of animated values there are several subclasses of - `KeyframeTrack`, inheriting the most properties and methods: + Corresponding to the different possible types of animated values there are + several subclasses of `KeyframeTrack`, inheriting the most properties and + methods:

    @@ -56,207 +60,205 @@

    [name]

- Some examples of how to manually create [page:AnimationClip AnimationClips] with different sorts - of KeyframeTracks can be found in the [link:https://threejs.org/examples/jsm/animation/AnimationClipCreator.js AnimationClipCreator] - file. + Some examples of how to manually create [page:AnimationClip AnimationClips] with different sorts of KeyframeTracks can be found in the + [link:https://threejs.org/examples/jsm/animation/AnimationClipCreator.js AnimationClipCreator] file.

- Since explicit values are only specified for the discrete points of time stored in the times array, - all values in between have to be interpolated. + Since explicit values are only specified for the discrete points of time + stored in the times array, all values in between have to be interpolated.

- The track's name is important for the connection of this track with a specific property of the - animated node (done by [page:PropertyBinding]). + The track's name is important for the connection of this track with a + specific property of the animated node (done by [page:PropertyBinding]).

-

Constructor

- -

[name]( [param:String name], [param:Array times], [param:Array values], [param:Constant interpolation] )

+

[name]( [param:String name], [param:Array times], [param:Array values], [param:Constant interpolation] ) +

[page:String name] - the identifier for the `KeyframeTrack`.
[page:Array times] - an array of keyframe times, converted internally to a [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array].
- [page:Array values] - an array with the values related to the times array, converted internally to a + [page:Array values] - an array with the values related to the times array, + converted internally to a [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array].
[page:Constant interpolation] - the type of interpolation to use. See - [page:Animation Animation Constants] for possible values. Default is [page:Animation InterpolateLinear]. + [page:Animation Animation Constants] for possible values. Default is + [page:Animation InterpolateLinear].

-

Properties

-

[property:String name]

- The track's name can refer to morph targets or [page:SkinnedMesh bones] or possibly other values within an animated object. See - [page:PropertyBinding.parseTrackName] for the forms of strings that can be parsed for property - binding: + The track's name can refer to morph targets or [page:SkinnedMesh bones] or + possibly other values within an animated object. See + [page:PropertyBinding.parseTrackName] for the forms of strings that can be + parsed for property binding:

- The name can specify the node either using its name or its uuid (although it needs to be in the - subtree of the scene graph node passed into the mixer). Or, if the track name starts with a dot, - the track applies to the root node that was passed into the mixer. + The name can specify the node either using its name or its uuid (although + it needs to be in the subtree of the scene graph node passed into the + mixer). Or, if the track name starts with a dot, the track applies to the + root node that was passed into the mixer.

- Usually after the node a property will be specified directly. But you can also specify a - subproperty, such as .rotation[x], if you just want to drive the X component of the rotation - via a float track. + Usually after the node a property will be specified directly. But you can + also specify a subproperty, such as .rotation[x], if you just want to + drive the X component of the rotation via a float track.

- You can also specify bones or multimaterials by using an object name, for example: - .bones[R_hand].scale; the red channel of the diffuse color of the fourth material in a - materials array - as a further example - can be accessed with .materials[3].diffuse[r]. + You can also specify bones or multimaterials by using an object name, for + example: .bones[R_hand].scale; the red channel of the diffuse color of the + fourth material in a materials array - as a further example - can be + accessed with .materials[3].diffuse[r].

- PropertyBinding will also resolve morph target names, for example: .morphTargetInfluences[run]. + PropertyBinding will also resolve morph target names, for example: + .morphTargetInfluences[run].

- Note: The track's name does not necessarily have to be unique. Multiple tracks can drive the same - property. The result should be based on a weighted blend between the multiple tracks according to - the weights of their respective actions. + Note: The track's name does not necessarily have to be unique. Multiple + tracks can drive the same property. The result should be based on a + weighted blend between the multiple tracks according to the weights of + their respective actions.

[property:Float32Array times]

- A [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], - converted from the times array which is passed in the constructor. + A + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], converted from the times array which is passed in the + constructor.

[property:Float32Array values]

- A [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], - converted from the values array which is passed in the constructor. + A + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], converted from the values array which is passed in the + constructor.

[property:Constant DefaultInterpolation]

-

- The default interpolation type: [page:Animation InterpolateLinear]. -

+

The default interpolation type: [page:Animation InterpolateLinear].

[property:Constant TimeBufferType ]

- [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], - the type of the buffer internally used for the times. + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], the type of the buffer internally used for the times.

[property:Constant ValueBufferType ]

- [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], - the type of the buffer internally used for the values. + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array Float32Array], the type of the buffer internally used for the values.

-

Methods

-

[method:KeyframeTrack clone]()

-

- Returns a copy of this track. -

+

Returns a copy of this track.

[method:Interpolant createInterpolant]()

- Creates a [page:LinearInterpolant LinearInterpolant], [page:CubicInterpolant CubicInterpolant] - or [page:DiscreteInterpolant DiscreteInterpolant], depending on the value of the interpolation + Creates a [page:LinearInterpolant LinearInterpolant], + [page:CubicInterpolant CubicInterpolant] or [page:DiscreteInterpolant DiscreteInterpolant], depending on the value of the interpolation parameter passed in the constructor.

[method:Interpolant getInterpolation]()

-

- Returns the interpolation type. -

+

Returns the interpolation type.

[method:Number getValueSize]()

- Returns the size of each value (that is the length of the [page:.values values] array divided - by the length of the [page:.times times] array). + Returns the size of each value (that is the length of the [page:.values values] array divided by the length of the [page:.times times] array).

-

[method:DiscreteInterpolant InterpolantFactoryMethodDiscrete]( [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array result] )

+

+ [method:DiscreteInterpolant InterpolantFactoryMethodDiscrete]( [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array result] ) +

Creates a new [page:DiscreteInterpolant DiscreteInterpolant] from the - [page:KeyframeTrack.times times] and [page:KeyframeTrack.times values]. A Float32Array can be - passed which will receive the results. Otherwise a new array with the appropriate size will be - created automatically. + [page:KeyframeTrack.times times] and [page:KeyframeTrack.times values]. A + Float32Array can be passed which will receive the results. Otherwise a new + array with the appropriate size will be created automatically.

-

[method:LinearInterpolant InterpolantFactoryMethodLinear]( [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array result] )

+

+ [method:LinearInterpolant InterpolantFactoryMethodLinear]( [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array result] ) +

Creates a new [page:LinearInterpolant LinearInterpolant] from the - [page:KeyframeTrack.times times] and [page:KeyframeTrack.times values]. A Float32Array can be - passed which will receive the results. Otherwise a new array with the appropriate size will be - created automatically. + [page:KeyframeTrack.times times] and [page:KeyframeTrack.times values]. A + Float32Array can be passed which will receive the results. Otherwise a new + array with the appropriate size will be created automatically.

-

[method:CubicInterpolant InterpolantFactoryMethodSmooth]( [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array result] )

+

+ [method:CubicInterpolant InterpolantFactoryMethodSmooth]( [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array result] ) +

Create a new [page:CubicInterpolant CubicInterpolant] from the - [page:KeyframeTrack.times times] and [page:KeyframeTrack.times values]. A Float32Array can be - passed which will receive the results. Otherwise a new array with the appropriate size will be - created automatically. + [page:KeyframeTrack.times times] and [page:KeyframeTrack.times values]. A + Float32Array can be passed which will receive the results. Otherwise a new + array with the appropriate size will be created automatically.

[method:this optimize]()

- Removes equivalent sequential keys, which are common in morph target sequences. + Removes equivalent sequential keys, which are common in morph target + sequences.

[method:this scale]()

Scales all keyframe times by a factor.

- Note: This is useful, for example, for conversions to a certain rate of frames per seconds (as it - is done internally by + Note: This is useful, for example, for conversions to a certain rate of + frames per seconds (as it is done internally by [page:AnimationClip.CreateFromMorphTargetSequence animationClip.CreateFromMorphTargetSequence]).

-

[method:this setInterpolation]( [param:Constant interpolationType] )

+

+ [method:this setInterpolation]( [param:Constant interpolationType] ) +

- Sets the interpolation type. See [page:Animation Animation Constants] for choices. + Sets the interpolation type. See [page:Animation Animation Constants] for + choices.

[method:this shift]( [param:Number timeOffsetInSeconds] )

-

- Moves all keyframes either forward or backward in time. -

- +

Moves all keyframes either forward or backward in time.

-

[method:this trim]( [param:Number startTimeInSeconds], [param:Number endTimeInSeconds] )

+

+ [method:this trim]( [param:Number startTimeInSeconds], [param:Number endTimeInSeconds] ) +

- Removes keyframes before `startTime` and after `endTime`, - without changing any values within the range [`startTime`, `endTime`]. + Removes keyframes before `startTime` and after `endTime`, without changing + any values within the range [`startTime`, `endTime`].

[method:Boolean validate]()

-

- Performs minimal validation on the tracks. Returns true if valid. -

+

Performs minimal validation on the tracks. Returns true if valid.

- This method logs errors to the console, if a track is empty, if the [page:.valueSize value size] is not valid, if an item - in the [page:.times times] or [page:.values values] array is not a valid number or if the items in the `times` array are out of order. + This method logs errors to the console, if a track is empty, if the + [page:.valueSize value size] is not valid, if an item in the [page:.times times] or [page:.values values] array is not a valid number or if the + items in the `times` array are out of order.

Static Methods

[method:JSON toJSON]( [param:KeyframeTrack track] )

-

- Converts the track to JSON. -

- +

Converts the track to JSON.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/PropertyBinding.html b/docs/api/en/animation/PropertyBinding.html index d3986ec4b72da4..4750bf194517c3 100644 --- a/docs/api/en/animation/PropertyBinding.html +++ b/docs/api/en/animation/PropertyBinding.html @@ -10,94 +10,56 @@

[name]

- This holds a reference to a real property in the scene graph; used internally. + This holds a reference to a real property in the scene graph; used + internally.

-

Constructor

-

[name]( [param:Object3D rootNode], path, parsedPath )

-

- -- [page:Object3D rootNode]: - -- path - -- parsedPath (optional) - -

+

-- [page:Object3D rootNode]: -- path -- parsedPath (optional)

Properties

[property:Number path]

-

- -

[property:Number parsedPath]

-

- -

[property:Number node]

-

- -

[property:Number rootNode]

-

- -

[property:Object BindingType]

-

- -

[property:Object Versioning]

-

- -

[property:Array GetterByBindingType]

-

- -

[property:Array SetterByBindingTypeAndVersioning]

-

- -

- -

Methods

[method:undefined getValue]( [param:Array targetArray], [param:Number offset] )

-

-

[method:undefined setValue]( [param:Array sourceArray], [param:Number offset] )

-

-

[method:undefined bind]( )

- Create getter / setter pair for a property in the scene graph. Used internally by - [page:PropertyBinding.getValue getValue] and [page:PropertyBinding.setValue setValue]. + Create getter / setter pair for a property in the scene graph. Used + internally by [page:PropertyBinding.getValue getValue] and + [page:PropertyBinding.setValue setValue].

[method:undefined unbind]( )

-

- Unbind getter / setter pair for a property in the scene graph. -

+

Unbind getter / setter pair for a property in the scene graph.

[method:Constructor Composite]( targetGroup, path, optionalParsedPath )

-

- Create a new Composite PropertyBinding. -

+

Create a new Composite PropertyBinding.

[method:Constructor create]( root, path, parsedPath )

- Create a new Composite PropertyBinding (if root is an [page:AnimationObjectGroup]) or PropertyBinding. + Create a new Composite PropertyBinding (if root is an + [page:AnimationObjectGroup]) or PropertyBinding.

[method:Constructor parseTrackName]( trackName )

@@ -115,16 +77,10 @@

[method:Constructor parseTrackName]( trackName )

[method:Constructor findNode]( root, nodeName )

-

- Find a node in a node tree or [page:Skeleton Skeleton]. -

- - - +

Find a node in a node tree or [page:Skeleton Skeleton].

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/PropertyMixer.html b/docs/api/en/animation/PropertyMixer.html index fdfec0d54fd04c..4f832f0fc93e3f 100644 --- a/docs/api/en/animation/PropertyMixer.html +++ b/docs/api/en/animation/PropertyMixer.html @@ -10,13 +10,12 @@

[name]

- Buffered scene graph property that allows weighted accumulation; used internally. + Buffered scene graph property that allows weighted accumulation; used + internally.

-

Constructor

-

[name]( [param:PropertyBinding binding], [param:String typeName], [param:Number valueSize] )

-- binding
@@ -24,56 +23,42 @@

[name]( [param:PropertyBinding binding], [param:String typeName], [param:Num -- valueSize

-

Properties

-

[property:PropertyBinding binding]

-

- -

[property:TypedArray buffer]

Buffer with size [page:PropertyMixer valueSize] * 4.

This has the layout: [ incoming | accu0 | accu1 | orig ]

- Interpolators can use .buffer as their .result and the data then goes to 'incoming'. - 'accu0' and 'accu1' are used frame-interleaved for the cumulative result and - are compared to detect changes. 'orig' stores the original state of the property. + Interpolators can use .buffer as their .result and the data then goes to + 'incoming'. 'accu0' and 'accu1' are used frame-interleaved for the + cumulative result and are compared to detect changes. 'orig' stores the + original state of the property.

[property:Number cumulativeWeight]

-

- Default is `0`. -

+

Default is `0`.

[property:Number cumulativeWeightAdditive]

-

- Default is `0`. -

+

Default is `0`.

[property:Number valueSize]

-

- -

[property:Number referenceCount]

-

- Default is `0`. -

+

Default is `0`.

[property:Number useCount]

-

- Default is `0`. -

- +

Default is `0`.

Methods

- -

[method:undefined accumulate]( [param:Number accuIndex], [param:Number weight] )

+

+ [method:undefined accumulate]( [param:Number accuIndex], [param:Number weight] ) +

- Accumulate data in [page:PropertyMixer.buffer buffer][accuIndex] 'incoming' region into 'accu[i]'.
+ Accumulate data in [page:PropertyMixer.buffer buffer][accuIndex] + 'incoming' region into 'accu[i]'.
If weight is `0` this does nothing.

@@ -81,30 +66,25 @@

[method:undefined accumulate]( [param:Number accuIndex], [param:Number weigh

[method:undefined accumulateAdditive]( [param:Number weight] )

Accumulate data in the 'incoming' region into 'add'.
- If weight is `0` this does nothing.

-

[method:undefined apply]( [param:Number accuIndex] )

- Apply the state of [page:PropertyMixer.buffer buffer] 'accu[i]' to the binding when accus differ. + Apply the state of [page:PropertyMixer.buffer buffer] 'accu[i]' to the + binding when accus differ.

[method:undefined saveOriginalState]( )

-

- Remember the state of the bound property and copy it to both accus. -

+

Remember the state of the bound property and copy it to both accus.

-

[method:undefined restoreOriginalState]( )

+

[method:undefined restoreOriginalState]( )

Apply the state previously taken via 'saveOriginalState' to the binding.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/tracks/BooleanKeyframeTrack.html b/docs/api/en/animation/tracks/BooleanKeyframeTrack.html index b29e036c42adcc..af3d582f2bdc66 100644 --- a/docs/api/en/animation/tracks/BooleanKeyframeTrack.html +++ b/docs/api/en/animation/tracks/BooleanKeyframeTrack.html @@ -7,33 +7,26 @@ - [page:KeyframeTrack] →

[name]

-

- A Track of boolean keyframe values. -

- +

A Track of boolean keyframe values.

Constructor

- -

[name]( [param:String name], [param:Array times], [param:Array values] )

+

+ [name]( [param:String name], [param:Array times], [param:Array values] ) +

[page:String name] - (required) identifier for the KeyframeTrack.
[page:Array times] - (required) array of keyframe times.
[page:Array values] - values for the keyframes at the times specified.

-

Properties

- -

- See [page:KeyframeTrack] for inherited properties. -

+

See [page:KeyframeTrack] for inherited properties.

[property:Constant DefaultInterpolation]

@@ -42,36 +35,29 @@

[property:Constant DefaultInterpolation]

[property:Array ValueBufferType]

- A normal Array (no Float32Array in this case, unlike `ValueBufferType` of [page:KeyframeTrack]). + A normal Array (no Float32Array in this case, unlike `ValueBufferType` of + [page:KeyframeTrack]).

[property:String ValueTypeName]

-

- String 'bool'. -

- +

String 'bool'.

Methods

- -

- See [page:KeyframeTrack] for inherited methods. -

+

See [page:KeyframeTrack] for inherited methods.

[method:undefined InterpolantFactoryMethodLinear ]()

- The value of this method here is 'undefined', as it does not make sense for discrete properties. + The value of this method here is 'undefined', as it does not make sense + for discrete properties.

[method:undefined InterpolantFactoryMethodSmooth ]()

- The value of this method here is 'undefined', as it does not make sense for discrete properties. + The value of this method here is 'undefined', as it does not make sense + for discrete properties.

- -

Source

- -

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/tracks/ColorKeyframeTrack.html b/docs/api/en/animation/tracks/ColorKeyframeTrack.html index 6cd83fedb3b044..04b321eae0acb2 100644 --- a/docs/api/en/animation/tracks/ColorKeyframeTrack.html +++ b/docs/api/en/animation/tracks/ColorKeyframeTrack.html @@ -7,55 +7,44 @@ - [page:KeyframeTrack] →

[name]

A Track of keyframe values that represent color changes.

- The very basic implementation of this subclass has nothing special yet. However, this is the place - for color space parameterization. + The very basic implementation of this subclass has nothing special yet. + However, this is the place for color space parameterization.

-

Constructor

- -

[name]( [param:String name], [param:Array times], [param:Array values] )

+

+ [name]( [param:String name], [param:Array times], [param:Array values] ) +

[page:String name] - (required) identifier for the KeyframeTrack.
[page:Array times] - (required) array of keyframe times.
- [page:Array values] - values for the keyframes at the times specified, a flat array of color components between 0 and 1.
+ [page:Array values] - values for the keyframes at the times specified, a + flat array of color components between 0 and 1.
[page:Constant interpolation] - the type of interpolation to use. See [page:Animation Animation Constants] for possible values. Default is [page:Animation InterpolateLinear].

-

Properties

- -

- See [page:KeyframeTrack] for inherited properties. -

+

See [page:KeyframeTrack] for inherited properties.

[property:String ValueTypeName]

-

- String 'color'. -

- +

String 'color'.

Methods

- -

- See [page:KeyframeTrack] for inherited methods. -

+

See [page:KeyframeTrack] for inherited methods.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/tracks/NumberKeyframeTrack.html b/docs/api/en/animation/tracks/NumberKeyframeTrack.html index 8545f9dc2af32d..94b3fef4cf2001 100644 --- a/docs/api/en/animation/tracks/NumberKeyframeTrack.html +++ b/docs/api/en/animation/tracks/NumberKeyframeTrack.html @@ -7,20 +7,17 @@ - [page:KeyframeTrack] →

[name]

-

- A Track of numeric keyframe values. -

- +

A Track of numeric keyframe values.

Constructor

- -

[name]( [param:String name], [param:Array times], [param:Array values] )

+

+ [name]( [param:String name], [param:Array times], [param:Array values] ) +

[page:String name] - (required) identifier for the KeyframeTrack.
[page:Array times] - (required) array of keyframe times.
@@ -30,32 +27,19 @@

[name]( [param:String name], [param:Array times], [param:Array values] )

-

Properties

- -

- See [page:KeyframeTrack] for inherited properties. -

- +

See [page:KeyframeTrack] for inherited properties.

[property:String ValueTypeName]

-

- String 'number'. -

- +

String 'number'.

Methods

- -

- See [page:KeyframeTrack] for inherited methods. -

- +

See [page:KeyframeTrack] for inherited methods.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/tracks/QuaternionKeyframeTrack.html b/docs/api/en/animation/tracks/QuaternionKeyframeTrack.html index e65b893e6882e7..7f1b7a05512d81 100644 --- a/docs/api/en/animation/tracks/QuaternionKeyframeTrack.html +++ b/docs/api/en/animation/tracks/QuaternionKeyframeTrack.html @@ -7,36 +7,30 @@ - [page:KeyframeTrack] →

[name]

-

- A Track of quaternion keyframe values. -

- +

A Track of quaternion keyframe values.

Constructor

- -

[name]( [param:String name], [param:Array times], [param:Array values] )

+

+ [name]( [param:String name], [param:Array times], [param:Array values] ) +

[page:String name] (required) identifier for the KeyframeTrack.
[page:Array times] (required) array of keyframe times.
- [page:Array values] values for the keyframes at the times specified, a flat array of quaternion components.
+ [page:Array values] values for the keyframes at the times specified, a + flat array of quaternion components.
[page:Constant interpolation] the type of interpolation to use. See [page:Animation Animation Constants] for possible values. Default is [page:Animation InterpolateLinear].

-

Properties

- -

- See [page:KeyframeTrack] for inherited properties. -

+

See [page:KeyframeTrack] for inherited properties.

[property:Constant DefaultInterpolation]

@@ -44,29 +38,22 @@

[property:Constant DefaultInterpolation]

[property:String ValueTypeName]

-

- String 'quaternion'. -

- +

String 'quaternion'.

Methods

+

See [page:KeyframeTrack] for inherited methods.

-

- See [page:KeyframeTrack] for inherited methods. -

- -

[method:QuaternionLinearInterpolant InterpolantFactoryMethodLinear]()

+

+ [method:QuaternionLinearInterpolant InterpolantFactoryMethodLinear]() +

- Returns a new [page:QuaternionLinearInterpolant QuaternionLinearInterpolant] based on the - [page:KeyframeTrack.values values], [page:KeyframeTrack.times times] and + Returns a new [page:QuaternionLinearInterpolant QuaternionLinearInterpolant] based on the [page:KeyframeTrack.values values], [page:KeyframeTrack.times times] and [page:KeyframeTrack.valueSize valueSize] of the keyframes.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/animation/tracks/StringKeyframeTrack.html b/docs/api/en/animation/tracks/StringKeyframeTrack.html index ec208bc3fa1f19..8464687c2e6acd 100644 --- a/docs/api/en/animation/tracks/StringKeyframeTrack.html +++ b/docs/api/en/animation/tracks/StringKeyframeTrack.html @@ -1,26 +1,25 @@ + - + [page:KeyframeTrack] →

[name]

-

- A Track of string keyframe values. -

- +

A Track of string keyframe values.

Constructor

- -

[name]( [param:String name], [param:Array times], [param:Array values] )

+

+ [name]( [param:String name], [param:Array times], [param:Array values] ) +

[page:String name] - (required) identifier for the KeyframeTrack.
[page:Array times] - (required) array of keyframe times.
@@ -30,13 +29,9 @@

[name]( [param:String name], [param:Array times], [param:Array values] )

-

Properties

- -

- See [page:KeyframeTrack] for inherited properties. -

+

See [page:KeyframeTrack] for inherited properties.

[property:Constant DefaultInterpolation]

@@ -45,38 +40,34 @@

[property:Constant DefaultInterpolation]

[property:Array ValueBufferType]

- A normal Array (no Float32Array in this case, unlike `ValueBufferType` of [page:KeyframeTrack]). + A normal Array (no Float32Array in this case, unlike `ValueBufferType` of + [page:KeyframeTrack]).

[property:String ValueTypeName]

-

- String 'string'. -

- +

String 'string'.

Methods

- -

- See [page:KeyframeTrack] for inherited methods. -

+

See [page:KeyframeTrack] for inherited methods.

[method:undefined InterpolantFactoryMethodLinear]()

- The value of this method here is 'undefined', as it does not make sense for discrete properties. + The value of this method here is 'undefined', as it does not make sense + for discrete properties.

[method:undefined InterpolantFactoryMethodSmooth]()

- The value of this method here is 'undefined', as it does not make sense for discrete properties. + The value of this method here is 'undefined', as it does not make sense + for discrete properties.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

- + + \ No newline at end of file diff --git a/docs/api/en/animation/tracks/VectorKeyframeTrack.html b/docs/api/en/animation/tracks/VectorKeyframeTrack.html index d02e3531489933..7d88ab2b4f77cc 100644 --- a/docs/api/en/animation/tracks/VectorKeyframeTrack.html +++ b/docs/api/en/animation/tracks/VectorKeyframeTrack.html @@ -6,55 +6,42 @@ - + [page:KeyframeTrack] →

[name]

-

- A Track of vector keyframe values. -

- +

A Track of vector keyframe values.

Constructor

- -

[name]( [param:String name], [param:Array times], [param:Array values] )

+

+ [name]( [param:String name], [param:Array times], [param:Array values] ) +

[page:String name] - (required) identifier for the KeyframeTrack.
[page:Array times] - (required) array of keyframe times.
- [page:Array values] - values for the keyframes at the times specified, a flat array of vector components.
+ [page:Array values] - values for the keyframes at the times specified, a + flat array of vector components.
[page:Constant interpolation] - the type of interpolation to use. See [page:Animation Animation Constants] for possible values. Default is [page:Animation InterpolateLinear].

-

Properties

- -

- See [page:KeyframeTrack] for inherited properties. -

+

See [page:KeyframeTrack] for inherited properties.

[property:String ValueTypeName]

-

- String 'vector'. -

- +

String 'vector'.

Methods

- -

- See [page:KeyframeTrack] for inherited methods. -

- +

See [page:KeyframeTrack] for inherited methods.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/audio/Audio.html b/docs/api/en/audio/Audio.html index a2e3db410cf608..07946bfd0527d1 100644 --- a/docs/api/en/audio/Audio.html +++ b/docs/api/en/audio/Audio.html @@ -14,12 +14,13 @@

[name]

Create a non-positional ( global ) audio object.

- This uses the [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API]. + This uses the + [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API].

Code Example

- + // create an AudioListener and add it to the camera const listener = new THREE.AudioListener(); camera.add( listener ); @@ -46,12 +47,8 @@

Examples

Constructor

-

[name]( [param:AudioListener listener] )

-

- listener — (required) [page:AudioListener AudioListener] instance. -

- +

listener — (required) [page:AudioListener AudioListener] instance.

Properties

@@ -59,22 +56,37 @@

[property:Boolean autoplay]

Whether to start playback automatically. Default is `false`.

[property:AudioContext context]

-

The [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext] of the [page:AudioListener listener] given in the constructor.

+

+ The [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext] of the [page:AudioListener listener] given in the + constructor. +

[property:Number detune]

-

Modify pitch, measured in cents. +/- 100 is a semitone. +/- 1200 is an octave. Default is `0`.

+

+ Modify pitch, measured in cents. +/- 100 is a semitone. +/- 1200 is an + octave. Default is `0`. +

[property:Array filters]

-

Represents an array of [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioNode AudioNodes]. Can be used to apply a variety of low-order filters to create more complex sound effects. - In most cases, the array contains instances of [link:https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode BiquadFilterNodes]. Filters are set via [page:Audio.setFilter] or [page:Audio.setFilters].

+

+ Represents an array of + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioNode AudioNodes]. Can be used to apply a variety of low-order filters to create + more complex sound effects. In most cases, the array contains instances of + [link:https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode BiquadFilterNodes]. Filters are set via [page:Audio.setFilter] or + [page:Audio.setFilters]. +

[property:GainNode gain]

-

A [link:https://developer.mozilla.org/en-US/docs/Web/API/GainNode GainNode] created - using [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createGain AudioContext.createGain]().

+

+ A [link:https://developer.mozilla.org/en-US/docs/Web/API/GainNode GainNode] created using + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createGain AudioContext.createGain](). +

[property:Boolean hasPlaybackControl]

-

Whether playback can be controlled using the [page:Audio.play play](), - [page:Audio.pause pause]() etc. methods. Default is `true`.

+

+ Whether playback can be controlled using the [page:Audio.play play](), + [page:Audio.pause pause]() etc. methods. Default is `true`. +

[property:Boolean isPlaying]

Whether the audio is currently playing.

@@ -86,14 +98,25 @@

[property:Number playbackRate]

Speed of playback. Default is `1`.

[property:Number offset]

-

An offset to the time within the audio buffer that playback should begin. Same as the `offset` parameter of [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/start AudioBufferSourceNode.start](). Default is `0`.

+

+ An offset to the time within the audio buffer that playback should begin. + Same as the `offset` parameter of + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/start AudioBufferSourceNode.start](). Default is `0`. +

[property:Number duration]

-

Overrides the duration of the audio. Same as the `duration` parameter of [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/start AudioBufferSourceNode.start](). Default is `undefined` to play the whole buffer.

+

+ Overrides the duration of the audio. Same as the `duration` parameter of + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/start AudioBufferSourceNode.start](). Default is `undefined` to play the whole + buffer. +

[property:AudioNode source]

-

An [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode AudioBufferSourceNode] created - using [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createBufferSource AudioContext.createBufferSource]().

+

+ An + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode AudioBufferSourceNode] created using + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createBufferSource AudioContext.createBufferSource](). +

[property:String sourceType]

Type of the audio source. Default is string 'empty'.

@@ -101,142 +124,130 @@

[property:String sourceType]

[property:String type]

String denoting the type, set to 'Audio'.

-

Methods

[method:this connect]()

- Connect to the [page:Audio.source]. This is used internally on initialisation and when - setting / removing filters. + Connect to the [page:Audio.source]. This is used internally on + initialisation and when setting / removing filters.

[method:this disconnect]()

- Disconnect from the [page:Audio.source]. This is used internally when - setting / removing filters. + Disconnect from the [page:Audio.source]. This is used internally when + setting / removing filters.

[method:Float getDetune]()

-

- Returns the detuning of oscillation in cents. -

+

Returns the detuning of oscillation in cents.

[method:BiquadFilterNode getFilter]()

-

- Returns the first element of the [page:Audio.filters filters] array. -

+

Returns the first element of the [page:Audio.filters filters] array.

[method:Array getFilters]()

-

- Returns the [page:Audio.filters filters] array. -

+

Returns the [page:Audio.filters filters] array.

[method:Boolean getLoop]()

- Return the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loop source.loop] - (whether playback should loop). + Return the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loop source.loop] (whether playback should loop).

[method:GainNode getOutput]()

-

- Return the [page:Audio.gain gainNode]. -

+

Return the [page:Audio.gain gainNode].

[method:Float getPlaybackRate]()

-

- Return the value of [page:Audio.playbackRate playbackRate]. -

+

Return the value of [page:Audio.playbackRate playbackRate].

[method:Float getVolume]( value )

-

- Return the current volume. -

+

Return the current volume.

[method:this play]( delay )

- If [page:Audio.hasPlaybackControl hasPlaybackControl] is true, starts playback. + If [page:Audio.hasPlaybackControl hasPlaybackControl] is true, starts + playback.

[method:this pause]()

- If [page:Audio.hasPlaybackControl hasPlaybackControl] is true, pauses playback. + If [page:Audio.hasPlaybackControl hasPlaybackControl] is true, pauses + playback.

[method:undefined onEnded]()

-

- Called automatically when playback finished. -

+

Called automatically when playback finished.

[method:this setBuffer]( audioBuffer )

- Setup the [page:Audio.source source] to the audioBuffer, and sets [page:Audio.sourceType sourceType] to 'buffer'.
- If [page:Audio.autoplay autoplay], also starts playback. + Setup the [page:Audio.source source] to the audioBuffer, and sets + [page:Audio.sourceType sourceType] to 'buffer'.
+ If [page:Audio.autoplay autoplay], also starts playback.

[method:this setDetune]( [param:Float value] )

-

- Defines the detuning of oscillation in cents. -

+

Defines the detuning of oscillation in cents.

[method:this setFilter]( filter )

-

- Applies a single filter node to the audio. -

+

Applies a single filter node to the audio.

[method:this setFilters]( [param:Array value] )

- value - arrays of filters.
- Applies an array of filter nodes to the audio. + value - arrays of filters.
+ Applies an array of filter nodes to the audio.

[method:this setLoop]( [param:Boolean value] )

- Set [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loop source.loop] to `value` - (whether playback should loop). + Set + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loop source.loop] to `value` (whether playback should loop).

[method:this setLoopStart]( [param:Float value] )

- Set [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loopStart source.loopStart] to `value`. + Set + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loopStart source.loopStart] to `value`.

[method:this setLoopEnd]( [param:Float value] )

- Set [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loopEnd source.loopEnd] to `value`. + Set + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/loopEnd source.loopEnd] to `value`.

[method:this setMediaElementSource]( mediaElement )

- Applies the given object of type [link:https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement HTMLMediaElement] as the source of this audio.
- Also sets [page:Audio.hasPlaybackControl hasPlaybackControl] to false. + Applies the given object of type + [link:https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement HTMLMediaElement] as the source of this audio.
+ Also sets [page:Audio.hasPlaybackControl hasPlaybackControl] to false.

[method:this setMediaStreamSource]( mediaStream )

- Applies the given object of type [link:https://developer.mozilla.org/en-US/docs/Web/API/MediaStream MediaStream] as the source of this audio.
- Also sets [page:Audio.hasPlaybackControl hasPlaybackControl] to false. + Applies the given object of type + [link:https://developer.mozilla.org/en-US/docs/Web/API/MediaStream MediaStream] as the source of this audio.
+ Also sets [page:Audio.hasPlaybackControl hasPlaybackControl] to false.

[method:this setNodeSource]( audioNode )

- Setup the [page:Audio.source source] to the audioBuffer, and sets [page:Audio.sourceType sourceType] to 'audioNode'.
- Also sets [page:Audio.hasPlaybackControl hasPlaybackControl] to false. - + Setup the [page:Audio.source source] to the audioBuffer, and sets + [page:Audio.sourceType sourceType] to 'audioNode'.
+ Also sets [page:Audio.hasPlaybackControl hasPlaybackControl] to false.

[method:this setPlaybackRate]( [param:Float value] )

- If [page:Audio.hasPlaybackControl hasPlaybackControl] is enabled, set the [page:Audio.playbackRate playbackRate] to `value`. + If [page:Audio.hasPlaybackControl hasPlaybackControl] is enabled, set the + [page:Audio.playbackRate playbackRate] to `value`.

[method:this setVolume]( [param:Float value] )

-

- Set the volume. -

+

Set the volume.

[method:this stop]()

- If [page:Audio.hasPlaybackControl hasPlaybackControl] is enabled, stops playback. + If [page:Audio.hasPlaybackControl hasPlaybackControl] is enabled, stops + playback.

Source

diff --git a/docs/api/en/audio/AudioAnalyser.html b/docs/api/en/audio/AudioAnalyser.html index 8ddfb7b4dd6784..99a418ccc26bf7 100644 --- a/docs/api/en/audio/AudioAnalyser.html +++ b/docs/api/en/audio/AudioAnalyser.html @@ -10,16 +10,16 @@

[name]

- Create a AudioAnalyser object, which uses an [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode AnalyserNode] - to analyse audio data.

- - This uses the [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API]. + Create a AudioAnalyser object, which uses an + [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode AnalyserNode] to analyse audio data.

+ This uses the + [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API].

Code Example

- + // create an AudioListener and add it to the camera const listener = new THREE.AudioListener(); camera.add( listener ); @@ -41,6 +41,7 @@

Code Example

// get the average frequency of the sound const data = analyser.getAverageFrequency(); +

Examples

@@ -52,43 +53,41 @@

Examples

Constructor

-

[name]( audio, [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/fftSize fftSize] )

-

- Create a new [page:AudioAnalyser AudioAnalyser]. -

- +

Create a new [page:AudioAnalyser AudioAnalyser].

Properties

[property:AnalyserNode analyser]

-

An [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode AnalyserNode] used to analyze audio.

+

+ An [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode AnalyserNode] used to analyze audio. +

[property:Integer fftSize]

- A non-zero power of two up to 2048, representing the size of the FFT (Fast Fourier Transform) to be used to determine the frequency domain. - See [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/fftSize this page] for details. + A non-zero power of two up to 2048, representing the size of the FFT (Fast + Fourier Transform) to be used to determine the frequency domain. See + [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/fftSize this page] for details.

[property:Uint8Array data]

- A Uint8Array with size determined by [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/frequencyBinCount analyser.frequencyBinCount] - used to hold analysis data. + A Uint8Array with size determined by + [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/frequencyBinCount analyser.frequencyBinCount] used to hold analysis data.

-

Methods

-

[method:Uint8Array getFrequencyData]()

- Uses the Web Audio's [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData getByteFrequencyData] method. - See that page. + Uses the Web Audio's + [link:https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData getByteFrequencyData] method. See that page.

[method:Number getAverageFrequency]()

- Get the average of the frequencies returned by the [page:AudioAnalyser.getFrequencyData getFrequencyData] method. + Get the average of the frequencies returned by the + [page:AudioAnalyser.getFrequencyData getFrequencyData] method.

Source

diff --git a/docs/api/en/audio/AudioContext.html b/docs/api/en/audio/AudioContext.html index ecbf4a6769fd83..f72b1e195b6f10 100644 --- a/docs/api/en/audio/AudioContext.html +++ b/docs/api/en/audio/AudioContext.html @@ -7,32 +7,30 @@ -

[name]

- This contains methods for setting up an [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext].

+ This contains methods for setting up an + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext].

- Used internally by the [page:AudioListener AudioListener] and [page:AudioLoader AudioLoader] classes.

+ Used internally by the [page:AudioListener AudioListener] and + [page:AudioLoader AudioLoader] classes.

- This uses the [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API]. + This uses the + [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API].

- -

Methods

[method:AudioContext getContext]()

- Return the value of the variable `context` in the outer scope, if defined, - otherwise set it to a new [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext]. + Return the value of the variable `context` in the outer scope, if defined, + otherwise set it to a new + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext].

[method:AudioContext setContext]( [param:AudioContext value] )

-

- Set the variable `context` in the outer scope to `value`. -

- +

Set the variable `context` in the outer scope to `value`.

Source

diff --git a/docs/api/en/audio/AudioListener.html b/docs/api/en/audio/AudioListener.html index 7eb3ba1c180929..b80c1ba1918ed7 100644 --- a/docs/api/en/audio/AudioListener.html +++ b/docs/api/en/audio/AudioListener.html @@ -12,14 +12,19 @@

[name]

- The [name] represents a virtual [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioListener listener] of the all positional and non-positional audio effects in the scene.
- A three.js application usually creates a single instance of [name]. It is a mandatory construtor parameter for audios entities like [page:Audio Audio] and [page:PositionalAudio PositionalAudio].
- In most cases, the listener object is a child of the camera. So the 3D transformation of the camera represents the 3D transformation of the listener. + The [name] represents a virtual + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioListener listener] of the all positional and non-positional audio effects in the + scene.
+ A three.js application usually creates a single instance of [name]. It is + a mandatory constructor parameter for audios entities like [page:Audio Audio] and [page:PositionalAudio PositionalAudio].
+ In most cases, the listener object is a child of the camera. So the 3D + transformation of the camera represents the 3D transformation of the + listener.

Code Example

- + // create an AudioListener and add it to the camera const listener = new THREE.AudioListener(); camera.add( listener ); @@ -35,6 +40,7 @@

Code Example

sound.setVolume(0.5); sound.play(); }); +

Examples

@@ -47,61 +53,51 @@

Examples

Constructor

- -

[name]( )

-

- Create a new AudioListener. -

- +

[name]( )

+

Create a new AudioListener.

Properties

[property:AudioContext context]

-

The [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext] of the [page:AudioListener listener] given in the constructor.

+

+ The [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext] of the [page:AudioListener listener] given in the + constructor. +

[property:GainNode gain]

-

A [link:https://developer.mozilla.org/en-US/docs/Web/API/GainNode GainNode] created - using [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createGain AudioContext.createGain]().

+

+ A [link:https://developer.mozilla.org/en-US/docs/Web/API/GainNode GainNode] created using + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createGain AudioContext.createGain](). +

[property:AudioNode filter]

Default is `null`.

[property:Number timeDelta]

-

Time delta value for audio entities. Use in context of [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioParam/linearRampToValueAtTime AudioParam.linearRampToValueAtTimeDefault](). Default is .

+

+ Time delta value for audio entities. Use in context of + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioParam/linearRampToValueAtTime AudioParam.linearRampToValueAtTimeDefault](). Default is . +

Methods

-

[method:GainNode getInput]()

-

- Return the [page:AudioListener.gain gainNode]. -

+

Return the [page:AudioListener.gain gainNode].

[method:this removeFilter]()

-

- Set the [page:AudioListener.filter filter] property to `null`. -

+

Set the [page:AudioListener.filter filter] property to `null`.

[method:AudioNode getFilter]()

-

- Returns the value of the [page:AudioListener.filter filter] property. -

+

Returns the value of the [page:AudioListener.filter filter] property.

[method:this setFilter]( [param:AudioNode value] )

-

- Set the [page:AudioListener.filter filter] property to `value`. -

+

Set the [page:AudioListener.filter filter] property to `value`.

[method:Float getMasterVolume]()

-

- Return the volume. -

+

Return the volume.

[method:this setMasterVolume]( [param:Number value] )

-

- Set the volume. -

- +

Set the volume.

Source

diff --git a/docs/api/en/audio/PositionalAudio.html b/docs/api/en/audio/PositionalAudio.html index 92b90098f89a45..5e4835d36d22b9 100644 --- a/docs/api/en/audio/PositionalAudio.html +++ b/docs/api/en/audio/PositionalAudio.html @@ -14,7 +14,8 @@

[name]

Create a positional audio object.

- This uses the [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API]. + This uses the + [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API Web Audio API].

Code Example

@@ -56,75 +57,78 @@

Examples

Constructor

[name]( [param:AudioListener listener] )

-

- listener — (required) [page:AudioListener AudioListener] instance. -

- +

listener — (required) [page:AudioListener AudioListener] instance.

Properties

-

- See the [page:Audio Audio] class for inherited properties. -

+

See the [page:Audio Audio] class for inherited properties.

[property:PannerNode panner]

-

The PositionalAudio's [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode PannerNode].

- +

+ The PositionalAudio's + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode PannerNode]. +

Methods

-

- See the [page:Audio Audio] class for inherited methods. -

+

See the [page:Audio Audio] class for inherited methods.

[method:PannerNode getOutput]()

-

- Returns the [page:PositionalAudio.panner panner]. -

+

Returns the [page:PositionalAudio.panner panner].

[method:Float getRefDistance]()

- Returns the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/refDistance panner.refDistance]. + Returns the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/refDistance panner.refDistance].

[method:this setRefDistance]( [param:Float value] )

- Sets the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/refDistance panner.refDistance]. + Sets the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/refDistance panner.refDistance].

[method:Float getRolloffFactor]()

- Returns the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/rolloffFactor panner.rolloffFactor]. + Returns the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/rolloffFactor panner.rolloffFactor].

[method:this setRolloffFactor]( [param:Float value] )

- Sets the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/rolloffFactor panner.rolloffFactor]. + Sets the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/rolloffFactor panner.rolloffFactor].

[method:String getDistanceModel]()

- Returns the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/distanceModel panner.distanceModel]. + Returns the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/distanceModel panner.distanceModel].

[method:this setDistanceModel]( [param:String value] )

- Sets the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/distanceModel panner.distanceModel]. + Sets the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/distanceModel panner.distanceModel].

[method:Float getMaxDistance]()

- Returns the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/maxDistance panner.maxDistance]. + Returns the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/maxDistance panner.maxDistance].

[method:this setMaxDistance]( [param:Float value] )

- Sets the value of [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/maxDistance panner.maxDistance]. + Sets the value of + [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/maxDistance panner.maxDistance].

-

[method:this setDirectionalCone]( [param:Float coneInnerAngle], [param:Float coneOuterAngle], [param:Float coneOuterGain] )

+

[method:this setDirectionalCone]( [param:Float coneInnerAngle], [param:Float coneOuterAngle], [param:Float coneOuterGain] ) +

- This method can be used in order to transform an omnidirectional sound into a [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode directional sound]. + This method can be used in order to transform an omnidirectional sound + into a [link:https://developer.mozilla.org/en-US/docs/Web/API/PannerNode directional sound].

Source

diff --git a/docs/api/en/cameras/ArrayCamera.html b/docs/api/en/cameras/ArrayCamera.html index 52a320b790d53b..7f033acd847461 100644 --- a/docs/api/en/cameras/ArrayCamera.html +++ b/docs/api/en/cameras/ArrayCamera.html @@ -10,44 +10,39 @@ [page:Object3D] → [page:Camera] → [page:PerspectiveCamera] →

[name]

-

- [name] can be used in order to efficiently render a scene with a predefined set of cameras. This is an important performance aspect for rendering VR scenes.
- An instance of [name] always has an array of sub cameras. It's mandatory to define for each sub camera the `viewport` property which determines the part of the viewport that is rendered with this camera. + [name] can be used in order to efficiently render a scene with a + predefined set of cameras. This is an important performance aspect for + rendering VR scenes.
+ An instance of [name] always has an array of sub cameras. It's mandatory + to define for each sub camera the `viewport` property which determines the + part of the viewport that is rendered with this camera.

Examples

-

[example:webgl_camera_array camera / array ]

Constructor

[name]( [param:Array array] )

-

- An array of cameras. -

- +

An array of cameras.

Properties

See the base [page:PerspectiveCamera] class for common properties.

[property:Array cameras]

-

- An array of cameras. -

+

An array of cameras.

[property:Boolean isArrayCamera]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

Methods

See the base [page:PerspectiveCamera] class for common methods.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ diff --git a/docs/api/en/cameras/Camera.html b/docs/api/en/cameras/Camera.html index 7cfb21ac6c5f44..f649dfdfd58e18 100644 --- a/docs/api/en/cameras/Camera.html +++ b/docs/api/en/cameras/Camera.html @@ -12,41 +12,38 @@

[name]

- Abstract base class for cameras. This class should always be inherited when you build a new camera. + Abstract base class for cameras. This class should always be inherited + when you build a new camera.

-

Constructor

-

[name]()

- Creates a new [name]. Note that this class is not intended to be called directly; - you probably want a [page:PerspectiveCamera] or [page:OrthographicCamera] instead. + Creates a new [name]. Note that this class is not intended to be called + directly; you probably want a [page:PerspectiveCamera] or + [page:OrthographicCamera] instead.

-

Properties

See the base [page:Object3D] class for common properties.

[property:Boolean isCamera]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Layers layers]

- The [page:Layers layers] that the camera is a member of. This is an inherited - property from [page:Object3D].

+ The [page:Layers layers] that the camera is a member of. This is an + inherited property from [page:Object3D].

- Objects must share at least one layer with the camera to be seen - when the camera's viewpoint is rendered. + Objects must share at least one layer with the camera to be seen when the + camera's viewpoint is rendered.

[property:Matrix4 matrixWorldInverse]

- This is the inverse of matrixWorld. MatrixWorld contains the Matrix which has - the world transform of the Camera. + This is the inverse of matrixWorld. MatrixWorld contains the Matrix which + has the world transform of the Camera.

[property:Matrix4 projectionMatrix]

@@ -55,26 +52,23 @@

[property:Matrix4 projectionMatrix]

[property:Matrix4 projectionMatrixInverse]

The inverse of projectionMatrix.

-

Methods

See the base [page:Object3D] class for common methods.

[method:Camera clone]( )

-

- Return a new camera with the same properties as this one. -

+

Return a new camera with the same properties as this one.

[method:this copy]( [param:Camera source], [param:Boolean recursive] )

-

- Copy the properties from the source camera into this one. -

+

Copy the properties from the source camera into this one.

[method:Vector3 getWorldDirection]( [param:Vector3 target] )

- [page:Vector3 target] — the result will be copied into this Vector3.

+ [page:Vector3 target] — the result will be copied into this Vector3. +

- Returns a [page:Vector3] representing the world space direction in which the camera is looking. - (Note: A camera looks down its local, negative z-axis).

+ Returns a [page:Vector3] representing the world space direction in which + the camera is looking. (Note: A camera looks down its local, negative + z-axis).

Source

diff --git a/docs/api/en/cameras/CubeCamera.html b/docs/api/en/cameras/CubeCamera.html index 884ccb796b90c0..f513c09cf0c6e3 100644 --- a/docs/api/en/cameras/CubeCamera.html +++ b/docs/api/en/cameras/CubeCamera.html @@ -11,11 +11,14 @@

[name]

-

Creates 6 cameras that render to a [page:WebGLCubeRenderTarget].

+

+ Creates 6 cameras that render to a [page:WebGLCubeRenderTarget]. +

Code Example

+ // Create cube render target const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 128, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } ); @@ -36,48 +39,39 @@

Code Example

// Render the scene car.visible = true; renderer.render( scene, camera ); +

Examples

-

- [example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic ] -

+

[example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic ]

Constructor

-

[name]( [param:Number near], [param:Number far], [param:WebGLCubeRenderTarget renderTarget] )

- near -- The near clipping distance.
- far -- The far clipping distance.
- renderTarget -- The destination cube render target. + near -- The near clipping distance.
+ far -- The far clipping distance.
+ renderTarget -- The destination cube render target.

-

- Constructs a CubeCamera that contains 6 [page:PerspectiveCamera PerspectiveCameras] that - render to a [page:WebGLCubeRenderTarget]. -

+

Constructs a CubeCamera that contains 6 [page:PerspectiveCamera PerspectiveCameras] that render to a [page:WebGLCubeRenderTarget].

Properties

See the base [page:Object3D] class for common properties.

[property:WebGLCubeRenderTarget renderTarget]

-

- The destination cube render target. -

+

The destination cube render target.

Methods

See the base [page:Object3D] class for common methods.

[method:undefined update]( [param:WebGLRenderer renderer], [param:Scene scene] )

- renderer -- The current WebGL renderer
- scene -- The current scene -

-

- Call this to update the [page:CubeCamera.renderTarget renderTarget]. + renderer -- The current WebGL renderer
+ scene -- The current scene

+

Call this to update the [page:CubeCamera.renderTarget renderTarget].

Source

diff --git a/docs/api/en/cameras/OrthographicCamera.html b/docs/api/en/cameras/OrthographicCamera.html index 498f8689be4a0a..d85488a7e8395b 100644 --- a/docs/api/en/cameras/OrthographicCamera.html +++ b/docs/api/en/cameras/OrthographicCamera.html @@ -10,58 +10,54 @@ [page:Object3D] → [page:Camera] →

[name]

-

- Camera that uses [link:https://en.wikipedia.org/wiki/Orthographic_projection orthographic projection].

+ Camera that uses + [link:https://en.wikipedia.org/wiki/Orthographic_projection orthographic projection].

- In this projection mode, an object's size in the rendered image stays constant - regardless of its distance from the camera.

+ In this projection mode, an object's size in the rendered image stays + constant regardless of its distance from the camera.

- This can be useful for rendering 2D scenes and UI elements, amongst other things. + This can be useful for rendering 2D scenes and UI elements, amongst other + things.

Code Example

- - + const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 ); scene.add( camera );

Examples

-

[example:webgl_camera camera ]
[example:webgl_interactive_cubes_ortho interactive / cubes / ortho ]
- [example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic ]
+ [example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic]
[example:webgl_postprocessing_advanced postprocessing / advanced ]
[example:webgl_postprocessing_dof2 postprocessing / dof2 ]
[example:webgl_postprocessing_godrays postprocessing / godrays ]
[example:webgl_rtt rtt ]
- [example:webgl_shaders_tonemapping shaders / tonemapping ]
[example:webgl_shadowmap shadowmap ]

Constructor

- -

[name]( [param:Number left], [param:Number right], [param:Number top], [param:Number bottom], [param:Number near], [param:Number far] )

- left — Camera frustum left plane.
- right — Camera frustum right plane.
- top — Camera frustum top plane.
- bottom — Camera frustum bottom plane.
- near — Camera frustum near plane.
- far — Camera frustum far plane.

- - Together these define the camera's [link:https://en.wikipedia.org/wiki/Viewing_frustum viewing frustum]. + left — Camera frustum left plane.
+ right — Camera frustum right plane.
+ top — Camera frustum top plane.
+ bottom — Camera frustum bottom plane.
+ near — Camera frustum near plane.
+ far — Camera frustum far plane.

+ + Together these define the camera's + [link:https://en.wikipedia.org/wiki/Viewing_frustum viewing frustum].

-

Properties

- See the base [page:Camera] class for common properties.
- Note that after making changes to most of these properties you will have to call - [page:OrthographicCamera.updateProjectionMatrix .updateProjectionMatrix] for the changes to take effect. + See the base [page:Camera] class for common properties.
+ Note that after making changes to most of these properties you will have + to call [page:OrthographicCamera.updateProjectionMatrix .updateProjectionMatrix] for the changes to take effect.

[property:Float bottom]

@@ -69,15 +65,12 @@

[property:Float bottom]

[property:Float far]

- Camera frustum far plane. Default is `2000`.

- - Must be greater than the current value of [page:.near near] plane. + Camera frustum far plane. Default is `2000`.

+ Must be greater than the current value of [page:.near near] plane.

[property:Boolean isOrthographicCamera]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Float left]

Camera frustum left plane.

@@ -86,9 +79,8 @@

[property:Float near]

Camera frustum near plane. Default is `0.1`.

- The valid range is between `0` and the current value of the [page:.far far] plane. - Note that, unlike for the [page:PerspectiveCamera], `0` is a valid value for an - OrthographicCamera's near plane. + The valid range is between `0` and the current value of the [page:.far far] plane. Note that, unlike for the [page:PerspectiveCamera], `0` is a + valid value for an OrthographicCamera's near plane.

[property:Float right]

@@ -98,7 +90,10 @@

[property:Float top]

Camera frustum top plane.

[property:Object view]

-

Set by [page:OrthographicCamera.setViewOffset setViewOffset]. Default is `null`.

+

+ Set by [page:OrthographicCamera.setViewOffset setViewOffset]. Default is + `null`. +

[property:number zoom]

Gets or sets the zoom factor of the camera. Default is `1`.

@@ -108,36 +103,37 @@

Methods

[method:undefined setViewOffset]( [param:Float fullWidth], [param:Float fullHeight], [param:Float x], [param:Float y], [param:Float width], [param:Float height] )

- fullWidth — full width of multiview setup
- fullHeight — full height of multiview setup
- x — horizontal offset of subcamera
- y — vertical offset of subcamera
- width — width of subcamera
- height — height of subcamera

- - Sets an offset in a larger [link:https://en.wikipedia.org/wiki/Viewing_frustum viewing frustum]. - This is useful for multi-window or multi-monitor/multi-machine setups. - For an example on how to use it see [page:PerspectiveCamera.setViewOffset PerspectiveCamera]. + fullWidth — full width of multiview setup
+ fullHeight — full height of multiview setup
+ x — horizontal offset of subcamera
+ y — vertical offset of subcamera
+ width — width of subcamera
+ height — height of subcamera

+ + Sets an offset in a larger + [link:https://en.wikipedia.org/wiki/Viewing_frustum viewing frustum]. This + is useful for multi-window or multi-monitor/multi-machine setups. For an + example on how to use it see [page:PerspectiveCamera.setViewOffset PerspectiveCamera].

[method:undefined clearViewOffset]()

-

- Removes any offset set by the .setViewOffset method. -

+

Removes any offset set by the .setViewOffset method.

[method:undefined updateProjectionMatrix]()

- Updates the camera projection matrix. Must be called after any change of parameters. + Updates the camera projection matrix. Must be called after any change of + parameters.

[method:Object toJSON]([param:Object meta])

- meta -- object containing metadata such as textures or images in objects' descendants.
- Convert the camera to three.js [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. + meta -- object containing metadata such as textures or images in objects' + descendants.
+ Convert the camera to three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/cameras/PerspectiveCamera.html b/docs/api/en/cameras/PerspectiveCamera.html index 156aae1787a598..3e426f80d651cb 100644 --- a/docs/api/en/cameras/PerspectiveCamera.html +++ b/docs/api/en/cameras/PerspectiveCamera.html @@ -10,12 +10,11 @@ [page:Object3D] → [page:Camera] →

[name]

-

- Camera that uses [link:https://en.wikipedia.org/wiki/Perspective_(graphical) perspective projection].

- - This projection mode is designed to mimic the way the human eye sees. It is the most - common projection mode used for rendering a 3D scene. + Camera that uses + [link:https://en.wikipedia.org/wiki/Perspective_(graphical) perspective projection].

+ This projection mode is designed to mimic the way the human eye sees. It + is the most common projection mode used for rendering a 3D scene.

Code Example

@@ -26,9 +25,8 @@

Code Example

Examples

-

- [example:webgl_animation_skinning_blending animation / skinning / blending ]
+ [example:webgl_animation_skinning_blending animation / skinning / blending]
[example:webgl_animation_skinning_morph animation / skinning / morph ]
[example:webgl_effects_stereo effects / stereo ]
[example:webgl_interactive_cubes interactive / cubes ]
@@ -39,73 +37,81 @@

Constructor

[name]( [param:Number fov], [param:Number aspect], [param:Number near], [param:Number far] )

- fov — Camera frustum vertical field of view.
- aspect — Camera frustum aspect ratio.
- near — Camera frustum near plane.
- far — Camera frustum far plane.

- - Together these define the camera's [link:https://en.wikipedia.org/wiki/Viewing_frustum viewing frustum]. + fov — Camera frustum vertical field of view.
+ aspect — Camera frustum aspect ratio.
+ near — Camera frustum near plane.
+ far — Camera frustum far plane.

+ Together these define the camera's + [link:https://en.wikipedia.org/wiki/Viewing_frustum viewing frustum].

-

Properties

- See the base [page:Camera] class for common properties.
- Note that after making changes to most of these properties you will have to call - [page:PerspectiveCamera.updateProjectionMatrix .updateProjectionMatrix] for the changes to take effect. + See the base [page:Camera] class for common properties.
+ Note that after making changes to most of these properties you will have + to call [page:PerspectiveCamera.updateProjectionMatrix .updateProjectionMatrix] for the changes to take effect.

[property:Float aspect]

-

Camera frustum aspect ratio, usually the canvas width / canvas height. Default is `1` (square canvas).

+

+ Camera frustum aspect ratio, usually the canvas width / canvas height. + Default is `1` (square canvas). +

[property:Float far]

Camera frustum far plane. Default is `2000`.

- Must be greater than the current value of [page:.near near] plane.

[property:Float filmGauge]

-

Film size used for the larger axis. Default is 35 (millimeters). This parameter does not influence the projection matrix unless .filmOffset is set to a nonzero value.

+

+ Film size used for the larger axis. Default is 35 (millimeters). This + parameter does not influence the projection matrix unless .filmOffset is + set to a nonzero value. +

[property:Float filmOffset]

-

Horizontal off-center offset in the same unit as `.filmGauge`. Default is `0`.

+

+ Horizontal off-center offset in the same unit as `.filmGauge`. Default is + `0`. +

[property:Float focus]

-

Object distance used for stereoscopy and depth-of-field effects. - This parameter does not influence the projection matrix unless a [page:StereoCamera] is being used. - Default is `10`. +

+ Object distance used for stereoscopy and depth-of-field effects. This + parameter does not influence the projection matrix unless a + [page:StereoCamera] is being used. Default is `10`.

[property:Float fov]

-

Camera frustum vertical field of view, from bottom to top of view, in degrees. Default is `50`.

- -

[property:Boolean isPerspectiveCamera]

- Read-only flag to check if a given object is of type [name]. + Camera frustum vertical field of view, from bottom to top of view, in + degrees. Default is `50`.

+

[property:Boolean isPerspectiveCamera]

+

Read-only flag to check if a given object is of type [name].

[property:Float near]

Camera frustum near plane. Default is `0.1`.

- - The valid range is greater than 0 and less than the current value of the [page:.far far] plane. - Note that, unlike for the [page:OrthographicCamera], `0` is not a valid value - for a PerspectiveCamera's near plane. + The valid range is greater than `0` and less than the current value of the + [page:.far far] plane. Note that, unlike for the + [page:OrthographicCamera], `0` is not a valid value for a + PerspectiveCamera's near plane.

[property:Object view]

- Frustum window specification or null. - This is set using the [page:PerspectiveCamera.setViewOffset .setViewOffset] method - and cleared using [page:PerspectiveCamera.clearViewOffset .clearViewOffset]. + Frustum window specification or null. This is set using the + [page:PerspectiveCamera.setViewOffset .setViewOffset] method and cleared + using [page:PerspectiveCamera.clearViewOffset .clearViewOffset].

[property:number zoom]

Gets or sets the zoom factor of the camera. Default is `1`.

-

Methods

See the base [page:Camera] class for common methods.

@@ -117,42 +123,47 @@

[method:Float getEffectiveFOV]()

[method:Float getFilmHeight]()

- Returns the height of the image on the film. If .aspect is less than or equal to one - (portrait format), the result equals .filmGauge. + Returns the height of the image on the film. If .aspect is less than or + equal to one (portrait format), the result equals .filmGauge.

[method:Float getFilmWidth]()

- Returns the width of the image on the film. If .aspect is greater than or equal to one - (landscape format), the result equals .filmGauge. + Returns the width of the image on the film. If .aspect is greater than or + equal to one (landscape format), the result equals .filmGauge.

[method:Float getFocalLength]()

-

Returns the focal length of the current .fov in respect to .filmGauge.

+

+ Returns the focal length of the current .fov in respect to .filmGauge. +

[method:undefined setFocalLength]( [param:Float focalLength] )

- Sets the FOV by focal length in respect to the current [page:PerspectiveCamera.filmGauge .filmGauge].

- - By default, the focal length is specified for a 35mm (full frame) camera. + Sets the FOV by focal length in respect to the current + [page:PerspectiveCamera.filmGauge .filmGauge].

+ By default, the focal length is specified for a 35mm (full frame) camera.

[method:undefined setViewOffset]( [param:Float fullWidth], [param:Float fullHeight], [param:Float x], [param:Float y], [param:Float width], [param:Float height] )

- fullWidth — full width of multiview setup
- fullHeight — full height of multiview setup
- x — horizontal offset of subcamera
- y — vertical offset of subcamera
- width — width of subcamera
- height — height of subcamera + fullWidth — full width of multiview setup
+ fullHeight — full height of multiview setup
+ x — horizontal offset of subcamera
+ y — vertical offset of subcamera
+ width — width of subcamera
+ height — height of subcamera

- Sets an offset in a larger frustum. This is useful for multi-window or multi-monitor/multi-machine setups. + Sets an offset in a larger frustum. This is useful for multi-window or + multi-monitor/multi-machine setups.

- For example, if you have 3x2 monitors and each monitor is 1920x1080 and the monitors are in grid like this:
+ For example, if you have 3x2 monitors and each monitor is 1920x1080 and + the monitors are in grid like this:
+

 +---+---+---+
@@ -182,25 +193,27 @@ 

[method:undefined setViewOffset]( [param:Float fullWidth], [param:Float full // F camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); - - Note there is no reason monitors have to be the same size or in a grid. -

+ +

Note there is no reason monitors have to be the same size or in a grid.

[method:undefined updateProjectionMatrix]()

- Updates the camera projection matrix. Must be called after any change of parameters. + Updates the camera projection matrix. Must be called after any change of + parameters.

[method:Object toJSON]([param:Object meta])

- meta -- object containing metadata such as textures or images in objects' descendants.
- Convert the camera to three.js [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. + meta -- object containing metadata such as textures or images in objects' + descendants.
+ Convert the camera to three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ diff --git a/docs/api/en/cameras/StereoCamera.html b/docs/api/en/cameras/StereoCamera.html index d1ba653db0cad1..28768569bec3f2 100644 --- a/docs/api/en/cameras/StereoCamera.html +++ b/docs/api/en/cameras/StereoCamera.html @@ -7,16 +7,15 @@ -

[name]

- Dual [page:PerspectiveCamera PerspectiveCamera]s used for effects such as - [link:https://en.wikipedia.org/wiki/Anaglyph_3D 3D Anaglyph] or [link:https://en.wikipedia.org/wiki/parallax_barrier Parallax Barrier]. + Dual [page:PerspectiveCamera PerspectiveCamera]s used for effects such as + [link:https://en.wikipedia.org/wiki/Anaglyph_3D 3D Anaglyph] or + [link:https://en.wikipedia.org/wiki/parallax_barrier Parallax Barrier].

Examples

-

[example:webgl_effects_anaglyph effects / anaglyph ]
[example:webgl_effects_parallaxbarrier effects / parallaxbarrier ]
@@ -24,9 +23,8 @@

Examples

Constructor

-

[name]( )

- +

Properties

[property:Float aspect]

@@ -36,20 +34,21 @@

[property:Float eyeSep]

Default is `0.064`.

[property:PerspectiveCamera cameraL]

-

Left camera. This is added to [page:Layers layer 1] - objects to be rendered - by the left camera must also be added to this layer.

+

+ Left camera. This is added to [page:Layers layer 1] - objects to be + rendered by the left camera must also be added to this layer. +

[property:PerspectiveCamera cameraR]

-

Right camera.This is added to [page:Layers layer 2] - objects to be rendered - by the right camera must also be added to this layer.

- +

+ Right camera.This is added to [page:Layers layer 2] - objects to be + rendered by the right camera must also be added to this layer. +

Methods

[method:undefined update]( [param:PerspectiveCamera camera] )

-

- Update the stereo cameras based on the camera passed in. -

+

Update the stereo cameras based on the camera passed in.

Source

diff --git a/docs/api/en/constants/BufferAttributeUsage.html b/docs/api/en/constants/BufferAttributeUsage.html index 91515dfdf05b54..bce5d258564987 100644 --- a/docs/api/en/constants/BufferAttributeUsage.html +++ b/docs/api/en/constants/BufferAttributeUsage.html @@ -10,7 +10,9 @@

Buffer Attribute Usage Constants

- The usage constants can be used to provide a hint to the API regarding how the geometry buffer attribute will be used in order to optimize performance. + The usage constants can be used to provide a hint to the API regarding how + the geometry buffer attribute will be used in order to optimize + performance.

Code Example

@@ -27,20 +29,21 @@

Examples

Geometry Usage

- THREE.StaticDrawUsage - THREE.DynamicDrawUsage + THREE.StaticDrawUsage + THREE.DynamicDrawUsage THREE.StreamDrawUsage - - THREE.StaticReadUsage - THREE.DynamicReadUsage + + THREE.StaticReadUsage + THREE.DynamicReadUsage THREE.StreamReadUsage - - THREE.StaticCopyUsage - THREE.DynamicCopyUsage + + THREE.StaticCopyUsage + THREE.DynamicCopyUsage THREE.StreamCopyUsage - For more detailed information on each of these constants see [link:https://www.khronos.org/opengl/wiki/Buffer_Object#Buffer_Object_Usage this OpenGL documentation]. + For more detailed information on each of these constants see + [link:https://www.khronos.org/opengl/wiki/Buffer_Object#Buffer_Object_Usage this OpenGL documentation].

Source

diff --git a/docs/api/en/constants/Core.html b/docs/api/en/constants/Core.html index a2e74b73091bc8..f7305c9ab83fc1 100644 --- a/docs/api/en/constants/Core.html +++ b/docs/api/en/constants/Core.html @@ -11,8 +11,8 @@

Core Constants

Revision Number

- -THREE.REVISION + +THREE.REVISION
@@ -21,51 +21,51 @@

Revision Number

Color Spaces

-THREE.NoColorSpace -THREE.SRGBColorSpace -THREE.LinearSRGBColorSpace +THREE.NoColorSpace = "" +THREE.SRGBColorSpace = "srgb" +THREE.LinearSRGBColorSpace = "srgb-linear"

- [page:NoColorSpace] defines no specific color space. + [page:NoColorSpace] defines no specific color space. It is commonly used + for textures including normal maps, roughness maps, metalness maps, + ambient occlusion maps, and other non-color data.

- [page:SRGBColorSpace] (“sRGB”) refers to the color space defined by the Rec. 709 primaries, D65 - white point, and nonlinear sRGB transfer functions. sRGB is the default color space in - CSS, and is often found in color palettes and color pickers. Colors expressed in - hexadecimal or CSS notation are typically in the sRGB color space. + [page:SRGBColorSpace] (“srgb”) refers to the color space defined by the + Rec. 709 primaries, D65 white point, and nonlinear sRGB transfer + functions. sRGB is the default color space in CSS, and is often found in + color palettes and color pickers. Colors expressed in hexadecimal or CSS + notation are typically in the sRGB color space.

- [page:LinearSRGBColorSpace] (“Linear-sRGB”) refers to the sRGB color space (above) with - linear transfer functions. Linear-sRGB is the working color space in three.js, used - throughout most of the rendering process. RGB components found in three.js materials - and shaders are in the Linear-sRGB color space. + [page:LinearSRGBColorSpace] (“srgb-linear”) refers to the sRGB color space + (above) with linear transfer functions. Linear-sRGB is the working color + space in three.js, used throughout most of the rendering process. RGB + components found in three.js materials and shaders are in the Linear-sRGB + color space.

-

- For further background and usage, see Color management. -

+

For further background and usage, see Color management.

Mouse Buttons

-THREE.MOUSE.LEFT -THREE.MOUSE.MIDDLE -THREE.MOUSE.RIGHT +THREE.MOUSE.LEFT +THREE.MOUSE.MIDDLE +THREE.MOUSE.RIGHT THREE.MOUSE.ROTATE -THREE.MOUSE.DOLLY +THREE.MOUSE.DOLLY THREE.MOUSE.PAN

- The constants LEFT and ROTATE have the same underlying value. - The constants MIDDLE and DOLLY have the same underlying value. - The constants RIGHT and PAN have the same underlying value. + The constants LEFT and ROTATE have the same underlying value. The + constants MIDDLE and DOLLY have the same underlying value. The constants + RIGHT and PAN have the same underlying value.

Touch Actions

-THREE.TOUCH.ROTATE -THREE.TOUCH.PAN -THREE.TOUCH.DOLLY_PAN +THREE.TOUCH.ROTATE THREE.TOUCH.PAN THREE.TOUCH.DOLLY_PAN THREE.TOUCH.DOLLY_ROTATE @@ -75,6 +75,4 @@

Source

[link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js]

- - diff --git a/docs/api/en/constants/CustomBlendingEquations.html b/docs/api/en/constants/CustomBlendingEquations.html index 0598bb6c79bc3e..f6e9d78d14f4c3 100644 --- a/docs/api/en/constants/CustomBlendingEquations.html +++ b/docs/api/en/constants/CustomBlendingEquations.html @@ -10,49 +10,54 @@

Custom Blending Equation Constants

- These work with all material types. First set the material's blending mode to THREE.CustomBlending, then set the desired Blending Equation, Source Factor and Destination Factor. + These work with all material types. First set the material's blending mode + to THREE.CustomBlending, then set the desired Blending Equation, Source + Factor and Destination Factor.

Code Example

const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); - material.blending = THREE.CustomBlending; - material.blendEquation = THREE.AddEquation; //default - material.blendSrc = THREE.SrcAlphaFactor; //default + material.blending = THREE.CustomBlending; + material.blendEquation = THREE.AddEquation; //default + material.blendSrc = THREE.SrcAlphaFactor; //default material.blendDst = THREE.OneMinusSrcAlphaFactor; //default

Examples

-

[example:webgl_materials_blending_custom materials / blending / custom ]

+

+ [example:webgl_materials_blending_custom materials / blending / custom ] +

Blending Equations

- THREE.AddEquation - THREE.SubtractEquation + THREE.AddEquation + THREE.SubtractEquation THREE.ReverseSubtractEquation - THREE.MinEquation + THREE.MinEquation THREE.MaxEquation

Source Factors

- THREE.ZeroFactor - THREE.OneFactor + THREE.ZeroFactor + THREE.OneFactor THREE.SrcColorFactor - THREE.OneMinusSrcColorFactor + THREE.OneMinusSrcColorFactor THREE.SrcAlphaFactor - THREE.OneMinusSrcAlphaFactor + THREE.OneMinusSrcAlphaFactor THREE.DstAlphaFactor - THREE.OneMinusDstAlphaFactor + THREE.OneMinusDstAlphaFactor THREE.DstColorFactor - THREE.OneMinusDstColorFactor + THREE.OneMinusDstColorFactor THREE.SrcAlphaSaturateFactor

Destination Factors

- All of the Source Factors are valid as Destination Factors, except for THREE.SrcAlphaSaturateFactor + All of the Source Factors are valid as Destination Factors, except for + THREE.SrcAlphaSaturateFactor

Source

diff --git a/docs/api/en/constants/Materials.html b/docs/api/en/constants/Materials.html index 3653d57cc0c9fe..7ffee38f8d0624 100644 --- a/docs/api/en/constants/Materials.html +++ b/docs/api/en/constants/Materials.html @@ -10,138 +10,175 @@

Material Constants

- These constants define properties common to all material types, - with the exception of Texture Combine Operations which only apply to [page:MeshBasicMaterial.combine MeshBasicMaterial], [page:MeshLambertMaterial.combine MeshLambertMaterial] and [page:MeshPhongMaterial.combine MeshPhongMaterial].
+ These constants define properties common to all material types, with the + exception of Texture Combine Operations which only apply to + [page:MeshBasicMaterial.combine MeshBasicMaterial], + [page:MeshLambertMaterial.combine MeshLambertMaterial] and + [page:MeshPhongMaterial.combine MeshPhongMaterial].

-

Side

- THREE.FrontSide - THREE.BackSide + THREE.FrontSide + THREE.BackSide THREE.DoubleSide +

- Defines which side of faces will be rendered - front, back or both. - Default is [page:Constant FrontSide]. + Defines which side of faces will be rendered - front, back or both. + Default is [page:Constant FrontSide].

Blending Mode

- THREE.NoBlending - THREE.NormalBlending + THREE.NoBlending + THREE.NormalBlending THREE.AdditiveBlending - THREE.SubtractiveBlending - THREE.MultiplyBlending + THREE.SubtractiveBlending + THREE.MultiplyBlending THREE.CustomBlending -

- These control the source and destination blending equations for the material's RGB and Alpha sent to the WebGLRenderer for use by WebGL.
- [page:Constant NormalBlending] is the default.
- Note that [page:Constant CustomBlending] must be set to use [page:CustomBlendingEquation Custom Blending Equations].
- See the [example:webgl_materials_blending materials / blending] example.
+ These control the source and destination blending equations for the + material's RGB and Alpha sent to the WebGLRenderer for use by WebGL.
+ [page:Constant NormalBlending] is the default.
+ Note that [page:Constant CustomBlending] must be set to use + [page:CustomBlendingEquation Custom Blending Equations].
+ See the [example:webgl_materials_blending materials / blending] + example.

Depth Mode

THREE.NeverDepth - THREE.AlwaysDepth - THREE.EqualDepth + THREE.AlwaysDepth + THREE.EqualDepth THREE.LessDepth - THREE.LessEqualDepth - THREE.GreaterEqualDepth + THREE.LessEqualDepth + THREE.GreaterEqualDepth THREE.GreaterDepth THREE.NotEqualDepth

- Which depth function the material uses to compare incoming pixels Z-depth against the current Z-depth buffer value. If the result of the comparison is true, the pixel will be drawn.
- [page:Materials NeverDepth] will never return true.
- [page:Materials AlwaysDepth] will always return true.
- [page:Materials EqualDepth] will return true if the incoming pixel Z-depth is equal to the current buffer Z-depth.
- [page:Materials LessDepth] will return true if the incoming pixel Z-depth is less than the current buffer Z-depth.
- [page:Materials LessEqualDepth] is the default and will return true if the incoming pixel Z-depth is less than or equal to the current buffer Z-depth.
- [page:Materials GreaterEqualDepth] will return true if the incoming pixel Z-depth is greater than or equal to the current buffer Z-depth.
- [page:Materials GreaterDepth] will return true if the incoming pixel Z-depth is greater than the current buffer Z-depth.
- [page:Materials NotEqualDepth] will return true if the incoming pixel Z-depth is not equal to the current buffer Z-depth.
+ Which depth function the material uses to compare incoming pixels Z-depth + against the current Z-depth buffer value. If the result of the comparison + is true, the pixel will be drawn.
+ [page:Materials NeverDepth] will never return true.
+ [page:Materials AlwaysDepth] will always return true.
+ [page:Materials EqualDepth] will return true if the incoming pixel Z-depth + is equal to the current buffer Z-depth.
+ [page:Materials LessDepth] will return true if the incoming pixel Z-depth + is less than the current buffer Z-depth.
+ [page:Materials LessEqualDepth] is the default and will return true if the + incoming pixel Z-depth is less than or equal to the current buffer + Z-depth.
+ [page:Materials GreaterEqualDepth] will return true if the incoming pixel + Z-depth is greater than or equal to the current buffer Z-depth.
+ [page:Materials GreaterDepth] will return true if the incoming pixel + Z-depth is greater than the current buffer Z-depth.
+ [page:Materials NotEqualDepth] will return true if the incoming pixel + Z-depth is not equal to the current buffer Z-depth.

Texture Combine Operations

- THREE.MultiplyOperation - THREE.MixOperation + THREE.MultiplyOperation + THREE.MixOperation THREE.AddOperation +

- These define how the result of the surface's color is combined with the environment map (if present), for [page:MeshBasicMaterial.combine MeshBasicMaterial], [page:MeshLambertMaterial.combine MeshLambertMaterial] and [page:MeshPhongMaterial.combine MeshPhongMaterial].
- [page:Constant MultiplyOperation] is the default and multiplies the environment map color with the surface color.
- [page:Constant MixOperation] uses reflectivity to blend between the two colors.
- [page:Constant AddOperation] adds the two colors. + These define how the result of the surface's color is combined with the + environment map (if present), for [page:MeshBasicMaterial.combine MeshBasicMaterial], + [page:MeshLambertMaterial.combine MeshLambertMaterial] + and [page:MeshPhongMaterial.combine MeshPhongMaterial].
+ [page:Constant MultiplyOperation] is the default and multiplies the + environment map color with the surface color.
+ [page:Constant MixOperation] uses reflectivity to blend between the two + colors.
+ [page:Constant AddOperation] adds the two colors.

Stencil Functions

- THREE.NeverStencilFunc - THREE.LessStencilFunc + THREE.NeverStencilFunc + THREE.LessStencilFunc THREE.EqualStencilFunc - THREE.LessEqualStencilFunc + THREE.LessEqualStencilFunc THREE.GreaterStencilFunc - THREE.NotEqualStencilFunc + THREE.NotEqualStencilFunc THREE.GreaterEqualStencilFunc THREE.AlwaysStencilFunc

- Which stencil function the material uses to determine whether or not to perform a stencil operation.
- [page:Materials NeverStencilFunc] will never return true.
- [page:Materials LessStencilFunc] will return true if the stencil reference value is less than the current stencil value.
- [page:Materials EqualStencilFunc] will return true if the stencil reference value is equal to the current stencil value.
- [page:Materials LessEqualStencilFunc] will return true if the stencil reference value is less than or equal to the current stencil value.
- [page:Materials GreaterStencilFunc] will return true if the stencil reference value is greater than the current stencil value.
- [page:Materials NotEqualStencilFunc] will return true if the stencil reference value is not equal to the current stencil value.
- [page:Materials GreaterEqualStencilFunc] will return true if the stencil reference value is greater than or equal to the current stencil value.
- [page:Materials AlwaysStencilFunc] will always return true.
+ Which stencil function the material uses to determine whether or not to + perform a stencil operation.
+ [page:Materials NeverStencilFunc] will never return true.
+ [page:Materials LessStencilFunc] will return true if the stencil reference + value is less than the current stencil value.
+ [page:Materials EqualStencilFunc] will return true if the stencil + reference value is equal to the current stencil value.
+ [page:Materials LessEqualStencilFunc] will return true if the stencil + reference value is less than or equal to the current stencil value.
+ [page:Materials GreaterStencilFunc] will return true if the stencil + reference value is greater than the current stencil value.
+ [page:Materials NotEqualStencilFunc] will return true if the stencil + reference value is not equal to the current stencil value.
+ [page:Materials GreaterEqualStencilFunc] will return true if the stencil + reference value is greater than or equal to the current stencil value.
+ [page:Materials AlwaysStencilFunc] will always return true.

Stencil Operations

- THREE.ZeroStencilOp - THREE.KeepStencilOp + THREE.ZeroStencilOp + THREE.KeepStencilOp THREE.ReplaceStencilOp - THREE.IncrementStencilOp + THREE.IncrementStencilOp THREE.DecrementStencilOp - THREE.IncrementWrapStencilOp + THREE.IncrementWrapStencilOp THREE.DecrementWrapStencilOp THREE.InvertStencilOp

- Which stencil operation the material will perform on the stencil buffer pixel if the provided stencil function passes.
- [page:Materials ZeroStencilOp] will set the stencil value to 0.
- [page:Materials KeepStencilOp] will not change the current stencil value.
- [page:Materials ReplaceStencilOp] will replace the stencil value with the specified stencil reference value.
- [page:Materials IncrementStencilOp] will increment the current stencil value by `1`.
- [page:Materials DecrementStencilOp] will decrement the current stencil value by `1`.
- [page:Materials IncrementWrapStencilOp] will increment the current stencil value by `1`. If the value increments past `255` it will be set to `0`.
- [page:Materials DecrementWrapStencilOp] will increment the current stencil value by `1`. If the value decrements below `0` it will be set to `255`.
- [page:Materials InvertStencilOp] will perform a bitwise inversion of the current stencil value.
+ Which stencil operation the material will perform on the stencil buffer + pixel if the provided stencil function passes.
+ [page:Materials ZeroStencilOp] will set the stencil value to 0.
+ [page:Materials KeepStencilOp] will not change the current stencil + value.
+ [page:Materials ReplaceStencilOp] will replace the stencil value with the + specified stencil reference value.
+ [page:Materials IncrementStencilOp] will increment the current stencil + value by `1`.
+ [page:Materials DecrementStencilOp] will decrement the current stencil + value by `1`.
+ [page:Materials IncrementWrapStencilOp] will increment the current stencil + value by `1`. If the value increments past `255` it will be set to `0`.
+ [page:Materials DecrementWrapStencilOp] will increment the current stencil + value by `1`. If the value decrements below `0` it will be set to + `255`.
+ [page:Materials InvertStencilOp] will perform a bitwise inversion of the + current stencil value.

Normal map type

- THREE.TangentSpaceNormalMap - THREE.ObjectSpaceNormalMap + THREE.TangentSpaceNormalMap + THREE.ObjectSpaceNormalMap +

- Defines the type of the normal map. - For TangentSpaceNormalMap, the information is relative to the underlying surface. - For ObjectSpaceNormalMap, the information is relative to the object orientation. - Default is [page:Constant TangentSpaceNormalMap]. + Defines the type of the normal map. For TangentSpaceNormalMap, the + information is relative to the underlying surface. For + ObjectSpaceNormalMap, the information is relative to the object + orientation. Default is [page:Constant TangentSpaceNormalMap].

GLSL Version

- THREE.GLSL1 - THREE.GLSL3 + THREE.GLSL1 + THREE.GLSL3

Source

diff --git a/docs/api/en/constants/Renderer.html b/docs/api/en/constants/Renderer.html index 20a31b4e215c96..eb68b61af5e8e4 100644 --- a/docs/api/en/constants/Renderer.html +++ b/docs/api/en/constants/Renderer.html @@ -11,57 +11,63 @@

WebGLRenderer Constants

Cull Face Modes

- THREE.CullFaceNone - THREE.CullFaceBack + THREE.CullFaceNone + THREE.CullFaceBack THREE.CullFaceFront THREE.CullFaceFrontBack

- [page:constant CullFaceNone] disables face culling.
- [page:constant CullFaceBack] culls back faces (default).
- [page:constant CullFaceFront] culls front faces.
- [page:constant CullFaceFrontBack] culls both front and back faces. + [page:constant CullFaceNone] disables face culling.
+ [page:constant CullFaceBack] culls back faces (default).
+ [page:constant CullFaceFront] culls front faces.
+ [page:constant CullFaceFrontBack] culls both front and back faces.

Shadow Types

- THREE.BasicShadowMap - THREE.PCFShadowMap + THREE.BasicShadowMap + THREE.PCFShadowMap THREE.PCFSoftShadowMap THREE.VSMShadowMap

- These define the WebGLRenderer's [page:WebGLRenderer.shadowMap.type shadowMap.type] property.

- - [page:constant BasicShadowMap] gives unfiltered shadow maps - fastest, but lowest quality.
- [page:constant PCFShadowMap] filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm (default).
- [page:constant PCFSoftShadowMap] filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm with better soft shadows especially when using low-resolution shadow maps.
- [page:constant VSMShadowMap] filters shadow maps using the Variance Shadow Map (VSM) algorithm. When using VSMShadowMap all shadow receivers will also cast shadows. + These define the WebGLRenderer's [page:WebGLRenderer.shadowMap.type shadowMap.type] property.

+ [page:constant BasicShadowMap] gives unfiltered shadow maps - fastest, but + lowest quality.
+ [page:constant PCFShadowMap] filters shadow maps using the + Percentage-Closer Filtering (PCF) algorithm (default).
+ [page:constant PCFSoftShadowMap] filters shadow maps using the + Percentage-Closer Filtering (PCF) algorithm with better soft shadows + especially when using low-resolution shadow maps.
+ [page:constant VSMShadowMap] filters shadow maps using the Variance Shadow + Map (VSM) algorithm. When using VSMShadowMap all shadow receivers will + also cast shadows.

+

Tone Mapping

- THREE.NoToneMapping - THREE.LinearToneMapping + THREE.NoToneMapping + THREE.LinearToneMapping THREE.ReinhardToneMapping - THREE.CineonToneMapping + THREE.CineonToneMapping THREE.ACESFilmicToneMapping THREE.CustomToneMapping

- These define the WebGLRenderer's [page:WebGLRenderer.toneMapping toneMapping] property. - This is used to approximate the appearance of high dynamic range (HDR) on the - low dynamic range medium of a standard computer monitor or mobile device's screen. + These define the WebGLRenderer's [page:WebGLRenderer.toneMapping toneMapping] property. This is used to approximate the appearance of high + dynamic range (HDR) on the low dynamic range medium of a standard computer + monitor or mobile device's screen.

- THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping and THREE.ACESFilmicToneMapping are built-in implementations of tone mapping. - THREE.CustomToneMapping expects a custom implementation by modyfing GLSL code of the material's fragment shader. - See the [example:webgl_tonemapping WebGL / tonemapping] example. + THREE.LinearToneMapping, THREE.ReinhardToneMapping, + THREE.CineonToneMapping and THREE.ACESFilmicToneMapping are built-in + implementations of tone mapping. THREE.CustomToneMapping expects a custom + implementation by modyfing GLSL code of the material's fragment shader. + See the [example:webgl_tonemapping WebGL / tonemapping] example.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js]

diff --git a/docs/api/en/constants/Textures.html b/docs/api/en/constants/Textures.html index b511e25f252b52..09a055425ca0a6 100644 --- a/docs/api/en/constants/Textures.html +++ b/docs/api/en/constants/Textures.html @@ -12,269 +12,298 @@

Texture Constants

Mapping Modes

THREE.UVMapping - THREE.CubeReflectionMapping + THREE.CubeReflectionMapping THREE.CubeRefractionMapping THREE.EquirectangularReflectionMapping - THREE.EquirectangularRefractionMapping + THREE.EquirectangularRefractionMapping THREE.CubeUVReflectionMapping

- These define the texture's mapping mode.
- [page:Constant UVMapping] is the default, and maps the texture using the mesh's UV coordinates.

- - The rest define environment mapping types.

- - [page:Constant CubeReflectionMapping] and [page:Constant CubeRefractionMapping] are for - use with a [page:CubeTexture CubeTexture], which is made up of six textures, one for each face of the cube. - [page:Constant CubeReflectionMapping] is the default for a [page:CubeTexture CubeTexture].

- - [page:Constant EquirectangularReflectionMapping] and [page:Constant EquirectangularRefractionMapping] - are for use with an equirectangular environment map. Also called a lat-long map, an equirectangular - texture represents a 360-degree view along the horizontal centerline, and a 180-degree view along the - vertical axis, with the top and bottom edges of the image corresponding to the north and south poles - of a mapped sphere.

- - See the [example:webgl_materials_envmaps materials / envmaps] example. + These define the texture's mapping mode.
+ [page:Constant UVMapping] is the default, and maps the texture using the + mesh's UV coordinates.

+ The rest define environment mapping types.

+ [page:Constant CubeReflectionMapping] and [page:Constant CubeRefractionMapping] are for use with a [page:CubeTexture CubeTexture], + which is made up of six textures, one for each face of the cube. + [page:Constant CubeReflectionMapping] is the default for a + [page:CubeTexture CubeTexture].

+ [page:Constant EquirectangularReflectionMapping] and [page:Constant EquirectangularRefractionMapping] are for use with an equirectangular + environment map. Also called a lat-long map, an equirectangular texture + represents a 360-degree view along the horizontal centerline, and a + 180-degree view along the vertical axis, with the top and bottom edges of + the image corresponding to the north and south poles of a mapped + sphere.

+ See the [example:webgl_materials_envmaps materials / envmaps] example.

-

Wrapping Modes

- THREE.RepeatWrapping + THREE.RepeatWrapping THREE.ClampToEdgeWrapping THREE.MirroredRepeatWrapping

- These define the texture's [page:Texture.wrapS wrapS] and [page:Texture.wrapT wrapT] properties, - which define horizontal and vertical texture wrapping.

- - With [page:constant RepeatWrapping] the texture will simply repeat to infinity.

- - [page:constant ClampToEdgeWrapping] is the default. - The last pixel of the texture stretches to the edge of the mesh.

- - With [page:constant MirroredRepeatWrapping] the texture will repeats to infinity, mirroring on each repeat. + These define the texture's [page:Texture.wrapS wrapS] and + [page:Texture.wrapT wrapT] properties, which define horizontal and + vertical texture wrapping.

+ With [page:constant RepeatWrapping] the texture will simply repeat to + infinity.

+ [page:constant ClampToEdgeWrapping] is the default. The last pixel of the + texture stretches to the edge of the mesh.

+ With [page:constant MirroredRepeatWrapping] the texture will repeats to + infinity, mirroring on each repeat.

Magnification Filters

- THREE.NearestFilter + THREE.NearestFilter THREE.LinearFilter

- For use with a texture's [page:Texture.magFilter magFilter] property, - these define the texture magnification function to be used when the pixel being textured maps to an - area less than or equal to one texture element (texel).

- - [page:constant NearestFilter] returns the value of the texture element that is nearest - (in Manhattan distance) to the specified texture coordinates.

- - [page:constant LinearFilter] is the default and returns the weighted average - of the four texture elements that are closest to the specified texture coordinates, - and can include items wrapped or repeated from other parts of a texture, - depending on the values of [page:Texture.wrapS wrapS] and [page:Texture.wrapT wrapT], and on the exact mapping. + For use with a texture's [page:Texture.magFilter magFilter] property, + these define the texture magnification function to be used when the pixel + being textured maps to an area less than or equal to one texture element + (texel).

+ + [page:constant NearestFilter] returns the value of the texture element + that is nearest (in Manhattan distance) to the specified texture + coordinates.

+ + [page:constant LinearFilter] is the default and returns the weighted + average of the four texture elements that are closest to the specified + texture coordinates, and can include items wrapped or repeated from other + parts of a texture, depending on the values of [page:Texture.wrapS wrapS] + and [page:Texture.wrapT wrapT], and on the exact mapping.

Minification Filters

- THREE.NearestFilter + THREE.NearestFilter THREE.NearestMipmapNearestFilter - THREE.NearestMipmapLinearFilter + THREE.NearestMipmapLinearFilter THREE.LinearFilter - THREE.LinearMipmapNearestFilter + THREE.LinearMipmapNearestFilter THREE.LinearMipmapLinearFilter

- For use with a texture's [page:Texture.minFilter minFilter] property, these define - the texture minifying function that is used whenever the pixel being textured maps - to an area greater than one texture element (texel).

- - In addition to [page:constant NearestFilter] and [page:constant LinearFilter], - the following four functions can be used for minification:

- - [page:constant NearestMipmapNearestFilter] chooses the mipmap that most closely - matches the size of the pixel being textured - and uses the [page:constant NearestFilter] criterion (the texel nearest to the - center of the pixel) to produce a texture value.

- - [page:constant NearestMipmapLinearFilter] chooses the two mipmaps that most closely - match the size of the pixel being textured and uses the [page:constant NearestFilter] criterion to produce - a texture value from each mipmap. The final texture value is a weighted average of those two values.

- - [page:constant LinearMipmapNearestFilter] chooses the mipmap that most closely matches - the size of the pixel being textured and uses the [page:constant LinearFilter] criterion - (a weighted average of the four texels that are closest to the center of the pixel) - to produce a texture value.

- - [page:constant LinearMipmapLinearFilter] is the default and chooses the two mipmaps - that most closely match the size of the pixel being textured and uses the [page:constant LinearFilter] criterion - to produce a texture value from each mipmap. The final texture value is a weighted average of those two values.

- - See the [example:webgl_materials_texture_filters materials / texture / filters] example. + For use with a texture's [page:Texture.minFilter minFilter] property, + these define the texture minifying function that is used whenever the + pixel being textured maps to an area greater than one texture element + (texel).

+ + In addition to [page:constant NearestFilter] and [page:constant LinearFilter], the following four functions can be used for + minification:

+ + [page:constant NearestMipmapNearestFilter] chooses the mipmap that most + closely matches the size of the pixel being textured and uses the + [page:constant NearestFilter] criterion (the texel nearest to the center + of the pixel) to produce a texture value.

+ + [page:constant NearestMipmapLinearFilter] chooses the two mipmaps that + most closely match the size of the pixel being textured and uses the + [page:constant NearestFilter] criterion to produce a texture value from + each mipmap. The final texture value is a weighted average of those two + values.

+ + [page:constant LinearMipmapNearestFilter] chooses the mipmap that most + closely matches the size of the pixel being textured and uses the + [page:constant LinearFilter] criterion (a weighted average of the four + texels that are closest to the center of the pixel) to produce a texture + value.

+ + [page:constant LinearMipmapLinearFilter] is the default and chooses the + two mipmaps that most closely match the size of the pixel being textured + and uses the [page:constant LinearFilter] criterion to produce a texture + value from each mipmap. The final texture value is a weighted average of + those two values.

+ + See the [example:webgl_materials_texture_filters materials / texture / filters] example.

Types

- THREE.UnsignedByteType - THREE.ByteType + THREE.UnsignedByteType + THREE.ByteType THREE.ShortType - THREE.UnsignedShortType - THREE.IntType + THREE.UnsignedShortType + THREE.IntType THREE.UnsignedIntType - THREE.FloatType - THREE.HalfFloatType + THREE.FloatType + THREE.HalfFloatType THREE.UnsignedShort4444Type - THREE.UnsignedShort5551Type + THREE.UnsignedShort5551Type THREE.UnsignedInt248Type

- For use with a texture's [page:Texture.type type] property, which must correspond to the correct format. See below for details.

+ For use with a texture's [page:Texture.type type] property, which must + correspond to the correct format. See below for details.

- [page:constant UnsignedByteType] is the default. + [page:constant UnsignedByteType] is the default.

Formats

- THREE.AlphaFormat - THREE.RedFormat - THREE.RedIntegerFormat + THREE.AlphaFormat + THREE.RedFormat + THREE.RedIntegerFormat THREE.RGFormat - THREE.RGIntegerFormat - THREE.RGBAFormat + THREE.RGIntegerFormat + THREE.RGBAFormat THREE.RGBAIntegerFormat - THREE.LuminanceFormat - THREE.LuminanceAlphaFormat + THREE.LuminanceFormat + THREE.LuminanceAlphaFormat THREE.DepthFormat THREE.DepthStencilFormat

- For use with a texture's [page:Texture.format format] property, these define - how elements of a 2d texture, or `texels`, are read by shaders.

- - [page:constant AlphaFormat] discards the red, green and blue components and reads just the alpha component.

- - [page:constant RedFormat] discards the green and blue components and reads just the red component. - (can only be used with a WebGL 2 rendering context). -

- - [page:constant RedIntegerFormat] discards the green and blue components and reads just the red component. - The texels are read as integers instead of floating point. - (can only be used with a WebGL 2 rendering context). -

- - [page:constant RGFormat] discards the alpha, and blue components and reads the red, and green components. - (can only be used with a WebGL 2 rendering context). -

- - [page:constant RGIntegerFormat] discards the alpha, and blue components and reads the red, and green components. - The texels are read as integers instead of floating point. - (can only be used with a WebGL 2 rendering context). -

- - [page:constant RGBAFormat] is the default and reads the red, green, blue and alpha components.

- - [page:constant RGBAIntegerFormat] is the default and reads the red, green, blue and alpha components. - The texels are read as integers instead of floating point. - (can only be used with a WebGL 2 rendering context). -

- - [page:constant LuminanceFormat] reads each element as a single luminance component. - This is then converted to a floating point, clamped to the range [0,1], and then assembled - into an RGBA element by placing the luminance value in the red, green and blue channels, - and attaching 1.0 to the alpha channel.

- - [page:constant LuminanceAlphaFormat] reads each element as a luminance/alpha double. - The same process occurs as for the [page:constant LuminanceFormat], except that the - alpha channel may have values other than `1.0`.

- - [page:constant DepthFormat] reads each element as a single depth value, converts it to floating point, and clamps to the range [0,1]. - This is the default for [page:DepthTexture DepthTexture].

- - [page:constant DepthStencilFormat] reads each element is a pair of depth and stencil values. - The depth component of the pair is interpreted as in [page:constant DepthFormat]. - The stencil component is interpreted based on the depth + stencil internal format. -

- - Note that the texture must have the correct [page:Texture.type type] set, as described above. - See [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D] for details. + For use with a texture's [page:Texture.format format] property, these + define how elements of a 2d texture, or `texels`, are read by shaders.

+ + [page:constant AlphaFormat] discards the red, green and blue components + and reads just the alpha component.

+ + [page:constant RedFormat] discards the green and blue components and reads + just the red component. (can only be used with a WebGL 2 rendering + context). +

+ + [page:constant RedIntegerFormat] discards the green and blue components + and reads just the red component. The texels are read as integers instead + of floating point. (can only be used with a WebGL 2 rendering context). +

+ + [page:constant RGFormat] discards the alpha, and blue components and reads + the red, and green components. (can only be used with a WebGL 2 rendering + context). +

+ + [page:constant RGIntegerFormat] discards the alpha, and blue components + and reads the red, and green components. The texels are read as integers + instead of floating point. (can only be used with a WebGL 2 rendering + context). +

+ + [page:constant RGBAFormat] is the default and reads the red, green, blue + and alpha components.

+ + [page:constant RGBAIntegerFormat] is the default and reads the red, green, + blue and alpha components. The texels are read as integers instead of + floating point. (can only be used with a WebGL 2 rendering context). +

+ + [page:constant LuminanceFormat] reads each element as a single luminance + component. This is then converted to a floating point, clamped to the + range [0,1], and then assembled into an RGBA element by placing the + luminance value in the red, green and blue channels, and attaching 1.0 to + the alpha channel.

+ + [page:constant LuminanceAlphaFormat] reads each element as a + luminance/alpha double. The same process occurs as for the [page:constant LuminanceFormat], except that the alpha channel may have values other than + `1.0`.

+ + [page:constant DepthFormat] reads each element as a single depth value, + converts it to floating point, and clamps to the range [0,1]. This is the + default for [page:DepthTexture DepthTexture].

+ + [page:constant DepthStencilFormat] reads each element is a pair of depth + and stencil values. The depth component of the pair is interpreted as in + [page:constant DepthFormat]. The stencil component is interpreted based on + the depth + stencil internal format. +

+ + Note that the texture must have the correct [page:Texture.type type] set, + as described above. See + [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D] for details.

DDS / ST3C Compressed Texture Formats

- THREE.RGB_S3TC_DXT1_Format + THREE.RGB_S3TC_DXT1_Format THREE.RGBA_S3TC_DXT1_Format - THREE.RGBA_S3TC_DXT3_Format + THREE.RGBA_S3TC_DXT3_Format THREE.RGBA_S3TC_DXT5_Format

- For use with a [page:CompressedTexture CompressedTexture]'s [page:Texture.format format] property, - these require support for the - [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/ WEBGL_compressed_texture_s3tc] - extension.

- - There are four [link:https://en.wikipedia.org/wiki/S3_Texture_Compression S3TC] formats available via this extension. These are:
- [page:constant RGB_S3TC_DXT1_Format]: A DXT1-compressed image in an RGB image format.
- [page:constant RGBA_S3TC_DXT1_Format]: A DXT1-compressed image in an RGB image format with a simple on/off alpha value.
- [page:constant RGBA_S3TC_DXT3_Format]: A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression.
- [page:constant RGBA_S3TC_DXT5_Format]: A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3 compression in how the alpha compression is done.
+ For use with a [page:CompressedTexture CompressedTexture]'s + [page:Texture.format format] property, these require support for the + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/ WEBGL_compressed_texture_s3tc] extension.

+ + There are four [link:https://en.wikipedia.org/wiki/S3_Texture_Compression S3TC] formats available via this extension. These are:
+ [page:constant RGB_S3TC_DXT1_Format]: A DXT1-compressed image in an RGB + image format.
+ [page:constant RGBA_S3TC_DXT1_Format]: A DXT1-compressed image in an RGB + image format with a simple on/off alpha value.
+ [page:constant RGBA_S3TC_DXT3_Format]: A DXT3-compressed image in an RGBA + image format. Compared to a 32-bit RGBA texture, it offers 4:1 + compression.
+ [page:constant RGBA_S3TC_DXT5_Format]: A DXT5-compressed image in an RGBA + image format. It also provides a 4:1 compression, but differs to the DXT3 + compression in how the alpha compression is done.

PVRTC Compressed Texture Formats

THREE.RGB_PVRTC_4BPPV1_Format THREE.RGB_PVRTC_2BPPV1_Format - THREE.RGBA_PVRTC_4BPPV1_Format + THREE.RGBA_PVRTC_4BPPV1_Format THREE.RGBA_PVRTC_2BPPV1_Format

- For use with a [page:CompressedTexture CompressedTexture]'s [page:Texture.format format] property, - these require support for the [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/ WEBGL_compressed_texture_pvrtc] - extension.
- PVRTC is typically only available on mobile devices with PowerVR chipsets, which are mainly Apple devices.

- - There are four [link:https://en.wikipedia.org/wiki/PVRTC PVRTC] formats available via this extension. These are:
- [page:constant RGB_PVRTC_4BPPV1_Format]: RGB compression in 4-bit mode. One block for each 4×4 pixels.
- [page:constant RGB_PVRTC_2BPPV1_Format]: RGB compression in 2-bit mode. One block for each 8×4 pixels.
- [page:constant RGBA_PVRTC_4BPPV1_Format]: RGBA compression in 4-bit mode. One block for each 4×4 pixels.
- [page:constant RGBA_PVRTC_2BPPV1_Format]: RGBA compression in 2-bit mode. One block for each 8×4 pixels.
+ For use with a [page:CompressedTexture CompressedTexture]'s + [page:Texture.format format] property, these require support for the + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/ WEBGL_compressed_texture_pvrtc] extension.
+ PVRTC is typically only available on mobile devices with PowerVR chipsets, + which are mainly Apple devices.

+ + There are four [link:https://en.wikipedia.org/wiki/PVRTC PVRTC] formats + available via this extension. These are:
+ [page:constant RGB_PVRTC_4BPPV1_Format]: RGB compression in 4-bit mode. + One block for each 4×4 pixels.
+ [page:constant RGB_PVRTC_2BPPV1_Format]: RGB compression in 2-bit mode. + One block for each 8×4 pixels.
+ [page:constant RGBA_PVRTC_4BPPV1_Format]: RGBA compression in 4-bit mode. + One block for each 4×4 pixels.
+ [page:constant RGBA_PVRTC_2BPPV1_Format]: RGBA compression in 2-bit mode. + One block for each 8×4 pixels.

ETC Compressed Texture Format

- THREE.RGB_ETC1_Format - THREE.RGB_ETC2_Format + THREE.RGB_ETC1_Format + THREE.RGB_ETC2_Format THREE.RGBA_ETC2_EAC_Format

- For use with a [page:CompressedTexture CompressedTexture]'s [page:Texture.format format] property, - these require support for the [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/ WEBGL_compressed_texture_etc1] - (ETC1) or [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc/ WEBGL_compressed_texture_etc] - (ETC2) extensions.

+ For use with a [page:CompressedTexture CompressedTexture]'s + [page:Texture.format format] property, these require support for the + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/ WEBGL_compressed_texture_etc1] (ETC1) or + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc/ WEBGL_compressed_texture_etc] (ETC2) extensions.

ASTC Compressed Texture Format

- THREE.RGBA_ASTC_4x4_Format + THREE.RGBA_ASTC_4x4_Format THREE.RGBA_ASTC_5x4_Format - THREE.RGBA_ASTC_5x5_Format + THREE.RGBA_ASTC_5x5_Format THREE.RGBA_ASTC_6x5_Format - THREE.RGBA_ASTC_6x6_Format + THREE.RGBA_ASTC_6x6_Format THREE.RGBA_ASTC_8x5_Format - THREE.RGBA_ASTC_8x6_Format + THREE.RGBA_ASTC_8x6_Format THREE.RGBA_ASTC_8x8_Format - THREE.RGBA_ASTC_10x5_Format + THREE.RGBA_ASTC_10x5_Format THREE.RGBA_ASTC_10x6_Format - THREE.RGBA_ASTC_10x8_Format + THREE.RGBA_ASTC_10x8_Format THREE.RGBA_ASTC_10x10_Format - THREE.RGBA_ASTC_12x10_Format + THREE.RGBA_ASTC_12x10_Format THREE.RGBA_ASTC_12x12_Format

- For use with a [page:CompressedTexture CompressedTexture]'s [page:Texture.format format] property, - these require support for the [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_astc/ WEBGL_compressed_texture_astc] extension.

+ For use with a [page:CompressedTexture CompressedTexture]'s + [page:Texture.format format] property, these require support for the + [link:https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_astc/ WEBGL_compressed_texture_astc] extension.

BPTC Compressed Texture Format

@@ -282,10 +311,23 @@

BPTC Compressed Texture Format

THREE.RGBA_BPTC_Format

- For use with a [page:CompressedTexture CompressedTexture]'s [page:Texture.format format] property, - these require support for the [link:https://www.khronos.org/registry/webgl/extensions/EXT_texture_compression_bptc/ EXT_texture_compression_bptc] extension.

+ For use with a [page:CompressedTexture CompressedTexture]'s + [page:Texture.format format] property, these require support for the + [link:https://www.khronos.org/registry/webgl/extensions/EXT_texture_compression_bptc/ EXT_texture_compression_bptc] extension.

+

Texture Comparison functions

+ + THREE.NeverCompare + THREE.LessCompare + THREE.EqualCompare + THREE.LessEqualCompare + THREE.GreaterCompare + THREE.NotEqualCompare + THREE.GreaterEqualCompare + THREE.AlwaysCompare + +

Internal Formats

'ALPHA' @@ -351,213 +393,239 @@

Internal Formats

+ Heads up: changing the internal format of a texture will only affect the + texture when using a WebGL 2 rendering context.

- Heads up: changing the internal format of a texture will only affect the - texture when using a WebGL 2 rendering context.

- - For use with a texture's [page:Texture.internalFormat internalFormat] property, - these define how elements of a texture, or `texels`, are stored on the GPU.

- - [page:constant R8] stores the red component on 8 bits.

+ For use with a texture's [page:Texture.internalFormat internalFormat] + property, these define how elements of a texture, or `texels`, are stored + on the GPU.

- [page:constant R8_SNORM] stores the red component on 8 bits. The component is stored as normalized.

+ [page:constant R8] stores the red component on 8 bits.

- [page:constant R8I] stores the red component on 8 bits. The component is stored as an integer.

+ [page:constant R8_SNORM] stores the red component on 8 bits. The component + is stored as normalized.

- [page:constant R8UI] stores the red component on 8 bits. The component is stored as an unsigned integer.

+ [page:constant R8I] stores the red component on 8 bits. The component is + stored as an integer.

- [page:constant R16I] stores the red component on 16 bits. The component is stored as an integer.

+ [page:constant R8UI] stores the red component on 8 bits. The component is + stored as an unsigned integer.

- [page:constant R16UI] stores the red component on 16 bits. The component is stored as an unsigned integer.

+ [page:constant R16I] stores the red component on 16 bits. The component is + stored as an integer.

- [page:constant R16F] stores the red component on 16 bits. The component is stored as floating point.

+ [page:constant R16UI] stores the red component on 16 bits. The component + is stored as an unsigned integer.

- [page:constant R32I] stores the red component on 32 bits. The component is stored as an integer.

+ [page:constant R16F] stores the red component on 16 bits. The component is + stored as floating point.

- [page:constant R32UI] stores the red component on 32 bits. The component is stored as an unsigned integer.

+ [page:constant R32I] stores the red component on 32 bits. The component is + stored as an integer.

- [page:constant R32F] stores the red component on 32 bits. The component is stored as floating point.

+ [page:constant R32UI] stores the red component on 32 bits. The component + is stored as an unsigned integer.

- [page:constant RG8] stores the red and green components on 8 bits each.

+ [page:constant R32F] stores the red component on 32 bits. The component is + stored as floating point.

- [page:constant RG8_SNORM] stores the red and green components on 8 bits each. - Every component is stored as normalized. -

+ [page:constant RG8] stores the red and green components on 8 bits each.

- [page:constant RG8I] stores the red and green components on 8 bits each. - Every component is stored as an integer. -

+ [page:constant RG8_SNORM] stores the red and green components on 8 bits + each. Every component is stored as normalized. +

- [page:constant RG8UI] stores the red and green components on 8 bits each. - Every component is stored as an unsigned integer. -

+ [page:constant RG8I] stores the red and green components on 8 bits each. + Every component is stored as an integer. +

- [page:constant RG16I] stores the red and green components on 16 bits each. - Every component is stored as an integer. -

+ [page:constant RG8UI] stores the red and green components on 8 bits each. + Every component is stored as an unsigned integer. +

- [page:constant RG16UI] stores the red and green components on 16 bits each. - Every component is stored as an unsigned integer. -

+ [page:constant RG16I] stores the red and green components on 16 bits each. + Every component is stored as an integer. +

- [page:constant RG16F] stores the red and green components on 16 bits each. - Every component is stored as floating point. -

+ [page:constant RG16UI] stores the red and green components on 16 bits + each. Every component is stored as an unsigned integer. +

- [page:constant RG32I] stores the red and green components on 32 bits each. - Every component is stored as an integer. -

+ [page:constant RG16F] stores the red and green components on 16 bits each. + Every component is stored as floating point. +

- [page:constant RG32UI] stores the red and green components on 32 bits. - Every component is stored as an unsigned integer. -

+ [page:constant RG32I] stores the red and green components on 32 bits each. + Every component is stored as an integer. +

- [page:constant RG32F] stores the red and green components on 32 bits. - Every component is stored as floating point. -

+ [page:constant RG32UI] stores the red and green components on 32 bits. + Every component is stored as an unsigned integer. +

- [page:constant RGB8] stores the red, green, and blue components on 8 bits each. + [page:constant RG32F] stores the red and green components on 32 bits. + Every component is stored as floating point. +

- [page:constant RGB8_SNORM] stores the red, green, and blue components on 8 bits each. - Every component is stored as normalized. -

+ [page:constant RGB8] stores the red, green, and blue components on 8 bits + each. [page:constant RGB8_SNORM] stores the red, green, and blue + components on 8 bits each. Every component is stored as normalized. +

- [page:constant RGB8I] stores the red, green, and blue components on 8 bits each. - Every component is stored as an integer. -

+ [page:constant RGB8I] stores the red, green, and blue components on 8 bits + each. Every component is stored as an integer. +

- [page:constant RGB8UI] stores the red, green, and blue components on 8 bits each. - Every component is stored as an unsigned integer. -

+ [page:constant RGB8UI] stores the red, green, and blue components on 8 + bits each. Every component is stored as an unsigned integer. +

- [page:constant RGB16I] stores the red, green, and blue components on 16 bits each. - Every component is stored as an integer. -

+ [page:constant RGB16I] stores the red, green, and blue components on 16 + bits each. Every component is stored as an integer. +

- [page:constant RGB16UI] stores the red, green, and blue components on 16 bits each. - Every component is stored as an unsigned integer. -

+ [page:constant RGB16UI] stores the red, green, and blue components on 16 + bits each. Every component is stored as an unsigned integer. +

- [page:constant RGB16F] stores the red, green, and blue components on 16 bits each. - Every component is stored as floating point -

+ [page:constant RGB16F] stores the red, green, and blue components on 16 + bits each. Every component is stored as floating point +

- [page:constant RGB32I] stores the red, green, and blue components on 32 bits each. - Every component is stored as an integer. -

+ [page:constant RGB32I] stores the red, green, and blue components on 32 + bits each. Every component is stored as an integer. +

- [page:constant RGB32UI] stores the red, green, and blue components on 32 bits each. - Every component is stored as an unsigned integer. -

+ [page:constant RGB32UI] stores the red, green, and blue components on 32 + bits each. Every component is stored as an unsigned integer. +

- [page:constant RGB32F] stores the red, green, and blue components on 32 bits each. - Every component is stored as floating point -

+ [page:constant RGB32F] stores the red, green, and blue components on 32 + bits each. Every component is stored as floating point +

- [page:constant R11F_G11F_B10F] stores the red, green, and blue components respectively on 11 bits, 11 bits, and 10bits. - Every component is stored as floating point. -

+ [page:constant R11F_G11F_B10F] stores the red, green, and blue components + respectively on 11 bits, 11 bits, and 10bits. Every component is stored as + floating point. +

- [page:constant RGB565] stores the red, green, and blue components respectively on 5 bits, 6 bits, and 5 bits.

+ [page:constant RGB565] stores the red, green, and blue components + respectively on 5 bits, 6 bits, and 5 bits.

- [page:constant RGB9_E5] stores the red, green, and blue components on 9 bits each.

+ [page:constant RGB9_E5] stores the red, green, and blue components on 9 + bits each.

- [page:constant RGBA8] stores the red, green, blue, and alpha components on 8 bits each.

+ [page:constant RGBA8] stores the red, green, blue, and alpha components on + 8 bits each.

- [page:constant RGBA8_SNORM] stores the red, green, blue, and alpha components on 8 bits. - Every component is stored as normalized. -

+ [page:constant RGBA8_SNORM] stores the red, green, blue, and alpha + components on 8 bits. Every component is stored as normalized. +

- [page:constant RGBA8I] stores the red, green, blue, and alpha components on 8 bits each. - Every component is stored as an integer. -

+ [page:constant RGBA8I] stores the red, green, blue, and alpha components + on 8 bits each. Every component is stored as an integer. +

- [page:constant RGBA8UI] stores the red, green, blue, and alpha components on 8 bits. - Every component is stored as an unsigned integer. -

+ [page:constant RGBA8UI] stores the red, green, blue, and alpha components + on 8 bits. Every component is stored as an unsigned integer. +

- [page:constant RGBA16I] stores the red, green, blue, and alpha components on 16 bits. - Every component is stored as an integer. -

+ [page:constant RGBA16I] stores the red, green, blue, and alpha components + on 16 bits. Every component is stored as an integer. +

- [page:constant RGBA16UI] stores the red, green, blue, and alpha components on 16 bits. - Every component is stored as an unsigned integer. -

+ [page:constant RGBA16UI] stores the red, green, blue, and alpha components + on 16 bits. Every component is stored as an unsigned integer. +

- [page:constant RGBA16F] stores the red, green, blue, and alpha components on 16 bits. - Every component is stored as floating point. -

+ [page:constant RGBA16F] stores the red, green, blue, and alpha components + on 16 bits. Every component is stored as floating point. +

- [page:constant RGBA32I] stores the red, green, blue, and alpha components on 32 bits. - Every component is stored as an integer. -

+ [page:constant RGBA32I] stores the red, green, blue, and alpha components + on 32 bits. Every component is stored as an integer. +

- [page:constant RGBA32UI] stores the red, green, blue, and alpha components on 32 bits. - Every component is stored as an unsigned integer. -

+ [page:constant RGBA32UI] stores the red, green, blue, and alpha components + on 32 bits. Every component is stored as an unsigned integer. +

- [page:constant RGBA32F] stores the red, green, blue, and alpha components on 32 bits. - Every component is stored as floating point. -

+ [page:constant RGBA32F] stores the red, green, blue, and alpha components + on 32 bits. Every component is stored as floating point. +

- [page:constant RGB5_A1] stores the red, green, blue, and alpha components respectively on 5 bits, 5 bits, 5 bits, and 1 bit.

+ [page:constant RGB5_A1] stores the red, green, blue, and alpha components + respectively on 5 bits, 5 bits, 5 bits, and 1 bit.

- [page:constant RGB10_A2] stores the red, green, blue, and alpha components respectively on 10 bits, 10 bits, 10 bits and 2 bits.

+ [page:constant RGB10_A2] stores the red, green, blue, and alpha components + respectively on 10 bits, 10 bits, 10 bits and 2 bits.

- [page:constant RGB10_A2UI] stores the red, green, blue, and alpha components respectively on 10 bits, 10 bits, 10 bits and 2 bits. - Every component is stored as an unsigned integer. -

+ [page:constant RGB10_A2UI] stores the red, green, blue, and alpha + components respectively on 10 bits, 10 bits, 10 bits and 2 bits. Every + component is stored as an unsigned integer. +

- [page:constant SRGB8] stores the red, green, and blue components on 8 bits each.

+ [page:constant SRGB8] stores the red, green, and blue components on 8 bits + each.

- [page:constant SRGB8_ALPHA8] stores the red, green, blue, and alpha components on 8 bits each.

+ [page:constant SRGB8_ALPHA8] stores the red, green, blue, and alpha + components on 8 bits each.

- [page:constant DEPTH_COMPONENT16] stores the depth component on 16bits.

+ [page:constant DEPTH_COMPONENT16] stores the depth component on 16bits.

- [page:constant DEPTH_COMPONENT24] stores the depth component on 24bits.

+ [page:constant DEPTH_COMPONENT24] stores the depth component on 24bits.

- [page:constant DEPTH_COMPONENT32F] stores the depth component on 32bits. The component is stored as floating point.

+ [page:constant DEPTH_COMPONENT32F] stores the depth component on 32bits. + The component is stored as floating point.

- [page:constant DEPTH24_STENCIL8] stores the depth, and stencil components respectively on 24 bits and 8 bits. - The stencil component is stored as an unsigned integer. -

+ [page:constant DEPTH24_STENCIL8] stores the depth, and stencil components + respectively on 24 bits and 8 bits. The stencil component is stored as an + unsigned integer. +

- [page:constant DEPTH32F_STENCIL8] stores the depth, and stencil components respectively on 32 bits and 8 bits. - The depth component is stored as floating point, and the stencil component as an unsigned integer. -

+ [page:constant DEPTH32F_STENCIL8] stores the depth, and stencil components + respectively on 32 bits and 8 bits. The depth component is stored as + floating point, and the stencil component as an unsigned integer. +

- Note that the texture must have the correct [page:Texture.type type] set, - as well as the correct [page:Texture.format format]. + Note that the texture must have the correct [page:Texture.type type] set, + as well as the correct [page:Texture.format format]. See + [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D], and + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texImage3D WebGL2RenderingContext.texImage3D], for more details regarding the + possible combination of [page:Texture.format format], + [page:Texture.internalFormat internalFormat], and [page:Texture.type type].

- See [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D], and - [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texImage3D WebGL2RenderingContext.texImage3D], - for more details regarding the possible combination of [page:Texture.format format], [page:Texture.internalFormat internalFormat], - and [page:Texture.type type].

- - For more in-depth information regarding internal formats, you can also refer directly - to the [link:https://www.khronos.org/registry/webgl/specs/latest/2.0/ WebGL2 Specification] and - to the [link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0 Specification]. + For more in-depth information regarding internal formats, you can also + refer directly to the + [link:https://www.khronos.org/registry/webgl/specs/latest/2.0/ WebGL2 Specification] and to the + [link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0 Specification].

-

Encoding

+

Depth Packing

- THREE.LinearEncoding - THREE.sRGBEncoding - THREE.BasicDepthPacking + THREE.BasicDepthPacking THREE.RGBADepthPacking

- For use with a Texture's [page:Texture.encoding encoding] property.

+ For use with the [page:MeshDepthMaterial.depthPacking depthPacking] + property of `MeshDepthMaterial`. +

- If the encoding type is changed after the texture has already been used by a material, - you will need to set [page:Material.needsUpdate Material.needsUpdate] to `true` to make the material recompile.

+

Color Space

+ + THREE.NoColorSpace = "" + THREE.SRGBColorSpace = "srgb" + THREE.LinearSRGBColorSpace = "srgb-linear" + +

+ Used to define the color space of textures (and the output color space of + the renderer).

- [page:constant LinearEncoding] is the default. - Values other than this are only valid for a material's map, envMap and emissiveMap. + If the color space type is changed after the texture has already been used + by a material, you will need to set [page:Material.needsUpdate Material.needsUpdate] to `true` to make the material recompile.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js]

diff --git a/docs/api/en/core/BufferAttribute.html b/docs/api/en/core/BufferAttribute.html index 02b3832453f566..ba570b79039182 100644 --- a/docs/api/en/core/BufferAttribute.html +++ b/docs/api/en/core/BufferAttribute.html @@ -10,202 +10,241 @@

[name]

- This class stores data for an attribute (such as vertex positions, face indices, normals, - colors, UVs, and any custom attributes ) associated with a [page:BufferGeometry], which allows - for more efficient passing of data to the GPU. See that page for details and a usage example. - When working with vector-like data, the .fromBufferAttribute( attribute, index ) - helper methods on [page:Vector2.fromBufferAttribute Vector2], - [page:Vector3.fromBufferAttribute Vector3], - [page:Vector4.fromBufferAttribute Vector4], and - [page:Color.fromBufferAttribute Color] classes may be helpful. + This class stores data for an attribute (such as vertex positions, face + indices, normals, colors, UVs, and any custom attributes ) associated with + a [page:BufferGeometry], which allows for more efficient passing of data + to the GPU. See that page for details and a usage example. When working + with vector-like data, the .fromBufferAttribute( attribute, index ) + helper methods on [page:Vector2.fromBufferAttribute Vector2], + [page:Vector3.fromBufferAttribute Vector3], + [page:Vector4.fromBufferAttribute Vector4], and + [page:Color.fromBufferAttribute Color] classes may be helpful.

Constructor

[name]( [param:TypedArray array], [param:Integer itemSize], [param:Boolean normalized] )

- [page:TypedArray array] -- Must be a [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/TypedArray TypedArray]. - Used to instantiate the buffer.
- This array should have - itemSize * numVertices - elements, where numVertices is the number of vertices in the associated [page:BufferGeometry BufferGeometry].

- - - [page:Integer itemSize] -- the number of values of the array that should be associated with - a particular vertex. For instance, if this - attribute is storing a 3-component vector (such as a position, normal, or color), then itemSize should be 3. -

- - [page:Boolean normalized] -- (optional) Applies to integer data only. Indicates how the underlying data - in the buffer maps to the values in the GLSL code. For instance, if [page:TypedArray array] is an instance - of UInt16Array, and [page:Boolean normalized] is true, the values `0 - +65535` in the array - data will be mapped to 0.0f - +1.0f in the GLSL attribute. An Int16Array (signed) would map - from -32768 - +32767 to -1.0f - +1.0f. If [page:Boolean normalized] is false, the values - will be converted to floats unmodified, i.e. 32767 becomes 32767.0f. + [page:TypedArray array] -- Must be a + [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/TypedArray TypedArray]. Used to instantiate the buffer.
+ This array should have + + itemSize * numVertices + + elements, where numVertices is the number of vertices in the associated + [page:BufferGemetry BufferGeometry].

+ + [page:Integer itemSize] -- the number of values of the array that should + be associated with a particular vertex. For instance, if this attribute is + storing a 3-component vector (such as a position, normal, or color), then + itemSize should be 3. +

+ + [page:Boolean normalized] -- (optional) Applies to integer data only. + Indicates how the underlying data in the buffer maps to the values in the + GLSL code. For instance, if [page:TypedArray array] is an instance of + UInt16Array, and [page:Boolean normalized] is true, the values `0 - + +65535` in the array data will be mapped to 0.0f - +1.0f in the GLSL + attribute. An Int16Array (signed) would map from -32768 - +32767 to -1.0f + - +1.0f. If [page:Boolean normalized] is false, the values will be + converted to floats unmodified, i.e. 32767 becomes 32767.0f.

Properties

[property:TypedArray array]

-

- The [page:TypedArray array] holding data stored in the buffer. -

+

The [page:TypedArray array] holding data stored in the buffer.

[property:Integer count]

- Stores the [page:BufferAttribute.array array]'s length divided by the [page:BufferAttribute.itemSize itemSize].

+ Stores the [page:BufferAttribute.array array]'s length divided by the + [page:BufferAttribute.itemSize itemSize].

- If the buffer is storing a 3-component vector (such as a position, normal, or color), - then this will count the number of such vectors stored. + If the buffer is storing a 3-component vector (such as a position, normal, + or color), then this will count the number of such vectors stored.

-

[property:Boolean isBufferAttribute]

+

[property:Number gpuType]

- Read-only flag to check if a given object is of type [name]. + Configures the bound GPU type for use in shaders. Either [page:BufferAttribute THREE.FloatType] or [page:BufferAttribute THREE.IntType], default is [page:BufferAttribute THREE.FloatType]. + + Note: this only has an effect for integer arrays and is not configurable for float arrays. For lower precision float types, see [page:BufferAttributeTypes THREE.Float16BufferAttribute].

-

[property:Integer itemSize]

-

The length of vectors that are being stored in the [page:BufferAttribute.array array].

+

[property:Boolean isBufferAttribute]

+

Read-only flag to check if a given object is of type [name].

-

[property:String name]

+

[property:Integer itemSize]

- Optional name for this attribute instance. Default is an empty string. + The length of vectors that are being stored in the + [page:BufferAttribute.array array].

+

[property:String name]

+

Optional name for this attribute instance. Default is an empty string.

+

[property:Boolean needsUpdate]

- Flag to indicate that this attribute has changed and should be re-sent to the GPU. - Set this to true when you modify the value of the array.

+ Flag to indicate that this attribute has changed and should be re-sent to + the GPU. Set this to true when you modify the value of the array.

- Setting this to true also increments the [page:BufferAttribute.version version]. + Setting this to true also increments the [page:BufferAttribute.version version].

[property:Boolean normalized]

- Indicates how the underlying data in the buffer maps to the values in the GLSL shader code. - See the constructor above for details. + Indicates how the underlying data in the buffer maps to the values in the + GLSL shader code. See the constructor above for details.

[property:Function onUploadCallback]

- A callback function that is executed after the Renderer has transferred the attribute array data to the GPU. + A callback function that is executed after the Renderer has transferred + the attribute array data to the GPU.

[property:Object updateRange]

-

Object containing:
- [page:Integer offset]: Default is `0`. Position at which to start update.
- [page:Integer count]: Default is `-1`, which means don't use update ranges.

+

+ Object containing:
+ [page:Integer offset]: Default is `0`. Position at which to start + update.
+ [page:Integer count]: Default is `-1`, which means don't use update + ranges.

- This can be used to only update some components of stored vectors (for example, just the component - related to color). + This can be used to only update some components of stored vectors (for + example, just the component related to color).

[property:Usage usage]

- Defines the intended usage pattern of the data store for optimization purposes. Corresponds to the `usage` parameter of - [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData](). - Default is [page:BufferAttributeUsage StaticDrawUsage]. See usage [page:BufferAttributeUsage constants] for all possible values.

- - Note: After the initial use of a buffer, its usage cannot be changed. Instead, instantiate a new one and set the desired usage before the next render. + Defines the intended usage pattern of the data store for optimization + purposes. Corresponds to the `usage` parameter of + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData](). Default is [page:BufferAttributeUsage StaticDrawUsage]. See usage [page:BufferAttributeUsage constants] for all + possible values.

+ + Note: After the initial use of a buffer, its usage cannot be changed. + Instead, instantiate a new one and set the desired usage before the next + render.

[property:Integer version]

-

A version number, incremented every time the [page:BufferAttribute.needsUpdate needsUpdate] property is set to true.

+

+ A version number, incremented every time the + [page:BufferAttribute.needsUpdate needsUpdate] property is set to true. +

Methods

[method:this applyMatrix3]( [param:Matrix3 m] )

-

Applies matrix [page:Matrix3 m] to every Vector3 element of this BufferAttribute.

+

+ Applies matrix [page:Matrix3 m] to every Vector3 element of this + BufferAttribute. +

[method:this applyMatrix4]( [param:Matrix4 m] )

-

Applies matrix [page:Matrix4 m] to every Vector3 element of this BufferAttribute.

+

+ Applies matrix [page:Matrix4 m] to every Vector3 element of this + BufferAttribute. +

[method:this applyNormalMatrix]( [param:Matrix3 m] )

-

Applies normal matrix [page:Matrix3 m] to every Vector3 element of this BufferAttribute.

+

+ Applies normal matrix [page:Matrix3 m] to every Vector3 element of this + BufferAttribute. +

[method:this transformDirection]( [param:Matrix4 m] )

-

Applies matrix [page:Matrix4 m] to every Vector3 element of this BufferAttribute, interpreting the elements as a direction vectors.

+

+ Applies matrix [page:Matrix4 m] to every Vector3 element of this + BufferAttribute, interpreting the elements as a direction vectors. +

-

[method:BufferAttribute clone]()

+

[method:BufferAttribute clone]()

Return a copy of this bufferAttribute.

[method:this copy]( [param:BufferAttribute bufferAttribute] )

Copies another BufferAttribute to this BufferAttribute.

-

[method:this copyArray]( array )

-

Copy the array given here (which can be a normal array or TypedArray) into +

[method:this copyArray]( array )

+

+ Copy the array given here (which can be a normal array or TypedArray) into [page:BufferAttribute.array array].

- See [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set TypedArray.set] - for notes on requirements if copying a TypedArray. + See + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set TypedArray.set] for notes on requirements if copying a TypedArray.

-

[method:this copyAt] ( [param:Integer index1], [param:BufferAttribute bufferAttribute], [param:Integer index2] )

+

[method:this copyAt] ( [param:Integer index1], [param:BufferAttribute bufferAttribute], [param:Integer index2] )

Copy a vector from bufferAttribute[index2] to [page:BufferAttribute.array array][index1].

-

[method:Number getX]( [param:Integer index] )

+

[method:Number getX]( [param:Integer index] )

Returns the x component of the vector at the given index.

-

[method:Number getY]( [param:Integer index] )

+

[method:Number getY]( [param:Integer index] )

Returns the y component of the vector at the given index.

-

[method:Number getZ]( [param:Integer index] )

+

[method:Number getZ]( [param:Integer index] )

Returns the z component of the vector at the given index.

-

[method:Number getW]( [param:Integer index] )

+

[method:Number getW]( [param:Integer index] )

Returns the w component of the vector at the given index.

-

[method:this onUpload]( [param:Function callback] )

+

[method:this onUpload]( [param:Function callback] )

- Sets the value of the onUploadCallback property.

+ Sets the value of the onUploadCallback property.

- In the [example:webgl_buffergeometry WebGL / Buffergeometry] this is used to free memory - after the buffer has been transferred to the GPU. + In the [example:webgl_buffergeometry WebGL / Buffergeometry] this is used + to free memory after the buffer has been transferred to the GPU.

-

[method:this set] ( [param:Array value], [param:Integer offset] )

+

[method:this set] ( [param:Array value], [param:Integer offset] )

- value -- an [page:Array] or [page:TypedArray] from which to copy values.
- offset -- (optional) index of the [page:BufferAttribute.array array] at which to start copying.

+ value -- an [page:Array] or [page:TypedArray] from which to copy values. +
+ offset -- (optional) index of the [page:BufferAttribute.array array] at + which to start copying.

- Calls [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set TypedArray.set]( [page:Array value], [page:Integer offset] ) - on the [page:BufferAttribute.array array].

+ Calls + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set TypedArray.set]( [page:Array value], [page:Integer offset] ) on the + [page:BufferAttribute.array array].

- In particular, see that page for requirements on [page:Array value] - being a [page:TypedArray]. + In particular, see that page for requirements on [page:Array value] being + a [page:TypedArray].

-

[method:this setUsage] ( [param:Usage value] )

+

[method:this setUsage] ( [param:Usage value] )

- Set [page:BufferAttribute.usage usage] to value. See usage [page:BufferAttributeUsage constants] for all possible input values.

+ Set [page:BufferAttribute.usage usage] to value. See usage + [page:BufferAttributeUsage constants] for all possible input values. +

- Note: After the initial use of a buffer, its usage cannot be changed. Instead, instantiate a new one and set the desired usage before the next render. + Note: After the initial use of a buffer, its usage cannot be changed. + Instead, instantiate a new one and set the desired usage before the next + render.

-

[method:this setX]( [param:Integer index], [param:Float x] )

+

[method:this setX]( [param:Integer index], [param:Float x] )

Sets the x component of the vector at the given index.

-

[method:this setY]( [param:Integer index], [param:Float y] )

+

[method:this setY]( [param:Integer index], [param:Float y] )

Sets the y component of the vector at the given index.

-

[method:this setZ]( [param:Integer index], [param:Float z] )

+

[method:this setZ]( [param:Integer index], [param:Float z] )

Sets the z component of the vector at the given index.

-

[method:this setW]( [param:Integer index], [param:Float w] )

+

[method:this setW]( [param:Integer index], [param:Float w] )

Sets the w component of the vector at the given index.

-

[method:this setXY]( [param:Integer index], [param:Float x], [param:Float y] )

+

[method:this setXY]( [param:Integer index], [param:Float x], [param:Float y] )

Sets the x and y components of the vector at the given index.

-

[method:this setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] )

+

[method:this setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] )

Sets the x, y and z components of the vector at the given index.

-

[method:this setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] )

+

[method:this setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] ) +

Sets the x, y, z and w components of the vector at the given index.

- -

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/core/BufferGeometry.html b/docs/api/en/core/BufferGeometry.html index c9d6d95eb32b50..2469686bcc404a 100644 --- a/docs/api/en/core/BufferGeometry.html +++ b/docs/api/en/core/BufferGeometry.html @@ -10,27 +10,30 @@

[name]

- A representation of mesh, line, or point geometry. Includes vertex positions, face - indices, normals, colors, UVs, and custom attributes within buffers, reducing the cost of - passing all this data to the GPU. + A representation of mesh, line, or point geometry. Includes vertex + positions, face indices, normals, colors, UVs, and custom attributes + within buffers, reducing the cost of passing all this data to the GPU.

- To read and edit data in BufferGeometry attributes, see [page:BufferAttribute] documentation. + To read and edit data in BufferGeometry attributes, see + [page:BufferAttribute] documentation.

Code Example

+ const geometry = new THREE.BufferGeometry(); + // create a simple square shape. We duplicate the top left and bottom right // vertices because each vertex needs to appear once per triangle. const vertices = new Float32Array( [ - -1.0, -1.0, 1.0, - 1.0, -1.0, 1.0, - 1.0, 1.0, 1.0, + -1.0, -1.0, 1.0, // v0 + 1.0, -1.0, 1.0, // v1 + 1.0, 1.0, 1.0, // v2 - 1.0, 1.0, 1.0, - -1.0, 1.0, 1.0, - -1.0, -1.0, 1.0 + 1.0, 1.0, 1.0, // v3 + -1.0, 1.0, 1.0, // v4 + -1.0, -1.0, 1.0 // v5 ] ); // itemSize = 3 because there are 3 values (components) per vertex @@ -39,6 +42,30 @@

Code Example

const mesh = new THREE.Mesh( geometry, material );
+

Code Example (Index)

+ + + const geometry = new THREE.BufferGeometry(); + + const vertices = new Float32Array( [ + -1.0, -1.0, 1.0, // v0 + 1.0, -1.0, 1.0, // v1 + 1.0, 1.0, 1.0, // v2 + -1.0, 1.0, 1.0, // v3 + ] ); + + const indices = [ + 0, 1, 2, + 2, 3, 0, + ]; + + geometry.setIndex( indices ); + geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); + + const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); + const mesh = new THREE.Mesh( geometry, material ); + +

Examples

[example:webgl_buffergeometry Mesh with non-indexed faces]
@@ -51,19 +78,20 @@

Examples

Constructor

-

[name]()

- This creates a new [name]. It also sets several properties to a default value. + This creates a new [name]. It also sets several properties to a default + value.
-

Properties

[property:Object attributes]

- This hashmap has as id the name of the attribute to be set and as value the [page:BufferAttribute buffer] to set it to. - Rather than accessing this property directly, use [page:.setAttribute] and [page:.getAttribute] to access attributes of this geometry. + This hashmap has as id the name of the attribute to be set and as value + the [page:BufferAttribute buffer] to set it to. Rather than accessing this + property directly, use [page:.setAttribute] and [page:.getAttribute] to + access attributes of this geometry.

[property:Box3 boundingBox]

@@ -80,10 +108,10 @@

[property:Sphere boundingSphere]

[property:Object drawRange]

- Determines the part of the geometry to render. This should not - be set directly, instead use [page:.setDrawRange]. Default is + Determines the part of the geometry to render. This should not be set + directly, instead use [page:.setDrawRange]. Default is - { start: 0, count: Infinity } + { start: 0, count: Infinity } For non-indexed BufferGeometry, count is the number of vertices to render. For indexed BufferGeometry, count is the number of indices to render. @@ -91,21 +119,26 @@

[property:Object drawRange]

[property:Array groups]

- Split the geometry into groups, each of which will be rendered in a separate WebGL draw call. - This allows an array of materials to be used with the geometry.

+ Split the geometry into groups, each of which will be rendered in a + separate WebGL draw call. This allows an array of materials to be used + with the geometry.

Each group is an object of the form: - { start: Integer, count: Integer, materialIndex: Integer } - where start specifies the first element in this draw call – the first vertex for non-indexed geometry, - otherwise the first triangle index. Count specifies how many vertices (or indices) are included, and - materialIndex specifies the material array index to use.

+ + { start: Integer, count: Integer, materialIndex: Integer } + + where start specifies the first element in this draw call – the first + vertex for non-indexed geometry, otherwise the first triangle index. Count + specifies how many vertices (or indices) are included, and materialIndex + specifies the material array index to use.

- Use [page:.addGroup] to add groups, rather than modifying this array directly.

+ Use [page:.addGroup] to add groups, rather than modifying this array + directly.

- Every vertex and index must belong to exactly one group — groups must not share vertices or indices, and must not leave vertices or indices unused. + Every vertex and index must belong to exactly one group — groups must not + share vertices or indices, and must not leave vertices or indices unused.

- -

[property:Integer id]

Unique number for this bufferGeometry instance.

[property:BufferAttribute index]

- Allows for vertices to be re-used across multiple triangles; this is called using "indexed triangles". - Each triangle is associated with the indices of three vertices. This attribute therefore stores the index of each vertex for each triangular face. - - If this attribute is not set, the [page:WebGLRenderer renderer] assumes that each three contiguous - positions represent a single triangle. - - Default is `null`. + Allows for vertices to be re-used across multiple triangles; this is + called using "indexed triangles". Each triangle is associated with the + indices of three vertices. This attribute therefore stores the index of + each vertex for each triangular face. If this attribute is not set, the + [page:WebGLRenderer renderer] assumes that each three contiguous positions + represent a single triangle. Default is `null`.

[property:Boolean isBufferGeometry]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Object morphAttributes]

- Hashmap of [page:BufferAttribute]s holding details of the geometry's morph targets.
- Note: Once the geometry has been rendered, the morph attribute data cannot be changed. You will have to call [page:.dispose](), and create a new instance of [name]. + Hashmap of [page:BufferAttribute]s holding details of the geometry's morph + targets.
+ Note: Once the geometry has been rendered, the morph attribute data cannot + be changed. You will have to call [page:.dispose](), and create a new + instance of [name].

[property:Boolean morphTargetsRelative]

- Used to control the morph target behavior; when set to true, the morph target data is treated as relative offsets, rather than as absolute positions/normals. - - Default is `false`. + Used to control the morph target behavior; when set to true, the morph + target data is treated as relative offsets, rather than as absolute + positions/normals. Default is `false`.

[property:String name]

- Optional name for this bufferGeometry instance. Default is an empty string. + Optional name for this bufferGeometry instance. Default is an empty + string.

[property:Object userData]

- An object that can be used to store custom data about the BufferGeometry. It should not hold - references to functions as these will not be cloned. + An object that can be used to store custom data about the BufferGeometry. + It should not hold references to functions as these will not be cloned.

[property:String uuid]

- [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this object instance. - This gets automatically assigned and shouldn't be edited. + [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of + this object instance. This gets automatically assigned and shouldn't be + edited.

Methods

-

[page:EventDispatcher EventDispatcher] methods are available on this class.

+

+ [page:EventDispatcher EventDispatcher] methods are available on this + class. +

[method:undefined addGroup]( [param:Integer start], [param:Integer count], [param:Integer materialIndex] )

@@ -193,25 +230,32 @@

[method:BufferGeometry clone]()

[method:undefined computeBoundingBox]()

- Computes bounding box of the geometry, updating [page:.boundingBox] attribute.
- Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`. + Computes bounding box of the geometry, updating [page:.boundingBox] + attribute.
+ Bounding boxes aren't computed by default. They need to be explicitly + computed, otherwise they are `null`.

[method:undefined computeBoundingSphere]()

- Computes bounding sphere of the geometry, updating [page:.boundingSphere] attribute.
- Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`. + Computes bounding sphere of the geometry, updating [page:.boundingSphere] + attribute.
+ Bounding spheres aren't computed by default. They need to be explicitly + computed, otherwise they are `null`.

[method:undefined computeTangents]()

- Calculates and adds a tangent attribute to this geometry.
- The computation is only supported for indexed geometries and if position, normal, and uv attributes are defined. When using a tangent space normal map, prefer the MikkTSpace algorithm provided by - [page:BufferGeometryUtils.computeMikkTSpaceTangents] instead. + Calculates and adds a tangent attribute to this geometry.
+ The computation is only supported for indexed geometries and if position, + normal, and uv attributes are defined. When using a tangent space normal + map, prefer the MikkTSpace algorithm provided by + [page:BufferGeometryUtils.computeMikkTSpaceTangents] instead.

[method:undefined computeVertexNormals]()

-

Computes vertex normals by averaging face normals.

+

Computes vertex normals for the given vertex data. For indexed geometries, the method sets each vertex normal to be the average of the face normals of the faces that share that vertex. + For non-indexed geometries, vertices are not shared, and the method sets each vertex normal to be the same as the face normal.

[method:this copy]( [param:BufferGeometry bufferGeometry] )

Copies another BufferGeometry to this BufferGeometry.

@@ -221,7 +265,8 @@

[method:BufferAttribute deleteAttribute]( [param:String name] )

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

[method:BufferAttribute getAttribute]( [param:String name] )

@@ -235,52 +280,60 @@

[method:Boolean hasAttribute]( [param:String name] )

[method:this lookAt] ( [param:Vector3 vector] )

- vector - A world vector to look at.

+ vector - A world vector to look at.

- Rotates the geometry to face a point in space. This is typically done as a one time operation, and not during a loop. - Use [page:Object3D.lookAt] for typical real-time mesh usage. + Rotates the geometry to face a point in space. This is typically done as a + one time operation, and not during a loop. Use [page:Object3D.lookAt] for + typical real-time mesh usage.

[method:undefined normalizeNormals]()

- Every normal vector in a geometry will have a magnitude of 1. - This will correct lighting on the geometry surfaces. + Every normal vector in a geometry will have a magnitude of 1. This will + correct lighting on the geometry surfaces.

[method:this rotateX] ( [param:Float radians] )

- Rotate the geometry about the X axis. This is typically done as a one time operation, and not during a loop. - Use [page:Object3D.rotation] for typical real-time mesh rotation. + Rotate the geometry about the X axis. This is typically done as a one time + operation, and not during a loop. Use [page:Object3D.rotation] for typical + real-time mesh rotation.

[method:this rotateY] ( [param:Float radians] )

- Rotate the geometry about the Y axis. This is typically done as a one time operation, and not during a loop. - Use [page:Object3D.rotation] for typical real-time mesh rotation. + Rotate the geometry about the Y axis. This is typically done as a one time + operation, and not during a loop. Use [page:Object3D.rotation] for typical + real-time mesh rotation.

[method:this rotateZ] ( [param:Float radians] )

- Rotate the geometry about the Z axis. This is typically done as a one time operation, and not during a loop. - Use [page:Object3D.rotation] for typical real-time mesh rotation. + Rotate the geometry about the Z axis. This is typically done as a one time + operation, and not during a loop. Use [page:Object3D.rotation] for typical + real-time mesh rotation.

[method:this scale] ( [param:Float x], [param:Float y], [param:Float z] )

- Scale the geometry data. This is typically done as a one time operation, and not during a loop. - Use [page:Object3D.scale] for typical real-time mesh scaling. + Scale the geometry data. This is typically done as a one time operation, + and not during a loop. Use [page:Object3D.scale] for typical real-time + mesh scaling.

[method:this setAttribute]( [param:String name], [param:BufferAttribute attribute] )

- Sets an attribute to this geometry. Use this rather than the attributes property, - because an internal hashmap of [page:.attributes] is maintained to speed up iterating over - attributes. + Sets an attribute to this geometry. Use this rather than the attributes + property, because an internal hashmap of [page:.attributes] is maintained + to speed up iterating over attributes.

[method:undefined setDrawRange] ( [param:Integer start], [param:Integer count] )

-

Set the [page:.drawRange] property. For non-indexed BufferGeometry, count is the number of vertices to render. - For indexed BufferGeometry, count is the number of indices to render.

+

+ Set the [page:.drawRange] property. For non-indexed BufferGeometry, count + is the number of vertices to render. For indexed BufferGeometry, count is + the number of indices to render. +

[method:this setFromPoints] ( [param:Array points] )

Sets the attributes for this BufferGeometry from an array of points.

@@ -289,15 +342,19 @@

[method:this setIndex] ( [param:BufferAttribute index] )

Set the [page:.index] buffer.

[method:Object toJSON]()

-

Convert the buffer geometry to three.js [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

+

+ Convert the buffer geometry to three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. +

[method:BufferGeometry toNonIndexed]()

Return a non-index version of an indexed BufferGeometry.

[method:this translate] ( [param:Float x], [param:Float y], [param:Float z] )

- Translate the geometry. This is typically done as a one time operation, and not during a loop. - Use [page:Object3D.position] for typical real-time mesh translation. + Translate the geometry. This is typically done as a one time operation, + and not during a loop. Use [page:Object3D.position] for typical real-time + mesh translation.

Source

diff --git a/docs/api/en/core/Clock.html b/docs/api/en/core/Clock.html index f37cf24ddf90f3..16f606b60d4553 100644 --- a/docs/api/en/core/Clock.html +++ b/docs/api/en/core/Clock.html @@ -10,67 +10,78 @@

[name]

- Object for keeping track of time. This uses [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now] - if it is available, otherwise it reverts to the less accurate [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now]. + Object for keeping track of time. This uses + [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now] if it is available, otherwise it reverts to the less + accurate + [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now].

Constructor

[name]( [param:Boolean autoStart] )

- autoStart — (optional) whether to automatically start the clock when [page:.getDelta]() is called for the first time. Default is `true`. + autoStart — (optional) whether to automatically start the clock when + [page:.getDelta]() is called for the first time. Default is `true`.

Properties

[property:Boolean autoStart]

- If set, starts the clock automatically when [page:.getDelta]() is called for the first time. Default is `true`. + If set, starts the clock automatically when [page:.getDelta]() is called + for the first time. Default is `true`.

[property:Float startTime]

- Holds the time at which the clock's [page:Clock.start start] method was last called. Default is `0`. -

+ Holds the time at which the clock's [page:Clock.start start] method was + last called. Default is `0`. +

[property:Float oldTime]

- Holds the time at which the clock's [page:Clock.start start], [page:.getElapsedTime]() or [page:.getDelta]() - methods were last called. Default is `0`. -

+ Holds the time at which the clock's [page:Clock.start start], + [page:.getElapsedTime]() or [page:.getDelta]() methods were last called. + Default is `0`. +

[property:Float elapsedTime]

- Keeps track of the total time that the clock has been running. Default is `0`. -

+ Keeps track of the total time that the clock has been running. Default is + `0`. +

[property:Boolean running]

-

- Whether the clock is running or not. Default is `false`. -

+

Whether the clock is running or not. Default is `false`.

Methods

[method:undefined start]()

- Starts clock. Also sets the [page:.startTime] and [page:.oldTime] to the current time, sets [page:.elapsedTime] to `0` and [page:.running] to `true`. + Starts clock. Also sets the [page:.startTime] and [page:.oldTime] to the + current time, sets [page:.elapsedTime] to `0` and [page:.running] to + `true`.

[method:undefined stop]()

- Stops clock and sets [page:Clock.oldTime oldTime] to the current time. + Stops clock and sets [page:Clock.oldTime oldTime] to the current time.

[method:Float getElapsedTime]()

- Get the seconds passed since the clock started and sets [page:.oldTime] to the current time.
- If [page:.autoStart] is `true` and the clock is not running, also starts the clock. + Get the seconds passed since the clock started and sets [page:.oldTime] to + the current time.
+ If [page:.autoStart] is `true` and the clock is not running, also starts + the clock.

[method:Float getDelta]()

- Get the seconds passed since the time [page:.oldTime] was set and sets [page:.oldTime] to the current time.
- If [page:.autoStart] is `true` and the clock is not running, also starts the clock. + Get the seconds passed since the time [page:.oldTime] was set and sets + [page:.oldTime] to the current time.
+ If [page:.autoStart] is `true` and the clock is not running, also starts + the clock.

Source

diff --git a/docs/api/en/core/EventDispatcher.html b/docs/api/en/core/EventDispatcher.html index 9cf4419bb62b13..76d0db0d687516 100644 --- a/docs/api/en/core/EventDispatcher.html +++ b/docs/api/en/core/EventDispatcher.html @@ -18,25 +18,16 @@

Code Example

// Adding events to a custom object - class Car extends EventDispatcher { - start() { - this.dispatchEvent( { type: 'start', message: 'vroom vroom!' } ); - } - }; // Using events with the custom object - const car = new Car(); - car.addEventListener( 'start', function ( event ) { - alert( event.message ); - } ); car.start(); @@ -45,48 +36,34 @@

Code Example

Constructor

[name]()

-

- Creates EventDispatcher object. -

- +

Creates EventDispatcher object.

Methods

[method:undefined addEventListener]( [param:String type], [param:Function listener] )

- type - The type of event to listen to.
- listener - The function that gets called when the event is fired. -

-

- Adds a listener to an event type. + type - The type of event to listen to.
+ listener - The function that gets called when the event is fired.

+

Adds a listener to an event type.

[method:Boolean hasEventListener]( [param:String type], [param:Function listener] )

- type - The type of event to listen to.
- listener - The function that gets called when the event is fired. -

-

- Checks if listener is added to an event type. + type - The type of event to listen to.
+ listener - The function that gets called when the event is fired.

+

Checks if listener is added to an event type.

[method:undefined removeEventListener]( [param:String type], [param:Function listener] )

- type - The type of the listener that gets removed.
- listener - The listener function that gets removed. -

-

- Removes a listener from an event type. + type - The type of the listener that gets removed.
+ listener - The listener function that gets removed.

+

Removes a listener from an event type.

[method:undefined dispatchEvent]( [param:Object event] )

-

- event - The event that gets fired. -

-

- Fire an event type. -

- +

event - The event that gets fired.

+

Fire an event type.

Source

diff --git a/docs/api/en/core/GLBufferAttribute.html b/docs/api/en/core/GLBufferAttribute.html index 9ce59f944b011e..66e2ddad30b21d 100644 --- a/docs/api/en/core/GLBufferAttribute.html +++ b/docs/api/en/core/GLBufferAttribute.html @@ -13,9 +13,9 @@

[name]

This buffer attribute class does not construct a VBO. Instead, it uses whatever VBO is passed in constructor and can later be altered via the `buffer` property.

- It is required to pass additional params alongside the VBO. Those are: - the GL context, the GL data type, the number of components per vertex, - the number of bytes per component, and the number of vertices.

+ It is required to pass additional params alongside the VBO. Those are: the + GL context, the GL data type, the number of components per vertex, the + number of bytes per component, and the number of vertices.

The most common use case for this class is when some kind of GPGPU calculation interferes or even produces the VBOs in question.

@@ -23,15 +23,21 @@

[name]

Constructor

[name]( [param:WebGLBuffer buffer], [param:GLenum type], [param:Integer itemSize], [param:Integer elementSize], [param:Integer count] )

- `buffer` — Must be a [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer]. -
- `type` — One of [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL Data Types]. -
- `itemSize` — The number of values of the array that should be associated with - a particular vertex. For instance, if this - attribute is storing a 3-component vector (such as a position, normal, or color), then itemSize should be 3. -
- `elementSize` — 1, 2 or 4. The corresponding size (in bytes) for the given "type" param. + `buffer` — Must be a + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer]. +
+ `type` — One of + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL Data Types]. +
+ `itemSize` — The number of values of the array that should be associated + with a particular vertex. For instance, if this attribute is storing a + 3-component vector (such as a position, normal, or color), then itemSize + should be 3. +
+ `elementSize` — 1, 2 or 4. The corresponding size (in bytes) for the given + "type" param. +

+
  • gl.FLOAT: 4
  • gl.UNSIGNED_SHORT: 2
  • @@ -42,37 +48,30 @@

    [name]( [param:WebGLBuffer buffer], [param:GLenum type], [param:Integer item
  • gl.UNSIGNED_BYTE: 1
`count` — The expected number of vertices in VBO. -

Properties

[property:WebGLBuffer buffer]

- The current [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer] instance. + The current + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer] instance.

[property:Integer count]

-

- The expected number of vertices in VBO. -

+

The expected number of vertices in VBO.

[property:Boolean isGLBufferAttribute]

-

- Read-only. Always `true`. -

+

Read-only. Always `true`.

[property:Integer itemSize]

-

- How many values make up each item (vertex). -

+

How many values make up each item (vertex).

[property:Integer elementSize]

- Stores the corresponding size in bytes for the current `type` property value. -

-

- See above (constructor) for a list of known type sizes. + Stores the corresponding size in bytes for the current `type` property + value.

+

See above (constructor) for a list of known type sizes.

[property:String name]

@@ -81,8 +80,8 @@

[property:String name]

[property:GLenum type]

- A [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL Data Type] - describing the underlying VBO contents. + A + [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL Data Type] describing the underlying VBO contents.

Set this property together with `elementSize`. The recommended way is @@ -91,26 +90,28 @@

[property:GLenum type]

Methods

-

[method:this setBuffer]( buffer )

+

[method:this setBuffer]( buffer )

Sets the `buffer` property.

-

[method:this setType]( type, elementSize )

+

[method:this setType]( type, elementSize )

Sets the both `type` and `elementSize` properties.

-

[method:this setItemSize]( itemSize )

+

[method:this setItemSize]( itemSize )

Sets the `itemSize` property.

-

[method:this setCount]( count )

+

[method:this setCount]( count )

Sets the `count` property.

[property:Integer version]

- A version number, incremented every time the needsUpdate property is set to true. + A version number, incremented every time the needsUpdate property is set + to true.

[property:Boolean needsUpdate]

- Default is `false`. Setting this to true increments [page:GLBufferAttribute.version version]. + Default is `false`. Setting this to true increments + [page:GLBufferAttribute.version version].

Source

diff --git a/docs/api/en/core/InstancedBufferAttribute.html b/docs/api/en/core/InstancedBufferAttribute.html index 81c03bee4849ba..fa5c765e2ef77e 100644 --- a/docs/api/en/core/InstancedBufferAttribute.html +++ b/docs/api/en/core/InstancedBufferAttribute.html @@ -10,31 +10,29 @@ [page:BufferAttribute] →

[name]

- -

- An instanced version of [page:BufferAttribute]. -

+

An instanced version of [page:BufferAttribute].

Constructor

[name]( [param:TypedArray array], [param:Integer itemSize], [param:Boolean normalized], [param:Number meshPerAttribute] )

-

-

Properties

See [page:BufferAttribute] for inherited properties.

[property:Number meshPerAttribute]

- Defines how often a value of this buffer attribute should be repeated. A value of one means that each value of the instanced attribute is used for a single instance. A value of two means that each value is used for two consecutive instances (and so on). Default is `1`. + Defines how often a value of this buffer attribute should be repeated. A + value of one means that each value of the instanced attribute is used for + a single instance. A value of two means that each value is used for two + consecutive instances (and so on). Default is `1`.

Methods

See [page:BufferAttribute] for inherited methods.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ diff --git a/docs/api/en/core/InstancedBufferGeometry.html b/docs/api/en/core/InstancedBufferGeometry.html index ae5089c9699c61..926686eff1e802 100644 --- a/docs/api/en/core/InstancedBufferGeometry.html +++ b/docs/api/en/core/InstancedBufferGeometry.html @@ -10,28 +10,19 @@ [page:BufferGeometry] →

[name]

- -

- An instanced version of [page:BufferGeometry]. -

+

An instanced version of [page:BufferGeometry].

Constructor

[name]( )

-

-

Properties

See [page:BufferGeometry] for inherited properties.

[property:Number instanceCount]

-

- Default is `Infinity`. -

+

Default is `Infinity`.

[property:Boolean isInstancedBufferGeometry]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

Methods

See [page:BufferGeometry] for inherited methods.

diff --git a/docs/api/en/core/InstancedInterleavedBuffer.html b/docs/api/en/core/InstancedInterleavedBuffer.html index 3feca977b90b4e..161794723ef53f 100644 --- a/docs/api/en/core/InstancedInterleavedBuffer.html +++ b/docs/api/en/core/InstancedInterleavedBuffer.html @@ -10,30 +10,19 @@ [page:InterleavedBuffer] →

[name]

- -

- An instanced version of [page:InterleavedBuffer]. -

+

An instanced version of [page:InterleavedBuffer].

Constructor

[name]( [param:TypedArray array], [param:Integer itemSize], [param:Number meshPerAttribute] )

-

-

Properties

-

- See [page:InterleavedBuffer] for inherited properties. -

+

See [page:InterleavedBuffer] for inherited properties.

[property:Number meshPerAttribute]

-

- Default is `1`. -

+

Default is `1`.

Methods

-

- See [page:InterleavedBuffer] for inherited methods. -

+

See [page:InterleavedBuffer] for inherited methods.

Source

diff --git a/docs/api/en/core/InterleavedBuffer.html b/docs/api/en/core/InterleavedBuffer.html index 4f9fb0b0137f1d..a1e1d16b96a2e5 100644 --- a/docs/api/en/core/InterleavedBuffer.html +++ b/docs/api/en/core/InterleavedBuffer.html @@ -8,100 +8,106 @@

[name]

-

- "Interleaved" means that multiple attributes, possibly of different types, (e.g., position, normal, uv, color) are packed into a single array buffer. -

- An introduction into interleaved arrays can be found here: [link:https://blog.tojicode.com/2011/05/interleaved-array-basics.html Interleaved array basics] + "Interleaved" means that multiple attributes, possibly of different types, + (e.g., position, normal, uv, color) are packed into a single array buffer. +

+ An introduction into interleaved arrays can be found here: + [link:https://blog.tojicode.com/2011/05/interleaved-array-basics.html Interleaved array basics]

Examples

- -

[example:webgl_buffergeometry_points_interleaved webgl / buffergeometry / points / interleaved]

+

+ [example:webgl_buffergeometry_points_interleaved webgl / buffergeometry / points / interleaved] +

Constructor

[name]( [param:TypedArray array], [param:Integer stride] )

- [page:TypedArray array] -- A typed array with a shared buffer. Stores the geometry data.
+ [page:TypedArray array] -- A typed array with a shared buffer. Stores the + geometry data.
[page:Integer stride] -- The number of typed-array elements per vertex.

Properties

[property:Array array]

-

- A typed array with a shared buffer. Stores the geometry data. -

+

A typed array with a shared buffer. Stores the geometry data.

[property:Integer stride]

-

- The number of typed-array elements per vertex. -

+

The number of typed-array elements per vertex.

[property:Integer count]

-

- Gives the total number of elements in the array. -

+

Gives the total number of elements in the array.

[property:Object updateRange]

- Object containing offset and count.
- - [page:Number offset]: Default is `0`.
- - [page:Number count]: Default is `-1`.
+ Object containing offset and count.
+ - [page:Number offset]: Default is `0`.
+ - [page:Number count]: Default is `-1`.

[property:String uuid]

- [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this instance. This gets automatically assigned, so this shouldn't be edited. + [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of + this instance. This gets automatically assigned, so this shouldn't be + edited.

[property:Integer version]

- A version number, incremented every time the needsUpdate property is set to true. + A version number, incremented every time the needsUpdate property is set + to true.

[property:Boolean needsUpdate]

- Default is `false`. Setting this to true increments [page:InterleavedBuffer.version version]. + Default is `false`. Setting this to true increments + [page:InterleavedBuffer.version version].

[property:Usage usage]

- Defines the intended usage pattern of the data store for optimization purposes. Corresponds to the `usage` parameter of + Defines the intended usage pattern of the data store for optimization + purposes. Corresponds to the `usage` parameter of [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData]().

Methods

-

[method:this copy]( [param:InterleavedBuffer source] )

+

[method:this copy]( [param:InterleavedBuffer source] )

+

Copies another [name] to this [name].

+ +

[method:this copyAt]( [param:Integer index1], [param:InterleavedBuffer attribute], [param:Integer index2] )

- Copies another [name] to this [name]. + Copies data from `attribute[index2]` to [page:InterleavedBuffer.array array][index1].

-

[method:this copyAt]( [param:Integer index1], [param:InterleavedBuffer attribute], [param:Integer index2] )

-

Copies data from `attribute[index2]` to [page:InterleavedBuffer.array array][index1].

- -

[method:this set]( [param:TypedArray value], [param:Integer offset] )

+

[method:this set]( [param:TypedArray value], [param:Integer offset] )

- value - The source (typed) array.
- offset - The offset into the target array at which to begin writing values from the source array. Default is `0`.

+ value - The source (typed) array.
+ offset - The offset into the target array at which to begin writing values + from the source array. Default is `0`.

- Stores multiple values in the buffer, reading input values from a specified array. + Stores multiple values in the buffer, reading input values from a + specified array.

-

[method:InterleavedBuffer clone]( [param:Object data] )

+

[method:InterleavedBuffer clone]( [param:Object data] )

- data - This object holds shared array buffers required for properly cloning geometries with interleaved attributes.

+ data - This object holds shared array buffers required for properly + cloning geometries with interleaved attributes.

Creates a clone of this [name].

-

[method:this setUsage] ( [param:Usage value] )

+

[method:this setUsage] ( [param:Usage value] )

Set [page:InterleavedBuffer.usage usage] to value.

-

[method:Object toJSON]( [param:Object data] )

+

[method:Object toJSON]( [param:Object data] )

- data - This object holds shared array buffers required for properly serializing geometries with interleaved attributes.

+ data - This object holds shared array buffers required for properly + serializing geometries with interleaved attributes.

Serializes this [name].

diff --git a/docs/api/en/core/InterleavedBufferAttribute.html b/docs/api/en/core/InterleavedBufferAttribute.html index 0bf4ff22ce7d0d..c213727bb12fcc 100644 --- a/docs/api/en/core/InterleavedBufferAttribute.html +++ b/docs/api/en/core/InterleavedBufferAttribute.html @@ -7,114 +7,109 @@ -

[name]

-

- -

+

Constructor

[name]( [param:InterleavedBuffer interleavedBuffer], [param:Integer itemSize], [param:Integer offset], [param:Boolean normalized] )

-

-

Properties

[property:InterleavedBuffer data]

- The [page:InterleavedBuffer InterleavedBuffer] instance passed in the constructor. + The [page:InterleavedBuffer InterleavedBuffer] instance passed in the + constructor.

[property:TypedArray array]

-

- The value of [page:InterleavedBufferAttribute.data data].array. -

+

The value of [page:InterleavedBufferAttribute.data data].array.

[property:Integer count]

- The value of [page:InterleavedBufferAttribute.data data].count. - - If the buffer is storing a 3-component item (such as a position, normal, or color), - then this will count the number of such items stored. + The value of [page:InterleavedBufferAttribute.data data].count. If the + buffer is storing a 3-component item (such as a position, normal, or + color), then this will count the number of such items stored.

[property:Boolean isInterleavedBufferAttribute]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Integer itemSize]

-

- How many values make up each item. -

+

How many values make up each item.

[property:String name]

- Optional name for this attribute instance. Default is an empty string. + Optional name for this attribute instance. Default is an empty string.

[property:Boolean needsUpdate]

- Default is `false`. Setting this to `true` will send the entire interleaved buffer (not just the specific attribute data) to the GPU again. + Default is `false`. Setting this to `true` will send the entire + interleaved buffer (not just the specific attribute data) to the GPU + again.

[property:Boolean normalized]

-

- Default is `false`. -

+

Default is `false`.

[property:Integer offset]

-

- The offset in the underlying array buffer where an item starts. -

+

The offset in the underlying array buffer where an item starts.

Methods

[method:this applyMatrix4]( [param:Matrix4 m] )

-

Applies matrix [page:Matrix4 m] to every Vector3 element of this InterleavedBufferAttribute.

+

+ Applies matrix [page:Matrix4 m] to every Vector3 element of this + InterleavedBufferAttribute. +

[method:this applyNormalMatrix]( [param:Matrix3 m] )

-

Applies normal matrix [page:Matrix3 m] to every Vector3 element of this InterleavedBufferAttribute.

+

+ Applies normal matrix [page:Matrix3 m] to every Vector3 element of this + InterleavedBufferAttribute. +

[method:this transformDirection]( [param:Matrix4 m] )

-

Applies matrix [page:Matrix4 m] to every Vector3 element of this InterleavedBufferAttribute, interpreting the elements as a direction vectors.

+

+ Applies matrix [page:Matrix4 m] to every Vector3 element of this + InterleavedBufferAttribute, interpreting the elements as a direction + vectors. +

-

[method:Number getX]( [param:Integer index] )

+

[method:Number getX]( [param:Integer index] )

Returns the x component of the item at the given index.

-

[method:Number getY]( [param:Integer index] )

+

[method:Number getY]( [param:Integer index] )

Returns the y component of the item at the given index.

-

[method:Number getZ]( [param:Integer index] )

+

[method:Number getZ]( [param:Integer index] )

Returns the z component of the item at the given index.

-

[method:Number getW]( [param:Integer index] )

+

[method:Number getW]( [param:Integer index] )

Returns the w component of the item at the given index.

-

[method:this setX]( [param:Integer index], [param:Float x] )

+

[method:this setX]( [param:Integer index], [param:Float x] )

Sets the x component of the item at the given index.

-

[method:this setY]( [param:Integer index], [param:Float y] )

+

[method:this setY]( [param:Integer index], [param:Float y] )

Sets the y component of the item at the given index.

-

[method:this setZ]( [param:Integer index], [param:Float z] )

+

[method:this setZ]( [param:Integer index], [param:Float z] )

Sets the z component of the item at the given index.

-

[method:this setW]( [param:Integer index], [param:Float w] )

+

[method:this setW]( [param:Integer index], [param:Float w] )

Sets the w component of the item at the given index.

-

[method:this setXY]( [param:Integer index], [param:Float x], [param:Float y] )

+

[method:this setXY]( [param:Integer index], [param:Float x], [param:Float y] )

Sets the x and y components of the item at the given index.

-

[method:this setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] )

+

[method:this setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] )

Sets the x, y and z components of the item at the given index.

-

[method:this setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] )

+

[method:this setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] )

Sets the x, y, z and w components of the item at the given index.

- -

Source

diff --git a/docs/api/en/core/Layers.html b/docs/api/en/core/Layers.html index f223cfa6c51b1c..f5f07725c8999d 100644 --- a/docs/api/en/core/Layers.html +++ b/docs/api/en/core/Layers.html @@ -10,38 +10,36 @@

[name]

- A [page:Layers] object assigns an [page:Object3D] to 1 or more of 32 layers numbered `0` to `31` - - internally the layers are stored as a [link:https://en.wikipedia.org/wiki/Mask_(computing) bit mask], and by default all - Object3Ds are a member of layer 0.

+ A [page:Layers] object assigns an [page:Object3D] to 1 or more of 32 + layers numbered `0` to `31` - internally the layers are stored as a + [link:https://en.wikipedia.org/wiki/Mask_(computing) bit mask], and by + default all Object3Ds are a member of layer 0.

- This can be used to control visibility - an object must share a layer with a [page:Camera camera] to be visible when that camera's - view is rendered.

+ This can be used to control visibility - an object must share a layer with + a [page:Camera camera] to be visible when that camera's view is + rendered.

- All classes that inherit from [page:Object3D] have an [page:Object3D.layers] property which is an instance of this class. + All classes that inherit from [page:Object3D] have an + [page:Object3D.layers] property which is an instance of this class.

Examples

-

- [example:webgl_layers WebGL / layers] -

+

[example:webgl_layers WebGL / layers]

Constructor

-

[name]()

-

- Create a new Layers object, with membership initially set to layer 0. -

+

Create a new Layers object, with membership initially set to layer 0.

Properties

[property:Integer mask]

- A bit mask storing which of the 32 layers this layers object is currently a member of. + A bit mask storing which of the 32 layers this layers object is currently + a member of.

-

Methods

[method:undefined disable]( [param:Integer layer] )

@@ -69,7 +67,8 @@

[method:Boolean test]( [param:Layers layers] )

layers - a Layers object

- Returns true if this and the passed `layers` object have at least one layer in common. + Returns true if this and the passed `layers` object have at least one + layer in common.

[method:Boolean isEnabled]( [param:Integer layer] )

@@ -87,14 +86,10 @@

[method:undefined toggle]( [param:Integer layer] )

[method:undefined enableAll]()

-

- Add membership to all layers. -

+

Add membership to all layers.

[method:undefined disableAll]()

-

- Remove membership from all layers. -

+

Remove membership from all layers.

Source

diff --git a/docs/api/en/core/Object3D.html b/docs/api/en/core/Object3D.html index 8a3a6c9674b0dc..08601c7e1acf06 100644 --- a/docs/api/en/core/Object3D.html +++ b/docs/api/en/core/Object3D.html @@ -10,22 +10,17 @@

[name]

- This is the base class for most objects in three.js and provides a set of properties and methods - for manipulating objects in 3D space.

+ This is the base class for most objects in three.js and provides a set of + properties and methods for manipulating objects in 3D space.

- Note that this can be used for grouping objects via the [page:.add]( object ) method - which adds the object as a child, however it is better to use [page:Group] for this. + Note that this can be used for grouping objects via the [page:.add]( object ) method which adds the object as a child, however it is better to + use [page:Group] for this.

-

Constructor

-

[name]()

-

- The constructor takes no arguments. -

- +

The constructor takes no arguments.

Properties

@@ -36,37 +31,46 @@

[property:Boolean castShadow]

Whether the object gets rendered into shadow map. Default is `false`.

[property:Array children]

-

Array with object's children. See [page:Group] for info on manually grouping objects.

+

+ Array with object's children. See [page:Group] for info on manually + grouping objects. +

[property:Material customDepthMaterial]

- Custom depth material to be used when rendering to the depth map. Can only be used in context of meshes. - When shadow-casting with a [page:DirectionalLight] or [page:SpotLight], if you are modifying vertex positions in the vertex shader you must specify a customDepthMaterial for proper shadows. Default is `undefined`. + Custom depth material to be used when rendering to the depth map. Can only + be used in context of meshes. When shadow-casting with a + [page:DirectionalLight] or [page:SpotLight], if you are modifying vertex + positions in the vertex shader you must specify a customDepthMaterial for + proper shadows. Default is `undefined`.

[property:Material customDistanceMaterial]

- Same as [page:.customDepthMaterial customDepthMaterial], but used with [page:PointLight]. Default is `undefined`. + Same as [page:.customDepthMaterial customDepthMaterial], but used with + [page:PointLight]. Default is `undefined`.

[property:Boolean frustumCulled]

- When this is set, it checks every frame if the object is in the frustum of the camera before rendering the object. If set to `false` the object gets rendered every frame even if it is not in the frustum of the camera. Default is `true`. + When this is set, it checks every frame if the object is in the frustum of + the camera before rendering the object. If set to `false` the object gets + rendered every frame even if it is not in the frustum of the camera. + Default is `true`.

[property:Integer id]

readonly – Unique number for this object instance.

[property:Boolean isObject3D]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Layers layers]

- The layer membership of the object. The object is only visible if it has at least one - layer in common with the [page:Camera] in use. This property can also be used to filter out - unwanted objects in ray-intersection tests when using [page:Raycaster]. + The layer membership of the object. The object is only visible if it has + at least one layer in common with the [page:Camera] in use. This property + can also be used to filter out unwanted objects in ray-intersection tests + when using [page:Raycaster].

[property:Matrix4 matrix]

@@ -74,74 +78,97 @@

[property:Matrix4 matrix]

[property:Boolean matrixAutoUpdate]

- When this is set, it calculates the matrix of position, (rotation or quaternion) and - scale every frame and also recalculates the matrixWorld property. Default is [page:Object3D.DEFAULT_MATRIX_AUTO_UPDATE] (true). + When this is set, it calculates the matrix of position, (rotation or + quaternion) and scale every frame and also recalculates the matrixWorld + property. Default is [page:Object3D.DEFAULT_MATRIX_AUTO_UPDATE] (true).

[property:Matrix4 matrixWorld]

- The global transform of the object. If the Object3D has no parent, then it's identical to - the local transform [page:.matrix]. + The global transform of the object. If the Object3D has no parent, then + it's identical to the local transform [page:.matrix].

[property:Boolean matrixWorldAutoUpdate]

- If set, then the renderer checks every frame if the object and its children need matrix updates. - When it isn't, then you have to maintain all matrices in the object and its children yourself. - Default is [page:Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE] (true). + If set, then the renderer checks every frame if the object and its + children need matrix updates. When it isn't, then you have to maintain all + matrices in the object and its children yourself. Default is + [page:Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE] (true).

[property:Boolean matrixWorldNeedsUpdate]

- When this is set, it calculates the matrixWorld in that frame and resets this property - to false. Default is `false`. + When this is set, it calculates the matrixWorld in that frame and resets + this property to false. Default is `false`.

[property:Matrix4 modelViewMatrix]

-

This is passed to the shader and used to calculate the position of the object.

+

+ This is passed to the shader and used to calculate the position of the + object. +

[property:String name]

-

Optional name of the object (doesn't need to be unique). Default is an empty string.

+

+ Optional name of the object (doesn't need to be unique). Default is an + empty string. +

[property:Matrix3 normalMatrix]

- This is passed to the shader and used to calculate lighting for the object. It is the transpose of the inverse of the upper left 3x3 sub-matrix of this object's modelViewMatrix.

+ This is passed to the shader and used to calculate lighting for the + object. It is the transpose of the inverse of the upper left 3x3 + sub-matrix of this object's modelViewMatrix.

- The reason for this special matrix is that simply using the modelViewMatrix could result in a non-unit length of normals (on scaling) or in a non-perpendicular direction (on non-uniform scaling).

+ The reason for this special matrix is that simply using the + modelViewMatrix could result in a non-unit length of normals (on scaling) + or in a non-perpendicular direction (on non-uniform scaling).

- On the other hand the translation part of the modelViewMatrix is not relevant for the calculation of normals. Thus a Matrix3 is sufficient. + On the other hand the translation part of the modelViewMatrix is not + relevant for the calculation of normals. Thus a Matrix3 is sufficient.

[property:Function onAfterRender]

- An optional callback that is executed immediately after a 3D object is rendered. - This function is called with the following parameters: renderer, scene, camera, geometry, - material, group. + An optional callback that is executed immediately after a 3D object is + rendered. This function is called with the following parameters: renderer, + scene, camera, geometry, material, group.

- Please notice that this callback is only executed for `renderable` 3D objects. Meaning 3D objects which define their visual - appearance with geometries and materials like instances of [page:Mesh], [page:Line], [page:Points] or [page:Sprite]. - Instances of [page:Object3D], [page:Group] or [page:Bone] are not renderable and thus this callback is not executed for such objects. + Please notice that this callback is only executed for `renderable` 3D + objects. Meaning 3D objects which define their visual appearance with + geometries and materials like instances of [page:Mesh], [page:Line], + [page:Points] or [page:Sprite]. Instances of [page:Object3D], [page:Group] + or [page:Bone] are not renderable and thus this callback is not executed + for such objects.

[property:Function onBeforeRender]

- An optional callback that is executed immediately before a 3D object is rendered. - This function is called with the following parameters: renderer, scene, camera, geometry, - material, group. + An optional callback that is executed immediately before a 3D object is + rendered. This function is called with the following parameters: renderer, + scene, camera, geometry, material, group.

- Please notice that this callback is only executed for `renderable` 3D objects. Meaning 3D objects which define their visual - appearance with geometries and materials like instances of [page:Mesh], [page:Line], [page:Points] or [page:Sprite]. - Instances of [page:Object3D], [page:Group] or [page:Bone] are not renderable and thus this callback is not executed for such objects. + Please notice that this callback is only executed for `renderable` 3D + objects. Meaning 3D objects which define their visual appearance with + geometries and materials like instances of [page:Mesh], [page:Line], + [page:Points] or [page:Sprite]. Instances of [page:Object3D], [page:Group] + or [page:Bone] are not renderable and thus this callback is not executed + for such objects.

[property:Object3D parent]

-

Object's parent in the [link:https://en.wikipedia.org/wiki/Scene_graph scene graph]. An object can have at most - one parent.

+

+ Object's parent in the [link:https://en.wikipedia.org/wiki/Scene_graph scene graph]. An object can have at most one parent. +

[property:Vector3 position]

-

A [page:Vector3] representing the object's local position. Default is `(0, 0, 0)`.

+

+ A [page:Vector3] representing the object's local position. Default is `(0, + 0, 0)`. +

[property:Quaternion quaternion]

Object's local rotation as a [page:Quaternion Quaternion].

@@ -151,250 +178,280 @@

[property:Boolean receiveShadow]

[property:Number renderOrder]

- This value allows the default rendering order of [link:https://en.wikipedia.org/wiki/Scene_graph scene graph] - objects to be overridden although opaque and transparent objects remain sorted independently. When this property - is set for an instance of [page:Group Group], all descendants objects will be sorted and rendered together. - Sorting is from lowest to highest renderOrder. Default value is `0`. + This value allows the default rendering order of + [link:https://en.wikipedia.org/wiki/Scene_graph scene graph] objects to be + overridden although opaque and transparent objects remain sorted + independently. When this property is set for an instance of [page:Group Group], all descendants objects will be sorted and rendered together. + Sorting is from lowest to highest renderOrder. Default value is `0`.

[property:Euler rotation]

- Object's local rotation (see [link:https://en.wikipedia.org/wiki/Euler_angles Euler angles]), in radians. + Object's local rotation (see + [link:https://en.wikipedia.org/wiki/Euler_angles Euler angles]), in + radians.

[property:Vector3 scale]

-

- The object's local scale. Default is [page:Vector3]( 1, 1, 1 ). -

+

The object's local scale. Default is [page:Vector3]( 1, 1, 1 ).

[property:Vector3 up]

- This is used by the [page:.lookAt lookAt] method, for example, to determine the orientation of the result.
- Default is [page:Object3D.DEFAULT_UP] - that is, `( 0, 1, 0 )`. + This is used by the [page:.lookAt lookAt] method, for example, to + determine the orientation of the result.
+ Default is [page:Object3D.DEFAULT_UP] - that is, `( 0, 1, 0 )`.

[property:Object userData]

- An object that can be used to store custom data about the Object3D. It should not hold - references to functions as these will not be cloned. + An object that can be used to store custom data about the Object3D. It + should not hold references to functions as these will not be cloned.

[property:String uuid]

- [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this object instance. - This gets automatically assigned, so this shouldn't be edited. + [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of + this object instance. This gets automatically assigned, so this shouldn't + be edited.

[property:Boolean visible]

Object gets rendered if `true`. Default is `true`.

- - -

Static Properties

- Static properties and methods are defined per class rather than per instance of that class. - This means that changing [page:Object3D.DEFAULT_UP] or [page:Object3D.DEFAULT_MATRIX_AUTO_UPDATE] - will change the values of [page:.up up] and [page:.matrixAutoUpdate matrixAutoUpdate] for - `every` instance of Object3D (or derived classes) created after the change has - been made (already created Object3Ds will not be affected). + Static properties and methods are defined per class rather than per + instance of that class. This means that changing + [page:Object3D.DEFAULT_UP] or [page:Object3D.DEFAULT_MATRIX_AUTO_UPDATE] + will change the values of [page:.up up] and [page:.matrixAutoUpdate matrixAutoUpdate] for `every` instance of Object3D (or derived classes) + created after the change has been made (already created Object3Ds will not + be affected).

[property:Vector3 DEFAULT_UP]

- The default [page:.up up] direction for objects, also used as the default position for [page:DirectionalLight], - [page:HemisphereLight] and [page:Spotlight] (which creates lights shining from the top down).
+ The default [page:.up up] direction for objects, also used as the default + position for [page:DirectionalLight], [page:HemisphereLight] and + [page:Spotlight] (which creates lights shining from the top down).
Set to ( 0, 1, 0 ) by default.

[property:Boolean DEFAULT_MATRIX_AUTO_UPDATE]

- The default setting for [page:.matrixAutoUpdate matrixAutoUpdate] for newly created Object3Ds.
- + The default setting for [page:.matrixAutoUpdate matrixAutoUpdate] for + newly created Object3Ds.

[property:Boolean DEFAULT_MATRIX_WORLD_AUTO_UPDATE]

- The default setting for [page:.matrixWorldAutoUpdate matrixWorldAutoUpdate] for newly created Object3Ds.
+ The default setting for [page:.matrixWorldAutoUpdate + matrixWorldAutoUpdate] for newly created Object3Ds.

Methods

-

[page:EventDispatcher EventDispatcher] methods are available on this class.

+

+ [page:EventDispatcher EventDispatcher] methods are available on this + class. +

[method:this add]( [param:Object3D object], ... )

- Adds `object` as child of this object. An arbitrary number of objects may be added. Any current parent on an - object passed in here will be removed, since an object can have at most one parent.

+ Adds `object` as child of this object. An arbitrary number of objects may + be added. Any current parent on an object passed in here will be removed, + since an object can have at most one parent.

- See [page:Group] for info on manually grouping objects. + See [page:Group] for info on manually grouping objects.

[method:undefined applyMatrix4]( [param:Matrix4 matrix] )

-

Applies the matrix transform to the object and updates the object's position, rotation and scale.

+

+ Applies the matrix transform to the object and updates the object's + position, rotation and scale. +

[method:this applyQuaternion]( [param:Quaternion quaternion] )

Applies the rotation represented by the quaternion to the object.

[method:this attach]( [param:Object3D object] )

-

Adds `object` as a child of this, while maintaining the object's world transform.

- Note: This method does not support scene graphs having non-uniformly-scaled nodes(s). +

+ Adds `object` as a child of this, while maintaining the object's world + transform.

+ Note: This method does not support scene graphs having + non-uniformly-scaled nodes(s).

[method:Object3D clone]( [param:Boolean recursive] )

- recursive -- if true, descendants of the object are also cloned. Default is true.

+ recursive -- if true, descendants of the object are also cloned. Default + is true.

- Returns a clone of this object and optionally all descendants. + Returns a clone of this object and optionally all descendants.

[method:this copy]( [param:Object3D object], [param:Boolean recursive] )

- recursive -- if true, descendants of the object are also copied. Default is true.

- - Copy the given object into this object. + recursive -- if true, descendants of the object are also copied. Default + is true.

- Note: event listeners and user-defined callbacks ([page:.onAfterRender] and [page:.onBeforeRender]) are not copied. + Copy the given object into this object. Note: event listeners and + user-defined callbacks ([page:.onAfterRender] and [page:.onBeforeRender]) + are not copied.

[method:Object3D getObjectById]( [param:Integer id] )

- id -- Unique number of the object instance

+ id -- Unique number of the object instance

- Searches through an object and its children, starting with the object itself, and returns the first with a matching id.
- Note that ids are assigned in chronological order: 1, 2, 3, ..., incrementing by one for each new object. + Searches through an object and its children, starting with the object + itself, and returns the first with a matching id.
+ Note that ids are assigned in chronological order: 1, 2, 3, ..., + incrementing by one for each new object.

[method:Object3D getObjectByName]( [param:String name] )

- name -- String to match to the children's Object3D.name property.

+ name -- String to match to the children's Object3D.name property. +

- Searches through an object and its children, starting with the object itself, and returns the first with a matching name.
- Note that for most objects the name is an empty string by default. You will - have to set it manually to make use of this method. + Searches through an object and its children, starting with the object + itself, and returns the first with a matching name.
+ Note that for most objects the name is an empty string by default. You + will have to set it manually to make use of this method.

[method:Object3D getObjectByProperty]( [param:String name], [param:Any value] )

- name -- the property name to search for.
- value -- value of the given property.

+ name -- the property name to search for.
+ value -- value of the given property.

- Searches through an object and its children, starting with the object itself, and returns the first with a property that matches the value given. + Searches through an object and its children, starting with the object + itself, and returns the first with a property that matches the value + given.

[method:Object3D getObjectsByProperty]( [param:String name], [param:Any value] )

- name -- the property name to search for.
- value -- value of the given property.

+ name -- the property name to search for.
+ value -- value of the given property.

- Searches through an object and its children, starting with the object itself, and returns all the objects with a property that matches the value given. + Searches through an object and its children, starting with the object + itself, and returns all the objects with a property that matches the value + given.

[method:Vector3 getWorldPosition]( [param:Vector3 target] )

- [page:Vector3 target] — the result will be copied into this Vector3.

+ [page:Vector3 target] — the result will be copied into this Vector3. +

- Returns a vector representing the position of the object in world space. + Returns a vector representing the position of the object in world space.

[method:Quaternion getWorldQuaternion]( [param:Quaternion target] )

- [page:Quaternion target] — the result will be copied into this Quaternion.

+ [page:Quaternion target] — the result will be copied into this Quaternion. +

- Returns a quaternion representing the rotation of the object in world space. + Returns a quaternion representing the rotation of the object in world + space.

[method:Vector3 getWorldScale]( [param:Vector3 target] )

- [page:Vector3 target] — the result will be copied into this Vector3.

+ [page:Vector3 target] — the result will be copied into this Vector3. +

- Returns a vector of the scaling factors applied to the object for each axis in world space. + Returns a vector of the scaling factors applied to the object for each + axis in world space.

[method:Vector3 getWorldDirection]( [param:Vector3 target] )

- [page:Vector3 target] — the result will be copied into this Vector3.

+ [page:Vector3 target] — the result will be copied into this Vector3. +

- Returns a vector representing the direction of object's positive z-axis in world space. + Returns a vector representing the direction of object's positive z-axis in + world space.

-

[method:Vector3 localToWorld]( [param:Vector3 vector] )

- vector - A vector representing a position in this object's local space.

+ vector - A vector representing a position in this object's local space.

- Converts the vector from this object's local space to world space. + Converts the vector from this object's local space to world space.

[method:undefined lookAt]( [param:Vector3 vector] )
- [method:undefined lookAt]( [param:Float x], [param:Float y], [param:Float z] )

+ [method:undefined lookAt]( [param:Float x], [param:Float y], [param:Float z] ) +

- vector - A vector representing a position in world space.

- Optionally, the [page:.x x], [page:.y y] and [page:.z z] components of the world space position.

+ vector - A vector representing a position in world space.

+ Optionally, the [page:.x x], [page:.y y] and [page:.z z] components of the + world space position.

- Rotates the object to face a point in world space.

+ Rotates the object to face a point in world space.

- This method does not support objects having non-uniformly-scaled parent(s). + This method does not support objects having non-uniformly-scaled + parent(s).

[method:undefined raycast]( [param:Raycaster raycaster], [param:Array intersects] )

- Abstract (empty) method to get intersections between a casted ray and this object. - Subclasses such as [page:Mesh], [page:Line], and [page:Points] implement this method in order - to use raycasting. + Abstract (empty) method to get intersections between a casted ray and this + object. Subclasses such as [page:Mesh], [page:Line], and [page:Points] + implement this method in order to use raycasting.

[method:this remove]( [param:Object3D object], ... )

- Removes `object` as child of this object. An arbitrary number of objects may be removed. + Removes `object` as child of this object. An arbitrary number of objects + may be removed.

[method:this removeFromParent]()

-

- Removes this object from its current parent. -

+

Removes this object from its current parent.

[method:this clear]()

-

- Removes all child objects. -

+

Removes all child objects.

[method:this rotateOnAxis]( [param:Vector3 axis], [param:Float angle] )

- axis -- A normalized vector in object space.
- angle -- The angle in radians.

+ axis -- A normalized vector in object space.
+ angle -- The angle in radians.

- Rotate an object along an axis in object space. The axis is assumed to be normalized. + Rotate an object along an axis in object space. The axis is assumed to be + normalized.

-

[method:this rotateOnWorldAxis]( [param:Vector3 axis], [param:Float angle] )

+

[method:this rotateOnWorldAxis]( [param:Vector3 axis], [param:Float angle])

- axis -- A normalized vector in world space.
- angle -- The angle in radians.

+ axis -- A normalized vector in world space.
+ angle -- The angle in radians.

- Rotate an object along an axis in world space. The axis is assumed to be normalized. - Method Assumes no rotated parent. + Rotate an object along an axis in world space. The axis is assumed to be + normalized. Method Assumes no rotated parent.

[method:this rotateX]( [param:Float rad] )

- rad - the angle to rotate in radians.

+ rad - the angle to rotate in radians.

- Rotates the object around x axis in local space. + Rotates the object around x axis in local space.

[method:this rotateY]( [param:Float rad] )

- rad - the angle to rotate in radians.

+ rad - the angle to rotate in radians.

- Rotates the object around y axis in local space. + Rotates the object around y axis in local space.

[method:this rotateZ]( [param:Float rad] )

- rad - the angle to rotate in radians.

+ rad - the angle to rotate in radians.

- Rotates the object around z axis in local space. + Rotates the object around z axis in local space.

[method:undefined setRotationFromAxisAngle]( [param:Vector3 axis], [param:Float angle] )

@@ -402,26 +459,26 @@

[method:undefined setRotationFromAxisAngle]( [param:Vector3 axis], [param:Fl axis -- A normalized vector in object space.
angle -- angle in radians

- Calls [page:Quaternion.setFromAxisAngle setFromAxisAngle]( [page:Float axis], [page:Float angle] ) - on the [page:.quaternion]. + Calls [page:Quaternion.setFromAxisAngle setFromAxisAngle]( [page:Float axis], [page:Float angle] ) on the [page:.quaternion].

[method:undefined setRotationFromEuler]( [param:Euler euler] )

euler -- Euler angle specifying rotation amount.
- Calls [page:Quaternion.setRotationFromEuler setRotationFromEuler]( [page:Euler euler]) - on the [page:.quaternion]. + Calls [page:Quaternion.setRotationFromEuler setRotationFromEuler]( + [page:Euler euler]) on the [page:.quaternion].

[method:undefined setRotationFromMatrix]( [param:Matrix4 m] )

m -- rotate the quaternion by the rotation component of the matrix.
- Calls [page:Quaternion.setFromRotationMatrix setFromRotationMatrix]( [page:Matrix4 m]) - on the [page:.quaternion].

+ Calls [page:Quaternion.setFromRotationMatrix setFromRotationMatrix]( + [page:Matrix4 m]) on the [page:.quaternion].

- Note that this assumes that the upper 3x3 of m is a pure rotation matrix (i.e, unscaled). + Note that this assumes that the upper 3x3 of m is a pure rotation matrix + (i.e, unscaled).

[method:undefined setRotationFromQuaternion]( [param:Quaternion q] )

@@ -433,16 +490,19 @@

[method:undefined setRotationFromQuaternion]( [param:Quaternion q] )

[method:Object toJSON]( [param:Object meta] )

- meta -- object containing metadata such as materials, textures or images for the object.
- Convert the object to three.js [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. + meta -- object containing metadata such as materials, textures or images + for the object.
+ Convert the object to three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

[method:this translateOnAxis]( [param:Vector3 axis], [param:Float distance] )

- axis -- A normalized vector in object space.
- distance -- The distance to translate.

+ axis -- A normalized vector in object space.
+ distance -- The distance to translate.

- Translate an object by distance along an axis in object space. The axis is assumed to be normalized. + Translate an object by distance along an axis in object space. The axis is + assumed to be normalized.

[method:this translateX]( [param:Float distance] )

@@ -456,27 +516,27 @@

[method:this translateZ]( [param:Float distance] )

[method:undefined traverse]( [param:Function callback] )

- callback - A function with as first argument an object3D object.

+ callback - A function with as first argument an object3D object.

- Executes the callback on this object and all descendants.
- Note: Modifying the scene graph inside the callback is discouraged. + Executes the callback on this object and all descendants.
+ Note: Modifying the scene graph inside the callback is discouraged.

[method:undefined traverseVisible]( [param:Function callback] )

- callback - A function with as first argument an object3D object.

+ callback - A function with as first argument an object3D object.

- Like traverse, but the callback will only be executed for visible objects. - Descendants of invisible objects are not traversed.
- Note: Modifying the scene graph inside the callback is discouraged. + Like traverse, but the callback will only be executed for visible objects. + Descendants of invisible objects are not traversed.
+ Note: Modifying the scene graph inside the callback is discouraged.

[method:undefined traverseAncestors]( [param:Function callback] )

- callback - A function with as first argument an object3D object.

+ callback - A function with as first argument an object3D object.

- Executes the callback on all ancestors.
- Note: Modifying the scene graph inside the callback is discouraged. + Executes the callback on all ancestors.
+ Note: Modifying the scene graph inside the callback is discouraged.

[method:undefined updateMatrix]()

@@ -484,26 +544,30 @@

[method:undefined updateMatrix]()

[method:undefined updateMatrixWorld]( [param:Boolean force] )

- force - A boolean that can be used to bypass [page:.matrixWorldAutoUpdate], - to recalculate the world matrix of the object and descendants on the current frame. - Useful if you cannot wait for the renderer to update it on the next frame (assuming [page:.matrixWorldAutoUpdate] set to `true`).

+ force - A boolean that can be used to bypass + [page:.matrixWorldAutoUpdate], to recalculate the world matrix of the + object and descendants on the current frame. Useful if you cannot wait for + the renderer to update it on the next frame (assuming + [page:.matrixWorldAutoUpdate] set to `true`).

- Updates the global transform of the object and its descendants if the world matrix needs update ([page:.matrixWorldNeedsUpdate] set to true) or if the `force` parameter is set to `true`. + Updates the global transform of the object and its descendants if the + world matrix needs update ([page:.matrixWorldNeedsUpdate] set to true) or + if the `force` parameter is set to `true`.

[method:undefined updateWorldMatrix]( [param:Boolean updateParents], [param:Boolean updateChildren] )

- updateParents - recursively updates global transform of ancestors.
- updateChildren - recursively updates global transform of descendants.

+ updateParents - recursively updates global transform of ancestors.
+ updateChildren - recursively updates global transform of descendants.

- Updates the global transform of the object. + Updates the global transform of the object.

[method:Vector3 worldToLocal]( [param:Vector3 vector] )

- vector - A vector representing a position in world space.

+ vector - A vector representing a position in world space.

- Converts the vector from world space to this object's local space. + Converts the vector from world space to this object's local space.

Source

diff --git a/docs/api/en/core/Raycaster.html b/docs/api/en/core/Raycaster.html index 980448ae062014..91e42a29e0c808 100644 --- a/docs/api/en/core/Raycaster.html +++ b/docs/api/en/core/Raycaster.html @@ -10,9 +10,10 @@

[name]

- This class is designed to assist with [link:https://en.wikipedia.org/wiki/Ray_casting raycasting]. - Raycasting is used for mouse picking (working out what objects in the 3d space the mouse is over) amongst - other things. + This class is designed to assist with + [link:https://en.wikipedia.org/wiki/Ray_casting raycasting]. Raycasting is + used for mouse picking (working out what objects in the 3d space the mouse + is over) amongst other things.

Code Example

@@ -72,131 +73,156 @@

Constructor

[name]( [param:Vector3 origin], [param:Vector3 direction], [param:Float near], [param:Float far] )

- [page:Vector3 origin] — The origin vector where the ray casts from.
- [page:Vector3 direction] — The direction vector that gives direction to the ray. Should be normalized.
- [page:Float near] — All results returned are further away than near. Near can't be negative. Default value is 0.
- [page:Float far] — All results returned are closer than far. Far can't be lower than near. Default value is Infinity. -

-

- This creates a new raycaster object.
+ [page:Vector3 origin] — The origin vector where the ray casts from.
+ [page:Vector3 direction] — The direction vector that gives direction to + the ray. Should be normalized.
+ [page:Float near] — All results returned are further away than near. Near + can't be negative. Default value is 0.
+ [page:Float far] — All results returned are closer than far. Far can't be + lower than near. Default value is Infinity.

- +

This creates a new raycaster object.

Properties

[property:Float far]

- The far factor of the raycaster. This value indicates which objects can be discarded based on the distance. - This value shouldn't be negative and should be larger than the near property. + The far factor of the raycaster. This value indicates which objects can be + discarded based on the distance. This value shouldn't be negative and + should be larger than the near property.

[property:Float near]

- The near factor of the raycaster. This value indicates which objects can be discarded based on the distance. - This value shouldn't be negative and should be smaller than the far property. + The near factor of the raycaster. This value indicates which objects can + be discarded based on the distance. This value shouldn't be negative and + should be smaller than the far property.

[property:Camera camera]

- The camera to use when raycasting against view-dependent objects such as billboarded objects like [page:Sprites]. This field - can be set manually or is set when calling "setFromCamera". - - Defaults to null. + The camera to use when raycasting against view-dependent objects such as + billboarded objects like [page:Sprites]. This field can be set manually or + is set when calling "setFromCamera". Defaults to null.

[property:Layers layers]

- Used by [name] to selectively ignore 3D objects when performing intersection tests. The following code example ensures that - only 3D objects on layer `1` will be honored by the instance of [name]. - - - raycaster.layers.set( 1 ); - object.layers.enable( 1 ); - + Used by [name] to selectively ignore 3D objects when performing + intersection tests. The following code example ensures that only 3D + objects on layer `1` will be honored by the instance of [name]. + +raycaster.layers.set( 1 ); +object.layers.enable( 1 ); +

[property:Object params]

- An object with the following properties: + An object with the following properties: -{ +{ Mesh: {}, Line: { threshold: 1 }, LOD: {}, Points: { threshold: 1 }, - Sprite: {} + Sprite: {} } - Where threshold is the precision of the raycaster when intersecting objects, in world units. + Where threshold is the precision of the raycaster when intersecting + objects, in world units.

[property:Ray ray]

The [Page:Ray] used for the raycasting.

-

Methods

-

[method:undefined set]( [param:Vector3 origin], [param:Vector3 direction] )

+

[method:undefined set]( [param:Vector3 origin], [param:Vector3 direction])

- [page:Vector3 origin] — The origin vector where the ray casts from.
- [page:Vector3 direction] — The normalized direction vector that gives direction to the ray. + [page:Vector3 origin] — The origin vector where the ray casts from.
+ [page:Vector3 direction] — The normalized direction vector that gives + direction to the ray.

- Updates the ray with a new origin and direction. Please note that this method only copies the values from the arguments. + Updates the ray with a new origin and direction. Please note that this + method only copies the values from the arguments.

[method:undefined setFromCamera]( [param:Vector2 coords], [param:Camera camera] )

- [page:Vector2 coords] — 2D coordinates of the mouse, in normalized device coordinates (NDC)---X and Y components should be between -1 and 1.
- [page:Camera camera] — camera from which the ray should originate -

-

- Updates the ray with a new origin and direction. + [page:Vector2 coords] — 2D coordinates of the mouse, in normalized device + coordinates (NDC)---X and Y components should be between -1 and 1.
+ [page:Camera camera] — camera from which the ray should originate

+

Updates the ray with a new origin and direction.

[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )

- [page:Object3D object] — The object to check for intersection with the ray.
- [page:Boolean recursive] — If true, it also checks all descendants. Otherwise it only checks intersection with the object. Default is true.
- [page:Array optionalTarget] — (optional) target to set the result. Otherwise a new [page:Array] is instantiated. If set, you must clear this array prior to each call (i.e., array.length = 0;). + [page:Object3D object] — The object to check for intersection with the + ray.
+ [page:Boolean recursive] — If true, it also checks all descendants. + Otherwise it only checks intersection with the object. Default is true.
+ [page:Array optionalTarget] — (optional) target to set the result. + Otherwise a new [page:Array] is instantiated. If set, you must clear this + array prior to each call (i.e., array.length = 0;).

- Checks all intersection between the ray and the object with or without the descendants. Intersections are returned sorted by distance, closest first. An array of intersections is returned... + Checks all intersection between the ray and the object with or without the + descendants. Intersections are returned sorted by distance, closest first. + An array of intersections is returned...

- - [ { distance, point, face, faceIndex, object }, ... ] - + [ { distance, point, face, faceIndex, object }, ... ]

- [page:Float distance] – distance between the origin of the ray and the intersection
+ [page:Float distance] – distance between the origin of the ray and the + intersection
[page:Vector3 point] – point of intersection, in world coordinates
[page:Object face] – intersected face
[page:Integer faceIndex] – index of the intersected face
[page:Object3D object] – the intersected object
[page:Vector2 uv] - U,V coordinates at point of intersection
- [page:Vector2 uv2] - Second set of U,V coordinates at point of intersection
- [page:Integer instanceId] – The index number of the instance where the ray intersects the InstancedMesh + [page:Vector2 uv1] - Second set of U,V coordinates at point of + intersection
+ [page:Vector3 normal] - interpolated normal vector at point of + intersection
+ [page:Integer instanceId] – The index number of the instance where the ray + intersects the InstancedMesh

- `Raycaster` delegates to the [page:Object3D.raycast raycast] method of the passed object, when evaluating whether the ray intersects the object or not. This allows [page:Mesh meshes] to respond differently to ray casting than [page:Line lines] and [page:Points pointclouds]. + `Raycaster` delegates to the [page:Object3D.raycast raycast] method of the + passed object, when evaluating whether the ray intersects the object or + not. This allows [page:Mesh meshes] to respond differently to ray casting + than [page:Line lines] and [page:Points pointclouds].

- *Note* that for meshes, faces must be pointed towards the origin of the [page:.ray ray] in order to be detected; intersections of the ray passing through the back of a face will not be detected. To raycast against both faces of an object, you'll want to set the [page:Mesh.material material]'s [page:Material.side side] property to `THREE.DoubleSide`. + *Note* that for meshes, faces must be pointed towards the origin of the + [page:.ray ray] in order to be detected; intersections of the ray passing + through the back of a face will not be detected. To raycast against both + faces of an object, you'll want to set the [page:Mesh.material material]'s + [page:Material.side side] property to `THREE.DoubleSide`.

[method:Array intersectObjects]( [param:Array objects], [param:Boolean recursive], [param:Array optionalTarget] )

- [page:Array objects] — The objects to check for intersection with the ray.
- [page:Boolean recursive] — If true, it also checks all descendants of the objects. Otherwise it only checks intersection with the objects. Default is true.
- [page:Array optionalTarget] — (optional) target to set the result. Otherwise a new [page:Array] is instantiated. If set, you must clear this array prior to each call (i.e., array.length = 0;). + [page:Array objects] — The objects to check for intersection with the + ray.
+ [page:Boolean recursive] — If true, it also checks all descendants of the + objects. Otherwise it only checks intersection with the objects. Default + is true.
+ [page:Array optionalTarget] — (optional) target to set the result. + Otherwise a new [page:Array] is instantiated. If set, you must clear this + array prior to each call (i.e., array.length = 0;).

- Checks all intersection between the ray and the objects with or without the descendants. Intersections are returned sorted by distance, closest first. Intersections are of the same form as those returned by [page:.intersectObject]. + Checks all intersection between the ray and the objects with or without + the descendants. Intersections are returned sorted by distance, closest + first. Intersections are of the same form as those returned by + [page:.intersectObject].

-

Source

diff --git a/docs/api/en/core/Uniform.html b/docs/api/en/core/Uniform.html index 9430ffe30be0d4..fe572c866fbb7b 100644 --- a/docs/api/en/core/Uniform.html +++ b/docs/api/en/core/Uniform.html @@ -9,34 +9,40 @@

[name]

-

Uniforms are global GLSL variables. They are passed to shader programs. +

+ Uniforms are global GLSL variables. They are passed to shader programs.

Code Example

- When declaring a uniform of a [page:ShaderMaterial], it is declared by value or by object. + When declaring a uniform of a [page:ShaderMaterial], it is declared by + value or by object.

uniforms: { - time: { value: 1.0 }, + time: { value: 1.0 }, resolution: new Uniform( new Vector2() ) };

Uniform types

-

- Each uniform must have a `value` property. The type of the value must correspond to the - type of the uniform variable in the GLSL code as specified for the primitive GLSL types - in the table below. Uniform structures and arrays are also supported. GLSL arrays of primitive - type must either be specified as an array of the corresponding THREE objects or as a flat - array containing the data of all the objects. In other words; GLSL primitives in arrays - must not be represented by arrays. This rule does not apply transitively. - An array of `vec2` arrays, each with a length of five vectors, must be an array of arrays, - of either five [page:Vector2] objects or ten `number`s. + Each uniform must have a `value` property. The type of the value must + correspond to the type of the uniform variable in the GLSL code as + specified for the primitive GLSL types in the table below. Uniform + structures and arrays are also supported. GLSL arrays of primitive type + must either be specified as an array of the corresponding THREE objects or + as a flat array containing the data of all the objects. In other words; + GLSL primitives in arrays must not be represented by arrays. This rule + does not apply transitively. An array of `vec2` arrays, each with a length + of five vectors, must be an array of arrays, of either five [page:Vector2] + objects or ten `number`s.

+ - + @@ -44,7 +50,6 @@

Uniform types

- @@ -65,7 +70,6 @@

Uniform types

- @@ -110,7 +114,6 @@

Uniform types

- @@ -143,7 +146,6 @@

Uniform types

- @@ -168,7 +170,6 @@

Uniform types

- @@ -177,44 +178,45 @@

Uniform types

-
Uniform types + Uniform types +
GLSL type
int [page:Number] bool [page:Number]
vec2 [page:Vector2 THREE.Vector2] vec4 [page:Array Array] (*)
mat2 [page:Float32Array Float32Array] (*) mat4 [page:Array Array] (*)
ivec2, bvec2 [page:Float32Array Float32Array] (*) ivec4, bvec4 [page:Array Array] (*)
sampler2D [page:Texture THREE.Texture] samplerCube [page:CubeTexture THREE.CubeTexture]

- (*) Same for an (innermost) array (dimension) of the same GLSL type, containing the components of all vectors or matrices in the array. + (*) Same for an (innermost) array (dimension) of the same GLSL type, + containing the components of all vectors or matrices in the array.

Structured Uniforms

- Sometimes you want to organize uniforms as `structs` in your shader code. The following style must be used so `three.js` is able - to process structured uniform data. + Sometimes you want to organize uniforms as `structs` in your shader code. + The following style must be used so `three.js` is able to process + structured uniform data.

uniforms = { - data: { + data: { value: { - position: new Vector3(), - direction: new Vector3( 0, 0, 1 ) - } - } + position: new Vector3(), + direction: new Vector3( 0, 0, 1 ) + } + } }; This definition can be mapped on the following GLSL code: - struct Data { + struct Data { vec3 position; vec3 direction; }; - uniform Data data;

Structured Uniforms with Arrays

- It's also possible to manage `structs` in arrays. The syntax for this use case looks like so: + It's also possible to manage `structs` in arrays. The syntax for this use + case looks like so:

const entry1 = { @@ -234,11 +236,10 @@

Structured Uniforms with Arrays

This definition can be mapped on the following GLSL code: - struct Data { - vec3 position; - vec3 direction; + struct Data { + vec3 position; + vec3 direction; }; - uniform Data data[ 2 ]; @@ -246,23 +247,23 @@

Constructor

[name]( [param:Object value] )

- value -- An object containing the value to set up the uniform. It's type must be one of the Uniform Types described above. + value -- An object containing the value to set up the uniform. It's type + must be one of the Uniform Types described above.

Properties

[property:Object value]

-

- Current value of the uniform. -

+

Current value of the uniform.

Methods

[method:Uniform clone]()

- Returns a clone of this uniform.
- If the uniform's value property is an [page:Object] with a clone() method, this is used, otherwise the value is copied by assignment. - Array values are shared between cloned [page:Uniform]s. + Returns a clone of this uniform.
+ If the uniform's value property is an [page:Object] with a clone() method, + this is used, otherwise the value is copied by assignment. Array values + are shared between cloned [page:Uniform]s.

Source

diff --git a/docs/api/en/core/bufferAttributeTypes/BufferAttributeTypes.html b/docs/api/en/core/bufferAttributeTypes/BufferAttributeTypes.html index 845693c7e32b45..9564956f85beef 100644 --- a/docs/api/en/core/bufferAttributeTypes/BufferAttributeTypes.html +++ b/docs/api/en/core/bufferAttributeTypes/BufferAttributeTypes.html @@ -12,20 +12,21 @@

BufferAttribute Types

- There are nine types of [page:BufferAttribute] available in three.js. These correspond to the JavaScript - [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#Syntax Typed Arrays]. + There are nine types of [page:BufferAttribute] available in three.js. + These correspond to the JavaScript + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#Syntax Typed Arrays].

- THREE.Float64BufferAttribute + THREE.Float64BufferAttribute THREE.Float32BufferAttribute - THREE.Float16BufferAttribute + THREE.Float16BufferAttribute THREE.Uint32BufferAttribute - THREE.Int32BufferAttribute + THREE.Int32BufferAttribute THREE.Uint16BufferAttribute - THREE.Int16BufferAttribute + THREE.Int16BufferAttribute THREE.Uint8ClampedBufferAttribute - THREE.Uint8BufferAttribute + THREE.Uint8BufferAttribute THREE.Int8BufferAttribute @@ -33,28 +34,29 @@

Constructor

All of the above are called in the same way.

-

TypedBufferAttribute( [param:Array_or_Integer array], [param:Integer itemSize], [param:Boolean normalized] )

+

+ TypedBufferAttribute( [param:Array_or_Integer array], [param:Integer itemSize], [param:Boolean normalized] ) +

- array -- this can be a typed or untyped (normal) array or an integer length. - An array value will be converted to the Type specified. - If a length is given a new TypedArray will created, initialized with all elements set to zero.

+ array -- this can be a typed or untyped (normal) array or an integer + length. An array value will be converted to the Type specified. If a + length is given a new TypedArray will created, initialized with all + elements set to zero.

- itemSize -- the number of values of the array that should be associated with a particular vertex.

+ itemSize -- the number of values of the array that should be associated + with a particular vertex.

- normalized -- (optional) indicates how the underlying data in the buffer maps to the values in the GLSL code. + normalized -- (optional) indicates how the underlying data in the buffer + maps to the values in the GLSL code.

Properties

-

- See the [page:BufferAttribute] page for inherited properties. -

+

See the [page:BufferAttribute] page for inherited properties.

Methods

-

- See the [page:BufferAttribute] page for inherited methods. -

+

See the [page:BufferAttribute] page for inherited methods.

Source

diff --git a/docs/api/en/extras/DataUtils.html b/docs/api/en/extras/DataUtils.html index 00ab9865a2360c..203232960920d7 100644 --- a/docs/api/en/extras/DataUtils.html +++ b/docs/api/en/extras/DataUtils.html @@ -9,24 +9,24 @@

[name]

-

- A class containing utility functions for data. -

+

A class containing utility functions for data.

Methods

[method:Number toHalfFloat]( [param:Number val] )

- val -- A single precision floating point value.

+ val -- A single precision floating point value.

- Returns a half precision floating point value from the given single precision floating point value. + Returns a half precision floating point value from the given single + precision floating point value.

[method:Number fromHalfFloat]( [param:Number val] )

- val -- A half precision floating point value.

+ val -- A half precision floating point value.

- Returns a single precision floating point value from the given half precision floating point value. + Returns a single precision floating point value from the given half + precision floating point value.

Source

diff --git a/docs/api/en/extras/Earcut.html b/docs/api/en/extras/Earcut.html index af4ad4302cf095..d1e5866035299a 100644 --- a/docs/api/en/extras/Earcut.html +++ b/docs/api/en/extras/Earcut.html @@ -10,18 +10,21 @@

[name]

- An implementation of the earcut polygon triangulation algorithm. The code is a port of [link:https://github.com/mapbox/earcut mapbox/earcut]. + An implementation of the earcut polygon triangulation algorithm. The code + is a port of [link:https://github.com/mapbox/earcut mapbox/earcut].

Methods

[method:Array triangulate]( data, holeIndices, dim )

- data -- A flat array of vertex coordinates.
- holeIndices -- An array of hole indices if any.
- dim -- The number of coordinates per vertex in the input array.

+ data -- A flat array of vertex coordinates.
+ holeIndices -- An array of hole indices if any.
+ dim -- The number of coordinates per vertex in the input array.

- Triangulates the given shape definition by returning an array of triangles. A triangle is defined by three consecutive integers representing vertex indices. + Triangulates the given shape definition by returning an array of + triangles. A triangle is defined by three consecutive integers + representing vertex indices.

Source

diff --git a/docs/api/en/extras/ImageUtils.html b/docs/api/en/extras/ImageUtils.html index 363766df5f6c7e..84a3ec5d9b00ab 100644 --- a/docs/api/en/extras/ImageUtils.html +++ b/docs/api/en/extras/ImageUtils.html @@ -9,24 +9,28 @@

[name]

-

- A class containing utility functions for images. -

+

A class containing utility functions for images.

Methods

-

[method:String getDataURL]( [param:HTMLCanvasElement image] | [param:HTMLImageElement image] | [param:ImageBitmap image] )

+

+ [method:String getDataURL]( [param:HTMLCanvasElement image] | + [param:HTMLImageElement image] | [param:ImageBitmap image] ) +

- image -- The image object.

+ image -- The image object.

- Returns a data URI containing a representation of the given image. + Returns a data URI containing a representation of the given image.

-

[method:Object sRGBToLinear]( [param:HTMLCanvasElement image] | [param:HTMLImageElement image] | [param:ImageBitmap image] )

+

+ [method:Object sRGBToLinear]( [param:HTMLCanvasElement image] | + [param:HTMLImageElement image] | [param:ImageBitmap image] ) +

- image -- The image object.

+ image -- The image object.

- Converts the given sRGB image data to linear color space. + Converts the given sRGB image data to linear color space.

Source

diff --git a/docs/api/en/extras/PMREMGenerator.html b/docs/api/en/extras/PMREMGenerator.html index 879f68046fdea2..f1ac5dfb54ae1e 100644 --- a/docs/api/en/extras/PMREMGenerator.html +++ b/docs/api/en/extras/PMREMGenerator.html @@ -10,72 +10,91 @@

[name]

- This class generates a Prefiltered, Mipmapped Radiance Environment Map (PMREM) from a cubeMap environment texture. - This allows different levels of blur to be quickly accessed based on material roughness. - Unlike a traditional mipmap chain, it only goes down to the LOD_MIN level (above), and then creates extra even more - filtered 'mips' at the same LOD_MIN resolution, associated with higher roughness levels. In this way we maintain - resolution to smoothly interpolate diffuse lighting while limiting sampling computation.

- - Note: The minimum [page:MeshStandardMaterial]'s roughness depends on the size of the provided texture. - If your render has small dimensions or the shiny parts have a lot of curvature, you may still be able to get away with - a smaller texture size. - - - - - - - - - - - - - - - - - - - - - - - - - -
texture sizeminimum roughness -
160.21
320.15
640.11
1280.076
2560.054
5120.038
10240.027
+ This class generates a Prefiltered, Mipmapped Radiance Environment Map + (PMREM) from a cubeMap environment texture. This allows different levels + of blur to be quickly accessed based on material roughness. Unlike a + traditional mipmap chain, it only goes down to the LOD_MIN level (above), + and then creates extra even more filtered 'mips' at the same LOD_MIN + resolution, associated with higher roughness levels. In this way we + maintain resolution to smoothly interpolate diffuse lighting while + limiting sampling computation.

+ + Note: The minimum [page:MeshStandardMaterial]'s roughness depends on the + size of the provided texture. If your render has small dimensions or the + shiny parts have a lot of curvature, you may still be able to get away + with a smaller texture size.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
texture sizeminimum roughness
160.21
320.15
640.11
1280.076
2560.054
5120.038
10240.027
+

Constructor

[name]( [param:WebGLRenderer renderer] )

-

- This constructor creates a new [name]. -

+

This constructor creates a new [name].

Methods

-

[method:WebGLRenderTarget fromScene]( [param:Scene scene], [param:Number sigma], [param:Number near], [param:Number far] )

+

+ [method:WebGLRenderTarget fromScene]( [param:Scene scene], [param:Number sigma], [param:Number near], [param:Number far] ) +

- [page:Scene scene] - The given scene.
- [page:Number sigma] - (optional) Specifies a blur radius in radians to be applied to the scene before PMREM generation. Default is `0`.
- [page:Number near] - (optional) The near plane value. Default is `0.1`.
+ [page:Scene scene] - The given scene.
+ [page:Number sigma] - (optional) Specifies a blur radius in radians to be + applied to the scene before PMREM generation. Default is `0`.
+ [page:Number near] - (optional) The near plane value. Default is `0.1`.
[page:Number far] - (optional) The far plane value. Default is `100`.

- Generates a PMREM from a supplied Scene, which can be faster than using an image if networking bandwidth is low. - Optional near and far planes ensure the scene is rendered in its entirety (the cubeCamera is placed at the origin). + Generates a PMREM from a supplied Scene, which can be faster than using an + image if networking bandwidth is low. Optional near and far planes ensure + the scene is rendered in its entirety (the cubeCamera is placed at the + origin).

-

[method:WebGLRenderTarget fromEquirectangular]( [param:Texture equirectangular] )

+

+ [method:WebGLRenderTarget fromEquirectangular]( [param:Texture equirectangular] ) +

[page:Texture equirectangular] - The equirectangular texture.

Generates a PMREM from an equirectangular texture.

-

[method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] )

+

+ [method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] ) +

[page:CubeTexture cubemap] - The cubemap texture.

@@ -84,17 +103,21 @@

[method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] )

[method:undefined compileCubemapShader]()

- Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during your texture's network fetch for increased concurrency. + Pre-compiles the cubemap shader. You can get faster start-up by invoking + this method during your texture's network fetch for increased concurrency.

[method:undefined compileEquirectangularShader]()

- Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during your texture's network fetch for increased concurrency. + Pre-compiles the equirectangular shader. You can get faster start-up by + invoking this method during your texture's network fetch for increased + concurrency.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

diff --git a/docs/api/en/extras/ShapeUtils.html b/docs/api/en/extras/ShapeUtils.html index fc0b4c8f634926..bbb0f4c7d00e7d 100644 --- a/docs/api/en/extras/ShapeUtils.html +++ b/docs/api/en/extras/ShapeUtils.html @@ -10,39 +10,40 @@

[name]

- A class containing utility functions for shapes.

+ A class containing utility functions for shapes.

- Note that these are all linear functions so it is necessary to calculate separately for - x, y (and z, w if present) components of a vector. + Note that these are all linear functions so it is necessary to calculate + separately for x, y (and z, w if present) components of a vector.

-

Methods

[method:Number area]( contour )

- contour -- 2D polygon. An array of THREE.Vector2()

+ contour -- 2D polygon. An array of THREE.Vector2()

- Calculate area of a ( 2D ) contour polygon. + Calculate area of a ( 2D ) contour polygon.

[method:Boolean isClockWise]( pts )

- pts -- points defining a 2D polygon

+ pts -- points defining a 2D polygon

- Note that this is a linear function so it is necessary to calculate separately for - x, y components of a polygon.

+ Note that this is a linear function so it is necessary to calculate + separately for x, y components of a polygon.

- Used internally by [page:Path Path], - [page:ExtrudeGeometry ExtrudeGeometry] and [page:ShapeGeometry ShapeGeometry]. + Used internally by [page:Path Path], [page:ExtrudeGeometry ExtrudeGeometry] and [page:ShapeGeometry ShapeGeometry].

[method:Array triangulateShape]( contour, holes )

- contour -- 2D polygon. An array of [page:Vector2].
- holes -- An array that holds arrays of [page:Vector2]s. Each array represents a single hole definition.

+ contour -- 2D polygon. An array of [page:Vector2].
+ holes -- An array that holds arrays of [page:Vector2]s. Each array + represents a single hole definition.

- Used internally by [page:ExtrudeGeometry ExtrudeGeometry] and [page:ShapeGeometry ShapeGeometry] to calculate faces in shapes with holes. + Used internally by [page:ExtrudeGeometry ExtrudeGeometry] and + [page:ShapeGeometry ShapeGeometry] to calculate faces in shapes with + holes.

Source

diff --git a/docs/api/en/extras/core/Curve.html b/docs/api/en/extras/core/Curve.html index 17766b31c4ede5..6bde52b833e2f5 100644 --- a/docs/api/en/extras/core/Curve.html +++ b/docs/api/en/extras/core/Curve.html @@ -10,42 +10,49 @@

[name]

- An abstract base class for creating a [name] object that contains methods for interpolation. - For an array of [name]s see [page:CurvePath]. + An abstract base class for creating a [name] object that contains methods + for interpolation. For an array of [name]s see [page:CurvePath].

Constructor

-

[name]()

-

- This constructor creates a new [name]. -

+

This constructor creates a new [name].

Properties

[property:Integer arcLengthDivisions]

-

This value determines the amount of divisions when calculating the cumulative segment lengths of a curve via [page:.getLengths]. - To ensure precision when using methods like [page:.getSpacedPoints], it is recommended to increase [page:.arcLengthDivisions] if the curve is very large. Default is 200.

+

+ This value determines the amount of divisions when calculating the + cumulative segment lengths of a curve via [page:.getLengths]. To ensure + precision when using methods like [page:.getSpacedPoints], it is + recommended to increase [page:.arcLengthDivisions] if the curve is very + large. Default is 200. +

Methods

[method:Vector getPoint]( [param:Float t], [param:Vector optionalTarget] )

- [page:Float t] - A position on the curve. Must be in the range [ 0, 1 ].
- [page:Vector optionalTarget] — (optional) If specified, the result will be copied into this Vector, - otherwise a new Vector will be created.

+ [page:Float t] - A position on the curve. Must be in the range [ 0, 1 ]. +
+ [page:Vector optionalTarget] — (optional) If specified, the result will be + copied into this Vector, otherwise a new Vector will be created. +

Returns a vector for a given position on the curve.

[method:Vector getPointAt]( [param:Float u], [param:Vector optionalTarget] )

- [page:Float u] - A position on the curve according to the arc length. Must be in the range [ 0, 1 ].
- [page:Vector optionalTarget] — (optional) If specified, the result will be copied into this Vector, - otherwise a new Vector will be created.

- - Returns a vector for a given position on the curve according to the arc length. + [page:Float u] - A position on the curve according to the arc length. Must + be in the range [ 0, 1 ].
+ [page:Vector optionalTarget] — (optional) If specified, the result will be + copied into this Vector, otherwise a new Vector will be created. +

+ + Returns a vector for a given position on the curve according to the arc + length.

[method:Array getPoints]( [param:Integer divisions] )

@@ -70,42 +77,48 @@

[method:Array getLengths]( [param:Integer divisions] )

[method:undefined updateArcLengths]()

- Update the cumlative segment distance cache. The method must be called every time curve parameters are changed. - If an updated curve is part of a composed curve like [page:CurvePath], [page:.updateArcLengths]() must be + Update the cumlative segment distance cache. The method must be called + every time curve parameters are changed. If an updated curve is part of a + composed curve like [page:CurvePath], [page:.updateArcLengths]() must be called on the composed curve, too.

[method:Float getUtoTmapping]( [param:Float u], [param:Float distance] )

- Given u in the range ( 0 .. 1 ), returns [page:Float t] also in the range ( 0 .. 1 ). - u and t can then be used to give you points which are equidistant from the ends of the curve, - using [page:.getPoint]. -

+ Given u in the range ( 0 .. 1 ), returns [page:Float t] also in the range + ( 0 .. 1 ). u and t can then be used to give you points which are + equidistant from the ends of the curve, using [page:.getPoint]. +

[method:Vector getTangent]( [param:Float t], [param:Vector optionalTarget] )

- [page:Float t] - A position on the curve. Must be in the range [ 0, 1 ].
- [page:Vector optionalTarget] — (optional) If specified, the result will be copied into this Vector, - otherwise a new Vector will be created.

- - Returns a unit vector tangent at t. If the derived curve does not implement its - tangent derivation, two points a small delta apart will be used to find its gradient - which seems to give a reasonable approximation. + [page:Float t] - A position on the curve. Must be in the range [ 0, 1 ]. +
+ [page:Vector optionalTarget] — (optional) If specified, the result will be + copied into this Vector, otherwise a new Vector will be created. +

+ + Returns a unit vector tangent at t. If the derived curve does not + implement its tangent derivation, two points a small delta apart will be + used to find its gradient which seems to give a reasonable approximation.

[method:Vector getTangentAt]( [param:Float u], [param:Vector optionalTarget] )

- [page:Float u] - A position on the curve according to the arc length. Must be in the range [ 0, 1 ].
- [page:Vector optionalTarget] — (optional) If specified, the result will be copied into this Vector, - otherwise a new Vector will be created.

- - Returns tangent at a point which is equidistant to the ends of the curve from the - point given in [page:.getTangent]. + [page:Float u] - A position on the curve according to the arc length. Must + be in the range [ 0, 1 ].
+ [page:Vector optionalTarget] — (optional) If specified, the result will be + copied into this Vector, otherwise a new Vector will be created. +

+ + Returns tangent at a point which is equidistant to the ends of the curve + from the point given in [page:.getTangent].

[method:Object computeFrenetFrames]( [param:Integer segments], [param:Boolean closed] )

- Generates the Frenet Frames. Requires a curve definition in 3D space. Used in geometries like [page:TubeGeometry] or [page:ExtrudeGeometry]. + Generates the Frenet Frames. Requires a curve definition in 3D space. Used + in geometries like [page:TubeGeometry] or [page:ExtrudeGeometry].

[method:Curve clone]()

diff --git a/docs/api/en/extras/core/CurvePath.html b/docs/api/en/extras/core/CurvePath.html index cd8400d3fd0d85..7adae8c28bc7a4 100644 --- a/docs/api/en/extras/core/CurvePath.html +++ b/docs/api/en/extras/core/CurvePath.html @@ -12,16 +12,14 @@

[name]

- An abstract base class extending [page:Curve]. A CurvePath is simply an array of connected curves, - but retains the api of a curve. + An abstract base class extending [page:Curve]. A CurvePath is simply an + array of connected curves, but retains the api of a curve.

Constructor

[name]()

-

- The constructor take no parameters. -

+

The constructor take no parameters.

Properties

See the base [page:Curve] class for common properties.

@@ -42,21 +40,27 @@

[method:undefined closePath]()

Adds a [page:LineCurve lineCurve] to close the path.

[method:Array getCurveLengths]()

-

Get list of cumulative curve lengths of the curves in the [page:.curves] array.

+

+ Get list of cumulative curve lengths of the curves in the [page:.curves] + array. +

[method:Array getPoints]( [param:Integer divisions] )

- divisions -- number of pieces to divide the curve into. Default is `12`.

- - Returns an array of points representing a sequence of curves. The `division` parameter defines - the number of pieces each curve is divided into. However, for optimization and quality purposes, - the actual sampling resolution for each curve depends on its type. For example, for a [page:LineCurve], - the returned number of points is always just 2. + divisions -- number of pieces to divide the curve into. Default is + `12`.

+ + Returns an array of points representing a sequence of curves. The + `division` parameter defines the number of pieces each curve is divided + into. However, for optimization and quality purposes, the actual sampling + resolution for each curve depends on its type. For example, for a + [page:LineCurve], the returned number of points is always just 2.

[method:Array getSpacedPoints]( [param:Integer divisions] )

- divisions -- number of pieces to divide the curve into. Default is `40`.

+ divisions -- number of pieces to divide the curve into. Default is + `40`.

Returns a set of divisions + 1 equi-spaced points using getPointAt( u ).

diff --git a/docs/api/en/extras/core/Interpolations.html b/docs/api/en/extras/core/Interpolations.html index 4acd88185d62ab..6d29127e782ad6 100644 --- a/docs/api/en/extras/core/Interpolations.html +++ b/docs/api/en/extras/core/Interpolations.html @@ -10,33 +10,37 @@

[name]

- [name] contains spline and Bézier functions internally used by concrete curve classes. + [name] contains spline and Bézier functions internally used by concrete + curve classes.

Methods

[method:Float CatmullRom]( [param:Float t], [param:Float p0], [param:Float p1], [param:Float p2], [param:Float p3] )

- t -- interpolation weight.
- p0, p1, p2, p3 -- the points defining the spline curve.

+ t -- interpolation weight.
+ p0, p1, p2, p3 -- the points defining the spline curve.

- Used internally by [page:SplineCurve SplineCurve]. + Used internally by [page:SplineCurve SplineCurve].

[method:Float QuadraticBezier]( [param:Float t], [param:Float p0], [param:Float p1], [param:Float p2] )

- t -- interpolation weight.
- p0, p1, p2 -- the starting, control and end points defining the curve.

+ t -- interpolation weight.
+ p0, p1, p2 -- the starting, control and end points defining the curve.

- Used internally by [page:QuadraticBezierCurve3 QuadraticBezierCurve3] and [page:QuadraticBezierCurve QuadraticBezierCurve]. + Used internally by [page:QuadraticBezierCurve3 QuadraticBezierCurve3] and + [page:QuadraticBezierCurve QuadraticBezierCurve].

[method:Float CubicBezier]( [param:Float t], [param:Float p0], [param:Float p1], [param:Float p2], [param:Float p3] )

- t -- interpolation weight.
- p0, p1, p2, p3 -- the starting, control(twice) and end points defining the curve.

+ t -- interpolation weight.
+ p0, p1, p2, p3 -- the starting, control(twice) and end points defining the + curve.

- Used internally by [page:CubicBezierCurve3 CubicBezierCurve3] and [page:CubicBezierCurve CubicBezierCurve]. + Used internally by [page:CubicBezierCurve3 CubicBezierCurve3] and + [page:CubicBezierCurve CubicBezierCurve].

Source

diff --git a/docs/api/en/extras/core/Path.html b/docs/api/en/extras/core/Path.html index 0a7f878cd54eb5..ae0c5733b58adf 100644 --- a/docs/api/en/extras/core/Path.html +++ b/docs/api/en/extras/core/Path.html @@ -12,7 +12,8 @@

[name]

- A 2D path representation. The class provides methods for creating paths and contours of 2D shapes similar to the 2D Canvas API. + A 2D path representation. The class provides methods for creating paths + and contours of 2D shapes similar to the 2D Canvas API.

Code Example

@@ -33,28 +34,28 @@

Code Example

scene.add( line );
-

Constructor

-

[name]( [param:Array points] )

- points -- (optional) array of [page:Vector2 Vector2s].

+ points -- (optional) array of [page:Vector2 Vector2s].

- Creates a Path from the points. The first point defines the offset, then successive points - are added to the [page:CurvePath.curves curves] array as [page:LineCurve LineCurves].

+ Creates a Path from the points. The first point defines the offset, then + successive points are added to the [page:CurvePath.curves curves] array as + [page:LineCurve LineCurves].

- If no points are specified, an empty path is created and the [page:.currentPoint] is set to - the origin. + If no points are specified, an empty path is created and the + [page:.currentPoint] is set to the origin.

-

Properties

See the base [page:CurvePath] class for common properties.

[property:Vector2 currentPoint]

-

The current offset of the path. Any new [page:Curve] added will start here.

- +

+ The current offset of the path. Any new [page:Curve] added will start + here. +

Methods

See the base [page:CurvePath] class for common methods.

@@ -67,7 +68,8 @@

[method:this absarc]( [param:Float x], [param:Float y], [param:Float radius] endAngle -- The end angle in radians.
clockwise -- Sweep the arc clockwise. Defaults to `false`.

- Adds an absolutely positioned [page:EllipseCurve EllipseCurve] to the path. + Adds an absolutely positioned [page:EllipseCurve EllipseCurve] to the + path.

[method:this absellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )

@@ -78,25 +80,31 @@

[method:this absellipse]( [param:Float x], [param:Float y], [param:Float xRa startAngle -- The start angle in radians.
endAngle -- The end angle in radians.
clockwise -- Sweep the ellipse clockwise. Defaults to false.
- rotation -- The rotation angle of the ellipse in radians, counterclockwise from the positive X axis. Optional, defaults to 0.

+ rotation -- The rotation angle of the ellipse in radians, counterclockwise + from the positive X axis. Optional, defaults to 0.

- Adds an absolutely positioned [page:EllipseCurve EllipseCurve] to the path. + Adds an absolutely positioned [page:EllipseCurve EllipseCurve] to the + path.

[method:this arc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise] )

- x, y -- The center of the arc offset from the last call.
- radius -- The radius of the arc.
- startAngle -- The start angle in radians.
- endAngle -- The end angle in radians.
- clockwise -- Sweep the arc clockwise. Defaults to `false`.

+ x, y -- The center of the arc offset from the last call.
+ radius -- The radius of the arc.
+ startAngle -- The start angle in radians.
+ endAngle -- The end angle in radians.
+ clockwise -- Sweep the arc clockwise. Defaults to `false`.

- Adds an [page:EllipseCurve EllipseCurve] to the path, positioned relative to [page:.currentPoint]. + Adds an [page:EllipseCurve EllipseCurve] to the path, positioned relative + to [page:.currentPoint].

-

[method:this bezierCurveTo]( [param:Float cp1X], [param:Float cp1Y], [param:Float cp2X], [param:Float cp2Y], [param:Float x], [param:Float y] )

-

This creates a bezier curve from [page:.currentPoint] with (cp1X, cp1Y) and (cp2X, cp2Y) as control points and updates [page:.currentPoint] to x and y.

+

+ This creates a bezier curve from [page:.currentPoint] with (cp1X, cp1Y) + and (cp2X, cp2Y) as control points and updates [page:.currentPoint] to x + and y. +

[method:this ellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )

@@ -106,31 +114,37 @@

[method:this ellipse]( [param:Float x], [param:Float y], [param:Float xRadiu startAngle -- The start angle in radians.
endAngle -- The end angle in radians.
clockwise -- Sweep the ellipse clockwise. Defaults to `false`.
- rotation -- The rotation angle of the ellipse in radians, counterclockwise from the positive X axis. Optional, defaults to `0`.

+ rotation -- The rotation angle of the ellipse in radians, counterclockwise + from the positive X axis. Optional, defaults to `0`.

- Adds an [page:EllipseCurve EllipseCurve] to the path, positioned relative to [page:.currentPoint]. + Adds an [page:EllipseCurve EllipseCurve] to the path, positioned relative + to [page:.currentPoint].

[method:this lineTo]( [param:Float x], [param:Float y] )

-

Connects a [page:LineCurve] from [page:.currentPoint] to x, y onto the path.

- +

+ Connects a [page:LineCurve] from [page:.currentPoint] to x, y onto the + path. +

[method:this moveTo]( [param:Float x], [param:Float y] )

Move the [page:.currentPoint] to x, y.

-

[method:this quadraticCurveTo]( [param:Float cpX], [param:Float cpY], [param:Float x], [param:Float y] )

-

Creates a quadratic curve from [page:.currentPoint] with cpX and cpY as control point and updates [page:.currentPoint] to x and y.

+

+ Creates a quadratic curve from [page:.currentPoint] with cpX and cpY as + control point and updates [page:.currentPoint] to x and y. +

[method:this setFromPoints]( [param:Array vector2s] )

- points -- array of [page:Vector2 Vector2s].

+ points -- array of [page:Vector2 Vector2s].

- Points are added to the [page:CurvePath.curves curves] - array as [page:LineCurve LineCurves]. + Points are added to the [page:CurvePath.curves curves] array as + [page:LineCurve LineCurves].

-

[method:this splineThru] ( [param:Array points] )

+

[method:this splineThru] ( [param:Array points] )

points - An array of [page:Vector2 Vector2s]

diff --git a/docs/api/en/extras/core/Shape.html b/docs/api/en/extras/core/Shape.html index 615b61cab1580f..dc388547125265 100644 --- a/docs/api/en/extras/core/Shape.html +++ b/docs/api/en/extras/core/Shape.html @@ -12,8 +12,9 @@

[name]

- Defines an arbitrary 2d shape plane using paths with optional holes. It can be used with [page:ExtrudeGeometry], - [page:ShapeGeometry], to get points, or to get triangulated faces. + Defines an arbitrary 2d shape plane using paths with optional holes. It + can be used with [page:ExtrudeGeometry], [page:ShapeGeometry], to get + points, or to get triangulated faces.

Code Example

@@ -29,7 +30,14 @@

Code Example

heartShape.bezierCurveTo( 80, 35, 80, 0, 50, 0 ); heartShape.bezierCurveTo( 35, 0, 25, 25, 25, 25 ); - const extrudeSettings = { depth: 8, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1, bevelThickness: 1 }; + const extrudeSettings = { + depth: 8, + bevelEnabled: true, + bevelSegments: 2, + steps: 2, + bevelSize: 1, + bevelThickness: 1 + }; const geometry = new THREE.ExtrudeGeometry( heartShape, extrudeSettings ); @@ -39,33 +47,32 @@

Code Example

Examples

- [example:webgl_geometry_shapes geometry / shapes ]
- [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]
- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2 ]
+ [example:webgl_geometry_shapes geometry / shapes ]
+ [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]

-

Constructor

-

[name]( [param:Array points] )

- points -- (optional) array of [page:Vector2 Vector2s].

+ points -- (optional) array of [page:Vector2 Vector2s].

- Creates a Shape from the points. The first point defines the offset, then successive points - are added to the [page:CurvePath.curves curves] array as [page:LineCurve LineCurves].

+ Creates a Shape from the points. The first point defines the offset, then + successive points are added to the [page:CurvePath.curves curves] array as + [page:LineCurve LineCurves].

- If no points are specified, an empty shape is created and the [page:.currentPoint] is set to - the origin. + If no points are specified, an empty shape is created and the + [page:.currentPoint] is set to the origin.

-

Properties

See the base [page:Path] class for common properties.

[property:String uuid]

- [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this instance. This gets automatically assigned, so this shouldn't be edited. + [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of + this instance. This gets automatically assigned, so this shouldn't be + edited.

[property:Array holes]

@@ -76,23 +83,20 @@

Methods

[method:Array extractPoints]( [param:Integer divisions] )

- divisions -- The fineness of the result.

+ divisions -- The fineness of the result.

- Call [page:Curve.getPoints getPoints] on the shape and the [page:.holes] array, and return an object of the form: - -{ - shape - holes -} - - where shape and holes are arrays of [page:Vector2 Vector2s]. + Call [page:Curve.getPoints getPoints] on the shape and the [page:.holes] + array, and return an object of the form: + { shape holes } + where shape and holes are arrays of [page:Vector2 Vector2s].

[method:Array getPointsHoles]( [param:Integer divisions] )

- divisions -- The fineness of the result.

+ divisions -- The fineness of the result.

- Get an array of [page:Vector2 Vector2s] that represent the holes in the shape. + Get an array of [page:Vector2 Vector2s] that represent the holes in the + shape.

Source

diff --git a/docs/api/en/extras/core/ShapePath.html b/docs/api/en/extras/core/ShapePath.html index b22f87f586b868..ca027fb71ff8ec 100644 --- a/docs/api/en/extras/core/ShapePath.html +++ b/docs/api/en/extras/core/ShapePath.html @@ -10,36 +10,25 @@

[name]

- This class is used to convert a series of shapes to an array of [page:Path]s, for example an SVG shape to a - path (see the example below). -

- -

Examples

-

- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2] + This class is used to convert a series of shapes to an array of + [page:Path]s, for example an SVG shape to a path (see the example below).

Constructor

- -

[name]( )

+

[name]( )

- Creates a new ShapePath. Unlike a [page:Path], no points are passed in as the ShapePath is designed to - be generated after creation. + Creates a new ShapePath. Unlike a [page:Path], no points are passed in as + the ShapePath is designed to be generated after creation.

-

Properties

[property:Array subPaths]

-

- Array of [page:Path]s. -

+

Array of [page:Path]s.

[property:Array currentPath]

-

- The current [page:Path] that is being generated. -

+

The current [page:Path] that is being generated.

[property:Color color]

[page:Color] of the shape, by default set to white (0xffffff).

@@ -48,41 +37,50 @@

Methods

[method:this moveTo]( [param:Float x], [param:Float y] )

- Starts a new [page:Path] and calls [page:Path.moveTo]( x, y ) on that [page:Path]. - Also points [page:ShapePath.currentPath currentPath] to that [page:Path]. + Starts a new [page:Path] and calls [page:Path.moveTo]( x, y ) on that + [page:Path]. Also points [page:ShapePath.currentPath currentPath] to that + [page:Path].

[method:this lineTo]( [param:Float x], [param:Float y] )

-

This creates a line from the [page:ShapePath.currentPath currentPath]'s - offset to X and Y and updates the offset to X and Y.

+

+ This creates a line from the [page:ShapePath.currentPath currentPath]'s + offset to X and Y and updates the offset to X and Y. +

-

[method:this quadraticCurveTo]( [param:Float cpX], [param:Float cpY], [param:Float x], [param:Float y] )

-

This creates a quadratic curve from the [page:ShapePath.currentPath currentPath]'s - offset to x and y with cpX and cpY as control point and updates the [page:ShapePath.currentPath currentPath]'s - offset to x and y.

+

+ [method:this quadraticCurveTo]( [param:Float cpX], [param:Float cpY], [param:Float x], [param:Float y] ) +

+

+ This creates a quadratic curve from the [page:ShapePath.currentPath currentPath]'s offset to x and y with cpX and cpY as control point and + updates the [page:ShapePath.currentPath currentPath]'s offset to x and y. +

-

[method:this bezierCurveTo]( [param:Float cp1X], [param:Float cp1Y], [param:Float cp2X], [param:Float cp2Y], [param:Float x], [param:Float y] )

-

This creates a bezier curve from the [page:ShapePath.currentPath currentPath]'s - offset to x and y with cp1X, cp1Y and cp2X, cp2Y as control points and updates the - [page:ShapePath.currentPath currentPath]'s offset to x and y.

+

+ [method:this bezierCurveTo]( [param:Float cp1X], [param:Float cp1Y], [param:Float cp2X], [param:Float cp2Y], [param:Float x], [param:Float y] ) +

+

+ This creates a bezier curve from the [page:ShapePath.currentPath currentPath]'s offset to x and y with cp1X, cp1Y and cp2X, cp2Y as control + points and updates the [page:ShapePath.currentPath currentPath]'s offset + to x and y. +

-

[method:this splineThru] ( [param:Array points] )

+

[method:this splineThru] ( [param:Array points] )

points - An array of [page:Vector2]s

-

Connects a new [page:SplineCurve] onto the [page:ShapePath.currentPath currentPath].

- - -

[method:Array toShapes]( [param:Boolean isCCW] )

- isCCW -- Changes how solids and holes are generated + Connects a new [page:SplineCurve] onto the [page:ShapePath.currentPath currentPath].

-

- Converts the [page:ShapePath.subPaths subPaths] array into an array of Shapes. By default solid shapes are defined clockwise (CW) and holes are defined counterclockwise (CCW). If isCCW is set to true, - then those are flipped. -
+

[method:Array toShapes]( [param:Boolean isCCW] )

+

isCCW -- Changes how solids and holes are generated

+

+ Converts the [page:ShapePath.subPaths subPaths] array into an array of + Shapes. By default solid shapes are defined clockwise (CW) and holes are + defined counterclockwise (CCW). If isCCW is set to true, then those are + flipped. +

-

Source

diff --git a/docs/api/en/extras/curves/ArcCurve.html b/docs/api/en/extras/curves/ArcCurve.html index 4d3c4c275ed80a..38d82cc145a069 100644 --- a/docs/api/en/extras/curves/ArcCurve.html +++ b/docs/api/en/extras/curves/ArcCurve.html @@ -16,9 +16,7 @@

[name]

Properties

See the [page:EllipseCurve] class for common properties.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/extras/curves/CatmullRomCurve3.html b/docs/api/en/extras/curves/CatmullRomCurve3.html index bd2c7a16dcca1d..a9b016332decd8 100644 --- a/docs/api/en/extras/curves/CatmullRomCurve3.html +++ b/docs/api/en/extras/curves/CatmullRomCurve3.html @@ -11,8 +11,10 @@

[name]

-

Create a smooth 3d spline curve from a series of points using the - [link:https://en.wikipedia.org/wiki/Centripetal_Catmull-Rom_spline Catmull-Rom] algorithm.

+

+ Create a smooth 3d spline curve from a series of points using the + [link:https://en.wikipedia.org/wiki/Centripetal_Catmull-Rom_spline Catmull-Rom] algorithm. +

Code Example

@@ -43,20 +45,24 @@

Examples

Constructor

-

[name]( [param:Array points], [param:Boolean closed], [param:String curveType], [param:Float tension] )

+

+ [name]( [param:Array points], [param:Boolean closed], [param:String curveType], [param:Float tension] ) +

- points – An array of [page:Vector3] points
- closed – Whether the curve is closed. Default is `false`.
- curveType – Type of the curve. Default is `centripetal`.
+ points – An array of [page:Vector3] points
+ closed – Whether the curve is closed. Default is `false`.
+ curveType – Type of the curve. Default is `centripetal`.
tension – Tension of the curve. Default is `0.5`.

-

Properties

See the base [page:Curve] class for common properties.

[property:Array points]

-

The array of [page:Vector3] points that define the curve. It needs at least two entries.

+

+ The array of [page:Vector3] points that define the curve. It needs at + least two entries. +

[property:Boolean closed]

The curve will loop back onto itself when this is true.

@@ -67,7 +73,6 @@

[property:String curveType]

[property:Float tension]

When [page:.curveType] is `catmullrom`, defines catmullrom's tension.

-

Methods

See the base [page:Curve] class for common methods.

diff --git a/docs/api/en/extras/curves/CubicBezierCurve.html b/docs/api/en/extras/curves/CubicBezierCurve.html index 7e5fc46c8be304..5b3ded36da6202 100644 --- a/docs/api/en/extras/curves/CubicBezierCurve.html +++ b/docs/api/en/extras/curves/CubicBezierCurve.html @@ -13,8 +13,11 @@

[name]

Create a smooth 2d - cubic bezier curve, - defined by a start point, endpoint and two control points. + cubic bezier curve, defined by a start point, endpoint and two control points.

Code Example

@@ -38,12 +41,14 @@

Code Example

Constructor

- -

[name] ( [param:Vector2 v0], [param:Vector2 v1], [param:Vector2 v2], [param:Vector2 v3] )

+

+ [name] ( [param:Vector2 v0], [param:Vector2 v1], [param:Vector2 v2], + [param:Vector2 v3] ) +

- [page:Vector2 v0] – The starting point.
- [page:Vector2 v1] – The first control point.
- [page:Vector2 v2] – The second control point.
+ [page:Vector2 v0] – The starting point.
+ [page:Vector2 v1] – The first control point.
+ [page:Vector2 v2] – The second control point.
[page:Vector2 v3] – The ending point.

@@ -62,7 +67,6 @@

[property:Vector2 v2]

[property:Vector2 v3]

The ending point.

-

Methods

See the base [page:Curve] class for common Methods.

diff --git a/docs/api/en/extras/curves/CubicBezierCurve3.html b/docs/api/en/extras/curves/CubicBezierCurve3.html index 45528487ecdf10..84ef76403b05ba 100644 --- a/docs/api/en/extras/curves/CubicBezierCurve3.html +++ b/docs/api/en/extras/curves/CubicBezierCurve3.html @@ -13,8 +13,11 @@

[name]

Create a smooth 3d - cubic bezier curve, - defined by a start point, endpoint and two control points. + cubic bezier curve, defined by a start point, endpoint and two control points.

Code Example

@@ -39,12 +42,14 @@

Code Example

Constructor

- -

[name]( [param:Vector3 v0], [param:Vector3 v1], [param:Vector3 v2], [param:Vector3 v3] )

+

+ [name]( [param:Vector3 v0], [param:Vector3 v1], [param:Vector3 v2], + [param:Vector3 v3] ) +

- [page:Vector3 v0] – The starting point.
- [page:Vector3 v1] – The first control point.
- [page:Vector3 v2] – The second control point.
+ [page:Vector3 v0] – The starting point.
+ [page:Vector3 v1] – The first control point.
+ [page:Vector3 v2] – The second control point.
[page:Vector3 v3] – The ending point.

@@ -63,7 +68,6 @@

[property:Vector3 v2]

[property:Vector3 v3]

The ending point.

-

Methods

See the base [page:Curve] class for common Methods.

diff --git a/docs/api/en/extras/curves/EllipseCurve.html b/docs/api/en/extras/curves/EllipseCurve.html index f5f7c3c7ddabeb..6b14b4426eb502 100644 --- a/docs/api/en/extras/curves/EllipseCurve.html +++ b/docs/api/en/extras/curves/EllipseCurve.html @@ -12,8 +12,7 @@

[name]

- Creates a 2d curve in the shape of an ellipse. Setting the - [page:Number xRadius] equal to the [page:Number yRadius] will result in a circle. + Creates a 2d curve in the shape of an ellipse. Setting the [page:Number xRadius] equal to the [page:Number yRadius] will result in a circle.

Code Example

@@ -38,17 +37,25 @@

Code Example

Constructor

- -

[name]( [param:Float aX], [param:Float aY], [param:Float xRadius], [param:Float yRadius], [param:Radians aStartAngle], [param:Radians aEndAngle], [param:Boolean aClockwise], [param:Radians aRotation] )

+

+ [name]( [param:Float aX], [param:Float aY], [param:Float xRadius], + [param:Float yRadius], [param:Radians aStartAngle], [param:Radians aEndAngle], [param:Boolean aClockwise], [param:Radians aRotation] ) +

- [page:Float aX] – The X center of the ellipse. Default is `0`.
- [page:Float aY] – The Y center of the ellipse. Default is `0`.
- [page:Float xRadius] – The radius of the ellipse in the x direction. Default is `1`.
- [page:Float yRadius] – The radius of the ellipse in the y direction. Default is `1`.
- [page:Radians aStartAngle] – The start angle of the curve in radians starting from the positive X axis. Default is `0`.
- [page:Radians aEndAngle] – The end angle of the curve in radians starting from the positive X axis. Default is `2 x Math.PI`.
- [page:Boolean aClockwise] – Whether the ellipse is drawn clockwise. Default is `false`.
- [page:Radians aRotation] – The rotation angle of the ellipse in radians, counterclockwise from the positive X axis (optional). Default is `0`.

+ [page:Float aX] – The X center of the ellipse. Default is `0`.
+ [page:Float aY] – The Y center of the ellipse. Default is `0`.
+ [page:Float xRadius] – The radius of the ellipse in the x direction. + Default is `1`.
+ [page:Float yRadius] – The radius of the ellipse in the y direction. + Default is `1`.
+ [page:Radians aStartAngle] – The start angle of the curve in radians + starting from the positive X axis. Default is `0`.
+ [page:Radians aEndAngle] – The end angle of the curve in radians starting + from the positive X axis. Default is `2 x Math.PI`.
+ [page:Boolean aClockwise] – Whether the ellipse is drawn clockwise. + Default is `false`.
+ [page:Radians aRotation] – The rotation angle of the ellipse in radians, + counterclockwise from the positive X axis (optional). Default is `0`.

Properties

@@ -67,17 +74,24 @@

[property:Radians yRadius]

The radius of the ellipse in the y direction.

[property:Float aStartAngle]

-

The start angle of the curve in radians starting from the middle right side.

+

+ The start angle of the curve in radians starting from the middle right + side. +

[property:Float aEndAngle]

-

The end angle of the curve in radians starting from the middle right side.

+

+ The end angle of the curve in radians starting from the middle right side. +

[property:Boolean aClockwise]

Whether the ellipse is drawn clockwise.

[property:Float aRotation]

-

The rotation angle of the ellipse in radians, counterclockwise from the positive X axis (optional). Default is `0`.

- +

+ The rotation angle of the ellipse in radians, counterclockwise from the + positive X axis (optional). Default is `0`. +

Methods

See the base [page:Curve] class for common methods.

diff --git a/docs/api/en/extras/curves/LineCurve.html b/docs/api/en/extras/curves/LineCurve.html index 37662c27ccd193..d69c9a076a147e 100644 --- a/docs/api/en/extras/curves/LineCurve.html +++ b/docs/api/en/extras/curves/LineCurve.html @@ -15,14 +15,12 @@

[name]

Constructor

-

[name]( [param:Vector2 v1], [param:Vector2 v2] )

- [page:Vector2 v1] – The start point.
+ [page:Vector2 v1] – The start point.
[page:Vector2 v2] - The end point.

-

Properties

See the base [page:Curve] class for common properties.

@@ -35,7 +33,6 @@

[property:Vector2 v2]

Methods

See the base [page:Curve] class for common methods.

-

Source

diff --git a/docs/api/en/extras/curves/LineCurve3.html b/docs/api/en/extras/curves/LineCurve3.html index ef31e5a898ba65..1a480424b89234 100644 --- a/docs/api/en/extras/curves/LineCurve3.html +++ b/docs/api/en/extras/curves/LineCurve3.html @@ -15,14 +15,12 @@

[name]

Constructor

-

[name]( [param:Vector3 v1], [param:Vector3 v2] )

- [page:Vector3 v1] – The start point.
+ [page:Vector3 v1] – The start point.
[page:Vector3 v2] - The end point.

-

Properties

See the base [page:Curve] class for common properties.

diff --git a/docs/api/en/extras/curves/QuadraticBezierCurve.html b/docs/api/en/extras/curves/QuadraticBezierCurve.html index b185170a1d9614..a1893af96856ce 100644 --- a/docs/api/en/extras/curves/QuadraticBezierCurve.html +++ b/docs/api/en/extras/curves/QuadraticBezierCurve.html @@ -13,8 +13,11 @@

[name]

Create a smooth 2d - quadratic bezier curve, - defined by a startpoint, endpoint and a single control point. + quadratic bezier curve, defined by a startpoint, endpoint and a single control point.

Code Example

@@ -37,15 +40,15 @@

Code Example

Constructor

- -

[name]( [param:Vector2 v0], [param:Vector2 v1], [param:Vector2 v2] )

+

+ [name]( [param:Vector2 v0], [param:Vector2 v1], [param:Vector2 v2] ) +

- [page:Vector2 v0] – The startpoint.
- [page:Vector2 v1] – The control point.
+ [page:Vector2 v0] – The startpoint.
+ [page:Vector2 v1] – The control point.
[page:Vector2 v2] – The endpoint.

-

Properties

See the base [page:Curve] class for common properties.

diff --git a/docs/api/en/extras/curves/QuadraticBezierCurve3.html b/docs/api/en/extras/curves/QuadraticBezierCurve3.html index a3e6ca76a4ff30..6d71059a32c4eb 100644 --- a/docs/api/en/extras/curves/QuadraticBezierCurve3.html +++ b/docs/api/en/extras/curves/QuadraticBezierCurve3.html @@ -13,8 +13,11 @@

[name]

Create a smooth 3d - quadratic bezier curve, - defined by a startpoint, endpoint and a single control point. + quadratic bezier curve, defined by a startpoint, endpoint and a single control point.

Code Example

@@ -37,16 +40,15 @@

Code Example

Constructor

- -

[name]( [param:Vector3 v0], [param:Vector3 v1], [param:Vector3 v2] )

+

+ [name]( [param:Vector3 v0], [param:Vector3 v1], [param:Vector3 v2] ) +

- [page:Vector3 v0] – The starting point
- [page:Vector3 v1] – The middle control point
- [page:Vector3 v2] – The ending point
+ [page:Vector3 v0] – The starting point
+ [page:Vector3 v1] – The middle control point
+ [page:Vector3 v2] – The ending point

- -

Properties

See the base [page:Curve] class for common properties.

diff --git a/docs/api/en/extras/curves/SplineCurve.html b/docs/api/en/extras/curves/SplineCurve.html index 72f24ebb222c99..c3454803388771 100644 --- a/docs/api/en/extras/curves/SplineCurve.html +++ b/docs/api/en/extras/curves/SplineCurve.html @@ -12,8 +12,8 @@

[name]

- Create a smooth 2d spline curve from a series of points. Internally this uses - [page:Interpolations.CatmullRom] to create the curve. + Create a smooth 2d spline curve from a series of points. Internally this + uses [page:Interpolations.CatmullRom] to create the curve.

Code Example

@@ -39,24 +39,18 @@

Code Example

Constructor

-

[name]( [param:Array points] )

points – An array of [page:Vector2] points that define the curve.

-

Properties

See the base [page:Curve] class for common properties.

[property:Array points]

The array of [page:Vector2] points that define the curve.

- -

Methods

See the base [page:Curve] class for common methods.

- -

Source

diff --git a/docs/api/en/geometries/BoxGeometry.html b/docs/api/en/geometries/BoxGeometry.html index bea5d51b7ed3cb..4be58bd3ee05ec 100644 --- a/docs/api/en/geometries/BoxGeometry.html +++ b/docs/api/en/geometries/BoxGeometry.html @@ -1,74 +1,98 @@ - - - - - - - - [page:BufferGeometry] → - -

[name]

- -

- [name] is a geometry class for a rectangular cuboid with a given 'width', 'height', and 'depth'. - On creation, the cuboid is centred on the origin, with each edge parallel to one of the axes. -

- - - - - -

Code Example

- - const geometry = new THREE.BoxGeometry( 1, 1, 1 ); - const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); - const cube = new THREE.Mesh( geometry, material ); - scene.add( cube ); - - -

Constructor

- -

[name]([param:Float width], [param:Float height], [param:Float depth], [param:Integer widthSegments], [param:Integer heightSegments], [param:Integer depthSegments])

-

- width — Width; that is, the length of the edges parallel to the X axis. Optional; defaults to 1.
- height — Height; that is, the length of the edges parallel to the Y axis. Optional; defaults to 1.
- depth — Depth; that is, the length of the edges parallel to the Z axis. Optional; defaults to 1.
- widthSegments — Number of segmented rectangular faces along the width of the sides. Optional; defaults to 1.
- heightSegments — Number of segmented rectangular faces along the height of the sides. Optional; defaults to 1.
- depthSegments — Number of segmented rectangular faces along the depth of the sides. Optional; defaults to 1.
-

- -

Properties

-

See the base [page:BufferGeometry] class for common properties.

- -

[property:Object parameters]

-

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. -

- -

Methods

-

See the base [page:BufferGeometry] class for common methods.

- -

Source

- -

- [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] -

- + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ [name] is a geometry class for a rectangular cuboid with a given 'width', + 'height', and 'depth'. On creation, the cuboid is centred on the origin, + with each edge parallel to one of the axes. +

+ + + + + +

Code Example

+ + +const geometry = new THREE.BoxGeometry( 1, 1, 1 ); +const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); +const cube = new THREE.Mesh( geometry, material ); +scene.add( cube ); + + +

Constructor

+ +

+ [name]([param:Float width], [param:Float height], [param:Float depth], + [param:Integer widthSegments], [param:Integer heightSegments], + [param:Integer depthSegments]) +

+

+ width — Width; that is, the length of the edges parallel to the X axis. + Optional; defaults to 1. +
+ height — Height; that is, the length of the edges parallel to the Y axis. + Optional; defaults to 1. +
+ depth — Depth; that is, the length of the edges parallel to the Z axis. + Optional; defaults to 1. +
+ widthSegments — Number of segmented rectangular faces along the width of + the sides. Optional; defaults to 1. +
+ heightSegments — Number of segmented rectangular faces along the height of + the sides. Optional; defaults to 1. +
+ depthSegments — Number of segmented rectangular faces along the depth of + the sides. Optional; defaults to 1. +
+

+ +

Properties

+

See the base [page:BufferGeometry] class for common properties.

+ +

[property:Object parameters]

+

+ An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry. +

+ +

Methods

+

See the base [page:BufferGeometry] class for common methods.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ diff --git a/docs/api/en/geometries/CapsuleGeometry.html b/docs/api/en/geometries/CapsuleGeometry.html index 9fe5041795b2b9..8615d9921995da 100644 --- a/docs/api/en/geometries/CapsuleGeometry.html +++ b/docs/api/en/geometries/CapsuleGeometry.html @@ -12,11 +12,14 @@

[name]

- [name] is a geometry class for a capsule with given radii and height. - It is constructed using a lathe. + [name] is a geometry class for a capsule with given radii and height. It + is constructed using a lathe.

- + - +

Code Example

- const geometry = new THREE.CircleGeometry( 5, 32 ); - const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); - const circle = new THREE.Mesh( geometry, material ); - scene.add( circle ); +const geometry = new THREE.CircleGeometry( 5, 32 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const circle = new THREE.Mesh( geometry, material ); scene.add( circle );

Constructor

-

[name]([param:Float radius], [param:Integer segments], [param:Float thetaStart], [param:Float thetaLength])

+

+ [name]([param:Float radius], [param:Integer segments], [param:Float thetaStart], [param:Float thetaLength]) +

- radius — Radius of the circle, default = 1.
- segments — Number of segments (triangles), minimum = 3, default = 32.
- thetaStart — Start angle for first segment, default = 0 (three o'clock position).
- thetaLength — The central angle, often called theta, of the circular sector. The default is 2*Pi, which makes for a complete circle. + radius — Radius of the circle, default = 1.
+ segments — Number of segments (triangles), minimum = 3, default = 32.
+ thetaStart — Start angle for first segment, default = 0 (three o'clock + position).
+ thetaLength — The central angle, often called theta, of the circular + sector. The default is 2*Pi, which makes for a complete circle.

Properties

@@ -60,7 +68,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/ConeGeometry.html b/docs/api/en/geometries/ConeGeometry.html index 6653ea1dff7211..c238c2e44d221c 100644 --- a/docs/api/en/geometries/ConeGeometry.html +++ b/docs/api/en/geometries/ConeGeometry.html @@ -33,23 +33,30 @@

[name]

Code Example

- const geometry = new THREE.ConeGeometry( 5, 20, 32 ); - const material = new THREE.MeshBasicMaterial( {color: 0xffff00} ); - const cone = new THREE.Mesh( geometry, material ); - scene.add( cone ); + +const geometry = new THREE.ConeGeometry( 5, 20, 32 ); +const material = new THREE.MeshBasicMaterial( {color: 0xffff00} ); +const cone = new THREE.Mesh(geometry, material ); scene.add( cone );

Constructor

-

[name]([param:Float radius], [param:Float height], [param:Integer radialSegments], [param:Integer heightSegments], [param:Boolean openEnded], [param:Float thetaStart], [param:Float thetaLength])

+

+ [name]([param:Float radius], [param:Float height], [param:Integer radialSegments], [param:Integer heightSegments], [param:Boolean openEnded], [param:Float thetaStart], [param:Float thetaLength]) +

- radius — Radius of the cone base. Default is 1.
- height — Height of the cone. Default is 1.
- radialSegments — Number of segmented faces around the circumference of the cone. Default is 32
- heightSegments — Number of rows of faces along the height of the cone. Default is 1.
- openEnded — A Boolean indicating whether the base of the cone is open or capped. Default is false, meaning capped.
- thetaStart — Start angle for first segment, default = 0 (three o'clock position).
- thetaLength — The central angle, often called theta, of the circular sector. The default is 2*Pi, which makes for a complete cone. + radius — Radius of the cone base. Default is 1.
+ height — Height of the cone. Default is 1.
+ radialSegments — Number of segmented faces around the circumference of the + cone. Default is 32
+ heightSegments — Number of rows of faces along the height of the cone. + Default is 1.
+ openEnded — A Boolean indicating whether the base of the cone is open or + capped. Default is false, meaning capped.
+ thetaStart — Start angle for first segment, default = 0 (three o'clock + position).
+ thetaLength — The central angle, often called theta, of the circular + sector. The default is 2*Pi, which makes for a complete cone.

Properties

@@ -57,7 +64,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/CylinderGeometry.html b/docs/api/en/geometries/CylinderGeometry.html index 4c6c295dd52433..c53b2bb2dff3ff 100644 --- a/docs/api/en/geometries/CylinderGeometry.html +++ b/docs/api/en/geometries/CylinderGeometry.html @@ -13,7 +13,10 @@

[name]

A class for generating cylinder geometries.

- + -

Code Example

@@ -46,23 +51,29 @@

Code Example

Constructor

-

[name]([param:Array points], [param:Integer segments], [param:Float phiStart], [param:Float phiLength])

-

- points — Array of Vector2s. The x-coordinate of each point must be greater than zero. Default is an array with (0,-0.5), (0.5,0) and (0,0.5) which creates a simple diamond shape.
- segments — the number of circumference segments to generate. Default is 12.
- phiStart — the starting angle in radians. Default is 0.
- phiLength — the radian (0 to 2PI) range of the lathed section 2PI is a closed lathe, less than 2PI is a portion. Default is 2PI. -

+

+ [name]([param:Array points], [param:Integer segments], [param:Float + phiStart], [param:Float phiLength]) +

- This creates a [name] based on the parameters. + points — Array of Vector2s. The x-coordinate of each point must be greater + than zero. Default is an array with (0,-0.5), (0.5,0) and (0,0.5) which + creates a simple diamond shape.
+ segments — the number of circumference segments to generate. Default is + 12.
+ phiStart — the starting angle in radians. Default is 0.
+ phiLength — the radian (0 to 2PI) range of the lathed section 2PI is a + closed lathe, less than 2PI is a portion. Default is 2PI.

+

This creates a [name] based on the parameters.

Properties

See the base [page:BufferGeometry] class for common properties.

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/OctahedronGeometry.html b/docs/api/en/geometries/OctahedronGeometry.html index a60d2b84b24ed7..4db513f8abc642 100644 --- a/docs/api/en/geometries/OctahedronGeometry.html +++ b/docs/api/en/geometries/OctahedronGeometry.html @@ -12,7 +12,10 @@

[name]

A class for generating an octahedron geometry.

- + -

Constructor

[name]([param:Float radius], [param:Integer detail])

- radius — Radius of the octahedron. Default is 1.
- detail — Default is 0. Setting this to a value greater than zero add vertices making it no longer an octahedron. + radius — Radius of the octahedron. Default is 1.
+ detail — Default is 0. Setting this to a value greater than zero add + vertices making it no longer an octahedron.

Properties

@@ -43,7 +46,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/PlaneGeometry.html b/docs/api/en/geometries/PlaneGeometry.html index 36b792788b43b7..acb046c6f7e1ae 100644 --- a/docs/api/en/geometries/PlaneGeometry.html +++ b/docs/api/en/geometries/PlaneGeometry.html @@ -13,7 +13,10 @@

[name]

A class for generating plane geometries.

- + -

Code Example

- const geometry = new THREE.PlaneGeometry( 1, 1 ); - const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} ); - const plane = new THREE.Mesh( geometry, material ); - scene.add( plane ); + +const geometry = new THREE.PlaneGeometry( 1, 1 ); +const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} ); +const plane = new THREE.Mesh( geometry, material ); +scene.add( plane );

Constructor

-

[name]([param:Float width], [param:Float height], [param:Integer widthSegments], [param:Integer heightSegments])

+

+ [name]([param:Float width], [param:Float height], [param:Integer + widthSegments], [param:Integer heightSegments]) +

- width — Width along the X axis. Default is 1.
- height — Height along the Y axis. Default is 1.
- widthSegments — Optional. Default is 1.
- heightSegments — Optional. Default is 1. + width — Width along the X axis. Default is 1.
+ height — Height along the Y axis. Default is 1.
+ widthSegments — Optional. Default is 1.
+ heightSegments — Optional. Default is 1.

Properties

@@ -54,7 +60,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/PolyhedronGeometry.html b/docs/api/en/geometries/PolyhedronGeometry.html index 6e4a44a1d4295f..1e4168dc8ff772 100644 --- a/docs/api/en/geometries/PolyhedronGeometry.html +++ b/docs/api/en/geometries/PolyhedronGeometry.html @@ -12,14 +12,16 @@

[name]

- A polyhedron is a solid in three dimensions with flat faces. This class will take an array of vertices, - project them onto a sphere, and then divide them up to the desired level of detail. This class is used - by [page:DodecahedronGeometry], [page:IcosahedronGeometry], [page:OctahedronGeometry], - and [page:TetrahedronGeometry] to generate their respective geometries. + A polyhedron is a solid in three dimensions with flat faces. This class + will take an array of vertices, project them onto a sphere, and then + divide them up to the desired level of detail. This class is used by + [page:DodecahedronGeometry], [page:IcosahedronGeometry], + [page:OctahedronGeometry], and [page:TetrahedronGeometry] to generate + their respective geometries.

Code Example

- + const verticesOfCube = [ -1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1, -1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1, @@ -39,13 +41,17 @@

Code Example

Constructor

- -

[name]([param:Array vertices], [param:Array indices], [param:Float radius], [param:Integer detail])

+

+ [name]([param:Array vertices], [param:Array indices], [param:Float radius], [param:Integer detail]) +

- vertices — [page:Array] of points of the form [1,1,1, -1,-1,-1, ... ]
- indices — [page:Array] of indices that make up the faces of the form [0,1,2, 2,3,0, ... ]
- radius — [page:Float] - The radius of the final shape
- detail — [page:Integer] - How many levels to subdivide the geometry. The more detail, the smoother the shape. + vertices — [page:Array] of points of the form [1,1,1, -1,-1,-1, ... ] +
+ indices — [page:Array] of indices that make up the faces of the form + [0,1,2, 2,3,0, ... ]
+ radius — [page:Float] - The radius of the final shape
+ detail — [page:Integer] - How many levels to subdivide the geometry. The + more detail, the smoother the shape.

Properties

@@ -53,7 +59,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/RingGeometry.html b/docs/api/en/geometries/RingGeometry.html index 4dde063dfa73b5..e3bd23a1f49e98 100644 --- a/docs/api/en/geometries/RingGeometry.html +++ b/docs/api/en/geometries/RingGeometry.html @@ -30,34 +30,37 @@

[name]

} -

Code Example

- const geometry = new THREE.RingGeometry( 1, 5, 32 ); - const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } ); - const mesh = new THREE.Mesh( geometry, material ); - scene.add( mesh ); + +const geometry = new THREE.RingGeometry( 1, 5, 32 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } ); +const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh );

Constructor

-

[name]([param:Float innerRadius], [param:Float outerRadius], [param:Integer thetaSegments], [param:Integer phiSegments], [param:Float thetaStart], [param:Float thetaLength])

+

+ [name]([param:Float innerRadius], [param:Float outerRadius], + [param:Integer thetaSegments], [param:Integer phiSegments], [param:Float thetaStart], [param:Float thetaLength]) +

- innerRadius — Default is 0.5.
- outerRadius — Default is 1.
- thetaSegments — Number of segments. A higher number means the ring will be more round. Minimum is 3. Default is 32.
- phiSegments — Minimum is 1. Default is 1.
- thetaStart — Starting angle. Default is 0.
- thetaLength — Central angle. Default is Math.PI * 2. + innerRadius — Default is 0.5.
+ outerRadius — Default is 1.
+ thetaSegments — Number of segments. A higher number means the ring will be + more round. Minimum is 3. Default is 32.
+ phiSegments — Minimum is 1. Default is 1.
+ thetaStart — Starting angle. Default is 0.
+ thetaLength — Central angle. Default is Math.PI * 2.

-

Properties

See the base [page:BufferGeometry] class for common properties.

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/ShapeGeometry.html b/docs/api/en/geometries/ShapeGeometry.html index 39e8ee98905a01..1d3170354003f2 100644 --- a/docs/api/en/geometries/ShapeGeometry.html +++ b/docs/api/en/geometries/ShapeGeometry.html @@ -11,9 +11,14 @@

[name]

-

Creates an one-sided polygonal geometry from one or more path shapes.

+

+ Creates an one-sided polygonal geometry from one or more path shapes. +

- + -

Code Example

- const x = 0, y = 0; @@ -56,11 +59,12 @@

Code Example

Constructor

-

[name]([param:Array shapes], [param:Integer curveSegments])

- shapes — [page:Array] of shapes or a single [page:Shape shape]. Default is a single triangle shape.
- curveSegments - [page:Integer] - Number of segments per shape. Default is 12. + shapes — [page:Array] of shapes or a single [page:Shape shape]. Default is + a single triangle shape.
+ curveSegments - [page:Integer] - Number of segments per shape. Default is + 12.

Properties

@@ -68,7 +72,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/SphereGeometry.html b/docs/api/en/geometries/SphereGeometry.html index ffcb555b56728b..91b904d89d7b87 100644 --- a/docs/api/en/geometries/SphereGeometry.html +++ b/docs/api/en/geometries/SphereGeometry.html @@ -13,7 +13,10 @@

[name]

A class for generating sphere geometries.

- + -

Code Example

- const geometry = new THREE.SphereGeometry( 15, 32, 16 ); - const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); - const sphere = new THREE.Mesh( geometry, material ); - scene.add( sphere ); + +const geometry = new THREE.SphereGeometry( 15, 32, 16 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const sphere = new THREE.Mesh( geometry, material ); scene.add( sphere );

Constructor

-

[name]([param:Float radius], [param:Integer widthSegments], [param:Integer heightSegments], [param:Float phiStart], [param:Float phiLength], [param:Float thetaStart], [param:Float thetaLength])

+

+ [name]([param:Float radius], [param:Integer widthSegments], [param:Integer heightSegments], [param:Float phiStart], [param:Float phiLength], + [param:Float thetaStart], [param:Float thetaLength]) +

- radius — sphere radius. Default is 1.
- widthSegments — number of horizontal segments. Minimum value is 3, and the default is 32.
- heightSegments — number of vertical segments. Minimum value is 2, and the default is 16.
- phiStart — specify horizontal starting angle. Default is 0.
- phiLength — specify horizontal sweep angle size. Default is Math.PI * 2.
- thetaStart — specify vertical starting angle. Default is 0.
- thetaLength — specify vertical sweep angle size. Default is Math.PI.
+ radius — sphere radius. Default is 1.
+ widthSegments — number of horizontal segments. Minimum value is 3, and the + default is 32.
+ heightSegments — number of vertical segments. Minimum value is 2, and the + default is 16.
+ phiStart — specify horizontal starting angle. Default is 0.
+ phiLength — specify horizontal sweep angle size. Default is Math.PI * + 2.
+ thetaStart — specify vertical starting angle. Default is 0.
+ thetaLength — specify vertical sweep angle size. Default is Math.PI.

- The geometry is created by sweeping and calculating vertexes around the Y axis (horizontal sweep) and the Z axis (vertical sweep). Thus, incomplete spheres (akin to `'sphere slices'`) can be created through the use of different values of phiStart, phiLength, thetaStart and thetaLength, in order to define the points in which we start (or end) calculating those vertices. + The geometry is created by sweeping and calculating vertexes around the Y + axis (horizontal sweep) and the Z axis (vertical sweep). Thus, incomplete + spheres (akin to `'sphere slices'`) can be created through the use of + different values of phiStart, phiLength, thetaStart and thetaLength, in + order to define the points in which we start (or end) calculating those + vertices.

Properties

@@ -62,7 +75,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/TetrahedronGeometry.html b/docs/api/en/geometries/TetrahedronGeometry.html index fbf54d41dfd9f0..ccbd9f09ebc5d2 100644 --- a/docs/api/en/geometries/TetrahedronGeometry.html +++ b/docs/api/en/geometries/TetrahedronGeometry.html @@ -13,7 +13,10 @@

[name]

A class for generating a tetrahedron geometries.

- + -

Constructor

[name]([param:Float radius], [param:Integer detail])

- radius — Radius of the tetrahedron. Default is 1.
- detail — Default is 0. Setting this to a value greater than 0 adds vertices making it no longer a tetrahedron. + radius — Radius of the tetrahedron. Default is 1.
+ detail — Default is 0. Setting this to a value greater than 0 adds + vertices making it no longer a tetrahedron.

Properties

@@ -44,7 +47,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/TorusGeometry.html b/docs/api/en/geometries/TorusGeometry.html index 3d30968e7eb299..709f39520bded9 100644 --- a/docs/api/en/geometries/TorusGeometry.html +++ b/docs/api/en/geometries/TorusGeometry.html @@ -13,7 +13,10 @@

[name]

A class for generating torus geometries.

- + -

Code Example

- const geometry = new THREE.TorusGeometry( 10, 3, 16, 100 ); - const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); - const torus = new THREE.Mesh( geometry, material ); - scene.add( torus ); + +const geometry = new THREE.TorusGeometry( 10, 3, 16, 100 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const torus = new THREE.Mesh( geometry, material ); scene.add( torus );

Constructor

-

[name]([param:Float radius], [param:Float tube], [param:Integer radialSegments], [param:Integer tubularSegments], [param:Float arc])

+

+ [name]([param:Float radius], [param:Float tube], [param:Integer radialSegments], [param:Integer tubularSegments], [param:Float arc]) +

- radius - Radius of the torus, from the center of the torus to the center of the tube. Default is 1.
- tube — Radius of the tube. Default is 0.4.
- radialSegments — Default is 12
- tubularSegments — Default is 48.
- arc — Central angle. Default is Math.PI * 2. + radius - Radius of the torus, from the center of the torus to the center + of the tube. Default is 1.
+ tube — Radius of the tube. Default is 0.4.
+ radialSegments — Default is 12
+ tubularSegments — Default is 48.
+ arc — Central angle. Default is Math.PI * 2.

Properties

@@ -55,7 +60,8 @@

Properties

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/TorusKnotGeometry.html b/docs/api/en/geometries/TorusKnotGeometry.html index 8c4804bc9016df..48f342ce407d68 100644 --- a/docs/api/en/geometries/TorusKnotGeometry.html +++ b/docs/api/en/geometries/TorusKnotGeometry.html @@ -11,9 +11,16 @@

[name]

-

Creates a torus knot, the particular shape of which is defined by a pair of coprime integers, p and q. If p and q are not coprime, the result will be a torus link.

+

+ Creates a torus knot, the particular shape of which is defined by a pair + of coprime integers, p and q. If p and q are not coprime, the result will + be a torus link. +

- + -

Code Example

- const geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 ); - const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); - const torusKnot = new THREE.Mesh( geometry, material ); - scene.add( torusKnot ); + +const geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 ); +const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); +const torusKnot = new THREE.Mesh( geometry, material ); scene.add( torusKnot );

Constructor

-

[name]([param:Float radius], [param:Float tube], [param:Integer tubularSegments], [param:Integer radialSegments], [param:Integer p], [param:Integer q])

-

-

    -
  • radius - Radius of the torus. Default is 1.
  • -
  • tube — Radius of the tube. Default is 0.4.
  • -
  • tubularSegments — Default is 64.
  • -
  • radialSegments — Default is 8.
  • -
  • p — This value determines, how many times the geometry winds around its axis of rotational symmetry. Default is 2.
  • -
  • q — This value determines, how many times the geometry winds around a circle in the interior of the torus. Default is 3.
  • -
-

+

+ [name]([param:Float radius], [param:Float tube], [param:Integer tubularSegments], [param:Integer radialSegments], [param:Integer p], + [param:Integer q]) +

+
    +
  • radius - Radius of the torus. Default is 1.
  • +
  • tube — Radius of the tube. Default is 0.4.
  • +
  • tubularSegments — Default is 64.
  • +
  • radialSegments — Default is 8.
  • +
  • + p — This value determines, how many times the geometry winds around its + axis of rotational symmetry. Default is 2. +
  • +
  • + q — This value determines, how many times the geometry winds around a + circle in the interior of the torus. Default is 3. +
  • +

Properties

See the base [page:BufferGeometry] class for common properties.

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

Methods

diff --git a/docs/api/en/geometries/TubeGeometry.html b/docs/api/en/geometries/TubeGeometry.html index 4e2e5051f36cb6..388c863b567dcd 100644 --- a/docs/api/en/geometries/TubeGeometry.html +++ b/docs/api/en/geometries/TubeGeometry.html @@ -37,11 +37,8 @@

Code Example

class CustomSinCurve extends THREE.Curve { constructor( scale = 1 ) { - super(); - this.scale = scale; - } getPoint( t, optionalTarget = new THREE.Vector3() ) { @@ -51,9 +48,7 @@

Code Example

const tz = 0; return optionalTarget.set( tx, ty, tz ).multiplyScalar( this.scale ); - } - } const path = new CustomSinCurve( 10 ); @@ -65,39 +60,37 @@

Code Example

Constructor

- -

[name]([param:Curve path], [param:Integer tubularSegments], [param:Float radius], [param:Integer radialSegments], [param:Boolean closed])

+

+ [name]([param:Curve path], [param:Integer tubularSegments], [param:Float radius], [param:Integer radialSegments], [param:Boolean closed]) +

- path — [page:Curve] - A 3D path that inherits from the [page:Curve] base class. Default is a quadratic bezier curve.
- tubularSegments — [page:Integer] - The number of segments that make up the tube. Default is `64`.
- radius — [page:Float] - The radius of the tube. Default is `1`.
- radialSegments — [page:Integer] - The number of segments that make up the cross-section. Default is `8`.
- closed — [page:Boolean] Is the tube open or closed. Default is `false`.
+ path — [page:Curve] - A 3D path that inherits from the [page:Curve] base + class. Default is a quadratic bezier curve.
+ tubularSegments — [page:Integer] - The number of segments that make up the + tube. Default is `64`.
+ radius — [page:Float] - The radius of the tube. Default is `1`.
+ radialSegments — [page:Integer] - The number of segments that make up the + cross-section. Default is `8`.
+ closed — [page:Boolean] Is the tube open or closed. Default is `false`.

-

Properties

See the base [page:BufferGeometry] class for common properties.

[property:Object parameters]

- An object with a property for each of the constructor parameters. Any modification after instantiation does not change the geometry. + An object with a property for each of the constructor parameters. Any + modification after instantiation does not change the geometry.

[property:Array tangents]

-

- An array of [page:Vector3] tangents -

+

An array of [page:Vector3] tangents

[property:Array normals]

-

- An array of [page:Vector3] normals -

+

An array of [page:Vector3] normals

[property:Array binormals]

-

- An array of [page:Vector3] binormals -

+

An array of [page:Vector3] binormals

Methods

See the base [page:BufferGeometry] class for common methods.

diff --git a/docs/api/en/geometries/WireframeGeometry.html b/docs/api/en/geometries/WireframeGeometry.html index c07e50de62f659..dbc243e5cf8d9d 100644 --- a/docs/api/en/geometries/WireframeGeometry.html +++ b/docs/api/en/geometries/WireframeGeometry.html @@ -11,7 +11,9 @@

[name]

-

This can be used as a helper object to view a [page:BufferGeometry geometry] as a wireframe.

+

+ This can be used as a helper object to view a [page:BufferGeometry geometry] as a wireframe. +

Code Example

@@ -30,16 +32,12 @@

Code Example

Examples

-

- [example:webgl_helpers helpers] -

+

[example:webgl_helpers helpers]

Constructor

[name]( [param:BufferGeometry geometry] )

-

- geometry — any geometry object. -

+

geometry — any geometry object.

Properties

See the base [page:BufferGeometry] class for common properties.

diff --git a/docs/api/en/helpers/ArrowHelper.html b/docs/api/en/helpers/ArrowHelper.html index c4456435c9ba75..da0baf740e4d3a 100644 --- a/docs/api/en/helpers/ArrowHelper.html +++ b/docs/api/en/helpers/ArrowHelper.html @@ -31,20 +31,24 @@

Code Example

Examples

-

- [example:webgl_shadowmesh WebGL / shadowmesh] -

+

[example:webgl_shadowmesh WebGL / shadowmesh]

Constructor

-

[name]([param:Vector3 dir], [param:Vector3 origin], [param:Number length], [param:Number hex], [param:Number headLength], [param:Number headWidth] )

+

+ [name]([param:Vector3 dir], [param:Vector3 origin], [param:Number length], + [param:Number hex], [param:Number headLength], [param:Number headWidth] ) +

- [page:Vector3 dir] -- direction from origin. Must be a unit vector.
- [page:Vector3 origin] -- Point at which the arrow starts.
- [page:Number length] -- length of the arrow. Default is `1`.
- [page:Number hex] -- hexadecimal value to define color. Default is 0xffff00.
- [page:Number headLength] -- The length of the head of the arrow. Default is 0.2 * length.
- [page:Number headWidth] -- The width of the head of the arrow. Default is 0.2 * headLength.
+ [page:Vector3 dir] -- direction from origin. Must be a unit vector.
+ [page:Vector3 origin] -- Point at which the arrow starts.
+ [page:Number length] -- length of the arrow. Default is `1`.
+ [page:Number hex] -- hexadecimal value to define color. Default is + 0xffff00.
+ [page:Number headLength] -- The length of the head of the arrow. Default + is 0.2 * length.
+ [page:Number headWidth] -- The width of the head of the arrow. Default is + 0.2 * headLength.

Properties

@@ -61,30 +65,33 @@

Methods

[method:undefined setColor]([param:Color color])

- color -- The desired color.

+ color -- The desired color.

- Sets the color of the arrowHelper. + Sets the color of the arrowHelper.

-

[method:undefined setLength]([param:Number length], [param:Number headLength], [param:Number headWidth])

+

+ [method:undefined setLength]([param:Number length], [param:Number headLength], [param:Number headWidth]) +

- length -- The desired length.
- headLength -- The length of the head of the arrow.
- headWidth -- The width of the head of the arrow.

+ length -- The desired length.
+ headLength -- The length of the head of the arrow.
+ headWidth -- The width of the head of the arrow.

- Sets the length of the arrowhelper. + Sets the length of the arrowhelper.

[method:undefined setDirection]([param:Vector3 dir])

- dir -- The desired direction. Must be a unit vector.

+ dir -- The desired direction. Must be a unit vector.

- Sets the direction of the arrowhelper. + Sets the direction of the arrowhelper.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

diff --git a/docs/api/en/helpers/AxesHelper.html b/docs/api/en/helpers/AxesHelper.html index befb1a6ce0c9fc..8ac7f105486643 100644 --- a/docs/api/en/helpers/AxesHelper.html +++ b/docs/api/en/helpers/AxesHelper.html @@ -10,32 +10,29 @@ [page:Object3D] → [page:Line] → [page:LineSegments] →

[name]

- -

An axis object to visualize the 3 axes in a simple way.
+

+ An axis object to visualize the 3 axes in a simple way.
The X axis is red. The Y axis is green. The Z axis is blue.

Code Example

- const axesHelper = new THREE.AxesHelper( 5 ); scene.add( axesHelper );

Examples

-

- [example:webgl_buffergeometry_compression WebGL / buffergeometry / compression]
- [example:webgl_geometry_convex WebGL / geometry / convex]
+ [example:webgl_buffergeometry_compression WebGL / buffergeometry / compression]
+ [example:webgl_geometry_convex WebGL / geometry / convex]
[example:webgl_loader_nrrd WebGL / loader / nrrd]

Constructor

- -

[name]( [param:Number size] )

- [page:Number size] -- (optional) size of the lines representing the axes. Default is `1`. + [page:Number size] -- (optional) size of the lines representing the axes. + Default is `1`.

Properties

@@ -44,18 +41,21 @@

Properties

Methods

See the base [page:LineSegments] class for common methods.

-

[method:this setColors]( [param:Color xAxisColor], [param:Color yAxisColor], [param:Color zAxisColor] )

+

+ [method:this setColors]( [param:Color xAxisColor], [param:Color yAxisColor], [param:Color zAxisColor] ) +

- Sets the axes colors to [page:Color xAxisColor], [page:Color yAxisColor], [page:Color zAxisColor]. + Sets the axes colors to [page:Color xAxisColor], [page:Color yAxisColor], + [page:Color zAxisColor].

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/helpers/Box3Helper.html b/docs/api/en/helpers/Box3Helper.html index 38fcaf46048cc0..04d7a210d3de01 100644 --- a/docs/api/en/helpers/Box3Helper.html +++ b/docs/api/en/helpers/Box3Helper.html @@ -11,10 +11,7 @@

[name]

-

- Helper object to visualize a [page:Box3]. -

- +

Helper object to visualize a [page:Box3].

Code Example

@@ -26,16 +23,14 @@

Code Example

scene.add( helper );
-

Constructor

-

[name]( [param:Box3 box], [param:Color color] )

- [page:Box3 box] -- the Box3 to show.
- [page:Color color] -- (optional) the box's color. Default is 0xffff00.

+ [page:Box3 box] -- the Box3 to show.
+ [page:Color color] -- (optional) the box's color. Default is 0xffff00.

- Creates a new wireframe box that represents the passed Box3. + Creates a new wireframe box that represents the passed Box3.

Properties

@@ -44,25 +39,22 @@

Properties

[property:Box3 box]

The Box3 being visualized.

-

Methods

See the base [page:LineSegments] class for common methods.

-

[method:undefined updateMatrixWorld]( [param:Boolean force] )

This overrides the method in the base [page:Object3D] class so that it - also updates the wireframe box to the extent of the [page:Box3Helper.box .box] - property. + also updates the wireframe box to the extent of the [page:Box3Helper.box .box] property.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/helpers/BoxHelper.html b/docs/api/en/helpers/BoxHelper.html index dd860844beacfa..a67399be65c36f 100644 --- a/docs/api/en/helpers/BoxHelper.html +++ b/docs/api/en/helpers/BoxHelper.html @@ -12,10 +12,12 @@

[name]

- Helper object to graphically show the world-axis-aligned bounding box around an object. The actual bounding box is handled with [page:Box3], this is just a visual helper for debugging. - It can be automatically resized with the [page:BoxHelper.update] method when the object it's created from is transformed. - Note that the object must have a [page:BufferGeometry] for this to work, - so it won't work with [page:Sprite Sprites]. + Helper object to graphically show the world-axis-aligned bounding box + around an object. The actual bounding box is handled with [page:Box3], + this is just a visual helper for debugging. It can be automatically + resized with the [page:BoxHelper.update] method when the object it's + created from is transformed. Note that the object must have a + [page:BufferGeometry] for this to work, so it won't work with [page:Sprite Sprites].

Code Example

@@ -28,36 +30,35 @@

Code Example

Examples

-

- [example:webgl_helpers WebGL / helpers]
- [example:webgl_loader_nrrd WebGL / loader / nrrd]
+ [example:webgl_helpers WebGL / helpers]
+ [example:webgl_loader_nrrd WebGL / loader / nrrd]
[example:webgl_buffergeometry_drawrange WebGL / buffergeometry / drawrange]

Constructor

- -

[name]( [param:Object3D object], [param:Color color] )

- [page:Object3D object] -- (optional) the object3D to show the world-axis-aligned boundingbox.
- [page:Color color] -- (optional) hexadecimal value that defines the box's color. Default is 0xffff00.

- - Creates a new wireframe box that bounds the passed object. Internally this uses [page:Box3.setFromObject] - to calculate the dimensions. Note that this includes any children. + [page:Object3D object] -- (optional) the object3D to show the + world-axis-aligned boundingbox.
+ [page:Color color] -- (optional) hexadecimal value that defines the box's + color. Default is 0xffff00.

+ + Creates a new wireframe box that bounds the passed object. Internally this + uses [page:Box3.setFromObject] to calculate the dimensions. Note that this + includes any children.

Properties

See the base [page:LineSegments] class for common properties.

-

Methods

See the base [page:LineSegments] class for common methods.

[method:undefined update]()

- Updates the helper's geometry to match the dimensions - of the object, including any children. See [page:Box3.setFromObject]. + Updates the helper's geometry to match the dimensions of the object, + including any children. See [page:Box3.setFromObject].

[method:this setFromObject]( [param:Object3D object] )

@@ -69,11 +70,11 @@

[method:this setFromObject]( [param:Object3D object] )

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/helpers/CameraHelper.html b/docs/api/en/helpers/CameraHelper.html index 27953560b4ab3d..b88f1f6a329090 100644 --- a/docs/api/en/helpers/CameraHelper.html +++ b/docs/api/en/helpers/CameraHelper.html @@ -12,8 +12,9 @@

[name]

- This helps with visualizing what a camera contains in its frustum. It visualizes the frustum of a camera using a [page:LineSegments].

- [name] must be a child of the scene. + This helps with visualizing what a camera contains in its frustum. It + visualizes the frustum of a camera using a [page:LineSegments].

+ [name] must be a child of the scene.

Code Example

@@ -25,17 +26,16 @@

Code Example

Examples

- [example:webgl_camera WebGL / camera]
+ [example:webgl_camera WebGL / camera]
[example:webgl_geometry_extrude_splines WebGL / extrude / splines]

Constructor

-

[name]( [param:Camera camera] )

- [page:Camera camera] -- The camera to visualize.

+ [page:Camera camera] -- The camera to visualize.

- This create a new [Name] for the specified camera. + This create a new [Name] for the specified camera.

Properties

@@ -52,8 +52,8 @@

[property:Object matrix]

[property:Object matrixAutoUpdate]

- See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is using the - camera's [page:Object3D.matrixWorld matrixWorld]. + See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is + using the camera's [page:Object3D.matrixWorld matrixWorld].

Methods

@@ -61,13 +61,14 @@

Methods

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

-

[method:this setColors]( [param:Color frustum], [param:Color cone], [param:Color up], [param:Color target], [param:Color cross] )

-

- Defines the colors of the helper. -

+

+ [method:this setColors]( [param:Color frustum], [param:Color cone], [param:Color up], [param:Color target], [param:Color cross] ) +

+

Defines the colors of the helper.

[method:undefined update]()

Updates the helper based on the projectionMatrix of the camera.

diff --git a/docs/api/en/helpers/DirectionalLightHelper.html b/docs/api/en/helpers/DirectionalLightHelper.html index ba90af7d3ee0bc..29d79f95f19314 100644 --- a/docs/api/en/helpers/DirectionalLightHelper.html +++ b/docs/api/en/helpers/DirectionalLightHelper.html @@ -12,9 +12,9 @@

[name]

- Helper object to assist with visualizing a [page:DirectionalLight]'s effect on the scene. - - This consists of plane and a line representing the light's position and direction. + Helper object to assist with visualizing a [page:DirectionalLight]'s + effect on the scene. This consists of plane and a line representing the + light's position and direction.

Code Example

@@ -27,54 +27,60 @@

Code Example

Constructor

- -

[name]( [param:DirectionalLight light], [param:Number size], [param:Hex color] )

+

+ [name]( [param:DirectionalLight light], [param:Number size], [param:Hex color] ) +

[page:DirectionalLight light]-- The light to be visualized.

- [page:Number size] -- (optional) dimensions of the plane. Default is `1`.

+ [page:Number size] -- (optional) dimensions of the plane. Default is + `1`.

- [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. + [page:Hex color] -- (optional) if this is not the set the helper will take + the color of the light.

-

Properties

See the base [page:Object3D] class for common properties.

-

[property:Line lightPlane]

Contains the line mesh showing the location of the directional light.

[property:DirectionalLight light]

-

Reference to the [page:DirectionalLight directionalLight] being visualized.

+

+ Reference to the [page:DirectionalLight directionalLight] being + visualized. +

[property:Object matrix]

Reference to the light's [page:Object3D.matrixWorld matrixWorld].

[property:Object matrixAutoUpdate]

- See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is using the - light's [page:Object3D.matrixWorld matrixWorld]. + See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is + using the light's [page:Object3D.matrixWorld matrixWorld].

[property:hex color]

- The color parameter passed in the constructor. Default is `undefined`. If this is changed, - the helper's color will update the next time [page:.update update] is called. + The color parameter passed in the constructor. Default is `undefined`. If + this is changed, the helper's color will update the next time + [page:.update update] is called.

-

Methods

See the base [page:Object3D] class for common properties.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

-

[method:undefined update]()

-

Updates the helper to match the position and direction of the [page:.light directionalLight] being visualized.

+

+ Updates the helper to match the position and direction of the [page:.light directionalLight] being visualized. +

Source

diff --git a/docs/api/en/helpers/GridHelper.html b/docs/api/en/helpers/GridHelper.html index aac2bbe69cdd70..956101ebb1beeb 100644 --- a/docs/api/en/helpers/GridHelper.html +++ b/docs/api/en/helpers/GridHelper.html @@ -11,11 +11,15 @@

[name]

-

The GridHelper is an object to define grids. Grids are two-dimensional arrays of lines.

+

+ The GridHelper is an object to define grids. Grids are two-dimensional + arrays of lines. +

Code Example

- const size = 10; + + const size = 10; const divisions = 10; const gridHelper = new THREE.GridHelper( size, divisions ); @@ -24,21 +28,27 @@

Code Example

Examples

-

- [example:webgl_helpers WebGL / helpers] -

+

[example:webgl_helpers WebGL / helpers]

Constructor

-

[name]( [param:number size], [param:Number divisions], [param:Color colorCenterLine], [param:Color colorGrid] )

+

+ [name]( [param:number size], [param:Number divisions], [param:Color colorCenterLine], [param:Color colorGrid] ) +

- size -- The size of the grid. Default is 10.
- divisions -- The number of divisions across the grid. Default is 10.
- colorCenterLine -- The color of the centerline. This can be a [page:Color], a hexadecimal value and an CSS-Color name. Default is 0x444444
- colorGrid -- The color of the lines of the grid. This can be a [page:Color], a hexadecimal value and an CSS-Color name. Default is 0x888888 + size -- The size of the grid. Default is 10.
+ divisions -- The number of divisions across the grid. Default is 10. +
+ colorCenterLine -- The color of the centerline. This can be a + [page:Color], a hexadecimal value and an CSS-Color name. Default is + 0x444444
+ colorGrid -- The color of the lines of the grid. This can be a + [page:Color], a hexadecimal value and an CSS-Color name. Default is + 0x888888

- Creates a new [name] of size 'size' and divided into 'divisions' segments per side. Colors are optional. + Creates a new [name] of size 'size' and divided into 'divisions' segments + per side. Colors are optional.

Methods

@@ -46,7 +56,8 @@

Methods

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

diff --git a/docs/api/en/helpers/HemisphereLightHelper.html b/docs/api/en/helpers/HemisphereLightHelper.html index e24cbc09e7969d..9145dc83270005 100644 --- a/docs/api/en/helpers/HemisphereLightHelper.html +++ b/docs/api/en/helpers/HemisphereLightHelper.html @@ -12,7 +12,8 @@

[name]

- Creates a visual aid consisting of a spherical [page:Mesh] for a [page:HemisphereLight HemisphereLight]. + Creates a visual aid consisting of a spherical [page:Mesh] for a + [page:HemisphereLight HemisphereLight].

Code Example

@@ -23,19 +24,21 @@

Code Example

scene.add( helper );
-

Constructor

-

[name]( [param:HemisphereLight light], [param:Number sphereSize], [param:Hex color] )

+

+ [name]( [param:HemisphereLight light], [param:Number sphereSize], + [param:Hex color] ) +

[page:HemisphereLight light] -- The light being visualized.

[page:Number size] -- The size of the mesh used to visualize the light.

- [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. + [page:Hex color] -- (optional) if this is not the set the helper will take + the color of the light.

-

Properties

See the base [page:Object3D] class for common properties.

@@ -43,32 +46,37 @@

[property:HemisphereLight light]

Reference to the HemisphereLight being visualized.

[property:Object matrix]

-

Reference to the hemisphereLight's [page:Object3D.matrixWorld matrixWorld].

+

+ Reference to the hemisphereLight's [page:Object3D.matrixWorld matrixWorld]. +

[property:Object matrixAutoUpdate]

- See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is using the - hemisphereLight's [page:Object3D.matrixWorld matrixWorld]. + See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is + using the hemisphereLight's [page:Object3D.matrixWorld matrixWorld].

[property:hex color]

- The color parameter passed in the constructor. Default is `undefined`. If this is changed, the helper's color will update - the next time [page:.update update] is called. + The color parameter passed in the constructor. Default is `undefined`. If + this is changed, the helper's color will update the next time + [page:.update update] is called.

-

Methods

See the base [page:Object3D] class for common methods.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

[method:undefined update]()

-

Updates the helper to match the position and direction of the [page:.light].

- +

+ Updates the helper to match the position and direction of the + [page:.light]. +

Source

diff --git a/docs/api/en/helpers/PlaneHelper.html b/docs/api/en/helpers/PlaneHelper.html index 4a0b00551e1928..e0f143ab9fac5b 100644 --- a/docs/api/en/helpers/PlaneHelper.html +++ b/docs/api/en/helpers/PlaneHelper.html @@ -11,10 +11,7 @@

[name]

-

- Helper object to visualize a [page:Plane]. -

- +

Helper object to visualize a [page:Plane].

Code Example

@@ -24,17 +21,19 @@

Code Example

scene.add( helper );
-

Constructor

- -

[name]( [param:Plane plane], [param:Float size], [param:Color hex] )

+

+ [name]( [param:Plane plane], [param:Float size], [param:Color hex] ) +

- [page:Plane plane] -- the plane to visualize.
- [page:Float size] -- (optional) side length of plane helper. Default is 1.
- [page:Color color] -- (optional) the color of the helper. Default is 0xffff00.

+ [page:Plane plane] -- the plane to visualize.
+ [page:Float size] -- (optional) side length of plane helper. Default is + 1.
+ [page:Color color] -- (optional) the color of the helper. Default is + 0xffff00.

- Creates a new wireframe representation of the passed plane. + Creates a new wireframe representation of the passed plane.

Properties

@@ -46,20 +45,19 @@

[property:Plane plane]

[property:Float size]

The side lengths of plane helper.

-

Methods

See the base [page:LineSegments] class for common methods.

[method:undefined updateMatrixWorld]( [param:Boolean force] )

- This overrides the method in the base [page:Object3D] class so that it also - updates the helper object according to the [page:PlaneHelper.plane .plane] and - [page:PlaneHelper.size .size] properties. + This overrides the method in the base [page:Object3D] class so that it + also updates the helper object according to the [page:PlaneHelper.plane .plane] and [page:PlaneHelper.size .size] properties.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

diff --git a/docs/api/en/helpers/PointLightHelper.html b/docs/api/en/helpers/PointLightHelper.html index add4a5e3d65494..367d8d963318cd 100644 --- a/docs/api/en/helpers/PointLightHelper.html +++ b/docs/api/en/helpers/PointLightHelper.html @@ -12,11 +12,11 @@

[name]

- This displays a helper object consisting of a spherical [page:Mesh] for visualizing - a [page:PointLight]. -

+ This displays a helper object consisting of a spherical [page:Mesh] for + visualizing a [page:PointLight]. +

-

Code Example

+

Code Example

const pointLight = new THREE.PointLight( 0xff0000, 1, 100 ); @@ -30,19 +30,21 @@

Code Example

Examples

-

- [example:webgl_helpers WebGL / helpers] -

+

[example:webgl_helpers WebGL / helpers]

Constructor

-

[name]( [param:PointLight light], [param:Float sphereSize], [param:Hex color] )

+

+ [name]( [param:PointLight light], [param:Float sphereSize], [param:Hex color] ) +

- [page:PointLight light] -- The light to be visualized.

+ [page:PointLight light] -- The light to be visualized.

- [page:Float sphereSize] -- (optional) The size of the sphere helper. Default is `1`.

+ [page:Float sphereSize] -- (optional) The size of the sphere helper. + Default is `1`.

- [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. + [page:Hex color] -- (optional) if this is not the set the helper will take + the color of the light.

Properties

@@ -52,18 +54,21 @@

[property:PointLight light]

The [page:PointLight] that is being visualized.

[property:Object matrix]

-

Reference to the pointLight's [page:Object3D.matrixWorld matrixWorld].

+

+ Reference to the pointLight's [page:Object3D.matrixWorld matrixWorld]. +

[property:Object matrixAutoUpdate]

- See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is using the - pointLight's [page:Object3D.matrixWorld matrixWorld]. + See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is + using the pointLight's [page:Object3D.matrixWorld matrixWorld].

[property:hex color]

- The color parameter passed in the constructor. Default is `undefined`. If this is changed, the helper's color will update - the next time [page:.update update] is called. + The color parameter passed in the constructor. Default is `undefined`. If + this is changed, the helper's color will update the next time + [page:.update update] is called.

Methods

@@ -71,10 +76,10 @@

Methods

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

-

[method:undefined update]()

Updates the helper to match the position of the [page:.light].

diff --git a/docs/api/en/helpers/PolarGridHelper.html b/docs/api/en/helpers/PolarGridHelper.html index 7c1959eb69ce7f..e365305bd03167 100644 --- a/docs/api/en/helpers/PolarGridHelper.html +++ b/docs/api/en/helpers/PolarGridHelper.html @@ -11,7 +11,10 @@

[name]

-

The PolarGridHelper is an object to define polar grids. Grids are two-dimensional arrays of lines.

+

+ The PolarGridHelper is an object to define polar grids. Grids are + two-dimensional arrays of lines. +

Code Example

@@ -27,23 +30,33 @@

Code Example

Examples

-

- [example:webgl_helpers WebGL / helpers] -

+

[example:webgl_helpers WebGL / helpers]

Constructor

-

[name]( [param:Number radius], [param:Number sectors], [param:Number rings], [param:Number divisions], [param:Color color1], [param:Color color2] )

+

+ [name]( [param:Number radius], [param:Number sectors], [param:Number rings], [param:Number divisions], [param:Color color1], [param:Color color2] ) +

- radius -- The radius of the polar grid. This can be any positive number. Default is 10.
- sectors -- The number of sectors the grid will be divided into. This can be any positive integer. Default is 16.
- rings -- The number of rings. This can be any positive integer. Default is 8.
- divisions -- The number of line segments used for each circle. This can be any positive integer that is 3 or greater. Default is 64.
- color1 -- The first color used for grid elements. This can be a [page:Color], a hexadecimal value and an CSS-Color name. Default is 0x444444
- color2 -- The second color used for grid elements. This can be a [page:Color], a hexadecimal value and an CSS-Color name. Default is 0x888888 + radius -- The radius of the polar grid. This can be any positive number. + Default is 10.
+ sectors -- The number of sectors the grid will be divided into. This can + be any positive integer. Default is 16.
+ rings -- The number of rings. This can be any positive integer. Default is + 8.
+ divisions -- The number of line segments used for each circle. This can be + any positive integer that is 3 or greater. Default is 64.
+ color1 -- The first color used for grid elements. This can be a + [page:Color], a hexadecimal value and an CSS-Color name. Default is + 0x444444
+ color2 -- The second color used for grid elements. This can be a + [page:Color], a hexadecimal value and an CSS-Color name. Default is + 0x888888

- Creates a new [name] of radius 'radius' with 'sectors' number of sectors and 'rings' number of rings, where each circle is smoothed into 'divisions' number of line segments. Colors are optional. + Creates a new [name] of radius 'radius' with 'sectors' number of sectors + and 'rings' number of rings, where each circle is smoothed into + 'divisions' number of line segments. Colors are optional.

Methods

@@ -51,7 +64,8 @@

Methods

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

diff --git a/docs/api/en/helpers/SkeletonHelper.html b/docs/api/en/helpers/SkeletonHelper.html index d8d119383a538d..714f404c351af5 100644 --- a/docs/api/en/helpers/SkeletonHelper.html +++ b/docs/api/en/helpers/SkeletonHelper.html @@ -12,8 +12,8 @@

[name]

- A helper object to assist with visualizing a [page:Skeleton Skeleton]. - The helper is rendered using a [page:LineBasicMaterial LineBasicMaterial]. + A helper object to assist with visualizing a [page:Skeleton Skeleton]. The + helper is rendered using a [page:LineBasicMaterial LineBasicMaterial].

Code Example

@@ -33,36 +33,30 @@

Examples

Constructor

-

[name]( [param:Object3D object] )

- object -- Usually an instance of [page:SkinnedMesh]. However, any instance of [page:Object3D] can be used if it represents - a hierarchy of [page:Bone Bone]s (via [page:Object3D.children]). + object -- Usually an instance of [page:SkinnedMesh]. However, any instance + of [page:Object3D] can be used if it represents a hierarchy of [page:Bone Bone]s (via [page:Object3D.children]).

Properties

[property:Array bones]

-

- The list of bones that the helper renders as [page:Line Lines]. -

+

The list of bones that the helper renders as [page:Line Lines].

[property:Boolean isSkeletonHelper]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Object3D root]

-

- The object passed in the constructor. -

+

The object passed in the constructor.

Methods

See the base [page:LineSegments] class for common methods.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

Source

diff --git a/docs/api/en/helpers/SpotLightHelper.html b/docs/api/en/helpers/SpotLightHelper.html index 91538424e26a4a..3da6593b9166e3 100644 --- a/docs/api/en/helpers/SpotLightHelper.html +++ b/docs/api/en/helpers/SpotLightHelper.html @@ -11,7 +11,9 @@

[name]

-

This displays a cone shaped helper object for a [page:SpotLight].

+

+ This displays a cone shaped helper object for a [page:SpotLight]. +

Code Example

@@ -24,20 +26,19 @@

Code Example

Examples

-

- [example:webgl_lights_spotlights WebGL/ lights / spotlights ] -

+

[example:webgl_lights_spotlights WebGL/ lights / spotlights ]

Constructor

[name]( [param:SpotLight light], [param:Hex color] )

- [page:SpotLight light] -- The [page:SpotLight] to be visualized.

+ [page:SpotLight light] -- The [page:SpotLight] to be visualized. +

- [page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. + [page:Hex color] -- (optional) if this is not the set the helper will take + the color of the light.

-

Properties

See the base [page:Object3D] class for common properties.

@@ -52,14 +53,15 @@

[property:Object matrix]

[property:Object matrixAutoUpdate]

- See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is using the - spotLight's [page:Object3D.matrixWorld matrixWorld]. + See [page:Object3D.matrixAutoUpdate]. Set to `false` here as the helper is + using the spotLight's [page:Object3D.matrixWorld matrixWorld].

[property:hex color]

- The color parameter passed in the constructor. Default is `undefined`. If this is changed, the helper's color will update - the next time [page:.update update] is called. + The color parameter passed in the constructor. Default is `undefined`. If + this is changed, the helper's color will update the next time + [page:.update update] is called.

Methods

@@ -67,7 +69,8 @@

Methods

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

[method:undefined update]()

diff --git a/docs/api/en/lights/AmbientLight.html b/docs/api/en/lights/AmbientLight.html index db210f505f034e..70f903368ea92c 100644 --- a/docs/api/en/lights/AmbientLight.html +++ b/docs/api/en/lights/AmbientLight.html @@ -28,27 +28,22 @@

Constructor

[name]( [param:Integer color], [param:Float intensity] )

- [page:Integer color] - (optional) Numeric value of the RGB component of the color. Default is 0xffffff.
- [page:Float intensity] - (optional) Numeric value of the light's strength/intensity. Default is 1.

+ [page:Integer color] - (optional) Numeric value of the RGB component of + the color. Default is 0xffffff.
+ [page:Float intensity] - (optional) Numeric value of the light's + strength/intensity. Default is 1.

- Creates a new [name]. + Creates a new [name].

Properties

-

- See the base [page:Light Light] class for common properties. -

+

See the base [page:Light Light] class for common properties.

[property:Boolean isAmbientLight]

-

- Read-only flag to check if a given object is of type [name]. -

- +

Read-only flag to check if a given object is of type [name].

Methods

-

- See the base [page:Light Light] class for common methods. -

+

See the base [page:Light Light] class for common methods.

Source

diff --git a/docs/api/en/lights/AmbientLightProbe.html b/docs/api/en/lights/AmbientLightProbe.html index b4efdd32d17745..a36432eb4b787c 100644 --- a/docs/api/en/lights/AmbientLightProbe.html +++ b/docs/api/en/lights/AmbientLightProbe.html @@ -12,34 +12,34 @@

[name]

- Light probes are an alternative way of adding light to a 3D scene. AmbientLightProbe is the light estimation data - of a single ambient light in the scene. For more information about light probes, go to [page:LightProbe]. + Light probes are an alternative way of adding light to a 3D scene. + AmbientLightProbe is the light estimation data of a single ambient light + in the scene. For more information about light probes, go to + [page:LightProbe].

Constructor

[name]( [param:Color color], [param:Float intensity] )

- [page:Color color] - (optional) An instance of Color, string representing a color or a number representing a color.
- [page:Float intensity] - (optional) Numeric value of the light probe's intensity. Default is 1.

+ [page:Color color] - (optional) An instance of Color, string representing + a color or a number representing a color.
+ [page:Float intensity] - (optional) Numeric value of the light probe's + intensity. Default is 1.

- Creates a new [name]. + Creates a new [name].

Properties

- See the base [page:LightProbe LightProbe] class for common properties. + See the base [page:LightProbe LightProbe] class for common properties.

[property:Boolean isAmbientLightProbe]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

Methods

-

- See the base [page:LightProbe LightProbe] class for common methods. -

+

See the base [page:LightProbe LightProbe] class for common methods.

Source

diff --git a/docs/api/en/lights/DirectionalLight.html b/docs/api/en/lights/DirectionalLight.html index 1eee76d0374beb..707db4a3dab060 100644 --- a/docs/api/en/lights/DirectionalLight.html +++ b/docs/api/en/lights/DirectionalLight.html @@ -12,28 +12,34 @@

[name]

- A light that gets emitted in a specific direction. This light will behave as though it is - infinitely far away and the rays produced from it are all parallel. The common use case - for this is to simulate daylight; the sun is far enough away that its position can be - considered to be infinite, and all light rays coming from it are parallel.

- - This light can cast shadows - see the [page:DirectionalLightShadow] page for details. + A light that gets emitted in a specific direction. This light will behave + as though it is infinitely far away and the rays produced from it are all + parallel. The common use case for this is to simulate daylight; the sun is + far enough away that its position can be considered to be infinite, and + all light rays coming from it are parallel.

+ + This light can cast shadows - see the [page:DirectionalLightShadow] page + for details.

A Note about Position, Target and rotation

- A common point of confusion for directional lights is that setting the rotation has no effect. - This is because three.js's DirectionalLight is the equivalent to what is often called a 'Target - Direct Light' in other applications.

- - This means that its direction is calculated as pointing - from the light's [page:Object3D.position position] to the [page:.target target]'s position - (as opposed to a 'Free Direct Light' that just has a rotation component).

- - The reason for this is to allow the light to cast shadows - the [page:.shadow shadow] - camera needs a position to calculate shadows from.

- - See the [page:.target target] property below for details on updating the target. + A common point of confusion for directional lights is that setting the + rotation has no effect. This is because three.js's DirectionalLight is the + equivalent to what is often called a 'Target Direct Light' in other + applications.

+ + This means that its direction is calculated as pointing from the light's + [page:Object3D.position position] to the [page:.target target]'s position + (as opposed to a 'Free Direct Light' that just has a rotation + component).

+ + The reason for this is to allow the light to cast shadows - the + [page:.shadow shadow] camera needs a position to calculate shadows + from.

+ + See the [page:.target target] property below for details on updating the + target.

Code Example

@@ -57,8 +63,10 @@

Constructor

[name]( [param:Integer color], [param:Float intensity] )

- [page:Integer color] - (optional) hexadecimal color of the light. Default is 0xffffff (white).
- [page:Float intensity] - (optional) numeric value of the light's strength/intensity. Default is 1.

+ [page:Integer color] - (optional) hexadecimal color of the light. Default + is 0xffffff (white).
+ [page:Float intensity] - (optional) numeric value of the light's + strength/intensity. Default is 1.

Creates a new [name].

@@ -69,19 +77,18 @@

Properties

[property:Boolean castShadow]

- If set to `true` light will cast dynamic shadows. *Warning*: This is expensive and - requires tweaking to get shadows looking right. See the [page:DirectionalLightShadow] for details. - The default is `false`. + If set to `true` light will cast dynamic shadows. *Warning*: This is + expensive and requires tweaking to get shadows looking right. See the + [page:DirectionalLightShadow] for details. The default is `false`.

[property:Boolean isDirectionalLight]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Vector3 position]

- This is set equal to [page:Object3D.DEFAULT_UP] (0, 1, 0), so that the light shines from the top down. + This is set equal to [page:Object3D.DEFAULT_UP] (0, 1, 0), so that the + light shines from the top down.

[property:DirectionalLightShadow shadow]

@@ -91,32 +98,29 @@

[property:DirectionalLightShadow shadow]

[property:Object3D target]

- The DirectionalLight points from its [page:.position position] to target.position. The default - position of the target is `(0, 0, 0)`.
+ The DirectionalLight points from its [page:.position position] to + target.position. The default position of the target is `(0, 0, 0)`.
- *Note*: For the target's position to be changed to anything other than the default, - it must be added to the [page:Scene scene] using + *Note*: For the target's position to be changed to anything other than the + default, it must be added to the [page:Scene scene] using

scene.add( light.target );

- This is so that the target's [page:Object3D.matrixWorld matrixWorld] gets automatically - updated each frame.

+ This is so that the target's [page:Object3D.matrixWorld matrixWorld] gets + automatically updated each frame.

- It is also possible to set the target to be another object in the scene (anything with a - [page:Object3D.position position] property), like so: + It is also possible to set the target to be another object in the scene + (anything with a [page:Object3D.position position] property), like so:

- const targetObject = new THREE.Object3D(); + const targetObject = new THREE.Object3D(); scene.add(targetObject); - + light.target = targetObject; -

- The directionalLight will now track the target object. -

- +

The directionalLight will now track the target object.

Methods

@@ -124,13 +128,14 @@

Methods

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

[method:this copy]( [param:DirectionalLight source] )

- Copies value of all the properties from the [page:DirectionalLight source] to this - DirectionalLight. + Copies value of all the properties from the [page:DirectionalLight source] + to this DirectionalLight.

Source

diff --git a/docs/api/en/lights/HemisphereLight.html b/docs/api/en/lights/HemisphereLight.html index fd0c82e544a7f2..4f1aa4102a4855 100644 --- a/docs/api/en/lights/HemisphereLight.html +++ b/docs/api/en/lights/HemisphereLight.html @@ -7,19 +7,17 @@ - [page:Object3D] → [page:Light] → + [page:Object3D] → [page:Light] →

[name]

- A light source positioned directly above the scene, with color fading from the - sky color to the ground color.

- + A light source positioned directly above the scene, with color fading from + the sky color to the ground color.

This light cannot be used to cast shadows.

Code Example

- const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 ); scene.add( light ); @@ -36,44 +34,45 @@

Examples

Constructor

-

[name]( [param:Integer skyColor], [param:Integer groundColor], [param:Float intensity] )

-

- [page:Integer skyColor] - (optional) hexadecimal color of the sky. Default is 0xffffff.
- [page:Integer groundColor] - (optional) hexadecimal color of the ground. Default is 0xffffff.
- [page:Float intensity] - (optional) numeric value of the light's strength/intensity. Default is 1.

- - Creates a new [name]. +

+ [name]( [param:Integer skyColor], [param:Integer groundColor], + [param:Float intensity] ) +

+

+ [page:Integer skyColor] - (optional) hexadecimal color of the sky. Default + is 0xffffff.
+ [page:Integer groundColor] - (optional) hexadecimal color of the ground. + Default is 0xffffff.
+ [page:Float intensity] - (optional) numeric value of the light's + strength/intensity. Default is 1.

+ + Creates a new [name].

Properties

-

- See the base [page:Light Light] class for common properties. -

+

See the base [page:Light Light] class for common properties.

[property:Float color]

- The light's sky color, as passed in the constructor. - Default is a new [page:Color] set to white (0xffffff). + The light's sky color, as passed in the constructor. Default is a new + [page:Color] set to white (0xffffff).

[property:Float groundColor]

- The light's ground color, as passed in the constructor. - Default is a new [page:Color] set to white (0xffffff). + The light's ground color, as passed in the constructor. Default is a new + [page:Color] set to white (0xffffff).

[property:Boolean isHemisphereLight]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Vector3 position]

- This is set equal to [page:Object3D.DEFAULT_UP] (0, 1, 0), so that the light shines from the top down. + This is set equal to [page:Object3D.DEFAULT_UP] (0, 1, 0), so that the + light shines from the top down.

- -

Methods

See the base [page:Light Light] class for common methods.

@@ -81,7 +80,8 @@

Methods

[method:this copy]( [param:HemisphereLight source] )

Copies the value of [page:.color color], [page:.intensity intensity] and - [page:.groundColor groundColor] from the [page:Light source] light into this one. + [page:.groundColor groundColor] from the [page:Light source] light into + this one.

Source

diff --git a/docs/api/en/lights/HemisphereLightProbe.html b/docs/api/en/lights/HemisphereLightProbe.html index e16178078b0fcd..50eb258fd4bdf7 100644 --- a/docs/api/en/lights/HemisphereLightProbe.html +++ b/docs/api/en/lights/HemisphereLightProbe.html @@ -12,35 +12,38 @@

[name]

- Light probes are an alternative way of adding light to a 3D scene. HemisphereLightProbe is the light estimation data - of a single hemisphere light in the scene. For more information about light probes, go to [page:LightProbe]. + Light probes are an alternative way of adding light to a 3D scene. + HemisphereLightProbe is the light estimation data of a single hemisphere + light in the scene. For more information about light probes, go to + [page:LightProbe].

Constructor

-

[name]( [param:Color skyColor], [param:Color groundColor], [param:Float intensity] )

+

+ [name]( [param:Color skyColor], [param:Color groundColor], [param:Float intensity] ) +

- [page:Color skyColor] - (optional) An instance of Color, string representing a color or a number representing a color.
- [page:Color groundColor] - (optional) An instance of Color, string representing a color or a number representing a color.
- [page:Float intensity] - (optional) Numeric value of the light probe's intensity. Default is 1.

+ [page:Color skyColor] - (optional) An instance of Color, string + representing a color or a number representing a color.
+ [page:Color groundColor] - (optional) An instance of Color, string + representing a color or a number representing a color.
+ [page:Float intensity] - (optional) Numeric value of the light probe's + intensity. Default is 1.

Creates a new [name].

Properties

- See the base [page:LightProbe LightProbe] class for common properties. + See the base [page:LightProbe LightProbe] class for common properties.

[property:Boolean isHemisphereLightProbe]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

Methods

-

- See the base [page:LightProbe LightProbe] class for common methods. -

+

See the base [page:LightProbe LightProbe] class for common methods.

Source

diff --git a/docs/api/en/lights/Light.html b/docs/api/en/lights/Light.html index a20df24b31797b..dec5eca152768e 100644 --- a/docs/api/en/lights/Light.html +++ b/docs/api/en/lights/Light.html @@ -12,65 +12,63 @@

[name]

- Abstract base class for lights - all other light types inherit the properties and methods - described here. + Abstract base class for lights - all other light types inherit the + properties and methods described here.

-

Constructor

-

[name]( [param:Integer color], [param:Float intensity] )

- [page:Integer color] - (optional) hexadecimal color of the light. Default is 0xffffff (white).
- [page:Float intensity] - (optional) numeric value of the light's strength/intensity. Default is 1.

- - Creates a new [name]. Note that this is not intended to be called directly (use one of derived classes instead). + [page:Integer color] - (optional) hexadecimal color of the light. Default + is 0xffffff (white).
+ [page:Float intensity] - (optional) numeric value of the light's + strength/intensity. Default is 1.

+ Creates a new [name]. Note that this is not intended to be called directly + (use one of derived classes instead).

Properties

-

- See the base [page:Object3D Object3D] class for common properties. -

+

See the base [page:Object3D Object3D] class for common properties.

[property:Color color]

- Color of the light. Defaults to a new [page:Color] set to white, if not passed in the constructor.
+ Color of the light. Defaults to a new [page:Color] set to white, if not + passed in the constructor.

[property:Float intensity]

The light's intensity, or strength.
- In [page:WebGLRenderer.physicallyCorrectLights physically correct] mode, the units of intensity depend on the type of light.
+ When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled, + the units of intensity depend on the type of light.
Default - `1.0`.

[property:Boolean isLight]

-

- Read-only flag to check if a given object is of type [name]. -

- +

Read-only flag to check if a given object is of type [name].

Methods

-

- See the base [page:Object3D Object3D] class for common methods. -

+

See the base [page:Object3D Object3D] class for common methods.

[method:undefined dispose]()

- Abstract dispose method for classes that extend this class; implemented by subclasses that have disposable GPU-related resources. + Abstract dispose method for classes that extend this class; implemented by + subclasses that have disposable GPU-related resources.

[method:this copy]( [param:Light source] )

- Copies the value of [page:.color color] and [page:.intensity intensity] from the - [page:Light source] light into this one. + Copies the value of [page:.color color] and [page:.intensity intensity] + from the [page:Light source] light into this one.

[method:Object toJSON]( [param:Object meta] )

- meta -- object containing metadata such as materials, textures for objects.
- Convert the light to three.js [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. + meta -- object containing metadata such as materials, textures for + objects.
+ Convert the light to three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

Source

diff --git a/docs/api/en/lights/LightProbe.html b/docs/api/en/lights/LightProbe.html index e6586de1753ec6..e04787a4d8980f 100644 --- a/docs/api/en/lights/LightProbe.html +++ b/docs/api/en/lights/LightProbe.html @@ -12,21 +12,26 @@

[name]

- Light probes are an alternative way of adding light to a 3D scene. Unlike classical light sources (e.g. directional, - point or spot lights), light probes do not emit light. Instead they store information about light passing through - 3D space. During rendering, the light that hits a 3D object is approximated by using the data from the light probe. + Light probes are an alternative way of adding light to a 3D scene. Unlike + classical light sources (e.g. directional, point or spot lights), light + probes do not emit light. Instead they store information about light + passing through 3D space. During rendering, the light that hits a 3D + object is approximated by using the data from the light probe.

- Light probes are usually created from (radiance) environment maps. The class [page:LightProbeGenerator] can - be used to create light probes from instances of [page:CubeTexture] or [page:WebGLCubeRenderTarget]. - However, light estimation data could also be provided in other forms e.g. by WebXR. This enables the rendering - of augmented reality content that reacts to real world lighting. + Light probes are usually created from (radiance) environment maps. The + class [page:LightProbeGenerator] can be used to create light probes from + instances of [page:CubeTexture] or [page:WebGLCubeRenderTarget]. However, + light estimation data could also be provided in other forms e.g. by WebXR. + This enables the rendering of augmented reality content that reacts to + real world lighting.

- The current probe implementation in three.js supports so-called diffuse light probes. This type of light probe - is functionally equivalent to an irradiance environment map. + The current probe implementation in three.js supports so-called diffuse + light probes. This type of light probe is functionally equivalent to an + irradiance environment map.

Examples

@@ -39,22 +44,23 @@

Constructor

[name]( [param:SphericalHarmonics3 sh], [param:Float intensity] )

- [page:SphericalHarmonics3 sh] - (optional) An instance of [page:SphericalHarmonics3].
- [page:Float intensity] - (optional) Numeric value of the light probe's intensity. Default is 1.

+ [page:SphericalHarmonics3 sh] - (optional) An instance of + [page:SphericalHarmonics3].
+ [page:Float intensity] - (optional) Numeric value of the light probe's + intensity. Default is 1.

- Creates a new [name]. + Creates a new [name].

Properties

- See the base [page:Light Light] class for common properties. The [page:Light.color color] property is currently - not evaluated and thus has no effect. + See the base [page:Light Light] class for common properties. The + [page:Light.color color] property is currently not evaluated and thus has + no effect.

[property:Boolean isLightProbe]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:SphericalHarmonics3 sh]

@@ -62,9 +68,7 @@

[property:SphericalHarmonics3 sh]

Methods

-

- See the base [page:Light Light] class for common methods. -

+

See the base [page:Light Light] class for common methods.

Source

diff --git a/docs/api/en/lights/PointLight.html b/docs/api/en/lights/PointLight.html index 1eb0b9b16912a6..ba4665362708b1 100644 --- a/docs/api/en/lights/PointLight.html +++ b/docs/api/en/lights/PointLight.html @@ -12,10 +12,12 @@

[name]

- A light that gets emitted from a single point in all directions. A common use case for this - is to replicate the light emitted from a bare lightbulb.

+ A light that gets emitted from a single point in all directions. A common + use case for this is to replicate the light emitted from a bare + lightbulb.

- This light can cast shadows - see [page:PointLightShadow] page for details. + This light can cast shadows - see [page:PointLightShadow] page for + details.

Code Example

@@ -37,66 +39,72 @@

Examples

Constructor

-

[name]( [param:Integer color], [param:Float intensity], [param:Number distance], [param:Float decay] )

+

+ [name]( [param:Integer color], [param:Float intensity], [param:Number distance], [param:Float decay] ) +

- [page:Integer color] - (optional) hexadecimal color of the light. Default is 0xffffff (white).
- [page:Float intensity] - (optional) numeric value of the light's strength/intensity. Default is 1.
- [page:Number distance] - Maximum range of the light. Default is 0 (no limit).
- [page:Float decay] - The amount the light dims along the distance of the light. Default is 2.

+ [page:Integer color] - (optional) hexadecimal color of the light. Default + is 0xffffff (white).
+ [page:Float intensity] - (optional) numeric value of the light's + strength/intensity. Default is 1.
+ [page:Number distance] - Maximum range of the light. Default is 0 (no + limit).
+ [page:Float decay] - The amount the light dims along the distance of the + light. Default is 2.

Creates a new [name].

Properties

-

- See the base [page:Light Light] class for common properties. -

- +

See the base [page:Light Light] class for common properties.

+

[property:Boolean castShadow]

- If set to `true` light will cast dynamic shadows. *Warning*: This is expensive and - requires tweaking to get shadows looking right. See the [page:PointLightShadow] for details. - The default is `false`. + If set to `true` light will cast dynamic shadows. *Warning*: This is + expensive and requires tweaking to get shadows looking right. See the + [page:PointLightShadow] for details. The default is `false`.

[property:Float decay]

- The amount the light dims along the distance of the light. Default is `2`.
- In context of physically-correct rendering the default value should not be changed. + The amount the light dims along the distance of the light. Default is + `2`.
+ In context of physically-correct rendering the default value should not be + changed.

[property:Float distance]

- `Default mode` — When distance is zero, light does not attenuate. When distance is - non-zero, light will attenuate linearly from maximum intensity at the light's position down to - zero at this distance from the light. -

-

- `[page:WebGLRenderer.physicallyCorrectLights Physically correct] mode` — When distance - is zero, light will attenuate according to inverse-square law to infinite distance. When - distance is non-zero, light will attenuate according to inverse-square law until near the - distance cutoff, where it will then attenuate quickly and smoothly to 0. Inherently, cutoffs - are not physically correct. + `Default mode` — When distance is zero, light does not attenuate. When + distance is non-zero, light will attenuate linearly from maximum intensity + at the light's position down to zero at this distance from the light.

- Default is `0.0`. + When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled — + When distance is zero, light will attenuate according to inverse-square + law to infinite distance. When distance is non-zero, light will attenuate + according to inverse-square law until near the distance cutoff, where it + will then attenuate quickly and smoothly to 0. Inherently, cutoffs are not + physically correct.

+

Default is `0.0`.

[property:Float intensity]

The light's intensity. Default is `1`.
- In [page:WebGLRenderer.physicallyCorrectLights physically correct] mode, intensity is the luminous - intensity of the light measured in candela (cd).

+ When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled, + intensity is the luminous intensity of the light measured in candela + (cd).

Changing the intensity will also change the light's power. -

[property:Float power]

The light's power.
- In [page:WebGLRenderer.physicallyCorrectLights physically correct] mode, power is the luminous - power of the light measured in lumens (lm).

+ When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled, + power is the luminous power of the light measured in lumens (lm). +

Changing the power will also change the light's intensity.

@@ -105,26 +113,26 @@

[property:PointLightShadow shadow]

A [page:PointLightShadow] used to calculate shadows for this light.

- The lightShadow's [page:LightShadow.camera camera] - is set to a [page:PerspectiveCamera] with [page:PerspectiveCamera.fov fov] of 90, - [page:PerspectiveCamera.aspect aspect] of 1, [page:PerspectiveCamera.near near] - clipping plane at 0.5 and [page:PerspectiveCamera.far far] clipping plane at 500. + The lightShadow's [page:LightShadow.camera camera] is set to a + [page:PerspectiveCamera] with [page:PerspectiveCamera.fov fov] of 90, + [page:PerspectiveCamera.aspect aspect] of 1, [page:PerspectiveCamera.near near] + clipping plane at 0.5 and [page:PerspectiveCamera.far far] clipping + plane at 500.

Methods

-

- See the base [page:Light Light] class for common methods. -

+

See the base [page:Light Light] class for common methods.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

[method:this copy]( [param:PointLight source] )

- Copies value of all the properties from the [page:PointLight source] to this - PointLight. + Copies value of all the properties from the [page:PointLight source] to + this PointLight.

Source

diff --git a/docs/api/en/lights/RectAreaLight.html b/docs/api/en/lights/RectAreaLight.html index b7ce411fb74557..5c0c0e3b698007 100644 --- a/docs/api/en/lights/RectAreaLight.html +++ b/docs/api/en/lights/RectAreaLight.html @@ -12,16 +12,23 @@

[name]

- RectAreaLight emits light uniformly across the face a rectangular plane. This light type can be - used to simulate light sources such as bright windows or strip lighting.

+ RectAreaLight emits light uniformly across the face a rectangular plane. + This light type can be used to simulate light sources such as bright + windows or strip lighting.

Important Notes: -

    -
  • There is no shadow support.
  • -
  • Only [page:MeshStandardMaterial MeshStandardMaterial] and [page:MeshPhysicalMaterial MeshPhysicalMaterial] are supported.
  • -
  • You have to include [link:https://threejs.org/examples/jsm/lights/RectAreaLightUniformsLib.js RectAreaLightUniformsLib] into your scene and call `init()`.
  • -

+
    +
  • There is no shadow support.
  • +
  • + Only [page:MeshStandardMaterial MeshStandardMaterial] and + [page:MeshPhysicalMaterial MeshPhysicalMaterial] are supported. +
  • +
  • + You have to include + [link:https://threejs.org/examples/jsm/lights/RectAreaLightUniformsLib.js RectAreaLightUniformsLib] into your scene and call `init()`. +
  • +

Code Example

@@ -40,17 +47,18 @@

Code Example

Examples

-

- [example:webgl_lights_rectarealight WebGL / rectarealight ] -

+

[example:webgl_lights_rectarealight WebGL / rectarealight ]

Constructor

- -

[name]( [param:Integer color], [param:Float intensity], [param:Float width], [param:Float height] )

+

+ [name]( [param:Integer color], [param:Float intensity], [param:Float width], [param:Float height] ) +

- [page:Integer color] - (optional) hexadecimal color of the light. Default is 0xffffff (white).
- [page:Float intensity] - (optional) the light's intensity, or brightness. Default is 1.
+ [page:Integer color] - (optional) hexadecimal color of the light. Default + is 0xffffff (white).
+ [page:Float intensity] - (optional) the light's intensity, or brightness. + Default is 1.
[page:Float width] - (optional) width of the light. Default is 10.
[page:Float height] - (optional) height of the light. Default is 10.

@@ -58,54 +66,44 @@

[name]( [param:Integer color], [param:Float intensity], [param:Float width],

Properties

-

- See the base [page:Light Light] class for common properties. -

+

See the base [page:Light Light] class for common properties.

[property:Float height]

-

- The height of the light. -

+

The height of the light.

[property:Float intensity]

The light's intensity. Default is `1`.
- In [page:WebGLRenderer.physicallyCorrectLights physically correct] mode, intensity is the luminance - (brightness) of the light measured in nits (cd/m^2).

+ When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled, + intensity is the luminance (brightness) of the light measured in nits + (cd/m^2).

Changing the intensity will also change the light's power. -

[property:Boolean isRectAreaLight]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Float power]

The light's power.
- In [page:WebGLRenderer.physicallyCorrectLights physically correct] mode, power is the luminous - power of the light measured in lumens (lm).

+ When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled, + power is the luminous power of the light measured in lumens (lm). +

Changing the power will also change the light's intensity.

[property:Float width]

-

- The width of the light. -

+

The width of the light.

Methods

-

- See the base [page:Light Light] class for common methods. -

- +

See the base [page:Light Light] class for common methods.

[method:this copy]( [param:RectAreaLight source] )

- Copies value of all the properties from the [page:RectAreaLight source] to this - RectAreaLight. + Copies value of all the properties from the [page:RectAreaLight source] to + this RectAreaLight.

diff --git a/docs/api/en/lights/SpotLight.html b/docs/api/en/lights/SpotLight.html index 103bffd75901e6..5cfc28e18b3b34 100644 --- a/docs/api/en/lights/SpotLight.html +++ b/docs/api/en/lights/SpotLight.html @@ -12,10 +12,10 @@

[name]

- This light gets emitted from a single point in one direction, along a cone that increases in size - the further from the light it gets.

- - This light can cast shadows - see the [page:SpotLightShadow] page for details. + This light gets emitted from a single point in one direction, along a cone + that increases in size the further from the light it gets.

+ This light can cast shadows - see the [page:SpotLightShadow] page for + details.

Code Example

@@ -39,130 +39,120 @@

Code Example

Examples

-

[example:webgl_lights_spotlight lights / spotlight ]
[example:webgl_lights_spotlights lights / spotlights ]

Constructor

- - -

[name]( [param:Integer color], [param:Float intensity], [param:Float distance], [param:Radians angle], [param:Float penumbra], [param:Float decay] )

-

- [page:Integer color] - (optional) hexadecimal color of the light. Default is 0xffffff (white).
- [page:Float intensity] - (optional) numeric value of the light's strength/intensity. Default is 1.
- [page:Float distance] - Maximum range of the light. Default is 0 (no limit).
- [page:Radians angle] - Maximum angle of light dispersion from its direction whose upper - bound is Math.PI/2.
- [page:Float penumbra] - Percent of the spotlight cone that is attenuated due to penumbra. - Takes values between zero and 1. Default is zero.
- [page:Float decay] - The amount the light dims along the distance of the light.

- +

+ [name]( [param:Integer color], [param:Float intensity], [param:Float distance], [param:Radians angle], [param:Float penumbra], [param:Float decay] ) +

+

+ [page:Integer color] - (optional) hexadecimal color of the light. Default + is 0xffffff (white).
+ [page:Float intensity] - (optional) numeric value of the light's + strength/intensity. Default is 1.
+ [page:Float distance] - Maximum range of the light. Default is 0 (no + limit).
+ [page:Radians angle] - Maximum angle of light dispersion from its + direction whose upper bound is Math.PI/2.
+ [page:Float penumbra] - Percent of the spotlight cone that is attenuated + due to penumbra. Takes values between zero and 1. Default is zero.
+ [page:Float decay] - The amount the light dims along the distance of the + light.

Creates a new [name].

Properties

-

See the base [page:Light Light] class for common properties.

[property:Float angle]

- Maximum extent of the spotlight, in radians, from its direction. Should be no more than - `Math.PI/2`. The default is `Math.PI/3`. + Maximum extent of the spotlight, in radians, from its direction. Should be + no more than `Math.PI/2`. The default is `Math.PI/3`.

-

[property:Boolean castShadow]

- If set to `true` light will cast dynamic shadows. *Warning*: This is expensive and - requires tweaking to get shadows looking right. See the [page:SpotLightShadow] for details. - The default is `false`. + If set to `true` light will cast dynamic shadows. *Warning*: This is + expensive and requires tweaking to get shadows looking right. See the + [page:SpotLightShadow] for details. The default is `false`.

[property:Float decay]

- The amount the light dims along the distance of the light. Default is `2`.
- In context of physically-correct rendering the default value should not be changed. + The amount the light dims along the distance of the light. Default is + `2`.
+ In context of physically-correct rendering the default value should not be + changed.

[property:Float distance]

- `Default mode` — When distance is zero, light does not attenuate. When distance is - non-zero, light will attenuate linearly from maximum intensity at the light's position down to - zero at this distance from the light. -

-

- `[page:WebGLRenderer.physicallyCorrectLights Physically correct] mode` — When distance - is zero, light will attenuate according to inverse-square law to infinite distance. When - distance is non-zero, light will attenuate according to inverse-square law until near the - distance cutoff, where it will then attenuate quickly and smoothly to `0`. Inherently, cutoffs - are not physically correct. + `Default mode` — When distance is zero, light does not attenuate. When + distance is non-zero, light will attenuate linearly from maximum intensity + at the light's position down to zero at this distance from the light.

- Default is `0.0`. + When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled — + When distance is zero, light will attenuate according to inverse-square + law to infinite distance. When distance is non-zero, light will attenuate + according to inverse-square law until near the distance cutoff, where it + will then attenuate quickly and smoothly to `0`. Inherently, cutoffs are + not physically correct.

+

Default is `0.0`.

[property:Float intensity]

The light's intensity. Default is `1`.
- In [page:WebGLRenderer.physicallyCorrectLights physically correct] mode, intensity is the luminous - intensity of the light measured in candela (cd).

- + When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled, + intensity is the luminous intensity of the light measured in candela + (cd).

Changing the intensity will also change the light's power. -

[property:Boolean isSpotLight]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Float penumbra]

- Percent of the spotlight cone that is attenuated due to penumbra. Takes values between - zero and 1. The default is `0.0`. + Percent of the spotlight cone that is attenuated due to penumbra. Takes + values between zero and 1. The default is `0.0`.

[property:Vector3 position]

- This is set equal to [page:Object3D.DEFAULT_UP] (0, 1, 0), so that the light shines from the top down. + This is set equal to [page:Object3D.DEFAULT_UP] (0, 1, 0), so that the + light shines from the top down.

[property:Float power]

The light's power.
- In [page:WebGLRenderer.physicallyCorrectLights physically correct] mode, power is the luminous - power of the light measured in lumens (lm).

- + When [page:WebGLRenderer.useLegacyLights legacy lighting mode] is disabled, + power is the luminous power of the light measured in lumens (lm). +

Changing the power will also change the light's intensity.

-

[property:SpotLightShadow shadow]

-

- A [page:SpotLightShadow] used to calculate shadows for this light. -

- +

A [page:SpotLightShadow] used to calculate shadows for this light.

[property:Object3D target]

- The Spotlight points from its [page:.position position] to target.position. The default - position of the target is *(0, 0, 0)*.
- - *Note*: For the target's position to be changed to anything other than the default, - it must be added to the [page:Scene scene] using - - scene.add( light.target ); - - - This is so that the target's [page:Object3D.matrixWorld matrixWorld] gets automatically - updated each frame.

- - It is also possible to set the target to be another object in the scene (anything with a - [page:Object3D.position position] property), like so: + The Spotlight points from its [page:.position position] to + target.position. The default position of the target is *(0, 0, 0)*.
+ *Note*: For the target's position to be changed to anything other than the + default, it must be added to the [page:Scene scene] using + scene.add( light.target ); + This is so that the target's [page:Object3D.matrixWorld matrixWorld] gets + automatically updated each frame.

+ It is also possible to set the target to be another object in the scene + (anything with a [page:Object3D.position position] property), like so: -const targetObject = new THREE.Object3D(); +const targetObject = new THREE.Object3D(); scene.add(targetObject); light.target = targetObject; @@ -172,10 +162,12 @@

[property:Object3D target]

[property:Texture map]

- A [page:Texture] used to modulate the color of the light. The spot light color is mixed - with the RGB value of this texture, with a ratio corresponding to its - alpha value. The cookie-like masking effect is reproduced using pixel values (0, 0, 0, 1-cookie_value). - *Warning*: [param:SpotLight map] is disabled if [param:SpotLight castShadow] is *false*. + A [page:Texture] used to modulate the color of the light. The spot light + color is mixed with the RGB value of this texture, with a ratio + corresponding to its alpha value. The cookie-like masking effect is + reproduced using pixel values (0, 0, 0, 1-cookie_value). *Warning*: + [param:SpotLight map] is disabled if [param:SpotLight castShadow] is + *false*.

Methods

@@ -184,13 +176,14 @@

Methods

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

[method:this copy]( [param:SpotLight source] )

- Copies value of all the properties from the [page:SpotLight source] to this - SpotLight. + Copies value of all the properties from the [page:SpotLight source] to + this SpotLight.

diff --git a/docs/api/en/lights/shadows/DirectionalLightShadow.html b/docs/api/en/lights/shadows/DirectionalLightShadow.html index 9021f303801dc6..5201c48061a7c8 100644 --- a/docs/api/en/lights/shadows/DirectionalLightShadow.html +++ b/docs/api/en/lights/shadows/DirectionalLightShadow.html @@ -12,11 +12,12 @@

[name]

- This is used internally by [page:DirectionalLight DirectionalLights] for calculating shadows.

+ This is used internally by [page:DirectionalLight DirectionalLights] for + calculating shadows.

- Unlike the other shadow classes, this uses an [page:OrthographicCamera] to calculate the shadows, - rather than a [page:PerspectiveCamera]. This is because light rays from a [page:DirectionalLight] - are parallel. + Unlike the other shadow classes, this uses an [page:OrthographicCamera] to + calculate the shadows, rather than a [page:PerspectiveCamera]. This is + because light rays from a [page:DirectionalLight] are parallel.

Code Example

@@ -62,8 +63,8 @@

Code Example

Constructor

[name]( )

- Creates a new [name]. This is not intended to be called directly - it is called - internally by [page:DirectionalLight]. + Creates a new [name]. This is not intended to be called directly - it is + called internally by [page:DirectionalLight].

Properties

@@ -73,25 +74,23 @@

Properties

[property:Camera camera]

- The light's view of the world. This is used to generate a depth map of the scene; objects behind - other objects from the light's perspective will be in shadow.

- - The default is an [page:OrthographicCamera] with [page:OrthographicCamera.left left] and - [page:OrthographicCamera.bottom bottom] set to -5, [page:OrthographicCamera.right right] - and [page:OrthographicCamera.top top] set to 5, the [page:OrthographicCamera.near near] - clipping plane at 0.5 and the [page:OrthographicCamera.far far] clipping plane at 500. + The light's view of the world. This is used to generate a depth map of the + scene; objects behind other objects from the light's perspective will be + in shadow.

+ + The default is an [page:OrthographicCamera] with + [page:OrthographicCamera.left left] and [page:OrthographicCamera.bottom bottom] + set to -5, [page:OrthographicCamera.right right] and + [page:OrthographicCamera.top top] set to 5, the + [page:OrthographicCamera.near near] clipping plane at 0.5 and the + [page:OrthographicCamera.far far] clipping plane at 500.

[property:Boolean isDirectionalLightShadow]

-

- Read-only flag to check if a given object is of type [name]. -

- +

Read-only flag to check if a given object is of type [name].

Methods

-

- See the base [page:LightShadow LightShadow] class for common methods. -

+

See the base [page:LightShadow LightShadow] class for common methods.

Source

diff --git a/docs/api/en/lights/shadows/LightShadow.html b/docs/api/en/lights/shadows/LightShadow.html index 1ca49fb872e064..e4576a6d66403c 100644 --- a/docs/api/en/lights/shadows/LightShadow.html +++ b/docs/api/en/lights/shadows/LightShadow.html @@ -7,146 +7,155 @@ -

[name]

-

- Serves as a base class for the other shadow classes. -

- +

Serves as a base class for the other shadow classes.

Constructor

[name]( [param:Camera camera] )

- [page:Camera camera] - the light's view of the world.

+ [page:Camera camera] - the light's view of the world.

- Create a new [name]. This is not intended to be called directly - it is used as a base class by - other light shadows. + Create a new [name]. This is not intended to be called directly - it is + used as a base class by other light shadows.

Properties

[property:Boolean autoUpdate]

- Enables automatic updates of the light's shadow. Default is `true`. - If you do not require dynamic lighting / shadows, you may set this to `false`. + Enables automatic updates of the light's shadow. Default is `true`. If you + do not require dynamic lighting / shadows, you may set this to `false`.

[property:Camera camera]

- The light's view of the world. This is used to generate a depth map of the scene; objects behind - other objects from the light's perspective will be in shadow. + The light's view of the world. This is used to generate a depth map of the + scene; objects behind other objects from the light's perspective will be + in shadow.

[property:Float bias]

- Shadow map bias, how much to add or subtract from the normalized depth when deciding whether a surface is in shadow.
- The default is 0. Very tiny adjustments here (in the order of 0.0001) may help reduce artifacts in shadows + Shadow map bias, how much to add or subtract from the normalized depth + when deciding whether a surface is in shadow.
+ The default is 0. Very tiny adjustments here (in the order of 0.0001) may + help reduce artifacts in shadows

[property:Integer blurSamples]

-

- The amount of samples to use when blurring a VSM shadow map. -

+

The amount of samples to use when blurring a VSM shadow map.

[property:WebGLRenderTarget map]

- The depth map generated using the internal camera; a location beyond a pixel's depth is - in shadow. Computed internally during rendering. + The depth map generated using the internal camera; a location beyond a + pixel's depth is in shadow. Computed internally during rendering.

[property:WebGLRenderTarget mapPass]

- The distribution map generated using the internal camera; an occlusion is calculated based - on the distribution of depths. Computed internally during rendering. + The distribution map generated using the internal camera; an occlusion is + calculated based on the distribution of depths. Computed internally during + rendering.

[property:Vector2 mapSize]

A [Page:Vector2] defining the width and height of the shadow map.

- Higher values give better quality shadows at the cost of computation time. Values must be - powers of 2, up to the [page:WebGLRenderer.capabilities].maxTextureSize for a given device, - although the width and height don't have to be the same (so, for example, (512, 1024) is valid). - The default is *( 512, 512 )*. + Higher values give better quality shadows at the cost of computation time. + Values must be powers of 2, up to the + [page:WebGLRenderer.capabilities].maxTextureSize for a given device, + although the width and height don't have to be the same (so, for example, + (512, 1024) is valid). The default is *( 512, 512 )*.

[property:Matrix4 matrix]

- Model to shadow camera space, to compute location and depth in shadow map. Stored - in a [page:Matrix4 Matrix4]. This is computed internally during rendering. + Model to shadow camera space, to compute location and depth in shadow map. + Stored in a [page:Matrix4 Matrix4]. This is computed internally during + rendering.

[property:Boolean needsUpdate]

- When set to `true`, shadow maps will be updated in the next `render` call. Default is `false`. - If you have set [page:.autoUpdate] to `false`, you will need to set this property to `true` and then make a render call to update the light's shadow. + When set to `true`, shadow maps will be updated in the next `render` call. + Default is `false`. If you have set [page:.autoUpdate] to `false`, you + will need to set this property to `true` and then make a render call to + update the light's shadow.

[property:Float normalBias]

- Defines how much the position used to query the shadow map is offset along the object normal. - The default is 0. Increasing this value can be used to reduce shadow acne especially in large scenes where light shines onto geometry at a shallow angle. The cost is that shadows may appear distorted. + Defines how much the position used to query the shadow map is offset along + the object normal. The default is 0. Increasing this value can be used to + reduce shadow acne especially in large scenes where light shines onto + geometry at a shallow angle. The cost is that shadows may appear + distorted.

[property:Float radius]

- Setting this to values greater than 1 will blur the edges of the shadow.
+ Setting this to values greater than 1 will blur the edges of the + shadow.
- High values will cause unwanted banding effects in the shadows - a greater [page:.mapSize mapSize] - will allow for a higher value to be used here before these effects become visible.
- If [page:WebGLRenderer.shadowMap.type] is set to [page:Renderer PCFSoftShadowMap], radius has - no effect and it is recommended to increase softness by decreasing [page:.mapSize mapSize] instead.

+ High values will cause unwanted banding effects in the shadows - a greater + [page:.mapSize mapSize] will allow for a higher value to be used here + before these effects become visible.
+ If [page:WebGLRenderer.shadowMap.type] is set to [page:Renderer PCFSoftShadowMap], + radius has no effect and it is recommended to increase + softness by decreasing [page:.mapSize mapSize] instead.

- Note that this has no effect if the [page:WebGLRenderer.shadowMap.type] is set to [page:Renderer BasicShadowMap]. + Note that this has no effect if the [page:WebGLRenderer.shadowMap.type] is + set to [page:Renderer BasicShadowMap].

-

Methods

[method:Vector2 getFrameExtents]()

- Used internally by the renderer to extend the shadow map to contain all viewports + Used internally by the renderer to extend the shadow map to contain all + viewports

[method:undefined updateMatrices]( [param:Light light] )

- Update the matrices for the camera and shadow, used internally by the renderer.

+ Update the matrices for the camera and shadow, used internally by the + renderer.

- light -- the light for which the shadow is being rendered. + light -- the light for which the shadow is being rendered.

[method:Frustum getFrustum]()

- Gets the shadow cameras frustum. Used internally by the renderer to cull objects. + Gets the shadow cameras frustum. Used internally by the renderer to cull + objects.

[method:number getViewportCount]()

- Used internally by the renderer to get the number of viewports that need to be rendered for this shadow. + Used internally by the renderer to get the number of viewports that need + to be rendered for this shadow.

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

[method:this copy]( [param:LightShadow source] )

- Copies value of all the properties from the [page:LightShadow source] to this - Light. + Copies value of all the properties from the [page:LightShadow source] to + this Light.

[method:LightShadow clone]()

-

- Creates a new LightShadow with the same properties as this one. -

+

Creates a new LightShadow with the same properties as this one.

[method:Object toJSON]()

-

- Serialize this LightShadow. -

+

Serialize this LightShadow.

Source

diff --git a/docs/api/en/lights/shadows/PointLightShadow.html b/docs/api/en/lights/shadows/PointLightShadow.html index 42a030a2ef95d1..5cb7e2d73821b5 100644 --- a/docs/api/en/lights/shadows/PointLightShadow.html +++ b/docs/api/en/lights/shadows/PointLightShadow.html @@ -12,10 +12,10 @@

[name]

- This is used internally by [page:PointLight PointLights] for calculating shadows. + This is used internally by [page:PointLight PointLights] for calculating + shadows.

-

Code Example

//Create a WebGLRenderer and turn on shadows in the renderer @@ -58,8 +58,8 @@

Code Example

Constructor

[name]( )

- Creates a new [name]. This is not intended to be called directly - it is called - internally by [page:PointLight]. + Creates a new [name]. This is not intended to be called directly - it is + called internally by [page:PointLight].

Properties

@@ -68,22 +68,21 @@

Properties

[property:Boolean isPointLightShadow]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

Methods

-

- See the base [page:LightShadow LightShadow] class for common methods. -

+

See the base [page:LightShadow LightShadow] class for common methods.

-

[method:undefined updateMatrices]( [param:Light light], [param:number viewportIndex])

+

+ [method:undefined updateMatrices]( [param:Light light], [param:number viewportIndex]) +

- Update the matrices for the camera and shadow, used internally by the renderer.

+ Update the matrices for the camera and shadow, used internally by the + renderer.

- light -- the light for which the shadow is being rendered.
- viewportIndex -- calculates the matrix for this viewport + light -- the light for which the shadow is being rendered.
+ viewportIndex -- calculates the matrix for this viewport

Source

diff --git a/docs/api/en/lights/shadows/SpotLightShadow.html b/docs/api/en/lights/shadows/SpotLightShadow.html index 28f834f2d6eb3e..8661bb36bdec5a 100644 --- a/docs/api/en/lights/shadows/SpotLightShadow.html +++ b/docs/api/en/lights/shadows/SpotLightShadow.html @@ -12,7 +12,8 @@

[name]

- This is used internally by [page:SpotLight SpotLights] for calculating shadows. + This is used internally by [page:SpotLight SpotLights] for calculating + shadows.

Code Example

@@ -56,35 +57,42 @@

Code Example

Constructor

-

The constructor creates a [param:PerspectiveCamera PerspectiveCamera] to manage the shadow's view of the world.

+

+ The constructor creates a [param:PerspectiveCamera PerspectiveCamera] to + manage the shadow's view of the world. +

Properties

-

See the base [page:LightShadow LightShadow] class for common properties.

- +

+ See the base [page:LightShadow LightShadow] class for common properties. +

[property:Camera camera]

- The light's view of the world. This is used to generate a depth map of the scene; objects behind - other objects from the light's perspective will be in shadow.

- - The default is a [page:PerspectiveCamera] with [page:PerspectiveCamera.near near] clipping plane at `0.5`. - The [page:PerspectiveCamera.fov fov] will track the [page:SpotLight.angle angle] property of the owning - [page:SpotLight SpotLight] via the [page:SpotLightShadow.update update] method. Similarly, the - [page:PerspectiveCamera.aspect aspect] property will track the aspect of the - [page:LightShadow.mapSize mapSize]. If the [page:SpotLight.distance distance] property of the light is - set, the [page:PerspectiveCamera.far far] clipping plane will track that, otherwise it defaults to `500`. - + The light's view of the world. This is used to generate a depth map of the + scene; objects behind other objects from the light's perspective will be + in shadow.

+ + The default is a [page:PerspectiveCamera] with + [page:PerspectiveCamera.near near] clipping plane at `0.5`. The + [page:PerspectiveCamera.fov fov] will track the [page:SpotLight.angle angle] + property of the owning [page:SpotLight SpotLight] via the + [page:SpotLightShadow.update update] method. Similarly, the + [page:PerspectiveCamera.aspect aspect] property will track the aspect of + the [page:LightShadow.mapSize mapSize]. If the [page:SpotLight.distance distance] + property of the light is set, the [page:PerspectiveCamera.far far] + clipping plane will track that, otherwise it defaults to `500`.

[property:Number focus]

- Used to focus the shadow camera. The camera's field of view is set as a percentage of the spotlight's field-of-view. Range is `[0, 1]`. Default is `1.0`.
+ Used to focus the shadow camera. The camera's field of view is set as a + percentage of the spotlight's field-of-view. Range is `[0, 1]`. Default is + `1.0`.

[property:Boolean isSpotLightShadow]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

Methods

See the base [page:LightShadow LightShadow] class for common methods.

diff --git a/docs/api/en/loaders/AnimationLoader.html b/docs/api/en/loaders/AnimationLoader.html index 136006b16518d0..6258f75685e1de 100644 --- a/docs/api/en/loaders/AnimationLoader.html +++ b/docs/api/en/loaders/AnimationLoader.html @@ -12,8 +12,8 @@

[name]

- Class for loading [page:AnimationClip AnimationClips] in JSON format. - This uses the [page:FileLoader] internally for loading files. + Class for loading [page:AnimationClip AnimationClips] in JSON format. This + uses the [page:FileLoader] internally for loading files.

Code Example

@@ -48,9 +48,9 @@

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- - Creates a new [name]. + [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ Creates a new [name].

Properties

@@ -59,27 +59,31 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:AnimationClip animation clips].
- [page:Function onProgress] (optional) — Will be called while load progresses. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] (optional) — Will be called if load errors.

- - Begin loading from url and pass the loaded animation to onLoad. + [page:Function onLoad] — Will be called when load completes. The argument + will be the loaded [page:AnimationClip animation clips].
+ [page:Function onProgress] (optional) — Will be called while load + progresses. The argument will be the ProgressEvent instance, which + contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.
+ [page:Function onError] (optional) — Will be called if load errors.

+ Begin loading from url and pass the loaded animation to onLoad.

[method:Array parse]( [param:JSON json] )

- [page:JSON json] — required

- - Parse the JSON object and return an array of animation clips. Individual clips in the object will - be parsed with [page:AnimationClip.parse]. + [page:JSON json] — required

+ Parse the JSON object and return an array of animation clips. Individual + clips in the object will be parsed with [page:AnimationClip.parse].

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/loaders/AudioLoader.html b/docs/api/en/loaders/AudioLoader.html index 1a29147d6c7971..1b571ea1e10fd2 100644 --- a/docs/api/en/loaders/AudioLoader.html +++ b/docs/api/en/loaders/AudioLoader.html @@ -13,8 +13,9 @@

[name]

Class for loading an - [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer AudioBuffer]. - This uses the [page:FileLoader] internally for loading files. + [link:https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer AudioBuffer]. + This uses the [page:FileLoader] internally for loading + files.

Code Example

@@ -65,9 +66,10 @@

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + Creates a new [name].

Properties

@@ -76,16 +78,24 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] — Will be called when load completes. The argument will be the loaded text response.
- [page:Function onProgress] (optional) — Will be called while load progresses. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:Function onLoad] — Will be called when load completes. The argument + will be the loaded text response.
+ [page:Function onProgress] (optional) — Will be called while load + progresses. The argument will be the ProgressEvent instance, which + contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and pass the loaded [page:String AudioBuffer] to onLoad. + Begin loading from url and pass the loaded [page:String AudioBuffer] to + onLoad.

Source

diff --git a/docs/api/en/loaders/BufferGeometryLoader.html b/docs/api/en/loaders/BufferGeometryLoader.html index 88e9c89e622dc1..50a22c2c65b9e4 100644 --- a/docs/api/en/loaders/BufferGeometryLoader.html +++ b/docs/api/en/loaders/BufferGeometryLoader.html @@ -12,8 +12,8 @@

[name]

- A loader for loading a [page:BufferGeometry]. - This uses the [page:FileLoader] internally for loading files. + A loader for loading a [page:BufferGeometry]. This uses the + [page:FileLoader] internally for loading files.

Code Example

@@ -46,21 +46,14 @@

Code Example

);
-

Examples

- -

- [example:webgl_performance WebGL / performance] -

-

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. -

-

- Creates a new [name]. + [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+

Creates a new [name].

Properties

See the base [page:Loader] class for common properties.

@@ -68,26 +61,32 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].d
- [page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:BufferGeometry].
- [page:Function onProgress] (optional) — Will be called while load progresses. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:Function onLoad] — Will be called when load completes. The argument + will be the loaded [page:BufferGeometry].
+ [page:Function onProgress] (optional) — Will be called while load + progresses. The argument will be the ProgressEvent instance, which + contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and call onLoad with the parsed response content. + Begin loading from url and call onLoad with the parsed response content.

[method:BufferGeometry parse]( [param:Object json] )

- [page:Object json] — The `JSON` structure to parse.

- Parse a `JSON` structure and return a [page:BufferGeometry]. + [page:Object json] — The `JSON` structure to parse.

+ Parse a `JSON` structure and return a [page:BufferGeometry].

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/loaders/Cache.html b/docs/api/en/loaders/Cache.html index b459ed3b7b1918..b2e5d55569a6f1 100644 --- a/docs/api/en/loaders/Cache.html +++ b/docs/api/en/loaders/Cache.html @@ -15,11 +15,8 @@

[name]

Code Example

-

To enable caching across all loaders that use [page:FileLoader], set

- - THREE.Cache.enabled = true. - - +

To enable caching across all loaders that use [page:FileLoader], set

+ THREE.Cache.enabled = true.

Examples

@@ -37,36 +34,36 @@

[property:Boolean enabled]

[property:Object files]

An [page:Object object] that holds cached files.

-

Methods

[method:undefined add]( [param:String key], [param:Object file] )

- [page:String key] — the [page:String key] to reference the cached file by.
- [page:Object file] — The file to be cached.

+ [page:String key] — the [page:String key] to reference the cached file + by.
+ [page:Object file] — The file to be cached.

- Adds a cache entry with a key to reference the file. If this key already holds a file, - it is overwritten. + Adds a cache entry with a key to reference the file. If this key already + holds a file, it is overwritten.

[method:Any get]( [param:String key] )

- [page:String key] — A string key

+ [page:String key] — A string key

- Get the value of [page:String key]. If the key does not exist `undefined` is returned. + Get the value of [page:String key]. If the key does not exist `undefined` + is returned.

[method:undefined remove]( [param:String key] )

- [page:String key] — A string key that references a cached file.

+ [page:String key] — A string key that references a cached file.

- Remove the cached file associated with the key. + Remove the cached file associated with the key.

[method:undefined clear]()

Remove all values from the cache.

-

Source

diff --git a/docs/api/en/loaders/CompressedTextureLoader.html b/docs/api/en/loaders/CompressedTextureLoader.html index 067a8a9081979d..9ca1611e0d9e47 100644 --- a/docs/api/en/loaders/CompressedTextureLoader.html +++ b/docs/api/en/loaders/CompressedTextureLoader.html @@ -12,15 +12,16 @@

[name]

- Abstract base class for block based textures loader (dds, pvr, ...). - This uses the [page:FileLoader] internally for loading files. + Abstract base class for block based textures loader (dds, pvr, ...). This + uses the [page:FileLoader] internally for loading files.

Examples

- See the [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/DDSLoader.js DDSLoader] - and [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PVRLoader.js PVRLoader] + See the + [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/DDSLoader.js DDSLoader] + and [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PVRLoader.js PVRLoader] for examples of derived classes.

@@ -28,10 +29,10 @@

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. - Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + Creates a new [name].

Properties

@@ -40,16 +41,25 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:CompressedTexture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:CompressedTexture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] (optional) — Will be called when load completes. The argument will be the loaded texture.
- [page:Function onProgress] (optional) — Will be called while load progresses. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:Function onLoad] (optional) — Will be called when load completes. + The argument will be the loaded texture.
+ [page:Function onProgress] (optional) — Will be called while load + progresses. The argument will be the ProgressEvent instance, which + contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and pass the loaded texture to onLoad. The method also returns a new texture object which can directly be used for material creation. + Begin loading from url and pass the loaded texture to onLoad. The method + also returns a new texture object which can directly be used for material + creation.

Source

diff --git a/docs/api/en/loaders/CubeTextureLoader.html b/docs/api/en/loaders/CubeTextureLoader.html index a4fda6a0798092..5656f0505897ba 100644 --- a/docs/api/en/loaders/CubeTextureLoader.html +++ b/docs/api/en/loaders/CubeTextureLoader.html @@ -12,8 +12,8 @@

[name]

- Class for loading a [page:CubeTexture CubeTexture]. - This uses the [page:ImageLoader] internally for loading files. + Class for loading a [page:CubeTexture CubeTexture]. This uses the + [page:ImageLoader] internally for loading files.

Code Example

@@ -44,9 +44,10 @@

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + Creates a new [name].

Properties

@@ -55,24 +56,32 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:CubeTexture load]( [param:String urls], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:CubeTexture load]( [param:String urls], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String urls] — array of 6 urls to images, one for each side of the CubeTexture. - The urls should be specified in the following order: pos-x, neg-x, pos-y, neg-y, pos-z, neg-z. - They can also be [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URIs].
- Note that, by convention, cube maps are specified in a coordinate system in which positive-x is to the right - when looking up the positive-z axis -- in other words, using a left-handed coordinate system. - Since three.js uses a right-handed coordinate system, environment maps used in three.js will have pos-x and neg-x swapped.
- [page:Function onLoad] (optional) — Will be called when load completes. The argument will be the loaded [page:CubeTexture texture].
- [page:Function onProgress] (optional) — This callback function is currently not supported.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:String urls] — array of 6 urls to images, one for each side of the + CubeTexture. The urls should be specified in the following order: pos-x, + neg-x, pos-y, neg-y, pos-z, neg-z. They can also be + [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URIs].
+ Note that, by convention, cube maps are specified in a coordinate system + in which positive-x is to the right when looking up the positive-z axis -- + in other words, using a left-handed coordinate system. Since three.js uses + a right-handed coordinate system, environment maps used in three.js will + have pos-x and neg-x swapped.
+ [page:Function onLoad] (optional) — Will be called when load completes. + The argument will be the loaded [page:CubeTexture texture].
+ [page:Function onProgress] (optional) — This callback function is + currently not supported.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and pass the loaded [page:CubeTexture texture] to onLoad. The method also returns a new texture object which can directly be used for material creation. + Begin loading from url and pass the loaded [page:CubeTexture texture] to + onLoad. The method also returns a new texture object which can directly be + used for material creation.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/loaders/DataTextureLoader.html b/docs/api/en/loaders/DataTextureLoader.html index f269f522de80e8..8e717ab602598a 100644 --- a/docs/api/en/loaders/DataTextureLoader.html +++ b/docs/api/en/loaders/DataTextureLoader.html @@ -12,26 +12,25 @@

[name]

- Abstract base class to load generic binary textures formats (rgbe, hdr, ...). - This uses the [page:FileLoader] internally for loading files, and creates a new - [page:DataTexture]. + Abstract base class to load generic binary textures formats (rgbe, hdr, + ...). This uses the [page:FileLoader] internally for loading files, and + creates a new [page:DataTexture].

Examples

-

- See the [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/RGBELoader.js RGBELoader] + See the + [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/RGBELoader.js RGBELoader] for an example of a derived class.

Constructor

-

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. - Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + Creates a new [name].

Properties

@@ -40,20 +39,28 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:DataTexture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:DataTexture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] (optional) — Will be called when load completes. The argument will be the loaded texture.
- [page:Function onProgress] (optional) — Will be called while load progresses.The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:Function onLoad] (optional) — Will be called when load completes. + The argument will be the loaded texture.
+ [page:Function onProgress] (optional) — Will be called while load + progresses.The argument will be the ProgressEvent instance, which contains + .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer + loaded]. If the server does not set the Content-Length header; + .[page:Integer total] will be 0.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and pass the loaded texture to onLoad. The method also returns a new texture object which can directly be used for material creation. + Begin loading from url and pass the loaded texture to onLoad. The method + also returns a new texture object which can directly be used for material + creation.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/loaders/FileLoader.html b/docs/api/en/loaders/FileLoader.html index 4b059d1c1cabf2..b7d74d2bdcb5ea 100644 --- a/docs/api/en/loaders/FileLoader.html +++ b/docs/api/en/loaders/FileLoader.html @@ -12,8 +12,9 @@

[name]

- A low level class for loading resources with Fetch, used internally by most loaders. - It can also be used directly to load any file type that does not have a loader. + A low level class for loading resources with Fetch, used internally by + most loaders. It can also be used directly to load any file type that does + not have a loader.

Code Example

@@ -46,17 +47,18 @@

Code Example

*Note:* The cache must be enabled using THREE.Cache.enabled = true; - This is a global property and only needs to be set once to be used by all loaders that use FileLoader internally. - [page:Cache Cache] is a cache module that holds the response from each request made through this loader, so each file is requested once. + This is a global property and only needs to be set once to be used by all + loaders that use FileLoader internally. [page:Cache Cache] is a cache + module that holds the response from each request made through this loader, + so each file is requested once.

-

Constructor

[name] ( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. - Default is [page:DefaultLoadingManager]. + [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:DefaultLoadingManager].

Properties

@@ -64,22 +66,33 @@

Properties

[property:String mimeType]

- The expected [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types mimeType]. + The expected + [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types mimeType]. See [page:.setMimeType]. Default is `undefined`.

[property:String responseType]

-

The expected response type. See [page:.setResponseType]. Default is `undefined`.

+

+ The expected response type. See [page:.setResponseType]. Default is + `undefined`. +

Methods

See the base [page:Loader] class for common methods.

-

[method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

[page:String url] — the path or URL to the file. This can also be a - [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] (optional) — Will be called when loading completes. The argument will be the loaded response.
- [page:Function onProgress] (optional) — Will be called while load progresses. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
+ [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
+ [page:Function onLoad] (optional) — Will be called when loading completes. + The argument will be the loaded response.
+ [page:Function onProgress] (optional) — Will be called while load + progresses. The argument will be the ProgressEvent instance, which + contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.
[page:Function onError] (optional) — Will be called if an error occurs.

Load the URL and pass the response to the onLoad function. @@ -87,21 +100,27 @@

[method:undefined load]( [param:String url], [param:Function onLoad], [param

[method:this setMimeType]( [param:String mimeType] )

- Set the expected [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types mimeType] - of the file being loaded. Note that in many cases this will be determined automatically, so by default it is `undefined`. + Set the expected + [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types mimeType] + of the file being loaded. Note that in many cases this will be + determined automatically, so by default it is `undefined`.

[method:this setResponseType]( [param:String responseType] )

Change the response type. Valid values are:
- [page:String text] or empty string (default) - returns the data as [page:String String].
- [page:String arraybuffer] - loads the data into a [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer ArrayBuffer] and returns that.
- [page:String blob] - returns the data as a [link:https://developer.mozilla.org/en/docs/Web/API/Blob Blob].
- [page:String document] - parses the file using the [link:https://developer.mozilla.org/en-US/docs/Web/API/DOMParser DOMParser].
- [page:String json] - parses the file using [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse JSON.parse].
+ [page:String text] or empty string (default) - returns the data as + [page:String String].
+ [page:String arraybuffer] - loads the data into a + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer ArrayBuffer] and returns that.
+ [page:String blob] - returns the data as a + [link:https://developer.mozilla.org/en/docs/Web/API/Blob Blob].
+ [page:String document] - parses the file using the + [link:https://developer.mozilla.org/en-US/docs/Web/API/DOMParser DOMParser].
+ [page:String json] - parses the file using + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse JSON.parse].

-

Source

diff --git a/docs/api/en/loaders/ImageBitmapLoader.html b/docs/api/en/loaders/ImageBitmapLoader.html index 1535f994337c28..bef3870017380a 100644 --- a/docs/api/en/loaders/ImageBitmapLoader.html +++ b/docs/api/en/loaders/ImageBitmapLoader.html @@ -12,16 +12,21 @@

[name]

- A loader for loading an [page:Image] as an [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap]. - An ImageBitmap provides an asynchronous and resource efficient pathway to prepare textures for rendering in WebGL.
- Unlike [page:FileLoader], [name] does not avoid multiple concurrent requests to the same URL. + A loader for loading an [page:Image] as an + [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap]. An ImageBitmap provides an asynchronous and resource + efficient pathway to prepare textures for rendering in WebGL.
+ Unlike [page:FileLoader], [name] does not avoid multiple concurrent + requests to the same URL.

- Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] are ignored. - [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] needs these configuration on bitmap creation - unlike regular images need them on uploading to GPU. You need to set the equivalent options via [page:ImageBitmapLoader.setOptions] - instead. Refer to [link:https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.10 WebGL specification] for the detail. + Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with + [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] are ignored. + [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] + needs these configuration on bitmap creation unlike regular + images need them on uploading to GPU. You need to set the equivalent + options via [page:ImageBitmapLoader.setOptions] instead. Refer to + [link:https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.10 WebGL specification] for the detail.

Code Example

@@ -49,55 +54,62 @@

Code Example

// onError callback function ( err ) { - console.log( 'An error happened' ); + console.log( 'An error happened' ); } );

Examples

-

- [example:webgl_loader_imagebitmap WebGL / loader / ImageBitmap] -

+

[example:webgl_loader_imagebitmap WebGL / loader / ImageBitmap]

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + Creates a new [name].

Properties

See the base [page:Loader] class for common properties.

[property:Boolean isImageBitmapLoader]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:String options]

-

An optional object that sets options for the internally used [link:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap createImageBitmap] factory method. Default is `undefined`.

+

+ An optional object that sets options for the internally used + [link:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap createImageBitmap] + factory method. Default is `undefined`. +

Methods

See the base [page:Loader] class for common methods.

-

[method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:Image image].
- [page:Function onProgress] (optional) — This callback function is currently not supported.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:Function onLoad] — Will be called when load completes. The argument + will be the loaded [page:Image image].
+ [page:Function onProgress] (optional) — This callback function is + currently not supported.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and return the [page:ImageBitmap image] object that will contain the data. + Begin loading from url and return the [page:ImageBitmap image] object that + will contain the data.

[method:this setOptions]( [param:Object options] )

- Sets the options object for [link:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap createImageBitmap]. + Sets the options object for + [link:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap createImageBitmap].

Source

diff --git a/docs/api/en/loaders/ImageLoader.html b/docs/api/en/loaders/ImageLoader.html index 6eb1b1306e9f41..99ee62c78e9b3b 100644 --- a/docs/api/en/loaders/ImageLoader.html +++ b/docs/api/en/loaders/ImageLoader.html @@ -12,8 +12,7 @@

[name]

- A loader for loading an [page:Image]. - This is used internally by the + A loader for loading an [page:Image]. This is used internally by the [page:CubeTextureLoader], [page:ObjectLoader] and [page:TextureLoader].

@@ -47,8 +46,9 @@

Code Example

- Please note three.js r84 dropped support for ImageLoader progress events. For an ImageLoader - that supports progress events, see [link:https://github.com/mrdoob/three.js/issues/10439#issuecomment-275785639 this thread]. + Please note three.js r84 dropped support for ImageLoader progress events. + For an ImageLoader that supports progress events, see + [link:https://github.com/mrdoob/three.js/issues/10439#issuecomment-275785639 this thread].

Examples

@@ -62,9 +62,10 @@

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + Creates a new [name].

Properties

@@ -73,16 +74,21 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:HTMLImageElement load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:HTMLImageElement load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:Image image].
- [page:Function onProgress] (optional) — This callback function is currently not supported.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:Function onLoad] — Will be called when load completes. The argument + will be the loaded [page:Image image].
+ [page:Function onProgress] (optional) — This callback function is + currently not supported.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and return the [page:Image image] object that will contain the data. + Begin loading from url and return the [page:Image image] object that will + contain the data.

Source

diff --git a/docs/api/en/loaders/Loader.html b/docs/api/en/loaders/Loader.html index 27daf902b83d01..3df6c1db7b3277 100644 --- a/docs/api/en/loaders/Loader.html +++ b/docs/api/en/loaders/Loader.html @@ -11,106 +11,122 @@

[name]

Base class for implementing loaders.

-

Constructor

-

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. -

-

- Creates a new [name]. + [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- +

Creates a new [name].

Properties

[property:String crossOrigin]

- The crossOrigin string to implement CORS for loading the url from a different domain that allows CORS. - Default is `anonymous`. + The crossOrigin string to implement CORS for loading the url from a + different domain that allows CORS. Default is `anonymous`.

[property:Boolean withCredentials]

- Whether the XMLHttpRequest uses credentials. See [page:.setWithCredentials]. - Default is `false`. + Whether the XMLHttpRequest uses credentials. See + [page:.setWithCredentials]. Default is `false`.

[property:LoadingManager manager]

- The [page:LoadingManager loadingManager] the loader is using. Default is [page:DefaultLoadingManager]. + The [page:LoadingManager loadingManager] the loader is using. Default is + [page:DefaultLoadingManager].

[property:String path]

- The base path from which the asset will be loaded. - Default is the empty string. + The base path from which the asset will be loaded. Default is the empty + string.

[property:String resourcePath]

- The base path from which additional resources like textures will be loaded. - Default is the empty string. + The base path from which additional resources like textures will be + loaded. Default is the empty string.

[property:Object requestHeader]

- The [link:https://developer.mozilla.org/en-US/docs/Glossary/Request_header request header] used in HTTP request. See [page:.setRequestHeader]. Default is empty object. + The [link:https://developer.mozilla.org/en-US/docs/Glossary/Request_header request header] + used in HTTP request. See [page:.setRequestHeader]. + Default is empty object.

Methods

[method:undefined load]()

- This method needs to be implement by all concrete loaders. It holds the logic for loading the asset from the backend. + This method needs to be implement by all concrete loaders. It holds the + logic for loading the asset from the backend.

-

[method:Promise loadAsync]( [param:String url], [param:Function onProgress] )

+

+ [method:Promise loadAsync]( [param:String url], [param:Function onProgress] ) +

- [page:String url] — A string containing the path/URL of the file to be loaded.
- [page:Function onProgress] (optional) — A function to be called while the loading is in progress. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
+ [page:String url] — A string containing the path/URL of the file to be + loaded.
+ [page:Function onProgress] (optional) — A function to be called while the + loading is in progress. The argument will be the ProgressEvent instance, + which contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.

- This method is equivalent to [page:.load], but returns a [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise Promise]. + This method is equivalent to [page:.load], but returns a + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise Promise].

- [page:Function onLoad] is handled by [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve Promise.resolve] and [page:Function onError] is handled by [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject Promise.reject]. + [page:Function onLoad] is handled by + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve Promise.resolve] + and [page:Function onError] is handled by + [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject Promise.reject].

[method:undefined parse]()

- This method needs to be implement by all concrete loaders. It holds the logic for parsing the asset into three.js entities. + This method needs to be implement by all concrete loaders. It holds the + logic for parsing the asset into three.js entities.

[method:this setCrossOrigin]( [param:String crossOrigin] )

- [page:String crossOrigin] — The crossOrigin string to implement CORS for loading the url from a different domain that allows CORS. + [page:String crossOrigin] — The crossOrigin string to implement CORS for + loading the url from a different domain that allows CORS.

[method:this setWithCredentials]( [param:Boolean value] )

- Whether the XMLHttpRequest uses credentials such as cookies, authorization headers or - TLS client certificates. See [link:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials XMLHttpRequest.withCredentials].
- Note that this has no effect if you are loading files locally or from the same domain. + Whether the XMLHttpRequest uses credentials such as cookies, authorization + headers or TLS client certificates. See + [link:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials XMLHttpRequest.withCredentials].
+ Note that this has no effect if you are loading files locally or from the + same domain.

[method:this setPath]( [param:String path] )

-

- [page:String path] — Set the base path for the asset. -

+

[page:String path] — Set the base path for the asset.

[method:this setResourcePath]( [param:String resourcePath] )

- [page:String resourcePath] — Set the base path for dependent resources like textures. + [page:String resourcePath] — Set the base path for dependent resources + like textures.

[method:this setRequestHeader]( [param:Object requestHeader] )

- [page:Object requestHeader] - key: The name of the header whose value is to be set. value: The value to set as the body of the header.

+ [page:Object requestHeader] - key: The name of the header whose value is + to be set. value: The value to set as the body of the header.

- Set the [link:https://developer.mozilla.org/en-US/docs/Glossary/Request_header request header] used in HTTP request. + Set the + [link:https://developer.mozilla.org/en-US/docs/Glossary/Request_header request header] used in HTTP request.

Source

diff --git a/docs/api/en/loaders/LoaderUtils.html b/docs/api/en/loaders/LoaderUtils.html index 08dd47d5b344dc..1d23f4921a447c 100644 --- a/docs/api/en/loaders/LoaderUtils.html +++ b/docs/api/en/loaders/LoaderUtils.html @@ -14,34 +14,29 @@

[name]

Functions

[method:String decodeText]( [param:TypedArray array] )

+

[page:TypedArray array] — A stream of bytes as a typed array.

- [page:TypedArray array] — A stream of bytes as a typed array. -

-

- The function takes a stream of bytes as input and returns a string representation. + The function takes a stream of bytes as input and returns a string + representation.

[method:String extractUrlBase]( [param:String url] )

-

- [page:String url] — The url to extract the base url from. -

-

- Extract the base from the URL. -

- +

[page:String url] — The url to extract the base url from.

+

Extract the base from the URL.

-

[method:String resolveURL]( [param:String url], [param:String path] )

+

+ [method:String resolveURL]( [param:String url], [param:String path] ) +

- [page:String url] — The absolute or relative url resolve. - [page:String path] — The base path for relative urls to be resolved against. + [page:String url] — The absolute or relative url resolve. [page:String path] — The base path for relative urls to be resolved against.

- Resolves relative urls against the given path. Absolute paths, data urls, and blob urls will be returned as is. Invalid urls will return an empty string. + Resolves relative urls against the given path. Absolute paths, data urls, + and blob urls will be returned as is. Invalid urls will return an empty + string.

-

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/loaders/MaterialLoader.html b/docs/api/en/loaders/MaterialLoader.html index 55aef6714ba851..8ff6173ca1f907 100644 --- a/docs/api/en/loaders/MaterialLoader.html +++ b/docs/api/en/loaders/MaterialLoader.html @@ -12,8 +12,8 @@

[name]

- A loader for loading a [page:Material] in JSON format. - This uses the [page:FileLoader] internally for loading files. + A loader for loading a [page:Material] in JSON format. This uses the + [page:FileLoader] internally for loading files.

Code Example

@@ -44,45 +44,57 @@

Code Example

);
-

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ Creates a new [name].

Properties

See the base [page:Loader] class for common properties.

[property:Object textures]

-

Object holding any textures used by the material. See [page:.setTextures].

+

+ Object holding any textures used by the material. See [page:.setTextures]. +

Methods

See the base [page:Loader] class for common methods.

-

[method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:Material].
- [page:Function onProgress] (optional) — Will be called while load progresses. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] (optional) — Will be called when load errors.

- - Begin loading from url. + [page:Function onLoad] — Will be called when load completes. The argument + will be the loaded [page:Material].
+ [page:Function onProgress] (optional) — Will be called while load + progresses. The argument will be the ProgressEvent instance, which + contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.
+ [page:Function onError] (optional) — Will be called when load errors.

+ + Begin loading from url.

[method:Material parse]( [param:Object json] )

- [page:Object json] — The json object containing the parameters of the Material.

+ [page:Object json] — The json object containing the parameters of the + Material.

- Parse a `JSON` structure and create a new [page:Material] of the type [page:String json.type] with parameters defined in the json object. + Parse a `JSON` structure and create a new [page:Material] of the type + [page:String json.type] with parameters defined in the json object.

[method:this setTextures]( [param:Object textures] )

- [page:Object textures] — object containing any textures used by the material. + [page:Object textures] — object containing any textures used by the + material.

Source

diff --git a/docs/api/en/loaders/ObjectLoader.html b/docs/api/en/loaders/ObjectLoader.html index daad3a79cd8471..85276489035e2c 100644 --- a/docs/api/en/loaders/ObjectLoader.html +++ b/docs/api/en/loaders/ObjectLoader.html @@ -12,8 +12,8 @@

[name]

- A loader for loading a JSON resource in the [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

- + A loader for loading a JSON resource in the + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

This uses the [page:FileLoader] internally for loading files.

@@ -53,17 +53,15 @@

Code Example

Examples

-

- [example:webgl_materials_lightmap WebGL / materials / lightmap] -

+

[example:webgl_materials_lightmap WebGL / materials / lightmap]

Constructor

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- - Creates a new [name]. + [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ Creates a new [name].

Properties

@@ -72,75 +70,91 @@

Properties

Methods

See the base [page:Loader] class for common methods.

-

[method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:Object3D object].
- [page:Function onProgress] (optional) — Will be called while load progresses. The argument will be the ProgressEvent instance, which contains .[page:Boolean lengthComputable], .[page:Integer total] and .[page:Integer loaded]. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
- [page:Function onError] (optional) — Will be called when load errors.
+ [page:Function onLoad] — Will be called when load completes. The argument + will be the loaded [page:Object3D object].
+ [page:Function onProgress] (optional) — Will be called while load + progresses. The argument will be the ProgressEvent instance, which + contains .[page:Boolean lengthComputable], .[page:Integer total] and + .[page:Integer loaded]. If the server does not set the Content-Length + header; .[page:Integer total] will be 0.
+ [page:Function onError] (optional) — Will be called when load errors.

- Begin loading from url and call onLoad with the parsed response content. + Begin loading from url and call onLoad with the parsed response content.

- -

[method:Object3D parse]( [param:Object json], [param:Function onLoad] )

+

+ [method:Object3D parse]( [param:Object json], [param:Function onLoad] ) +

- [page:Object json] — required. The JSON source to parse.

- [page:Function onLoad] — Will be called when parsed completes. The argument will be the parsed [page:Object3D object].

- - Parse a `JSON` structure and return a three.js object. - This is used internally by [page:.load]() but can also be used directly to parse a previously loaded JSON structure. + [page:Object json] — required. The JSON source to parse.

+ [page:Function onLoad] — Will be called when parsed completes. The + argument will be the parsed [page:Object3D object].

+ Parse a `JSON` structure and return a three.js object. This is used + internally by [page:.load]() but can also be used directly to parse a + previously loaded JSON structure.

[method:Object parseGeometries]( [param:Object json] )

- [page:Object json] — required. The JSON source to parse.

+ [page:Object json] — required. The JSON source to parse.

- This is used by [page:.parse]() to parse any [page:BufferGeometry geometries] in the JSON structure. + This is used by [page:.parse]() to parse any [page:BufferGeometry geometries] in the JSON structure.

[method:Object parseMaterials]( [param:Object json] )

- [page:Object json] — required. The JSON source to parse.

+ [page:Object json] — required. The JSON source to parse.

- This is used by [page:.parse]() to parse any materials in the JSON structure using [page:MaterialLoader]. + This is used by [page:.parse]() to parse any materials in the JSON + structure using [page:MaterialLoader].

[method:Object parseAnimations]( [param:Object json] )

- [page:Object json] — required. The JSON source to parse.

+ [page:Object json] — required. The JSON source to parse.

- This is used by [page:.parse]() to parse any animations in the JSON structure, using [page:AnimationClip.parse](). + This is used by [page:.parse]() to parse any animations in the JSON + structure, using [page:AnimationClip.parse]().

[method:Object parseImages]( [param:Object json] )

- [page:Object json] — required. The JSON source to parse.

+ [page:Object json] — required. The JSON source to parse.

- This is used by [page:.parse]() to parse any images in the JSON structure, using [page:ImageLoader]. + This is used by [page:.parse]() to parse any images in the JSON structure, + using [page:ImageLoader].

[method:Object parseTextures]( [param:Object json] )

- [page:Object json] — required. The JSON source to parse.

+ [page:Object json] — required. The JSON source to parse.

- This is used by [page:.parse]() to parse any textures in the JSON structure. + This is used by [page:.parse]() to parse any textures in the JSON + structure.

-

[method:Object3D parseObject]( [param:Object json], [param:BufferGeometry geometries], [param:Material materials], [param:AnimationClip animations] )

+

+ [method:Object3D parseObject]( [param:Object json], [param:BufferGeometry geometries], [param:Material materials], [param:AnimationClip animations] ) +

- [page:Object json] — required. The JSON source to parse.
- [page:BufferGeometry geometries] — required. The geometries of the JSON.
- [page:Material materials] — required. The materials of the JSON.
- [page:AnimationClip animations] — required. The animations of the JSON.

- - This is used by [page:.parse]() to parse any 3D objects in the JSON structure. + [page:Object json] — required. The JSON source to parse.
+ [page:BufferGeometry geometries] — required. The geometries of the + JSON.
+ [page:Material materials] — required. The materials of the JSON.
+ [page:AnimationClip animations] — required. The animations of the JSON.

+ + This is used by [page:.parse]() to parse any 3D objects in the JSON + structure.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/loaders/TextureLoader.html b/docs/api/en/loaders/TextureLoader.html index 3bd6c74c0a0917..1d2cea076cbae2 100644 --- a/docs/api/en/loaders/TextureLoader.html +++ b/docs/api/en/loaders/TextureLoader.html @@ -12,17 +12,17 @@

[name]

- Class for loading a [page:Texture texture]. - This uses the [page:ImageLoader] internally for loading files. + Class for loading a [page:Texture texture]. This uses the + [page:ImageLoader] internally for loading files.

Code Example

- const texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' ); - - // immediately use the texture for material creation - const material = new THREE.MeshBasicMaterial( { map: texture } ); + const texture = new THREE.TextureLoader().load('textures/land_ocean_ice_cloud_2048.jpg' ); + // immediately use the texture for material creation + + const material = new THREE.MeshBasicMaterial( { map:texture } );

Code Example with Callbacks

@@ -55,45 +55,48 @@

Code Example with Callbacks

- Please note three.js r84 dropped support for TextureLoader progress events. For a TextureLoader that supports progress events, see [link:https://github.com/mrdoob/three.js/issues/10439#issuecomment-293260145 this thread]. + Please note three.js r84 dropped support for TextureLoader progress + events. For a TextureLoader that supports progress events, see + [link:https://github.com/mrdoob/three.js/issues/10439#issuecomment-293260145 this thread].

Examples

- -

- [example:webgl_geometry_cube geometry / cube] -

+

[example:webgl_geometry_cube geometry / cube]

Constructor

-

[name]( [param:LoadingManager manager] )

- [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

+ [page:LoadingManager manager] — The [page:LoadingManager loadingManager] + for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

- Creates a new [name]. + Creates a new [name].

-

Properties

See the base [page:Loader] class for common properties.

Methods

See the base [page:Loader] class for common methods.

-

[method:Texture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [method:Texture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] ) +

- [page:String url] — the path or URL to the file. This can also be a + [page:String url] — the path or URL to the file. This can also be a [link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].
- [page:Function onLoad] (optional) — Will be called when load completes. The argument will be the loaded [page:Texture texture].
- [page:Function onProgress] (optional) — This callback function is currently not supported.
- [page:Function onError] (optional) — Will be called when load errors.

- - Begin loading from the given URL and pass the fully loaded [page:Texture texture] to onLoad. The method also returns a new texture object which can directly be used for material creation. - If you do it this way, the texture may pop up in your scene once the respective loading process is finished. + [page:Function onLoad] (optional) — Will be called when load completes. + The argument will be the loaded [page:Texture texture].
+ [page:Function onProgress] (optional) — This callback function is + currently not supported.
+ [page:Function onError] (optional) — Will be called when load errors.

+ + Begin loading from the given URL and pass the fully loaded [page:Texture texture] + to onLoad. The method also returns a new texture object which can + directly be used for material creation. If you do it this way, the texture + may pop up in your scene once the respective loading process is finished.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/loaders/managers/DefaultLoadingManager.html b/docs/api/en/loaders/managers/DefaultLoadingManager.html index 882ee8f04b3bdd..717eeead3c3fcd 100644 --- a/docs/api/en/loaders/managers/DefaultLoadingManager.html +++ b/docs/api/en/loaders/managers/DefaultLoadingManager.html @@ -9,62 +9,58 @@

[name]

-

A global instance of the [page:LoadingManager LoadingManager], used by most loaders - when no custom manager has been specified.

+

+ A global instance of the [page:LoadingManager LoadingManager], used by + most loaders when no custom manager has been specified.

- This will be sufficient for most purposes, however there may be times when you desire separate loading managers - for say, textures and models. + This will be sufficient for most purposes, however there may be times when + you desire separate loading managers for say, textures and models.

Code Example

- You can optionally set the [page:LoadingManager.onStart onStart], [page:LoadingManager.onLoad onLoad], - [page:LoadingManager.onProgress onProgress], [page:LoadingManager.onStart onError] functions for the manager. - These will then apply to any loaders using the DefaultLoadingManager.

- - Note that these shouldn't be confused with the similarly named functions of individual loaders, - as they are intended for displaying information about the overall status of loading, - rather than dealing with the data that has been loaded. + You can optionally set the [page:LoadingManager.onStart onStart], + [page:LoadingManager.onLoad onLoad], [page:LoadingManager.onProgress onProgress], + [page:LoadingManager.onStart onError] functions for the + manager. These will then apply to any loaders using the + DefaultLoadingManager.

+ + Note that these shouldn't be confused with the similarly named functions + of individual loaders, as they are intended for displaying information + about the overall status of loading, rather than dealing with the data + that has been loaded.

THREE.DefaultLoadingManager.onStart = function ( url, itemsLoaded, itemsTotal ) { - console.log( 'Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); - }; THREE.DefaultLoadingManager.onLoad = function ( ) { - console.log( 'Loading Complete!'); - }; - THREE.DefaultLoadingManager.onProgress = function ( url, itemsLoaded, itemsTotal ) { - console.log( 'Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); - }; THREE.DefaultLoadingManager.onError = function ( url ) { - console.log( 'There was an error loading ' + url ); - }; -

Properties

- -

See the [page:LoadingManager LoadingManager] page for details of properties.

+

+ See the [page:LoadingManager LoadingManager] page for details of + properties. +

Methods

- -

See the [page:LoadingManager LoadingManager] page for details of methods.

+

+ See the [page:LoadingManager LoadingManager] page for details of methods. +

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/loaders/LoadingManager.js src/loaders/LoadingManager.js]

diff --git a/docs/api/en/loaders/managers/LoadingManager.html b/docs/api/en/loaders/managers/LoadingManager.html index d48363a12b836d..767f1dbc4a56b5 100644 --- a/docs/api/en/loaders/managers/LoadingManager.html +++ b/docs/api/en/loaders/managers/LoadingManager.html @@ -10,12 +10,13 @@

[name]

- Handles and keeps track of loaded and pending data. A default global instance of this class - is created and used by loaders if not supplied manually - see [page:DefaultLoadingManager].

- - In general that should be sufficient, however there are times when it can be useful to have separate loaders - - for example if you want to show separate loading bars for objects and textures. + Handles and keeps track of loaded and pending data. A default global + instance of this class is created and used by loaders if not supplied + manually - see [page:DefaultLoadingManager].

+ In general that should be sufficient, however there are times when it can + be useful to have separate loaders - for example if you want to show + separate loading bars for objects and textures.

Code Example

@@ -28,35 +29,24 @@

Code Example

const manager = new THREE.LoadingManager(); manager.onStart = function ( url, itemsLoaded, itemsTotal ) { - console.log( 'Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); - }; manager.onLoad = function ( ) { - console.log( 'Loading complete!'); - }; - manager.onProgress = function ( url, itemsLoaded, itemsTotal ) { - console.log( 'Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); - }; manager.onError = function ( url ) { - console.log( 'There was an error loading ' + url ); - }; const loader = new THREE.OBJLoader( manager ); loader.load( 'file.obj', function ( object ) { - // - } ); @@ -78,9 +68,7 @@

Code Example

manager.setURLModifier( ( url ) => { url = URL.createObjectURL( blobs[ url ] ); - objectURLs.push( url ); - return url; } ); @@ -90,7 +78,6 @@

Code Example

loader.load( 'fish.gltf', (gltf) => { scene.add( gltf.scene ); - objectURLs.forEach( ( url ) => URL.revokeObjectURL( url ) ); }); @@ -100,28 +87,30 @@

Examples

[example:webgl_loader_obj WebGL / loader / obj]
- [example:webgl_materials_physical_reflectivity WebGL / materials / physical / reflectivity]
[example:webgl_postprocessing_outline WebGL / postprocesing / outline]

Constructor

- -

[name]( [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

+

+ [name]( [param:Function onLoad], [param:Function onProgress], + [param:Function onError] ) +

- [page:Function onLoad] — (optional) this function will be called when all loaders are done.
- [page:Function onProgress] — (optional) this function will be called when an item is complete.
- [page:Function onError] — (optional) this function will be called a loader encounters errors.
+ [page:Function onLoad] — (optional) this function will be called when all + loaders are done.
+ [page:Function onProgress] — (optional) this function will be called when + an item is complete.
+ [page:Function onError] — (optional) this function will be called a loader + encounters errors.
- Creates a new [name]. + Creates a new [name].

-

Properties

[property:Function onStart]

- This function will be called when loading starts. - The arguments are:
+ This function will be called when loading starts. The arguments are:
[page:String url] — The url of the item just loaded.
[page:Integer itemsLoaded] — the number of items already loaded so far.
[page:Integer itemsTotal] — the total amount of items to be loaded.

@@ -131,19 +120,19 @@

[property:Function onStart]

[property:Function onLoad]

- This function will be called when all loading is completed. By default this is undefined, - unless passed in the constructor. + This function will be called when all loading is completed. By default + this is undefined, unless passed in the constructor.

[property:Function onProgress]

- This function will be called when an item is complete. - The arguments are:
- [page:String url] — The url of the item just loaded.
- [page:Integer itemsLoaded] — the number of items already loaded so far.
- [page:Integer itemsTotal] — the total amount of items to be loaded.

+ This function will be called when an item is complete. The arguments + are:
+ [page:String url] — The url of the item just loaded.
+ [page:Integer itemsLoaded] — the number of items already loaded so far.
+ [page:Integer itemsTotal] — the total amount of items to be loaded.

- By default this is undefined, unless passed in the constructor. + By default this is undefined, unless passed in the constructor.

[property:Function onError]

@@ -154,80 +143,88 @@

[property:Function onError]

By default this is undefined, unless passed in the constructor.

-

Methods

-

[method:this addHandler]( [param:Object regex], [param:Loader loader] )

+

+ [method:this addHandler]( [param:Object regex], [param:Loader loader] ) +

- [page:Object regex] — A regular expression.
- [page:Loader loader] — The loader. + [page:Object regex] — A regular expression.
+ [page:Loader loader] — The loader. +

+

- Registers a loader with the given regular expression. Can be used to define what loader should be used in - order to load specific files. A typical use case is to overwrite the default loader for textures. + Registers a loader with the given regular expression. Can be used to + define what loader should be used in order to load specific files. A + typical use case is to overwrite the default loader for textures.

-// add handler for TGA textures +// add handler for TGA textures manager.addHandler( /\.tga$/i, new TGALoader() );

[method:Loader getHandler]( [param:String file] )

+

[page:String file] — The file path.

+

- [page:String file] — The file path. -

- Can be used to retrieve the registered loader for the given file path. + Can be used to retrieve the registered loader for the given file path.

[method:this removeHandler]( [param:Object regex] )

-

- [page:Object regex] — A regular expression. -

- Removes the loader for the given regular expression. -

+

[page:Object regex] — A regular expression.

+ +

Removes the loader for the given regular expression.

[method:String resolveURL]( [param:String url] )

- [page:String url] — the url to load

+ [page:String url] — the url to load

- Given a URL, uses the URL modifier callback (if any) and returns a resolved URL. If no - URL modifier is set, returns the original URL. + Given a URL, uses the URL modifier callback (if any) and returns a + resolved URL. If no URL modifier is set, returns the original URL.

[method:this setURLModifier]( [param:Function callback] )

- [page:Function callback] — URL modifier callback. Called with [page:String url] argument, and - must return [page:String resolvedURL].

+ [page:Function callback] — URL modifier callback. Called with [page:String url] argument, + and must return [page:String resolvedURL].

- If provided, the callback will be passed each resource URL before a request is sent. The - callback may return the original URL, or a new URL to override loading behavior. This - behavior can be used to load assets from .ZIP files, drag-and-drop APIs, and Data URIs. + If provided, the callback will be passed each resource URL before a + request is sent. The callback may return the original URL, or a new URL to + override loading behavior. This behavior can be used to load assets from + .ZIP files, drag-and-drop APIs, and Data URIs.


- Note: The following methods are designed to be called internally by loaders. You shouldn't call - them directly. + + Note: The following methods are designed to be called internally by + loaders. You shouldn't call them directly. +

[method:undefined itemStart]( [param:String url] )

- [page:String url] — the url to load

+ [page:String url] — the url to load

- This should be called by any loader using the manager when the loader starts loading an url. + This should be called by any loader using the manager when the loader + starts loading an url.

[method:undefined itemEnd]( [param:String url] )

- [page:String url] — the loaded url

+ [page:String url] — the loaded url

- This should be called by any loader using the manager when the loader ended loading an url. + This should be called by any loader using the manager when the loader + ended loading an url.

[method:undefined itemError]( [param:String url] )

- [page:String url] — the loaded url

+ [page:String url] — the loaded url

- This should be called by any loader using the manager when the loader errors loading an url. + This should be called by any loader using the manager when the loader + errors loading an url.

Source

diff --git a/docs/api/en/materials/LineBasicMaterial.html b/docs/api/en/materials/LineBasicMaterial.html index dc910698ac16eb..afcb3e22638f99 100644 --- a/docs/api/en/materials/LineBasicMaterial.html +++ b/docs/api/en/materials/LineBasicMaterial.html @@ -14,7 +14,6 @@

[name]

A material for drawing wireframe-style geometries.

Code Example

- const material = new THREE.LineBasicMaterial( { color: 0xffffff, @@ -25,7 +24,6 @@

Code Example

Examples

-

[example:webgl_buffergeometry_drawrange WebGL / buffergeometry / drawrange]
[example:webgl_buffergeometry_lines WebGL / buffergeometry / lines]
@@ -38,21 +36,22 @@

Examples

[example:webgl_interactive_voxelpainter WebGL / interactive / voxelpainter]
[example:webgl_lines_colors WebGL / lines / colors]
[example:webgl_lines_dashed WebGL / lines / dashed]
- [example:webgl_lines_sphere WebGL / lines / sphere]
[example:webgl_materials WebGL / materials]
[example:physics_ammo_rope physics / ammo / rope]

Constructor

-

[name]( [param:Object parameters] )

- [page:Object parameters] - (optional) an object with one or more properties defining the material's appearance. - Any property of the material (including any property inherited from [page:Material]) can be passed in here.

- - The exception is the property [page:Hexadecimal color], which can be passed in as a hexadecimal - string and is `0xffffff` (white) by default. [page:Color.set]( color ) is called internally. + [page:Object parameters] - (optional) an object with one or more + properties defining the material's appearance. Any property of the + material (including any property inherited from [page:Material]) can be + passed in here.

+ + The exception is the property [page:Hexadecimal color], which can be + passed in as a hexadecimal string and is `0xffffff` (white) by default. + [page:Color.set]( color ) is called internally.

Properties

@@ -68,28 +67,35 @@

[property:Float linewidth]

Controls line thickness. Default is `1`.

- Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] - with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will - always be 1 regardless of the set value. + Due to limitations of the + [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + with the [page:WebGLRenderer WebGL] renderer on most + platforms linewidth will always be 1 regardless of the set value.

[property:String linecap]

- Define appearance of line ends. Possible values are 'butt', 'round' and 'square'. - Default is 'round'.

+ Define appearance of line ends. Possible values are 'butt', 'round' and + 'square'. Default is 'round'.

- This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] + This corresponds to the + [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] property and it is ignored by the [page:WebGLRenderer WebGL] renderer.

[property:String linejoin]

- Define appearance of line joints. Possible values are 'round', 'bevel' and 'miter'. Default is 'round'.

+ Define appearance of line joints. Possible values are 'round', 'bevel' and + 'miter'. Default is 'round'.

- This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] + This corresponds to the + [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] property and it is ignored by the [page:WebGLRenderer WebGL] renderer.

+

[property:Texture map]

+

Sets the color of the lines using data from a [page:Texture].

+

Methods

See the base [page:Material] class for common methods.

diff --git a/docs/api/en/materials/LineDashedMaterial.html b/docs/api/en/materials/LineDashedMaterial.html index c87247e2749d25..3a0741fde92e0b 100644 --- a/docs/api/en/materials/LineDashedMaterial.html +++ b/docs/api/en/materials/LineDashedMaterial.html @@ -11,7 +11,9 @@

[name]

-

A material for drawing wireframe-style geometries with dashed lines.

+

+ A material for drawing wireframe-style geometries with dashed lines. +

Code Example

@@ -27,34 +29,32 @@

Code Example

Examples

-

- [example:webgl_lines_dashed WebGL / lines / dashed]
-

+

[example:webgl_lines_dashed WebGL / lines / dashed]

Constructor

-

[name]( [param:Object parameters] )

- [page:Object parameters] - (optional) an object with one or more properties defining the material's appearance. - Any property of the material (including any property inherited from [page:LineBasicMaterial]) can be passed in here. + [page:Object parameters] - (optional) an object with one or more + properties defining the material's appearance. Any property of the + material (including any property inherited from [page:LineBasicMaterial]) + can be passed in here.

-

Properties

See the base [page:LineBasicMaterial] class for common properties.

[property:number dashSize]

-

The size of the dash. This is both the gap with the stroke. Default is `3`.

+

+ The size of the dash. This is both the gap with the stroke. Default is + `3`. +

[property:number gapSize]

The size of the gap. Default is `1`.

[property:Boolean isLineDashedMaterial]

-

- Read-only flag to check if a given object is of type [name]. -

- +

Read-only flag to check if a given object is of type [name].

[property:number scale]

The scale of the dashed part of a line. Default is `1`.

@@ -63,7 +63,6 @@

Methods

See the base [page:LineBasicMaterial] class for common methods.

Source

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/en/materials/Material.html b/docs/api/en/materials/Material.html index bd18a541b15c02..5b43f8d5102a5c 100644 --- a/docs/api/en/materials/Material.html +++ b/docs/api/en/materials/Material.html @@ -10,201 +10,244 @@

[name]

- Abstract base class for materials.

+ Abstract base class for materials.

- Materials describe the appearance of [page:Object objects]. - They are defined in a (mostly) renderer-independent way, so you don't have to - rewrite materials if you decide to use a different renderer.

+ Materials describe the appearance of [page:Object objects]. They are + defined in a (mostly) renderer-independent way, so you don't have to + rewrite materials if you decide to use a different renderer.

- The following properties and methods are inherited by all other material types - (although they may have different defaults). + The following properties and methods are inherited by all other material + types (although they may have different defaults).

Constructor

-

[name]()

This creates a generic material.

-

Properties

[property:Float alphaTest]

- Sets the alpha value to be used when running an alpha test. - The material will not be rendered if the opacity is lower than this value. - Default is `0`. + Sets the alpha value to be used when running an alpha test. The material + will not be rendered if the opacity is lower than this value. Default is + `0`.

[property:Boolean alphaToCoverage]

- Enables alpha to coverage. Can only be used with MSAA-enabled contexts (meaning when the renderer was created with `antialias` parameter set to `true`). - Default is `false`. + Enables alpha to coverage. Can only be used with MSAA-enabled contexts + (meaning when the renderer was created with `antialias` parameter set to + `true`). Default is `false`.

[property:Integer blendDst]

- Blending destination. Default is [page:CustomBlendingEquation OneMinusSrcAlphaFactor]. - See the destination factors [page:CustomBlendingEquation constants] for all possible values.
- The material's [page:Constant blending] must be set to [page:Materials CustomBlending] for this to have any effect. + Blending destination. Default is [page:CustomBlendingEquation OneMinusSrcAlphaFactor]. + See the destination factors [page:CustomBlendingEquation constants] for all possible values.
+ The material's [page:Constant blending] must be set to [page:Materials CustomBlending] + for this to have any effect.

[property:Integer blendDstAlpha]

-

The transparency of the [page:.blendDst]. Uses [page:.blendDst] value if null. Default is `null`.

+

+ The transparency of the [page:.blendDst]. Uses [page:.blendDst] value if + null. Default is `null`. +

[property:Integer blendEquation]

- Blending equation to use when applying blending. Default is [page:CustomBlendingEquation AddEquation]. - See the blending equation [page:CustomBlendingEquation constants] for all possible values.
- The material's [page:Constant blending] must be set to [page:Materials CustomBlending] for this to have any effect. + Blending equation to use when applying blending. Default is + [page:CustomBlendingEquation AddEquation]. See the blending equation + [page:CustomBlendingEquation constants] for all possible values.
+ The material's [page:Constant blending] must be set to [page:Materials CustomBlending] + for this to have any effect.

[property:Integer blendEquationAlpha]

-

The transparency of the [page:.blendEquation]. Uses [page:.blendEquation] value if null. Default is `null`.

+

+ The transparency of the [page:.blendEquation]. Uses [page:.blendEquation] + value if null. Default is `null`. +

[property:Blending blending]

- Which blending to use when displaying objects with this material.
- This must be set to [page:Materials CustomBlending] to use custom [page:Constant blendSrc], [page:Constant blendDst] or [page:Constant blendEquation].
- See the blending mode [page:Materials constants] for all possible values. Default is [page:Materials NormalBlending]. + Which blending to use when displaying objects with this material.
+ This must be set to [page:Materials CustomBlending] to use custom + [page:Constant blendSrc], [page:Constant blendDst] or [page:Constant blendEquation].
+ See the blending mode [page:Materials constants] for all possible values. + Default is [page:Materials NormalBlending].

[property:Integer blendSrc]

- Blending source. Default is [page:CustomBlendingEquation SrcAlphaFactor]. - See the source factors [page:CustomBlendingEquation constants] for all possible values.
- The material's [page:Constant blending] must be set to [page:Materials CustomBlending] for this to have any effect. + Blending source. Default is [page:CustomBlendingEquation SrcAlphaFactor]. + See the source factors [page:CustomBlendingEquation constants] for all + possible values.
+ The material's [page:Constant blending] must be set to [page:Materials CustomBlending] + for this to have any effect.

[property:Integer blendSrcAlpha]

-

The transparency of the [page:.blendSrc]. Uses [page:.blendSrc] value if null. Default is `null`.

+

+ The transparency of the [page:.blendSrc]. Uses [page:.blendSrc] value if + null. Default is `null`. +

[property:Boolean clipIntersection]

- Changes the behavior of clipping planes so that only their intersection is clipped, rather than their union. - Default is `false`. + Changes the behavior of clipping planes so that only their intersection is + clipped, rather than their union. Default is `false`.

[property:Array clippingPlanes]

- User-defined clipping planes specified as THREE.Plane objects in world space. - These planes apply to the objects this material is attached to. - Points in space whose signed distance to the plane is negative are clipped (not rendered). - This requires [page:WebGLRenderer.localClippingEnabled] to be `true`. - See the [example:webgl_clipping_intersection WebGL / clipping /intersection] example. - Default is `null`. + User-defined clipping planes specified as THREE.Plane objects in world + space. These planes apply to the objects this material is attached to. + Points in space whose signed distance to the plane is negative are clipped + (not rendered). This requires [page:WebGLRenderer.localClippingEnabled] to + be `true`. See the [example:webgl_clipping_intersection WebGL / clipping /intersection] example. Default is `null`.

[property:Boolean clipShadows]

- Defines whether to clip shadows according to the clipping planes specified on this material. Default is `false`. + Defines whether to clip shadows according to the clipping planes specified + on this material. Default is `false`.

[property:Boolean colorWrite]

- Whether to render the material's color. - This can be used in conjunction with a mesh's [page:Integer renderOrder] property to create invisible objects that occlude other objects. Default is `true`. + Whether to render the material's color. This can be used in conjunction + with a mesh's [page:Integer renderOrder] property to create invisible + objects that occlude other objects. Default is `true`.

[property:Object defines]

- Custom defines to be injected into the shader. These are passed in form of an object literal, with key/value pairs. `{ MY_CUSTOM_DEFINE: '' , PI2: Math.PI * 2 }`. The pairs are defined in both vertex and fragment shaders. Default is `undefined`. + Custom defines to be injected into the shader. These are passed in form of + an object literal, with key/value pairs. `{ MY_CUSTOM_DEFINE: '' , PI2: + Math.PI * 2 }`. The pairs are defined in both vertex and fragment shaders. + Default is `undefined`.

[property:Integer depthFunc]

- Which depth function to use. Default is [page:Materials LessEqualDepth]. See the depth mode [page:Materials constants] for all possible values. + Which depth function to use. Default is [page:Materials LessEqualDepth]. + See the depth mode [page:Materials constants] for all possible values.

[property:Boolean depthTest]

- Whether to have depth test enabled when rendering this material. Default is `true`. + Whether to have depth test enabled when rendering this material. Default + is `true`.

[property:Boolean depthWrite]

- Whether rendering this material has any effect on the depth buffer. Default is `true`.

+ Whether rendering this material has any effect on the depth buffer. + Default is `true`.

- When drawing 2D overlays it can be useful to disable the depth writing in order to layer several things together without creating z-index artifacts. + When drawing 2D overlays it can be useful to disable the depth writing in + order to layer several things together without creating z-index artifacts.

[property:Boolean forceSinglePass]

- Whether double-sided, transparent objects should be rendered with a single pass or not. Default is `false`.

+ Whether double-sided, transparent objects should be rendered with a single + pass or not. Default is `false`.

- The engine renders double-sided, transparent objects with two draw calls (back faces first, then front faces) to mitigate transparency artifacts. - There are scenarios however where this approach produces no quality gains but still doubles draw calls e.g. when rendering flat vegetation like grass sprites. - In these cases, set the `forceSinglePass` flag to `false` to disable the two pass rendering to avoid performance issues. + The engine renders double-sided, transparent objects with two draw calls + (back faces first, then front faces) to mitigate transparency artifacts. + There are scenarios however where this approach produces no quality gains + but still doubles draw calls e.g. when rendering flat vegetation like + grass sprites. In these cases, set the `forceSinglePass` flag to `true` to + disable the two pass rendering to avoid performance issues.

[property:Boolean isMaterial]

-

- Read-only flag to check if a given object is of type [name]. -

+

Read-only flag to check if a given object is of type [name].

[property:Boolean stencilWrite]

- Whether stencil operations are performed against the stencil buffer. In order to perform writes or comparisons against the stencil buffer this value must be `true`. Default is `false`. + Whether stencil operations are performed against the stencil buffer. In + order to perform writes or comparisons against the stencil buffer this + value must be `true`. Default is `false`.

[property:Integer stencilWriteMask]

- The bit mask to use when writing to the stencil buffer. Default is `0xFF`. + The bit mask to use when writing to the stencil buffer. Default is `0xFF`.

[property:Integer stencilFunc]

- The stencil comparison function to use. Default is [page:Materials AlwaysStencilFunc]. See stencil function [page:Materials constants] for all possible values. + The stencil comparison function to use. Default is [page:Materials AlwaysStencilFunc]. + See stencil function [page:Materials constants] for + all possible values.

[property:Integer stencilRef]

- The value to use when performing stencil comparisons or stencil operations. Default is `0`. + The value to use when performing stencil comparisons or stencil + operations. Default is `0`.

[property:Integer stencilFuncMask]

- The bit mask to use when comparing against the stencil buffer. Default is `0xFF`. + The bit mask to use when comparing against the stencil buffer. Default is + `0xFF`.

[property:Integer stencilFail]

- Which stencil operation to perform when the comparison function returns false. Default is [page:Materials KeepStencilOp]. See the stencil operations [page:Materials constants] for all possible values. + Which stencil operation to perform when the comparison function returns + false. Default is [page:Materials KeepStencilOp]. See the stencil + operations [page:Materials constants] for all possible values.

[property:Integer stencilZFail]

- Which stencil operation to perform when the comparison function returns true but the depth test fails. Default is [page:Materials KeepStencilOp]. See the stencil operations [page:Materials constants] for all possible values. + Which stencil operation to perform when the comparison function returns + true but the depth test fails. Default is [page:Materials KeepStencilOp]. + See the stencil operations [page:Materials constants] for all possible + values.

[property:Integer stencilZPass]

- Which stencil operation to perform when the comparison function returns true and the depth test passes. Default is [page:Materials KeepStencilOp]. See the stencil operations [page:Materials constants] for all possible values. + Which stencil operation to perform when the comparison function returns + true and the depth test passes. Default is [page:Materials KeepStencilOp]. + See the stencil operations [page:Materials constants] for all possible + values.

[property:Integer id]

Unique number for this material instance.

[property:String name]

-

Optional name of the object (doesn't need to be unique). Default is an empty string.

- -

[property:Boolean needsUpdate]

- Specifies that the material needs to be recompiled. + Optional name of the object (doesn't need to be unique). Default is an + empty string.

+

[property:Boolean needsUpdate]

+

Specifies that the material needs to be recompiled.

+

[property:Float opacity]

- Float in the range of `0.0` - `1.0` indicating how transparent the material is. - A value of `0.0` indicates fully transparent, `1.0` is fully opaque.
- If the material's [page:Boolean transparent] property is not set to `true`, the material will remain - fully opaque and this value will only affect its color.
- Default is `1.0`. + Float in the range of `0.0` - `1.0` indicating how transparent the + material is. A value of `0.0` indicates fully transparent, `1.0` is fully + opaque.
+ If the material's [page:Boolean transparent] property is not set to + `true`, the material will remain fully opaque and this value will only + affect its color.
+ Default is `1.0`.

[property:Boolean polygonOffset]

- Whether to use polygon offset. Default is `false`. This corresponds to the `GL_POLYGON_OFFSET_FILL` WebGL feature. + Whether to use polygon offset. Default is `false`. This corresponds to the + `GL_POLYGON_OFFSET_FILL` WebGL feature.

[property:Integer polygonOffsetFactor]

@@ -215,28 +258,30 @@

[property:Integer polygonOffsetUnits]

[property:String precision]

- Override the renderer's default precision for this material. Can be `"highp"`, `"mediump"` or `"lowp"`. - Default is `null`. + Override the renderer's default precision for this material. Can be + `"highp"`, `"mediump"` or `"lowp"`. Default is `null`.

[property:Boolean premultipliedAlpha]

- Whether to premultiply the alpha (transparency) value. - See [Example:webgl_materials_physical_transmission WebGL / Materials / Physical / Transmission] for an example of the difference. - Default is `false`. + Whether to premultiply the alpha (transparency) value. See + [Example:webgl_materials_physical_transmission WebGL / Materials / Physical / Transmission] + for an example of the difference. Default is `false`.

[property:Boolean dithering]

- Whether to apply dithering to the color to remove the appearance of banding. - Default is `false`. + Whether to apply dithering to the color to remove the appearance of + banding. Default is `false`.

[property:Integer shadowSide]

- Defines which side of faces cast shadows. - When set, can be [page:Materials THREE.FrontSide], [page:Materials THREE.BackSide], or [page:Materials THREE.DoubleSide]. Default is `null`.
- If `null`, the side casting shadows is determined as follows:
+ Defines which side of faces cast shadows. When set, can be [page:Materials THREE.FrontSide], + [page:Materials THREE.BackSide], or [page:Materials THREE.DoubleSide]. + Default is `null`.
+ If `null`, the side casting shadows is determined as follows:
+

@@ -246,7 +291,6 @@

[property:Integer shadowSide]

- @@ -262,68 +306,68 @@

[property:Integer shadowSide]

THREE.FrontSide back side
- -

-

[property:Integer side]

- Defines which side of faces will be rendered - front, back or both. - Default is [page:Materials THREE.FrontSide]. - Other options are [page:Materials THREE.BackSide] or [page:Materials THREE.DoubleSide]. + Defines which side of faces will be rendered - front, back or both. + Default is [page:Materials THREE.FrontSide]. Other options are + [page:Materials THREE.BackSide] or [page:Materials THREE.DoubleSide].

[property:Boolean toneMapped]

- Defines whether this material is tone mapped according to the renderer's [page:WebGLRenderer.toneMapping toneMapping] setting. Default is `true`. + Defines whether this material is tone mapped according to the renderer's + [page:WebGLRenderer.toneMapping toneMapping] setting. Default is `true`.

[property:Boolean transparent]

- Defines whether this material is transparent. This has an effect on rendering - as transparent objects need special treatment and are rendered after - non-transparent objects.
- When set to true, the extent to which the material is transparent is - controlled by setting its [page:Float opacity] property.
- Default is `false`. + Defines whether this material is transparent. This has an effect on + rendering as transparent objects need special treatment and are rendered + after non-transparent objects.
+ When set to true, the extent to which the material is transparent is + controlled by setting its [page:Float opacity] property.
+ Default is `false`.

[property:String type]

- Value is the string 'Material'. This shouldn't be changed, and can be used to - find all objects of this type in a scene. + Value is the string 'Material'. This shouldn't be changed, and can be used + to find all objects of this type in a scene.

[property:String uuid]

- [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this material instance. - This gets automatically assigned, so this shouldn't be edited. + [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of + this material instance. This gets automatically assigned, so this + shouldn't be edited.

[property:Integer version]

- This starts at `0` and counts how many times [page:Material.needsUpdate .needsUpdate] is set to `true`. + This starts at `0` and counts how many times [page:Material.needsUpdate .needsUpdate] is set to `true`.

[property:Boolean vertexColors]

- Defines whether vertex coloring is used. Default is `false`. - The engine supports RGB and RGBA vertex colors depending on whether a three (RGB) or four (RGBA) component color buffer attribute is used. + Defines whether vertex coloring is used. Default is `false`. The engine + supports RGB and RGBA vertex colors depending on whether a three (RGB) or + four (RGBA) component color buffer attribute is used.

[property:Boolean visible]

-

- Defines whether this material is visible. Default is `true`. -

+

Defines whether this material is visible. Default is `true`.

[property:Object userData]

- An object that can be used to store custom data about the Material. It should not hold - references to functions as these will not be cloned. + An object that can be used to store custom data about the Material. It + should not hold references to functions as these will not be cloned.

Methods

- -

[page:EventDispatcher EventDispatcher] methods are available on this class.

+

+ [page:EventDispatcher EventDispatcher] methods are available on this + class. +

[method:Material clone]( )

Return a new material with the same parameters as this material.

@@ -333,61 +377,70 @@

[method:this copy]( [param:material material] )

[method:undefined dispose]()

- Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. + Frees the GPU-related resources allocated by this instance. Call this + method whenever this instance is no longer used in your app.

- Material textures must be be disposed of by the dispose() method of [page:Texture Texture].

+ Material textures must be be disposed of by the dispose() method of + [page:Texture Texture].

-

[method:undefined onBeforeCompile]( [param:Shader shader], [param:WebGLRenderer renderer] )

+

+ [method:undefined onBeforeCompile]( [param:Shader shader], [param:WebGLRenderer renderer] ) +

- An optional callback that is executed immediately before the shader program is compiled. - This function is called with the shader source code as a parameter. Useful for the modification of built-in materials. + An optional callback that is executed immediately before the shader + program is compiled. This function is called with the shader source code + as a parameter. Useful for the modification of built-in materials.

- Unlike properties, the callback is not supported by [page:Material.clone .clone](), [page:Material.copy .copy]() and [page:Material.toJSON .toJSON](). + Unlike properties, the callback is not supported by [page:Material.clone .clone](), + [page:Material.copy .copy]() and [page:Material.toJSON .toJSON]().

[method:String customProgramCacheKey]()

- In case onBeforeCompile is used, this callback can be used to identify values of settings used in onBeforeCompile, so three.js can reuse a cached shader or recompile the shader for this material as needed. + In case onBeforeCompile is used, this callback can be used to identify + values of settings used in onBeforeCompile, so three.js can reuse a cached + shader or recompile the shader for this material as needed.

- For example, if onBeforeCompile contains a conditional statement like:
- - if ( black ) { - - shader.fragmentShader = shader.fragmentShader.replace('gl_FragColor = vec4(1)', 'gl_FragColor = vec4(0)') - - } - - - then customProgramCacheKey should be set like this:
- - material.customProgramCacheKey = function() { + For example, if onBeforeCompile contains a conditional statement like:
- return black ? '1' : '0'; + + if ( black ) { + shader.fragmentShader = shader.fragmentShader.replace('gl_FragColor = vec4(1)', + 'gl_FragColor = vec4(0)') + } + - } -
+ then customProgramCacheKey should be set like this:
+ + material.customProgramCacheKey = function() { + return black ? '1' : '0'; + } +

- Unlike properties, the callback is not supported by [page:Material.clone .clone](), [page:Material.copy .copy]() and [page:Material.toJSON .toJSON](). + Unlike properties, the callback is not supported by [page:Material.clone .clone](), + [page:Material.copy .copy]() and [page:Material.toJSON .toJSON]().

[method:undefined setValues]( [param:Object values] )

- values -- a container with parameters.
- Sets the properties based on the `values`. + values -- a container with parameters.
+ Sets the properties based on the `values`.

[method:Object toJSON]( [param:Object meta] )

- meta -- object containing metadata such as textures or images for the material.
- Convert the material to three.js [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format]. + meta -- object containing metadata such as textures or images for the + material.
+ Convert the material to three.js + [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].

Source

diff --git a/docs/api/en/materials/MeshBasicMaterial.html b/docs/api/en/materials/MeshBasicMaterial.html index f0beacc102f32b..998c4dddccee62 100644 --- a/docs/api/en/materials/MeshBasicMaterial.html +++ b/docs/api/en/materials/MeshBasicMaterial.html @@ -12,13 +12,16 @@

[name]

- A material for drawing geometries in a simple shaded (flat or wireframe) way.

+ A material for drawing geometries in a simple shaded (flat or wireframe) + way.

This material is not affected by lights.

- - + + + + + [page:Material] → + +

[name]

+ +

Un matériau pour dessiner des géométries de style filaire.

+ +

Exemple de code

+ + + const material = new THREE.LineBasicMaterial( { + color: 0xffffff, + linewidth: 1, + linecap: 'round', //ignored by WebGLRenderer + linejoin: 'round' //ignored by WebGLRenderer + } ); + + +

Exemples

+ +

+ [example:webgl_buffergeometry_drawrange WebGL / buffergeometry / drawrange]
+ [example:webgl_buffergeometry_lines WebGL / buffergeometry / lines]
+ [example:webgl_buffergeometry_lines_indexed WebGL / buffergeometry / lines / indexed]
+ [example:webgl_decals WebGL / decals]
+ [example:webgl_geometry_nurbs WebGL / geometry / nurbs]
+ [example:webgl_geometry_shapes WebGL / geometry / shapes]
+ [example:webgl_geometry_spline_editor WebGL / geometry / spline / editor]
+ [example:webgl_interactive_buffergeometry WebGL / interactive / buffergeometry]
+ [example:webgl_interactive_voxelpainter WebGL / interactive / voxelpainter]
+ [example:webgl_lines_colors WebGL / lines / colors]
+ [example:webgl_lines_dashed WebGL / lines / dashed]
+ [example:webgl_materials WebGL / materials]
+ [example:physics_ammo_rope physics / ammo / rope] +

+ +

Constructeur

+ +

[name]( [param:Object parameters] )

+ +

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les prppriétés communes.

+ +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog), la valeur par défaut est `true`

+ +

[property:Float linewidth]

+

+ Contrôle l'épaisseur des lignes, la valeur par défaut est `1`.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

[property:String linecap]

+

+ Définit l'apparence de la fin de la ligne. les valeurs possibles sont 'butt', 'round' et 'square'. + La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:String linejoin]

+

+ Définit l'apparence des jointures de lignes. Les valeurs possibles sont 'round', 'bevel' et 'miter'. La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:Texture map]

+

+ Sets the color of the lines using data from a [page:Texture]. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/LineDashedMaterial.html b/docs/api/fr/materials/LineDashedMaterial.html new file mode 100644 index 00000000000000..54c52ae9a7508e --- /dev/null +++ b/docs/api/fr/materials/LineDashedMaterial.html @@ -0,0 +1,71 @@ + + + + + + + + + + [page:Material] → [page:LineBasicMaterial] → + +

[name]

+ +

Un matériau pour dessiner des géométries de style filaire, avec des pointillés.

+ +

Exemple de Code

+ + + const material = new THREE.LineDashedMaterial( { + color: 0xffffff, + linewidth: 1, + scale: 1, + dashSize: 3, + gapSize: 1, + } ); + + +

Exemples

+ +

+ [example:webgl_lines_dashed WebGL / lines / dashed]
+

+ +

Constructeur

+ + +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:LineBasicMaterial]) peut être passée dans l'objet. +

+ + +

Propriétés

+

Voir la classe [page:LineBasicMaterial] pour les propriétés communes.

+ +

[property:number dashSize]

+

La taille des tirets, c'est à dire de l'espace additionnée à celle du trait. La valeur par défaut est `3`.

+ +

[property:number gapSize]

+

La taille de l'espace. La valeur par défaut est `1`.

+ +

[property:Boolean isLineDashedMaterial]

+

+ Attribut pour vérifier si un objet donné est de type [name], en lecture seule. +

+ + +

[property:number scale]

+

L'échelle de la partie pointillée d'une ligne. La valeur par défaut est `1`.

+ +

Méthodes

+

Voir la classe [page:LineBasicMaterial] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/Material.html b/docs/api/fr/materials/Material.html new file mode 100644 index 00000000000000..19456dba557017 --- /dev/null +++ b/docs/api/fr/materials/Material.html @@ -0,0 +1,399 @@ + + + + + + + + + +

[name]

+ +

+ Classe abstraite pour les matériaux.

+ + Les matériaux décrivent l'apparence des [page:Object objects]. + Ils sont définis de manière (principalement) indépendante du moteur de rendu, vous n'avez donc pas à + réécrire les matériaux si vous décidez d'utiliser un moteur de rendu différent.

+ + Les propriétés suivantes sont héritées par tous les autres types de matériaux + (ils peuvent cependant avoir d'autres valeurs par défaut). +

+ +

Constructeur

+ + +

[name]()

+

Crée un matériau générique.

+ + +

Propriétés

+ +

[property:Float alphaTest]

+

+ Définit la valeur alpha à utiliser lors de l'exécution d'un test alpha. + Le matériau ne sera pas rendu si l'opacité est inférieure à cette valeur. + La valeur par défaut est `0`. +

+ +

[property:Boolean alphaToCoverage]

+

+ Active l'alpha lors du coverage. Ne peut être utilisé qu'avec des contextes compatibles MSAA + (ce qui signifie que le moteur de rendu a été créé avec le paramètre `antialias` ayant la valeur `true`). + La valeur par défaut est `false`. +

+ +

[property:Integer blendDst]

+

+ Destination de mélange. La valeur par défaut est [page:CustomBlendingEquation OneMinusSrcAlphaFactor]. + Voir les facteurs de destination [page:Constantes CustomBlendingEquation] pour toutes les valeurs possibles.
+ Le [page:Constant blending] (mélange) du matériau doit être défini sur [page:Materials CustomBlending] pour que cela ait un effet. +

+ +

[property:Integer blendDstAlpha]

+

La transparence de [page:.blendDst] (destination du mélange). Utilise la valeur [page:.blendDst] si elle est nulle. La valeur par défaut est `null`.

+ +

[property:Integer blendEquation]

+

+ Équation de mélange à appliquer lors du mélange La valeur par défaut est [page:CustomBlendingEquation AddEquation]. + Voir l'équation de mélange [page:CustomBlendingEquation constants] pour toutes les valeurs possibles.
+ Le [page:Constant blending] (mélange) du matériau doit être défini sur [page:Materials CustomBlending] pour que cela ait un effet. +

+ +

[property:Integer blendEquationAlpha]

+

La transparence de la [page:.blendEquation] (équation de mélange). Utilise la valeur [page:.blendDst] si elle est nulle. La valeur par défaut est `null`.

+ +

[property:Blending blending]

+

+ Quel mélange utiliser lors de l'affichage d'objets avec ce matériau.
+ Il doit être défini sur [page:Materials CustomBlending] pour utiliser [page:Constant blendSrc], [page:Constant blendDst] ou [page:Constant blendEquation] personnalisés.
+ Voir le mode de fusion [page:Constantes de matériaux] pour toutes les valeurs possibles. La valeur par défaut est [page:Materials NormalBlending]. +

+ +

[property:Integer blendSrc]

+

+ Source de mélange. La valeur par défaut est [page:CustomBlendingEquation SrcAlphaFactor]. + Voir les facteurs source [page:Constantes CustomBlendingEquation] pour toutes les valeurs possibles.
+ Le [page:Constant blending] du matériau doit être défini sur [page:Materials CustomBlending] pour que cela ait un effet. +

+ +

[property:Integer blendSrcAlpha]

+

La transparence de la [page:.blendSrc]. Utilise la valeur [page:.blendSrc] si null. La valeur par défaut est `null`.

+ +

[property:Boolean clipIntersection]

+

+ Modifie le comportement des plans de découpage afin que seule leur intersection soit découpée, plutôt que leur union. + La valeur par défaut est "false". +

+ +

[property:Array clippingPlanes]

+

+ Plans de détourage définis par l'utilisateur spécifiés en tant qu'objets THREE.Plane dans l'espace univers. + Ces plans s'appliquent aux objets auxquels ce matériau est attaché. + Les points dans l'espace dont la distance signée au plan est négative sont coupés (pas rendus). + Cela nécessite que [page:WebGLRenderer.localClippingEnabled] soit "true". + Voir l'exemple [example:webgl_clipping_intersection WebGL / clipping /intersection]. + La valeur par défaut est `null`. +

+ +

[property:Boolean clipShadows]

+

+ Définit s'il faut découper les ombres en fonction des plans de découpe spécifiés sur ce matériau. La valeur par défaut est `false`. +

+ +

[property:Boolean colorWrite]

+

+ S'il faut rendre la couleur du matériau. Cela peut être utilisé en conjonction avec la propriété [page:Integer render Order] d'un maillage pour créer des objets invisibles qui masquent d'autres objets. La valeur par défaut est `true`. +

+ +

[property:Object defines]

+

+ Définitions personnalisé à injecter dans le shader. Ceux-ci sont passés sous la forme d'un littéral d'objet, avec des paires clé/valeur. `{ MY_CUSTOM_DEFINE: '' , PI2: Math.PI * 2 }`.Les paires sont définies à la fois dans les shaders de vertex et de fragment. La valeur par défaut est `undefined`. +

+ +

[property:Integer depthFunc]

+

+ Quelle fonction de profondeur utiliser. La valeur par défaut est [page:Materials LessEqualDepth]. Voir le mode profondeur [page:Constantes des matériaux] pour toutes les valeurs possibles. +

+ +

[property:Boolean depthTest]

+

+ Le test de profondeur doit-il être activé lors du rendu de ce matériau. La valeur par défaut est `true`. +

+ +

[property:Boolean depthWrite]

+

+ Si le rendu de ce matériau a un effet sur le tampon de profondeur. La valeur par défaut est `true`.

+ + Lorsque vous dessinez des superpositions 2D, il peut être utile de désactiver l'écriture en profondeur afin de superposer plusieurs choses ensemble sans créer d'artefacts z-index. +

+ +

[property:Boolean forceSinglePass]

+

+ Indique si les objets transparents à double face doivent être rendus en une seule passe ou non. La valeur par défaut est `false`.

+ + Le moteur rend les objets transparents à double face avec deux appels de dessin (les faces arrière d'abord, puis les faces avant) pour atténuer les artefacts de transparence. + Il existe cependant des scénarios où cette approche ne produit aucun gain de qualité mais double toujours les draw calls, par ex. lors du rendu d'une végétation plate comme des sprites d'herbe. + Dans ces cas, définissez l'indicateur `forceSinglePass` sur `true` pour désactiver le rendu en deux passes afin d'éviter les problèmes de performances. +

+ +

[property:Boolean isMaterial]

+

+ Booléen en lecture seule pour vérifier si un object est de type [name]. +

+ +

[property:Boolean stencilWrite]

+

+ Indique si les opérations de stencil sont effectuées sur le tampon de stencil. Afin d'effectuer des écritures ou des comparaisons avec le tampon stencil, cette valeur doit être "true". La valeur par défaut est `false`. +

+ +

[property:Integer stencilWriteMask]

+

+ Le masque de bits à utiliser lors de l'écriture dans le tampon stencil. La valeur par défaut est `0xFF`. +

+ +

[property:Integer stencilFunc]

+

+ La fonction de comparaison de gabarits à utiliser. La valeur par défaut est [page:Materials AlwaysStencilFunc]. Voir fonction stencil [page:Constantes de matériaux] pour toutes les valeurs possibles. +

+ +

[property:Integer stencilRef]

+

+ La valeur à utiliser lors de l'exécution de comparaisons de gabarits ou d'opérations de gabarits. La valeur par défaut est `0`. +

+ +

[property:Integer stencilFuncMask]

+

+ Le masque de bits à utiliser lors de la comparaison avec le tampon stencil. La valeur par défaut est `0xFF`. +

+ +

[property:Integer stencilFail]

+

+ Quelle opération de gabarit effectuer lorsque la fonction de comparaison renvoie false. La valeur par défaut est [page:Materials KeepStencilOp]. Voir les opérations stencil [page:Materials constants] pour toutes les valeurs possibles. +

+ +

[property:Integer stencilZFail]

+

+ Quelle opération de gabarit effectuer lorsque la fonction de comparaison renvoie true mais que le test de profondeur échoue. La valeur par défaut est [page:Materials KeepStencilOp]. Voir les opérations stencil [page:Materials constants] pour toutes les valeurs possibles. +

+ +

[property:Integer stencilZPass]

+

+ Quelle opération de gabarit effectuer lorsque la fonction de comparaison renvoie true et que le test de profondeur réussit. La valeur par défaut est [page:Materials KeepStencilOp]. Voir les opérations stencil [page:Materials constants] pour toutes les valeurs possibles. +

+ +

[property:Integer id]

+

Nombre unique pour cette instance de matériau.

+ +

[property:String name]

+

Nom optionnel de l'object (n'a pas besoin d'être unique). La valeur par défaut est une chaine de caractères vide.

+ +

[property:Boolean needsUpdate]

+

+ Scécifie que le matériau doit être recompilé. +

+ +

[property:Float opacity]

+

+ Flotte dans la plage de `0.0` - `1.0` indiquant la transparence du matériau. + Une valeur de `0.0` indique entièrement transparent, `1.0` est entièrement opaque.
+ Si la propriété [page:Boolean transparent] du matériau n'est pas définie sur "true", le matériau restera + entièrement opaque et cette valeur n'affectera que sa couleur.
+ La valeur par défaut est '1.0'. +

+ +

[property:Boolean polygonOffset]

+

+ Indique s'il faut utiliser le décalage du polygone. La valeur par défaut est "false". Cela correspond à la fonctionnalité WebGL `GL_POLYGON_OFFSET_FILL`. +

+ +

[property:Integer polygonOffsetFactor]

+

Définit le facteur de décalage du polygone. La valeur par défaut est `0`.

+ +

[property:Integer polygonOffsetUnits]

+

Définit les unités de décalage du polygone. La valeur par défaut est `0`.

+ +

[property:String precision]

+

+ Remplace la précision par défaut du rendu pour ce matériau. Peut être `"highp"`, `"mediump"` ou `"lowp"`. + La valeur par défaut est `null`. +

+ +

[property:Boolean premultipliedAlpha]

+

+ Indique s'il faut prémultiplier la valeur alpha (transparence). + Voir [Example:webgl_materials_physical_transmission WebGL / Materials / Physical / Transmission] pour un exemple de la différence. + La valeur par défaut est "false". +

+ +

[property:Boolean dithering]

+

+ Indique s'il faut appliquer un tramage à la couleur pour supprimer l'apparence des bandes. + La valeur par défaut est `false`. +

+ +

[property:Integer shadowSide]

+

+ Définit de quel côté des faces projettent des ombres. + Lorsqu'il est défini, peut être [page:Materials THREE.FrontSide], [page:Materials THREE.BackSide] ou [page:Materials THREE.DoubleSide]. La valeur par défaut est "null".
+ Si `null`, le côté projetant des ombres est déterminé comme suit :
+ + + + + + + + + + + + + + + + + + + + + + + +
[page:Material.side]Ombres portées sur les côtés
THREE.FrontSideverso
THREE.BackSiderecto
THREE.DoubleSidedeux côtés
+ + +

+ +

[property:Integer side]

+

+ Définit quel côté des faces sera rendu - avant, arrière ou les deux. + La valeur par défaut est [page:Materials THREE.FrontSide]. + Les autres options sont [page:Materials THREE.BackSide] ou [page:Materials THREE.DoubleSide]. +

+ +

[property:Boolean toneMapped]

+

+ Définit si ce matériau est tonifié en fonction du paramètre [page:WebGLRenderer.toneMapping toneMapping] du moteur de rendu. La valeur par défaut est `true`. +

+ +

[property:Boolean transparent]

+

+ Définit si ce matériau est transparent. Cela a un effet sur le rendu + car les objets transparents nécessitent un traitement spécial et sont rendus après les + objets opaques.
+ Lorsqu'il est défini sur true, le taux de transparence est + contrôlé en définissant sa propriété [page:Float opacity].
+ La valeur par défaut est `false`. +

+ +

[property:String type]

+

+ La valeur est la chaîne 'Matériau'. Cela ne devrait pas être modifié et peut être utilisé pour + trouver tous les objets de ce type dans une scène. +

+ +

[property:String uuid]

+

+ [link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] de cette instance du matériau. + Ceci est automatiquement attribué, donc cela ne devrait pas être modifié. +

+ +

[property:Integer version]

+

+ Cela commence à '0' et compte combien de fois [page:Material.needsUpdate .needsUpdate] est défini sur 'true'. +

+ +

[property:Boolean vertexColors]

+

+ Définit si la coloration des sommets est utilisée. La valeur par défaut est "false". + Le moteur prend en charge les couleurs de sommet RVB et RVBA selon qu'un attribut de tampon de couleur à trois (RVB) ou à quatre (RVBA) composants est utilisé. +

+ +

[property:Boolean visible]

+

+ Indique si le matériau est visible. La valeur par défaut est `true`. +

+ +

[property:Object userData]

+

+ Un objet qui peut être utilisé pour stocker des données personnalisées sur le matériau. ne doit pas contenir de + références aux fonctions car celles-ci ne seront pas clonées. +

+ +

Méthodes

+ +

Les méthodes [page:EventDispatcher EventDispatcher] sont disponibles dans classe.

+ +

[method:Material clone]( )

+

Renvoie un nouveau matériau avec les mêmes paramètres que le matériau courant.

+ +

[method:this copy]( [param:material material] )

+

Copie les paramètres du matériau précédent dans ce matériau.

+ +

[method:undefined dispose]()

+

+ Libère les ressources liées au GPU allouées par cette instance. Appelez cette méthode chaque fois que cette instance n'est plus utilisée dans votre application. +

+

+ Les textures matérielles doivent être éliminées par la méthode dispose() de [page:Texture Texture].

+

+ +

[method:undefined onBeforeCompile]( [param:Shader shader], [param:WebGLRenderer renderer] )

+

+ Un callback facultatif qui est exécuté immédiatement avant la compilation du programme shader. + Cette fonction est appelée avec le code source du shader comme paramètre. Utile pour la modification des matériaux intégrés. +

+

+ Contrairement aux propriétés, le callback n'est pas pris en charge par [page:Material.clone .clone](), [page:Material.copy .copy]() et [page:Material.toJSON .toJSON](). +

+ +

[method:String customProgramCacheKey]()

+

+ Dans le cas où onBeforeCompile est utilisé, ce callback peut être utilisé pour identifier les valeurs des paramètres utilisés dans onBeforeCompile, afin que three.js puisse réutiliser un shader mis en cache ou recompiler le shader pour ce matériau selon les besoins. +

+ +

+ Par exemple, si onBeforeCompile contient une instruction conditionnelle telle que :
+ + if ( black ) { + + shader.fragmentShader = shader.fragmentShader.replace('gl_FragColor = vec4(1)', 'gl_FragColor = vec4(0)') + + } + + + alors customProgramCacheKey doit être défini comme ceci :
+ + material.customProgramCacheKey = function() { + + return black ? '1' : '0'; + + } + + +

+ +

+ Contrairement aux propriétés, le callback n'est pas pris en charge par [page:Material.clone .clone](), [page:Material.copy .copy]() et [page:Material.toJSON .toJSON](). +

+ +

[method:undefined setValues]( [param:Object values] )

+

+ values -- un conteneur avec des paramètres.
+ Définit les propriétés en fonction des "valeurs". +

+ +

[method:Object toJSON]( [param:Object meta] )

+

+ meta -- objet contenant des métadonnées telles que des textures ou des images pour le matériau.
+ Convertir le matériel au [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format] three.js. +

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshBasicMaterial.html b/docs/api/fr/materials/MeshBasicMaterial.html new file mode 100644 index 00000000000000..2e4f9ed8529748 --- /dev/null +++ b/docs/api/fr/materials/MeshBasicMaterial.html @@ -0,0 +1,154 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ Un matériau pour dessiner des géométries de manière simple et ombrée (à plat ou filaire).

+ + Ce matériau n'est pas affecté par les lumières. +

+ + + + + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Texture aoMap]

+

Le canal rouge de cette texture est utilisé comme carte d'occlusion ambiante. La valeur par défaut est nulle. + L'aoMap nécessite un deuxième ensemble d'UVs.

+ +

[property:Float aoMapIntensity]

+

Intensité de l'effet d'occlusion ambiante. La valeur par défaut est 1. Zéro signifie qu'il n'y a pas d'effet d'occlusion.

+ +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Integer combine]

+

+ Comment combiner le résultat de la couleur de la surface avec la carte d'environnement, le cas échéant.

+ + Les options sont [page:Materials THREE.MultiplyOperation] (par défaut), [page:Materials THREE.MixOperation], + [page :Matériaux TROIS.AddOperation]. Si mix est choisi, la [page:.reflectivity] est utilisée pour + mélanger les deux couleurs. +

+ +

[property:Texture envMap]

+

La carte de l'environnement. La valeur par défaut est nulle.

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Texture lightMap]

+

La carte des lumières (light map). La valeur par défaut est null. La lightMap nécessite un deuxième ensemble d'UVs.

+ +

[property:Float lightMapIntensity]

+

Intensité de la lumière préparée. La valeur par défaut est 1.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. +

+ +

[property:Float reflectivity]

+

+ Dans quelle mesure la carte d'environnement affecte la surface ; voir aussi [page:.combine]. + La valeur par défaut est 1 et la plage valide est comprise entre 0 (aucune réflexion) et 1 (réflexions complètes). +

+ +

[property:Float refractionRatio]

+

+ L'indice de réfraction (IOR) de l'air (environ 1) divisé par l'indice de réfraction du matériau. + Il est utilisé avec les modes de mapping d'environnement [page:Textures THREE.CubeRefractionMapping] et [page:Textures THREE.EquirectangularRefractionMapping]. + Le rapport de réfraction ne doit pas dépasser 1. La valeur par défaut est `0.98`. +

+ +

[property:Texture specularMap]

+

Texture spéculaire utilisée par le matériau. La valeur par défaut est null.

+ +

[property:Boolean wireframe]

+

Rendre la géométrie en fil de fer. La valeur par défaut est "false" (c'est-à-dire rendre sous forme de polygones plats).

+ +

[property:String wireframeLinecap]

+

+ Définit l'apparence de la fin de la ligne. les valeurs possibles sont 'butt', 'round' et 'square'. + La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:String wireframeLinejoin]

+

+ Définit l'apparence des jointures de lignes. Les valeurs possibles sont 'round', 'bevel' et 'miter'. La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshDepthMaterial.html b/docs/api/fr/materials/MeshDepthMaterial.html new file mode 100644 index 00000000000000..58ecfe6f36999f --- /dev/null +++ b/docs/api/fr/materials/MeshDepthMaterial.html @@ -0,0 +1,111 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

Un matériau pour dessiner la géométrie par profondeur. La profondeur est basée sur le plan proche et éloigné de la caméra. Le blanc est le plus proche, le noir est le plus éloigné.

+ + + + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Constant depthPacking]

+

Encodage pour l'emballage en profondeur. La valeur par défaut est [page:Textures BasicDepthPacking].

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes + qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, + bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est + une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, + et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, + et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. + La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. + Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `false`.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. +

+ +

[property:Boolean wireframe]

+

Rendre la géométrie en fil de fer. La valeur par défaut est false (c'est-à-dire rendu en ombré lisse).

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ + +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshDistanceMaterial.html b/docs/api/fr/materials/MeshDistanceMaterial.html new file mode 100644 index 00000000000000..db4a186c3b6e1a --- /dev/null +++ b/docs/api/fr/materials/MeshDistanceMaterial.html @@ -0,0 +1,107 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ [name] est utilisé en interne pour implémenter le shadow mapping avec [page:PointLight]s.

+ + Peut également être utilisé pour personnaliser la projection d'ombre d'un objet en attribuant une instance de [name] à [page:Object3D.customDistanceMaterial]. + Les exemples suivants illustrent cette approche afin de s'assurer que les parties transparentes des objets ne projettent pas d'ombres.ce of [name] to [page:Object3D.customDistanceMaterial]. + The following examples demonstrates this approach in order to ensure transparent parts of objects do no cast shadows. +

+ +

Exemples

+ +

+ [example:webgl_shadowmap_pointlight WebGL / shadowmap / pointlight] +

+ + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes + qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, + bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est + une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, + et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, + et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. + La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. + Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `false`.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ + +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshLambertMaterial.html b/docs/api/fr/materials/MeshLambertMaterial.html new file mode 100644 index 00000000000000..bfbbc41cf660b6 --- /dev/null +++ b/docs/api/fr/materials/MeshLambertMaterial.html @@ -0,0 +1,229 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ Un matériau pour surfaces non brillantes, sans reflets spéculaires.

+ + Le matériau utilise un modèle [link:https://en.wikipedia.org/wiki/Lambertian_reflectance Lambertien] non basé sur la physique + pour calculer la réflectance. Il peut simuler certaines surfaces (comme le bois non traité ou la pierre), + mais ne peut pas simuler des surfaces brillantes avec des reflets spéculaires (comme le bois verni). [name] utilise un ombrage par fragment.

+ + En raison de la simplicité des modèles de réflectance et d'éclairage, les performances seront supérieures + lors de l'utilisation de ce matériau par rapport au [page:MeshPhongMaterial], [page:MeshStandardMaterial] ou [page:MeshPhysicalMaterial], + au prix d'une certaine précision graphique. +

+ + + + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Texture aoMap]

+

Le canal rouge de cette texture est utilisé comme carte d'occlusion ambiante. La valeur par défaut est nulle. + L'aoMap nécessite un deuxième ensemble d'UV.

+ +

[property:Float aoMapIntensity]

+

Intensité de l'effet d'occlusion ambiante. La valeur par défaut est 1. Zéro signifie qu'il n'y a pas d'effet d'occlusion.

+ +

[property:Texture bumpMap]

+

+ La texture pour créer une carte en relief. Les valeurs de noir et blanc correspondent à la profondeur perçue par rapport aux lumières. + Bump n'affecte pas réellement la géométrie de l'objet, seulement l'éclairage. Si une carte normale est définie, cela sera ignoré. +

+ +

[property:Float bumpScale]

+

A quel point la texture en relief affecte le matériau. Les plages typiques sont 0-1. La valeur par défaut est 1.

+ +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Integer combine]

+

+ Comment combiner le résultat de la couleur de la surface avec la carte d'environnement, le cas échéant.

+ + Les options sont [page:Materials THREE.MultiplyOperation] (par défaut), [page:Materials THREE.MixOperation], + [page :Matériaux TROIS.AddOperation]. Si mix est choisi, la [page:.reflectivity] est utilisée pour + mélanger les deux couleurs. +

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes + qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, + bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est + une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, + et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, + et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. + La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. + Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Color emissive]

+

+ Couleur émissive (claire) du matériau, essentiellement une couleur unie non affectée par un autre éclairage. + La valeur par défaut est noire. +

+ +

[property:Texture emissiveMap]

+

+ Définit la carte émissive (lueur). La valeur par défaut est nulle. La couleur de la carte émissive est modulée par + la couleur émissive et l'intensité émissive. Si vous avez une carte émissive, assurez-vous de + régler la couleur émissive sur autre chose que le noir. +

+ +

[property:Float emissiveIntensity]

+

Intensité de la lumière émissive. Module la couleur émissive. La valeur par défaut est 1.

+ +

[property:Texture envMap]

+

La carte de l'environnement. La valeur par défaut est nulle.

+ +

[property:Boolean flatShading]

+

+ Définit si le matériau est rendu avec un ombrage plat. La valeur par défaut est false. +

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Texture lightMap]

+

La carte des lumières (light map). La valeur par défaut est null. La lightMap nécessite un deuxième ensemble d'UVs.

+ +

[property:Float lightMapIntensity]

+

Intensité de la lumière préparée. La valeur par défaut est 1.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. +

+ +

[property:Texture normalMap]

+

+ La texture pour créer une carte normale. Les valeurs RVB affectent la surface normale pour chaque fragment de pixel et changent + la façon dont la couleur est illuminée. Les cartes normales ne changent pas la forme réelle de la surface, seulement l'éclairage. + Dans le cas où le matériau a une carte normale créée en utilisant la convention "left handed", le composant y de normalScale + devrait être négatif pour compenser les différences de latéralité. +

+ +

[property:Integer normalMapType]

+

+ Le type de carte d'ombrage.

+ + Les options sont [page:constant THREE.TangentSpaceNormalMap] (par défaut), et [page:constant THREE.ObjectSpaceNormalMap]. +

+ +

[property:Vector2 normalScale]

+

+ A quel point la carte normale affecte le matériau. Les plages typiques sont 0-1. + La valeur par défaut est un [page:Vector2] défini sur (1,1). +

+ +

[property:Float reflectivity]

+

A quel point la carte d'environnement affecte la surface ; voir aussi [page:.combine].

+ +

[property:Float refractionRatio]

+

+ L'indice de réfraction (IOR) de l'air (environ 1) divisé par l'indice de réfraction du matériau. + Il est utilisé avec les modes de mapping d'environnement [page:Textures THREE.CubeRefractionMapping] et [page:Textures THREE.EquirectangularRefractionMapping]. + Le rapport de réfraction ne doit pas dépasser 1. La valeur par défaut est `0.98`. +

+ +

[property:Texture specularMap]

+

Texture spéculaire utilisée par le matériau. La valeur par défaut est null.

+ +

[property:Boolean wireframe]

+

Rendre la géométrie en fil de fer. La valeur par défaut est "false" (c'est-à-dire rendre sous forme de polygones plats).

+ +

[property:String wireframeLinecap]

+

+ Définit l'apparence de la fin de la ligne. les valeurs possibles sont 'butt', 'round' et 'square'. + La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:String wireframeLinejoin]

+

+ Définit l'apparence des jointures de lignes. Les valeurs possibles sont 'round', 'bevel' et 'miter'. La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshMatcapMaterial.html b/docs/api/fr/materials/MeshMatcapMaterial.html new file mode 100644 index 00000000000000..4e87c44b5c6ccb --- /dev/null +++ b/docs/api/fr/materials/MeshMatcapMaterial.html @@ -0,0 +1,145 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ [name] est définie par une texture MatCap (ou Lit Sphere), qui encode la couleur et l'ombrage du matériau.

+ [name] ne répond pas aux lumières car le fichier image matcap encode l'éclairage préparé. + Il projettera une ombre sur un objet qui reçoit des ombres (et l'écrêtage des ombres fonctionne), mais il ne s'auto-ombrera pas et ne recevra pas d'ombres. +

+ + + + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Texture bumpMap]

+

+ La texture pour créer une carte en relief. Les valeurs de noir et blanc correspondent à la profondeur perçue par rapport aux lumières. + Bump n'affecte pas réellement la géométrie de l'objet, seulement l'éclairage. Si une carte normale est définie, cela sera ignoré. +

+ +

[property:Float bumpScale]

+

A quel point la texture en relief affecte le matériau. Les plages typiques sont 0-1. La valeur par défaut est 1.

+ +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes + qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, + bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est + une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, + et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, + et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. + La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. + Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Boolean flatShading]

+

+ Définit si le matériau est rendu avec un ombrage plat. La valeur par défaut est false. +

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. + La couleur de la carte de texture est modulée par la couleur ([page:.color]) diffuse.. +

+ +

[property:Texture matcap]

+

La carte matcap. La valeur par défaut est null.

+ +

[property:Texture normalMap]

+

+ La texture pour créer une carte normale. Les valeurs RVB affectent la surface normale pour chaque fragment de pixel et changent + la façon dont la couleur est illuminée. Les cartes normales ne changent pas la forme réelle de la surface, seulement l'éclairage. + Dans le cas où le matériau a une carte normale créée en utilisant la convention "left handed", le composant y de normalScale + devrait être négatif pour compenser les différences de latéralité. +

+ +

[property:Integer normalMapType]

+

+ Le type de carte d'ombrage.

+ + Les options sont [page:constant THREE.TangentSpaceNormalMap] (par défaut), et [page:constant THREE.ObjectSpaceNormalMap]. +

+ +

[property:Vector2 normalScale]

+

+ A quel point la carte normale affecte le matériau. Les plages typiques sont 0-1. + La valeur par défaut est un [page:Vector2] défini sur (1,1). +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshNormalMaterial.html b/docs/api/fr/materials/MeshNormalMaterial.html new file mode 100644 index 00000000000000..98dd07141a94d5 --- /dev/null +++ b/docs/api/fr/materials/MeshNormalMaterial.html @@ -0,0 +1,130 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

Un matériau qui mappe les vecteurs normaux aux couleurs RVB.

+ + + + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet. +

+ + +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture bumpMap]

+

+ La texture pour créer une carte en relief. Les valeurs de noir et blanc correspondent à la profondeur perçue par rapport aux lumières. + Bump n'affecte pas réellement la géométrie de l'objet, seulement l'éclairage. Si une carte normale est définie, cela sera ignoré. +

+ +

[property:Float bumpScale]

+

A quel point la texture en relief affecte le matériau. Les plages typiques sont 0-1. La valeur par défaut est 1.

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes + qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, + bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est + une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, + et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, + et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. + La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. + Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Boolean flatShading]

+

+ Définit si le matériau est rendu avec un ombrage plat. La valeur par défaut est false. +

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `false`.

+ +

[property:Texture normalMap]

+

+ La texture pour créer une carte normale. Les valeurs RVB affectent la surface normale pour chaque fragment de pixel et changent + la façon dont la couleur est illuminée. Les cartes normales ne changent pas la forme réelle de la surface, seulement l'éclairage. + Dans le cas où le matériau a une carte normale créée en utilisant la convention "left handed", le composant y de normalScale + devrait être négatif pour compenser les différences de latéralité. +

+ +

[property:Integer normalMapType]

+

+ Le type de carte d'ombrage.

+ + Les options sont [page:constant THREE.TangentSpaceNormalMap] (par défaut), et [page:constant THREE.ObjectSpaceNormalMap]. +

+ +

[property:Vector2 normalScale]

+

+ A quel point la carte normale affecte le matériau. Les plages typiques sont 0-1. + La valeur par défaut est un [page:Vector2] défini sur (1,1). +

+ +

[property:Boolean wireframe]

+

+ Rendre la géométrie en fil de fer. La valeur par défaut est false (c'est-à-dire rendu en ombré lisse). +

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ + + +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshPhongMaterial.html b/docs/api/fr/materials/MeshPhongMaterial.html new file mode 100644 index 00000000000000..35a0e62aa466c3 --- /dev/null +++ b/docs/api/fr/materials/MeshPhongMaterial.html @@ -0,0 +1,247 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ Un matériau pour les surfaces brillantes avec des reflets spéculaires.

+ + Le matériau utilise un modèle de [link:https://en.wikipedia.org/wiki/Blinn-Phong_shading_model Blinn-Phong] non basé sur la physique + pour calculer la réflectance. Contrairement au modèle lambertien utilisé dans la [page:MeshLambertMaterial] + cela peut simuler des surfaces brillantes avec des reflets spéculaires (comme le bois verni). [name] utilise un ombrage par fragment.

+ + Les performances seront généralement meilleurs qu'avec un [page:MeshStandardMaterial] + ou un [page:MeshPhysicalMaterial], au prix d'une perte de précision graphique. +

+ + + + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Texture aoMap]

+

Le canal rouge de cette texture est utilisé comme carte d'occlusion ambiante. La valeur par défaut est nulle. + L'aoMap nécessite un deuxième ensemble d'UV.

+ +

[property:Float aoMapIntensity]

+

Intensité de l'effet d'occlusion ambiante. La valeur par défaut est 1. Zéro signifie qu'il n'y a pas d'effet d'occlusion.

+ +

[property:Texture bumpMap]

+

+ La texture pour créer une carte en relief. Les valeurs de noir et blanc correspondent à la profondeur perçue par rapport aux lumières. + Bump n'affecte pas réellement la géométrie de l'objet, seulement l'éclairage. Si une carte normale est définie, cela sera ignoré. +

+ +

[property:Float bumpScale]

+

A quel point la texture en relief affecte le matériau. Les plages typiques sont 0-1. La valeur par défaut est 1.

+ + +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Integer combine]

+

+ Comment combiner le résultat de la couleur de la surface avec la carte d'environnement, le cas échéant.

+ + Les options sont [page:Materials THREE.MultiplyOperation] (par défaut), [page:Materials THREE.MixOperation], + [page :Matériaux TROIS.AddOperation]. Si mix est choisi, la [page:.reflectivity] est utilisée pour + mélanger les deux couleurs. +

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes + qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, + bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est + une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, + et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, + et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. + La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. + Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Color emissive]

+

+ Couleur émissive (claire) du matériau, essentiellement une couleur unie non affectée par un autre éclairage. + La valeur par défaut est noire. +

+ +

[property:Texture emissiveMap]

+

+ Définit la carte émissive (lueur). La valeur par défaut est nulle. La couleur de la carte émissive est modulée par + la couleur émissive et l'intensité émissive. Si vous avez une carte émissive, assurez-vous de + régler la couleur émissive sur autre chose que le noir. +

+ +

[property:Float emissiveIntensity]

+

Intensité de la lumière émissive. Module la couleur émissive. La valeur par défaut est 1.

+ +

[property:Texture envMap]

+

La carte de l'environnement. La valeur par défaut est nulle.

+ +

[property:Boolean flatShading]

+

+ Définit si le matériau est rendu avec un ombrage plat. La valeur par défaut est false. +

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Texture lightMap]

+

La carte des lumières (light map). La valeur par défaut est null. La lightMap nécessite un deuxième ensemble d'UVs.

+ +

[property:Float lightMapIntensity]

+

Intensité de la lumière préparée. La valeur par défaut est 1.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. + La couleur de la carte de texture est modulée par la couleur ([page:.color]) diffuse.. +

+ +

[property:Texture normalMap]

+

+ La texture pour créer une carte normale. Les valeurs RVB affectent la surface normale pour chaque fragment de pixel et changent + la façon dont la couleur est illuminée. Les cartes normales ne changent pas la forme réelle de la surface, seulement l'éclairage. + Dans le cas où le matériau a une carte normale créée en utilisant la convention "left handed", le composant y de normalScale + devrait être négatif pour compenser les différences de latéralité. +

+ +

[property:Integer normalMapType]

+

+ Le type de carte d'ombrage.

+ + Les options sont [page:constant THREE.TangentSpaceNormalMap] (par défaut), et [page:constant THREE.ObjectSpaceNormalMap]. +

+ +

[property:Vector2 normalScale]

+

+ A quel point la carte normale affecte le matériau. Les plages typiques sont 0-1. + La valeur par défaut est un [page:Vector2] défini sur (1,1). +

+ + +

[property:Float reflectivity]

+

+ Dans quelle mesure la carte d'environnement affecte la surface ; voir aussi [page:.combine]. + La valeur par défaut est 1 et la plage valide est comprise entre 0 (aucune réflexion) et 1 (réflexions complètes). +

+ +

[property:Float refractionRatio]

+

+ L'indice de réfraction (IOR) de l'air (environ 1) divisé par l'indice de réfraction du matériau. + Il est utilisé avec les modes de mapping d'environnement [page:Textures THREE.CubeRefractionMapping] et [page:Textures THREE.EquirectangularRefractionMapping]. + Le rapport de réfraction ne doit pas dépasser 1. La valeur par défaut est `0.98`. +

+ +

[property:Float shininess]

+

À quel point la surbrillance [page:.specular] est-elle brillante ? une valeur plus élevée donne une surbrillance plus nette. La valeur par défaut est `30`.

+ +

[property:Color specular]

+

+ Couleur spéculaire du matériau. La valeur par défaut est une [page:Color] de `0x111111` (gris très foncé).

+ + Cela définit à quel point le matériau brille et la couleur de brillance. +

+ +

[property:Texture specularMap]

+

+ La valeur de carte spéculaire affecte à la fois l'importance de la surbrillance de la surface spéculaire + et à quel point la carte d'environnement affecte la surface. La valeur par défaut est null. +

+ +

[property:Boolean wireframe]

+

Rendre la géométrie en fil de fer. La valeur par défaut est "false" (c'est-à-dire rendre sous forme de polygones plats).

+ +

[property:String wireframeLinecap]

+

+ Définit l'apparence de la fin de la ligne. les valeurs possibles sont 'butt', 'round' et 'square'. + La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:String wireframeLinejoin]

+

+ Définit l'apparence des jointures de lignes. Les valeurs possibles sont 'round', 'bevel' et 'miter'. La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshPhysicalMaterial.html b/docs/api/fr/materials/MeshPhysicalMaterial.html new file mode 100644 index 00000000000000..76cd50f9c13b11 --- /dev/null +++ b/docs/api/fr/materials/MeshPhysicalMaterial.html @@ -0,0 +1,234 @@ + + + + + + + + + + [page:Material] → [page:MeshStandardMaterial] → + +

[name]

+ +

+ Une extension du [page:MeshStandardMaterial], qui prodigue des propriétés de rendu plus avancées basées sur des modèles physiques : +

+ +
    +
  • + Clearcoat : certains matériaux, tels que les peintures automobiles, la fibre de carbone et les surfaces humides, nécessitent une + couche transparente et réfléchissante au-dessus d'une autre couche qui peut être irrégulière ou rugueuse. Clearcoat + se rapproche de cet effet, sans avoir besoin d'une surface transparente séparée. +
  • +
  • + Physically-based transparency: Une limitation de [page:Material.opacity .opacity] est + que les matériaux hautement transparents sont moins réfléchissants. La [page:.transmission] basée sur la physique + offre une option plus réaliste pour les surfaces fines et transparentes comme le verre. +
  • +
  • + Advanced reflectivity: Réflectivité plus flexible pour les matériaux non métalliques. +
  • +
  • + Sheen: Peut être utilisé pour représenter des vêtements et du tissu. +
  • +
+ +

+ En raison de ces fonctionnalités d'ombrage complexes, MeshPhysicalMaterial a un coût de performance par pixel plus élevée + que les autres matériaux three.js. La plupart des effets sont désactivés par défaut et ajoutent un + coût lorsqu'ils sont activés. Pour de meilleurs résultats, spécifiez toujours une carte d'environnement [page:.envMap] + lors de l'utilisation de ce matériel. +

+ + + + + +

Exemples

+

+ [example:webgl_materials_physical_clearcoat materials / physical / clearcoat]
+ [example:webgl_loader_gltf_sheen loader / gltf / sheen]
+ [example:webgl_materials_physical_transmission materials / physical / transmission] +

+ +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (incluant toute propriété héritée de [page:Material] ou [page:MeshStandardMaterial]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color],qui peut être passée avec une chaîne de caractères hexadécimale, définie à `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ + +

Propriétés

+

Voir la classe [page:Material] and [page:MeshStandardMaterial] classes for common properties.

+ +

[property:Color attenuationColor]

+

+ La couleur dans laquelle la lumière blanche se transforme en raison de l'absorption lorsqu'elle atteint la distance d'atténuation. La valeur par défaut est `blanc` (0xffffff). +

+ +

[property:Float attenuationDistance]

+

+ Densité du milieu donnée comme la distance moyenne parcourue par la lumière dans le milieu avant d'interagir avec une particule. La valeur est exprimée en unités spatiales mondiales et doit être supérieure à zéro. La valeur par défaut est `Infinity`. +

+ +

[property:Float clearcoat]

+

+ Représente l'intensité de la couche transparente, de '0.0' à '1.0'. Utiliser les propriétés liées à la couche transparente pour activer le multicouche + matériaux qui ont une fine couche translucide sur la couche de base. La valeur par défaut est `0.0`. +

+ +

[property:Texture clearcoatMap]

+

+ Le canal rouge de cette texture est multiplié par [page:.clearcoat], pour un contrôle par pixel + sur l'intensité d'un revêtement. La valeur par défaut est "null". +

+ +

[property:Texture clearcoatNormalMap]

+

Peut être utilisé pour activer des normales indépendantes pour la couche de revêtement transparente. La valeur par défaut est `null`.

+ +

[property:Vector2 clearcoatNormalScale]

+

De combien [page:.clearcoatNormalMap] affecte la couche transparente, de `(0,0)` à `(1,1)`. La valeur par défaut est `(1,1)`.

+ +

[property:Float clearcoatRoughness]

+

Rugosité de la couche transparente, de `0.0` à `1.0`. La valeur par défaut est `0.0`.

+ +

[property:Texture clearcoatRoughnessMap]

+

+ Le canal vert de cette texture est multiplié par [page:.clearcoatRoughness], pour un contrôle par pixel + sur la rugosité d'un revêtement. La valeur par défaut est `null`. +

+ +

[property:Object defines]

+

Un objet de la forme : + + { + + 'STANDARD': '' + 'PHYSICAL': '', + + }; + + + Est utilisé par [page:WebGLRenderer] pour sélectionner les shaders. +

+ +

[property:Float ior]

+

+ Indice de réfraction pour les matériaux non métalliques, de "1,0" à "2,333". La valeur par défaut est `1.5`.
+

+ +

[property:Float reflectivity]

+

+ Degré de réflectivité, de '0.0' à '1.0'. La valeur par défaut est `0.5`, ce qui correspond à un indice de réfraction de 1,5.
+ + This models the reflectivity of non-metallic materials. It has no effect when [page:MeshStandardMaterial.metalness metalness] is `1.0`. +

+ +

[property:Float sheen]

+

+ Intensité de la couche de brillance, de '0.0' à '1.0'. La valeur par défaut est `0.0`. +

+ +

[property:Float sheenRoughness]

+

+ Rugosité de la couche de brillance, de '0.0' à '1.0'. La valeur par défaut est `1.0`. +

+ +

[property:Texture sheenRoughnessMap]

+

+ Le canal alpha de cette texture est multiplié par [page:.sheen Roughness], pour un contrôle par pixel sur la rugosité de la brillance. + La valeur par défaut est `null`. +

+ +

[property:Color sheenColor]

+

+ La teinte brillante. La valeur par défaut est `0xffffff`, white. +

+ +

[property:Texture sheenColorMap]

+

+ Les canaux RVB de cette texture sont multipliés par [page:.sheenColor], pour un contrôle par pixel + sur la teinte brillante. La valeur par défaut est `null`. +

+ +

[property:Float specularIntensity]

+

+ Un float qui met à l'échelle la quantité de réflexion spéculaire pour les non-métaux uniquement. Lorsqu'il est défini sur zéro, le modèle est effectivement lambertien. De `0.0` à `1.0`. La valeur par défaut est `0.0`. +

+ +

[property:Texture specularIntensityMap]

+

+ Le canal alpha de cette texture est multiplié par [page:.specularIntensity], pour un contrôle par pixel sur l'intensité spéculaire. + La valeur par défaut est `null`. +

+ +

[property:Color specularColor]

+

+ Une [page:Couleur] qui teinte la réflexion spéculaire à une incidence normale pour les non-métaux uniquement. + La valeur par défaut est `0xffffff`, blanc. +

+ +

[property:Texture specularColorMap]

+

+ Les canaux RVB de cette texture sont multipliés par rapport à [page:.specularColor], pour un contrôle par pixel sur la couleur spéculaire. La valeur par défaut est `null`. +

+ +

[property:Float thickness]

+

+ L'épaisseur du volume sous la surface. La valeur est donnée dans l'espace de coordonnées du maillage. + Si la valeur est 0, le matériau est à paroi mince. Sinon, le matériau est une limite de volume. + La valeur par défaut est `0`. +

+ +

[property:Texture thicknessMap]

+

+ Une texture qui définit l'épaisseur, stockée dans le canal G. Cela sera multiplié par [page:.thickness]. La valeur par défaut est `null`. +

+ +

[property:Float transmission]

+

+ Degré de transmission (ou transparence optique), de '0.0' à '1.0'. La valeur par défaut est `0.0`.
+ + Les matériaux minces, transparents ou semi-transparents, en plastique ou en verre restent largement réfléchissants même s'ils sont totalement transmissifs. + + La propriété de transmission peut être utilisée pour modéliser ces matériaux.
+ + Lorsque la transmission est différente de zéro, [page:Material.opacity opacity] doit être défini sur "0". +

+ +

[property:Texture transmissionMap]

+

+ Le canal rouge de cette texture est multiplié par [page:.transmission], pour un contrôle par pixel + sur la transparence optique. La valeur par défaut est `null`. +

+ +

Méthodes

+

Voir la classe [page:Material] and [page:MeshStandardMaterial] pour les méthodes communes.

+ + +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshStandardMaterial.html b/docs/api/fr/materials/MeshStandardMaterial.html new file mode 100644 index 00000000000000..ec6de1d75929c3 --- /dev/null +++ b/docs/api/fr/materials/MeshStandardMaterial.html @@ -0,0 +1,272 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ Un matériau physique standard, utilisant le flux de travail Metallic-Roughness.

+ + Le rendu basé sur la physique (PBR) est récemment devenu la norme dans de nombreuses applications 3D, telles que + [link:https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/ Unity], + [link:https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/PhysicallyBased/ Unreal] et + [link:http://area.autodesk.com/blogs/the-3ds-max-blog/what039s-new-for-rendering-in-3ds-max-2017 3D Studio Max].

+ + Cette approche diffère des approches plus anciennes, au lieu d'utiliser des approximations pour la manière dont + la lumière interagit avec une surface, un modèle physiquement correct est utilisé. L'idée est de choisir + un matériau qui réagira « correctement » dans tous les scénarios d'éclairage, au lieu d'essayer de manipuler les matériaux + pour qu'ils aient un bon rendu avec une lumière spécifique.

+ + En pratique, cela donne un résultat plus précis et réaliste que le [page:MeshLambertMaterial] + ou [page:MeshPhongMaterial],au prix d'être un peu plus coûteux en calcul. [name] utilise un ombrage par fragment.

+ + Notez que pour de meilleurs résultats, vous devez toujours spécifier une [page:.envMap environment map] lors de l'utilisation + ce materiel.

+ + Pour une introduction non technique au concept de PBR et comment mettre en place un matériel PBR, + consultez ces articles rédigés par des personnes de [link:https://www.marmoset.co marmoset]: +

    +
  • + [link:https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/ Basic Theory of Physically Based Rendering] +
  • +
  • + [link:https://www.marmoset.co/posts/physically-based-rendering-and-you-can-too/ Physically Based Rendering and You Can Too] +
  • +
+

+

+ Les détails techniques de l'approche utilisée dans three.js (et la plupart des autres systèmes PBR) peuvent être trouvés sur ce pdf : + [link:https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf paper from Disney], + de Brent Burley. +

+ + + + + +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Texture aoMap]

+

Le canal rouge de cette texture est utilisé comme carte d'occlusion ambiante. La valeur par défaut est nulle. + L'aoMap nécessite un deuxième ensemble d'UV.

+ +

[property:Float aoMapIntensity]

+

Intensité de l'effet d'occlusion ambiante. La valeur par défaut est 1. Zéro signifie qu'il n'y a pas d'effet d'occlusion.

+ +

[property:Texture bumpMap]

+

+ La texture pour créer une carte en relief. Les valeurs de noir et blanc correspondent à la profondeur perçue par rapport aux lumières. + Bump n'affecte pas réellement la géométrie de l'objet, seulement l'éclairage. Si une carte normale est définie, cela sera ignoré. +

+ +

[property:Float bumpScale]

+

A quel point la texture en relief affecte le matériau. Les plages typiques sont 0-1. La valeur par défaut est 1.

+ + +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Object defines]

+

Un objet de la forme : + + { 'STANDARD': '' }; + + + Est utilisé par [page:WebGLRenderer] pour choisir les shaders. +

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes + qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, + bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est + une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, + et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, + et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. + La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. + Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Color emissive]

+

+ Couleur émissive (claire) du matériau, essentiellement une couleur unie non affectée par un autre éclairage. + La valeur par défaut est noire. +

+ +

[property:Texture emissiveMap]

+

+ Définit la carte émissive (lueur). La valeur par défaut est nulle. La couleur de la carte émissive est modulée par + la couleur émissive et l'intensité émissive. Si vous avez une carte émissive, assurez-vous de + régler la couleur émissive sur autre chose que le noir. +

+ +

[property:Float emissiveIntensity]

+

Intensité de la lumière émissive. Module la couleur émissive. La valeur par défaut est 1.

+ +

[property:Texture envMap]

+

La carte de l'environnement. Pour garantir un rendu physiquement correct, vous ne devez ajouter que des + cartes d'environnement qui ont été prétraitées par [page: PMREMGenerator]. La valeur par défaut est null. +

+ +

[property:Float envMapIntensity]

+

Met à l'échelle l'effet de la carte d'environnement en multipliant sa couleur.

+ +

[property:Boolean flatShading]

+

+ Définit si le matériau est rendu avec un ombrage plat. La valeur par défaut est false. +

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Boolean isMeshStandardMaterial]

+

+ Booléen en lecture seule pour vérifier si un objet donné est de type [name]. +

+ +

[property:Texture lightMap]

+

La carte des lumières (light map). La valeur par défaut est null. La lightMap nécessite un deuxième ensemble d'UVs.

+ +

[property:Float lightMapIntensity]

+

Intensité de la lumière préparée. La valeur par défaut est 1.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. + La couleur de la carte de texture est modulée par la couleur ([page:.color]) diffuse.. +

+ +

[property:Float metalness]

+

+ Combien le matériau est comme un métal. Les matériaux non métalliques tels que le bois ou la pierre utilisent 0,0, les métaux utilisent 1,0, sans rien + (généralement) entre les deux. La valeur par défaut est 0.0. Une valeur comprise entre 0,0 et 1,0 peut être utilisée pour un aspect de métal rouillé. Si metalnessMap est + également fourni, les deux valeurs sont multipliées. +

+ +

[property:Texture metalnessMap]

+

Le canal bleu de cette texture est utilisé pour modifier la métallité du matériau.

+ +

[property:Texture normalMap]

+

+ La texture pour créer une carte normale. Les valeurs RVB affectent la surface normale pour chaque fragment de pixel et changent + la façon dont la couleur est illuminée. Les cartes normales ne changent pas la forme réelle de la surface, seulement l'éclairage. + Dans le cas où le matériau a une carte normale créée en utilisant la convention "left handed", le composant y de normalScale + devrait être négatif pour compenser les différences de latéralité. +

+ +

[property:Integer normalMapType]

+

+ Le type de carte d'ombrage.

+ + Les options sont [page:constant THREE.TangentSpaceNormalMap] (par défaut), et [page:constant THREE.ObjectSpaceNormalMap]. +

+ +

[property:Vector2 normalScale]

+

+ A quel point la carte normale affecte le matériau. Les plages typiques sont 0-1. + La valeur par défaut est un [page:Vector2] défini sur (1,1). +

+ +

[property:Float roughness]

+

+ La rugosité du matériau apparaît. 0,0 signifie une réflexion miroir lisse, 1,0 signifie entièrement diffus. La valeur par défaut est 1.0. + Si roughnessMap est également fourni, les deux valeurs sont multipliées. +

+ +

[property:Texture roughnessMap]

+

Le canal vert de cette texture est utilisé pour modifier la rugosité du matériau.

+ +

[property:Boolean wireframe]

+

Rendre la géométrie en fil de fer. La valeur par défaut est "false" (c'est-à-dire rendre sous forme de polygones plats).

+ +

[property:String wireframeLinecap]

+

+ Définit l'apparence de la fin de la ligne. les valeurs possibles sont 'butt', 'round' et 'square'. + La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:String wireframeLinejoin]

+

+ Définit l'apparence des jointures de lignes. Les valeurs possibles sont 'round', 'bevel' et 'miter'. La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ + +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/MeshToonMaterial.html b/docs/api/fr/materials/MeshToonMaterial.html new file mode 100644 index 00000000000000..18ad4bddcf115b --- /dev/null +++ b/docs/api/fr/materials/MeshToonMaterial.html @@ -0,0 +1,200 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +
Un matériau mettant en œuvre le toon shading.
+ + + + + +

Exemples

+

+ [example:webgl_materials_toon materials / toon] +

+ +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Texture aoMap]

+

Le canal rouge de cette texture est utilisé comme carte d'occlusion ambiante. La valeur par défaut est nulle. +L'aoMap nécessite un deuxième ensemble d'UV.

+ +

[property:Float aoMapIntensity]

+

Intensité de l'effet d'occlusion ambiante. La valeur par défaut est 1. Zéro signifie qu'il n'y a pas d'effet d'occlusion.

+ +

[property:Texture bumpMap]

+

+ La texture pour créer une carte en relief. Les valeurs de noir et blanc correspondent à la profondeur perçue par rapport aux lumières. +Bump n'affecte pas réellement la géométrie de l'objet, seulement l'éclairage. Si une carte normale est définie, cela sera ignoré. +

+ +

[property:Float bumpScale]

+

A quel point la texture en relief affecte le matériau. Les plages typiques sont 0-1. La valeur par défaut est 1.

+ + +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Texture displacementMap]

+

+ La carte de déplacement affecte la position des sommets du maillage. Contrairement aux autres cartes +qui n'affectent que la lumière et l'ombre du matériau, les sommets déplacés peuvent projeter des ombres, +bloquer d'autres objets et agir autrement comme une géométrie réelle. La texture de déplacement est +une image sur laquelle la valeur de chaque pixel (le blanc étant le plus élevé) est mappée, +et repositionne, les sommets du maillage. +

+ +

[property:Float displacementScale]

+

+ Dans quelle mesure la carte de déplacement affecte le maillage (où le noir n'est pas un déplacement, +et le blanc est le déplacement maximal). Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. +La valeur par défaut est 1. +

+ +

[property:Float displacementBias]

+

+ Le décalage des valeurs de la carte de déplacement sur les sommets du maillage. +Sans ensemble de cartes de déplacement, cette valeur n'est pas appliquée. La valeur par défaut est 0. +

+ +

[property:Color emissive]

+

+ Couleur émissive (claire) du matériau, essentiellement une couleur unie non affectée par un autre éclairage. +La valeur par défaut est noire. +

+ +

[property:Texture emissiveMap]

+

+ Définit la carte émissive (lueur). La valeur par défaut est nulle. La couleur de la carte émissive est modulée par +la couleur émissive et l'intensité émissive. Si vous avez une carte émissive, assurez-vous de +régler la couleur émissive sur autre chose que le noir. +

+ +

[property:Float emissiveIntensity]

+

Intensité de la lumière émissive. Module la couleur émissive. La valeur par défaut est 1.

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Texture gradientMap]

+

Carte de dégradé pour l'ombrage toon. Il est nécessaire de définir [page:Texture.minFilter] et [page:Texture.magFilter] sur + [page:Textures THREE.NearestFilter] lors de l'utilisation de ce type de texture. La valeur par défaut est `null`.

+ +

[property:Texture lightMap]

+

La carte des lumières (light map). La valeur par défaut est null. La lightMap nécessite un deuxième ensemble d'UVs.

+ +

[property:Float lightMapIntensity]

+

Intensité de la lumière préparée. La valeur par défaut est 1.

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec +[page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. + La couleur de la carte de texture est modulée par la couleur ([page:.color]) diffuse.. +

+ +

[property:Texture normalMap]

+

+ La texture pour créer une carte normale. Les valeurs RVB affectent la surface normale pour chaque fragment de pixel et changent +la façon dont la couleur est illuminée. Les cartes normales ne changent pas la forme réelle de la surface, seulement l'éclairage. +Dans le cas où le matériau a une carte normale créée en utilisant la convention "left handed", le composant y de normalScale +devrait être négatif pour compenser les différences de latéralité. +

+ +

[property:Integer normalMapType]

+

+ Le type de carte d'ombrage.

+ + Les options sont [page:constant THREE.TangentSpaceNormalMap] (par défaut), et [page:constant THREE.ObjectSpaceNormalMap]. +

+ +

[property:Vector2 normalScale]

+

+ A quel point la carte normale affecte le matériau. Les plages typiques sont 0-1. +La valeur par défaut est un [page:Vector2] défini sur (1,1). +

+ +

[property:Boolean wireframe]

+

Rendre la géométrie en fil de fer. La valeur par défaut est "false" (c'est-à-dire rendre sous forme de polygones plats).

+ +

[property:String wireframeLinecap]

+

+ Définit l'apparence de la fin de la ligne. les valeurs possibles sont 'butt', 'round' et 'square'. + La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:String wireframeLinejoin]

+

+ Définit l'apparence des jointures de lignes. Les valeurs possibles sont 'round', 'bevel' et 'miter'. La valeur par défaut est 'round'.

+ + Cela correspond à la propriété [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] + et est ignorée par le moteur de rendu [page:WebGLRenderer WebGL]. +

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/PointsMaterial.html b/docs/api/fr/materials/PointsMaterial.html new file mode 100644 index 00000000000000..c2749cb0747a3b --- /dev/null +++ b/docs/api/fr/materials/PointsMaterial.html @@ -0,0 +1,110 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

Le matériau par défaut utilisé par [page:Points].

+ +

Code Example

+ + const vertices = []; + + for ( let i = 0; i < 10000; i ++ ) { + + const x = THREE.MathUtils.randFloatSpread( 2000 ); + const y = THREE.MathUtils.randFloatSpread( 2000 ); + const z = THREE.MathUtils.randFloatSpread( 2000 ); + + vertices.push( x, y, z ); + + } + + const geometry = new THREE.BufferGeometry(); + geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); + + const material = new THREE.PointsMaterial( { color: 0x888888 } ); + + const points = new THREE.Points( geometry, material ); + + scene.add( points ); + + +

Exemples

+

+ [example:misc_controls_fly misc / controls / fly]
+ [example:webgl_buffergeometry_drawrange WebGL / BufferGeometry / drawrange]
+ [example:webgl_buffergeometry_points WebGL / BufferGeometry / points]
+ [example:webgl_buffergeometry_points_interleaved WebGL / BufferGeometry / points / interleaved]
+ [example:webgl_camera WebGL / camera ]
+ [example:webgl_geometry_convex WebGL / geometry / convex]
+ [example:webgl_geometry_shapes WebGL / geometry / shapes]
+ [example:webgl_interactive_raycasting_points WebGL / interactive / raycasting / points]
+ [example:webgl_multiple_elements_text WebGL / multiple / elements / text]
+ [example:webgl_points_billboards WebGL / points / billboards]
+ [example:webgl_points_dynamic WebGL / points / dynamic]
+ [example:webgl_points_sprites WebGL / points / sprites] +

+ +

Constructeur

+

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff).

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Texture map]

+

+ Définit la couleur des points à l'aide des données d'une [page:Texture]. + Peut éventuellement inclure un canal alpha, généralement combiné avec + [page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. +

+ +

[property:Number size]

+

Définit la taille des points en pixels. La valeur par défaut est 1.0.
+ Sera plafonné s'il dépasse le paramètre dépendant du matériel [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter gl.ALIASED_POINT_SIZE_RANGE].

+ +

[property:Boolean sizeAttenuation]

+

Spécifiez si la taille des points est atténuée par la profondeur de la caméra. (Caméra perspective uniquement). La valeur par défaut est true.

+ + +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/RawShaderMaterial.html b/docs/api/fr/materials/RawShaderMaterial.html new file mode 100644 index 00000000000000..81a6759c100af1 --- /dev/null +++ b/docs/api/fr/materials/RawShaderMaterial.html @@ -0,0 +1,66 @@ + + + + + + + + + + [page:Material] → [page:ShaderMaterial] → + +

[name]

+ +

+ Cette classe fonctionne exactement comme [page:ShaderMaterial], sauf que les définitions des + uniformes et les attributs intégrés ne sont pas automatiquement ajoutées au code du shader GLSL. +

+ +

Code Example

+ + const material = new THREE.RawShaderMaterial( { + + uniforms: { + time: { value: 1.0 } + }, + vertexShader: document.getElementById( 'vertexShader' ).textContent, + fragmentShader: document.getElementById( 'fragmentShader' ).textContent, + + } ); + + +

Exemples

+

+ [example:webgl_buffergeometry_rawshader WebGL / buffergeometry / rawshader]
+ [example:webgl_buffergeometry_instancing_billboards WebGL / buffergeometry / instancing / billboards]
+ [example:webgl_buffergeometry_instancing WebGL / buffergeometry / instancing]
+ [example:webgl_raymarching_reflect WebGL / raymarching / reflect]
+ [example:webgl2_volume_cloud WebGL 2 / volume / cloud]
+ [example:webgl2_volume_instancing WebGL 2 / volume / instancing]
+ [example:webgl2_volume_perlin WebGL 2 / volume / perlin] +

+ +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material] and [page:ShaderMaterial]) peut être passée dans l'objet.

+

+ + +

Propriétés

+

Voir la classe [page:Material] et [page:ShaderMaterial] pour les propriétés communes.

+ + +

Méthodes

+

Voir la classe [page:Material] et [page:ShaderMaterial] pour les méthodes communes.

+ + +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/ShaderMaterial.html b/docs/api/fr/materials/ShaderMaterial.html new file mode 100644 index 00000000000000..1709b2cd2729b3 --- /dev/null +++ b/docs/api/fr/materials/ShaderMaterial.html @@ -0,0 +1,441 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ Un matériau rendu avec des shaders personnalisés. Un shader est un petit programme écrit en + [link:https://www.khronos.org/files/opengles_shading_language.pdf GLSL] qui s'exécute sur le GPU. + Vous pouvez utiliser un shader personnalisé si vous avez besoin de : +

    +
  • implémenter un effet qui n'est inclus dans aucun des [page:Material materials] intégrés
  • +
  • combiner de nombreux objets en une seule [page:BufferGeometry] afin d'améliorer les performances
  • +
+ Il y a les notes suivantes à garder à l'esprit lors de l'utilisation d'un `ShaderMaterial` : + +
    +
  • + Un `ShaderMaterial` ne sera rendu correctement que par [page: WebGLRenderer], + depuis le code GLSL dans le [link:https://en.wikipedia.org/wiki/Shader#Vertex_shaders vertexShader] + et les propriétés [link:https://en.wikipedia.org/wiki/Shader#Pixel_shaders fragmentShader] doivent + être compilées et exécutées sur le GPU à l'aide de WebGL. +
  • +
  • + Depuis THREE r72, l'attribution directe d'attributs dans un ShaderMaterial n'est plus prise en charge. + Une instance [page:BufferGeometry] doit être utilisée à la place, en utilisant des instances [page:BufferAttribute] pour définir des attributs personnalisés. +
  • +
  • + Depuis THREE r77, les instances [page:WebGLRenderTarget] ou [page:WebGLCubeRenderTarget] + ne sont plus censés être utilisés comme uniformes. Leur propriété [page:Texture texture] + doit être utilisé à la place. +
  • +
  • + Les attributs et les uniformes intégrés sont transmis aux shaders avec votre code. + Si vous ne voulez pas que [page:WebGLProgram] ajoute quoi que ce soit à votre code de shader, vous pouvez utiliser + [page:RawShaderMaterial] au lieu de cette classe. +
  • +
  • + Vous pouvez utiliser la directive #pragma unroll_loop_start et #pragma unroll_loop_end afin de dérouler une boucle `for` en GLSL par le préprocesseur de shader. + La directive doit être placée juste au-dessus de la boucle. Le formatage de la boucle doit correspondre à une norme définie. +
      +
    • + La boucle doit être normalisée ([link:https://en.wikipedia.org/wiki/Normalized_loop normalized]). +
    • +
    • + La variable d'itération de la boucle doit être *i*. +
    • +
    • + La valeur `UNROLLED_LOOP_INDEX` sera remplacée par la valeur explicite de *i* pour l'itération donnée et peut être utilisée dans les instructions du préprocesseur. +
    • +
    + + #pragma unroll_loop_start + for ( int i = 0; i < 10; i ++ ) { + + // ... + + } + #pragma unroll_loop_end + +
  • +
+

+ +

Code Example

+ + + const material = new THREE.ShaderMaterial( { + + uniforms: { + + time: { value: 1.0 }, + resolution: { value: new THREE.Vector2() } + + }, + + vertexShader: document.getElementById( 'vertexShader' ).textContent, + + fragmentShader: document.getElementById( 'fragmentShader' ).textContent + + } ); + + +

Exemples

+ +

+ [example:webgl_buffergeometry_custom_attributes_particles webgl / buffergeometry / custom / attributes / particles]
+ [example:webgl_buffergeometry_selective_draw webgl / buffergeometry / selective / draw]
+ [example:webgl_custom_attributes webgl / custom / attributes]
+ [example:webgl_custom_attributes_lines webgl / custom / attributes / lines]
+ [example:webgl_custom_attributes_points webgl / custom / attributes / points]
+ [example:webgl_custom_attributes_points2 webgl / custom / attributes / points2]
+ [example:webgl_custom_attributes_points3 webgl / custom / attributes / points3]
+ [example:webgl_depth_texture webgl / depth / texture]
+ [example:webgl_gpgpu_birds webgl / gpgpu / birds]
+ [example:webgl_gpgpu_protoplanet webgl / gpgpu / protoplanet]
+ [example:webgl_gpgpu_water webgl / gpgpu / water]
+ [example:webgl_interactive_points webgl / interactive / points]
+ [example:webgl_video_kinect webgl / video / kinect]
+ [example:webgl_lights_hemisphere webgl / lights / hemisphere]
+ [example:webgl_marchingcubes webgl / marchingcubes]
+ [example:webgl_materials_envmaps webgl / materials / envmaps]
+ [example:webgl_materials_lightmap webgl / materials / lightmap]
+ [example:webgl_materials_wireframe webgl / materials / wireframe]
+ [example:webgl_modifier_tessellation webgl / modifier / tessellation]
+ [example:webgl_postprocessing_dof2 webgl / postprocessing / dof2]
+ [example:webgl_postprocessing_godrays webgl / postprocessing / godrays] +

+ +

Shaders de vertex et shaders de fragments

+ +
+

Vous pouvez spécifier deux types de shaders différents pour chaque matériau :

+
    +
  • + Le vertex shader s'exécute en premier ; il reçoit des `attributs`, calcule / manipule + la position de chaque sommet individuel, et transmet des données supplémentaires ("variantes") au fragment shader. +
  • +
  • + Le shader fragment ( ou pixel ) s'exécute en second ; il définit la couleur de chaque "fragment" individuel + (pixel) rendu à l'écran. +
  • +
+

Il existe trois types de variables dans les shaders : les `uniforms`, les `attributes` et les `varyings` :

+
    +
  • + Les `Uniforms` sont des variables qui ont la même valeur pour tous les sommets - éclairage, brouillard, + et les cartes d'ombre sont des exemples de données qui seraient stockées dans des uniformes. + Les uniformes sont accessibles à la fois par le vertex shader et le fragment shader. +
  • +
  • + `Attributes` sont des variables associées à chaque sommet --- par exemple, la position du sommet, + face normale et vertex color sont tous des exemples de données qui seraient stockées dans des attributs. + Les attributs ne sont accessibles "que" dans le vertex shader. +
  • +
  • + `Varyings` sont des variables qui sont passées du vertex shader au fragment shader. + Pour chaque fragment, la valeur de chaque variable sera interpolée en douceur à partir des valeurs des sommets adjacents. +
  • +
+

+ Notez que "dans" le shader lui-même, les uniformes et les attributs agissent comme des constantes ; + vous ne pouvez modifier leurs valeurs qu'en transmettant des valeurs différentes aux tampons à partir de votre code JavaScript. +

+
+ + +

Attributs et uniformes intégrés

+ +
+

+ La [page:WebGLRenderer] fournit de nombreux attributs et uniformes aux shaders par défaut ; + les définitions de ces variables sont ajoutées à vos `fragmentShader` et `vertexShader` + codés par le [page:WebGLProgram] lorsque le shader est compilé ; vous n'avez pas besoin de les déclarer vous-même. + Voir [page:WebGLProgram] pour plus de détails sur ces variables. +

+

+ Certains de ces uniformes ou attributs (par exemple, ceux concernant l'éclairage, le brouillard, etc.) + exigent que les propriétés soient définies sur le matériau pour que [page: WebGLRenderer] copie + les valeurs appropriées au GPU - assurez-vous de définir ces flags si vous souhaitez les utiliser + fonctionnalités dans votre propre shader. +

+

+ Si vous ne voulez pas que [page:WebGLProgram] ajoute quoi que ce soit à votre code de shader, vous pouvez utiliser + [page:RawShaderMaterial] au lieu de cette classe. +

+
+ + +

Attributs et uniformes personnalisés

+ +
+

+ Les attributs personnalisés et les uniformes doivent être déclarés dans votre code de shader GLSL + (dans `vertexShader` et/ou `fragmentShader`). Les uniformes personnalisés doivent être définis dans "les deux" + propriétés `uniforms` de votre `ShaderMaterial`, alors que tous les attributs personnalisés doivent être + définis via les instances [page:BufferAttribute]. Notez que "varying" doit uniquement être déclaré dans le code du shader (et non dans le matériau). +

+

+ Pour déclarer un attribut personnalisé, veuillez vous référer à la page [page:BufferGeometry] pour un aperçu, +et la page [page:BufferAttribute] pour un aperçu détaillé de l'API `BufferAttribute`. +

+

+ Lors de la création de vos attributs, chaque tableau typé que vous créez pour contenir vos + données doit être un multiple de la taille de votre type de données. Par exemple, si votre attribut + est de type [page:Vector3 THREE.Vector3], et vous avez 3000 sommets dans votre + [page:BufferGeometry], votre valeur de tableau typée doit être créée avec une longueur de 3000 * 3, + ou 9000 (une valeur par composant). Un tableau de la taille de chaque type de données est présenté ci-dessous à titre de référence : +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Taille des attributs
type GLSLtype JavaScripttaille
float[page:Number]1
vec2[page:Vector2 THREE.Vector2]2
vec3[page:Vector3 THREE.Vector3]3
vec3[page:Color THREE.Color]3
vec4[page:Vector4 THREE.Vector4]4
+ +

+ Notez que les tampons d'attributs ne sont `pas` actualisés automatiquement lorsque leurs valeurs changent. Pour mettre à jour les attributs personnalisés, + définissez le paramètre `needsUpdate` sur true sur le [page:BufferAttribute] de la géométrie (voir [page:BufferGeometry] + pour plus de détails). +

+ +

+ Pour déclarer un [page:Uniform] personnalisé, utilisez la propriété `uniforms` : + + uniforms: { + time: { value: 1.0 }, + resolution: { value: new THREE.Vector2() } + } + +

+ +

+ Il est recommandé de mettre à jour les valeurs [page:Uniform] personnalisées en fonction de [page:Object3D object] et [page:Camera camera] + dans [page:Object3D.onBeforeRender] car [page:Material] peut être partagé entre [page:Mesh meshes], [page:Matrix4 matrixWorld] + de [page:Scene] et [page:Camera] sont mis à jour dans [page:WebGLRenderer.render], et certains effets rendent une [page:Scene scene] + avec leur propre [page : cameras] privées. +

+ +
+ +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet. +

+ +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Boolean clipping]

+

+ Définit si ce matériau prend en charge l'écrêtage ; true pour laisser le moteur de rendu transmettre l'uniforme clippingPlanes. La valeur par défaut est false. +

+ +

[property:Object defaultAttributeValues]

+

+ Lorsque la géométrie rendue n'inclut pas ces attributs mais que le matériau le fait, + ces valeurs par défaut seront transmises aux shaders. Cela évite les erreurs lorsque des données de tampon sont manquantes. + + + this.defaultAttributeValues = { + 'color': [ 1, 1, 1 ], + 'uv': [ 0, 0 ], + 'uv1': [ 0, 0 ] + }; + + +

+ + +

[property:Object defines]

+

+ Définit des constantes personnalisées à l'aide des directives `#define` dans le code GLSL pour les deux + shader de vertex et le shader de fragment ; chaque paire clé/valeur produit une autre directive : + + defines: { + FOO: 15, + BAR: true + } + + yields the lines + + #define FOO 15 + #define BAR true + + in the GLSL code. +

+ +

[property:Object extensions]

+

+ Un objet avec les propriétés suivantes : + + this.extensions = { + derivatives: false, // set to use derivatives + fragDepth: false, // set to use fragment depth values + drawBuffers: false, // set to use draw buffers + shaderTextureLOD: false // set to use shader texture LOD + }; + +

+ + +

[property:Boolean fog]

+

+ Définissez si la couleur du matériau est affectée par les paramètres de brouillard globaux ; vrai pour passer + les uniformes de brouillard au shader. La valeur par défaut est false. +

+ + +

[property:String fragmentShader]

+

+ Code GLSL du shader de fragment. C'est le code réel du shader. Dans l'exemple ci-dessus, + le code `vertexShader` et `fragmentShader` est extrait du DOM ; il peut être passé + sous forme de chaîne de caractères ou chargé via AJAX à la place. +

+ +

[property:String glslVersion]

+

+ Définit la version GLSL du code de shader personnalisé. Pertinent uniquement pour WebGL 2 afin de définir s'il faut spécifier + GLSL 3.0 ou pas. Les valeurs valides sont `THREE.GLSL1` ou `THREE.GLSL3`. La valeur par défaut est `null`. +

+ +

[property:String index0AttributeName]

+

+ Si définit, cela appelle [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindAttribLocation gl.bindAttribLocation] + pour lier un index de sommet générique à une variable d'attribut. + La valeur par défaut est undefined. + +

+ +

[property:Boolean isShaderMaterial]

+

+ Attribut en lecture seule pour vérifier si l'object donné est de type [name]. +

+ +

[property:Boolean lights]

+

+ Définit si ce matériau utilise l'éclairage ; true pour transmettre des données uniformes liées à l'éclairage à ce shader. La valeur par défaut est false. +

+ +

[property:Float linewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ +

[property:Boolean flatShading]

+

+ Définit si le matériau est rendu avec un ombrage plat. La valeur par défaut est false. +

+ +

[property:Object uniforms]

+

+ Un object de la forme: + + { "uniform1": { value: 1.0 }, "uniform2": { value: 2 } } + + spécifiant les uniformes à transmettre au code shader ; les clés sont des noms uniformes, les valeurs sont des définitions de la forme + + { value: 1.0 } + + Quand `value` est la valeur de l'uniforme. Les noms doivent correspondre au nom de l'uniforme, + tel que défini dans le code GLSL. A noter que les uniformes sont rafraichis à chaque frame, + donc la mise à jour de la valeur de l'uniforme mettra immédiatement à jour la valeur disponible pour le code GLSL. +

+ +

[property:Boolean uniformsNeedUpdate]

+

+ Peut être utilisé pour forcer une mise à jour uniforme lors du changement d'uniformes dans [page:Object3D.onBeforeRender](). La valeur par défaut est `false`. +

+ +

[property:Boolean vertexColors]

+

+ Définit si la coloration des sommets est utilisée. La valeur par défaut est `false`. +

+ +

[property:String vertexShader]

+

+ Code GLSL du vertex shader. C'est le code réel du shader. Dans l'exemple ci-dessus, + le code `vertexShader` et `fragmentShader` est extrait du DOM ; il peut être passé + sous forme de chaîne de caractères ou chargé via AJAX à la place. +

+ +

[property:Boolean wireframe]

+

+ Rendre la géométrie en fil de fer (en utilisant GL_LINES au lieu de GL_TRIANGLES). La valeur par défaut est false (c'est-à-dire rendre sous forme de polygones plats). +

+ +

[property:Float wireframeLinewidth]

+

Contrôle l'épaisseur du filaire. La valeur par défaut est 1.

+ + A cause des limitations de [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] + avec le moteur de rendu [page:WebGLRenderer WebGL] sur la plupârt des plateformes, l'épaisseur de ligne (linewidth) sera toujours + à 1, indépendamment de la valeur définie. +

+ + + +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

[method:ShaderMaterial clone]()

+

+ Génère une copie superficielle de ce matériau. Notez que le vertexShader et le fragmentShader + sont copiés "par référence", de même que les définitions des "attributs" ; cela signifie + que les clones du matériel partageront la même [page:WebGLProgram] compilée. Cependant, le + `uniformes` sont copiés `par valeur`, ce qui vous permet d'avoir différents ensembles d'uniformes + pour différentes copies du matériel. +

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/ShadowMaterial.html b/docs/api/fr/materials/ShadowMaterial.html new file mode 100644 index 00000000000000..9fe8b8cc410b70 --- /dev/null +++ b/docs/api/fr/materials/ShadowMaterial.html @@ -0,0 +1,69 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

+ Ce matériau peut recevoir des ombres, mais sinon il est complètement transparent. +

+ +

Code Example

+ + + const geometry = new THREE.PlaneGeometry( 2000, 2000 ); + geometry.rotateX( - Math.PI / 2 ); + + const material = new THREE.ShadowMaterial(); + material.opacity = 0.2; + + const plane = new THREE.Mesh( geometry, material ); + plane.position.y = -200; + plane.receiveShadow = true; + scene.add( plane ); + + +

Exemples

+ +

+ [example:webgl_geometry_spline_editor geometry / spline / editor] +

+ +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+

+ + +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Color color]

+

[page:Color] couleur du matériau, noire par défaut (0x000000).

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Boolean transparent]

+

Définit si le matériau est transparent. La valeur par défaut est `true`.

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/SpriteMaterial.html b/docs/api/fr/materials/SpriteMaterial.html new file mode 100644 index 00000000000000..ded73c3f54ed18 --- /dev/null +++ b/docs/api/fr/materials/SpriteMaterial.html @@ -0,0 +1,97 @@ + + + + + + + + + + [page:Material] → + +

[name]

+ +

Un matériau pour utiliser un [page:Sprite].

+ +

Code Example

+ + + const map = new THREE.TextureLoader().load( 'textures/sprite.png' ); + const material = new THREE.SpriteMaterial( { map: map, color: 0xffffff } ); + + const sprite = new THREE.Sprite( material ); + sprite.scale.set(200, 200, 1) + scene.add( sprite ); + + +

Exemples

+

+ [example:webgl_raycaster_sprite WebGL / raycast / sprite]
+ [example:webgl_sprites WebGL / sprites]
+ [example:svg_sandbox SVG / sandbox] +

+ +

Constructeur

+ +

[name]( [param:Object parameters] )

+

+ [page:Object parameters] - (optionnel) un objet avec une ou plusieurs propriétés définissant l'apparence du matériau. + Toute propriété du matériau (y compris toute proprioété héritée de [page:Material]) peut être passée dans l'objet.

+ + L'exception est la propriété [page:Hexadecimal color], qui peut être passée comme une chaine de caractères hexadécimale, + ayant la valeur `0xffffff` (blanc) par défaut. [page:Color.set]( color ) est appelée en interne. + + Les SpriteMaterials ne sont pas coupés en utilisant [page:Material.clippingPlanes]. +

+ + +

Propriétés

+

Voir la classe [page:Material] pour les propriétés communes.

+ +

[property:Texture alphaMap]

+

La carte alpha est une texture en niveaux de gris qui contrôle l'opacité sur la surface + (noir : entièrement transparent ; blanc : entièrement opaque). La valeur par défaut est nulle.

+ + Seule la couleur de la texture est utilisée, en ignorant le canal alpha s'il en existe un. + Pour les textures RGB et RGBA, le moteur de rendu [page:WebGLRenderer WebGL] utilisera le + canal vert lors de l'échantillonnage de cette texture en raison du peu de précision supplémentaire fourni + pour le vert dans les formats RVB 565 compressés DXT et non compressés. + Les textures avec uniquement de la luminance ou les textures luminance/alpha fonctionneront également comme prévu. +

+ +

[property:Color color]

+

[page:Color], couleur du matériau, par défaut en blanc (0xffffff). The [page:.map] is multiplied by the color.

+ +

[property:Boolean fog]

+

Si le matériau est affecté par le brouillard (fog) La valeur par défaut est `true`.

+ +

[property:Boolean isSpriteMaterial]

+

+ Booléen en lecture seule pour tester si l'object est de type [name]. +

+ +

[property:Texture map]

+

+ La carte des couleurs. Peut éventuellement inclure un canal alpha, généralement combiné avec +[page:Material.transparent .transparent] ou [page:Material.alphaTest .alphaTest]. La valeur par défaut est null. +

+ +

[property:Radians rotation]

+

La rotation du sprite en radians. La valeur par défaut est 0.

+ +

[property:Boolean sizeAttenuation]

+

Si la taille du sprite est atténuée par la profondeur de la caméra. (Caméra perspective uniquement). La valeur par défaut est `true`.

+ +

[property:Boolean transparent]

+

Définit si ce matériau est transparent. La valeur par défaut est `true`.

+ +

Méthodes

+

Voir la classe [page:Material] pour les méthodes communes.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/it/cameras/OrthographicCamera.html b/docs/api/it/cameras/OrthographicCamera.html index c57542a7b7e104..b754eb10cac4a7 100644 --- a/docs/api/it/cameras/OrthographicCamera.html +++ b/docs/api/it/cameras/OrthographicCamera.html @@ -37,7 +37,6 @@

Esempi

[example:webgl_postprocessing_dof2 postprocessing / dof2 ]
[example:webgl_postprocessing_godrays postprocessing / godrays ]
[example:webgl_rtt rtt ]
- [example:webgl_shaders_tonemapping shaders / tonemapping ]
[example:webgl_shadowmap shadowmap ]

diff --git a/docs/api/it/constants/Core.html b/docs/api/it/constants/Core.html index 41e9da8d67930b..ce86c87eca583f 100644 --- a/docs/api/it/constants/Core.html +++ b/docs/api/it/constants/Core.html @@ -21,22 +21,22 @@

Numero di Revisione

Spazi Colore

-THREE.NoColorSpace -THREE.SRGBColorSpace -THREE.LinearSRGBColorSpace +THREE.NoColorSpace = "" +THREE.SRGBColorSpace = "srgb" +THREE.LinearSRGBColorSpace = "srgb-linear"

[page:NoColorSpace] non definisce uno spazio colore specifico.

- [page:SRGBColorSpace] (“sRGB”) si riferisce allo spazio colore definito dal Rec. 709 + [page:SRGBColorSpace] (“srgb”) si riferisce allo spazio colore definito dal Rec. 709 primari, punto di bianco D65 e funzioni di trasferimento sRGB non lineare. sRGB è lo spazio colore predefinito nei CSS, e si trova spesso nelle palette dei colori e nei selettori di colore. I colori espressi in esadecimale o in notazione CSS sono tipicamente nello spazio colore sRGB.

- [page:LinearSRGBColorSpace] (“Linear-sRGB”) si riferisce allo spazio colore sRGB (sopra) con + [page:LinearSRGBColorSpace] (“srgb-linear”) si riferisce allo spazio colore sRGB (sopra) con funzioni di trasferimento lineare. Linear-sRGB è lo spazio colore di lavoro in three.js, utilizzato durante la maggior parte del processo di rendering. I componenti RGB presenti nei materiali, negli shader in three.js si trovano nello spazio colore Linear-sRGB. diff --git a/docs/api/it/constants/Textures.html b/docs/api/it/constants/Textures.html index 092d89d9a5840c..7f9977c546ecdf 100644 --- a/docs/api/it/constants/Textures.html +++ b/docs/api/it/constants/Textures.html @@ -534,23 +534,27 @@

Formati Interni

[link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf Specifica OpenGL ES 3.0].

-

Encoding

+

Depth Packing

- THREE.LinearEncoding - THREE.sRGBEncoding THREE.BasicDepthPacking THREE.RGBADepthPacking

- Da usare con la proprietà [page:Texture.encoding encoding] della Texture.

- - Se il tipo di encoding viene modificato dopo che la texture è già stata utilizzata dal materiale, - sarà necessario impostare il valore [page:Material.needsUpdate Material.needsUpdate] a `true` per fare in modo - che il materiale venga ricompilato.

- - [page:constant LinearEncoding] è l'impostazione predefinita. - Valori diversi da questo sono validi solo per la mappa di un materiale, envMap ed emissiveMap. -

+ For use with the [page:MeshDepthMaterial.depthPacking depthPacking] property of `MeshDepthMaterial`. +

+ +

Color Space

+ + THREE.NoColorSpace = "" + THREE.SRGBColorSpace = "srgb" + THREE.LinearSRGBColorSpace = "srgb-linear" + +

+ Used to define the color space of textures (and the output color space of the renderer).

+ + If the color space type is changed after the texture has already been used by a material, + you will need to set [page:Material.needsUpdate Material.needsUpdate] to `true` to make the material recompile.

+

Source

diff --git a/docs/api/it/core/BufferAttribute.html b/docs/api/it/core/BufferAttribute.html index c8d97887dc11ed..67f30fada40bca 100644 --- a/docs/api/it/core/BufferAttribute.html +++ b/docs/api/it/core/BufferAttribute.html @@ -53,6 +53,13 @@

[property:Integer count]

questo conterà il numero dei vettori memorizzati.

+

[property:Number gpuType]

+

+ Configures the bound GPU type for use in shaders. Either [page:BufferAttribute THREE.FloatType] or [page:BufferAttribute THREE.IntType], default is [page:BufferAttribute THREE.FloatType]. + + Note: this only has an effect for integer arrays and is not configurable for float arrays. For lower precision float types, see [page:BufferAttributeTypes THREE.Float16BufferAttribute]. +

+

[property:Boolean isBufferAttribute]

Flag di sola lettura per verificare se un dato oggetto è di tipo [name]. diff --git a/docs/api/it/core/Raycaster.html b/docs/api/it/core/Raycaster.html index 9097b5271fab50..691b1862fde324 100644 --- a/docs/api/it/core/Raycaster.html +++ b/docs/api/it/core/Raycaster.html @@ -178,7 +178,8 @@

[method:Array intersectObject]( [param:Object3D object], [param:Boolean recu [page:Integer faceIndex] – indice della faccia intersecata
[page:Object3D object] – l'oggetto intersecato
[page:Vector2 uv] - le coordinate U,V nel punto di intersezione
- [page:Vector2 uv2] - Secondo insieme delle coordinate U,V nel punto di intersezione
+ [page:Vector2 uv1] - Secondo insieme delle coordinate U,V nel punto di intersezione
+ [page:Vector3 normal] - vettore normale interpolato nel punto di intersezione
[page:Integer instanceId] – Il numero di indice dell'istanza in cui il raggio interseca la InstancedMesh.

diff --git a/docs/api/it/extras/core/Shape.html b/docs/api/it/extras/core/Shape.html index 09390a5d5f9d33..09ac0b0b1aa9ea 100644 --- a/docs/api/it/extras/core/Shape.html +++ b/docs/api/it/extras/core/Shape.html @@ -40,8 +40,7 @@

Esempi

[example:webgl_geometry_shapes geometry / shapes ]
- [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]
- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2 ]
+ [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]

diff --git a/docs/api/it/extras/core/ShapePath.html b/docs/api/it/extras/core/ShapePath.html index 541f766361a61a..79595d06292fea 100644 --- a/docs/api/it/extras/core/ShapePath.html +++ b/docs/api/it/extras/core/ShapePath.html @@ -14,11 +14,6 @@

[name]

forma SVG in un path (vedere l'esempio seguente).

-

Esempi

-

- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2] -

-

Costruttore

diff --git a/docs/api/it/lights/Light.html b/docs/api/it/lights/Light.html index 5721ea71134dd4..1885ffa6d88bb6 100644 --- a/docs/api/it/lights/Light.html +++ b/docs/api/it/lights/Light.html @@ -40,7 +40,7 @@

[property:Color color]

[property:Float intensity]

L'intensità o la forza della luce.
- In modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta], le unità di intensità dipendono dal tipo di luce.
+ Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata, le unità di intensità dipendono dal tipo di luce.
Il valore predefinito è `1.0`.

diff --git a/docs/api/it/lights/PointLight.html b/docs/api/it/lights/PointLight.html index 106ac7f0563171..e80e14be8b7ee7 100644 --- a/docs/api/it/lights/PointLight.html +++ b/docs/api/it/lights/PointLight.html @@ -73,7 +73,7 @@

[property:Float distance]

dalla luce.

- `Modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta]` — Quando la distanza è + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata — Quando la distanza è zero, la luce si attenuerà secondo la legge dell'inverso del quadrato alla distanza infinita. Quando la distanza è diversa da zero, la luce si attenuerà secondo la legge dell'inverso del quadrato fino in prossimità del limite di distanza, dove si attenuerà quindi rapidamente e senza intoppi fino a 0. @@ -86,7 +86,7 @@

[property:Float distance]

[property:Float intensity]

L'intensità della luce. Il valore predefinito è `1`.
- Nella modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta], l'intensità + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata, l'intensità è l'intensità luminosa della luce misurata in candela (cd).

Modificando l'intensità si modificherà anche la potenza della luce. @@ -95,7 +95,7 @@

[property:Float intensity]

[property:Float power]

La potenza della luce.
- Nella modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta], la potenza è la potenza + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata, la potenza è la potenza della luminosità della luce misurata in lumen (lm).

Modificando la potenza si modificherà anche l'intensità della luce. diff --git a/docs/api/it/lights/RectAreaLight.html b/docs/api/it/lights/RectAreaLight.html index 2607c2cd8a7ef8..bdbcfcf5232f3f 100644 --- a/docs/api/it/lights/RectAreaLight.html +++ b/docs/api/it/lights/RectAreaLight.html @@ -70,7 +70,7 @@

[property:Float height]

[property:Float intensity]

L'intensità della luce. Il valore predefinito è `1`.
- Nella modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta], l'intesità è la luminanza + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata, l'intesità è la luminanza (luminosità) della luce misurata in nits (cd/m^2).

Modificando l'intensità si modificherà anche la potenza della luce. @@ -84,7 +84,7 @@

[property:Boolean isRectAreaLight]

[property:Float power]

La potenza della luce.
- Nella modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta], la potenza è la potenza + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata, la potenza è la potenza della luminosità della luce misurata in lumen (lm).

Modificando la potenza si modificherà anche l'intensità della luce. diff --git a/docs/api/it/lights/SpotLight.html b/docs/api/it/lights/SpotLight.html index 1ada80b1ad9afb..43a7d4b15583e6 100644 --- a/docs/api/it/lights/SpotLight.html +++ b/docs/api/it/lights/SpotLight.html @@ -93,7 +93,7 @@

[property:Float distance]

dalla luce.

- `Modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta]` — Quando la distanza è + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata — Quando la distanza è zero, la luce si attenuerà secondo la legge dell'inverso del quadrato alla distanza infinita. Quando la distanza è diversa da zero, la luce si attenuerà secondo la legge dell'inverso del quadrato fino in prossimità del limite di distanza, dove si attenuerà quindi rapidamente e uniformemente fino a `0`. @@ -106,7 +106,7 @@

[property:Float distance]

[property:Float intensity]

L'intensità della luce. Il valore predefinito è `1`.
- Nella modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta], l'intensità + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata, l'intensità è l'intensità luminosa della luce misurata in candela (cd).

Modificando l'intensità si modificherà anche la potenza della luce. @@ -132,7 +132,7 @@

[property:Float power]

La potenza della luce.
- Nella modalità [page:WebGLRenderer.physicallyCorrectLights fisicamente corretta], la potenza è la potenza + Quando [page:WebGLRenderer.useLegacyLights legacy lighting mode] è disabilitata, la potenza è la potenza della luminosità della luce misurata in lumen (lm).

Modificando la potenza si modificherà anche l'intensità della luce. diff --git a/docs/api/it/loaders/BufferGeometryLoader.html b/docs/api/it/loaders/BufferGeometryLoader.html index dcaff410ab02f3..d9cd60f2883802 100644 --- a/docs/api/it/loaders/BufferGeometryLoader.html +++ b/docs/api/it/loaders/BufferGeometryLoader.html @@ -46,12 +46,6 @@

Codice di Esempio

);
-

Esempi

- -

- [example:webgl_performance WebGL / performance] -

-

Costruttore

[name]( [param:LoadingManager manager] )

diff --git a/docs/api/it/loaders/managers/LoadingManager.html b/docs/api/it/loaders/managers/LoadingManager.html index 0f750dd83382d3..2bd2e7edca7775 100644 --- a/docs/api/it/loaders/managers/LoadingManager.html +++ b/docs/api/it/loaders/managers/LoadingManager.html @@ -100,7 +100,6 @@

Esempi

[example:webgl_loader_obj WebGL / loader / obj]
- [example:webgl_materials_physical_reflectivity WebGL / materials / physical / reflectivity]
[example:webgl_postprocessing_outline WebGL / postprocesing / outline]

diff --git a/docs/api/it/materials/LineBasicMaterial.html b/docs/api/it/materials/LineBasicMaterial.html index 89e18a9932d776..cdc4eb5dcd61d0 100644 --- a/docs/api/it/materials/LineBasicMaterial.html +++ b/docs/api/it/materials/LineBasicMaterial.html @@ -38,7 +38,6 @@

Esempi

[example:webgl_interactive_voxelpainter WebGL / interactive / voxelpainter]
[example:webgl_lines_colors WebGL / lines / colors]
[example:webgl_lines_dashed WebGL / lines / dashed]
- [example:webgl_lines_sphere WebGL / lines / sphere]
[example:webgl_materials WebGL / materials]
[example:physics_ammo_rope physics / ammo / rope]

@@ -90,6 +89,11 @@

[property:String linejoin]

e viene ignorata dal renderer [page:WebGLRenderer WebGL].

+

[property:Texture map]

+

+ Sets the color of the lines using data from a [page:Texture]. +

+

Metodi

Vedi la classe base [page:Material] per i metodi comuni.

diff --git a/docs/api/it/materials/Material.html b/docs/api/it/materials/Material.html index 65f7196c0960d0..00c139e6d7aa73 100644 --- a/docs/api/it/materials/Material.html +++ b/docs/api/it/materials/Material.html @@ -143,7 +143,7 @@

[property:Boolean forceSinglePass]

The engine renders double-sided, transparent objects with two draw calls (back faces first, then front faces) to mitigate transparency artifacts. There are scenarios however where this approach produces no quality gains but still doubles draw calls e.g. when rendering flat vegetation like grass sprites. - In these cases, set the `forceSinglePass` flag to `false` to disable the two pass rendering to avoid performance issues. + In these cases, set the `forceSinglePass` flag to `true` to disable the two pass rendering to avoid performance issues.

[property:Boolean isMaterial]

diff --git a/docs/api/it/materials/MeshDistanceMaterial.html b/docs/api/it/materials/MeshDistanceMaterial.html index cfe7e08491c2f5..12cd31b1fa6617 100644 --- a/docs/api/it/materials/MeshDistanceMaterial.html +++ b/docs/api/it/materials/MeshDistanceMaterial.html @@ -87,11 +87,6 @@

[property:Float displacementBias]

non viene applicato. Il valore predefinito è 0.

-

[property:Float farDistance]

-

- Il valore far della telecamera d'ombra interna della luce puntiforme. -

-

[property:Boolean fog]

Indica se il materiale è influenzato dalla nebbia. Il valore predefinito è `false`.

@@ -101,16 +96,6 @@

[property:Texture map]

[page:Material.transparent .transparent] o [page:Material.alphaTest .alphaTest]. Il valore predefinito è `null`.

-

[property:Float nearDistance]

-

- Il valore near della telecamera d'obra interna della luce puntiforme. -

- -

[property:Vector3 referencePosition]

-

- La posizione della luce puntiforme nello spazio world. -

-

Metodi

Vedi la classe base [page:Material] per i metodi comuni.

diff --git a/docs/api/it/materials/MeshPhysicalMaterial.html b/docs/api/it/materials/MeshPhysicalMaterial.html index e38648f3d1542e..cbce5a11831710 100644 --- a/docs/api/it/materials/MeshPhysicalMaterial.html +++ b/docs/api/it/materials/MeshPhysicalMaterial.html @@ -63,9 +63,7 @@

[name]

Esempi

- [example:webgl_materials_variations_physical materials / variations / physical]
[example:webgl_materials_physical_clearcoat materials / physical / clearcoat]
- [example:webgl_materials_physical_reflectivity materials / physical / reflectivity]
[example:webgl_loader_gltf_sheen loader / gltf / sheen]
[example:webgl_materials_physical_transmission materials / physical / transmission]

diff --git a/docs/api/it/materials/MeshToonMaterial.html b/docs/api/it/materials/MeshToonMaterial.html index 7c398a58411976..607f2ed557d0f9 100644 --- a/docs/api/it/materials/MeshToonMaterial.html +++ b/docs/api/it/materials/MeshToonMaterial.html @@ -33,7 +33,7 @@

[name]

Esempi

- [example:webgl_materials_variations_toon materials / variations / toon] + [example:webgl_materials_toon materials / toon]

Costruttore

diff --git a/docs/api/it/materials/PointsMaterial.html b/docs/api/it/materials/PointsMaterial.html index 3abe4d6d07e492..a692ecd1acf115 100644 --- a/docs/api/it/materials/PointsMaterial.html +++ b/docs/api/it/materials/PointsMaterial.html @@ -50,8 +50,7 @@

Esempi

[example:webgl_multiple_elements_text WebGL / multiple / elements / text]
[example:webgl_points_billboards WebGL / points / billboards]
[example:webgl_points_dynamic WebGL / points / dynamic]
- [example:webgl_points_sprites WebGL / points / sprites]
- [example:webgl_trails WebGL / trails] + [example:webgl_points_sprites WebGL / points / sprites]

Costruttore

diff --git a/docs/api/it/materials/ShaderMaterial.html b/docs/api/it/materials/ShaderMaterial.html index 94663209c4c0ad..371fff28f757eb 100644 --- a/docs/api/it/materials/ShaderMaterial.html +++ b/docs/api/it/materials/ShaderMaterial.html @@ -288,7 +288,7 @@

[property:Object defaultAttributeValues]

this.defaultAttributeValues = { 'color': [ 1, 1, 1 ], 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] + 'uv1': [ 0, 0 ] };
@@ -428,7 +428,7 @@

[property:Float wireframeLinewidth]

Metodi

Vedi la classe base [page:Material] per i metodi comuni.

-

[method:ShaderMaterial clone]() [param:ShaderMaterial this]

+

[method:ShaderMaterial clone]()

Genera una copia superficiale di questo materiale. Si noti che il vertexShader e il fragmentShader sono copiati `per riferimento`, così come le definizioni degli `attributi`; questo significa diff --git a/docs/api/it/math/Color.html b/docs/api/it/math/Color.html index 1ed186632686b2..8460c5d8679e61 100644 --- a/docs/api/it/math/Color.html +++ b/docs/api/it/math/Color.html @@ -51,7 +51,7 @@

[name]( [param:Color_Hex_or_String r], [param:Float g], [param:Float b] ) [page:Color_Hex_or_String r] - (opzionale) Se gli argomenti [page:Float g] e [page:Float b] sono definiti, indica il componente rosso del colore. Se non sono definiti, questo può essere una [link:https://en.wikipedia.org/wiki/Web_colors#Hex_triplet tripletta esadecimale] (consigliato), - una stringa CSS-style, o un'altra istanza Color.
+ una stringa CSS-style, o un'altra istanza `Color`.
[page:Float g] - (opzionale) Se è definito, indica la componente verde del colore.
[page:Float b] - (opzionale) Se è definito, indica la componente blu del colore.

@@ -181,6 +181,13 @@

[method:Object getHSL]( [param:Object target], [param:string colorSpace] = L

+

[method:Color getRGB]( [param:Color target], [param:string colorSpace] = SRGBColorSpace )

+

+ [page:Color target] - questo risultato sarà copiato in questo oggetto.

+ + Returns the RGB values of this color as an instance of [page:Color]. +

+

[method:String getStyle]( [param:string colorSpace] = SRGBColorSpace )

Restituisce il valore di questo colore come una stringa CSS style. Esempio: `rgb(255,0,0)`.

@@ -230,12 +237,15 @@

[method:this offsetHSL]( [param:Float h], [param:Float s], [param:Float l] ) aggiunge [page:Float h], [page:Float s], e [page:Float l] e poi converte il colore nero a RGB.

-

[method:this set]( [param:Color_Hex_or_String value] )

+

[method:this set]( [param:Color_Hex_or_String r], [param:Float g], [param:Float b] )

- [page:Color_Hex_or_String value] - Valore a cui impostare il valore.

+ [page:Color_Hex_or_String r] - (optional) If arguments [page:Float g] and [page:Float b] are defined, the red component of the color. If they are + not defined, it can be a [link:https://en.wikipedia.org/wiki/Web_colors#Hex_triplet hexadecimal triplet] (recommended), a CSS-style string, or another `Color` instance.
+ [page:Float g] - (optional) If it is defined, the green component of the color.
+ [page:Float b] - (optional) If it is defined, the blue component of the color.

- Vedi il costruttore sopra per i dettagli completi di quale [page:Color_Hex_or_String valore] può assumere. - Delega a [page:.copy], [page:.setStyle], o [page:.setHex] a seconda del tipo di input. + See the Constructor above for full details about possible arguments. Delegates to [page:.copy], + [page:.setStyle], [page:.setRGB] or [page:.setHex] depending on input type.

[method:this setHex]( [param:Integer hex], [param:string colorSpace] = SRGBColorSpace )

@@ -312,6 +322,11 @@

[method:Array toArray]( [param:Array array], [param:Integer offset] )

Restituisce un array della forma [ r, g, b ].

+

[method:Number toJSON]()

+

+ This methods defines the serialization result of [name]. Returns the color as a hexadecimal value. +

+

Source

diff --git a/docs/api/it/math/Matrix3.html b/docs/api/it/math/Matrix3.html index 46ebce6a0352cc..1733b712971e65 100644 --- a/docs/api/it/math/Matrix3.html +++ b/docs/api/it/math/Matrix3.html @@ -46,10 +46,12 @@

Una nota sull'ordine delle Row-Major (righe principali) e delle Column-Major

Costruttore

-

[name]()

+

[name]( [param:Number n11], [param:Number n12], [param:Number n13], + [param:Number n21], [param:Number n22], [param:Number n22], + [param:Number n31], [param:Number n32], [param:Number n33] )

- Crea e inizializza [name] nella - [link:https://en.wikipedia.org/wiki/Identity_matrix matrice] identità 3x3. + Creates a 3x3 matrix with the given arguments in row-major. If no arguments are provided, the constructor initializes + the [name] to the 3x3 [link:https://en.wikipedia.org/wiki/Identity_matrix identity matrix].

Proprietà

@@ -155,8 +157,11 @@

[method:this makeScale]( [param:Float x], [param:Float y] )

+

[method:this makeTranslation]( [param:Vector2 v] )

[method:this makeTranslation]( [param:Float x], [param:Float y] )

+ [page:Vector2 v] a translation transform from vector.
+ or
[page:Float x] - la quantità da translare sull'asse X.
[page:Float y] - la quantità da translare sull'asse Y.
diff --git a/docs/api/it/math/Matrix4.html b/docs/api/it/math/Matrix4.html index 9c794001f03026..adb460937354cb 100644 --- a/docs/api/it/math/Matrix4.html +++ b/docs/api/it/math/Matrix4.html @@ -105,11 +105,15 @@

Estrazione della posizione, della rotazione e del ridimensionamento

Costruttore

-

[name]()

+

[name]( [param:Number n11], [param:Number n12], [param:Number n13], [param:Number n14], + [param:Number n21], [param:Number n22], [param:Number n23], [param:Number n24], + [param:Number n31], [param:Number n32], [param:Number n33], [param:Number n34], + [param:Number n41], [param:Number n42], [param:Number n43], [param:Number n44] )

- Crea e inizializza [name] nella [link:https://en.wikipedia.org/wiki/Identity_matrix matrice] identità 4x4. -

+ Creates a 4x4 matrix with the given arguments in row-major order. If no arguments are provided, the constructor initializes + the [name] to the 4x4 [link:https://en.wikipedia.org/wiki/Identity_matrix identity matrix]. +

Proprietà

@@ -338,13 +342,12 @@

[method:this makeShear]( [param:Float xy], [param:Float xz], [param:Float yx

-

[method:this makeTranslation]( [param:Float x], [param:Float y], [param:Float z] )

+

[method:this makeTranslation]( [param:Vector3 v] )

+

+ [method:this makeTranslation]( [param:Float x], [param:Float y], [param:Float z] ) // optional API +

- [page:Float x] - la quantità da translare sull'asse X.
- [page:Float y] - la quantità da translare sull'asse Y.
- [page:Float z] - la quantità da translare sull'asse Z.

- - Imposta questa matrice come una trasformata di traslazione: + Imposta questa matrice come una trasformata di traslazione dal vettore [page:Vector3 v]: 1, 0, 0, x, 0, 1, 0, y, diff --git a/docs/api/it/math/Quaternion.html b/docs/api/it/math/Quaternion.html index 129ce9cb8949e4..fe993d46e06aa0 100644 --- a/docs/api/it/math/Quaternion.html +++ b/docs/api/it/math/Quaternion.html @@ -218,6 +218,11 @@

[method:Array toArray]( [param:Array array], [param:Integer offset] )

Restituisce gli elementi numerici di questo quaternione in un array del formato [x, y, z, w].

+

[method:Array toJSON]()

+

+ This methods defines the serialization result of [name]. Restituisce gli elementi numerici di questo quaternione in un array del formato [x, y, z, w]. +

+

[method:this fromBufferAttribute]( [param:BufferAttribute attribute], [param:Integer index] )

[page:BufferAttribute attribute] - l'attributo sorgente.
diff --git a/docs/api/it/math/Ray.html b/docs/api/it/math/Ray.html index 468207b2eef1e9..29090521f00253 100644 --- a/docs/api/it/math/Ray.html +++ b/docs/api/it/math/Ray.html @@ -193,7 +193,7 @@

[method:this recast]( [param:Float t] )

[method:this set]( [param:Vector3 origin], [param:Vector3 direction] )

[page:Vector3 origin] - l'[page:.origin origine] del [page:Ray raggio].
- [page:Vector3 origin] - la [page:.direction direzione] del [page:Ray raggio]. + [page:Vector3 direction] - la [page:.direction direzione] del [page:Ray raggio]. Deve essere normalizzato (con [page:Vector3.normalize]) affinchè i metodi funzionino correttamente.

Imposta le proprietà [page:.origin origine] e [page:.direction direzione] di questo raggio copiando i valori dagli oggetti dati. diff --git a/docs/api/it/math/Triangle.html b/docs/api/it/math/Triangle.html index a15cdd46041564..b7591344baf42e 100644 --- a/docs/api/it/math/Triangle.html +++ b/docs/api/it/math/Triangle.html @@ -111,15 +111,15 @@

[method:Plane getPlane]( [param:Plane target] )

Calcola il [page:Plane piano] in base al triangolo.

-

[method:Vector2 getUV]( [param:Vector3 point], [param:Vector2 uv1], [param:Vector2 uv2], [param:Vector2 uv3], [param:Vector2 target] )

+

[method:Vector2 getInterpolation]( [param:Vector3 point], [param:Vector2 v1] | [param:Vector3 v1] | [param:Vector4 v1], [param:Vector2 v2] | [param:Vector3 v2] | [param:Vector4 v3], [param:Vector2 v3] | [param:Vector3 v3] | [param:Vector4 v3], [param:Vector2 target] )

[page:Vector3 point] - Il punto sul triangolo.
- [page:Vector2 uv1] - La coordinata uv del primo vertice del triangolo.
- [page:Vector2 uv2] - La coordinata uv del secondo vertice del triangolo.
- [page:Vector2 uv3] - La coordinata uv del terzo vertice del triangolo.
- [page:Vector2 target] — il risultato sarà copiato in questo Vector2.

+ [page:Vector2 v1] - La valore del primo vertice del triangolo.
+ [page:Vector2 v2] - La valore del secondo vertice del triangolo.
+ [page:Vector2 v3] - La valore del terzo vertice del triangolo.
+ [page:Vector2 target] — il risultato sarà copiato in questo Vector.

- Restituisce le coordinate uv per il punto specificato sul triangolo. + Restituisce le valore interpolato baricentricamente per il punto specificato sul triangolo.

[method:Boolean intersectsBox]( [param:Box3 box] )

diff --git a/docs/api/it/math/Vector2.html b/docs/api/it/math/Vector2.html index 6a1ee84606ed3b..0330387d0a4814 100644 --- a/docs/api/it/math/Vector2.html +++ b/docs/api/it/math/Vector2.html @@ -100,6 +100,11 @@

[method:Float angle]()

Calcola l'angolo in radianti di questo vettore rispetto all'asse x positivo.

+

[method:Float angleTo]( [param:Vector2 v] )

+

+ Restituisce l'angolo tra questo vettore e il vettore [page:Vector2 v] in radianti. +

+

[method:this applyMatrix3]( [param:Matrix3 m] )

Moltiplica questo vettore (con un 1 implicito come terza componente) per m. diff --git a/docs/api/it/math/Vector4.html b/docs/api/it/math/Vector4.html index 16542c439c0a39..e850bf5c0124b0 100644 --- a/docs/api/it/math/Vector4.html +++ b/docs/api/it/math/Vector4.html @@ -284,7 +284,7 @@

[method:this setAxisAngleFromRotationMatrix]( [param:Matrix4 m] )

[method:this setComponent]( [param:Integer index], [param:Float value] )

- [page:Integer index] - 0, 1 o 2.
+ [page:Integer index] - 0, 1, 2 o 3.
[page:Float value] - [page:Float]

Se l'indice è uguale a 0 imposta [page:.x x] a [page:Float value].
diff --git a/docs/api/it/objects/InstancedMesh.html b/docs/api/it/objects/InstancedMesh.html index 2b5bc774e6984e..82367c746a05da 100644 --- a/docs/api/it/objects/InstancedMesh.html +++ b/docs/api/it/objects/InstancedMesh.html @@ -38,6 +38,16 @@

[name]( [param:BufferGeometry geometry], [param:Material material], [param:I

Proprietà

Vedi la classe base [page:Mesh] per le proprietà comuni.

+

[property:Box3 boundingBox]

+

+ Bounding box per la [name], che può essere calcolato con [page:.computeBoundingBox](). Il valore predefinito è `null`. +

+ +

[property:Sphere boundingSphere]

+

+ Bounding sphere per la [name], che può essere calcolato con [page:.computeBoundingSphere](). Il valore predefinito è `null`. +

+

[property:Integer count]

Il numero di istanze. Il valore `count` passato nel costruttore rappresenta il numero @@ -70,6 +80,20 @@

[property:Boolean isInstancedMesh]

Metodi

Vedi la classe base [page:Mesh] per i metodi comuni.

+

[method:undefined computeBoundingBox]()

+

+ Calcola il bounding box, aggiornando l'attributo [page:.boundingBox].
+ I Bounding box non sono calcolati per impostazione predefinita. Devono essere calcolati esplicitamente, + altrimenti sono `null`. +

+ +

[method:undefined computeBoundingSphere]()

+

+ Calcola il bounding sphere, aggiornando l'attributo [page:.boundingSphere].
+ I Bounding sphere non sono calcolati per impostazione predefinita. Devono essere calcolati esplicitamente, + altrimenti sono `null`. +

+

[method:undefined dispose]()

Libera le risorse relative alla GPU allocate da questa istanza. diff --git a/docs/api/it/objects/SkinnedMesh.html b/docs/api/it/objects/SkinnedMesh.html index b0608c714adf30..564b6600e3a3e8 100644 --- a/docs/api/it/objects/SkinnedMesh.html +++ b/docs/api/it/objects/SkinnedMesh.html @@ -117,6 +117,16 @@

[property:Matrix4 bindMatrixInverse]

La matrice di base che viene utilizzata per reimpostare le trasformazioni ossee vincolate.

+

[property:Box3 boundingBox]

+

+ Bounding box per la [name], che può essere calcolato con [page:.computeBoundingBox](). Il valore predefinito è `null`. +

+ +

[property:Sphere boundingSphere]

+

+ Bounding sphere per la [name], che può essere calcolato con [page:.computeBoundingSphere](). Il valore predefinito è `null`. +

+

[property:Boolean isSkinnedMesh]

Flag di sola lettura per verificare se l'oggetto dato è di tipo [name]. @@ -144,6 +154,20 @@

[method:SkinnedMesh clone]()

Questo metodo attualmente non clona correttamente un'istanza di [name]. Si prega di utilizzare [page:SkeletonUtils.clone]() nel frattempo.

+

[method:undefined computeBoundingBox]()

+

+ Computes the bounding box, updating [page:.boundingBox] attribute.
+ Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`. + If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box. +

+ +

[method:undefined computeBoundingSphere]()

+

+ Computes the bounding sphere, updating [page:.boundingSphere] attribute.
+ Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`. + If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere. +

+

[method:undefined normalizeSkinWeights]()

Normalizza i pesi della skin. @@ -154,15 +178,9 @@

[method:undefined pose]()

Questo metodo imposta la skinned mesh nella posa di riposo (reimposta la posa).

-

[method:Vector3 boneTransform]( [param:Integer index], [param:Vector3 target] )

+

[method:Vector3 applyBoneTransform]( [param:Integer index], [param:Vector3 vector] )

- Calcola la posizione del vertice in corrispondenza dell'indice specificato rispetto alle attuali trasformazioni ossee. - Il vettore target deve essere inizializzato con le coordinate del vertice prima della trasformazione: - -const target = new THREE.Vector3(); -target.fromBufferAttribute( mesh.geometry.attributes.position, index ); -mesh.boneTransform( index, target ); - + Applies the bone transform associated with the given index to the given position vector. Returns the updated vector.

Source

diff --git a/docs/api/it/renderers/WebGLCubeRenderTarget.html b/docs/api/it/renderers/WebGLCubeRenderTarget.html index d7ea771d77b688..5dd5358781ac01 100644 --- a/docs/api/it/renderers/WebGLCubeRenderTarget.html +++ b/docs/api/it/renderers/WebGLCubeRenderTarget.html @@ -40,7 +40,7 @@

[name]([param:Number size], [param:Object options])

[page:Constant format] - Il valore predefinito è [page:Textures RGBAFormat].
[page:Constant type] - Il valore predefinito è [page:Textures UnsignedByteType].
[page:Number anisotropy] - Il valore predefinito è `1`. Vedi [page:Texture.anisotropy]
- [page:Constant encoding] - Il valore predefinito è [page:Textures LinearEncoding].
+ [page:Constant colorSpace] - Il valore predefinito è [page:Textures NoColorSpace].
[page:Boolean depthBuffer] - Il valore predefinito è `true`.
[page:Boolean stencilBuffer] - Il valore predefinito è `false`.

diff --git a/docs/api/it/renderers/WebGLRenderTarget.html b/docs/api/it/renderers/WebGLRenderTarget.html index d0454663814a45..8c52cb134d8166 100644 --- a/docs/api/it/renderers/WebGLRenderTarget.html +++ b/docs/api/it/renderers/WebGLRenderTarget.html @@ -39,7 +39,7 @@

[name]([param:Number width], [param:Number height], [param:Object options])< [page:Constant format] - il valore predefinito è [page:Textures RGBAFormat].
[page:Constant type] - il valore predefinito è [page:Textures UnsignedByteType].
[page:Number anisotropy] - il valore predefinito è `1`. Vedi [page:Texture.anisotropy]
- [page:Constant encoding] - il valore predefinito è [page:Textures LinearEncoding].
+ [page:Constant colorSpace] - il valore predefinito è [page:Textures NoColorSpace].
[page:Boolean depthBuffer] - il valore predefinito è `true`.
[page:Boolean stencilBuffer] - il valore predefinito è `false`.
[page:Number samples] - il valore predefinito è 0.

diff --git a/docs/api/it/renderers/WebGLRenderer.html b/docs/api/it/renderers/WebGLRenderer.html index 2fcd7cda80755d..ccf8d7c1f1101a 100644 --- a/docs/api/it/renderers/WebGLRenderer.html +++ b/docs/api/it/renderers/WebGLRenderer.html @@ -103,7 +103,11 @@

[property:Object debug]

Può essere utile disabilitare questo controllo in produzione per aumentare le prestazioni. È fortemente raccomandato mantenere questi controlli attivi durante lo sviluppo. Se lo shader non si compila e non si collega - non funzionerà e il materiale associato non verrà visualizzato. - Il valore predefinito è `true`. + Il valore predefinito è `true`.
+ - [page:Function onShaderError]( gl, program, glVertexShader, glFragmentShader ): + A callback function that can be used for custom error reporting. The callback receives the WebGL context, an instance of WebGLProgram as well + two instances of WebGLShader representing the vertex and fragment shader. Assigning a custom function disables the default error reporting. + Default is `null`.

[property:Object capabilities]

@@ -171,10 +175,10 @@

[property:Object extensions]

-

[property:number outputEncoding]

-

Definisce la codifica di output del renderer. Il valore predefinito è [page:Textures THREE.LinearEncoding].

+

[property:string outputColorSpace]

+

Definisce la codifica di output del renderer. Il valore predefinito è [page:Textures THREE.SRGBColorSpace].

Se il target render è stato impostato utilizzando [page:WebGLRenderer.setRenderTarget .setRenderTarget], - verrà invece utilizzato renderTarget.texture.encoding.

+ verrà invece utilizzato renderTarget.texture.colorSpace.

Vedi la pagina [page:Textures texture constants] per i dettagli su altri formati.

[property:Object info]

@@ -219,10 +223,9 @@

[property:Object info]

[property:Boolean localClippingEnabled]

Definisce se il render rispetta i piani di taglio a livello di oggetto. Il valore predefinito è `false`.

-

[property:Boolean physicallyCorrectLights]

+

[property:Boolean useLegacyLights]

- Indica se utilizzare la modalità di illuminazione fisicamente corretta. Il valore predefinito è `false`. - Vedi l'esempio [example:webgl_lights_physical lights / physical]. + Whether to use the legacy lighting mode or not. Il valore predefinito è `true`.

[property:Object properties]

diff --git a/docs/api/it/scenes/Fog.html b/docs/api/it/scenes/Fog.html index 39d1bbefe3e194..522a3e9449da68 100644 --- a/docs/api/it/scenes/Fog.html +++ b/docs/api/it/scenes/Fog.html @@ -11,6 +11,11 @@

[name]

Questa classe contiene i parametri che definiscono la nebbia lineare, cioè che cresce linearmente con la distanza.

+

Codice di Esempio

+ + const scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0xcccccc, 10, 15 ); +

Costruttore

diff --git a/docs/api/it/scenes/FogExp2.html b/docs/api/it/scenes/FogExp2.html index 927670675b4b9d..61515b33a4d39c 100644 --- a/docs/api/it/scenes/FogExp2.html +++ b/docs/api/it/scenes/FogExp2.html @@ -15,6 +15,12 @@

[name]

a densità esponenziale più lontana dalla telecamera.

+

Codice di Esempio

+ + const scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 ); + +

Costruttore

diff --git a/docs/api/it/textures/CompressedTexture.html b/docs/api/it/textures/CompressedTexture.html index 7482bf461e341c..86f6242f34ccc9 100644 --- a/docs/api/it/textures/CompressedTexture.html +++ b/docs/api/it/textures/CompressedTexture.html @@ -22,7 +22,7 @@

[name]

Costruttore

-

[name]( [param:Array mipmaps], [param:Number width], [param:Number height], [param:Constant format], [param:Constant type], [param:Constant mapping], [param:Constant wrapS], [param:Constant wrapT], [param:Constant magFilter], [param:Constant minFilter], [param:Number anisotropy] )

+

[name]( [param:Array mipmaps], [param:Number width], [param:Number height], [param:Constant format], [param:Constant type], [param:Constant mapping], [param:Constant wrapS], [param:Constant wrapT], [param:Constant magFilter], [param:Constant minFilter], [param:Number anisotropy], [param:Constant colorSpace] )

[page:Array mipmaps] -- L'array mipmap dovrebbe contenere oggetti con dati, larghezza e altezza. Le mipmap dovrebbero essere del formato e del tipo corretti.
@@ -56,7 +56,10 @@

[name]( [param:Array mipmaps], [param:Number width], [param:Number height], [page:Number anisotropy] -- Il numero di campioni prelevati lungo l'asse attravero il pixel che ha la densità di texel più alta. Per impostazione predefinita, questo valore è 1. Un valore più alto fornisce un risultato meno sfuocato rispetto ad una mipmap di base, a costo di utilizzare più campioni di texture. Usa [page:WebGLrenderer.getMaxAnisotropy renderer.getMaxAnisotropy]() - per trovare il valore di anisotropia massimo valido per la GPU; questo valore è solitamente una potenza di 2.

+ per trovare il valore di anisotropia massimo valido per la GPU; questo valore è solitamente una potenza di 2.
+ + [page:Constant colorSpace] -- The default is [page:Textures THREE.NoColorSpace]. + See [page:Textures color space constants] for other choices.

diff --git a/docs/api/it/textures/CubeTexture.html b/docs/api/it/textures/CubeTexture.html index d5525d3ecb8870..ec378763a5edcf 100644 --- a/docs/api/it/textures/CubeTexture.html +++ b/docs/api/it/textures/CubeTexture.html @@ -31,7 +31,7 @@

Codice di Esempio

Costruttore

-

[name]( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy )

+

[name]( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace )

CubeTexture è quasi equivalente in funzionalità ed utilizzo alla classe [page:Texture]. Le uniche differenze sono che le immagini diff --git a/docs/api/it/textures/DataArrayTexture.html b/docs/api/it/textures/DataArrayTexture.html index a54843676947ed..075df901760139 100644 --- a/docs/api/it/textures/DataArrayTexture.html +++ b/docs/api/it/textures/DataArrayTexture.html @@ -89,7 +89,7 @@

Proprietà

Vedi la classe base [page:Texture Texture] per le proprietà comuni.

-

[property:Image image]

+

[property:Object image]

Sostituito con un tipo di record contenente dati, larghezza, altezza e profondità.

diff --git a/docs/api/it/textures/DataTexture.html b/docs/api/it/textures/DataTexture.html index 1daf374a4add6a..375ef99173f6c1 100644 --- a/docs/api/it/textures/DataTexture.html +++ b/docs/api/it/textures/DataTexture.html @@ -15,7 +15,7 @@

[name]

Costruttore

-

[name]( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding )

+

[name]( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace )

L'argomento data deve essere un [link:https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView ArrayBufferView]. Ulteriori parametri corrispondono alle proprietà ereditate da [page:Texture], dove sia magFilter che minFilter per impostazione predefinita sono THREE.NearestFilter. @@ -83,7 +83,7 @@

[property:Boolean generateMipmaps]

Indica se generare mipmap (se possibile) per una texture. Falso per impostazione predefinita.

-

[property:Image image]

+

[property:Object image]

Sostituito con un tipo di record contenente dati, larghezza, altezza e profondità.

diff --git a/docs/api/it/textures/FramebufferTexture.html b/docs/api/it/textures/FramebufferTexture.html index e770af62384d7c..390bb5a6df839b 100644 --- a/docs/api/it/textures/FramebufferTexture.html +++ b/docs/api/it/textures/FramebufferTexture.html @@ -16,17 +16,13 @@

[name]

Costruttore

-

[name]( [param:Number width], [param:Number height], [param:Constant format] )

+

[name]( [param:Number width], [param:Number height] )

[page:Number width] -- La larghezza della texture.
- [page:Number height] -- L'altezza della texture.
- - [page:Constant format] -- Il formato utilizzato nella texture. - Vedi [page:Textures format constants] per altre scelte.
+ [page:Number height] -- L'altezza della texture.

-

Proprietà

diff --git a/docs/api/it/textures/Texture.html b/docs/api/it/textures/Texture.html index 4a47dcd14857b8..f59aace39ff34d 100644 --- a/docs/api/it/textures/Texture.html +++ b/docs/api/it/textures/Texture.html @@ -30,7 +30,7 @@

Codice di Esempio

Costruttore

-

[name]( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding )

+

[name]( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace )

Proprietà

@@ -79,6 +79,11 @@

[property:number mapping]

Vedi la pagina [page:Textures texture constants] per altri tipi di mapping.

+

[property:Integer channel]

+

+ Lets you select the uv attribute to map the texture to. `0` for `uv`, `1` for `uv1`, `2` for `uv2` and `3` for `uv3`. +

+

[property:number wrapS]

Questo definisce come la texture è wrappata orizzontalmente e corrisponde a *U* nel mapping UV.
@@ -152,32 +157,6 @@

[property:Vector2 offset]

Di quanto una singola ripetizione della texture è sfalsata dall'inizio, in ciascuna direzione U e V. L'intervallo tipico è compreso tra `0.0` e `1.0`.

-

- I tipi di texture seguenti condividono il `primo` canale uv nel motore. L'impostazione dell'offset (e della ripetizione) viene valutata - in base alle seguenti priorità e quindi condivisa da tali texture: -

    -
  1. color map
  2. -
  3. specular map
  4. -
  5. displacement map
  6. -
  7. normal map
  8. -
  9. bump map
  10. -
  11. roughness map
  12. -
  13. metalness map
  14. -
  15. alpha map
  16. -
  17. emissive map
  18. -
  19. clearcoat map
  20. -
  21. clearcoat normal map
  22. -
  23. clearcoat roughnessMap map
  24. -
-

-

- I tipi di texture seguenti condividono il `secondo` canale uv nel motore. L'impostazione dell'offset (e della ripetizione) viene valutata - in base alle seguenti priorità e quindi condivisa da tali texture: -

    -
  1. ao map
  2. -
  3. light map
  4. -
-

[property:Vector2 repeat]

@@ -185,7 +164,6 @@

[property:Vector2 repeat]

impostata su un valore maggiore di 1 in entrambe le direzioni, anche il parametro Wrap corrispondente deve essere impostato su [page:Textures THREE.RepeatWrapping] o [page:Textures THREE.MirroredRepeatWrapping] per ottenere l'effetto di piastrellatura desiderato. - L'impostazione di diversi valori di ripetizione per le texture è limitata allo stesso modo di [page:.offset].

[property:number rotation]

@@ -247,13 +225,10 @@

[property:number unpackAlignment]

Vedi [link:http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml glPixelStorei] per maggiori informazioni.

-

[property:number encoding]

+

[property:string colorSpace]

- [page:Textures THREE.LinearEncoding] è l'impostazione predefinita. - Vedi la pagina [page:Textures texture constants] per i dettagli su altri formati.

- - Si noti che questo valore viene modificato su una texture dopo che il materiale è stato utilizzato, - è necessario attivare un Material.needsUpdate affinché questo valore venga realizzato nello shader. + [page:Textures THREE.NoColorSpace] è l'impostazione predefinita. + Vedi la pagina [page:Textures texture constants] per i dettagli su altri formati.

[property:Integer version]

diff --git a/docs/api/ko/cameras/OrthographicCamera.html b/docs/api/ko/cameras/OrthographicCamera.html index 98cf3b50a9b6f0..37816e4bd23e74 100644 --- a/docs/api/ko/cameras/OrthographicCamera.html +++ b/docs/api/ko/cameras/OrthographicCamera.html @@ -36,7 +36,6 @@

예제

[example:webgl_postprocessing_dof2 postprocessing / dof2 ]
[example:webgl_postprocessing_godrays postprocessing / godrays ]
[example:webgl_rtt rtt ]
- [example:webgl_shaders_tonemapping shaders / tonemapping ]
[example:webgl_shadowmap shadowmap ]

diff --git a/docs/api/ko/constants/BufferAttributeUsage.html b/docs/api/ko/constants/BufferAttributeUsage.html new file mode 100644 index 00000000000000..87860146bec770 --- /dev/null +++ b/docs/api/ko/constants/BufferAttributeUsage.html @@ -0,0 +1,51 @@ + + + + + + + + + +

Buffer Attribute Usage Constants

+ +

+ 사용 상수를 사용하여 성능을 최적화하기 위해 지오메트리 버퍼 속성을 사용하는 방법에 대한 힌트를 API에 제공할 수 있습니다. +

+ +

코드 예제

+ + + const geometry = new THREE.BufferGeometry(); + const positionAttribute = new THREE.BufferAttribute( array, 3 , false ); + positionAttribute.setUsage( THREE.DynamicDrawUsage ); + geometry.setAttribute( 'position', positionAttribute ); + + +

예제

+

[example:webgl_buffergeometry_drawrange materials / buffergeometry / drawrange ]

+ +

Geometry Usage

+ + THREE.StaticDrawUsage + THREE.DynamicDrawUsage + THREE.StreamDrawUsage + + THREE.StaticReadUsage + THREE.DynamicReadUsage + THREE.StreamReadUsage + + THREE.StaticCopyUsage + THREE.DynamicCopyUsage + THREE.StreamCopyUsage + + + 이러한 각 상수에 대한 자세한 내용은 [link:https://www.khronos.org/opengl/wiki/Buffer_Object#Buffer_Object_Usage this OpenGL documentation]를 참조하세요. + +

소스코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js] +

+ + \ No newline at end of file diff --git a/docs/api/ko/constants/Core.html b/docs/api/ko/constants/Core.html index b7e22bbca75de6..15c3e42b083e37 100644 --- a/docs/api/ko/constants/Core.html +++ b/docs/api/ko/constants/Core.html @@ -26,14 +26,14 @@

Color Spaces

- [page:SRGBColorSpace] (“sRGB”) refers to the color space defined by the Rec. 709 primaries, D65 + [page:SRGBColorSpace] (“srgb”) refers to the color space defined by the Rec. 709 primaries, D65 white point, and nonlinear sRGB transfer functions. sRGB is the default color space in CSS, and is often found in color palettes and color pickers. Colors expressed in hexadecimal or CSS notation are typically in the sRGB color space.

- [page:LinearSRGBColorSpace] (“Linear-sRGB”) refers to the sRGB color space (above) with + [page:LinearSRGBColorSpace] (“srgb-linear”) refers to the sRGB color space (above) with linear transfer functions. Linear-sRGB is the working color space in three.js, used throughout most of the rendering process. RGB components found in three.js materials and shaders are in the Linear-sRGB color space. diff --git a/docs/api/ko/constants/Textures.html b/docs/api/ko/constants/Textures.html index 3c9e084c314558..3e4e62177f844d 100644 --- a/docs/api/ko/constants/Textures.html +++ b/docs/api/ko/constants/Textures.html @@ -522,21 +522,26 @@

내부 포맷

[link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0 Specification]를 확인해보세요.

-

인코딩

+

Depth Packing

- THREE.LinearEncoding - THREE.sRGBEncoding THREE.BasicDepthPacking THREE.RGBADepthPacking

- 텍스쳐의 [page:Texture.encoding encoding] 프로퍼티와 함께 사용됩니다.

+ For use with the [page:MeshDepthMaterial.depthPacking depthPacking] property of `MeshDepthMaterial`. +

- 텍스쳐가 재질을 통해 이미 변경된 후에 인코딩 타입이 변경되면, - [page:Material.needsUpdate Material.needsUpdate]을 *true*로 설정해 재질을 리컴파일해야합니다.

+

Color Space

+ + THREE.NoColorSpace = "" + THREE.SRGBColorSpace = "srgb" + THREE.LinearSRGBColorSpace = "srgb-linear" + +

+ Used to define the color space of textures (and the output color space of the renderer).

- [page:constant LinearEncoding]이 기본값입니다. - 이 값으로는 재질의 map, envMap 및 emissiveMap 값만 유효합니다. + If the color space type is changed after the texture has already been used by a material, + you will need to set [page:Material.needsUpdate Material.needsUpdate] to `true` to make the material recompile.

소스 코드

diff --git a/docs/api/ko/core/BufferAttribute.html b/docs/api/ko/core/BufferAttribute.html index 060a119ad1f678..e3843d427bdb7b 100644 --- a/docs/api/ko/core/BufferAttribute.html +++ b/docs/api/ko/core/BufferAttribute.html @@ -59,6 +59,13 @@

[property:Integer count]

저장된 벡터들의 수를 계산합니다.

+

[property:Number gpuType]

+

+ Configures the bound GPU type for use in shaders. Either [page:BufferAttribute THREE.FloatType] or [page:BufferAttribute THREE.IntType], default is [page:BufferAttribute THREE.FloatType]. + + Note: this only has an effect for integer arrays and is not configurable for float arrays. For lower precision float types, see [page:BufferAttributeTypes THREE.Float16BufferAttribute]. +

+

[property:Boolean isBufferAttribute]

Read-only flag to check if a given object is of type [name]. diff --git a/docs/api/ko/core/Raycaster.html b/docs/api/ko/core/Raycaster.html index 578707eee354f8..640c5da46e4486 100644 --- a/docs/api/ko/core/Raycaster.html +++ b/docs/api/ko/core/Raycaster.html @@ -174,7 +174,8 @@

[method:Array intersectObject]( [param:Object3D object], [param:Boolean recu [page:Integer faceIndex] – 교차 면의 인덱스
[page:Object3D object] – 교차된 객체
[page:Vector2 uv] - 교차점의 U,V 좌표
- [page:Vector2 uv2] - 교차점의 U,V 2차 좌표
+ [page:Vector2 uv1] - 교차점의 U,V 2차 좌표
+ [page:Vector3 normal] - 교차점에서 보간된 법선 벡터
[page:Integer instanceId] – InstancedMesh에 교차하는 레이의 인스턴스 인덱스 넘버입니다.

diff --git a/docs/api/ko/extras/core/Shape.html b/docs/api/ko/extras/core/Shape.html index 85a3a6423777cc..2fb85213fce666 100644 --- a/docs/api/ko/extras/core/Shape.html +++ b/docs/api/ko/extras/core/Shape.html @@ -39,8 +39,7 @@

예제

[example:webgl_geometry_shapes geometry / shapes ]
- [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]
- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2 ]
+ [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]

diff --git a/docs/api/ko/extras/core/ShapePath.html b/docs/api/ko/extras/core/ShapePath.html index 51c5ac9a8e6638..e3ec60caa2e181 100644 --- a/docs/api/ko/extras/core/ShapePath.html +++ b/docs/api/ko/extras/core/ShapePath.html @@ -13,11 +13,6 @@

[name]

This class is used to convert 이 클래스는 연속된 shape들을 [page:Path] 배열로 바꾸는데에 사용되며, 일례로 SVG shape를 path로 바꾸는 것이 있습니다.(아래 예제를 확인하세요).

-

예제

-

- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2] -

-

생성자

diff --git a/docs/api/ko/geometries/BoxGeometry.html b/docs/api/ko/geometries/BoxGeometry.html new file mode 100644 index 00000000000000..89eaed1becb21c --- /dev/null +++ b/docs/api/ko/geometries/BoxGeometry.html @@ -0,0 +1,75 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ [name]는 주어진 '폭', '높이', '깊이'를 갖는 직사각형 정육면체 형상에 대한 클래스입니다. + 생성 시, 정육면체는 원점의 중심에 위치하며, 각 모서리는 축 중 하나와 평행합니다. +

+ + + + + +

코드 예제

+ + + const geometry = new THREE.BoxGeometry( 1, 1, 1 ); + const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); + const cube = new THREE.Mesh( geometry, material ); + scene.add( cube ); + + +

생성자

+ +

[name]([param:Float width], [param:Float height], [param:Float depth], [param:Integer widthSegments], [param:Integer heightSegments], [param:Integer depthSegments])

+

+ width — 너비, 즉 X축에 평행한 모서리의 길이입니다. Optional; 기본값은 1 입니다.
+ height — 높이, 즉 Y축에 평행한 가장자리의 길이입니다. Optional; 기본값은 1 입니다.
+ depth — 깊이, 즉 Z축에 평행한 가장자리의 길이입니다. Optional; 기본값은 1 입니다.
+ widthSegments — 변의 폭을 따라 분할된 직사각형 면의 수입니다. Optional; 기본값은 1 입니다.
+ heightSegments — 변의 높이를 따라 분할된 직사각형 면의 수입니다. Optional; 기본값은 1 입니다.
+ depthSegments — 변의 깊이를 따라 분할된 직사각형 면의 수입니다. Optional; 기본값은 1 입니다.
+

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/CapsuleGeometry.html b/docs/api/ko/geometries/CapsuleGeometry.html new file mode 100644 index 00000000000000..a6dab61f3d5751 --- /dev/null +++ b/docs/api/ko/geometries/CapsuleGeometry.html @@ -0,0 +1,74 @@ + + + + + + + + + + [page:BufferGeometry] → [page:LatheGeometry] → + +

[name]

+ +

+ [name]는 주어진 반지름과 높이를 가진 캡슐 형상에 대한 클래스입니다. + LatheGeometry를 사용하여 생성됩니다. +

+ + + + + +

코드 예제

+ + + const geometry = new THREE.CapsuleGeometry( 1, 1, 4, 8 ); + const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); + const capsule = new THREE.Mesh( geometry, material ); + scene.add( capsule ); + + +

생성자

+ +

[name]([param:Float radius], [param:Float length], [param:Integer capSubdivisions], [param:Integer radialSegments])

+

+ + radius — 캡슐의 반경입니다. Optional; 기본값은 1 입니다.
+ length — 중간 구역의 길이입니다. Optional; 기본값은 1 입니다.
+ capSegments — 캡을 구성하는 데 사용된 곡선 면의 수입니다. Optional; 기본값은 4 입니다.
+ radialSegments — 캡슐 둘레 주변의 분할된 면의 수입니다. Optional; 기본값은 8 입니다.
+

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/CircleGeometry.html b/docs/api/ko/geometries/CircleGeometry.html new file mode 100644 index 00000000000000..e738a6c89da0c8 --- /dev/null +++ b/docs/api/ko/geometries/CircleGeometry.html @@ -0,0 +1,75 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ [name]는 유클리드 기하학의 단순한 모양입니다. + 중심점을 중심으로 방향을 잡고 주어진 반경만큼 멀리 뻗어있는 많은 삼각형 세그먼트로 구성됩니다. + 시작 각도와 주어진 중심 각도에서 시계 반대 방향으로 만들어집니다. + 세그먼트의 수가 변의 수를 결정하는 정규 다각형을 만드는 데도 사용할 수 있습니다. +

+ + + + + +

코드 예제

+ + + const geometry = new THREE.CircleGeometry( 5, 32 ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); + const circle = new THREE.Mesh( geometry, material ); + scene.add( circle ); + + +

생성자

+ +

[name]([param:Float radius], [param:Integer segments], [param:Float thetaStart], [param:Float thetaLength])

+

+ radius — 원의 반지름, 기본값 = 1.
+ segments — 세그먼트 수(삼각형), 최소값 = 3, 기본값 = 32.
+ thetaStart — 첫 세그먼트의 각도 시작, 기본값 = 0 (3시 위치).
+ thetaLength — 원형 섹터의 중심 각도(흔히 세타라고 함)입니다. 기본값은 완전한 원을 만드는 2*Pi 입니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/ConeGeometry.html b/docs/api/ko/geometries/ConeGeometry.html new file mode 100644 index 00000000000000..f6225ee469fe92 --- /dev/null +++ b/docs/api/ko/geometries/ConeGeometry.html @@ -0,0 +1,73 @@ + + + + + + + + + + [page:BufferGeometry] → [page:CylinderGeometry] → + +

[name]

+ +

원뿔 형상을 생성하기 위한 클래스입니다.

+ + + + + +

코드 예제

+ + + const geometry = new THREE.ConeGeometry( 5, 20, 32 ); + const material = new THREE.MeshBasicMaterial( {color: 0xffff00} ); + const cone = new THREE.Mesh( geometry, material ); + scene.add( cone ); + + +

생성자

+ +

[name]([param:Float radius], [param:Float height], [param:Integer radialSegments], [param:Integer heightSegments], [param:Boolean openEnded], [param:Float thetaStart], [param:Float thetaLength])

+

+ radius — 원뿔 밑면의 반지름입니다. 기본값은 1 입니다.
+ height — 원뿔의 높이입니다. 기본값은 1 입니다.
+ radialSegments — 원뿔 둘레 주변의 분할된 면의 수입니다. 기본값은 32 입니다.
+ heightSegments — 원뿔 높이를 따라 있는 면의 행 수입니다. 기본값은 1 입니다.
+ openEnded — 원뿔의 밑면이 열려 있는지 닫혀 있는지를 나타내는 부울입니다. 기본값은 닫힘을 의미하는 false 입니다.
+ thetaStart — 첫 번째 세그먼트의 시작 각도, 기본값은 0 입니다 (3시 위치).
+ thetaLength — 원형 섹터의 중심 각도(흔히 세타라고 함)입니다. 기본값은 완전한 원을 만드는 2*Pi 입니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:CylinderGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:CylinderGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/CylinderGeometry.html b/docs/api/ko/geometries/CylinderGeometry.html new file mode 100644 index 00000000000000..781c2e818afa8e --- /dev/null +++ b/docs/api/ko/geometries/CylinderGeometry.html @@ -0,0 +1,74 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

실린더 형상을 생성하기 위한 클래스입니다..

+ + + + + +

코드 예제

+ + + const geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 ); + const material = new THREE.MeshBasicMaterial( {color: 0xffff00} ); + const cylinder = new THREE.Mesh( geometry, material ); + scene.add( cylinder ); + + +

생성자

+ +

[name]([param:Float radiusTop], [param:Float radiusBottom], [param:Float height], [param:Integer radialSegments], [param:Integer heightSegments], [param:Boolean openEnded], [param:Float thetaStart], [param:Float thetaLength])

+

+ radiusTop — 상단에서 원통의 반지름입니다. 기본값은 1 입니다.
+ radiusBottom — 바닥에서 원통의 반지름입니다. 기본값은 1 입니다.
+ height — 실린더의 높이입니다. 기본값은 1 입니다.
+ radialSegments — 실린더 원주 주위의 분할된 면의 수입니다. 기본값은 32 입니다.
+ heightSegments — 원통 높이를 따라 있는 면의 행 수입니다. 기본값은 1 입니다.
+ openEnded — 원뿔의 끝이 열려 있는지 닫혀 있는지를 나타내는 부울입니다. 기본값은 닫힘을 의미하는 false 입니다.
+ thetaStart — 첫 번째 세그먼트의 시작 각도, 기본값은 0 입니다 (3시 위치).
+ thetaLength — 원형 섹터의 중심 각도(흔히 세타라고 함)입니다. 기본값은 완전한 실린더를 만드는 2*Pi 입니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/DodecahedronGeometry.html b/docs/api/ko/geometries/DodecahedronGeometry.html new file mode 100644 index 00000000000000..46d7db1fe267b8 --- /dev/null +++ b/docs/api/ko/geometries/DodecahedronGeometry.html @@ -0,0 +1,59 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] → + +

[name]

+ +

12면체 형상을 생성하기 위한 클래스입니다.

+ + + + + +

생성자

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — 12면체의 반지름입니다. 기본값은 1입니다.
+ detail — 기본값은 0 입니다. 이 값을 0보다 큰 값으로 설정하면 정점이 추가되어 더 이상 12면체가 아닙니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/EdgesGeometry.html b/docs/api/ko/geometries/EdgesGeometry.html new file mode 100644 index 00000000000000..20cee02217f166 --- /dev/null +++ b/docs/api/ko/geometries/EdgesGeometry.html @@ -0,0 +1,55 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

[page:BufferGeometry geometry]는 지오메트리의 모서리를 보기 위한 도우미 개체로 사용할 수 있습니다.

+ +

코드 예제

+ + + const geometry = new THREE.BoxGeometry( 100, 100, 100 ); + const edges = new THREE.EdgesGeometry( geometry ); + const line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0xffffff } ) ); + scene.add( line ); + + +

예제

+

+ [example:webgl_helpers helpers] +

+ +

생성자

+ +

[name]( [param:BufferGeometry geometry], [param:Integer thresholdAngle] )

+

+ geometry — 모든 기하학 객체.
+ thresholdAngle — 인접한 면의 면 법선 사이의 각도 (단위는 도)가 이 값을 초과하는 경우에만 가장자리가 렌더링됩니다. 기본값 = 1도. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/ExtrudeGeometry.html b/docs/api/ko/geometries/ExtrudeGeometry.html new file mode 100644 index 00000000000000..5adff6ec07dff1 --- /dev/null +++ b/docs/api/ko/geometries/ExtrudeGeometry.html @@ -0,0 +1,111 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

경로 모양에서 돌출된 형상을 만듭니다.

+ + + + + +

코드 예제

+ + + + const length = 12, width = 8; + + const shape = new THREE.Shape(); + shape.moveTo( 0,0 ); + shape.lineTo( 0, width ); + shape.lineTo( length, width ); + shape.lineTo( length, 0 ); + shape.lineTo( 0, 0 ); + + const extrudeSettings = { + steps: 2, + depth: 16, + bevelEnabled: true, + bevelThickness: 1, + bevelSize: 1, + bevelOffset: 0, + bevelSegments: 1 + }; + + const geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings ); + const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + const mesh = new THREE.Mesh( geometry, material ) ; + scene.add( mesh ); + + + +

생성자

+ + +

[name]([param:Array shapes], [param:Object options])

+

+ shapes — 모양 또는 모양의 배열입니다.
+ options — 다음 매개변수를 포함할 수 있는 객체입니다. + +

    +
  • curveSegments — int. 곡선의 점 수. 기본값은 12 입니다.
  • +
  • steps — int. 돌출된 스플라인의 깊이를 따라 세그먼트를 세분화하는 데 사용되는 점 수입니다. 기본값은 1 입니다.
  • +
  • depth — float. 모양을 돌출시킬 깊이입니다. 기본값은 1 입니다.
  • +
  • bevelEnabled — bool. 모양에 베벨링을 적용합니다. 기본값은 true 입니다.
  • +
  • bevelThickness — float. 베벨이 원래 모양으로 들어가는 깊이입니다. 기본값은 0.2 입니다.
  • +
  • bevelSize — float. 베벨이 확장되는 모양 윤곽선으로부터의 거리입니다. 기본값은 bevelThickness - 0.1 입니다.
  • +
  • bevelOffset — float. 경사가 시작되는 모양 윤곽선으로부터의 거리입니다. 기본값은 0 입니다.
  • +
  • bevelSegments — int. 베벨 레이어 수. 기본값은 3 입니다.
  • +
  • extrudePath — THREE.Curve. 모양이 돌출되어야 하는 3D 스플라인 경로입니다. 경로 돌출에는 베벨이 지원되지 않습니다.
  • +
  • UVGenerator — Object. UV 제너레이터 기능을 제공하는 객체
  • +
+ +

+

+ 이 객체는 2D 모양을 3D 형상으로 돌출시킵니다. +

+ +

+ 이 지오메트리로 메시를 생성할 때 면과 돌출된 면에 별도의 재질을 사용하려는 경우 여러 재질을 사용할 수 있습니다. 첫 번째 재질이 얼굴에 적용됩니다. 두 번째 재료는 측면에 적용됩니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/IcosahedronGeometry.html b/docs/api/ko/geometries/IcosahedronGeometry.html new file mode 100644 index 00000000000000..23dcf0230954f2 --- /dev/null +++ b/docs/api/ko/geometries/IcosahedronGeometry.html @@ -0,0 +1,58 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] → +

[name]

+ +

20면체 형상을 생성하기 위한 클래스입니다.

+ + + + + +

생성자

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — 기본값은 1 입니다.
+ detail — 기본값은 0 입니다. 이 값을 0보다 큰 값으로 설정하면 정점이 더 추가되어 더 이상 20면체가 아닙니다. 디테일이 1보다 크면 사실상 구체입니다. +

+ +

프로퍼티

+

일반 프로퍼티 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/LatheGeometry.html b/docs/api/ko/geometries/LatheGeometry.html new file mode 100644 index 00000000000000..dcfa72725e5aac --- /dev/null +++ b/docs/api/ko/geometries/LatheGeometry.html @@ -0,0 +1,77 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

꽃병과 같은 축 대칭으로 메쉬를 만듭니다. 선반은 Y축을 중심으로 회전합니다.

+ + + + + +

코드 예제

+ + + const points = []; + for ( let i = 0; i < 10; i ++ ) { + points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) ); + } + const geometry = new THREE.LatheGeometry( points ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); + const lathe = new THREE.Mesh( geometry, material ); + scene.add( lathe ); + + +

생성자

+ +

[name]([param:Array points], [param:Integer segments], [param:Float phiStart], [param:Float phiLength])

+

+ points — Vector2의 배열. 각 점의 x 좌표는 0보다 커야 합니다. 기본값은 단순한 다이아몬드 모양을 만드는 (0,-0.5), (0.5,0) 및 (0,0.5)의 배열입니다.
+ segments — 생성할 원주 세그먼트의 수입니다. 기본값은 12 입니다.
+ phiStart — 시작 각도(라디안 단위). 기본값은 0 입니다.
+ phiLength — 선반 섹션의 라디안(0 ~ 2PI) 범위 2PI는 닫힌 선반이고, 2PI 미만이 한 부분입니다. 기본값은 2PI 입니다. +

+

+ 이렇게 하면 매개변수를 기반으로 [name]가 생성됩니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성을 가진 개체입니다. 인스턴스화 후에 수정해도 지오메트리는 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/OctahedronGeometry.html b/docs/api/ko/geometries/OctahedronGeometry.html new file mode 100644 index 00000000000000..82b4cd2881d95a --- /dev/null +++ b/docs/api/ko/geometries/OctahedronGeometry.html @@ -0,0 +1,58 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] → +

[name]

+ +

팔면체 형상을 생성하기 위한 클래스입니다..

+ + + + + +

생성자

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — 팔면체의 반지름. 기본값은 1 입니다.
+ detail — 기본값은 0 입니다. 이 값을 0보다 큰 값으로 설정하면 정점이 더 이상 팔면체가 아닙니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/PlaneGeometry.html b/docs/api/ko/geometries/PlaneGeometry.html new file mode 100644 index 00000000000000..89f227119d5672 --- /dev/null +++ b/docs/api/ko/geometries/PlaneGeometry.html @@ -0,0 +1,70 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

평면 형상을 생성하기 위한 클래스입니다.

+ + + + + +

코드 예제

+ + + const geometry = new THREE.PlaneGeometry( 1, 1 ); + const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} ); + const plane = new THREE.Mesh( geometry, material ); + scene.add( plane ); + + +

생성자

+ +

[name]([param:Float width], [param:Float height], [param:Integer widthSegments], [param:Integer heightSegments])

+

+ width — X축의 너비입니다. 기본값은 1 입니다.
+ height — Y축의 높이입니다. 기본값은 1 입니다.
+ widthSegments — Optional. 기본값은 1 입니다.
+ heightSegments — Optional. 기본값은 1 입니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/PolyhedronGeometry.html b/docs/api/ko/geometries/PolyhedronGeometry.html new file mode 100644 index 00000000000000..9c26d55d66a1e1 --- /dev/null +++ b/docs/api/ko/geometries/PolyhedronGeometry.html @@ -0,0 +1,67 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

+ 다면체는 평평한 면을 가진 3차원 입체입니다. 이 클래스는 정점 배열을 구에 투영한 다음 원하는 세부 수준으로 나눕니다. + 이 클래스는 [page:DodecahedronGeometry], [page:IcosahedronGeometry], [page:OctahedronGeometry], + 및 [page:TetrahedronGeometry] 에서 각각의 형상을 생성하는 데 사용됩니다 . +

+ +

코드 예제

+ + const verticesOfCube = [ + -1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1, + -1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1, + ]; + + const indicesOfFaces = [ + 2,1,0, 0,3,2, + 0,4,7, 7,3,0, + 0,1,5, 5,4,0, + 1,2,6, 6,5,1, + 2,3,7, 7,6,2, + 4,5,6, 6,7,4 + ]; + + const geometry = new THREE.PolyhedronGeometry( verticesOfCube, indicesOfFaces, 6, 2 ); + + +

생성자

+ + +

[name]([param:Array vertices], [param:Array indices], [param:Float radius], [param:Integer detail])

+

+ vertices — 다음과 같은 형태의 점 [page:Array] [1,1,1, -1,-1,-1, ... ]
+ indices — 다음과 같은 형식의 면을 구성하는 인덱스들의 [page:Array] [0,1,2, 2,3,0, ... ]
+ radius — [page:Float] - 최종 모양의 반지름
+ detail — [page:Integer] - 지오메트리를 세분화할 레벨 수. 디테일이 많을수록 모양이 부드러워집니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/RingGeometry.html b/docs/api/ko/geometries/RingGeometry.html new file mode 100644 index 00000000000000..78081255c396a3 --- /dev/null +++ b/docs/api/ko/geometries/RingGeometry.html @@ -0,0 +1,73 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

2차원 링 형상을 생성하기 위한 클래스입니다.

+ + + + + +

코드 예제

+ + + const geometry = new THREE.RingGeometry( 1, 5, 32 ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } ); + const mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + +

생성자

+ +

[name]([param:Float innerRadius], [param:Float outerRadius], [param:Integer thetaSegments], [param:Integer phiSegments], [param:Float thetaStart], [param:Float thetaLength])

+

+ innerRadius — 기본값은 0.5 입니다.
+ outerRadius — 기본값은 1 입니다.
+ thetaSegments — 세그먼트 수. 숫자가 높을수록 링이 더 둥글다는 의미입니다. 최소값은 3 입니다. 기본값은 32 입니다.
+ phiSegments — 최소값은 1 입니다. 기본값은 1 입니다.
+ thetaStart — 시작 각도입니다. 기본값은 0 입니다.
+ thetaLength — 중심 각도입니다. 기본값은 Math.PI * 2 입니다. +

+ + +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 찹조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/ShapeGeometry.html b/docs/api/ko/geometries/ShapeGeometry.html new file mode 100644 index 00000000000000..8e0eadd31c0e85 --- /dev/null +++ b/docs/api/ko/geometries/ShapeGeometry.html @@ -0,0 +1,83 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

하나 이상의 경로 모양에서 한면 다각형 형상을 만듭니다.

+ + + + + + +

코드 예제

+ + + + const x = 0, y = 0; + + const heartShape = new THREE.Shape(); + + heartShape.moveTo( x + 5, y + 5 ); + heartShape.bezierCurveTo( x + 5, y + 5, x + 4, y, x, y ); + heartShape.bezierCurveTo( x - 6, y, x - 6, y + 7,x - 6, y + 7 ); + heartShape.bezierCurveTo( x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19 ); + heartShape.bezierCurveTo( x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7 ); + heartShape.bezierCurveTo( x + 16, y + 7, x + 16, y, x + 10, y ); + heartShape.bezierCurveTo( x + 7, y, x + 5, y + 5, x + 5, y + 5 ); + + const geometry = new THREE.ShapeGeometry( heartShape ); + const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + const mesh = new THREE.Mesh( geometry, material ) ; + scene.add( mesh ); + + +

생성자

+ + +

[name]([param:Array shapes], [param:Integer curveSegments])

+

+ shapes — 모양의 [page:Array] 또는 단일 [page:Shape shape]. 기본값은 단일 삼각형 모양입니다.
+ curveSegments - [page:Integer] - 모양당 세그먼트 수입니다. 기본값은 12 입니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/SphereGeometry.html b/docs/api/ko/geometries/SphereGeometry.html new file mode 100644 index 00000000000000..eb13eaa4d01a72 --- /dev/null +++ b/docs/api/ko/geometries/SphereGeometry.html @@ -0,0 +1,78 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

구 형상을 생성하기 위한 클래스입니다.

+ + + + + +

코드 예제

+ + + const geometry = new THREE.SphereGeometry( 15, 32, 16 ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); + const sphere = new THREE.Mesh( geometry, material ); + scene.add( sphere ); + + +

생성자

+ +

[name]([param:Float radius], [param:Integer widthSegments], [param:Integer heightSegments], [param:Float phiStart], [param:Float phiLength], [param:Float thetaStart], [param:Float thetaLength])

+ +

+ radius — 구 반지름. Default is 1.
+ widthSegments — 수평 세그먼트의 수입니다. 최소값은 3 입니다, 그리고 기본값은 32 입니다.
+ heightSegments — 수직 세그먼트의 수입니다. 최소값은 2 입니다, 그리고 기본값은 16 입니다.
+ phiStart — 수평 시작 각도를 지정합니다. 기본값은 0 입니다.
+ phiLength — 수평 스위프 각도 크기를 지정합니다. 기본값은 Math.PI * 2 입니다.
+ thetaStart — 수직 시작 각도를 지정합니다. 기본값은 0 입니다.
+ thetaLength — 수직 스위프 각도 크기를 지정합니다. 기본값은 Math.PI 입니다.
+

+ +

+ 지오메트리는 Y축(수평 스윕)과 Z축(수직 스윕) 주위의 정점을 스윕하고 계산하여 생성됩니다.따라서, 우리가 정점 계산을 시작(또는 종료)하는 지점을 정의하기 위해, 다른 값의 phiStart, phiLength, 세타Start 및 세타Length를 사용하여 불완전한 구('sphere slices' 와 유사한)를 만들 수 있다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/TetrahedronGeometry.html b/docs/api/ko/geometries/TetrahedronGeometry.html new file mode 100644 index 00000000000000..7fe0a148982f63 --- /dev/null +++ b/docs/api/ko/geometries/TetrahedronGeometry.html @@ -0,0 +1,59 @@ + + + + + + + + + + [page:BufferGeometry] → [page:PolyhedronGeometry] → + +

[name]

+ +

사면체 형상을 생성하기 위한 클래스입니다.

+ + + + + +

생성자

+ +

[name]([param:Float radius], [param:Integer detail])

+

+ radius — 사면체의 반지름. 기본값은 1 입니다.
+ detail — 기본값은 0 입니다. 이 값을 0보다 큰 값으로 설정하면 정점이 추가되어 더 이상 사면체가 아닙니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:PolyhedronGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/TorusGeometry.html b/docs/api/ko/geometries/TorusGeometry.html new file mode 100644 index 00000000000000..ca7326981bfc76 --- /dev/null +++ b/docs/api/ko/geometries/TorusGeometry.html @@ -0,0 +1,71 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

도넛 모양 형상을 생성하기 위한 클래스입니다.

+ + + + + +

코드 예제

+ + + const geometry = new THREE.TorusGeometry( 10, 3, 16, 100 ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); + const torus = new THREE.Mesh( geometry, material ); + scene.add( torus ); + + +

생성자

+ +

[name]([param:Float radius], [param:Float tube], [param:Integer radialSegments], [param:Integer tubularSegments], [param:Float arc])

+

+ radius - 도넛 모양 중심에서 튜브 중심까지의 도넛 모양 반경. 기본값은 1 입니다.
+ tube — 튜브의 반경입니다. 기본값은 0.4 입니다.
+ radialSegments — 기본값은 12 입니다.
+ tubularSegments — 기본값은 48 입니다.
+ arc — 중심 각도입니다. 기본값은 Math.PI * 2 입니다. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/TorusKnotGeometry.html b/docs/api/ko/geometries/TorusKnotGeometry.html new file mode 100644 index 00000000000000..6b2ec2d10016f2 --- /dev/null +++ b/docs/api/ko/geometries/TorusKnotGeometry.html @@ -0,0 +1,74 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

도넛 모양 매듭의 특정 모양이 한 쌍의 서로소 정수(p 및 q)로 정의되는 도넛 모양 매듭을 만듭니다. p와 q가 서로소가 아니면 결과는 도넛 모양 링크가 됩니다.

+ + + + + +

코드 예제

+ + + const geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 ); + const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); + const torusKnot = new THREE.Mesh( geometry, material ); + scene.add( torusKnot ); + + +

생성자

+ +

[name]([param:Float radius], [param:Float tube], [param:Integer tubularSegments], [param:Integer radialSegments], [param:Integer p], [param:Integer q])

+

+

    +
  • radius - 도넛 모양의 반경. 기본값은 1 입니다.
  • +
  • tube — 큐브의 반경. 기본값은 0.4 입니다.
  • +
  • tubularSegments — 기본값은 64 입니다.
  • +
  • radialSegments — 기본값은 8 입니다.
  • +
  • p — 이 값은 형상이 회전 대칭 축 주위를 감는 횟수를 결정합니다. 기본값은 2 입니다.
  • +
  • q — 이 값은 형상이 도넛 모양 내부의 원 주위를 감는 횟수를 결정합니다. 기본값은 3 입니다.
  • +
+

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/TubeGeometry.html b/docs/api/ko/geometries/TubeGeometry.html new file mode 100644 index 00000000000000..c784127b634d26 --- /dev/null +++ b/docs/api/ko/geometries/TubeGeometry.html @@ -0,0 +1,111 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

3D 커브를 따라 돌출되는 튜브를 생성합니다.

+ + + + + +

코드 예제

+ + + class CustomSinCurve extends THREE.Curve { + + constructor( scale = 1 ) { + + super(); + + this.scale = scale; + + } + + getPoint( t, optionalTarget = new THREE.Vector3() ) { + + const tx = t * 3 - 1.5; + const ty = Math.sin( 2 * Math.PI * t ); + const tz = 0; + + return optionalTarget.set( tx, ty, tz ).multiplyScalar( this.scale ); + + } + + } + + const path = new CustomSinCurve( 10 ); + const geometry = new THREE.TubeGeometry( path, 20, 2, 8, false ); + const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + const mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + +

생성자

+ + +

[name]([param:Curve path], [param:Integer tubularSegments], [param:Float radius], [param:Integer radialSegments], [param:Boolean closed])

+

+ path — [page:Curve] - [page:Curve] 기본 클래스 에서 상속되는 3D 경로입니다. 기본값은 2차 베지어 곡선입니다.
+ tubularSegments — [page:Integer] - 튜브를 구성하는 세그먼트 수입니다. 기본값은 64 입니다.
+ radius — [page:Float] - 튜브의 반지름입니다. 기본값은 1 입니다.
+ radialSegments — [page:Integer] - 횡단면을 구성하는 세그먼트의 수입니다. 기본값은 8 입니다.
+ closed — [page:Boolean] 튜브가 열려 있거나 닫혀 있는지 여부입니다. 기본값은 false 입니다.
+

+ + +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

[property:Object parameters]

+

+ 각 생성자 매개 변수에 대한 속성이 있는 개체입니다. 인스턴스화 후 수정해도 형상은 변경되지 않습니다. +

+ +

[property:Array tangents]

+

+ [page:Vector3] 접선의 배열 +

+ +

[property:Array normals]

+

+ [page:Vector3] 법선의 배열 +

+ +

[property:Array binormals]

+

+ [page:Vector3] 종법선의 배열 +

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/ko/geometries/WireframeGeometry.html b/docs/api/ko/geometries/WireframeGeometry.html new file mode 100644 index 00000000000000..c27c36ce5447b7 --- /dev/null +++ b/docs/api/ko/geometries/WireframeGeometry.html @@ -0,0 +1,56 @@ + + + + + + + + + + [page:BufferGeometry] → + +

[name]

+ +

[page:BufferGeometry geometry] 와이어프레임으로 보기 위한 도우미 오브젝트로 사용할 수 있습니다.

+ +

코드 예제

+ + + const geometry = new THREE.SphereGeometry( 100, 100, 100 ); + + const wireframe = new THREE.WireframeGeometry( geometry ); + + const line = new THREE.LineSegments( wireframe ); + line.material.depthTest = false; + line.material.opacity = 0.25; + line.material.transparent = true; + + scene.add( line ); + + +

예제

+ +

+ [example:webgl_helpers helpers] +

+ +

생성자

+ +

[name]( [param:BufferGeometry geometry] )

+

+ geometry — any geometry object. +

+ +

프로퍼티

+

일반 프로퍼티는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

메서드

+

일반 메서드는 기본 [page:BufferGeometry] 클래스를 참조하십시오.

+ +

소스 코드

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/pt-br/cameras/OrthographicCamera.html b/docs/api/pt-br/cameras/OrthographicCamera.html index c4636a06bb53a1..007bf1702213fe 100644 --- a/docs/api/pt-br/cameras/OrthographicCamera.html +++ b/docs/api/pt-br/cameras/OrthographicCamera.html @@ -37,7 +37,6 @@

Exemplos

[example:webgl_postprocessing_dof2 postprocessing / dof2 ]
[example:webgl_postprocessing_godrays postprocessing / godrays ]
[example:webgl_rtt rtt ]
- [example:webgl_shaders_tonemapping shaders / tonemapping ]
[example:webgl_shadowmap shadowmap ]

diff --git a/docs/api/pt-br/cameras/PerspectiveCamera.html b/docs/api/pt-br/cameras/PerspectiveCamera.html index a0329c2b364695..2f854629292cfb 100644 --- a/docs/api/pt-br/cameras/PerspectiveCamera.html +++ b/docs/api/pt-br/cameras/PerspectiveCamera.html @@ -90,7 +90,7 @@

[property:Float near]

Plano próximo do tronco da câmera. O padrão é `0.1`.

- O intervalo válido é maior que 0 e menor que o valor atual do plano [page:.far far] (distante). + O intervalo válido é maior que `0` e menor que o valor atual do plano [page:.far far] (distante). Observe que, diferentemente da [page:OrthographicCamera], `0` não é um valor válido para um plano próximo da PerspectiveCamera.

diff --git a/docs/api/pt-br/constants/Core.html b/docs/api/pt-br/constants/Core.html index 795980e3a4246c..669232320f52f7 100644 --- a/docs/api/pt-br/constants/Core.html +++ b/docs/api/pt-br/constants/Core.html @@ -21,22 +21,22 @@

Número de Revisão

Espaço de Cores

-THREE.NoColorSpace -THREE.SRGBColorSpace -THREE.LinearSRGBColorSpace +THREE.NoColorSpace = "" +THREE.SRGBColorSpace = "srgb" +THREE.LinearSRGBColorSpace = "srgb-linear"

[page:NoColorSpace] não define nenhum espaço de cor específico.

- [page:SRGBColorSpace] (“sRGB”) refere-se ao espaço de cores definido pelo Rec. 709 primárias, D65 + [page:SRGBColorSpace] (“srgb”) refere-se ao espaço de cores definido pelo Rec. 709 primárias, D65 ponto branco e funções de transferência sRGB não lineares. sRGB é o espaço de cor padrão em CSS, e é frequentemente encontrado em paletas e seletores de cores. Cores expressas em notação hexadecimal ou CSS estão normalmente no espaço de cores sRGB.

- [page:LinearSRGBColorSpace] (“Linear-sRGB”) refere-se ao espaço de cores sRGB (acima) com + [page:LinearSRGBColorSpace] (“srgb-linear”) refere-se ao espaço de cores sRGB (acima) com funções de transferência lineares. Linear-sRGB é o espaço de cores de trabalho em three.js, usado durante a maior parte do processo de renderização. Componentes RGB encontrados em materiais three.js e os shaders estão no espaço de cores Linear-sRGB. diff --git a/docs/api/pt-br/constants/Textures.html b/docs/api/pt-br/constants/Textures.html index 29e21adfcc2c4f..43b5f6c28f539e 100644 --- a/docs/api/pt-br/constants/Textures.html +++ b/docs/api/pt-br/constants/Textures.html @@ -534,21 +534,26 @@

Formatos Internos

a especificação [link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0].

-

Encoding

+

Depth Packing

- THREE.LinearEncoding - THREE.sRGBEncoding THREE.BasicDepthPacking THREE.RGBADepthPacking

- Para uso com a propriedade [page:Texture.encoding encoding] de uma textura.

+ For use with the [page:MeshDepthMaterial.depthPacking depthPacking] property of `MeshDepthMaterial`. +

- Se o tipo de codificação for alterado após a textura já ter sido usada por um material, - você precisará definir [page:Material.needsUpdate Material.needsUpdate] como `true` para fazer o material recompilar.

+

Color Space

+ + THREE.NoColorSpace = "" + THREE.SRGBColorSpace = "srgb" + THREE.LinearSRGBColorSpace = "srgb-linear" + +

+ Used to define the color space of textures (and the output color space of the renderer).

- [page:constant LinearEncoding] é o padrão. - Valores diferentes deste são válidos apenas para o mapa de um material, envMap e emissiveMap. + If the color space type is changed after the texture has already been used by a material, + you will need to set [page:Material.needsUpdate Material.needsUpdate] to `true` to make the material recompile.

Source

diff --git a/docs/api/zh/cameras/OrthographicCamera.html b/docs/api/zh/cameras/OrthographicCamera.html index b07bd82e261d54..6073f29efbb213 100644 --- a/docs/api/zh/cameras/OrthographicCamera.html +++ b/docs/api/zh/cameras/OrthographicCamera.html @@ -37,7 +37,6 @@

例子

[example:webgl_postprocessing_dof2 postprocessing / dof2 ]
[example:webgl_postprocessing_godrays postprocessing / godrays ]
[example:webgl_rtt rtt ]
- [example:webgl_shaders_tonemapping shaders / tonemapping ]
[example:webgl_shadowmap shadowmap ]

diff --git a/docs/api/zh/constants/Core.html b/docs/api/zh/constants/Core.html index b70697cd7b358d..7124c93cc3c644 100644 --- a/docs/api/zh/constants/Core.html +++ b/docs/api/zh/constants/Core.html @@ -26,14 +26,14 @@

Color Spaces

- [page:SRGBColorSpace] (“sRGB”) refers to the color space defined by the Rec. 709 primaries, D65 + [page:SRGBColorSpace] (“srgb”) refers to the color space defined by the Rec. 709 primaries, D65 white point, and nonlinear sRGB transfer functions. sRGB is the default color space in CSS, and is often found in color palettes and color pickers. Colors expressed in hexadecimal or CSS notation are typically in the sRGB color space.

- [page:LinearSRGBColorSpace] (“Linear-sRGB”) refers to the sRGB color space (above) with + [page:LinearSRGBColorSpace] (“srgb-linear”) refers to the sRGB color space (above) with linear transfer functions. Linear-sRGB is the working color space in three.js, used throughout most of the rendering process. RGB components found in three.js materials and shaders are in the Linear-sRGB color space. diff --git a/docs/api/zh/constants/Textures.html b/docs/api/zh/constants/Textures.html index 758db0ad507e3d..893a4f5d06873a 100644 --- a/docs/api/zh/constants/Textures.html +++ b/docs/api/zh/constants/Textures.html @@ -517,21 +517,26 @@

Internal Formats

to the [link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0 Specification].

-

编码

+

Depth Packing

- THREE.LinearEncoding - THREE.sRGBEncoding - THREE.BasicDepthPacking - THREE.RGBADepthPacking - + THREE.BasicDepthPacking + THREE.RGBADepthPacking +

- 这些常量用于纹理的[page:Texture.encoding encoding]属性。

+ For use with the [page:MeshDepthMaterial.depthPacking depthPacking] property of `MeshDepthMaterial`. +

- 如果编码类型在纹理已被一个材质使用之后发生了改变, - 你需要来设置[page:Material.needsUpdate Material.needsUpdate]为*true*来使得材质重新编译。

+

Color Space

+ + THREE.NoColorSpace = "" + THREE.SRGBColorSpace = "srgb" + THREE.LinearSRGBColorSpace = "srgb-linear" + +

+ Used to define the color space of textures (and the output color space of the renderer).

- [page:constant LinearEncoding]是默认值。 - 除此之外的其他值仅在材质的贴图、envMap和emissiveMap中有效。 + If the color space type is changed after the texture has already been used by a material, + you will need to set [page:Material.needsUpdate Material.needsUpdate] to `true` to make the material recompile.

源代码

diff --git a/docs/api/zh/core/BufferAttribute.html b/docs/api/zh/core/BufferAttribute.html index 929d4af72dd761..98203c6085a9e9 100644 --- a/docs/api/zh/core/BufferAttribute.html +++ b/docs/api/zh/core/BufferAttribute.html @@ -16,11 +16,10 @@

[name]

在 BufferAttribute 中,数据被存储为任意长度的矢量(通过[page:BufferAttribute.itemSize itemSize]进行定义),下列函数如无特别说明, 函数参数中的index会自动乘以矢量长度进行计算。 - When working with vector-like data, the .fromBufferAttribute( attribute, index ) - helper methods on [page:Vector2.fromBufferAttribute Vector2], - [page:Vector3.fromBufferAttribute Vector3], - [page:Vector4.fromBufferAttribute Vector4], and - [page:Color.fromBufferAttribute Color] classes may be helpful. + 当想要处理类似向量的数据时, + 可以使用在[page:Vector2.fromBufferAttribute Vector2],[page:Vector3.fromBufferAttribute Vector3], + [page:Vector4.fromBufferAttribute Vector4]以及[page:Color.fromBufferAttribute Color]这些类中的.fromBufferAttribute( attribute, index ) + 方法来更为便捷地处理。

构造函数

@@ -57,9 +56,16 @@

[property:Integer count]

若缓存存储三元组(例如顶点位置、法向量、颜色值),则该值应等于队列中三元组的个数。

+

[property:Number gpuType]

+

+ Configures the bound GPU type for use in shaders. Either [page:BufferAttribute THREE.FloatType] or [page:BufferAttribute THREE.IntType], default is [page:BufferAttribute THREE.FloatType]. + + Note: this only has an effect for integer arrays and is not configurable for float arrays. For lower precision float types, see [page:BufferAttributeTypes THREE.Float16BufferAttribute]. +

+

[property:Boolean isBufferAttribute]

- Read-only flag to check if a given object is of type [name]. + 用于判断对象是否为[name]类型的只读标记.

[property:Integer itemSize]

@@ -96,9 +102,8 @@

[property:Object updateRange]

[property:Usage usage]

- Defines the intended usage pattern of the data store for optimization purposes. Corresponds to the *usage* parameter of - [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData](). - Default is [page:BufferAttributeUsage StaticDrawUsage]. See usage [page:BufferAttributeUsage constants] for all possible values. + 为输入的数据定义最优的预估使用方式。等同于在[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData]() + 中的*usage*参数。默认为[page:BufferAttributeUsage StaticDrawUsage]。在usage [page:BufferAttributeUsage constants]中查看可用值。

[property:Integer version]

@@ -108,16 +113,16 @@

[property:Integer version]

方法

[method:this applyMatrix3]( [param:Matrix3 m] )

-

Applies matrix [page:Matrix3 m] to every Vector3 element of this BufferAttribute.

+

将矩阵[page:Matrix3 m]应用此BufferAttribute中的每一个Vector3元素中。

[method:this applyMatrix4]( [param:Matrix4 m] )

-

Applies matrix [page:Matrix4 m] to every Vector3 element of this BufferAttribute.

+

将矩阵[page:Matrix4 m]应用到此BufferAttribute的每一个Vector3元素中

[method:this applyNormalMatrix]( [param:Matrix3 m] )

-

Applies normal matrix [page:Matrix3 m] to every Vector3 element of this BufferAttribute.

+

将正规矩阵[page:Matrix3 m]应用到此BufferAttribute的每一个Vector3元素中

[method:this transformDirection]( [param:Matrix4 m] )

-

Applies matrix [page:Matrix4 m] to every Vector3 element of this BufferAttribute, interpreting the elements as a direction vectors.

+

将矩阵[page:Matrix4 m]应用到此BufferAttribute的每一个Vector3元素中,并将所有元素解释为方向向量。

[method:BufferAttribute clone]()

返回该 BufferAttribute 的拷贝。

diff --git a/docs/api/zh/core/BufferGeometry.html b/docs/api/zh/core/BufferGeometry.html index 5551016ce4fa88..a6142f561ccc53 100644 --- a/docs/api/zh/core/BufferGeometry.html +++ b/docs/api/zh/core/BufferGeometry.html @@ -125,20 +125,19 @@

[property:BufferAttribute index]

[property:Boolean isBufferGeometry]

- Read-only flag to check if a given object is of type [name]. + 用于判断对象是否为[name]的只读标记.

[property:Object morphAttributes]

存储 [page:BufferAttribute] 的 Hashmap,存储了几何体 morph targets 的细节信息。
- Note: Once the geometry has been rendered, the morph attribute data cannot be changed. You will have to call [page:.dispose](), and create a new instance of [name]. + 注意:当这个geometry渲染之后,morph attribute 数据无法更改。你需要调用[page:.dispose](),并重新创建一个新的[name]实例。

[property:Boolean morphTargetsRelative]

- Used to control the morph target behavior; when set to true, the morph target data is treated as relative offsets, rather than as absolute positions/normals. - - Default is *false*. + 用于控制morph target的行为,如果设置为 `true`,morph target数据作为相对的偏移量,而非绝对的位置/法向。 + 默认为*false*。

[property:String name]

@@ -202,9 +201,8 @@

[method:undefined computeBoundingSphere]()

[method:undefined computeTangents]()

- Calculates and adds a tangent attribute to this geometry.
- The computation is only supported for indexed geometries and if position, normal, and uv attributes are defined. When using a tangent space normal map, prefer the MikkTSpace algorithm provided by - [page:BufferGeometryUtils.computeMikkTSpaceTangents] instead. + 计算并向此geometry中添加tangent attribute。
+ 只支持索引化的几何体对象,并且必须拥有position(位置),normal(法向)和 uv attributes。如果使用了切线空间法向贴图,最好使用[page:BufferGeometryUtils.computeMikkTSpaceTangents]中的MikkTSpace算法。

[method:undefined computeVertexNormals]()

@@ -223,7 +221,7 @@

[method:BufferAttribute getIndex] ()

返回缓存相关的 [page:.index]。

[method:Boolean hasAttribute]( [param:String name] )

-

Returns *true* if the attribute with the specified name exists.

+

检查是否存在有指定名称的attribute,如果有返回*true*。

[method:this lookAt] ( [param:Vector3 vector] )

diff --git a/docs/api/zh/core/GLBufferAttribute.html b/docs/api/zh/core/GLBufferAttribute.html index ac1a4f02545502..d013c8ea4cce5e 100644 --- a/docs/api/zh/core/GLBufferAttribute.html +++ b/docs/api/zh/core/GLBufferAttribute.html @@ -10,28 +10,21 @@

[name]

- This buffer attribute class does not construct a VBO. Instead, it uses - whatever VBO is passed in constructor and can later be altered via the - *buffer* property.

- It is required to pass additional params alongside the VBO. Those are: - the GL context, the GL data type, the number of components per vertex, - the number of bytes per component, and the number of vertices.

- The most common use case for this class is when some kind of GPGPU - calculation interferes or even produces the VBOs in question. + 此缓冲区属性类不构造 VBO。相反,它使用在构造函数中传递的任何 VBO,以后可以通过 缓冲区属性进行更改。

+ 它需要与 VBO 一起传递额外的参数。它们是:GL 上下文、GL 数据类型、每个顶点的组件数、每个组件的字节数和顶点数。

+ 此类最常见的用例是当某种 GPGPU 计算干扰甚至产生有问题的 VBO 时。

-

Constructor

+

构造方法(Constructor)

[name]( [param:WebGLBuffer buffer], [param:GLenum type], [param:Integer itemSize], [param:Integer elementSize], [param:Integer count] )

- *buffer* — Must be a [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer]. + *buffer* — 必须是 [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer].
- *type* — One of [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL Data Types]. + *type* — [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL数据类型]之一.
- *itemSize* — The number of values of the array that should be associated with - a particular vertex. For instance, if this - attribute is storing a 3-component vector (such as a position, normal, or color), then itemSize should be 3. + *itemSize* — 应与特定顶点关联的数组值的数量。例如,如果此属性存储一个3分量向量(例如位置、法线或颜色),则itemSize应为 3。
- *elementSize* — 1, 2 or 4. The corresponding size (in bytes) for the given "type" param. + *elementSize* — 1、2 或 4。给定的相应大小(以字节为单位)“类型”参数。

  • gl.FLOAT: 4
  • gl.UNSIGNED_SHORT: 2
  • @@ -41,79 +34,77 @@

    [name]( [param:WebGLBuffer buffer], [param:GLenum type], [param:Integer item
  • gl.BYTE: 1
  • gl.UNSIGNED_BYTE: 1
- *count* — The expected number of vertices in VBO. + *count* — VBO 中预期的顶点数。

-

Properties

+

特性(Properties)

[property:WebGLBuffer buffer]

- The current [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer] instance. + 当前[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer]的实例.

[property:Integer count]

- The expected number of vertices in VBO. + VBO 中的预期顶点数。

[property:Boolean isGLBufferAttribute]

- Read-only. Always *true*. + 只读。值永远为"true"。

[property:Integer itemSize]

- How many values make up each item (vertex). + 每个项目(顶点)组成多少个值。

[property:Integer elementSize]

- Stores the corresponding size in bytes for the current *type* property value. + 存储当前类型属性值的相应大小(以字节为单位)。

- See above (constructor) for a list of known type sizes. + 有关已知类型大小的列表,请参见上面的(构造函数)。

[property:String name]

- 该 attribute 实例的别名,默认值为空字符串。 + 该attribute实例的别名,默认值为空字符串。

[property:GLenum type]

- A [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL Data Type] - describing the underlying VBO contents. + 描述底层 VBO 内容的[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Data_types WebGL数据类型]

- Set this property together with *elementSize*. The recommended way is - using the *setType* method. + 将此属性与elementSize一起设置。推荐的方法是使用setType方法。

-

Methods

+

方法(Methods)

[method:this setBuffer]( buffer )

-

Sets the *buffer* property.

+

设置缓冲区属性。

[method:this setType]( type, elementSize )

-

Sets the both *type* and *elementSize* properties.

+

设置type和elementSize属性。

[method:this setItemSize]( itemSize )

-

Sets the *itemSize* property.

+

设置itemSize属性。

[method:this setCount]( count )

-

Sets the *count* property.

+

设置计数属性。

[property:Integer version]

- A version number, incremented every time the needsUpdate property is set to true. + 版本号,每次将needsUpdate属性设置为true时递增。

[property:Boolean needsUpdate]

- Default is *false*. Setting this to true increments [page:GLBufferAttribute.version version]. + 默认为假。将此设置为 true 增量[page:GLBufferAttribute.version 版本]

-

Source

+

源代码(Source)

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/zh/core/Object3D.html b/docs/api/zh/core/Object3D.html index 3494bc2d5ca4af..23aa484440b449 100644 --- a/docs/api/zh/core/Object3D.html +++ b/docs/api/zh/core/Object3D.html @@ -30,7 +30,7 @@

[name]()

属性

[property:AnimationClip animations]

-

Array with object's animation clips.

+

三维物体所属的动画剪辑数组.

[property:Boolean castShadow]

对象是否被渲染到阴影贴图中。默认值为*false*。

@@ -39,17 +39,17 @@

[property:Array children]

含有对象的子级的数组。请参阅[page:Group]来了解将手动对象进行分组的相关信息。

[property:Material customDepthMaterial]

-

Custom depth material to be used when rendering to the depth map. Can only be used in context of meshes. - When shadow-casting with a [page:DirectionalLight] or [page:SpotLight], if you are modifying vertex positions in the vertex shader you must specify a customDepthMaterial for proper shadows. Default is *undefined*. +

在渲染到深度图的时候所用的自定义深度材质。 只能在网格中使用。 + 当使用[page:DirectionalLight](平行光)或者[page:SpotLight](聚光灯光)生成影子的时候, 如果你调整过顶点着色器中的顶点位置,就需要定义一个自定义深度材质来生成正确的影子。默认为*undefined*.

[property:Material customDistanceMaterial]

-

与[page:.customDepthMaterial customDepthMaterial]相同,但与[page:PointLight]一起使用。默认值为*undefined*。 +

与[page:.customDepthMaterial customDepthMaterial]相同,但与[page:PointLight](点光源)一起使用。默认值为*undefined*。

[property:Boolean frustumCulled]

- When this is set, it checks every frame if the object is in the frustum of the camera before rendering the object. If set to `false` the object gets rendered every frame even if it is not in the frustum of the camera. Default is `true`. + 当这个设置了的时候,每一帧渲染前都会检测这个物体是不是在相机的视椎体范围内。 如果设置为`false` 物体不管是不是在相机的视椎体范围内都会渲染。默认为`true`。

[property:Integer id]

@@ -57,14 +57,13 @@

[property:Integer id]

[property:Boolean isObject3D]

- Read-only flag to check if a given object is of type [name]. + 查看所给对象是不是[name]类型的只读标记.

[property:Layers layers]

物体的层级关系。 - 物体只有和一个正在使用的[page:Camera]至少在同一个层时才可见。This property can also be used to filter out - unwanted objects in ray-intersection tests when using [page:Raycaster]. + 物体只有和一个正在使用的[page:Camera]至少在同一个层时才可见。当使用[page:Raycaster]进行射线检测的时候此项属性可以用于过滤不参与检测的物体.

[property:Matrix4 matrix]

@@ -82,9 +81,8 @@

[property:Matrix4 matrixWorld]

[property:Boolean matrixWorldAutoUpdate]

- If set, then the renderer checks every frame if the object and its children need matrix updates. - When it isn't, then you have to maintain all matrices in the object and its children yourself. - Default is [page:Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE] (true). + 默认为 true. 当设置的时候,渲染器在每一帧都会检查物体自身以及它的自带是否需要更新世界变换矩阵。 + 如果不需要的话它自身以及它的子代的所有世界变换矩阵都需要你来维护。

[property:Boolean matrixWorldNeedsUpdate]

@@ -114,9 +112,8 @@

[property:Function onAfterRender]

使用以下参数来调用此函数:renderer,scene,camera,geometry,material,group。

- Please notice that this callback is only executed for *renderable* 3D objects. Meaning 3D objects which define their visual - appearance with geometries and materials like instances of [page:Mesh], [page:Line], [page:Points] or [page:Sprite]. - Instances of [page:Object3D], [page:Group] or [page:Bone] are not renderable and thus this callback is not executed for such objects. + 注意此回调函数只会在*可渲染*的3D物体上执行。可渲染的3D物体指的是那种拥有视觉表现的、定义了几何体与材质的物体,例如像是[page:Mesh]、[page:Line]、[page:Points] 或者[page:Sprite]。 + [page:Object3D]、 [page:Group] 或者 [page:Bone] 这些是不可渲染的物体,因此此回调函数不会在这样的物体上执行。

[property:Function onBeforeRender]

@@ -125,9 +122,8 @@

[property:Function onBeforeRender]

使用以下参数来调用此函数:renderer,scene,camera,geometry,material,group。

- Please notice that this callback is only executed for *renderable* 3D objects. Meaning 3D objects which define their visual - appearance with geometries and materials like instances of [page:Mesh], [page:Line], [page:Points] or [page:Sprite]. - Instances of [page:Object3D], [page:Group] or [page:Bone] are not renderable and thus this callback is not executed for such objects. + 注意此回调函数只会在*可渲染*的3D物体上执行。可渲染的3D物体指的是那种拥有视觉表现的、定义了几何体与材质的物体,例如像是[page:Mesh]、[page:Line]、[page:Points] 或者[page:Sprite]。 + [page:Object3D]、 [page:Group] 或者 [page:Bone] 这些是不可渲染的物体,因此此回调函数不会在这样的物体上执行。

[property:Object3D parent]

@@ -452,10 +448,10 @@

[method:undefined updateMatrixWorld]( [param:Boolean force] )

[method:undefined updateWorldMatrix]( [param:Boolean updateParents], [param:Boolean updateChildren] )

- updateParents - recursively updates global transform of ancestors.
- updateChildren - recursively updates global transform of descendants.

+ updateParents - 递归更新物体的所有祖先的全局变换.
+ updateChildren - 递归更新物体的所有后代的全局变换.

- Updates the global transform of the object. + 更新物体的全局变换。

[method:Vector3 worldToLocal]( [param:Vector3 vector] )

diff --git a/docs/api/zh/core/Raycaster.html b/docs/api/zh/core/Raycaster.html index d2dbfa32e9be71..69b88138a9158e 100644 --- a/docs/api/zh/core/Raycaster.html +++ b/docs/api/zh/core/Raycaster.html @@ -179,7 +179,8 @@

[method:Array intersectObject]( [param:Object3D object], [param:Boolean recu [page:Integer faceIndex] —— 相交的面的索引
[page:Object3D object] —— 相交的物体
[page:Vector2 uv] —— 相交部分的点的UV坐标。
- [page:Vector2 uv2] —— Second set of U,V coordinates at point of intersection
+ [page:Vector2 uv1] —— Second set of U,V coordinates at point of intersection
+ [page:Vector3 normal] - 交点处的内插法向量
[page:Integer instanceId] – The index number of the instance where the ray intersects the InstancedMesh

diff --git a/docs/api/zh/extras/PMREMGenerator.html b/docs/api/zh/extras/PMREMGenerator.html index 98576d94aa5783..0e4f4e90a5c549 100644 --- a/docs/api/zh/extras/PMREMGenerator.html +++ b/docs/api/zh/extras/PMREMGenerator.html @@ -10,67 +10,64 @@

[name]

- This class generates a Prefiltered, Mipmapped Radiance Environment Map (PMREM) from a cubeMap environment texture. - This allows different levels of blur to be quickly accessed based on material roughness. It is packed into a special - CubeUV format that allows us to perform custom interpolation so that we can support nonlinear formats such as RGBE. - Unlike a traditional mipmap chain, it only goes down to the LOD_MIN level (above), and then creates extra even more - filtered 'mips' at the same LOD_MIN resolution, associated with higher roughness levels. In this way we maintain - resolution to smoothly interpolate diffuse lighting while limiting sampling computation. + 此类从立方体贴图环境纹理生成经过预过滤的Mipmapped辐射环境贴图(PMREM)。 + 这允许根据材料粗糙度快速访问不同级别的模糊。 + 它被打包成一种特殊的CubeUV格式,允许我们执行自定义插值,以便我们可以支持RGBE等非线性格式。 + 与传统的mipmap链不同,它只下降到LOD_MIN级别(上图),然后以相同的 LOD_MIN 分辨率创建额外的甚至更多的过滤“mips”,并与更高的粗糙度级别相关联。 + 通过这种方式,我们保持分辨率以平滑地插入漫射照明,同时限制采样计算。

-

Constructor

+

构造器(Constructor)

[name]( [param:WebGLRenderer renderer] )

- This constructor creates a new [name]. + 此构造函数创建一个新的[name]。

-

Methods

+

方法(Methods)

[method:WebGLRenderTarget fromScene]( [param:Scene scene], [param:Number sigma], [param:Number near], [param:Number far] )

- [page:Scene scene] - The given scene.
- [page:Number sigma] - (optional) Specifies a blur radius in radians to be applied to the scene before PMREM generation. Default is *0*.
- [page:Number near] - (optional) The near plane value. Default is *0.1*.
- [page:Number far] - (optional) The far plane value. Default is *100*.

+ [page:Scene scene] - 给定的场景
+ [page:Number sigma] - (可选)指定在PMREM生成之前应用于场景的以弧度为单位的模糊半径。默认为0。
+ [page:Number near] - (可选)近平面值,默认值为0.1。
+ [page:Number far] - (可选)远平面值。默认值为100。

- Generates a PMREM from a supplied Scene, which can be faster than using an image if networking bandwidth is low. - Optional near and far planes ensure the scene is rendered in its entirety (the cubeCamera is placed at the origin). + 从提供的场景生成PMREM,如果网络带宽较低,这可能比使用图像更快。可选的近平面和远平面确保场景被完整渲染(cubeCamera放置在原点)。

[method:WebGLRenderTarget fromEquirectangular]( [param:Texture equirectangular] )

- [page:Texture equirectangular] - The equirectangular texture.

+ [page:Texture equirectangular] - equirectangular纹理。

- Generates a PMREM from an equirectangular texture, which can be either LDR or HDR. - The ideal input image size is 1k (1024 x 512), as this matches best with the 256 x 256 cubemap output. + 从等距柱状纹理生成PMREM,可以是LDR或HDR。理想的输入图像大小为1k(1024x512),因为这与256x256立方体贴图输出最匹配。

[method:WebGLRenderTarget fromCubemap]( [param:CubeTexture cubemap] )

- [page:CubeTexture cubemap] - The cubemap texture.

+ [page:CubeTexture cubemap] - 立方体贴图纹理。

- Generates a PMREM from an cubemap texture, which can be either LDR or HDR. - The ideal input cube size is 256 x 256, as this matches best with the 256 x 256 cubemap output. + 从立方体贴图纹理生成PMREM,可以是LDR或HDR。理想的输入立方体大小为256x256,因为这与 256x256立方体贴图输出最匹配。

[method:undefined compileCubemapShader]()

- Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during your texture's network fetch for increased concurrency. + 预编译立方体贴图着色器。您可以通过在纹理的网络获取期间调用此方法来提高并发性,从而加快启动速度。

[method:undefined compileEquirectangularShader]()

- Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during your texture's network fetch for increased concurrency. + 预编译等距柱状着色器。您可以通过在纹理的网络获取期间调用此方法来提高并发性,从而加快启动速度。

[method:undefined dispose]()

- Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, so you should not need more than one - PMREMGenerator object. If you do, calling dispose() on one of them will cause any others to also become unusable. + 处理PMREMGenerator的内部存储器。 + 请注意,PMREMGenerator是一个静态类,因此您不需要多个PMREMGenerator对象。 + 如果这样做,对其中之一调用dispose()将导致任何其他对象也变得不可用。

-

Source

+

源代码(Source)

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/extras/core/Shape.html b/docs/api/zh/extras/core/Shape.html index 65d226006e63b6..e8f8bdce8454a8 100644 --- a/docs/api/zh/extras/core/Shape.html +++ b/docs/api/zh/extras/core/Shape.html @@ -40,8 +40,7 @@

例子

[example:webgl_geometry_shapes geometry / shapes ]
- [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]
- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2 ] + [example:webgl_geometry_extrude_shapes geometry / extrude / shapes ]

构造函数

diff --git a/docs/api/zh/extras/core/ShapePath.html b/docs/api/zh/extras/core/ShapePath.html index 11247d3a073128..d58d483a30e8e9 100644 --- a/docs/api/zh/extras/core/ShapePath.html +++ b/docs/api/zh/extras/core/ShapePath.html @@ -13,11 +13,6 @@

形状路径([name])

该类用于转换一系列的形状为一个[page:Path]数组,例如转换SVG中的Path为three.js中的Path(请参阅下方的example)。

-

例子

-

- [example:webgl_geometry_extrude_shapes2 geometry / extrude / shapes2] -

-

构造函数

diff --git a/docs/api/zh/geometries/CapsuleGeometry.html b/docs/api/zh/geometries/CapsuleGeometry.html new file mode 100644 index 00000000000000..7b9feeb186ca4b --- /dev/null +++ b/docs/api/zh/geometries/CapsuleGeometry.html @@ -0,0 +1,76 @@ + + + + + + + + + + [page:BufferGeometry] → [page:LatheGeometry] → + +

[name]

+ +

+ [name]是一个胶囊图形类,通过半径和高度来进行构造。使用lathe来进行构造。 +

+ + + + + +

代码示例

+ + +const geometry = new THREE.CapsuleGeometry( 1, 1, 4, 8 ); +const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); +const capsule = new THREE.Mesh( geometry, material ); scene.add( capsule ); + + +

构造函数

+ +

+ [name]([param:Float radius], [param:Float length], [param:Integer capSubdivisions], [param:Integer radialSegments]) +

+

+ radius — 胶囊半径。可选的; 默认值为1。
+ length — 中间区域的长度。可选的; 默认值为1。
+ capSegments — 构造盖子的曲线部分的个数。可选的; 默认值为4。
+ radialSegments — 覆盖胶囊圆周的分离的面的个数。可选的; 默认值为8。
+

+ +

属性

+

查看公共属性请参考基类[page:BufferGeometry]。

+ +

[property:Object parameters]

+

+ 有属性的构造函数参数对象。任何实例化之后的修改都不会改变图形。 +

+ +

方法

+

查看公共属性请参考基类[page:BufferGeometry]。

+ +

源码

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/zh/lights/AmbientLight.html b/docs/api/zh/lights/AmbientLight.html index 8f954543fdc8b5..dcdf3a019a9be0 100644 --- a/docs/api/zh/lights/AmbientLight.html +++ b/docs/api/zh/lights/AmbientLight.html @@ -20,18 +20,18 @@

[name]

代码示例

- const light = new THREE.AmbientLight( 0x404040 ); // soft white light + const light = new THREE.AmbientLight( 0x404040 ); // 柔和的白光 scene.add( light );

构造函数

-

[name]( [param:Integer color], [param:Float intensity] )

+

[name]( [param:Color color], [param:Float intensity] )

- [page:Integer color] - (参数可选)颜色的rgb数值。缺省值为 0xffffff。
- [page:Float intensity] - (参数可选)光照的强度。缺省值为 1。

+ [page:Color color] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照的强度。默认值为 1。

- 创建一个环境光对象。 + 创建一个环境光对象。

属性

@@ -39,14 +39,9 @@

属性

公共属性请查看基类 [page:Light Light]。

-

[property:Boolean castShadow]

-

- 这个参数在对象构造的时候就被设置成了 *undefined* 。因为环境光不能投射阴影。 -

-

[property:Boolean isAmbientLight]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

diff --git a/docs/api/zh/lights/AmbientLightProbe.html b/docs/api/zh/lights/AmbientLightProbe.html index c19c0e6db99546..97b0a0f7f90cfb 100644 --- a/docs/api/zh/lights/AmbientLightProbe.html +++ b/docs/api/zh/lights/AmbientLightProbe.html @@ -20,25 +20,25 @@

构造函数

[name]( [param:Color color], [param:Float intensity] )

- [page:Color color] - (可选)一个表示颜色的 Color 的实例、字符串或数字。
- [page:Float intensity] - (可选)光照探针强度的数值。默认值为1。

+ [page:Color color] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照探针强度的数值。默认值为 1。

- 创建一个新的[name]。 + 创建一个新的[name]。

属性

- See the base [page:LightProbe LightProbe] class for common properties. + 公共属性请查看基类 [page:LightProbe LightProbe]。

[property:Boolean isAmbientLightProbe]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

方法

- See the base [page:LightProbe LightProbe] class for common methods. + 公共方法请查看基类 [page:LightProbe LightProbe]。

源码

diff --git a/docs/api/zh/lights/DirectionalLight.html b/docs/api/zh/lights/DirectionalLight.html index 8ab0787b88a0bd..68ccb278fd5a29 100644 --- a/docs/api/zh/lights/DirectionalLight.html +++ b/docs/api/zh/lights/DirectionalLight.html @@ -12,21 +12,21 @@

平行光([name])

- 平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 - 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。

+ 平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光的效果。 + 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。

平行光可以投射阴影 - 跳转至 [page:DirectionalLightShadow] 查看更多细节。

关于位置、目标和旋转说明

- Three.js 的平行光常见的困惑是设置旋转没有效果。这是因为 three.js 的平行光类似与其他引擎的"目标平行光"。 + Three.js 的平行光常见的困惑是设置旋转没有效果。这是因为 three.js 的平行光类似与其他引擎的“目标平行光”。

- 这意味着它的方向是从一个平行光的位置 [page:Object3D.position position] 到 [page:.target target]的位置。 - (而不是一个只有旋转分量的'自由平行光')。

+ 这意味着它的方向是从一个平行光的位置 [page:Object3D.position position] 到 [page:.target target] 的位置。 + (而不是一个只有旋转分量的“自由平行光”)。

- 这样做的原因是为了让光线投射阴影。[page:.shadow shadow]摄像机需要一个位置来计算阴影。

+ 这样做是为了让光线投射阴影。[page:.shadow shadow] 摄像机需要一个位置来计算阴影。

有关更新目标的详细信息,请参阅 [page:.target target] 下面的目标属性。

@@ -34,7 +34,7 @@

关于位置、目标和旋转说明

代码示例

- // White directional light at half intensity shining from the top. + // 从上方照射的白色平行光,强度为 0.5。 const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 ); scene.add( directionalLight ); @@ -50,10 +50,10 @@

例子

构造器

-

[name]( [param:Integer color], [param:Float intensity] )

+

[name]( [param:Color color], [param:Float intensity] )

- [page:Integer color] - (可选参数) 16进制表示光的颜色。 缺省值为 0xffffff (白色)。
- [page:Float intensity] - (可选参数) 光照的强度。缺省值为1。

+ [page:Color color] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照的强度。默认值为 1。

创建一个新的 [name]。

@@ -64,63 +64,60 @@

属性

[property:Boolean castShadow]

- 如果设置为 *true* 该平行光会产生动态阴影。 警告: 这样做的代价比较高而且需要一直调整到阴影看起来正确. - 查看 [page:DirectionalLightShadow] 了解详细信息。该属性默认为 *false*。 + 此属性设置为 `true` 灯光将投射阴影。*注意*:这样做的代价比较高,需要通过调整让阴影看起来正确。 + 查看 [page:DirectionalLightShadow] 了解详细信息。 + 默认值为 `false`。

[property:Boolean isDirectionalLight]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

[property:Vector3 position]

- 假如这个值设置等于 [page:Object3D.DEFAULT_UP] (0, 1, 0),那么光线将会从上往下照射。 + 假如这个值设置为 [page:Object3D.DEFAULT_UP] (0, 1, 0),光线将会从上往下照射。

[property:DirectionalLightShadow shadow]

- 这个 [page:DirectionalLightShadow] 对象用来计算该平行光产生的阴影。 + [page:DirectionalLightShadow] 对象,用于计算该平行光产生的阴影。

[property:Object3D target]

- 平行光的方向是从它的位置到目标位置。默认的目标位置为原点 *(0,0,0)*。
- - 注意: 对于目标的位置,要将其更改为除缺省值之外的任何位置,它必须被添加到 [page:Scene scene] - 场景中去。 -

- - scene.add( light.target ); - -

- 这使得属性target中的 [page:Object3D.matrixWorld matrixWorld] 会每帧自动更新。 -

- 它也可以设置target为场景中的其他对象(任意拥有 [page:Object3D.position position] 属性的对象), 示例如下: -

- - const targetObject = new THREE.Object3D(); - scene.add(targetObject); - - light.target = targetObject; - -

- 完成上述操作后,平行光现在就可以追踪到目标对像了。 + 灯光从它的位置([page:.position position])指向目标位置。默认的目标位置为`(0, 0, 0)`。
+ *注意*:对于目标的位置,如果要改为除默认值之外的其他位置,该位置必须被添加到场景([page:Scene scene])中去。 + + scene.add( light.target ); + + 这是为了让目标的 [page:Object3D.matrixWorld matrixWorld] 在每一帧自动更新。

+ 也可以将目标设置为场景中的其他对象(任意拥有 [page:Object3D.position position] 属性的对象),如: + +const targetObject = new THREE.Object3D(); +scene.add(targetObject); + +light.target = targetObject; + + 通过上述操作,光源就可以追踪目标对象了。

方法

-

公共方法请查看基类 [page:Light Light]。

+

[method:undefined dispose]()

+

+ 释放由该实例分配的 GPU 相关资源。 当这个实例不再在你的应用中使用时,调用这个方法。 +

+

[method:this copy]( [param:DirectionalLight source] )

复制 source 的值到这个平行光源对象。

源码

-

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/zh/lights/HemisphereLight.html b/docs/api/zh/lights/HemisphereLight.html index 725daee2d8b6b1..b334d981847460 100644 --- a/docs/api/zh/lights/HemisphereLight.html +++ b/docs/api/zh/lights/HemisphereLight.html @@ -37,45 +37,39 @@

例子

构造器(Constructor)

[name]( [param:Integer skyColor], [param:Integer groundColor], [param:Float intensity] )

-

- [page:Integer skyColor] - (可选参数) 天空中发出光线的颜色。 缺省值 0xffffff。
- [page:Integer groundColor] - (可选参数) 地面发出光线的颜色。 缺省值 0xffffff。
- [page:Float intensity] - (可选参数) 光照强度。 缺省值 1。

+

+ [page:Color skyColor] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Color groundColor] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照强度。默认值为 1。

- 创建一个半球光。 + 创建一个半球光。

属性(Properties)

- 公共属性请查看基类[page:Light Light]。 + 公共属性请查看基类 [page:Light Light]。

-

[property:Boolean castShadow]

-

- 该参数在构造时被设置为 *undefined* 因为半球光不能投射阴影。 -

- - -

[property:Float color]

+

[property:Color color]

在构造时传递的天空发出光线的颜色。 - 默认会创建 [page:Color] 并设置为白色(0xffffff)。 + 默认值为白色(0xffffff)的 [page:Color] 对象。

-

[property:Float groundColor]

+

[property:Color groundColor]

在构造时传递的地面发出光线的颜色。 - 默认会创建 [page:Color] 并设置为白色(0xffffff)。 + 默认值为白色(0xffffff)的 [page:Color] 对象。

[property:Boolean isHemisphereLight]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

[property:Vector3 position]

- 假如这个值设置等于 [page:Object3D.DEFAULT_UP] (0, 1, 0),那么光线将会从上往下照射。 + 假如这个值设置为 [page:Object3D.DEFAULT_UP] (0, 1, 0),光线将会从上往下照射。

@@ -86,7 +80,7 @@

方法(Methods)

[method:this copy]( [param:HemisphereLight source] )

- 从[page:Light source]复制 [page:.color color], [page:.intensity intensity] 和 + 从 [page:Light source] 复制 [page:.color color]、[page:.intensity intensity] 和 [page:.groundColor groundColor] 的值到当前半球光对象中。

diff --git a/docs/api/zh/lights/HemisphereLightProbe.html b/docs/api/zh/lights/HemisphereLightProbe.html index baca4a5eecaaf2..71927ff23b1936 100644 --- a/docs/api/zh/lights/HemisphereLightProbe.html +++ b/docs/api/zh/lights/HemisphereLightProbe.html @@ -20,26 +20,26 @@

构造函数

[name]( [param:Color skyColor], [param:Color groundColor], [param:Float intensity] )

- [page:Color skyColor] - (可选)一个表示颜色的 Color 的实例、字符串或数字。
- [page:Color groundColor] - (可选)一个表示颜色的 Color 的实例、字符串或数字。
- [page:Float intensity] - (可选)光照探针强度的数值。默认值为1。

+ [page:Color skyColor] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Color groundColor] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照探针强度的数值。默认值为 1。

创建一个新的 [name]。

属性

- See the base [page:LightProbe LightProbe] class for common properties. + 公共属性请查看基类 [page:LightProbe LightProbe]。

[property:Boolean isHemisphereLightProbe]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

方法

- See the base [page:LightProbe LightProbe] class for common methods. + 公共方法请查看基类 [page:LightProbe LightProbe]

源码

diff --git a/docs/api/zh/lights/Light.html b/docs/api/zh/lights/Light.html index b8b525d659b546..3a196ea922530a 100644 --- a/docs/api/zh/lights/Light.html +++ b/docs/api/zh/lights/Light.html @@ -19,36 +19,34 @@

[name]

构造器(Constructor)

-

[name]( [param:Integer color], [param:Float intensity] )

+

[name]( [param:Color color], [param:Float intensity] )

- [page:Integer color] - (可选参数) 16进制表示光的颜色。 缺省值 0xffffff (白色)。
- [page:Float intensity] - (可选参数) 光照强度。 缺省值 1。

+ [page:Color color] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照强度。默认值为 1。

- 创造一个新的光源。注意,这并不是直接调用的(而是使用派生类之一)。 + 创造一个新的光源。注意,这并不是直接调用的(而是使用它的派生类)。

属性(Properties)

- 公共属性请查看基类[page:Object3D Object3D]。 + 公共属性请查看基类 [page:Object3D Object3D]。

[property:Color color]

- 光源的颜色。如果构造的时候没有传递,默认会创建一个新的 [page:Color] 并设置为白色。 + 光源的颜色。如果构造的时候没有传递,默认会创建一个新的 [page:Color] 对象并设置为白色。

[property:Float intensity]

- 光照的强度,或者说能量。 - 在 [page:WebGLRenderer.physicallyCorrectLights physically correct] 模式下, [page:.color color] 和强度 - 的乘积被解析为以坎德拉(candela)为单位的发光强度。 - 默认值 - *1.0* -
+ 光照的强度,或者说能量。
+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下,强度的单位取决于光的类型。
+ 默认值为 `1.0`。

[property:Boolean isLight]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

@@ -57,11 +55,14 @@

Methods

公共方法请查看基类 [page:Object3D Object3D]。

+

[method:undefined dispose]()

+

+ 释放由该实例分配的 GPU 相关资源。 当这个实例不再在你的应用中使用时,调用这个方法。 +

[method:this copy]( [param:Light source] )

- 从[page:Light source]复制 [page:.color color], [page:.intensity intensity] - 的值到当前光源对象中。 + 从 [page:Light source] 复制 [page:.color color]、[page:.intensity intensity] 的值到当前光源对象中。

[method:Object toJSON]( [param:Object meta] )

diff --git a/docs/api/zh/lights/LightProbe.html b/docs/api/zh/lights/LightProbe.html index c8f2866244598e..4f3908da728017 100644 --- a/docs/api/zh/lights/LightProbe.html +++ b/docs/api/zh/lights/LightProbe.html @@ -18,15 +18,15 @@

光照探针[name]

- 光照探针通常从(辐射)环境贴图中创建。 [page:LightProbeGenerator] 类可以根据 [page:CubeTexture] 或 + 光照探针通常从(辐射)环境贴图中创建。[page:LightProbeGenerator] 类可以用于从 [page:CubeTexture] 或 [page:WebGLCubeRenderTarget] 的实例来创建光照探针。 但是,光照估算数据同样可以以其他形式提供,例如,通过WebXR。 - 这将能够渲染可对真实世界的光照做出反应的增强现实内容。 + 这使得增强现实内容的渲染能够对现实世界的照明做出反应。

- three.js中,当前的探针实现支持所谓的漫反射光照探针。 - 这种类型的光照探针功能上等效于辐照环境贴图。 + 目前在 Three.js 中的探测实现支持所谓的漫射光探测。 + 这种类型的光照探针在功能上等效于辐照环境贴图。

例子

@@ -39,21 +39,21 @@

构造函数

[name]( [param:SphericalHarmonics3 sh], [param:Float intensity] )

- [page:SphericalHarmonics3 sh] - (可选)一个[page:SphericalHarmonics3]的实例。
- [page:Float intensity] - (可选)光照探针强度的数值。默认值为1。

+ [page:SphericalHarmonics3 sh] -(可选)一个 [page:SphericalHarmonics3] 的实例。
+ [page:Float intensity] -(可选)光照探针强度的数值。默认值为 1。

- 创建一个新的 [name] 。 + 创建一个新的 [name] 。

属性

- See the base [page:Light Light] class for common properties. - [page:Light.color color] 属性当前未做评估,因此不生效。 + 公共属性请查看基类 [page:Light Light]。 + [page:Light.color color] 属性当前未做评估,因此不生效。

[property:Boolean isLightProbe]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

[property:SphericalHarmonics3 sh]

@@ -63,10 +63,10 @@

[property:SphericalHarmonics3 sh]

方法

- See the base [page:Light Light] class for common methods. + 公共方法请查看基类 [page:Light Light]。

-

源码

+

源码

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

diff --git a/docs/api/zh/lights/PointLight.html b/docs/api/zh/lights/PointLight.html index 21533147169e6e..1073133c317ef5 100644 --- a/docs/api/zh/lights/PointLight.html +++ b/docs/api/zh/lights/PointLight.html @@ -36,61 +36,67 @@

例子

构造器(Constructor)

-

[name]( [param:Integer color], [param:Float intensity], [param:Number distance], [param:Float decay] )

+

[name]( [param:Color color], [param:Float intensity], [param:Number distance], [param:Float decay] )

- [page:Integer color] - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
- [page:Float intensity] - (可选参数) 光照强度。 缺省值 1。
- [page:Number distance] - 这个距离表示从光源到光照强度为0的位置。 - 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
- [page:Float decay] - 沿着光照距离的衰退量。缺省值 2。

+ [page:Color color] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照强度。默认值为 1。
+ [page:Number distance] - 光源照射的最大距离。默认值为 0(无限远)。
+ [page:Float decay] - 沿着光照距离的衰退量。默认值为 2。

创建一个新的点光源(PointLight)。

属性(Properties)

- 公共属性请查看基类[page:Light Light]。 + 公共属性请查看基类 [page:Light Light]。

[property:Boolean castShadow]

- If set to `true` light will cast dynamic shadows. *Warning*: This is expensive and - requires tweaking to get shadows looking right. See the [page:PointLightShadow] for details. - The default is `false`. + 此属性设置为 `true` 灯光将投射阴影。*注意*:这样做的代价比较高,需要通过调整让阴影看起来正确。 + 查看 [page:PointLightShadow] 了解详细信息。 + 默认值为 `false`。

[property:Float decay]

- The amount the light dims along the distance of the light. Default is `2`.
- In context of physically-correct rendering the default value should not be changed. + 光线随着距离增加变暗的衰减量。默认值为 `2`。
+ 在物理正确渲染的上下文中,不应更改默认值。

[property:Float distance]

- 如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0。 - 缺省值为 *0.0*。 + 默认模式下 — 当值为零时,光线不会衰减。当值不为零时,光线会从灯光的位置开始,到指定的距离之间,随着距离的增加线性衰减为零。 +

+

+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下 — + 当值为零时,光线将根据平方反比定律衰减到无限远。 + 当值不为零时,光线会先按照平方反比定律衰减,直到距离截止点附近,然后线性衰减到 0。 +

+

默认值为 `0.0`。

+ +

[property:Float intensity]

+

+ 光源的强度。默认值为 `1`。
+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下,单位是坎德拉(cd)。

+ 改变该值会影响到 `power` 的值。

[property:Float power]

- 光功率
- 在 [page:WebGLRenderer.physicallyCorrectLights physically correct] 模式中, - 表示以"流明(光通量单位)"为单位的光功率。 缺省值 - *4Math.PI*。

- - 该值与 [page:.intensity intensity] 直接关联 - - power = intensity * 4π - - 修改该值也会导致光强度的改变。 + 光源的功率。
+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下,单位为流明(lm)。 +

+ 改变该值会影响到 `intensity` 的值。

[property:PointLightShadow shadow]

- [page:PointLightShadow]用与计算此光照的阴影。

+ [page:PointLightShadow] 对象,用与计算此光照的阴影。

- 此对象的摄像机被设置为 [page:PerspectiveCamera.fov fov] 为90度,[page:PerspectiveCamera.aspect aspect]为1, - 近裁剪面 [page:PerspectiveCamera.near near] 为0,远裁剪面[page:PerspectiveCamera.far far] - 为500的透视摄像机 [page:PerspectiveCamera]。 + 此对象的摄像机为:一个 [page:PerspectiveCamera.fov fov] 值为90度、[page:PerspectiveCamera.aspect aspect] 值为 1、 + [page:PerspectiveCamera.near near] 值为 0、[page:PerspectiveCamera.far far] + 值为 500 的透视摄像机([page:PerspectiveCamera])。

方法(Methods)

@@ -98,6 +104,11 @@

方法(Methods)

公共方法请查看基类 [page:Light Light]。

+

[method:undefined dispose]()

+

+ 释放由该实例分配的 GPU 相关资源。 当这个实例不再在你的应用中使用时,调用这个方法。 +

+

[method:this copy]( [param:PointLight source] )

将所有属性的值从源 [page:PointLight source] 复制到此点光源对象。 diff --git a/docs/api/zh/lights/RectAreaLight.html b/docs/api/zh/lights/RectAreaLight.html index 336a5e1cdf856e..24c353455c5f4a 100644 --- a/docs/api/zh/lights/RectAreaLight.html +++ b/docs/api/zh/lights/RectAreaLight.html @@ -18,7 +18,7 @@

平面光光源([name])

  • 不支持阴影。
  • 只支持 [page:MeshStandardMaterial MeshStandardMaterial] 和 [page:MeshPhysicalMaterial MeshPhysicalMaterial] 两种材质。
  • -
  • 你必须在你的场景中加入 [link:https://threejs.org/examples/jsm/lights/RectAreaLightUniformsLib.js RectAreaLightUniformsLib] ,并调用*init()*。
  • +
  • 你必须在你的场景中加入 [link:https://threejs.org/examples/jsm/lights/RectAreaLightUniformsLib.js RectAreaLightUniformsLib],并调用 `init()`。

@@ -46,12 +46,12 @@

例子

构造器(Constructor)

-

[name]( [param:Integer color], [param:Float intensity], [param:Float width], [param:Float height] )

+

[name]( [param:Color color], [param:Float intensity], [param:Float width], [param:Float height] )

- [page:Integer color] - (可选参数) 十六进制数字表示的光照颜色。缺省值为 0xffffff (白色)
- [page:Float intensity] - (可选参数) 光源强度/亮度 。缺省值为 1。
- [page:Float width] - (可选参数) 光源宽度。缺省值为 10。
- [page:Float height] - (可选参数) 光源高度。缺省值为 10。

+ [page:Color color] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光源强度/亮度 。默认值为 1。
+ [page:Float width] -(可选)光源宽度。默认值为 10。
+ [page:Float height] -(可选)光源高度。默认值为 10。

创建一个新的平面光。

@@ -61,11 +61,33 @@

属性(Properties)

公共属性请查看基类[page:Light Light]。

+

[property:Float height]

+

光源高度。

+ +

[property:Float intensity]

+

+ 光源的强度。默认值为 `1`。
+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下,单位是尼特(cd/m^2)。

+ + 改变该值会影响到 `power` 的值。 +

+

[property:Boolean isRectAreaLight]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

+

[property:Float power]

+

+ 光源的功率。
+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下,单位为流明(lm)。

+ + 改变该值会影响到 `intensity` 的值。 +

+ +

[property:Float width]

+

光源宽度。

+

方法(Methods)

公共方法请查看基类 [page:Light Light]。 diff --git a/docs/api/zh/lights/SpotLight.html b/docs/api/zh/lights/SpotLight.html index e67fc3e3308f62..3367702157a41d 100644 --- a/docs/api/zh/lights/SpotLight.html +++ b/docs/api/zh/lights/SpotLight.html @@ -19,7 +19,7 @@

聚光灯([name])

代码示例

- // white spotlight shining from the side, modulated by a texture, casting a shadow + // 白色聚光灯从侧面照射,经过纹理调节,形成阴影 const spotLight = new THREE.SpotLight( 0xffffff ); spotLight.position.set( 100, 1000, 100 ); @@ -47,109 +47,111 @@

例子

构造器(Constructor)

-

[name]( [param:Integer color], [param:Float intensity], [param:Float distance], [param:Radians angle], [param:Float penumbra], [param:Float decay] )

+

[name]( [param:Color color], [param:Float intensity], [param:Float distance], [param:Radians angle], [param:Float penumbra], [param:Float decay] )

- [page:Integer color] - (可选参数) 十六进制光照颜色。 缺省值 0xffffff (白色)。
- [page:Float intensity] - (可选参数) 光照强度。 缺省值 1。
- [page:Float distance] - 从光源发出光的最大距离,其强度根据光源的距离线性衰减。
- [page:Radians angle] - 光线散射角度,最大为Math.PI/2。
- [page:Float penumbra] - 聚光锥的半影衰减百分比。在0和1之间的值。默认为0。
- [page:Float decay] - 沿着光照距离的衰减量。

+ [page:Color color] -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 [page:Color Color] 对象。
+ [page:Float intensity] -(可选)光照强度。默认值为 1。
+ [page:Float distance] - 光源照射的最大距离。默认值为 0(无限远)。
+ [page:Radians angle] - 光线照射范围的角度。默认值为 Math.PI/3。
+ [page:Float penumbra] - 聚光锥的半影衰减百分比。默认值为 0。
+ [page:Float decay] - 沿着光照距离的衰减量。默认值为 2。

创建一个新的聚光灯。

属性(Properties)

-

公共属性请查看基类[page:Light Light]。

+

公共属性请查看基类 [page:Light Light]。

[property:Float angle]

- 从聚光灯的位置以弧度表示聚光灯的最大范围。应该不超过 *Math.PI/2*。默认值为 *Math.PI/3*。 + 光线照射范围的角度,用弧度表示。不应超过 `Math.PI/2`。默认值为 `Math.PI/3`。

[property:Boolean castShadow]

- 此属性设置为 *true* 聚光灯将投射阴影。警告: 这样做的代价比较高而且需要一直调整到阴影看起来正确。 + 此属性设置为 `true` 灯光将投射阴影。*注意*:这样做的代价比较高,需要通过调整让阴影看起来正确。 查看 [page:SpotLightShadow] 了解详细信息。 - 默认值为 *false* + 默认值为 `false`。

[property:Float decay]

- The amount the light dims along the distance of the light. Default is `2`.
- In context of physically-correct rendering the default value should not be changed. + 光线随着距离增加变暗的衰减量。默认值为 `2`。
+ 在物理正确渲染的上下文中,不应更改默认值。

[property:Float distance]

- 如果非零,那么光强度将会从最大值当前灯光位置处按照距离线性衰减到0。 - 缺省值为 *0.0*。 + 默认模式下 — 当值为零时,光线不会衰减。当值不为零时,光线会从灯光的位置开始,到指定的距离之间,随着距离的增加线性衰减为零。 +

+

+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下 — + 当值为零时,光线将根据平方反比定律衰减到无限远。 + 当值不为零时,光线会先按照平方反比定律衰减,直到距离截止点附近,然后线性衰减到 0。 +

+

默认值为 `0.0`。

+ +

[property:Float intensity]

+

+ 光源的强度。默认值为 `1`。
+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下,单位是坎德拉(cd)。

+ 改变该值会影响到 `power` 的值。

[property:Boolean isSpotLight]

- Read-only flag to check if a given object is of type [name]. + 只读,用于检查对象的类型是否为 [name]。

[property:Float penumbra]

- 聚光锥的半影衰减百分比。在0和1之间的值。 - 默认值 — 0.0。 + 该属性设置照明区域在边缘附近的平滑衰减速度,取值范围在 0 到 1 之间。默认值为 `0.0`。

[property:Vector3 position]

- 假如这个值设置等于 [page:Object3D.DEFAULT_UP] (0, 1, 0),那么光线将会从上往下照射。 + 假如这个值设置为 [page:Object3D.DEFAULT_UP] (0, 1, 0),光线将会从上往下照射。

[property:Float power]

- 光功率
- 在 [page:WebGLRenderer.physicallyCorrectLights physically correct] 模式中, - 表示以"流明(光通量单位)"为单位的光功率。 缺省值 - *4Math.PI*。

- - 该值与 [page:.intensity intensity] 直接关联 - - power = intensity * 4π - - 修改该值也会导致光强度的改变。 + 光源的功率。
+ 禁用 [page:WebGLRenderer.useLegacyLights legacy lighting mode] 的情况下,单位为流明(lm)。 +

+ 改变该值会影响到 `intensity` 的值。

[property:SpotLightShadow shadow]

- [page:SpotLightShadow]用与计算此光照的阴影。 + [page:SpotLightShadow] 对象,用与计算此光照的阴影。

[property:Object3D target]

- 聚光灯的方向是从它的位置到目标位置.默认的目标位置为原点 *(0,0,0)*。
- 注意: 对于目标的位置,要将其更改为除缺省值之外的任何位置,它必须被添加到 [page:Scene scene] - 场景中去。 + 灯光从它的位置([page:.position position])指向目标位置。默认的目标位置为`(0, 0, 0)`。
+ *注意*:对于目标的位置,如果要改为除默认值之外的其他位置,该位置必须被添加到场景([page:Scene scene])中去。 scene.add( light.target ); - - 这使得属性target中的 [page:Object3D.matrixWorld matrixWorld] 会每帧自动更新。

- - 它也可以设置target为场景中的其他对象(任意拥有 [page:Object3D.position position] 属性的对象), 示例如下: + 这是为了让目标的 [page:Object3D.matrixWorld matrixWorld] 在每一帧自动更新。

+ 也可以将目标设置为场景中的其他对象(任意拥有 [page:Object3D.position position] 属性的对象),如: const targetObject = new THREE.Object3D(); scene.add(targetObject); light.target = targetObject; - 完成上述操作后,聚光灯现在就可以追踪到目标对像了。 + 通过上述操作,光源就可以追踪目标对象了。

[property:Texture map]

- A [page:Texture] used to modulate the color of the light. The spot light color is mixed - with the RGB value of this texture, with a ratio corresponding to its - alpha value. The cookie-like masking effect is reproduced using pixel values (0, 0, 0, 1-cookie_value). - *Warning*: [param:SpotLight map] is disabled if [param:SpotLight castShadow] is *false*. + 用于调节光线颜色的纹理([page:Texture]),聚光灯颜色会与该纹理的RGB值混合,其比例与其alpha值相对应。
+ The cookie-like masking effect is reproduced using pixel values (0, 0, 0, 1-cookie_value).
+ *注意*: 如果 `castShadow` 值为 `false` 时,`map` 不可用。

@@ -157,6 +159,11 @@

方法(Methods)

公共方法请查看基类 [page:Light Light]。

+

[method:undefined dispose]()

+

+ 释放由该实例分配的 GPU 相关资源。 当这个实例不再在你的应用中使用时,调用这个方法。 +

+

[method:this copy]( [param:SpotLight source] )

将所有属性的值从源 [page:SpotLight source] 复制到此聚光灯光源对象。 @@ -167,3 +174,4 @@

[method:this copy]( [param:SpotLight source] )

+ diff --git a/docs/api/zh/loaders/BufferGeometryLoader.html b/docs/api/zh/loaders/BufferGeometryLoader.html index 455f6c77f8ec28..5b95184938458c 100644 --- a/docs/api/zh/loaders/BufferGeometryLoader.html +++ b/docs/api/zh/loaders/BufferGeometryLoader.html @@ -46,12 +46,6 @@

代码示例

);
-

例子

- -

- [example:webgl_performance WebGL / performance] -

-

构造函数

[name]( [param:LoadingManager manager] )

diff --git a/docs/api/zh/loaders/managers/LoadingManager.html b/docs/api/zh/loaders/managers/LoadingManager.html index b112a21a21d96b..f0fd894d4c30df 100644 --- a/docs/api/zh/loaders/managers/LoadingManager.html +++ b/docs/api/zh/loaders/managers/LoadingManager.html @@ -98,7 +98,6 @@

例子

[example:webgl_loader_fbx WebGL / loader / fbx]
[example:webgl_loader_obj WebGL / loader / obj]
- [example:webgl_materials_physical_reflectivity WebGL / materials / physical / reflectivity]
[example:webgl_postprocessing_outline WebGL / postprocesing / outline]

diff --git a/docs/api/zh/materials/LineBasicMaterial.html b/docs/api/zh/materials/LineBasicMaterial.html index daf5fb01281c57..36b03110837246 100644 --- a/docs/api/zh/materials/LineBasicMaterial.html +++ b/docs/api/zh/materials/LineBasicMaterial.html @@ -38,7 +38,6 @@

例子

[example:webgl_interactive_voxelpainter WebGL / interactive / voxelpainter]
[example:webgl_lines_colors WebGL / lines / colors]
[example:webgl_lines_dashed WebGL / lines / dashed]
- [example:webgl_lines_sphere WebGL / lines / sphere]
[example:webgl_materials WebGL / materials]
[example:physics_ammo_rope physics / ammo / rope]

@@ -79,6 +78,11 @@

[property:String linejoin]

并且会被[page:WebGLRenderer WebGL]渲染器忽略。

+

[property:Texture map]

+

+ Sets the color of the lines using data from a [page:Texture]. +

+

方法(Methods)

共有方法请参见其基类[page:Material]。

diff --git a/docs/api/zh/materials/Material.html b/docs/api/zh/materials/Material.html index 7ad8b698bfd047..8bcbeefe5a7efd 100644 --- a/docs/api/zh/materials/Material.html +++ b/docs/api/zh/materials/Material.html @@ -109,11 +109,11 @@

[property:Boolean depthWrite]

[property:Boolean forceSinglePass]

-Whether double-sided, transparent objects should be rendered with a single pass or not. Default is `false`.

+决定双面透明的东西是否强制使用单通道渲染,默认为`false`。

-The engine renders double-sided, transparent objects with two draw calls (back faces first, then front faces) to mitigate transparency artifacts. -There are scenarios however where this approach produces no quality gains but still doubles draw calls e.g. when rendering flat vegetation like grass sprites. -In these cases, set the `forceSinglePass` flag to `false` to disable the two pass rendering to avoid performance issues. +为了减少一些半透明物体的渲染错误,此引擎调用两次绘制来渲染渲染双面透明的东西。 +但是此方案可能会导致在某些情况下使绘制调用次数翻倍,例如渲染一些平面的植物例如草精灵之类的。 +在这些情况下,将`forceSinglePass`设置为`true`来使用单通道渲染来避免性能问题。

[property:Boolean isMaterial]

@@ -267,7 +267,7 @@

[property:Integer version]

[property:Boolean vertexColors]

是否使用顶点着色。默认值为false。 -The engine supports RGB and RGBA vertex colors depending on whether a three (RGB) or four (RGBA) component color buffer attribute is used. +此引擎支持RGB或者RGBA两种顶点颜色,取决于缓冲 attribute 使用的是三分量(RGB)还是四分量(RGBA)。

[property:Boolean visible]

@@ -301,7 +301,7 @@

[method:undefined onBeforeCompile]( [param:Shader shader], [param:WebGLRende

[method:String customProgramCacheKey]()

-当用到onBeforeCompile回调的时候,这个回调函数可以用来定义在onBeforeCompile中使用的配置项,这样three.js就可以根据这个回调返回的字符串来判定使用一个缓存的编译好的着色器代码还是根据需求重新编译一个新的着色器代码。 +当用到onBeforeCompile回调的时候,这个回调函数可以用来定义在onBeforeCompile中使用的配置项,这样three.js就可以根据这个回调返回的字符串来判定使用一个缓存的编译好的着色器代码还是根据需求重新编译一段新的着色器代码。

diff --git a/docs/api/zh/materials/MeshDistanceMaterial.html b/docs/api/zh/materials/MeshDistanceMaterial.html index ae675804cce854..ba6adeac12395a 100644 --- a/docs/api/zh/materials/MeshDistanceMaterial.html +++ b/docs/api/zh/materials/MeshDistanceMaterial.html @@ -73,27 +73,12 @@

[property:Float displacementBias]

位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。

-

[property:Float farDistance]

-

- The far value of the point light's internal shadow camera. -

-

[property:Texture map]

颜色贴图。可以选择包括一个alpha通道,通常与[page:Material.transparent .transparent] 或[page:Material.alphaTest .alphaTest]。默认为null。

-

[property:Float nearDistance]

-

- The near value of the point light's internal shadow camera. -

- -

[property:Vector3 referencePosition]

-

- The position of the point light in world space. -

-

方法(Methods)

共有方法请参见其基类[page:Material]。

diff --git a/docs/api/zh/materials/MeshPhysicalMaterial.html b/docs/api/zh/materials/MeshPhysicalMaterial.html index fed77cfa5a8daf..7ec11885c59cfd 100644 --- a/docs/api/zh/materials/MeshPhysicalMaterial.html +++ b/docs/api/zh/materials/MeshPhysicalMaterial.html @@ -55,9 +55,7 @@

物理网格材质([name])

例子

- [example:webgl_materials_variations_physical materials / variations / physical]
[example:webgl_materials_physical_clearcoat materials / physical / clearcoat]
- [example:webgl_materials_physical_reflectivity materials / physical / reflectivity]
[example:webgl_loader_gltf_sheen loader / gltf / sheen]
[example:webgl_materials_physical_transmission materials / physical / transmission]

diff --git a/docs/api/zh/materials/MeshToonMaterial.html b/docs/api/zh/materials/MeshToonMaterial.html index 47ee650af449d3..83e3704939f4d3 100644 --- a/docs/api/zh/materials/MeshToonMaterial.html +++ b/docs/api/zh/materials/MeshToonMaterial.html @@ -11,7 +11,7 @@

[name]

-
A material implementing toon shading.
+
一种实现卡通着色的材质。
@@ -33,165 +33,137 @@

[name]

例子

- [example:webgl_materials_variations_toon materials / variations / toon] + [example:webgl_materials_toon materials / toon]

-

Constructor

+

构造函数(Constructor)

[name]( [param:Object parameters] )

- [page:Object parameters] - (optional) an object with one or more properties defining the material's appearance. - Any property of the material (including any property inherited from [page:Material]) can be passed in here.

+ [page:Object parameters] - (可选) 具有定义材料外观的一个或多个属性的对象。材料的任何属性(包括从Material继承的任何属性)都可以在这里传递.

- The exception is the property [page:Hexadecimal color], which can be passed in as a hexadecimal - string and is *0xffffff* (white) by default. [page:Color.set]( color ) is called internally. + 例外是属性[page:Hexadecimal color],它可以作为十六进制字符串传入,默认为0xffffff(白色)。[page:Color.set]Color.set ( color ) 在内部被调用。

-

Properties

-

See the base [page:Material] class for common properties.

+

属性(Properties)

+

请参阅基础Material[page:Material]类以了解常见属性。

[property:Texture alphaMap]

-

The alpha map is a grayscale texture that controls the opacity across the surface - (black: fully transparent; white: fully opaque). Default is null.

+

alpha 贴图是一种灰度纹理,可控制整个表面的不透明度(黑色:完全透明;白色:完全不透明)。默认为空。

- Only the color of the texture is used, ignoring the alpha channel if one exists. - For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the - green channel when sampling this texture due to the extra bit of precision provided - for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and - luminance/alpha textures will also still work as expected. + 仅使用纹理的颜色,如果存在则忽略alpha通道。对于RGB和RGBA纹理,由于在DXT压缩和未压缩的RGB565格式中为绿色提供了额外的精度,[page:WebGLRenderer WebGL]渲染器将在对该纹理进行采样时使用绿色通道。仅亮度和亮度/alpha纹理也将按预期工作。

[property:Texture aoMap]

-

The red channel of this texture is used as the ambient occlusion map. Default is null. - The aoMap requires a second set of UVs.

+

该纹理的红色通道用作环境遮挡贴图。默认为空。aoMap需要第二组UV。

[property:Float aoMapIntensity]

-

Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.

+

环境遮挡效果的强度。默认值为1。零表示没有遮挡效果。

[property:Texture bumpMap]

- The texture to create a bump map. The black and white values map to the perceived depth in relation to the lights. - Bump doesn't actually affect the geometry of the object, only the lighting. If a normal map is defined this will - be ignored. + 创建凹凸贴图的纹理。黑色和白色值映射到与灯光相关的感知深度。凹凸实际上不会影响对象的几何形状,只会影响光照。如果定义了法线贴图,这将被忽略。

[property:Float bumpScale]

-

How much the bump map affects the material. Typical ranges are 0-1. Default is 1.

+

凹凸贴图对材质的影响程度。典型范围是0-1。默认值为1。

[property:Color color]

-

[page:Color] of the material, by default set to white (0xffffff).

+

材质的颜色[page:Color],默认设置为白色 (0xffffff)。

[property:Texture displacementMap]

- The displacement map affects the position of the mesh's vertices. Unlike other maps - which only affect the light and shade of the material the displaced vertices can cast shadows, - block other objects, and otherwise act as real geometry. The displacement texture is - an image where the value of each pixel (white being the highest) is mapped against, - and repositions, the vertices of the mesh. + 置换贴图影响网格顶点的位置。 + 与其他仅影响材质明暗的贴图不同,置换的顶点可以投射阴影、阻挡其他对象,并以其他方式充当真实几何体。 + 位移纹理是一个图像,其中每个像素的值(白色为最高)映射到网格的顶点并重新定位。

[property:Float displacementScale]

- How much the displacement map affects the mesh (where black is no displacement, - and white is maximum displacement). Without a displacement map set, this value is not applied. - Default is 1. + 置换贴图对网格的影响程度(黑色表示无置换,白色表示最大置换)。如果没有置换贴图集,则不会应用此值。默认值为1。

[property:Float displacementBias]

- The offset of the displacement map's values on the mesh's vertices. - Without a displacement map set, this value is not applied. Default is 0. + 置换贴图值在网格顶点上的偏移量。如果没有置换贴图集,则不会应用此值。默认为0。

[property:Color emissive]

- Emissive (light) color of the material, essentially a solid color unaffected by other lighting. - Default is black. + 材料的发射(光)颜色,本质上是一种不受其他光照影响的纯色。默认为黑色。

[property:Texture emissiveMap]

- Set emissive (glow) map. Default is null. The emissive map color is modulated by - the emissive color and the emissive intensity. If you have an emissive map, be sure to - set the emissive color to something other than black. + 设置发射(发光)贴图。默认为空。发射贴图颜色由发射颜色和发射强度调制。如果您有自发光贴图,请务必将自发光颜色设置为黑色以外的颜色。

[property:Float emissiveIntensity]

-

Intensity of the emissive light. Modulates the emissive color. Default is 1.

+

发射光的强度。调制发光颜色。默认值为1。

[property:Boolean fog]

材质是否受雾影响。默认为*true*。

[property:Texture gradientMap]

-

Gradient map for toon shading. It's required to set [page:Texture.minFilter] and [page:Texture.magFilter] to - [page:Textures THREE.NearestFilter] when using this type of texture. Default is *null*.

+

卡通着色的渐变贴图。使用此类纹理时,需要将Texture.minFilter[page:Texture.minFilter]和Texture.magFilter[page:Texture.magFilter]设置为[page:Textures THREE.NearestFilter]。默认为空。 +

[property:Texture lightMap]

-

The light map. Default is null. The lightMap requires a second set of UVs.

+

光照贴图。默认为空。lightMap需要第二组UV。

[property:Float lightMapIntensity]

-

Intensity of the baked light. Default is 1.

+

烘焙光的强度。默认值为1。

[property:Texture map]

- The color map. May optionally include an alpha channel, typically combined with - [page:Material.transparent .transparent] or [page:Material.alphaTest .alphaTest]. Default is null. - The texture map color is modulated by the diffuse [page:.color]. + 彩色地图。可以选择包含一个alpha通道,通常与[page:Material.transparent .transparent]或[page:Material.alphaTest .alphaTest]结合使用。默认为空。纹理贴图颜色由漫反射.color[page:.color]调制。

[property:Texture normalMap]

- The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change - the way the color is lit. Normal maps do not change the actual shape of the surface, only the lighting. - In case the material has a normal map authored using the left handed convention, the y component of normalScale - should be negated to compensate for the different handedness. + 创建法线贴图的纹理。RGB值影响每个像素片段的表面法线并改变颜色的点亮方式。法线贴图不会改变表面的实际形状,只会改变光照。如果材质具有使用左手惯例创作的法线贴图,则应取反normalScale的y分量以补偿不同的手性。

[property:Integer normalMapType]

- The type of normal map.

+ 法线贴图的类型。

- Options are [page:constant THREE.TangentSpaceNormalMap] (default), and [page:constant THREE.ObjectSpaceNormalMap]. + 选项为[page:constant THREE.TangentSpaceNormalMap](默认)和[page:constant THREE.ObjectSpaceNormalMap]。

[property:Vector2 normalScale]

- How much the normal map affects the material. Typical ranges are 0-1. - Default is a [page:Vector2] set to (1,1). + 法线贴图对材质的影响有多大。典型范围是0-1。默认是设置为(1,1)的二维向量[page:Vector2]。

[property:Boolean wireframe]

-

Render geometry as wireframe. Default is *false* (i.e. render as flat polygons).

+

将几何渲染为线框。默认为false(即呈现为平面多边形)。

[property:String wireframeLinecap]

- Define appearance of line ends. Possible values are "butt", "round" and "square". Default is 'round'.

+ 定义线端的外观。可能的值为“butt”、“round”和“square”。默认为“圆形”。

- This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap] - property and it is ignored by the [page:WebGLRenderer WebGL] renderer. + 这对应于[link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2DCanvas]的lineCap属性,它会被[page:WebGLRenderer WebGL]渲染器忽略。

[property:String wireframeLinejoin]

- Define appearance of line joints. Possible values are "round", "bevel" and "miter". Default is 'round'.

+ 定义线接头的外观。可能的值是“round”、“bevel”和“miter”。默认为“圆形”。

- This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin] - property and it is ignored by the [page:WebGLRenderer WebGL] renderer. + 这对应于[link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2DCanvas]的lineCap属性,它会被[page:WebGLRenderer WebGL]渲染器忽略。

[property:Float wireframeLinewidth]

-

Controls wireframe thickness. Default is 1.

+

控制线框厚度。默认值为1。

- Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] - with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will - always be 1 regardless of the set value. + 由于[link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]与[page:WebGLRenderer WebGL]渲染器在大多数平台上的限制,无论设置值如何,线宽始终为1。

-

Methods

-

See the base [page:Material] class for common methods.

+

方法(Methods)

+

有关常用方法,请参见Material[page:Material]类。

-

Source

+

源码(Source)

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/materials/PointsMaterial.html b/docs/api/zh/materials/PointsMaterial.html index 8693b118da28f1..f8877eacdefe51 100644 --- a/docs/api/zh/materials/PointsMaterial.html +++ b/docs/api/zh/materials/PointsMaterial.html @@ -51,8 +51,7 @@

例子

[example:webgl_multiple_elements_text WebGL / multiple / elements / text]
[example:webgl_points_billboards WebGL / points / billboards]
[example:webgl_points_dynamic WebGL / points / dynamic]
- [example:webgl_points_sprites WebGL / points / sprites]
- [example:webgl_trails WebGL / trails] + [example:webgl_points_sprites WebGL / points / sprites]

[name]( [param:Object parameters] )

diff --git a/docs/api/zh/materials/ShaderMaterial.html b/docs/api/zh/materials/ShaderMaterial.html index 65553d38689d33..f18b7e706bc0bb 100644 --- a/docs/api/zh/materials/ShaderMaterial.html +++ b/docs/api/zh/materials/ShaderMaterial.html @@ -254,7 +254,7 @@

[property:Object defaultAttributeValues]

this.defaultAttributeValues = { 'color': [ 1, 1, 1 ], 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] + 'uv1': [ 0, 0 ] };
@@ -374,7 +374,7 @@

[property:Float wireframeLinewidth]

方法(Methods)

共有方法请参见其基类[page:Material]。

-

[method:ShaderMaterial clone]() [param:ShaderMaterial this]

+

[method:ShaderMaterial clone]()

创建该材质的一个浅拷贝。需要注意的是,vertexShader和fragmentShader使用引用拷贝; *attributes*的定义也是如此; 这意味着,克隆的材质将共享相同的编译[page:WebGLProgram]; diff --git a/docs/api/zh/math/Color.html b/docs/api/zh/math/Color.html index 98087d993c231f..2e77617fb21007 100644 --- a/docs/api/zh/math/Color.html +++ b/docs/api/zh/math/Color.html @@ -49,7 +49,7 @@

构造器(Constructor)

[name]( [param:Color_Hex_or_String r], [param:Float g], [param:Float b] )

[page:Color_Hex_or_String r] - (可选参数) 如果参数g和b被定义,则r表示颜色中的红色分量。 - 如果未被定义,r可以是一个十六进制 [link:https://en.wikipedia.org/wiki/Web_colors#Hex_triplet hexadecimal triplet] 颜色值或CSS样式的字符串或一个Color实例。
+ 如果未被定义,r可以是一个十六进制 [link:https://en.wikipedia.org/wiki/Web_colors#Hex_triplet hexadecimal triplet] 颜色值或CSS样式的字符串或一个`Color`实例。
[page:Float g] - (可选参数) 如果被定义,表示颜色中的绿色分量。
[page:Float b] - (可选参数) 如果被定义,表示颜色中的蓝色分量。

@@ -182,6 +182,13 @@

[method:Object getHSL]( [param:Object target], [param:string colorSpace] = L

+

[method:Color getRGB]( [param:Color target], [param:string colorSpace] = SRGBColorSpace )

+

+ [page:Color target] - 结果将复制到这个对象中.

+ + Returns the RGB values of this color as an instance of [page:Color]. +

+

[method:String getStyle]( [param:string colorSpace] = SRGBColorSpace )

以CSS样式字符串的形式返回该颜色的值。例如:“rgb(255,0,0)”。

@@ -226,12 +233,15 @@

[method:this offsetHSL]( [param:Float h], [param:Float s], [param:Float l] ) 相加,最后再将结果转成RGB值。

-

[method:this set]( [param:Color_Hex_or_String value] )

+

[method:this set]( [param:Color_Hex_or_String r], [param:Float g], [param:Float b] )

- [page:Color_Hex_or_String value] - 用于设置该颜色的值。

+ [page:Color_Hex_or_String r] - (optional) If arguments [page:Float g] and [page:Float b] are defined, the red component of the color. If they are + not defined, it can be a [link:https://en.wikipedia.org/wiki/Web_colors#Hex_triplet hexadecimal triplet] (recommended), a CSS-style string, or another `Color` instance.
+ [page:Float g] - (optional) If it is defined, the green component of the color.
+ [page:Float b] - (optional) If it is defined, the blue component of the color.

- 有关 [page:Color_Hex_or_String value] 的详细信息,请参阅上面的构造函数。 - 根据输入类型,将会委托给 [page:.copy], [page:.setStyle], 或者 [page:.setHex] 函数处理。 + See the Constructor above for full details about possible arguments. Delegates to [page:.copy], + [page:.setStyle], [page:.setRGB] or [page:.setHex] depending on input type.

[method:this setHex]( [param:Integer hex], [param:string colorSpace] = SRGBColorSpace )

@@ -308,6 +318,11 @@

[method:Array toArray]( [param:Array array], [param:Integer offset] )

返回一个格式为[ r, g, b ] 数组。

+

[method:Number toJSON]()

+

+ This methods defines the serialization result of [name]. Returns the color as a hexadecimal value. +

+

源码(Source)

diff --git a/docs/api/zh/math/Matrix3.html b/docs/api/zh/math/Matrix3.html index 03df1e51aa128b..356cdaa77c2d89 100644 --- a/docs/api/zh/math/Matrix3.html +++ b/docs/api/zh/math/Matrix3.html @@ -43,13 +43,15 @@

注意行优先列优先的顺序。

Constructor

-

[name]()

+

[name]( [param:Number n11], [param:Number n12], [param:Number n13], + [param:Number n21], [param:Number n22], [param:Number n22], + [param:Number n31], [param:Number n32], [param:Number n33] )

- 创建并初始化一个3X3的单位矩阵[link:https://en.wikipedia.org/wiki/Identity_matrix identity matrix]. + Creates a 3x3 matrix with the given arguments in row-major order. If no arguments are provided, the constructor initializes + the [name] to the 3x3 [link:https://en.wikipedia.org/wiki/Identity_matrix identity matrix].

-

属性(Properties)

[property:Array elements]

@@ -149,8 +151,11 @@

[method:this makeScale]( [param:Float x], [param:Float y] )

+

[method:this makeTranslation]( [param:Vector2 v] )

[method:this makeTranslation]( [param:Float x], [param:Float y] )

+ [page:Vector2 v] a translation transform from vector.
+ or
[page:Float x] - the amount to translate in the X axis.
[page:Float y] - the amount to translate in the Y axis.
diff --git a/docs/api/zh/math/Matrix4.html b/docs/api/zh/math/Matrix4.html index 5761969003e7df..2a2251026d4c27 100644 --- a/docs/api/zh/math/Matrix4.html +++ b/docs/api/zh/math/Matrix4.html @@ -95,11 +95,15 @@

提取位置(平移)、旋转和缩放

构造器(Constructor)

-

[name]()

+

[name]( [param:Number n11], [param:Number n12], [param:Number n13], [param:Number n14], + [param:Number n21], [param:Number n22], [param:Number n23], [param:Number n24], + [param:Number n31], [param:Number n32], [param:Number n33], [param:Number n34], + [param:Number n41], [param:Number n42], [param:Number n43], [param:Number n44] )

- 创建并初始化一个4X4的单位矩阵[link:https://en.wikipedia.org/wiki/Identity_matrix identity matrix]. -

+ Creates a 4x4 matrix with the given arguments in row-major order. If no arguments are provided, the constructor initializes + the [name] to the 4x4 [link:https://en.wikipedia.org/wiki/Identity_matrix identity matrix]. +

属性(Properties)

@@ -316,13 +320,12 @@

[method:this makeShear]( [param:Float x], [param:Float y], [param:Float z] )

-

[method:this makeTranslation]( [param:Float x], [param:Float y], [param:Float z] )

+

[method:this makeTranslation]( [param:Vector3 v] )

+

+ [method:this makeTranslation]( [param:Float x], [param:Float y], [param:Float z] ) // optional API +

- [page:Float x] - 在X轴上的平移量。
- [page:Float y] - 在Y轴上的平移量。
- [page:Float z] - 在Z轴上的平移量。

- - 设置该矩阵为平移变换: + 取传入参数[param:Vector3 v]中值设设置该矩阵为平移变换: 1, 0, 0, x, 0, 1, 0, y, diff --git a/docs/api/zh/math/Quaternion.html b/docs/api/zh/math/Quaternion.html index 4d3b576dbdb1ef..26077d92c18f3a 100644 --- a/docs/api/zh/math/Quaternion.html +++ b/docs/api/zh/math/Quaternion.html @@ -203,6 +203,11 @@

[method:Array toArray]( [param:Array array], [param:Integer offset] )

在形如[x, y, z, w]的数组中,返回四元数中的数字元素。

+

[method:Array toJSON]()

+

+ This methods defines the serialization result of [name]. 在形如[x, y, z, w]的数组中,返回四元数中的数字元素。 +

+

[method:this fromBufferAttribute]( [param:BufferAttribute attribute], [param:Integer index] )

[page:BufferAttribute attribute] - 源 attribute。
diff --git a/docs/api/zh/math/Ray.html b/docs/api/zh/math/Ray.html index 771bead91b3793..88e7f2ff4dfb43 100644 --- a/docs/api/zh/math/Ray.html +++ b/docs/api/zh/math/Ray.html @@ -188,7 +188,7 @@

[method:this recast]( [param:Float t] )

[method:this set]( [param:Vector3 origin], [param:Vector3 direction] )

[page:Vector3 origin] - [page:Ray](射线)的[page:.origin origin](原点)。
- [page:Vector3 origin] - [page:Ray](射线)的[page:.direction direction](方向)。 + [page:Vector3 direction] - [page:Ray](射线)的[page:.direction direction](方向)。 该向量必须经过标准化(使用[page:Vector3.normalize]),这样才能使方法正常运行。

diff --git a/docs/api/zh/math/SphericalHarmonics3.html b/docs/api/zh/math/SphericalHarmonics3.html index 9f753509b4cd1b..d274c437bd39d3 100644 --- a/docs/api/zh/math/SphericalHarmonics3.html +++ b/docs/api/zh/math/SphericalHarmonics3.html @@ -9,131 +9,129 @@

[name]

-

Represents a third-order spherical harmonics (SH). Light probes use this class to encode lighting information.

+

表示三次球面谐波(SH)。光照探测器使用此类来编码光照信息。

-

Constructor

+

构造函数(Constructor)

[name]()

- Creates a new instance of [name]. + 创建[name]的新实例。

-

Properties

+

特性(Properties)

[property:Array coefficients]

-

An array holding the (9) SH coefficients. A single coefficient is represented as an instance of [page:Vector3].

+

包含(9)个SH系数的数组。单个系数表示为[page:Vector3 Vector3]的实例。

[property:Boolean isSphericalHarmonics3]

- Read-only flag to check if a given object is of type [name]. + 用于检查给定对象是否为SphericalHarmonics3类型的只读标志。

Methods

[method:SphericalHarmonics3 add]( [param:SphericalHarmonics3 sh] )

- [page:SphericalHarmonics3 sh] - The SH to add.

+ [page:SphericalHarmonics3 sh] - 要添加的SH。

- Adds the given SH to this instance. + 将给定的 SH 添加到此实例。

[method:SphericalHarmonics3 addScaledSH]( [param:SphericalHarmonics3 sh], [param:Number scale] )

- [page:SphericalHarmonics3 sh] - The SH to add.
- [page:Number scale] - The scale factor.

- - A convenience method for performing [page:.add]() and [page:.scale]() at once. + [page:SphericalHarmonics3 sh] - 要添加的SH。
+ [page:Number scale] - 比例因子。

+ 一次 执行[page:.add]()和[page:.scale]()的便捷方法。

[method:SphericalHarmonics3 clone]()

- Returns a new instance of [name] with equal coefficients. + 返回具有相等系数的[name]的新实例。

[method:SphericalHarmonics3 copy]( [param:SphericalHarmonics3 sh] )

- [page:SphericalHarmonics3 sh] - The SH to copy.

+ [page:SphericalHarmonics3 sh] - 要复制的SH。

- Copies the given SH to this instance. + 将给定的SH复制到此实例。

[method:Boolean equals]( [param:SphericalHarmonics3 sh] )

- [page:SphericalHarmonics3 sh] - The SH to compare with.

+ [page:SphericalHarmonics3 sh] - 要与之比较的 SH。

- Returns true if the given SH and this instance have equal coefficients. + 如果给定的SH和此实例具有相等的系数,则返回true。

[method:SphericalHarmonics3 fromArray]( [param:Array array], [param:Number offset] )

- [page:Array array] - The array holding the numbers of the SH coefficients.
- [page:Number offset] - (optional) The array offset.

+ [page:Array array] - 保存SH系数数的数组。
+ [page:Number offset] - (可选)数组偏移量。

- Sets the coefficients of this instance from the given array. + 从给定数组设置此实例的系数。

[method:Vector3 getAt]( [param:Vector3 normal], [param:Vector3 target] )

- [page:Vector3 normal] - The normal vector (assumed to be unit length).
- [page:Vector3 target] - The result vector.

+ [page:Vector3 normal] - 法向量(假定为单位长度)。
+ [page:Vector3 target] - 结果向量。

- Returns the radiance in the direction of the given normal. + 返回给定法线方向的辐射度。

[method:Vector3 getIrradianceAt]( [param:Vector3 normal], [param:Vector3 target] )

- [page:Vector3 normal] - The normal vector (assumed to be unit length).
- [page:Vector3 target] - The result vector.

+ [page:Vector3 normal] - 法向量(假定为单位长度)。
+ [page:Vector3 target] - 结果向量。

- Returns the irradiance (radiance convolved with cosine lobe) in the direction of the given normal. + 返回给定法线方向的辐照度(辐射度与余弦波瓣卷积)。

[method:SphericalHarmonics3 lerp]( [param:SphericalHarmonics3 sh], [param:Number alpha] )

- [page:SphericalHarmonics3 sh] - The SH to interpolate with.
- [page:Number alpha] - The alpha factor.

+ [page:SphericalHarmonics3 sh] - 要插入的SH。
+ [page:Number alpha] - alpha因子。

- Linear interpolates between the given SH and this instance by the given alpha factor. + 通过给定的alpha因子在给定的SH和此实例之间进行线性插值。

[method:SphericalHarmonics3 scale]( [param:Number scale] )

- [page:Number sh] - The scale factor.

+ [page:Number sh] - 比例因子。

- Scales this SH by the given scale factor. + 按给定的比例因子缩放此SH。

[method:SphericalHarmonics3 set]( [param:Array coefficients] )

- [page:Array coefficients] - An array of SH coefficients.

+ [page:Array coefficients] - 一组SH系数。

- Sets the given SH coefficients to this instance. + 将给定的SH系数设置为此实例。

[method:Array toArray]( [param:Array array], [param:Number offset] )

- [page:Array array] - (optional) The target array.
- [page:Number offset] - (optional) The array offset.

+ [page:Array array] - (可选)目标数组。
+ [page:Number offset] - (可选)数组偏移量。

- Returns an array with the coefficients, or copies them into the provided array. The coefficients - are represented as numbers. + 返回包含系数的数组,或将它们复制到提供的数组中。系数表示为数字。

[method:SphericalHarmonics3 zero]()

- Sets all SH coefficients to 0. + 将所有SH系数设置为0。

-

Static Methods

+

静态方法(Static Methods)

[method:undefined getBasisAt]( [param:Vector3 normal], [param:Array shBasis] )

- [page:Vector3 normal] - The normal vector (assumed to be unit length).
- [page:Array shBasis] - The resulting SH basis.

+ [page:Vector3 normal] - 法向量(假定为单位长度)。
+ [page:Array shBasis] - 生成的SH基础。

- Computes the SH basis for the given normal vector. + 计算给定法向量的 SH 基础。

-

Source

+

源代码(Source)

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/math/Vector2.html b/docs/api/zh/math/Vector2.html index 59f8b167d33a07..9423dfc0937d76 100644 --- a/docs/api/zh/math/Vector2.html +++ b/docs/api/zh/math/Vector2.html @@ -97,6 +97,11 @@

[method:Float angle]()

计算该向量相对于x轴正方向的弧度角度。

+

[method:Float angleTo]( [param:Vector2 v] )

+

+ 以弧度返回该向量与向量[page:Vector2 v]之间的角度。 +

+

[method:this applyMatrix3]( [param:Matrix3 m] )

将该向量乘以三阶矩阵m(第三个值隐式地为1)。 diff --git a/docs/api/zh/objects/InstancedMesh.html b/docs/api/zh/objects/InstancedMesh.html index da3ccaf99fa3bc..83ea9ce4fae6aa 100644 --- a/docs/api/zh/objects/InstancedMesh.html +++ b/docs/api/zh/objects/InstancedMesh.html @@ -36,6 +36,16 @@

[name]( [param:BufferGeometry geometry], [param:Material material], [param:I

属性

See the base [page:Mesh] class for common properties.

+

[property:Box3 boundingBox]

+

+ 当前 [name] 的外边界矩形。可以通过 [page:.computeBoundingBox]() 计算。默认值是 *null*。 +

+ +

[property:Sphere boundingSphere]

+

+ 当前 [name] 的外边界球形。可以通过 [page:.computeBoundingSphere]() 计算。默认值是 *null*。 +

+

[property:Integer count]

实例的数量。被传入到构造函数中的*count*表示mesh实例数量的最大值。 @@ -66,6 +76,18 @@

[property:Boolean isInstancedMesh]

方法

See the base [page:Mesh] class for common methods.

+

[method:undefined computeBoundingBox]()

+

+ 计算当前几何体的的边界矩形,该操作会更新已有 [param:.boundingBox]。
+ 边界矩形不会默认计算,需要调用该接口指定计算边界矩形,否则保持默认值 *null*。 +

+ +

[method:undefined computeBoundingSphere]()

+

+ 计算当前几何体的的边界球形,该操作会更新已有 [param:.boundingSphere]。
+ 边界球形不会默认计算,需要调用该接口指定计算边界球形,否则保持默认值 *null*。 +

+

[method:undefined dispose]()

Frees the internal resources of this instance. diff --git a/docs/api/zh/objects/SkinnedMesh.html b/docs/api/zh/objects/SkinnedMesh.html index 23a1957f50b2e8..f5e0f71937f4f7 100644 --- a/docs/api/zh/objects/SkinnedMesh.html +++ b/docs/api/zh/objects/SkinnedMesh.html @@ -95,10 +95,6 @@

[name]( [param:BufferGeometry geometry], [param:Material material] )

[page:Material material] —— (可选)一个[page:Material]实例,默认值是一个新的[page:MeshBasicMaterial]。

- - - -

属性

共有属性请参见其基类[page:Mesh]。

@@ -119,6 +115,16 @@

[property:Matrix4 bindMatrixInverse]

该基础矩阵用于重置绑定骨骼的变换。

+

[property:Box3 boundingBox]

+

+ The bounding box of the [name]. Can be calculated with [page:.computeBoundingBox](). Default is `null`. +

+ +

[property:Sphere boundingSphere]

+

+ The bounding sphere of the [name]. Can be calculated with [page:.computeBoundingSphere](). Default is `null`. +

+

[property:Boolean isSkinnedMesh]

Read-only flag to check if a given object is of type [name]. @@ -129,11 +135,14 @@

[property:Skeleton skeleton]

用于表示蒙皮网格中骨骼的层次结构的[page:Skeleton](骨架)。

- -

方法

共有方法请参见其基类[page:Mesh]。

+

[method:Vector3 applyBoneTransform]( [param:Integer index], [param:Vector3 vector] )

+

+ Applies the bone transform associated with the given index to the given position vector. Returns the updated vector. +

+

[method:undefined bind]( [param:Skeleton skeleton], [param:Matrix4 bindMatrix] )

[page:Skeleton skeleton] —— 由一棵[page:Bone Bones]树创建的[page:Skeleton]。
@@ -146,6 +155,20 @@

[method:SkinnedMesh clone]()

This method does currently not clone an instance of [name] correctly. Please use [page:SkeletonUtils.clone]() in the meanwhile.

+

[method:undefined computeBoundingBox]()

+

+ Computes the bounding box, updating [page:.boundingBox] attribute.
+ Bounding boxes aren't computed by default. They need to be explicitly computed, otherwise they are `null`. + If an instance of [name] is animated, this method should be called per frame to compute a correct bounding box. +

+ +

[method:undefined computeBoundingSphere]()

+

+ Computes the bounding sphere, updating [page:.boundingSphere] attribute.
+ Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are `null`. + If an instance of [name] is animated, this method should be called per frame to compute a correct bounding sphere. +

+

[method:undefined normalizeSkinWeights]()

标准化蒙皮的权重。 diff --git a/docs/api/zh/renderers/WebGL3DRenderTarget.html b/docs/api/zh/renderers/WebGL3DRenderTarget.html new file mode 100644 index 00000000000000..39ae27e6916b3d --- /dev/null +++ b/docs/api/zh/renderers/WebGL3DRenderTarget.html @@ -0,0 +1,48 @@ + + + + + + + + + + [page:WebGLRenderTarget] → + +

[name]

+ +

表示三维的渲染目标。

+ +

构造函数

+ +

+ [name]( [param:Number width], [param:Number height], [param:Number depth] ) +

+

+ [page:Number width] - 渲染目标的宽度,单位为像素。默认值为`1`。
+ [page:Number height] - 渲染目标的高度,单位为像素。默认值为`1`。
+ [page:Number depth] - 渲染目标的深度。 默认值为`1`。

+ + 创建新的[name]. +

+ +

属性

+

继承属性请参考[page:WebGLRenderTarget]

+ +

[property:number depth]

+

渲染目标的深度。

+ +

[property:Data3DTexture texture]

+

+ [page:Data3DTexture]实例覆盖纹理属性。 +

+ +

方法

+

继承方法请参考[page:WebGLRenderTarget]

+ +

源码

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/zh/renderers/WebGLArrayRenderTarget.html b/docs/api/zh/renderers/WebGLArrayRenderTarget.html new file mode 100644 index 00000000000000..d1b42529a2f083 --- /dev/null +++ b/docs/api/zh/renderers/WebGLArrayRenderTarget.html @@ -0,0 +1,57 @@ + + + + + + + + + + [page:WebGLRenderTarget] → + +

[name]

+ +

+ 该类型的渲染目标表示一组纹理。 +

+ +

示例

+ +

+ [example:webgl2_rendertarget_texture2darray WebGL 2 / render target / array]
+

+ +

构造函数

+ +

+ [name]( [param:Number width], [param:Number height], [param:Number depth] ) +

+

+ [page:Number width] - 渲染目标的宽度,单位为像素。默认值为`1`。
+ [page:Number height] - 渲染目标的高度,单位为像素。默认值为`1`。
+ [page:Number depth] - 渲染目标的深度或图层数。 默认值为`1`。

+ + 创建新的[name]. +

+ +

属性

+ +

继承属性请参考[page:WebGLRenderTarget]

+ +

[property:number depth]

+

渲染目标的深度。

+ +

[property:DataArrayTexture texture]

+

+ [page:DataArrayTexture]实例覆盖纹理属性。 +

+ +

方法

+

继承方法请参考[page:WebGLRenderTarget]

+ +

源码

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/zh/renderers/WebGLCubeRenderTarget.html b/docs/api/zh/renderers/WebGLCubeRenderTarget.html index 16c62fa168bea0..a61a840bb8d09c 100644 --- a/docs/api/zh/renderers/WebGLCubeRenderTarget.html +++ b/docs/api/zh/renderers/WebGLCubeRenderTarget.html @@ -37,7 +37,7 @@

[name]([param:Number size], [param:Object options])

[page:Constant format] - 默认是[page:Textures RGBAFormat].
[page:Constant type] - 默认是[page:Textures UnsignedByteType].
[page:Number anisotropy] - 默认是 *1*. 参见[page:Texture.anisotropy]
- [page:Constant encoding] - 默认是[page:Textures LinearEncoding].
+ [page:Constant colorSpace] - 默认是[page:Textures NoColorSpace].
[page:Boolean depthBuffer] - 默认是*true*.
[page:Boolean stencilBuffer] - default is *false*.

diff --git a/docs/api/zh/renderers/WebGLMultipleRenderTargets.html b/docs/api/zh/renderers/WebGLMultipleRenderTargets.html index b4c9f3d7e2ee6e..a266b8bba9fcf5 100644 --- a/docs/api/zh/renderers/WebGLMultipleRenderTargets.html +++ b/docs/api/zh/renderers/WebGLMultipleRenderTargets.html @@ -12,49 +12,47 @@

[name]

- A special render target that enables a fragment shader to write to several textures. - This approach is useful for advanced rendering techniques like post-processing or deferred rendering. - - Heads up: [name] can only be used with a WebGL 2 rendering context. + 一个特殊的渲染目标,使片段着色器能够写入多个纹理。这种方法对于高级渲染技术很有用,例如后处理或延迟渲染。 + + 注意:[name]只能与 WebGL 2 渲染上下文一起使用。

-

Examples

+

例子(Examples)

[example:webgl2_multiple_rendertargets webgl2 / multiple / rendertargets ]

-

Constructor

+

构造器(Constructor)

[name]([param:Number width], [param:Number height], [param:Number count])

- [page:Number width] - The width of the render target. Default is `1`.
- [page:Number height] - The height of the render target. Default is `1`.
- [page:Number count] - The number of render targets. Default is `1`. + [page:Number width] - 渲染目标的宽度。默认为`1`。
+ [page:Number height] - 渲染目标的高度。默认为`1`。
+ [page:Number count] - 渲染目标的数量。默认为`1`。

-

Properties

+

特性(Properties)

[property:Boolean isWebGLMultipleRenderTargets]

- Read-only flag to check if a given object is of type [name]. + 只读标志,用于检查给定对象是否属于[name]类型。

[property:Array texture]

- The texture property is overwritten in [name] and replaced with an array. This array holds the [page:WebGLRenderTarget.texture texture] - references of the respective render targets. + 纹理属性在[name]中被覆盖并替换为数组。该数组包含各个渲染目标的[page:WebGLRenderTarget.texture 纹理]引用。

-

[page:WebGLRenderTarget WebGLRenderTarget] properties are available on this class.

+

[page:WebGLRenderTarget WebGLRenderTarget]属性在此类上可用。

-

Methods

+

方法(Methods)

-

[page:WebGLRenderTarget WebGLRenderTarget] methods are available on this class.

+

[page:WebGLRenderTarget WebGLRenderTarget]方法在此类上可用。

-

Source

+

源代码(Source)

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/renderers/WebGLRenderTarget.html b/docs/api/zh/renderers/WebGLRenderTarget.html index edc56ae8242267..212aa3fb73b021 100644 --- a/docs/api/zh/renderers/WebGLRenderTarget.html +++ b/docs/api/zh/renderers/WebGLRenderTarget.html @@ -35,7 +35,7 @@

[name]([param:Number width], [param:Number height], [param:Object options])< [page:Constant format] - 默认是[page:Textures RGBAFormat].
[page:Constant type] - 默认是[page:Textures UnsignedByteType].
[page:Number anisotropy] - 默认是`1`. 参见[page:Texture.anisotropy]
- [page:Constant encoding] - 默认是[page:Textures LinearEncoding].
+ [page:Constant colorSpace] - 默认是[page:Textures NoColorSpace].
[page:Boolean depthBuffer] - 默认是`true`.
[page:Boolean stencilBuffer] - 默认是`false`.
[page:Number samples] - 默认是`0`.

diff --git a/docs/api/zh/renderers/WebGLRenderer.html b/docs/api/zh/renderers/WebGLRenderer.html index 57f8e119da9ed6..263e861f436fea 100644 --- a/docs/api/zh/renderers/WebGLRenderer.html +++ b/docs/api/zh/renderers/WebGLRenderer.html @@ -89,7 +89,11 @@

[property:Object debug]

编译和链接过程中的错误。 禁用此检查生产以获得性能增益可能很有用。 强烈建议在开发期间保持启用这些检查。 如果着色器没有编译和链接 - 它将无法工作,并且相关材料将不会呈现。 - 默认是*true* + 默认是*true*
+ - [page:Function onShaderError]( gl, program, glVertexShader, glFragmentShader ): + A callback function that can be used for custom error reporting. The callback receives the WebGL context, an instance of WebGLProgram as well + two instances of WebGLShader representing the vertex and fragment shader. Assigning a custom function disables the default error reporting. + Default is `null`.

[property:Object capabilities]

@@ -147,9 +151,9 @@

[property:Object extensions]

-

[property:number outputEncoding]

-

定义渲染器的输出编码。默认为[page:Textures THREE.LinearEncoding]

-

如果渲染目标已经使用 [page:WebGLRenderer.setRenderTarget .setRenderTarget]、之后将直接使用renderTarget.texture.encoding

+

[property:string outputColorSpace]

+

定义渲染器的输出编码。默认为[page:Textures THREE.SRGBColorSpace]

+

如果渲染目标已经使用 [page:WebGLRenderer.setRenderTarget .setRenderTarget]、之后将直接使用renderTarget.texture.colorSpace

查看[page:Textures texture constants]页面以获取其他格式细节

[property:Object info]

@@ -188,10 +192,9 @@

[property:Object info]

[property:Boolean localClippingEnabled]

定义渲染器是否考虑对象级剪切平面。 默认为*false*.

-

[property:Boolean physicallyCorrectLights]

+

[property:Boolean useLegacyLights]

- 是否使用物理上正确的光照模式。 默认是*false*。 - 示例:[example:webgl_lights_physical lights / physical] + Whether to use the legacy lighting mode or not. 默认是*true*。

[property:Object properties]

diff --git a/docs/api/zh/renderers/shaders/UniformsUtils.html b/docs/api/zh/renderers/shaders/UniformsUtils.html index 91f6a4b254024e..4014078491aacc 100644 --- a/docs/api/zh/renderers/shaders/UniformsUtils.html +++ b/docs/api/zh/renderers/shaders/UniformsUtils.html @@ -10,29 +10,26 @@

[name]

- Provides utility functions for managing uniforms. + 提供用于管理uniforms的实用功能。

-

方法

+

方法(Method)

[method:Object clone]( [param:Object src] )

- src -- An object representing uniform definitions.

+ src -- 表示定义uniforms的对象的路径

- Clones the given uniform definitions by performing a deep-copy. That means if - the [page:Uniform.value value] of a uniform refers to an object like a [page:Vector3] - or [page:Texture], the cloned uniform will refer to a new object reference. + 通过执行深层复制克隆给定的统一定义。 + 这意味着如果uniform的[page:Uniform.value 值]引用[page:Vector3]或[page:Texture]之类的对象,则克隆的uniform将引用新的对象引用。

[method:Object merge]( [param:Array uniforms] )

- uniforms -- An array of objects containing uniform definitions.

+ uniforms -- 包含uniforms定义的对象数组

- Merges the given uniform definitions into a single object. Since the method - internally uses [page:.clone](), it performs a deep-copy when producing the - merged uniform definitions. + 将给定的统一定义合并到一个对象中。由于该方法在内部使用[page:.clone](),因此它在生成合并的统一定义时执行深度复制。 -

源码

+

源代码(Source)

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/renderers/webxr/WebXRManager.html b/docs/api/zh/renderers/webxr/WebXRManager.html index 8c5a0caf4fc79e..6c13bf7a9e502d 100644 --- a/docs/api/zh/renderers/webxr/WebXRManager.html +++ b/docs/api/zh/renderers/webxr/WebXRManager.html @@ -11,129 +11,123 @@

[name]

- - This class represents an abstraction of the WebXR Device API and is internally used by [page:WebGLRenderer]. - [name] also provides a public interface that allows users to enable/disable XR and perform XR related tasks like - for instance retrieving controllers. + 此类表示WebXR设备API的抽象,并由[page:WebGLRenderer]在内部使用。 + [name]还提供了一个公共接口,允许用户启用/禁用XR并执行XR相关任务,例如检索控制器。

Properties

[property:Boolean cameraAutoUpdate]

- Whether the manager's XR camera should be automatically updated or not. Default is *true*. + manager的XR摄像头是否应自动更新。默认为*true*。

[property:Boolean enabled]

- This flag notifies the renderer to be ready for XR rendering. Default is *false*. Set it to *true* if you are going - to use XR in your app. + 此标志通知渲染器准备好进行XR渲染。默认为假。 + 如果您要在应用中使用XR,请将其设置为*true*。

[property:Boolean isPresenting]

- Whether XR presentation is active or not. Default is *false*. This flag is read-only and automatically set by [name]. + XR演示是否处于活动状态。默认为*false*。该标志是只读的,由[name]自动设置。

-

Methods

+

方法(Methods)

[method:ArrayCamera getCamera]()

- Returns an instance of [page:ArrayCamera] which represents the XR camera of the active XR session. - For each view it holds a separate camera object in its [page:ArrayCamera.cameras cameras] property. + 返回表示活动XR会话的XR相机的[page:ArrayCamera]实例。 + 对于每个视图,它在其[page:ArrayCamera.cameras cameras]属性中包含一个单独的相机对象。

- The camera's *fov* is currently not used and does not reflect the fov of the XR camera. If you need the fov on app level, - you have to compute in manually from the XR camera's projection matrices. + 当前未使用相机的*fov*,不反映 XR 相机的 fov。 + 如果您需要应用级别的fov,则必须从XR相机的投影矩阵中手动计算。

[method:Group getController]( [param:Integer index] )

- [page:Integer index] — The index of the controller.

- - Returns a [page:Group] representing the so called *target ray* space of the XR controller. - Use this space for visualizing 3D objects that support the user in pointing tasks like UI interaction. + [page:Integer index] — 控制器的索引。

+ + 返回表示XR控制器所谓的*目标光线*空间的[page:Group 组]。使用此空间可视化3D对象,支持用户完成UI交互等指向任务。

[method:Group getControllerGrip]( [param:Integer index] )

- [page:Integer index] — The index of the controller.

+ [page:Integer index] — 控制器的索引。

+ + 返回一个[page:Group 组],代表所谓的XR控制器的*抓地力*空间。如果用户要握住其他3D对象(如光剑),请使用此空间。 - Returns a [page:Group] representing the so called *grip* space of the XR controller. - Use this space if the user is going to hold other 3D objects like a lightsaber.

- Note: If you want to show something in the user's hand AND offer a pointing ray at the same time, you'll want to attached the handheld object to the - group returned by [page:.getControllerGrip]() and the ray to the group returned by [page:.getController](). The idea is to have two different groups - in two different coordinate spaces for the same WebXR controller. + 注意:如果你想显示用户手中的东西并同时提供指向光线, + 你需要将手持对象附加到[page:.getControllerGrip]()返回的组, + 并将光线附加到[page:.getController]()返回的组. + 这个想法是在同一个WebXR控制器的两个不同坐标空间中有两个不同的组。

[method:Group getHand]( [param:Integer index] )

- [page:Integer index] — The index of the controller.

+ [page:Integer index] — 控制器的索引。

- Returns a [page:Group] representing the so called *hand* or *joint* space of the XR controller. - Use this space for visualizing the user's hands when no physical controllers are used. -

- -

[method:Set getPlanes]()

-

- Returns the set of planes detected by WebXR's plane detection API. + 返回代表XR控制器所谓的*手或关节*空间的[page:Group 组]。在不使用物理控制器时,使用此空间可视化用户的手。

[method:String getReferenceSpace]()

- Returns the reference space. + 返回参考空间。

[method:XRSession getSession]()

- Returns the *XRSession* object which allows a more fine-grained management of active WebXR sessions on application level. + 返回*XRSession*对象,它允许在应用程序级别更细粒度地管理活动的WebXR会话。

[method:undefined setFramebufferScaleFactor]( [param:Float factor], [param:Boolean limited] )

- [page:Float factor] — The framebuffer scale factor to set.
- [page:Boolean limited] — Whether the framebuffer scale factor should be reduced to the native limit if the value ends up being higher than the device's capabilities. Default is `false`.

+ [page:Float factor] — 要设置的帧缓冲区比例因子。
+ [page:Boolean limited] — 如果值最终高于设备的能力,是否应将帧缓冲区比例因子减小到本机限制。默认为`false`。

- Specifies the scaling factor to use when determining the size of the framebuffer when rendering to a XR device. - The value is relative to the default XR device display resolution. Default is *1*. A value of *0.5* would specify - a framebuffer with 50% of the display's native resolution. + 指定在渲染到XR设备时确定帧缓冲区大小时要使用的比例因子。 + 该值是相对于默认XR设备显示分辨率的。默认为*1*。值0.5将指定具有显示器原始分辨率50%的帧缓冲区。 +

- Note: It is not possible to change the framebuffer scale factor while presenting XR content. + 注意:在呈现XR内容时无法更改帧缓冲区比例因子。

[method:undefined setReferenceSpace]( [param:XRReferenceSpace referenceSpace] )

- [page:XRReferenceSpace referenceSpace] — A custom reference space.

+ [page:XRReferenceSpace referenceSpace] — 自定义参考空间。

- Can be used to configure a custom reference space which overwrites the default reference space. + 可用于配置覆盖默认参考空间的自定义参考空间。

[method:undefined setReferenceSpaceType]( [param:String referenceSpaceType] )

- [page:String referenceSpaceType] — The reference space type to set.

+ [page:String referenceSpaceType] — 要设置的参考空间类型。

- Can be used to configure a spatial relationship with the user's physical environment. Depending on how the user moves in 3D space, setting an - appropriate reference space can improve tracking. Default is *local-floor*. - Please check out the [link:https://developer.mozilla.org/en-US/docs/Web/API/XRReferenceSpaceType MDN] for possible values and their use cases. + 可用于配置与用户物理环境的空间关系。 + 根据用户在3D空间中的移动方式,设置适当的参考空间可以改进跟踪。 + 默认为*本层空间*。 + 请查看[link:https://developer.mozilla.org/en-US/docs/Web/API/XRReferenceSpaceType MDN]以了解可能的值及其用例。

[method:undefined updateCamera]( [param:PerspectiveCamera camera] )

- Updates the state of the XR camera. Use this method on app level if you set [page:.cameraAutoUpdate] to *false*. - The method requires the non-XR camera of the scene as a parameter. The passed in camera's transformation is automatically - adjusted to the position of the XR camera when calling this method. + 更新 XR 相机的状态。 + 如果您将[page:.cameraAutoUpdate]设置为*false*,请在应用级别使用此方法。 + 该方法需要场景的非 XR 相机作为参数。 + 调用此方法时,传入的相机变换会自动调整到 XR 相机的位置。

- Note: It is not possible to change the reference space type while presenting XR content. + 注意:在呈现 XR 内容时无法更改参考空间类型。

-

Source

+

源代码(Source)

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/scenes/Fog.html b/docs/api/zh/scenes/Fog.html index 8df0148c218012..17a096ad8b9085 100644 --- a/docs/api/zh/scenes/Fog.html +++ b/docs/api/zh/scenes/Fog.html @@ -11,6 +11,11 @@

雾([name])

这个类中的参数定义了线性雾。也就是说,雾的密度是随着距离线性增大的。

+

代码示例

+ + const scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0xcccccc, 10, 15 ); +

构造器

diff --git a/docs/api/zh/scenes/FogExp2.html b/docs/api/zh/scenes/FogExp2.html index 7ea9293d927f3a..63353f14083b61 100644 --- a/docs/api/zh/scenes/FogExp2.html +++ b/docs/api/zh/scenes/FogExp2.html @@ -11,6 +11,12 @@

雾-指数([name])

该类所包含的参数定义了指数雾,它可以在相机附近提供清晰的视野,且距离相机越远,雾的浓度随着指数增长越快。

+

代码示例

+ + const scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 ); + +

构造器

diff --git a/docs/api/zh/textures/CompressedTexture.html b/docs/api/zh/textures/CompressedTexture.html index ce3393a62e986d..62efc4c1d9135b 100644 --- a/docs/api/zh/textures/CompressedTexture.html +++ b/docs/api/zh/textures/CompressedTexture.html @@ -22,7 +22,7 @@

压缩的纹理([name])

构造函数

-

[name]( [param:Array mipmaps], [param:Number width], [param:Number height], [param:Constant format], [param:Constant type], [param:Constant mapping], [param:Constant wrapS], [param:Constant wrapT], [param:Constant magFilter], [param:Constant minFilter], [param:Number anisotropy] )

+

[name]( [param:Array mipmaps], [param:Number width], [param:Number height], [param:Constant format], [param:Constant type], [param:Constant mapping], [param:Constant wrapS], [param:Constant wrapT], [param:Constant magFilter], [param:Constant minFilter], [param:Number anisotropy], , [param:Constant colorSpace] )

[page:Array mipmaps] -- mipmaps数组中需要包含具有数据、宽、高的对象。mipmaps应当具有正确的格式与类型。
@@ -55,7 +55,10 @@

[name]( [param:Array mipmaps], [param:Number width], [param:Number height], [page:Number anisotropy] -- 沿着轴,通过具有最高纹素密度的像素的样本数。 默认情况下,这个值为1。设置一个较高的值将会产生比基本的mipmap更清晰的效果,代价是需要使用更多纹理样本。 - 使用[page:WebGLrenderer.getMaxAnisotropy renderer.getMaxAnisotropy]() 来查询GPU中各向异性的最大有效值;这个值通常是2的幂。

+ 使用[page:WebGLrenderer.getMaxAnisotropy renderer.getMaxAnisotropy]() 来查询GPU中各向异性的最大有效值;这个值通常是2的幂。
+ + [page:Constant colorSpace] -- The default is [page:Textures THREE.NoColorSpace]. + See [page:Textures color space constants] for other choices.

diff --git a/docs/api/zh/textures/CubeTexture.html b/docs/api/zh/textures/CubeTexture.html index 08ebde4b8665b0..c8017fce2d0a33 100644 --- a/docs/api/zh/textures/CubeTexture.html +++ b/docs/api/zh/textures/CubeTexture.html @@ -31,7 +31,7 @@

代码示例

构造函数

-

[name]( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy )

+

[name]( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace )

CubeTexture(立方贴图)的功能以及用法几乎和[page:Texture]是相同的。区别在于,CubeTexture中的图像是6个单独的图像所组成的数组, diff --git a/docs/api/zh/textures/DataArrayTexture.html b/docs/api/zh/textures/DataArrayTexture.html new file mode 100644 index 00000000000000..46829d2a3b3104 --- /dev/null +++ b/docs/api/zh/textures/DataArrayTexture.html @@ -0,0 +1,152 @@ + + + + + + + + + + [page:Texture] → + +

数据数组纹理([name])

+ +

+ 直接从原始数据、宽度、高度和深度创建纹理数组。这种类型的纹理只能与 WebGL 2 渲染上下文一起使用。 +

+ + +

构造函数(Constructor)

+ +

[name]( data, width, height, depth )

+

+ data参数必须是[link:https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView ArrayBufferView]。 + 默认继承自[page:Texture Texture]的属性,除了magFilter和minFilter默认为THREE.NearestFilter。 + 属性flipY和generateMipmaps最初设置为false。 +

+

+ 数据的解释取决于类型和格式:如果类型是THREE.UnsignedByteType,则Uint8Array可用于寻址纹素数据。 + 如果格式为THREE.RGBAFormat,则数据需要为一个纹素提供四个值;红色、绿色、蓝色和Alpha(通常是不透明度)。 + 对于打包类型,THREE.UnsignedShort4444Type和THREE.UnsignedShort5551Type,一个纹素的所有颜色分量都可以作为Uint16Array的整数元素中的位域进行寻址。 + 为了使用THREE.FloatType和THREE.HalfFloatType类型,WebGL实现必须支持相应的扩展OES_texture_float和OES_texture_half_float。 + 为了将THREE.LinearFilter用于基于这些类型的纹素的分量双线性插值,还必须存在WebGL扩展OES_texture_float_linear或OES_texture_half_float_linear。 +

+ +

代码示例(Code Example)

+ +

这将创建一个[name],其中每个纹理都有不同的颜色。

+ + + // 使用颜色数据创建缓冲区 + + const width = 512; + const height = 512; + const depth = 100; + + const size = width * height; + const data = new Uint8Array( 4 * size * depth ); + + for ( let i = 0; i < depth; i ++ ) { + + const color = new THREE.Color( Math.random(), Math.random(), Math.random() ); + const r = Math.floor( color.r * 255 ); + const g = Math.floor( color.g * 255 ); + const b = Math.floor( color.b * 255 ); + + for ( let j = 0; j < size; j ++ ) { + + const stride = ( i * size + j ) * 4; + + data[ stride ] = r; + data[ stride + 1 ] = g; + data[ stride + 2 ] = b; + data[ stride + 3 ] = 255; + + } + } + + // 使用缓冲区创建的颜色数据创建缓冲区[name] + + const texture = new THREE.DataArrayTexture( data, width, height, depth ); + texture.needsUpdate = true; + + +

示例(Examples)

+ +

+ [example:webgl2_materials_texture2darray WebGL2 / materials / texture2darray] + [example:webgl2_rendertarget_texture2darray WebGL2 / rendertarget / texture2darray] +

+ +

特性(Properties)

+ +

+ 请参阅基本[page:Texture Texture]类以了解通用属性 +

+ +

[property:Boolean flipY]

+

+ 纹理上传到GPU时是否沿Y轴翻转。默认为false。 +

+ +

[property:Boolean generateMipmaps]

+

+ 是否为纹理生成mipmap(如果可能)。默认为false。 +

+ +

[property:Object image]

+

+ 被包含数据、宽度、高度和深度的对象覆盖。 +

+ +

[property:Boolean isDataArrayTexture]

+

+ 只读标志,用于检查给定对象是否属于[name]类型。 +

+ +

[property:number magFilter]

+

+ 当纹素覆盖多个像素时如何对纹理进行采样。默认值为[page:Textures THREE.NearestFilter],它使用最近的纹理元素的值。 +

+ + 有关详细信息,请参阅[page:Textures texture constants]页面。 +

+ +

[property:number minFilter]

+

+ 当纹素覆盖少于一个像素时如何对纹理进行采样。默认值为[page:Textures THREE.NearestFilter],它使用最近的纹理元素的值。 +

+ + 有关详细信息,请参阅[page:Textures texture constants]页面。 +

+ +

[property:number unpackAlignment]

+

+ 默认为1。 + 指定内存中每个像素行开始的对齐要求。 + 允许的值为1(字节对齐)、2(行对齐到偶数字节)、4(字对齐)和8(行从双字边界开始)。 + 有关详细信息,请参阅[link:https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glPixelStorei.xhtml glPixelStorei]。 +

+ +

[property:number wrapR]

+

+ 这定义了纹理在深度方向上的包裹方式。
+ 默认值为[page:Textures THREE.ClampToEdgeWrapping],其中边缘被夹紧到外边缘纹素。 + 其他两个选择是[page:Textures THREE.RepeatWrapping]和[page:Textures THREE.MirroredRepeatWrapping]。 + + 有关详细信息,请参阅[page:Textures texture constants]页面。 +

+ +

方法(Methods)

+ +

+ 有关常用方法, 请参见[page:Texture Texture]类。 +

+ +

源代码(Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/zh/textures/DataTexture.html b/docs/api/zh/textures/DataTexture.html index f7a45e1bf2f68e..33ab84cdf6b1d1 100644 --- a/docs/api/zh/textures/DataTexture.html +++ b/docs/api/zh/textures/DataTexture.html @@ -16,7 +16,7 @@

[name]

构造函数

-

[name]( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy )

+

[name]( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace )

data 参数必须是一个 [link:https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView ArrayBufferView] 。 其他参数对应于继承自 [page:Texture] 的属性,其中 magFilter 与 minFilter 默认为 THREE.NearestFilter。 @@ -80,7 +80,7 @@

[property:Boolean generateMipmaps]

Whether to generate mipmaps (if possible) for a texture. False by default.

-

[property:Image image]

+

[property:Object image]

Overridden with a record type holding data, width and height.

diff --git a/docs/api/zh/textures/DataTexture2DArray.html b/docs/api/zh/textures/DataTexture2DArray.html deleted file mode 100644 index f196e9ab869d87..00000000000000 --- a/docs/api/zh/textures/DataTexture2DArray.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - [page:Texture] → - -

[name]

- -

Creates an array of textures directly from raw data, width and height and depth. This type of texture can only be used with a WebGL 2 rendering context.

- - -

Constructor

- -

[name]( data, width, height, depth )

-

- The data argument must be an [link:https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView ArrayBufferView]. - The properties inherited from [page:Texture] are the default, except magFilter and minFilter default to THREE.NearestFilter. The properties flipY and generateMipmaps are initially set to false. -

-

- The interpretation of the data depends on type and format: - If the type is THREE.UnsignedByteType, a Uint8Array will be useful for addressing the texel data. - If the format is THREE.RGBAFormat, data needs four values for one texel; Red, Green, Blue and Alpha (typically the opacity).
- - For the packed types, THREE.UnsignedShort4444Type and THREE.UnsignedShort5551Type all color components of one texel can be addressed as bitfields within an integer element of a Uint16Array.
- - In order to use the types THREE.FloatType and THREE.HalfFloatType, the WebGL implementation must support the respective extensions OES_texture_float and OES_texture_half_float. In order to use THREE.LinearFilter for component-wise, bilinear interpolation of the texels based on these types, the WebGL extensions OES_texture_float_linear or OES_texture_half_float_linear must also be present. -

- -

代码示例

- -

This creates a [name] where each texture has a different color.

- - - // create a buffer with color data - - const width = 512; - const height = 512; - const depth = 100; - - const size = width * height; - const data = new Uint8Array( 4 * size * depth ); - - for ( let i = 0; i < depth; i ++ ) { - - const color = new THREE.Color( Math.random(), Math.random(), Math.random() ); - const r = Math.floor( color.r * 255 ); - const g = Math.floor( color.g * 255 ); - const b = Math.floor( color.b * 255 ); - - for ( let j = 0; j < size; j ++ ) { - - const stride = ( i * size + j ) * 4; - - data[ stride ] = r; - data[ stride + 1 ] = g; - data[ stride + 2 ] = b; - data[ stride + 3 ] = 255; - - } - } - - // used the buffer to create a [name] - - const texture = new THREE.DataArrayTexture( data, width, height, depth ); - texture.needsUpdate = true; - - -

- [example:webgl2_materials_texture3d WebGL2 / materials / texture3d] -

- -

Properties

- -

- See the base [page:Texture Texture] class for common properties. -

- -

[property:Image image]

-

- Overridden with a record type holding data, width and height and depth. -

- -

Methods

- -

- See the base [page:Texture Texture] class for common methods. -

- -

Source

- -

- [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] -

- - diff --git a/docs/api/zh/textures/DepthTexture.html b/docs/api/zh/textures/DepthTexture.html index c6024eb6dc043e..a5d2b276436f7c 100644 --- a/docs/api/zh/textures/DepthTexture.html +++ b/docs/api/zh/textures/DepthTexture.html @@ -9,7 +9,7 @@ [page:Texture] → -

深度纹理([name])

+

深度纹理([name])

This class can be used to automatically save the depth information of a rendering into a texture. diff --git a/docs/api/zh/textures/FramebufferTexture.html b/docs/api/zh/textures/FramebufferTexture.html index 18f5ee7f05802d..a68d0e8f8c4eac 100644 --- a/docs/api/zh/textures/FramebufferTexture.html +++ b/docs/api/zh/textures/FramebufferTexture.html @@ -9,41 +9,82 @@ [page:Texture] → -

[name]

+

帧缓冲纹理([name])

- This class can only be used in combination with [page:WebGLRenderer.copyFramebufferToTexture](). + 这个类只能与 [page:WebGLRenderer.copyFramebufferToTexture]() 结合使用。

-

Constructor

-

[name]( [param:Number width], [param:Number height], [param:Constant format] )

+ + const pixelRatio = window.devicePixelRatio; + const textureSize = 128 * pixelRatio; + + // instantiate a framebuffer texture + const frameTexture = new FramebufferTexture( textureSize, textureSize ); + + // calculate start position for copying part of the frame data + const vector = new Vector2(); + vector.x = ( window.innerWidth * pixelRatio / 2 ) - ( textureSize / 2 ); + vector.y = ( window.innerHeight * pixelRatio / 2 ) - ( textureSize / 2 ); + + // render the scene + renderer.clear(); + renderer.render( scene, camera ); + + // copy part of the rendered frame into the framebuffer texture + renderer.copyFramebufferToTexture( vector, frameTexture ); + + +

例子

+ +

[example:webgl_framebuffer_texture]

+ +

构造函数

+

[name]( [param:Number width], [param:Number height] )

- [page:Number width] -- The width of the texture.
+ [page:Number width] -- 纹理的宽度
- [page:Number height] -- The height of the texture.
+ [page:Number height] -- 纹理的高度

- [page:Constant format] -- The format used in the texture. - See [page:Textures format constants] for other choices.

-

Properties

+

属性

+ +

共有属性请参见其基类 [page:Texture Texture]

-

See the base [page:Texture Texture] class for common properties.

+

[property:Boolean generateMipmaps]

+

是否为 [name] 生成 mipmaps ,默认为`false`

[property:Boolean isFramebufferTexture]

+

只读,检查给定对象是否为 [name] 类型

+ +

[property:number magFilter]

- Read-only flag to check if a given object is of type [name]. + 纹理元素覆盖多个像素时如何对纹理进行采样。默认值为 [page:Textures THREE.NearestFilter] ,它使用最接近的纹理元素。 +

+ + 更多细节详见 [page:Textures texture constants] +

+ +

[property:number minFilter]

+

+ 纹理元素覆盖少于一个像素时如何对纹理进行采样。默认值为 [page:Textures THREE.NearestFilter] ,它使用最近的纹理元素。 +

+ + 更多细节详见 [page:Textures texture constants]

[property:Boolean needsUpdate]

-

Methods

+

默认为 `true` ,这是加载 canvas 数据所必需的

+ +

方法

-

See the base [page:Texture Texture] class for common methods.

+

共有方法请参见其基类 [page:Texture Texture]

-

Source

+

源代码

[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] diff --git a/docs/api/zh/textures/Texture.html b/docs/api/zh/textures/Texture.html index 6b77c9a7147624..364308063252bc 100644 --- a/docs/api/zh/textures/Texture.html +++ b/docs/api/zh/textures/Texture.html @@ -14,7 +14,7 @@

纹理([name])

构造函数

-

[name]( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding )

+

[name]( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace )

代码示例

@@ -71,6 +71,11 @@

[property:number mapping]

请参阅[page:Textures texture constants](映射模式常量)来了解其他映射类型。

+

[property:Integer channel]

+

+ Lets you select the uv attribute to map the texture to. `0` for `uv`, `1` for `uv1`, `2` for `uv2` and `3` for `uv3`. +

+

[property:number wrapS]

这个值定义了纹理贴图在水平方向上将如何包裹,在UV映射中对应于*U*。
@@ -122,13 +127,10 @@

[property:number format]

[property:String internalFormat]

- The default value is obtained using a combination of [page:Texture.format .format] and - [page:Texture.type .type].
+ 此项的默认值由[page:Texture.format .format]和[page:Texture.type .type]混合并决定。
- The GPU format allows the developer to specify how the data is going to be - stored on the GPU.

- - See the [page:Textures texture constants] page for details regarding all supported internal formats. + 这项GPU格式设置允许开发者决定在GPU中的数据存储方式。

+ 查看[page:Textures texture constants]页面来了解所有可用的Internal Formats以及其细节。

[property:number type]

@@ -141,42 +143,15 @@

[property:number type]

[property:Vector2 offset]

- How much a single repetition of the texture is offset from the beginning, in each direction U and V. - Typical range is *0.0* to *1.0*. -

-

- The below texture types share the *first* uv channel in the engine. The offset (and repeat) setting is evaluated according to - the following priorities and then shared by those textures: -

    -
  1. color map
  2. -
  3. specular map
  4. -
  5. displacement map
  6. -
  7. normal map
  8. -
  9. bump map
  10. -
  11. roughness map
  12. -
  13. metalness map
  14. -
  15. alpha map
  16. -
  17. emissive map
  18. -
  19. clearcoat map
  20. -
  21. clearcoat normal map
  22. -
  23. clearcoat roughnessMap map
  24. -
-

-

- The below texture types share the *second* uv channel in the engine. The offset (and repeat) setting is evaluated according to - the following priorities and then shared by those textures: -

    -
  1. ao map
  2. -
  3. light map
  4. -
+ 贴图单次重复中的起始偏移量,分别表示U和V。 + 一般范围是由`0.0`到`1.0`。

[property:Vector2 repeat]

- How many times the texture is repeated across the surface, in each direction U and V. If repeat is set - greater than 1 in either direction, the corresponding Wrap parameter should also be set to - [page:Textures THREE.RepeatWrapping] or [page:Textures THREE.MirroredRepeatWrapping] to achieve the desired - tiling effect. Setting different repeat values for textures is restricted in the same way like [page:.offset]. + 决定纹理在表面的重复次数,两个方向分别表示U和V,如果重复次数在任何方向上设置了超过1的数值, + 对应的Wrap需要设置为[page:Textures THREE.RepeatWrapping]或者[page:Textures THREE.MirroredRepeatWrapping]来 + 达到想要的平铺效果。

[property:number rotation]

@@ -213,18 +188,18 @@

[property:Boolean generateMipmaps]

[property:Boolean premultiplyAlpha]

- If set to *true*, the alpha channel, if present, is multiplied into the color channels when the texture is uploaded to the GPU. Default is *false*.

+ 如果设置为*true*并且alpha通道存在的话,上传到GPU时alpha的数值将会与颜色通道的数值相乘。默认为*false*。

- Note that this property has no effect for [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap]. - You need to configure on bitmap creation instead. See [page:ImageBitmapLoader]. + 注意此项属性不会影响到[link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap]。 + 如果你想要则需要在bitmap创建的时候进行配置,如何配置请查看[page:ImageBitmapLoader]。

[property:Boolean flipY]

- If set to *true*, the texture is flipped along the vertical axis when uploaded to the GPU. Default is *true*.

+ 如果设置为*true*,纹理在上传到GPU的时候会进行纵向的翻转。默认值为*true*。

- Note that this property has no effect for [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap]. - You need to configure on bitmap creation instead. See [page:ImageBitmapLoader]. + 注意此项属性不会影响到[link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap]。 + 如果你想要则需要在bitmap创建的时候进行配置,如何配置请查看[page:ImageBitmapLoader]。

[property:number unpackAlignment]

@@ -234,13 +209,10 @@

[property:number unpackAlignment]

请参阅[link:http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml glPixelStorei]来了解详细信息。

-

[property:number encoding]

+

[property:string colorSpace]

- 默认值为[page:Textures THREE.LinearEncoding]。 - 请参阅[page:Textures texture constants]来了解其他格式的详细信息。

- - 请注意,如果在材质被使用之后,纹理贴图中这个值发生了改变, - 需要触发Material.needsUpdate,来使得这个值在着色器中实现。 + 默认值为[page:Textures THREE.NoColorSpace]。 + 请参阅[page:Textures texture constants]来了解其他格式的详细信息。

[property:Integer version]

@@ -262,14 +234,12 @@

[property:Boolean needsUpdate]

[property:Object userData]

- An object that can be used to store custom data about the texture. It should not hold - references to functions as these will not be cloned. + 保存关于纹理的自定义信息的对象。不应该放函数引用,因为函数不会拷贝。

[property:Source source]

- The data definition of a texture. A reference to the data source can be shared across textures. - This is often useful in context of spritesheets where multiple textures render the same data but with different texture transformations. + 纹理的数据源信息。可以在不同的纹理之间引用相同的数据源,这在使用精灵表的情况下很好用,因为在这种情况下不同的纹理只是使用了不同的偏移,但是其数据源是相同的。

方法

@@ -285,7 +255,7 @@

[method:undefined updateMatrix]()

[method:Texture clone]()

拷贝纹理。请注意。这不是“深拷贝”,图像是共用的。 - Besides, cloning a texture does not automatically mark it for a texture upload. You have to set [page:Texture.needsUpdate] to true as soon as its image property (the data source) is fully loaded or ready. + 除此之外,拷贝一个纹理并不会将此纹理自动标记并上传。你需要在图片的属性变更或者源数据完全加载完的时候并准备好的时候将[page:Texture.needsUpdate]设置为true。

[method:Object toJSON]( [param:Object meta] )

diff --git a/docs/examples/en/animations/CCDIKSolver.html b/docs/examples/en/animations/CCDIKSolver.html index 7025708e0d6cb1..bb1cc7e0af7905 100644 --- a/docs/examples/en/animations/CCDIKSolver.html +++ b/docs/examples/en/animations/CCDIKSolver.html @@ -16,6 +16,17 @@

[name]

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { CCDIKSolver } from 'three/addons/animation/CCDIKSolver.js'; + +

Code Example

@@ -118,6 +129,7 @@

[name]( [param:SkinnedMesh mesh], [param:Array iks] )

[page:SkinnedMesh mesh] — [page:SkinnedMesh] for which [name] solves IK problem.
[page:Array iks] — An array of [page:Object] specifying IK parameter. target, effector, and link-index are index integers in .skeleton.bones. The bones relation should be "links[ n ], links[ n - 1 ], ..., links[ 0 ], effector" in order from parent to child.
+

  • [page:Integer target] — Target bone.
  • [page:Integer effector] — Effector bone.
  • @@ -134,7 +146,6 @@

    [name]( [param:SkinnedMesh mesh], [param:Array iks] )

  • [page:Number minAngle] — (optional) Minimum rotation angle in a step. Default is undefined.
  • [page:Number maxAngle] — (optional) Maximum rotation angle in a step. Default is undefined.
-

Creates a new [name].

diff --git a/docs/examples/en/animations/MMDAnimationHelper.html b/docs/examples/en/animations/MMDAnimationHelper.html index 1ba7fd81419ee9..29ab1627380265 100644 --- a/docs/examples/en/animations/MMDAnimationHelper.html +++ b/docs/examples/en/animations/MMDAnimationHelper.html @@ -14,6 +14,17 @@

[name]

It uses [page:CCDIKSolver] and [page:MMDPhysics] inside.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { MMDAnimationHelper } from 'three/addons/animation/MMDAnimationHelper.js'; + +

Code Example

@@ -73,6 +84,7 @@

Constructor

[name]( [param:Object params] )

[page:Object params] — (optional)
+

  • [page:Boolean sync] - Whether animation durations of added objects are synched. Default is true.
  • [page:Number afterglow] - Default is 0.0.
  • @@ -80,7 +92,6 @@

    [name]( [param:Object params] )

  • [page:Boolean pmxAnimation] - If it is set to true, the helper follows the complex and costly PMX animation system. Try this option only if your PMX model animation doesn't work well. Default is false.
-

Creates a new [name].

@@ -108,6 +119,7 @@

[method:MMDAnimationHelper add]( [param:Object3D object], [param:Object para

[page:Object3D object] — [page:SkinnedMesh], [page:Camera], or [page:Audio]
[page:Object params] — (optional)
+

  • [page:AnimationClip animation] - an [page:AnimationClip] or an array of [page:AnimationClip] set to object. Only for [page:SkinnedMesh] and [page:Camera]. Default is undefined.
  • [page:Boolean physics] - Only for [page:SkinnedMesh]. A flag whether turn on physics. Default is true.
  • @@ -117,7 +129,6 @@

    [method:MMDAnimationHelper add]( [param:Object3D object], [param:Object para
  • [page:Vector3 gravity] - Only for [page:SkinnedMesh] and physics is true. Physics parameter. Default is ( 0, - 9.8 * 10, 0 ).
  • [page:Number delayTime] - Only for [page:Audio]. Default is 0.0.
-

Add an [page:SkinnedMesh], [page:Camera], or [page:Audio] to helper and setup animation. The anmation durations of added objects are synched. If camera/audio has already been added, it'll be replaced with a new one. @@ -137,12 +148,12 @@

[method:MMDAnimationHelper pose]( [param:SkinnedMesh mesh], [param:Object vp [page:SkinnedMesh mesh] — [page:SkinnedMesh] which changes the posing. It doesn't need to be added to helper.
[page:Object vpd] — VPD content obtained by [page:MMDLoader].loadVPD
[page:Object params] — (optional)
+

  • [page:Boolean resetPose] - Default is true.
  • [page:Boolean ik] - Default is true.
  • [page:Boolean grant] - Default is true.
-

Changes the posing of [page:SkinnedMesh] as VPD content specifies.

diff --git a/docs/examples/en/animations/MMDPhysics.html b/docs/examples/en/animations/MMDPhysics.html index 148256b5c5c937..ffb78be3173175 100644 --- a/docs/examples/en/animations/MMDPhysics.html +++ b/docs/examples/en/animations/MMDPhysics.html @@ -13,6 +13,17 @@

[name]

[name] calculates Physics for model loaded by [page:MMDLoader] with [link:https://github.com/kripken/ammo.js/ ammo.js] (Bullet-based JavaScript Physics engine).

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { MMDPhysics } from 'three/addons/animation/MMDPhysics.js'; + +

Code Example

@@ -54,12 +65,12 @@

[name]( [param:SkinnedMesh mesh], [param:Array rigidBodyParams], [param:Arra [page:Array rigidBodyParams] — An array of [page:Object] specifying Rigid Body parameters.
[page:Array constraintParams] — (optional) An array of [page:Object] specifying Constraint parameters.
[page:Object params] — (optional)
+

  • [page:Number unitStep] - Default is 1 / 65.
  • [page:Integer maxStepNum] - Default is 3.
  • [page:Vector3 gravity] - Default is ( 0, - 9.8 * 10, 0 )
-

Creates a new [name].

diff --git a/docs/examples/en/controls/ArcballControls.html b/docs/examples/en/controls/ArcballControls.html index 8e7a65fdf9a7c7..9565896556b0d7 100644 --- a/docs/examples/en/controls/ArcballControls.html +++ b/docs/examples/en/controls/ArcballControls.html @@ -31,9 +31,19 @@

[name]

To use this, as with all files in the /examples directory, you will have to include the file separately in your HTML. +

+ +

Import

+

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons].

+ + import { ArcballControls } from 'three/addons/controls/ArcballControls.js'; + +

Code Example

diff --git a/docs/examples/en/controls/DragControls.html b/docs/examples/en/controls/DragControls.html index 073e21a2945996..71a1ce7cce2e3c 100644 --- a/docs/examples/en/controls/DragControls.html +++ b/docs/examples/en/controls/DragControls.html @@ -12,9 +12,20 @@

[name]

- This class can be used to provide a drag'n'drop interaction. + This class can be used to provide a drag'n'drop interaction.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { DragControls } from 'three/addons/controls/DragControls.js'; + +

Code Example

@@ -42,7 +53,6 @@

Examples

Constructor

[name]( [param:Array objects], [param:Camera camera], [param:HTMLDOMElement domElement] )

-

[page:Array objects]: An array of draggable 3D objects.

@@ -55,7 +65,6 @@

[name]( [param:Array objects], [param:Camera camera], [param:HTMLDOMElement

Creates a new instance of [name].

-

Events

diff --git a/docs/examples/en/controls/FirstPersonControls.html b/docs/examples/en/controls/FirstPersonControls.html index f2b01b6409f0b2..580cb786eecf9b 100644 --- a/docs/examples/en/controls/FirstPersonControls.html +++ b/docs/examples/en/controls/FirstPersonControls.html @@ -14,6 +14,17 @@

[name]

This class is an alternative implementation of [page:FlyControls].

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js'; + +

Examples

[example:webgl_geometry_terrain webgl / geometry / terrain ]

@@ -21,7 +32,7 @@

Examples

Constructor

[name]( [param:Camera object], [param:HTMLDOMElement domElement] )

-

+

[page:Camera object]: The camera to be controlled.

@@ -31,7 +42,7 @@

[name]( [param:Camera object], [param:HTMLDOMElement domElement] )

Creates a new instance of [name].

-

+

Properties

diff --git a/docs/examples/en/controls/FlyControls.html b/docs/examples/en/controls/FlyControls.html index 1a096fcd66e89a..952b6b84618f60 100644 --- a/docs/examples/en/controls/FlyControls.html +++ b/docs/examples/en/controls/FlyControls.html @@ -15,6 +15,17 @@

[name]

3D space without any limitations (e.g. focus on a specific target).

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { FlyControls } from 'three/addons/controls/FlyControls.js'; + +

Examples

[example:misc_controls_fly misc / controls / fly ]

@@ -22,7 +33,7 @@

Examples

Constructor

[name]( [param:Camera object], [param:HTMLDOMElement domElement] )

-

+

[page:Camera object]: The camera to be controlled.

@@ -32,7 +43,7 @@

[name]( [param:Camera object], [param:HTMLDOMElement domElement] )

Creates a new instance of [name].

-

+

Events

diff --git a/docs/examples/en/controls/MapControls.html b/docs/examples/en/controls/MapControls.html new file mode 100644 index 00000000000000..447dda488219be --- /dev/null +++ b/docs/examples/en/controls/MapControls.html @@ -0,0 +1,119 @@ + + + + + + + + + + [page:OrbitControls] → + +

[name]

+ +

+ [name] is intended for transforming a camera over a map from bird's eye perspective. + The class shares its implementation with [page:OrbitControls] but uses a specific preset for mouse/touch interaction and disables screen space panning by default. +

+ +

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { MapControls } from 'three/addons/controls/MapControls.js'; + + +

Code Example

+ + + const renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); + + const scene = new THREE.Scene(); + + const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 20, 100 ); + + const controls = new MapControls( camera, renderer.domElement ); + controls.enableDamping = true; + + function animate() { + + requestAnimationFrame( animate ); + + // required if controls.enableDamping or controls.autoRotate are set to true + controls.update(); + + renderer.render( scene, camera ); + + } + + +

Examples

+ +

[example:misc_controls_map misc / controls / map ]

+ +

Constructor

+ +

[name]( [param:Camera object], [param:HTMLDOMElement domElement] )

+

+ [page:Camera object]: (required) The camera to be controlled. The camera must not be a child of another object, unless that object is the scene itself.

+ + [page:HTMLDOMElement domElement]: The HTML element used for event listeners. +

+ +

Events

+ +

See the base [page:OrbitControls] class for common events.

+ +

Properties

+ +

See the base [page:OrbitControls] class for common properties.

+ +

+ [property:Object mouseButtons]

+

+ This object contains references to the mouse actions used by the controls. + +controls.mouseButtons = { + LEFT: THREE.MOUSE.PAN, + MIDDLE: THREE.MOUSE.DOLLY, + RIGHT: THREE.MOUSE.ROTATE +} + +

+ +

[property:Boolean screenSpacePanning]

+

+ Defines how the camera's position is translated when panning. If true, the camera pans in screen space. + Otherwise, the camera pans in the plane orthogonal to the camera's up direction. + Default is `false`. +

+ +

[property:Object touches]

+

+ This object contains references to the touch actions used by the controls. + +controls.touches = { + ONE: THREE.TOUCH.PAN, + TWO: THREE.TOUCH.DOLLY_ROTATE +} + +

+ +

Methods

+ +

See the base [page:OrbitControls] class for common methods.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/MapControls.js examples/jsm/controls/MapControls.js] +

+ + diff --git a/docs/examples/en/controls/OrbitControls.html b/docs/examples/en/controls/OrbitControls.html index c7429566a84a04..b8f38209c9be5e 100644 --- a/docs/examples/en/controls/OrbitControls.html +++ b/docs/examples/en/controls/OrbitControls.html @@ -10,13 +10,23 @@

[name]

- Orbit controls allow the camera to orbit around a target.
+ Orbit controls allow the camera to orbit around a target.
- To use this, as with all files in the /examples directory, you will have to - include the file separately in your HTML. + To use this, as with all files in the /examples directory, you will have to + include the file separately in your HTML. +

+ +

Import

+

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons].

+ + import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; + +

Code Example

@@ -228,7 +238,7 @@

[property:Boolean screenSpacePanning]

Defines how the camera's position is translated when panning. If true, the camera pans in screen space. Otherwise, the camera pans in the plane orthogonal to the camera's up direction. - Default is true for OrbitControls; false for MapControls. + Default is `true`.

[property:Vector3 target0]

@@ -302,6 +312,11 @@

[method:undefined saveState] ()

Save the current state of the controls. This can later be recovered with [page:.reset].

+

[method:undefined stopListenToKeyEvents] ()

+

+ Removes the key event listener previously defined with [page:.listenToKeyEvents](). +

+

[method:Boolean update] ()

Update the controls. Must be called after any manual changes to the camera's transform, diff --git a/docs/examples/en/controls/PointerLockControls.html b/docs/examples/en/controls/PointerLockControls.html index 5b2698292b76f9..29265de39a5a4d 100644 --- a/docs/examples/en/controls/PointerLockControls.html +++ b/docs/examples/en/controls/PointerLockControls.html @@ -12,10 +12,21 @@

[name]

- The implementation of this class is based on the [link:https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API Pointer Lock API]. - [name] is a perfect choice for first person 3D games. + The implementation of this class is based on the [link:https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API Pointer Lock API]. + [name] is a perfect choice for first person 3D games.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js'; + +

Code Example

@@ -43,7 +54,7 @@

Examples

Constructor

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

-

+

[page:Camera camera]: The camera of the rendered scene.

@@ -53,7 +64,7 @@

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

Creates a new instance of [name].

-

+

Events

diff --git a/docs/examples/en/controls/TrackballControls.html b/docs/examples/en/controls/TrackballControls.html index 3ecbfbc98f1c07..ed2fd22311620f 100644 --- a/docs/examples/en/controls/TrackballControls.html +++ b/docs/examples/en/controls/TrackballControls.html @@ -12,12 +12,23 @@

[name]

-

+ [name] is similar to [page:OrbitControls]. However, it does not maintain a constant camera [page:Object3D.up up] vector. That means if the camera orbits over the “north” and “south” poles, it does not flip to stay "right side up". -

+ +

+ +

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons].

+ + import { TrackballControls } from 'three/addons/controls/TrackballControls.js'; + +

Examples

[example:misc_controls_trackball misc / controls / trackball ]

@@ -25,7 +36,7 @@

Examples

Constructor

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

-

+

[page:Camera camera]: The camera of the rendered scene.

@@ -35,7 +46,7 @@

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

Creates a new instance of [name].

-

+

Events

@@ -73,7 +84,7 @@

[property:Boolean enabled]

[property:Array keys]

-

+ This array holds keycodes for controlling interactions.

  • When the first defined key is pressed, all mouse interactions (left, middle, right) performs orbiting.
  • @@ -81,28 +92,38 @@

    [property:Array keys]

  • When the third defined key is pressed, all mouse interactions (left, middle, right) performs panning.
Default is *KeyA, KeyS, KeyD* which represents A, S, D. -

+

[property:Number maxDistance]

- How far you can zoom out. Default is `Infinity`. + How far you can dolly out ( [page:PerspectiveCamera] only ). Default is `Infinity`.

[property:Number minDistance]

- How far you can zoom in. Default is *0*. + How far you can dolly in ( [page:PerspectiveCamera] only ). Default is *0*. +

+ +

[property:Float maxZoom]

+

+ How far you can zoom out ( [page:OrthographicCamera] only ). Default is `Infinity`. +

+ +

[property:Float minZoom]

+

+ How far you can zoom in ( [page:OrthographicCamera] only ). Default is *0*.

[property:Object mouseButtons]

-

+ This object contains references to the mouse actions used by the controls.

  • .LEFT is assigned with `THREE.MOUSE.ROTATE`
  • .MIDDLE is assigned with `THREE.MOUSE.ZOOM`
  • .RIGHT is assigned with `THREE.MOUSE.PAN`
-

+

[property:Boolean noPan]

@@ -135,7 +156,7 @@

[property:Number rotateSpeed]

[property:Object screen]

-

+ Represents the properties of the screen. Automatically set when [page:.handleResize handleResize]() is called.

  • left: Represents the offset in pixels to the screen's left boundary.
  • @@ -143,7 +164,7 @@

    [property:Object screen]

  • width: Represents the screen width in pixels.
  • height: Represents the screen height in pixels.
-

+

[property:Boolean staticMoving]

diff --git a/docs/examples/en/controls/TransformControls.html b/docs/examples/en/controls/TransformControls.html index 1a030425199404..334ca36614f04c 100644 --- a/docs/examples/en/controls/TransformControls.html +++ b/docs/examples/en/controls/TransformControls.html @@ -18,6 +18,17 @@

[name]

[name] expects that its attached 3D object is part of the scene graph.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { TransformControls } from 'three/addons/controls/TransformControls.js'; + +

Examples

[example:misc_controls_transform misc / controls / transform ]

@@ -25,7 +36,7 @@

Examples

Constructor

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

-

+

[page:Camera camera]: The camera of the rendered scene.

@@ -35,7 +46,7 @@

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

Creates a new instance of [name].

-

+

Events

diff --git a/docs/examples/en/exporters/ColladaExporter.html b/docs/examples/en/exporters/ColladaExporter.html index 6cc323cda2dc46..e64279dfd388fa 100644 --- a/docs/examples/en/exporters/ColladaExporter.html +++ b/docs/examples/en/exporters/ColladaExporter.html @@ -17,6 +17,17 @@

[name]

This exporter only supports exporting geometry, materials, textures, and scene hierarchy.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { ColladaExporter } from 'three/addons/exporters/ColladaExporter.js'; + +

Code Example

@@ -44,6 +55,7 @@

[method:Object parse]( [param:Object3D input], [param:Function onCompleted], [page:Object input] — Object3D to be exported
[page:Function onCompleted] — Will be called when the export completes. Optional. The same data is immediately returned from the function.
[page:Options options] — Export options
+

  • version - string. Which version of Collada to export. The options are "1.4.1" or "1.5.0". Defaults to "1.4.1".
  • author - string. The name to include in the author field. Author field is excluded by default.
  • @@ -52,7 +64,6 @@

    [method:Object parse]( [param:Object3D input], [param:Function onCompleted],
  • unitName - string. Name of the unit. Can be any string, but could be for example "meter", "inch", or "parsec".
  • unitMeter - number. Length of the unit in meters.
-

Generates an object with Collada file and texture data. This object is returned from the function and passed into the "onCompleted" callback. diff --git a/docs/examples/en/exporters/DRACOExporter.html b/docs/examples/en/exporters/DRACOExporter.html index 60c15a554b1b83..39b8545d97b910 100644 --- a/docs/examples/en/exporters/DRACOExporter.html +++ b/docs/examples/en/exporters/DRACOExporter.html @@ -24,6 +24,17 @@

[name]

using [link:https://github.com/AnalyticalGraphicsInc/gltf-pipeline glTF-Pipeline].

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { DRACOExporter } from 'three/addons/exporters/DRACOExporter.js'; + +

Code Example

diff --git a/docs/examples/en/exporters/EXRExporter.html b/docs/examples/en/exporters/EXRExporter.html index cf8f90e2f83769..fba1be4c981a52 100644 --- a/docs/examples/en/exporters/EXRExporter.html +++ b/docs/examples/en/exporters/EXRExporter.html @@ -21,6 +21,17 @@

[name]

and DI.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { EXRExporter } from 'three/addons/exporters/EXRExporter.js'; + +

Code Example

diff --git a/docs/examples/en/exporters/GLTFExporter.html b/docs/examples/en/exporters/GLTFExporter.html index f343e909c3c61b..a4fd41627a3e13 100644 --- a/docs/examples/en/exporters/GLTFExporter.html +++ b/docs/examples/en/exporters/GLTFExporter.html @@ -20,6 +20,17 @@

[name]

textures, skins, skeletons, morph targets, animations, lights, and/or cameras.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js'; + +

Extensions

diff --git a/docs/examples/en/exporters/OBJExporter.html b/docs/examples/en/exporters/OBJExporter.html index 441466cbb7a818..d4d11713d84cce 100644 --- a/docs/examples/en/exporters/OBJExporter.html +++ b/docs/examples/en/exporters/OBJExporter.html @@ -10,12 +10,22 @@

[name]

- An exporter for the [link:https://en.wikipedia.org/wiki/Wavefront_.obj_file OBJ] file format. + An exporter for the [link:https://en.wikipedia.org/wiki/Wavefront_.obj_file OBJ] file format. +

+ [name] is not able to export material data into MTL files so only geometry data are supported.

-

- [name] is not able to export material data into MTL files so only geometry data are supported. + +

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons].

+ + import { OBJExporter } from 'three/addons/exporters/OBJExporter.js'; + +

Code Example

diff --git a/docs/examples/en/exporters/PLYExporter.html b/docs/examples/en/exporters/PLYExporter.html index e06d08497b8895..c70b8d3c64bb7f 100644 --- a/docs/examples/en/exporters/PLYExporter.html +++ b/docs/examples/en/exporters/PLYExporter.html @@ -18,6 +18,17 @@

[name]

uv coordinates. No textures or texture references are saved.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { PLYExporter } from 'three/addons/exporters/PLYExporter.js'; + +

Code Example

diff --git a/docs/examples/en/exporters/STLExporter.html b/docs/examples/en/exporters/STLExporter.html index 0ac6ef38dc43fb..fde8f506b6763c 100644 --- a/docs/examples/en/exporters/STLExporter.html +++ b/docs/examples/en/exporters/STLExporter.html @@ -17,6 +17,17 @@

[name]

STL files contain no scale information or indexes, and the units are arbitrary.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { STLExporter } from 'three/addons/exporters/STLExporter.js'; + +

Code Example

diff --git a/docs/examples/en/geometries/ConvexGeometry.html b/docs/examples/en/geometries/ConvexGeometry.html index c1d953d1139cca..ddbbd0d087fa71 100644 --- a/docs/examples/en/geometries/ConvexGeometry.html +++ b/docs/examples/en/geometries/ConvexGeometry.html @@ -11,8 +11,21 @@

[name]

-

[name] can be used to generate a convex hull for a given array of 3D points. - The average time complexity for this task is considered to be O(nlog(n)).

+

+ [name] can be used to generate a convex hull for a given array of 3D points. + The average time complexity for this task is considered to be O(nlog(n)). +

+ +

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { ConvexGeometry } from 'three/addons/geometries/ConvexGeometry.js'; +

Code Example

diff --git a/docs/examples/en/geometries/DecalGeometry.html b/docs/examples/en/geometries/DecalGeometry.html index 5b3b9245bc4574..f0630acba33e6d 100644 --- a/docs/examples/en/geometries/DecalGeometry.html +++ b/docs/examples/en/geometries/DecalGeometry.html @@ -11,7 +11,21 @@

[name]

-

[name] can be used to create a decal mesh that serves different kinds of purposes e.g. adding unique details to models, performing dynamic visual environmental changes or covering seams.

+

+ [name] can be used to create a decal mesh that serves different kinds of purposes e.g. adding unique details + to models, performing dynamic visual environmental changes or covering seams. +

+ +

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { DecalGeometry } from 'three/addons/geometries/DecalGeometry.js'; +

Code Example

diff --git a/docs/examples/en/geometries/ParametricGeometry.html b/docs/examples/en/geometries/ParametricGeometry.html index 53bf11a2b15c8d..e4b5f56fe1e72d 100644 --- a/docs/examples/en/geometries/ParametricGeometry.html +++ b/docs/examples/en/geometries/ParametricGeometry.html @@ -11,23 +11,20 @@

[name]

-

Generate geometry representing a parametric surface.

- - + + import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js'; +

Code Example

diff --git a/docs/examples/en/geometries/TextGeometry.html b/docs/examples/en/geometries/TextGeometry.html index ace3d2a2b26ff9..c4eb6c29b6ba8b 100644 --- a/docs/examples/en/geometries/TextGeometry.html +++ b/docs/examples/en/geometries/TextGeometry.html @@ -17,21 +17,16 @@

[name]

See the [page:FontLoader] page for additional details.

- + + import { TextGeometry } from 'three/addons/geometries/TextGeometry.js'; +

Code Example

diff --git a/docs/examples/en/helpers/LightProbeHelper.html b/docs/examples/en/helpers/LightProbeHelper.html index 328e5cbd3059a0..8fdb088ea62f40 100644 --- a/docs/examples/en/helpers/LightProbeHelper.html +++ b/docs/examples/en/helpers/LightProbeHelper.html @@ -15,6 +15,17 @@

[name]

Renders a sphere to visualize a light probe in the scene.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { LightProbeHelper } from 'three/addons/helpers/LightProbeHelper.js'; + +

Code Example

diff --git a/docs/examples/en/helpers/PositionalAudioHelper.html b/docs/examples/en/helpers/PositionalAudioHelper.html index abc75a9d7ce7fe..b5bb4b570d2bf5 100644 --- a/docs/examples/en/helpers/PositionalAudioHelper.html +++ b/docs/examples/en/helpers/PositionalAudioHelper.html @@ -13,6 +13,17 @@

[name]

This helper displays the directional cone of a [page:PositionalAudio].

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { PositionalAudioHelper } from 'three/addons/helpers/PositionalAudioHelper.js'; + +

Code Example

const positionalAudio = new THREE.PositionalAudio( listener ); diff --git a/docs/examples/en/helpers/RectAreaLightHelper.html b/docs/examples/en/helpers/RectAreaLightHelper.html index 096fd880ae9e7e..778599fae114ac 100644 --- a/docs/examples/en/helpers/RectAreaLightHelper.html +++ b/docs/examples/en/helpers/RectAreaLightHelper.html @@ -15,6 +15,17 @@

[name]

Creates a visual aid for a [page:RectAreaLight].

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js'; + +

Code Example

diff --git a/docs/examples/en/helpers/VertexNormalsHelper.html b/docs/examples/en/helpers/VertexNormalsHelper.html index e8c9fe2732e3ce..4ea3f082d9c6e6 100644 --- a/docs/examples/en/helpers/VertexNormalsHelper.html +++ b/docs/examples/en/helpers/VertexNormalsHelper.html @@ -17,6 +17,17 @@

[name]

have been calculated using [page:BufferGeometry.computeVertexNormals computeVertexNormals].

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { VertexNormalsHelper } from 'three/addons/helpers/VertexNormalsHelper.js'; + +

Code Example

diff --git a/docs/examples/en/helpers/VertexTangentsHelper.html b/docs/examples/en/helpers/VertexTangentsHelper.html index 21b38592573047..3c99ce3ef531da 100644 --- a/docs/examples/en/helpers/VertexTangentsHelper.html +++ b/docs/examples/en/helpers/VertexTangentsHelper.html @@ -17,6 +17,17 @@

[name]

have been calculated using [page:BufferGeometry.computeTangents computeTangents].

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { VertexTangentsHelper } from 'three/addons/helpers/VertexTangentsHelper.js'; + +

Code Example

diff --git a/docs/examples/en/lights/LightProbeGenerator.html b/docs/examples/en/lights/LightProbeGenerator.html index dbe74f01710355..5f0f5ce4dc025b 100644 --- a/docs/examples/en/lights/LightProbeGenerator.html +++ b/docs/examples/en/lights/LightProbeGenerator.html @@ -14,6 +14,17 @@

[name]

Utility class for creating instances of [page:LightProbe].

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { LightProbeGenerator } from 'three/addons/lights/LightProbeGenerator.js'; + +

Examples

diff --git a/docs/examples/en/loaders/3DMLoader.html b/docs/examples/en/loaders/3DMLoader.html index ef38f63083c2b4..5661da3e5725f0 100644 --- a/docs/examples/en/loaders/3DMLoader.html +++ b/docs/examples/en/loaders/3DMLoader.html @@ -17,6 +17,17 @@

[name]

The loader currently uses [link:https://www.npmjs.com/package/rhino3dm/v/0.15.0-beta rhino3dm.js 0.15.0-beta.]

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { Rhino3dmLoader } from 'three/addons/loaders/3DMLoader.js'; + +

Supported Conversions

@@ -110,7 +121,7 @@

Code Example

// Specify path to a folder containing WASM/JS libraries or a CDN. //loader.setLibraryPath( '/path_to_library/rhino3dm/' ); - loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@0.15.0-beta/' ); + loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@7.15.0/' ); // Load a 3DM file loader.load( @@ -184,13 +195,13 @@

[method:undefined parse]( [param:ArrayBuffer buffer], [param:Function onLoad

- import rhino3dm from 'https://cdn.jsdelivr.net/npm/rhino3dm@0.15.0-beta/rhino3dm.module.js' + import rhino3dm from 'https://cdn.jsdelivr.net/npm/rhino3dm@7.15.0/rhino3dm.module.js' // Instantiate a loader const loader = new Rhino3dmLoader(); // Specify path to a folder containing WASM/JS libraries or a CDN. - loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@0.15.0-beta/' ); + loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@7.15.0/' ); rhino3dm().then(async m => { @@ -227,7 +238,7 @@

[method:this setLibraryPath]( [param:String value] )

// Specify path to a folder containing the WASM/JS library: loader.setLibraryPath( '/path_to_library/rhino3dm/' ); // or from a CDN: - loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@0.15.0-beta/' ); + loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@7.15.0/' );

[method:this setWorkerLimit]( [param:Number workerLimit] )

diff --git a/docs/examples/en/loaders/DRACOLoader.html b/docs/examples/en/loaders/DRACOLoader.html index 0b29dbeccccf96..f68ceee641098b 100644 --- a/docs/examples/en/loaders/DRACOLoader.html +++ b/docs/examples/en/loaders/DRACOLoader.html @@ -31,6 +31,17 @@

[name]

decoder instances.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'; + +

Code Example

diff --git a/docs/examples/en/loaders/FontLoader.html b/docs/examples/en/loaders/FontLoader.html index cd5dfd0287f4f0..da797aeaf2bd02 100644 --- a/docs/examples/en/loaders/FontLoader.html +++ b/docs/examples/en/loaders/FontLoader.html @@ -19,6 +19,17 @@

[name]

You can convert fonts online using [link:https://gero3.github.io/facetype.js/ facetype.js]

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { FontLoader } from 'three/addons/loaders/FontLoader.js'; + +

Code Example

diff --git a/docs/examples/en/loaders/GLTFLoader.html b/docs/examples/en/loaders/GLTFLoader.html index 3a1995d658cc74..5e276132e78aed 100644 --- a/docs/examples/en/loaders/GLTFLoader.html +++ b/docs/examples/en/loaders/GLTFLoader.html @@ -25,6 +25,17 @@

[name]

and they require special handling during the disposal process. More information in the [link:https://threejs.org/docs/#manual/en/introduction/How-to-dispose-of-objects How to dispose of objects] guide.

+

Import

+ +

+ [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; + +

Extensions

@@ -44,7 +55,7 @@

Extensions

  • KHR_mesh_quantization
  • KHR_lights_punctual1
  • KHR_texture_basisu
  • -
  • KHR_texture_transform2
  • +
  • KHR_texture_transform
  • EXT_texture_webp
  • EXT_meshopt_compression
  • EXT_mesh_gpu_instancing
  • @@ -55,24 +66,16 @@

    Extensions

      -
    • [link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]3
    • +
    • [link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]2
    • [link:https://github.com/takahirox/three-gltf-extensions MSFT_texture_dds]

    - 1Requires [link:https://threejs.org/docs/#api/en/renderers/WebGLRenderer.physicallyCorrectLights physicallyCorrectLights] to be enabled. -

    -

    - 2UV transforms are supported, with several key limitations. Transforms applied to - a texture using the first UV slot (all textures except aoMap and lightMap) must share the same - transform, or no transform at all. The aoMap and lightMap textures cannot be transformed. No - more than one transform may be used per material. See - #[link:https://github.com/mrdoob/three.js/pull/13831 13831] and - #[link:https://github.com/mrdoob/three.js/issues/12788 12788]. + 1Requires [link:https://threejs.org/docs/#api/en/renderers/WebGLRenderer.useLegacyLights useLegacyLights] to be disabled.

    - 3You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example]. + 2You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example].

    Code Example

    @@ -132,7 +135,7 @@

    Textures

    in linear colorspace, always configure [page:WebGLRenderer] as follows when using glTF:

    - renderer.outputEncoding = THREE.sRGBEncoding; + renderer.outputColorSpace = THREE.SRGBColorSpace;

    GLTFLoader will automatically configure textures referenced from a .gltf or .glb file correctly, with the @@ -141,7 +144,7 @@

    Textures

    // If texture is used for color information, set colorspace. - texture.encoding = THREE.sRGBEncoding; + texture.colorSpace = THREE.SRGBColorSpace; // UVs use the convention that (0, 0) corresponds to the upper left corner of a texture. texture.flipY = false; diff --git a/docs/examples/en/loaders/KTX2Loader.html b/docs/examples/en/loaders/KTX2Loader.html index 4db6185de96970..f15530cc58cf02 100644 --- a/docs/examples/en/loaders/KTX2Loader.html +++ b/docs/examples/en/loaders/KTX2Loader.html @@ -27,6 +27,17 @@

    [name]

    directory.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js'; + +

    Code Example

    diff --git a/docs/examples/en/loaders/LDrawLoader.html b/docs/examples/en/loaders/LDrawLoader.html index a7132bcf4a430f..00fd9c22e17902 100644 --- a/docs/examples/en/loaders/LDrawLoader.html +++ b/docs/examples/en/loaders/LDrawLoader.html @@ -29,6 +29,16 @@

    [name]

    See section 'Packing LDraw models'. The LDrawLoader example loads several packed files. The official parts library is not included due to its large size.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { LDrawLoader } from 'three/addons/loaders/LDrawLoader.js'; +

    Extensions

    diff --git a/docs/examples/en/loaders/MMDLoader.html b/docs/examples/en/loaders/MMDLoader.html index 7458af24639579..89b5c416a7ad10 100644 --- a/docs/examples/en/loaders/MMDLoader.html +++ b/docs/examples/en/loaders/MMDLoader.html @@ -15,7 +15,18 @@

    [name]

    [name] creates Three.js Objects from MMD resources as PMD, PMX, VMD, and VPD files. See [page:MMDAnimationHelper] for MMD animation handling as IK, Grant, and Physics.

    - If you want raw content of MMD resources, use .loadPMD/PMX/VMD/VPD methods. + If you want raw content of MMD resources, use .loadPMD/PMX/VMD/VPD methods.

    + +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { MMDLoader } from 'three/addons/loaders/MMDLoader.js'; +

    Code Example

    diff --git a/docs/examples/en/loaders/MTLLoader.html b/docs/examples/en/loaders/MTLLoader.html index 4cc1c29a1b13c6..cb4e18ebd0a419 100644 --- a/docs/examples/en/loaders/MTLLoader.html +++ b/docs/examples/en/loaders/MTLLoader.html @@ -16,6 +16,17 @@

    [name]

    (material) properties of objects within one or more .OBJ files.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { MTLLoader } from 'three/addons/loaders/MTLLoader.js'; + +

    Constructor

    [name]( [param:LoadingManager loadingManager] )

    diff --git a/docs/examples/en/loaders/OBJLoader.html b/docs/examples/en/loaders/OBJLoader.html index 626828a3b5ac6f..f17952c4a50812 100644 --- a/docs/examples/en/loaders/OBJLoader.html +++ b/docs/examples/en/loaders/OBJLoader.html @@ -18,6 +18,17 @@

    [name]

    vertices, and texture vertices.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { OBJLoader } from 'three/addons/loaders/OBJLoader.js'; + +

    Code Example

    diff --git a/docs/examples/en/loaders/PCDLoader.html b/docs/examples/en/loaders/PCDLoader.html index 9b1eb3eb7493bb..2161564bef8ccd 100644 --- a/docs/examples/en/loaders/PCDLoader.html +++ b/docs/examples/en/loaders/PCDLoader.html @@ -22,6 +22,17 @@

    [name]

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { PCDLoader } from 'three/addons/loaders/PCDLoader.js'; + +

    Code Example

    diff --git a/docs/examples/en/loaders/PDBLoader.html b/docs/examples/en/loaders/PDBLoader.html index 4d38e2dd635ea6..906fdc1fcc2625 100644 --- a/docs/examples/en/loaders/PDBLoader.html +++ b/docs/examples/en/loaders/PDBLoader.html @@ -15,6 +15,17 @@

    [name]

    The [link:http://en.wikipedia.org/wiki/Protein_Data_Bank_(file_format) Protein Data Bank] file format is a textual file describing the three-dimensional structures of molecules.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { PDBLoader } from 'three/addons/loaders/PDBLoader.js'; + +

    Code Example

    diff --git a/docs/examples/en/loaders/PRWMLoader.html b/docs/examples/en/loaders/PRWMLoader.html deleted file mode 100644 index dbdd39e19083a8..00000000000000 --- a/docs/examples/en/loaders/PRWMLoader.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - [page:Loader] → - -

    [name]

    - -

    A loader for loading a `.prwm` resource.
    - Packed Raw WebGL Model is an open-source binary file format for nD geometries specifically designed for - JavaScript and WebGL with a strong focus on fast parsing (from 1ms to 0.1ms in Chrome 59 - on a MBP Late 2013). The parsing of PRWM file is especially fast when the endianness of the file is - the same as the endianness of the client platform. More information - on this [link:https://github.com/kchapelier/PRWM here]. -

    - -

    Code Example

    - - - // instantiate a loader - const loader = new PRWMLoader(); - - // load a resource - loader.load( - // resource URL - 'models/nefertiti.le.prwm', - // called when resource is loaded - function ( bufferGeometry ) { - - const object = new THREE.Mesh( bufferGeometry, new THREE.MeshNormalMaterial() ); - scene.add( object ); - - }, - // called when loading is in progresses - function ( xhr ) { - - console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' ); - - }, - // called when loading has errors - function ( error ) { - - console.log( 'An error happened' ); - - } - ); - - -

    Examples

    -

    - [example:webgl_loader_prwm] -

    - -

    Constructor

    - -

    [name]( [param:LoadingManager manager] )

    -

    - [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. -

    -

    - Creates a new [name]. -

    - -

    Properties

    -

    See the base [page:Loader] class for common properties.

    - -

    Methods

    -

    See the base [page:Loader] class for common methods.

    - -

    [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

    -

    - [page:String url] — A string containing the path/URL of the `.prwm` file. Any `*` character in the URL will be automatically replaced by `le` or `be` depending on the platform endianness.
    - [page:Function onLoad] — (optional) A function to be called after the loading is successfully completed. The function receives the loaded [page:BufferGeometry] as an argument.
    - [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The function receives a XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes. If the server does not set the Content-Length header; .[page:Integer total] will be 0.
    - [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.
    -

    -

    - Begin loading from url and call onLoad with the parsed response content. -

    - -

    [method:BufferGeometry parse]( [param:ArrayBuffer arrayBuffer] )

    -

    - [page:ArrayBuffer arrayBuffer] — ArrayBuffer containing the `prwm` data. -

    -

    - Parse a `prwm` file passed as an ArrayBuffer and directly return an instance of [page:BufferGeometry]. -

    - -

    PRWMLoader.isBigEndianPlatform( )

    - -

    - Return true if the endianness of the platform is Big Endian, false otherwise. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PRWMLoader.js examples/jsm/loaders/PRWMLoader.js] -

    - - - diff --git a/docs/examples/en/loaders/SVGLoader.html b/docs/examples/en/loaders/SVGLoader.html index 53fddfdf936fa6..c99f1c8a1dbf0d 100644 --- a/docs/examples/en/loaders/SVGLoader.html +++ b/docs/examples/en/loaders/SVGLoader.html @@ -15,6 +15,17 @@

    [name]

    [link:https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Scalable Vector Graphics] is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { SVGLoader } from 'three/addons/loaders/SVGLoader.js'; + +

    Code Example

    diff --git a/docs/examples/en/loaders/TGALoader.html b/docs/examples/en/loaders/TGALoader.html index 6616f918d1f7d7..391b931e28db9d 100644 --- a/docs/examples/en/loaders/TGALoader.html +++ b/docs/examples/en/loaders/TGALoader.html @@ -15,6 +15,17 @@

    [name]

    [link:https://en.wikipedia.org/wiki/Truevision_TGA TGA] is a raster graphics, image file format.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { TGALoader } from 'three/addons/loaders/TGALoader.js'; + +

    Code Example

    diff --git a/docs/examples/en/math/Lut.html b/docs/examples/en/math/Lut.html index 37fde3527bbe0a..0f9a370cb2587c 100644 --- a/docs/examples/en/math/Lut.html +++ b/docs/examples/en/math/Lut.html @@ -10,9 +10,20 @@

    [name]

    - Represents a lookup table for colormaps. It is used to determine the color values from a range of data values. + Represents a lookup table for colormaps. It is used to determine the color values from a range of data values.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { Lut } from 'three/addons/math/Lut.js'; + +

    Code Example

    diff --git a/docs/examples/en/math/MeshSurfaceSampler.html b/docs/examples/en/math/MeshSurfaceSampler.html index 5cd6691bd062a9..ceb92ecd2d0141 100644 --- a/docs/examples/en/math/MeshSurfaceSampler.html +++ b/docs/examples/en/math/MeshSurfaceSampler.html @@ -13,6 +13,17 @@

    [name]

    Weighted sampling is useful for effects like heavier foliage growth in certain areas of terrain, or concentrated particle emissions from specific parts of a mesh. Vertex weights may be written programmatically, or painted by hand as vertex colors in 3D tools like Blender.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { MeshSurfaceSampler } from 'three/addons/math/MeshSurfaceSampler.js'; + +

    Code Example

    @@ -21,25 +32,23 @@

    Code Example

    .setWeightAttribute( 'color' ) .build(); - const sampleMesh = new THREE.InstancedMesh( sampleGeometry, sampleMaterial, 100 ); + const mesh = new THREE.InstancedMesh( sampleGeometry, sampleMaterial, 100 ); - const _position = new THREE.Vector3(); - const _matrix = new THREE.Matrix4(); + const position = new THREE.Vector3(); + const matrix = new THREE.Matrix4(); // Sample randomly from the surface, creating an instance of the sample // geometry at each sample point. for ( let i = 0; i < 100; i ++ ) { - sampler.sample( _position ); + sampler.sample( position ); - _matrix.makeTranslation( _position.x, _position.y, _position.z ); + matrix.makeTranslation( position.x, position.y, position.z ); - mesh.setMatrixAt( i, _matrix ); + mesh.setMatrixAt( i, matrix ); } - mesh.instanceMatrix.needsUpdate = true; - scene.add( mesh );
    diff --git a/docs/examples/en/math/OBB.html b/docs/examples/en/math/OBB.html index 8d99766377b4d1..0ffd648f29a1c2 100644 --- a/docs/examples/en/math/OBB.html +++ b/docs/examples/en/math/OBB.html @@ -13,6 +13,17 @@

    [name]

    Represents an oriented bounding box (OBB) in 3D space.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { OBB } from 'three/addons/math/OBB.js'; + +

    Examples

    [example:webgl_math_obb] diff --git a/docs/examples/en/math/convexhull/ConvexHull.html b/docs/examples/en/math/convexhull/ConvexHull.html index b12a88ff86a125..81c74ab0fab518 100644 --- a/docs/examples/en/math/convexhull/ConvexHull.html +++ b/docs/examples/en/math/convexhull/ConvexHull.html @@ -13,6 +13,17 @@

    [name]

    A convex hull class. Implements the Quickhull algorithm by: Dirk Gregorius. March 2014, Game Developers Conference: [link:http://media.steampowered.com/apps/valve/2014/DirkGregorius_ImplementingQuickHull.pdf Implementing QuickHull].

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { ConvexHull } from 'three/addons/math/ConvexHull.js'; + +

    Constructor

    diff --git a/docs/examples/en/math/convexhull/Face.html b/docs/examples/en/math/convexhull/Face.html index 3d95701b837f13..b82a0a22eb8a69 100644 --- a/docs/examples/en/math/convexhull/Face.html +++ b/docs/examples/en/math/convexhull/Face.html @@ -10,9 +10,21 @@

    [name]

    - Represents a section bounded by a specific amount of half-edges. The current implementation assumes that a face always consist of three edges. + Represents a section bounded by a specific amount of half-edges. The current implementation + assumes that a face always consist of three edges.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { Face } from 'three/addons/math/ConvexHull.js'; + +

    Constructor

    diff --git a/docs/examples/en/math/convexhull/HalfEdge.html b/docs/examples/en/math/convexhull/HalfEdge.html index a6e51dc75e1da1..bc76e5b36457db 100644 --- a/docs/examples/en/math/convexhull/HalfEdge.html +++ b/docs/examples/en/math/convexhull/HalfEdge.html @@ -10,9 +10,20 @@

    [name]

    - The basis for a half-edge data structure, also known as doubly connected edge list (DCEL).
    + The basis for a half-edge data structure, also known as doubly connected edge list (DCEL).

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { HalfEdge } from 'three/addons/math/ConvexHull.js'; + +

    Constructor

    diff --git a/docs/examples/en/math/convexhull/VertexList.html b/docs/examples/en/math/convexhull/VertexList.html index 0355a2e644533b..cfd565dac2a39f 100644 --- a/docs/examples/en/math/convexhull/VertexList.html +++ b/docs/examples/en/math/convexhull/VertexList.html @@ -13,6 +13,17 @@

    [name]

    A doubly linked list of vertices.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { VertexList } from 'three/addons/math/ConvexHull.js'; + +

    Constructor

    diff --git a/docs/examples/en/math/convexhull/VertexNode.html b/docs/examples/en/math/convexhull/VertexNode.html index b6bdda2b32fe5b..e6663fef8f7e1e 100644 --- a/docs/examples/en/math/convexhull/VertexNode.html +++ b/docs/examples/en/math/convexhull/VertexNode.html @@ -13,6 +13,17 @@

    [name]

    A vertex as a double linked list node.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { VertexNode } from 'three/addons/math/ConvexHull.js'; + +

    Constructor

    diff --git a/docs/examples/en/objects/Lensflare.html b/docs/examples/en/objects/Lensflare.html index e78650bee6cee7..c0ccfbbdb50caf 100644 --- a/docs/examples/en/objects/Lensflare.html +++ b/docs/examples/en/objects/Lensflare.html @@ -15,6 +15,17 @@

    [name]

    Creates a simulated lens flare that tracks a light. [name] can only be used when setting the `alpha` context parameter of [page:WebGLRenderer] to `true`.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { Lensflare } from 'three/addons/objects/Lensflare.js'; + +

    Code Example

    diff --git a/docs/examples/en/postprocessing/EffectComposer.html b/docs/examples/en/postprocessing/EffectComposer.html index db89c9451d3b6d..609eaff26debc5 100644 --- a/docs/examples/en/postprocessing/EffectComposer.html +++ b/docs/examples/en/postprocessing/EffectComposer.html @@ -16,6 +16,17 @@

    [name]

    The last pass is automatically rendered to screen.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; + +

    Examples

    diff --git a/docs/examples/en/renderers/CSS2DRenderer.html b/docs/examples/en/renderers/CSS2DRenderer.html index a3a1db3bfcc999..631abd882d6dd5 100644 --- a/docs/examples/en/renderers/CSS2DRenderer.html +++ b/docs/examples/en/renderers/CSS2DRenderer.html @@ -10,9 +10,21 @@

    [name]

    [name] is a simplified version of [page:CSS3DRenderer]. The only transformation that is supported is translation.

    - The renderer is very useful if you want to combine HTML based labels with 3D objects. Here too, the respective DOM elements are wrapped into an instance of `CSS2DObject` and added to the scene graph.
    + The renderer is very useful if you want to combine HTML based labels with 3D objects. Here too, the respective DOM elements are wrapped into an instance of `CSS2DObject` and added to the scene graph.

    + `[name]` only supports 100% browser and display zoom.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js'; + +

    Examples

    diff --git a/docs/examples/en/renderers/CSS3DRenderer.html b/docs/examples/en/renderers/CSS3DRenderer.html index 04aaf57216ef9e..ad3baee5d5575e 100644 --- a/docs/examples/en/renderers/CSS3DRenderer.html +++ b/docs/examples/en/renderers/CSS3DRenderer.html @@ -18,10 +18,22 @@

    [name]

    • It's not possible to use the material system of *three.js*.
    • It's also not possible to use geometries.
    • +
    • `[name]` only supports 100% browser and display zoom.
    So `[name]` is just focused on ordinary DOM elements. These elements are wrapped into special objects (`CSS3DObject` or `CSS3DSprite`) and then added to the scene graph.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { CSS3DRenderer } from 'three/addons/renderers/CSS3DRenderer.js'; + +

    Examples

    diff --git a/docs/examples/en/renderers/SVGRenderer.html b/docs/examples/en/renderers/SVGRenderer.html index 17eb1e82d76ee1..a030a4974f59bb 100644 --- a/docs/examples/en/renderers/SVGRenderer.html +++ b/docs/examples/en/renderers/SVGRenderer.html @@ -33,6 +33,17 @@

    [name]

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { SVGRenderer } from 'three/addons/renderers/SVGRenderer.js'; + +

    Examples

    diff --git a/docs/examples/en/utils/BufferGeometryUtils.html b/docs/examples/en/utils/BufferGeometryUtils.html index 08af0f8e6d1b54..1b4fe1f4f83fa5 100644 --- a/docs/examples/en/utils/BufferGeometryUtils.html +++ b/docs/examples/en/utils/BufferGeometryUtils.html @@ -10,9 +10,19 @@

    [name]

    - A class containing utility functions for [page:BufferGeometry BufferGeometry] instances. + A class containing utility functions for [page:BufferGeometry BufferGeometry] instances.

    +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js'; +

    Methods

    @@ -74,7 +84,7 @@

    [method:InterleavedBufferAttribute interleaveAttributes]( [param:Array attri

    -

    [method:BufferAttribute mergeBufferAttributes]( [param:Array attributes] )

    +

    [method:BufferAttribute mergeAttributes]( [param:Array attributes] )

    attributes -- Array of [page:BufferAttribute BufferAttribute] instances.

    @@ -84,7 +94,7 @@

    [method:BufferAttribute mergeBufferAttributes]( [param:Array attributes] ) -

    [method:BufferGeometry mergeBufferGeometries]( [param:Array geometries], [param:Boolean useGroups] )

    +

    [method:BufferGeometry mergeGeometries]( [param:Array geometries], [param:Boolean useGroups] )

    geometries -- Array of [page:BufferGeometry BufferGeometry] instances.
    useGroups -- Whether groups should be generated for the merged geometry or not.

    diff --git a/docs/examples/en/utils/CameraUtils.html b/docs/examples/en/utils/CameraUtils.html index ebcbe0dae6e614..5d2876df7c98e4 100644 --- a/docs/examples/en/utils/CameraUtils.html +++ b/docs/examples/en/utils/CameraUtils.html @@ -9,8 +9,20 @@

    [name]

    -

    A class containing useful utility functions for camera manipulation.

    +

    + A class containing useful utility functions for camera manipulation. +

    + +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + import { CameraUtils } from 'three/addons/utils/CameraUtils.js'; +

    Methods

    diff --git a/docs/examples/en/utils/SceneUtils.html b/docs/examples/en/utils/SceneUtils.html index 6a46df2bcf7878..3ad2e2174a29c4 100644 --- a/docs/examples/en/utils/SceneUtils.html +++ b/docs/examples/en/utils/SceneUtils.html @@ -9,8 +9,20 @@

    [name]

    -

    A class containing useful utility functions for scene manipulation.

    +

    + A class containing useful utility functions for scene manipulation. +

    + +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + import { SceneUtils } from 'three/addons/utils/SceneUtils.js'; +

    Methods

    diff --git a/docs/examples/en/utils/SkeletonUtils.html b/docs/examples/en/utils/SkeletonUtils.html index 879cc51d932d05..6694df6fde48c5 100644 --- a/docs/examples/en/utils/SkeletonUtils.html +++ b/docs/examples/en/utils/SkeletonUtils.html @@ -9,8 +9,20 @@

    [name]

    -

    Utility functions for [page:Skeleton], [page:SkinnedMesh], and [page:Bone] manipulation.

    +

    + Utility functions for [page:Skeleton], [page:SkinnedMesh], and [page:Bone] manipulation. +

    + +

    Import

    + +

    + [name] is an add-on, and must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js'; +

    Methods

    @@ -22,30 +34,6 @@

    [method:Object3D clone]( [param:Object3D object] )

    reference.

    -

    [method:Object findBoneTrackData]( [param:String name], [param:Array tracks] )

    -

    - -

    [method:Bone getBoneByName]( [param:String name], [param:Skeleton skeleton] )

    -

    - -

    [method:Array getBones]( [param:Skeleton skeleton] )

    -

    - -

    [method:Array getEqualsBonesNames]( [param:Skeleton skeleton], [param:Skeleton targetSkeleton] )

    -

    - -

    [method:SkeletonHelper getHelperFromSkeleton]( [param:Skeleton skeleton] )

    -

    - -

    [method:Bone getNearestBone]( [param:Bone bone], [param:Array names] )

    -

    - -

    [method:Object getSkeletonOffsets]( [param:SkeletonHelper target], [param:SkeletonHelper source], [param:Object options] )

    -

    - -

    [method:this renameBones]( [param:Skeleton skeleton], [param:Array names] )

    -

    -

    [method:undefined retarget]( [param:SkeletonHelper target], [param:SkeletonHelper source], [param:Object options] )

    diff --git a/docs/examples/ko/controls/DragControls.html b/docs/examples/ko/controls/DragControls.html index 0f53d771ae6221..0cbc3ee74224c2 100644 --- a/docs/examples/ko/controls/DragControls.html +++ b/docs/examples/ko/controls/DragControls.html @@ -15,6 +15,17 @@

    [name]

    해당 클래스는 드래그 앤 드롭 상호작용에 대해 사용 됩니다.

    +

    수입

    + +

    + [name] 는 애드온이며 명시적으로 가져와야 합니다. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { DragControls } from 'three/addons/controls/DragControls.js'; + +

    코드 예시

    diff --git a/docs/examples/ko/controls/FirstPersonControls.html b/docs/examples/ko/controls/FirstPersonControls.html index 0eb329a3f4a925..13d6c8fd0f9fe4 100644 --- a/docs/examples/ko/controls/FirstPersonControls.html +++ b/docs/examples/ko/controls/FirstPersonControls.html @@ -14,6 +14,17 @@

    [name]

    해당 클래스는 [page:FlyControls] 의 대안적인 구현 방법입니다.

    +

    수입

    + +

    + [name] 는 애드온이며 명시적으로 가져와야 합니다. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js'; + +

    예시

    [example:webgl_geometry_terrain webgl / geometry / terrain ]

    diff --git a/docs/examples/ko/controls/FlyControls.html b/docs/examples/ko/controls/FlyControls.html index d7f21b41931d93..2e74af2f0f1ff2 100644 --- a/docs/examples/ko/controls/FlyControls.html +++ b/docs/examples/ko/controls/FlyControls.html @@ -15,6 +15,17 @@

    [name]

    +

    수입

    + +

    + [name] 는 애드온이며 명시적으로 가져와야 합니다. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { FlyControls } from 'three/addons/controls/FlyControls.js'; + +

    예시

    [example:misc_controls_fly misc / controls / fly ]

    diff --git a/docs/examples/ko/controls/OrbitControls.html b/docs/examples/ko/controls/OrbitControls.html index c5e38dfa3ea678..9bf86f3e03c2ed 100644 --- a/docs/examples/ko/controls/OrbitControls.html +++ b/docs/examples/ko/controls/OrbitControls.html @@ -16,6 +16,17 @@

    [name]

    +

    수입

    + +

    + [name] 는 애드온이며 명시적으로 가져와야 합니다. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; + +

    코드 예시

    @@ -298,6 +309,11 @@

    [method:undefined saveState] ()

    컨트롤의 현재 상태를 저장합니다. 나중에 [page:.reset]을 이용하여 현재 상태로 복구할 수 있습니다.

    +

    [method:undefined stopListenToKeyEvents] ()

    +

    + Removes the key event listener previously defined with [page:.listenToKeyEvents](). +

    +

    [method:Boolean update] ()

    컨트롤을 업데이트합니다. 카메라를 수동으로 변환하거나, [page:.autoRotate] 또는 [page:.enableDamping]을 설정할 경우 업데이트 루프에서 호출해야 합니다. diff --git a/docs/examples/ko/controls/PointerLockControls.html b/docs/examples/ko/controls/PointerLockControls.html index 0b6d5374af9d5c..b96ef9016b9a89 100644 --- a/docs/examples/ko/controls/PointerLockControls.html +++ b/docs/examples/ko/controls/PointerLockControls.html @@ -15,6 +15,17 @@

    [name]

    해당 클래스의 구현은 [link:https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API Pointer Lock API] 를 기반으로 합니다. [name] 은 1 인칭 3D 게임을 위한 완벽한 선택입니다.

    +

    수입

    + +

    + [name] 는 애드온이며 명시적으로 가져와야 합니다. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js'; + +

    Code Example

    diff --git a/docs/examples/ko/controls/TrackballControls.html b/docs/examples/ko/controls/TrackballControls.html index 8a8dfad98c3f5c..4d87f65d9e921d 100644 --- a/docs/examples/ko/controls/TrackballControls.html +++ b/docs/examples/ko/controls/TrackballControls.html @@ -18,6 +18,17 @@

    [name]

    +

    수입

    + +

    + [name] 는 애드온이며 명시적으로 가져와야 합니다. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { TrackballControls } from 'three/addons/controls/TrackballControls.js'; + +

    예시

    [example:misc_controls_trackball misc / controls / trackball ]

    @@ -84,12 +95,22 @@

    [property:Array keys]

    [property:Number maxDistance]

    - 축소할 수 있는 범위를 설정합니다. 기본값은 *무한대* 입니다. + 축소할 수 있는 범위를 설정합니다. ([page:PerspectiveCamera] only). 기본값은 *무한대* 입니다.

    [property:Number minDistance]

    - 확대할 수 있는 범위를 설정합니다. 기본값은 *0* 입니다. + 확대할 수 있는 범위를 설정합니다. ([page:PerspectiveCamera] only). 기본값은 *0* 입니다. +

    + +

    [property:Float maxZoom]

    +

    + 축소 할 수 있는 범위를 설정합니다. ( [page:OrthographicCamera] only ). 기본값은 *무한대* 입니다. +

    + +

    [property:Float minZoom]

    +

    + 확대 할 수 있는 범위를 설정합니다. ( [page:OrthographicCamera] only ). 기본값은 *0* 입니다.

    diff --git a/docs/examples/ko/controls/TransformControls.html b/docs/examples/ko/controls/TransformControls.html index 2f499a4921ce8d..744c6a395ab210 100644 --- a/docs/examples/ko/controls/TransformControls.html +++ b/docs/examples/ko/controls/TransformControls.html @@ -19,6 +19,17 @@

    [name]

    +

    수입

    + +

    + [name] 는 애드온이며 명시적으로 가져와야 합니다. + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { TransformControls } from 'three/addons/controls/TransformControls.js'; + +

    예시

    [example:misc_controls_transform misc / controls / transform ]

    diff --git a/docs/examples/zh/animations/CCDIKSolver.html b/docs/examples/zh/animations/CCDIKSolver.html deleted file mode 100644 index 567dc32094eaf6..00000000000000 --- a/docs/examples/zh/animations/CCDIKSolver.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    A solver for IK with CCD Algorithm.

    - [name] solves Inverse Kinematics Problem with CCD Algorithm. - [name] is designed to work with [page:SkinnedMesh] but also can be used with [page:MMDLoader] or [page:GLTFLoader] skeleton. -

    - - - -

    代码示例

    - - - let ikSolver; - - // - // Bones hierarchy: - // - // root - // ├── bone0 - // │ └── bone1 - // │ └── bone2 - // │ └── bone3 - // └── target - // - // Positioned as follow on the cylinder: - // - // o <- target (y = 20) - // - // +----o----+ <- bone3 (y = 12) - // | | - // | o | <- bone2 (y = 4) - // | | - // | o | <- bone1 (y = -4) - // | | - // +----oo---+ <- root, bone0 (y = -12) - // - - let bones = [] - - // "root" - let rootBone = new Bone(); - rootBone.position.y = -12; - bones.push( rootBone ); - - // "bone0" - let prevBone = new Bone(); - prevBone.position.y = 0; - rootBone.add( prevBone ); - bones.push( prevBone ); - - // "bone1", "bone2", "bone3" - for ( let i = 1; i <= 3; i ++ ) { - const bone = new Bone(); - bone.position.y = 8; - bones.push( bone ); - - prevBone.add( bone ); - prevBone = bone; - } - - // "target" - const targetBone = new Bone(); - targetBone.position.y = 24 + 8 - rootBone.add( targetBone ); - bones.push( targetBone ); - - // - // skinned mesh - // - - const mesh = new SkinnedMesh( geometry, material ); - const skeleton = new Skeleton( bones ); - - mesh.add( bones[ 0 ] ); // "root" bone - mesh.bind( skeleton ); - - // - // ikSolver - // - - const iks = [ - { - target: 5, // "target" - effector: 4, // "bone3" - links: [ { index: 3 }, { index: 2 }, { index: 1 } ] // "bone2", "bone1", "bone0" - } - ]; - ikSolver = new CCDIKSolver( mesh, iks ); - - function render() { - ikSolver?.update(); - renderer.render( scene, camera ); - } - - -

    例子

    - -

    - [example:webgl_loader_mmd]
    - [example:webgl_loader_mmd_pose]
    - [example:webgl_loader_mmd_audio] -

    - -

    Constructor

    - -

    [name]( [param:SkinnedMesh mesh], [param:Array iks] )

    -

    - [page:SkinnedMesh mesh] — [page:SkinnedMesh] for which [name] solves IK problem.
    - [page:Array iks] — An array of [page:Object] specifying IK parameter. target, effector, and link-index are index integers in .skeleton.bones. - The bones relation should be "links[ n ], links[ n - 1 ], ..., links[ 0 ], effector" in order from parent to child.
    -

      -
    • [page:Integer target] — Target bone.
    • -
    • [page:Integer effector] — Effector bone.
    • -
    • [page:Array links] — An array of [page:Object] specifying link bones. -
        -
      • [page:Integer index] — Link bone.
      • -
      • [page:Vector3 limitation] — (optional) Rotation axis. Default is undefined.
      • -
      • [page:Vector3 rotationMin] — (optional) Rotation minimum limit. Default is undefined.
      • -
      • [page:Vector3 rotationMax] — (optional) Rotation maximum limit. Default is undefined.
      • -
      • [page:Boolean enabled] — (optional) Default is true.
      • -
      -
    • -
    • [page:Integer iteration] — (optional) Iteration number of calculation. Smaller is faster but less precise. Default is 1.
    • -
    • [page:Number minAngle] — (optional) Minimum rotation angle in a step. Default is undefined.
    • -
    • [page:Number maxAngle] — (optional) Maximum rotation angle in a step. Default is undefined.
    • -
    -

    -

    - Creates a new [name]. -

    - -

    Properties

    - -

    [property:Array iks]

    -

    An array of IK parameter passed to the constructor.

    - -

    [property:SkinnedMesh mesh]

    -

    [page:SkinnedMesh] passed to the constructor.

    - -

    Methods

    - -

    [method:CCDIKHelper createHelper]()

    -

    - Return [page:CCDIKHelper]. You can visualize IK bones by adding the helper to scene. -

    - -

    [method:this update]()

    -

    - Update IK bones quaternion by solving CCD algorithm. -

    - -

    [method:this updateOne]( [param:Object ikParam] )

    -

    - Update an IK bone quaternion by solving CCD algorithm. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/CCDIKSolver.js examples/jsm/animation/CCDIKSolver.js] -

    - - diff --git a/docs/examples/zh/animations/MMDAnimationHelper.html b/docs/examples/zh/animations/MMDAnimationHelper.html deleted file mode 100644 index 9890342d8d8cdd..00000000000000 --- a/docs/examples/zh/animations/MMDAnimationHelper.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    A animation helper for MMD resources.

    - [name] handles animation of MMD assets loaded by [page:MMDLoader] with MMD special features as IK, Grant, and Physics. - It uses [page:CCDIKSolver] and [page:MMDPhysics] inside. -

    - -

    代码示例

    - - - // Instantiate a helper - const helper = new MMDAnimationHelper(); - - // Load MMD resources and add to helper - new MMDLoader().loadWithAnimation( - 'models/mmd/miku.pmd', - 'models/mmd/dance.vmd', - function ( mmd ) { - - helper.add( mmd.mesh, { - animation: mmd.animation, - physics: true - } ); - - scene.add( mmd.mesh ); - - new THREE.AudioLoader().load( - 'audios/mmd/song.mp3', - function ( buffer ) { - - const listener = new THREE.AudioListener(); - const audio = new THREE.Audio( listener ).setBuffer( buffer ); - - listener.position.z = 1; - - scene.add( audio ); - scene.add( listener ); - - } - - ); - - } - ); - - function render() { - - helper.update( clock.getDelta() ); - renderer.render( scene, camera ); - - } - - -

    例子

    - -

    - [example:webgl_loader_mmd]
    - [example:webgl_loader_mmd_pose]
    - [example:webgl_loader_mmd_audio] -

    - -

    Constructor

    - -

    [name]( [param:Object params] )

    -

    - [page:Object params] — (optional)
    -

      -
    • [page:Boolean sync] - Whether animation durations of added objects are synched. Default is true.
    • -
    • [page:Number afterglow] - Default is 0.0.
    • -
    • [page:Boolean resetPhysicsOnLoop] - Default is true.
    • -
    • [page:Boolean pmxAnimation] - If it is set to true, the helper follows the complex and costly PMX animation system. - Try this option only if your PMX model animation doesn't work well. Default is false.
    • -
    -

    -

    - Creates a new [name]. -

    - -

    Properties

    - -

    [property:Audio audio]

    -

    An [page:Audio] added to helper.

    - -

    [property:Camera camera]

    -

    An [page:Camera] added to helper.

    - -

    [property:Array meshes]

    -

    An array of [page:SkinnedMesh] added to helper.

    - -

    [property:WeakMap objects]

    -

    A [page:WeakMap] which holds animation stuffs used in helper for objects added to helper. For example, you can access [page:AnimationMixer] for an added [page:SkinnedMesh] with "helper.objects.get( mesh ).mixer"

    - -

    [property:Function onBeforePhysics]

    -

    An optional callback that is executed immediately before the physicis calculation for an [page:SkinnedMesh]. This function is called with the [page:SkinnedMesh].

    - -

    Methods

    - -

    [method:MMDAnimationHelper add]( [param:Object3D object], [param:Object params] )

    -

    - [page:Object3D object] — [page:SkinnedMesh], [page:Camera], or [page:Audio]
    - [page:Object params] — (optional)
    -

      -
    • [page:AnimationClip animation] - an [page:AnimationClip] or an array of [page:AnimationClip] set to object. Only for [page:SkinnedMesh] and [page:Camera]. Default is undefined.
    • -
    • [page:Boolean physics] - Only for [page:SkinnedMesh]. A flag whether turn on physics. Default is true.
    • -
    • [page:Integer warmup] - Only for [page:SkinnedMesh] and physics is true. Physics parameter. Default is 60.
    • -
    • [page:Number unitStep] - Only for [page:SkinnedMesh] and physics is true. Physics parameter. Default is 1 / 65.
    • -
    • [page:Integer maxStepNum] - Only for [page:SkinnedMesh] and physics is true. Physics parameter. Default is 3.
    • -
    • [page:Vector3 gravity] - Only for [page:SkinnedMesh] and physics is true. Physics parameter. Default is ( 0, - 9.8 * 10, 0 ).
    • -
    • [page:Number delayTime] - Only for [page:Audio]. Default is 0.0.
    • -
    -

    -

    - Add an [page:SkinnedMesh], [page:Camera], or [page:Audio] to helper and setup animation. The anmation durations of added objects are synched. - If camera/audio has already been added, it'll be replaced with a new one. -

    - -

    [method:MMDAnimationHelper enable]( [param:String key], [param:Boolean enabled] )

    -

    - [page:String key] — Allowed strings are 'animation', 'ik', 'grant', 'physics', and 'cameraAnimation'.
    - [page:Boolean enabled] — true is enable, false is disable
    -

    -

    - Enable/Disable an animation feature -

    - -

    [method:MMDAnimationHelper pose]( [param:SkinnedMesh mesh], [param:Object vpd], [param:Object params] )

    -

    - [page:SkinnedMesh mesh] — [page:SkinnedMesh] which changes the posing. It doesn't need to be added to helper.
    - [page:Object vpd] — VPD content obtained by [page:MMDLoader].loadVPD
    - [page:Object params] — (optional)
    -

      -
    • [page:Boolean resetPose] - Default is true.
    • -
    • [page:Boolean ik] - Default is true.
    • -
    • [page:Boolean grant] - Default is true.
    • -
    -

    -

    - Changes the posing of [page:SkinnedMesh] as VPD content specifies. -

    - -

    [method:MMDAnimationHelper remove]( [param:Object3D object] )

    -

    - [page:Object3D object] — [page:SkinnedMesh], [page:Camera], or [page:Audio]
    -

    -

    - Remove an [page:SkinnedMesh], [page:Camera], or [page:Audio] from helper. -

    - -

    [method:MMDAnimationHelper update]( [param:Nummber delta] )

    -

    - [page:Number delta] — number in second
    -

    -

    - Advance mixer time and update the animations of objects added to helper -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/MMDAnimationHelper.js examples/jsm/animation/MMDAnimationHelper.js] -

    - - diff --git a/docs/examples/zh/animations/MMDPhysics.html b/docs/examples/zh/animations/MMDPhysics.html deleted file mode 100644 index d4519c9d7b17d3..00000000000000 --- a/docs/examples/zh/animations/MMDPhysics.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    A Physics handler for MMD resources.

    - [name] calculates Physics for model loaded by [page:MMDLoader] with [link:https://github.com/kripken/ammo.js/ ammo.js] (Bullet-based JavaScript Physics engine). -

    - -

    代码示例

    - - - const physics; - - // Load MMD resources and instantiate MMDPhysics - new MMDLoader().load( - 'models/mmd/miku.pmd', - function ( mesh ) { - - physics = new MMDPhysics( mesh ) - scene.add( mesh ); - - } - ); - - function render() { - - const delta = clock.getDelta(); - animate( delta ); // update bones - if ( physics !== undefined ) physics.update( delta ); - renderer.render( scene, camera ); - - } - - -

    例子

    - -

    - [example:webgl_loader_mmd]
    - [example:webgl_loader_mmd_audio] -

    - -

    Constructor

    - -

    [name]( [param:SkinnedMesh mesh], [param:Array rigidBodyParams], [param:Array constraintParams], [param:Object params] )

    -

    - [page:SkinnedMesh mesh] — [page:SkinnedMesh] for which [name] calculates Physics.
    - [page:Array rigidBodyParams] — An array of [page:Object] specifying Rigid Body parameters.
    - [page:Array constraintParams] — (optional) An array of [page:Object] specifying Constraint parameters.
    - [page:Object params] — (optional)
    -

      -
    • [page:Number unitStep] - Default is 1 / 65.
    • -
    • [page:Integer maxStepNum] - Default is 3.
    • -
    • [page:Vector3 gravity] - Default is ( 0, - 9.8 * 10, 0 )
    • -
    -

    -

    - Creates a new [name]. -

    - -

    Properties

    - -

    [property:Array mesh]

    -

    [page:SkinnedMesh] passed to the constructor.

    - -

    Methods

    - -

    [method:MMDPhysicsHelper createHelper]()

    -

    - Return [page:MMDPhysicsHelper]. You can visualize Rigid bodies by adding the helper to scene. -

    - -

    [method:this reset]()

    -

    - Resets Rigid bodies transform to current bone's. -

    - -

    [method:this setGravity]( [param:Vector3 gravity] )

    -

    - [page:Vector3 gravity] — Direction and volume of gravity. -

    -

    - Set gravity. -

    - -

    [method:this update]( [param:Number delta] )

    -

    - [page:Number delta] — Time in second. -

    -

    - Advance Physics calculation and updates bones. -

    - -

    [method:this warmup]( [param:Integer cycles] )

    -

    - [page:Number delta] — Time in second. -

    -

    - Warm up Rigid bodies. Calculates cycles steps. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/MMDPhysics.js examples/jsm/animation/MMDPhysics.js] -

    - - diff --git a/docs/examples/zh/controls/DragControls.html b/docs/examples/zh/controls/DragControls.html index 38db47e73b4c0c..f81e6efee0b4b9 100644 --- a/docs/examples/zh/controls/DragControls.html +++ b/docs/examples/zh/controls/DragControls.html @@ -15,6 +15,17 @@

    拖放控制器([name])

    该类被用于提供一个拖放交互。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { DragControls } from 'three/addons/controls/DragControls.js'; + +

    代码示例

    diff --git a/docs/examples/zh/controls/FirstPersonControls.html b/docs/examples/zh/controls/FirstPersonControls.html index 6cb86ddf356f9c..a2d504e8fc219e 100644 --- a/docs/examples/zh/controls/FirstPersonControls.html +++ b/docs/examples/zh/controls/FirstPersonControls.html @@ -14,6 +14,17 @@

    第一人称控制器([name])

    该类是 [page:FlyControls] 的另一个实现。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js'; + +

    例子

    [example:webgl_geometry_terrain webgl / geometry / terrain ]

    diff --git a/docs/examples/zh/controls/FlyControls.html b/docs/examples/zh/controls/FlyControls.html index bce44269d5a87a..99691d491823bd 100644 --- a/docs/examples/zh/controls/FlyControls.html +++ b/docs/examples/zh/controls/FlyControls.html @@ -15,6 +15,17 @@

    飞行控制器([name])

    你可以在3D空间中任意变换摄像机,并且无任何限制(例如,专注于一个特定的目标)。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { FlyControls } from 'three/addons/controls/FlyControls.js'; + +

    例子

    [example:misc_controls_fly misc / controls / fly ]

    diff --git a/docs/examples/zh/controls/OrbitControls.html b/docs/examples/zh/controls/OrbitControls.html index 2d832284d00140..cfee58e37fc3bb 100644 --- a/docs/examples/zh/controls/OrbitControls.html +++ b/docs/examples/zh/controls/OrbitControls.html @@ -17,6 +17,17 @@

    轨道控制器([name])

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; + +

    代码示例

    @@ -300,6 +311,11 @@

    [method:undefined saveState] ()

    保存当前控制器的状态。这一状态可在之后由[page:.reset]所恢复。

    +

    [method:undefined stopListenToKeyEvents] ()

    +

    + Removes the key event listener previously defined with [page:.listenToKeyEvents](). +

    +

    [method:Boolean update] ()

    更新控制器。必须在摄像机的变换发生任何手动改变后调用, diff --git a/docs/examples/zh/controls/PointerLockControls.html b/docs/examples/zh/controls/PointerLockControls.html index 70409d3c3f6f6c..12a8d4db54e650 100644 --- a/docs/examples/zh/controls/PointerLockControls.html +++ b/docs/examples/zh/controls/PointerLockControls.html @@ -16,6 +16,17 @@

    指针锁定控制器([name])

    对于第一人称3D游戏来说, [name] 是一个非常完美的选择。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js'; + +

    代码示例

    diff --git a/docs/examples/zh/controls/TrackballControls.html b/docs/examples/zh/controls/TrackballControls.html index 681fbb852cce5c..4176810317b4cc 100644 --- a/docs/examples/zh/controls/TrackballControls.html +++ b/docs/examples/zh/controls/TrackballControls.html @@ -18,6 +18,17 @@

    轨迹球控制器([name])

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { TrackballControls } from 'three/addons/controls/TrackballControls.js'; + +

    例子

    [example:misc_controls_trackball misc / controls / trackball ]

    @@ -84,12 +95,22 @@

    [property:Array keys]

    [property:Number maxDistance]

    - 你能够将相机向外移动多少,其默认值为*Infinity*。 + 你能够将相机向外移动多少(仅适用于[page:PerspectiveCamera]),其默认值为*Infinity*。

    [property:Number minDistance]

    - 你能够将相机向内移动多少,其默认值为*0*。 + 你能够将相机向内移动多少(仅适用于[page:PerspectiveCamera]),其默认值为*0*。 +

    + +

    [property:Float maxZoom]

    +

    + 你能够将相机缩小多少(仅适用于[page:OrthographicCamera]),其默认值为*Infinity*。 +

    + +

    [property:Float minZoom]

    +

    + 你能够将相机放大多少(仅适用于[page:OrthographicCamera]),其默认值为*0*。

    diff --git a/docs/examples/zh/controls/TransformControls.html b/docs/examples/zh/controls/TransformControls.html index 24b95992ddf325..bb72b36f499d95 100644 --- a/docs/examples/zh/controls/TransformControls.html +++ b/docs/examples/zh/controls/TransformControls.html @@ -18,6 +18,17 @@

    变换控制器([name])

    [name] 期望其所附加的3D对象是场景图的一部分。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { TransformControls } from 'three/addons/controls/TransformControls.js'; + +

    例子

    [example:misc_controls_transform misc / controls / transform ]

    diff --git a/docs/examples/zh/exporters/ColladaExporter.html b/docs/examples/zh/exporters/ColladaExporter.html deleted file mode 100644 index 1ca5da5a67a309..00000000000000 --- a/docs/examples/zh/exporters/ColladaExporter.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - An exporter for *Collada*. -

    - [link:https://www.khronos.org/collada/ Collada] is a - file format for robust representation of scenes, materials, animations, and other 3D content in an xml format. - This exporter only supports exporting geometry, materials, textures, and scene hierarchy. -

    - -

    代码示例

    - - - // Instantiate an exporter - const exporter = new ColladaExporter(); - - // Parse the input and generate the collada ( .dae ) output - const data = exporter.parse( scene, null, options ); - downloadFile( data ); - - -

    Constructor

    - -

    [name]()

    -

    -

    -

    - Creates a new [name]. -

    - -

    Methods

    - -

    [method:Object parse]( [param:Object3D input], [param:Function onCompleted], [param:Object options] )

    -

    - [page:Object input] — Object3D to be exported
    - [page:Function onCompleted] — Will be called when the export completes. Optional. The same data is immediately returned from the function.
    - [page:Options options] — Export options
    -

      -
    • version - string. Which version of Collada to export. The options are "1.4.1" or "1.5.0". Defaults to "1.4.1".
    • -
    • author - string. The name to include in the author field. Author field is excluded by default.
    • -
    • textureDirectory - string. The directory relative to the Collada file to save the textures to.
    • -
    -

    -

    - Generates an object with Collada file and texture data. This object is returned from the function and passed into the "onCompleted" callback. - - { - // Collada file content - data: "", - - // List of referenced textures - textures: [{ - - // File directory, name, and extension of the texture data - directory: "", - name: "", - ext: "", - - // The texture data and original texture object - data: [], - original: <THREE.Texture> - }, ...] - } - -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/ColladaExporter.js examples/jsm/exporters/ColladaExporter.js] -

    - - diff --git a/docs/examples/zh/exporters/GLTFExporter.html b/docs/examples/zh/exporters/GLTFExporter.html deleted file mode 100644 index 930c44380ea038..00000000000000 --- a/docs/examples/zh/exporters/GLTFExporter.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - An exporter for `glTF` 2.0. -

    - [link:https://www.khronos.org/gltf glTF] (GL Transmission Format) is an - [link:https://github.com/KhronosGroup/glTF/tree/master/specification/2.0 open format specification] - for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf) - or binary (.glb) format. External files store textures (.jpg, .png) and additional binary - data (.bin). A glTF asset may deliver one or more scenes, including meshes, materials, - textures, skins, skeletons, morph targets, animations, lights, and/or cameras. -

    - -

    Extensions

    - -

    - GLTFExporter supports the following - [link:https://github.com/KhronosGroup/glTF/tree/master/extensions/ glTF 2.0 extensions]: -

    - -
      -
    • KHR_lights_punctual
    • -
    • KHR_materials_clearcoat
    • -
    • KHR_materials_emissive_strength
    • -
    • KHR_materials_ior
    • -
    • KHR_materials_iridescence
    • -
    • KHR_materials_specular
    • -
    • KHR_materials_sheen
    • -
    • KHR_materials_transmission
    • -
    • KHR_materials_unlit
    • -
    • KHR_materials_volume
    • -
    • KHR_mesh_quantization
    • -
    • KHR_texture_transform
    • -
    -

    - The following glTF 2.0 extension is supported by an external user plugin -

    - -
      -
    • [link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]
    • -
    - -

    代码示例

    - - - // Instantiate a exporter - const exporter = new GLTFExporter(); - - // Parse the input and generate the glTF output - exporter.parse( - scene, - // called when the gltf has been generated - function ( gltf ) { - - console.log( gltf ); - downloadJSON( gltf ); - - }, - // called when there is an error in the generation - function ( error ) { - - console.log( 'An error happened' ); - - }, - options - ); - - -

    例子

    - -

    - [example:misc_exporter_gltf] -

    - -

    构造函数

    - -

    [name]()

    -

    -

    -

    - Creates a new [name]. -

    - -

    方法

    - -

    [method:undefined parse]( [param:Object3D input], [param:Function onCompleted], [param:Function onError], [param:Object options] )

    - -

    - [page:Object input] — Scenes or objects to export. Valid options:
    -

      -
    • - Export scenes - - exporter.parse( scene1, ... ) - exporter.parse( [ scene1, scene2 ], ... ) - -
    • -
    • - Export objects (It will create a new Scene to hold all the objects) - - exporter.parse( object1, ... ) - exporter.parse( [ object1, object2 ], ... ) - -
    • -
    • - Mix scenes and objects (It will export the scenes as usual but it will create a new scene to hold all the single objects). - - exporter.parse( [ scene1, object1, object2, scene2 ], ... ) - -
    • -
    - - [page:Function onCompleted] — Will be called when the export completes. The argument will be the generated glTF JSON or binary ArrayBuffer.
    - [page:Function onError] — Will be called if there are any errors during the gltf generation.
    - [page:Options options] — Export options
    -
      -
    • trs - bool. Export position, rotation and scale instead of matrix per node. Default is false
    • -
    • onlyVisible - bool. Export only visible objects. Default is true.
    • -
    • binary - bool. Export in binary (.glb) format, returning an ArrayBuffer. Default is false.
    • -
    • maxTextureSize - int. Restricts the image maximum size (both width and height) to the given value. Default is Infinity.
    • -
    • animations - Array<[page:AnimationClip AnimationClip]>. List of animations to be included in the export.
    • -
    • includeCustomExtensions - bool. Export custom glTF extensions defined on an object's userData.gltfExtensions property. Default is false.
    • -
    -

    -

    - Generates a .gltf (JSON) or .glb (binary) output from the input (Scenes or Objects) -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/GLTFExporter.js examples/jsm/exporters/GLTFExporter.js] -

    - - diff --git a/docs/examples/zh/exporters/PLYExporter.html b/docs/examples/zh/exporters/PLYExporter.html deleted file mode 100644 index 35a852e0aafecc..00000000000000 --- a/docs/examples/zh/exporters/PLYExporter.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - An exporter for *PLY*. -

    - [link:https://en.wikipedia.org/wiki/PLY_(file_format) PLY] (Polygon or Stanford Triangle Format) is a - file format for efficient delivery and loading of simple, static 3D content in a dense format. - Both binary and ascii formats are supported. PLY can store vertex positions, colors, normals and - uv coordinates. No textures or texture references are saved. -

    - -

    代码示例

    - - - // Instantiate an exporter - const exporter = new PLYExporter(); - - // Parse the input and generate the ply output - const data = exporter.parse( scene, options ); - downloadFile( data ); - - -

    Constructor

    - -

    [name]()

    -

    -

    -

    - Creates a new [name]. -

    - -

    Methods

    - -

    [method:Object parse]( [param:Object3D input], [param:Function onDone], [param:Object options] )

    -

    - [page:Object input] — Object3D
    - [page:Function onCompleted] — Will be called when the export completes. The argument will be the generated ply ascii or binary ArrayBuffer.
    - [page:Options options] — Export options
    -

      -
    • excludeAttributes - array. Which properties to explicitly exclude from the exported PLY file. Valid values are 'color', 'normal', 'uv', and 'index'. If triangle indices are excluded, then a point cloud is exported. Default is an empty array.
    • -
    • binary - bool. Export in binary format, returning an ArrayBuffer. Default is false.
    • -
    -

    -

    - Generates ply file data as string or ArrayBuffer (ascii or binary) output from the input object. The data that is returned is the same - that is passed into the "onCompleted" function. - If the object is composed of multiple children and geometry, they are merged into a single mesh in the file. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/PLYExporter.js examples/jsm/exporters/PLYExporter.js] -

    - - diff --git a/docs/examples/zh/geometries/ConvexGeometry.html b/docs/examples/zh/geometries/ConvexGeometry.html index c651e56b09ee9a..449f6d850581ca 100644 --- a/docs/examples/zh/geometries/ConvexGeometry.html +++ b/docs/examples/zh/geometries/ConvexGeometry.html @@ -14,6 +14,17 @@

    凸包几何体([name])

    [name] 可被用于为传入的一组点生成凸包。 该任务的平均时间复杂度被认为是O(nlog(n))。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { ConvexGeometry } from 'three/addons/geometries/ConvexGeometry.js'; + +

    代码示例

    const geometry = new ConvexGeometry( points ); diff --git a/docs/examples/zh/geometries/DecalGeometry.html b/docs/examples/zh/geometries/DecalGeometry.html index 1e15da6c190dfa..7234d3d139ea2a 100644 --- a/docs/examples/zh/geometries/DecalGeometry.html +++ b/docs/examples/zh/geometries/DecalGeometry.html @@ -13,6 +13,17 @@

    贴花几何体([name])

    [name] 可被用于创建贴花网格物体,以达到不同的目的,例如:为模型增加独特的细节、进行动态的视觉环境改变或覆盖接缝。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { DecalGeometry } from 'three/addons/geometries/DecalGeometry.js'; + +

    代码示例

    diff --git a/docs/examples/zh/geometries/ParametricGeometry.html b/docs/examples/zh/geometries/ParametricGeometry.html index c2b59d9ccd9a48..ea92a6686e47b8 100644 --- a/docs/examples/zh/geometries/ParametricGeometry.html +++ b/docs/examples/zh/geometries/ParametricGeometry.html @@ -13,21 +13,16 @@

    参数化缓冲几何体([name])

    生成由参数表示其表面的几何体。

    - + + import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js'; +

    代码示例

    diff --git a/docs/examples/zh/geometries/TextGeometry.html b/docs/examples/zh/geometries/TextGeometry.html index d886f3552e0ecd..a400dd0299491f 100644 --- a/docs/examples/zh/geometries/TextGeometry.html +++ b/docs/examples/zh/geometries/TextGeometry.html @@ -17,21 +17,16 @@

    文本缓冲几何体([name])

    请参阅[page:FontLoader]页面来查看更多详细信息。

    - + + import { TextGeometry } from 'three/addons/geometries/TextGeometry.js'; +

    代码示例

    diff --git a/docs/examples/zh/helpers/LightProbeHelper.html b/docs/examples/zh/helpers/LightProbeHelper.html index c4a5897a1f707d..56ede10b7007cb 100644 --- a/docs/examples/zh/helpers/LightProbeHelper.html +++ b/docs/examples/zh/helpers/LightProbeHelper.html @@ -15,6 +15,17 @@

    [name]

    在场景中渲染一个球来可视化光照探针。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { LightProbeHelper } from 'three/addons/helpers/LightProbeHelper.js'; + +

    代码示例

    diff --git a/docs/examples/zh/helpers/PositionalAudioHelper.html b/docs/examples/zh/helpers/PositionalAudioHelper.html index 8a418450727111..d8ce6a4d376357 100644 --- a/docs/examples/zh/helpers/PositionalAudioHelper.html +++ b/docs/examples/zh/helpers/PositionalAudioHelper.html @@ -13,6 +13,17 @@

    [name]

    这一辅助对象显示[page:PositionalAudio]的方向锥。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { PositionalAudioHelper } from 'three/addons/helpers/PositionalAudioHelper.js'; + +

    代码示例

    const positionalAudio = new THREE.PositionalAudio( listener ); diff --git a/docs/examples/zh/helpers/RectAreaLightHelper.html b/docs/examples/zh/helpers/RectAreaLightHelper.html index 305a2ef012e6bc..10bb807444c82a 100644 --- a/docs/examples/zh/helpers/RectAreaLightHelper.html +++ b/docs/examples/zh/helpers/RectAreaLightHelper.html @@ -15,6 +15,17 @@

    [name]

    创建一个表示 [page:RectAreaLight] 的辅助对象.

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js'; + +

    代码示例

    diff --git a/docs/examples/zh/helpers/VertexNormalsHelper.html b/docs/examples/zh/helpers/VertexNormalsHelper.html index 5bf4bd5a82e759..a1f68c8d9ed009 100644 --- a/docs/examples/zh/helpers/VertexNormalsHelper.html +++ b/docs/examples/zh/helpers/VertexNormalsHelper.html @@ -17,6 +17,17 @@

    [name]

    使用了 [page:BufferGeometry.computeVertexNormals computeVertexNormals] 方法计算了顶点法线.

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { VertexNormalsHelper } from 'three/addons/helpers/VertexNormalsHelper.js'; + +

    代码示例

    diff --git a/docs/examples/zh/helpers/VertexTangentsHelper.html b/docs/examples/zh/helpers/VertexTangentsHelper.html deleted file mode 100644 index eea4136caf9491..00000000000000 --- a/docs/examples/zh/helpers/VertexTangentsHelper.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - [page:Object3D] → [page:Line] → [page:LineSegments] → - -

    [name]

    - -

    - Renders arrows to visualize an object's vertex tangent vectors. - Requires that tangents have been specified in a [page:BufferAttribute custom attribute] or - have been calculated using [page:BufferGeometry.computeTangents computeTangents].

    - - This helper supports [page:BufferGeometry] only. -

    - -

    代码示例

    - - - const geometry = new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 ); - const material = new THREE.MeshNormalMaterial(); - const box = new THREE.Mesh( geometry, material ); - - const helper = new VertexTangentsHelper( box, 1, 0x00ffff, 1 ); - - scene.add( box ); - scene.add( helper ); - - -

    例子

    -

    - [example:webgl_helpers WebGL / helpers] -

    - -

    Constructor

    - - -

    [name]( [param:Object3D object], [param:Number size], [param:Hex color], [param:Number linewidth] )

    -

    - [page:Object3D object] -- object for which to render vertex tangents.
    - [page:Number size] -- (optional) length of the arrows. Default is *1*.
    - [page:Hex color] -- hex color of the arrows. Default is 0x00ffff.
    - [page:Number linewidth] -- (optional) width of the arrow lines. Default is *1*. (Setting lineWidth is currently not supported.) -

    - - -

    Properties

    -

    See the base [page:LineSegments] class for common properties.

    - -

    [property:Object matrixAutoUpdate]

    -

    - See [page:Object3D.matrixAutoUpdate]. Set to *false* here as the helper is using the - objects's [page:Object3D.matrixWorld matrixWorld]. -

    - -

    [property:Object3D object]

    -

    The object for which the vertex tangents are being visualized.

    - -

    [property:Number size]

    -

    Length of the arrows. Default is *1*.

    - - -

    Methods

    -

    See the base [page:LineSegments] class for common methods.

    - - -

    [method:undefined update]()

    -

    Updates the vertex tangents preview based on the object's world transform.

    - - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/helpers/VertexTangentsHelper.js examples/jsm/helpers/VertexTangentsHelper.js] -

    - - diff --git a/docs/examples/zh/lights/LightProbeGenerator.html b/docs/examples/zh/lights/LightProbeGenerator.html index 1e96249d7772d0..8444a339fee5c7 100644 --- a/docs/examples/zh/lights/LightProbeGenerator.html +++ b/docs/examples/zh/lights/LightProbeGenerator.html @@ -14,6 +14,17 @@

    光照探针生成器([name])

    用于创建 [page:LightProbe] 实例的工具类。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { LightProbeGenerator } from 'three/addons/lights/LightProbeGenerator.js'; + +

    例子

    diff --git a/docs/examples/zh/loaders/DRACOLoader.html b/docs/examples/zh/loaders/DRACOLoader.html index ac87d678dc862f..b443af14a457c2 100644 --- a/docs/examples/zh/loaders/DRACOLoader.html +++ b/docs/examples/zh/loaders/DRACOLoader.html @@ -11,21 +11,33 @@

    [name]

    - A loader for geometry compressed with the Draco library.

    - [link:https://google.github.io/draco/ Draco] is an open source library for compressing and - decompressing 3D meshes and point clouds. Compressed geometry can be significantly smaller, - at the cost of additional decoding time on the client device. + 一个用于加载经过Draco压缩的图形库。

    + [link:https://google.github.io/draco/ Draco]是一个开源的库,主要用于压缩和解压缩三维模型及点云。 + 以客户端上解压缩为代价,显著减少压缩的图形。

    - Standalone Draco files have a .drc extension, and contain vertex positions, - normals, colors, and other attributes. Draco files do not contain materials, - textures, animation, or node hierarchies – to use these features, embed Draco geometry - inside of a glTF file. A normal glTF file can be converted to a Draco-compressed glTF file - using [link:https://github.com/AnalyticalGraphicsInc/gltf-pipeline glTF-Pipeline]. When - using Draco with glTF, an instance of DRACOLoader will be used internally by [page:GLTFLoader]. + 独立的Draco文件后缀为`.drc`,其中包含顶点坐标,法线,颜色和其他的属性, + Draco文件*不*包含材质,纹理,动画和节点结构-为了能使用这些特征,需要将Draco图形 + 嵌入到GLTF文件中。使用[link:https://github.com/AnalyticalGraphicsInc/gltf-pipeline glTF-Pipeline]可以将一个普通的GLTF文件转化为经过Draco压缩的GLTF文件。 + 当使用Draco压缩的GLTF模型时,[page:GLTFLoader]内部会调用DRACOLoader。

    +

    + 推荐创建一个DRACOLoader实例并重用,可以有效避免重复创建加载多个解压器实例。 +

    + +

    Import

    + +

    + [name]是一个插件,必须显示引用。 + 请参考 [link:#manual/introduction/Installation Installation / Addons]。 +

    + + + import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'; + +

    代码示例

    @@ -71,76 +83,74 @@

    例子

    [example:webgl_loader_draco]

    -

    Browser compatibility

    +

    浏览器兼容性

    -

    DRACOLoader will automatically use either the JS or the WASM decoding library, based on browser capabilities.

    +

    DRACOLoader会根据浏览器的特性,自动使用JS或者WASM解码库。



    -

    Constructor

    +

    构造函数

    [name]( [param:LoadingManager manager] )

    - [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. + [page:LoadingManager manager] — 加载器使用的[page:LoadingManager loadingManager]. 默认值为[page:LoadingManager THREE.DefaultLoadingManager].

    - Creates a new [name]. + 创建一个新的[name].

    -

    Properties

    -

    See the base [page:Loader] class for common properties.

    +

    属性

    +

    查看公共属性请参考基类[page:Loader]

    -

    Methods

    -

    See the base [page:Loader] class for common methods.

    +

    方法

    +

    查看公共方法请查看基类[page:Loader]

    [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

    - [page:String url] — A string containing the path/URL of the .drc file.
    - [page:Function onLoad] — A function to be called after the loading is successfully completed.
    - [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, that contains .[page:Integer total] and .[page:Integer loaded] bytes.
    - [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.
    + [page:String url] — 一个`.drc`文件的路径或者网络地址。
    + [page:Function onLoad] — 加载成功之后调用的函数。
    + [page:Function onProgress] — (可选的) 正在加载时调用的函数。参数为XMLHttpRequest实例,包含.[page:Integer total]和.[page:Integer loaded]
    + [page:Function onError] — (可选的)加载出现错误时调用的函数。该函将错误信息作为参数。

    - Begin loading from url and call the onLoad function with the decompressed geometry. + 开始加载解压缩的图形并调用`onLoad`函数。

    [method:this setDecoderPath]( [param:String value] )

    - [page:String value] — Path to folder containing the JS and WASM decoder libraries. + [page:String value] — 包含JS和WASM解压缩库的文件夹路径。

    [method:this setDecoderConfig]( [param:Object config] )

    - [page:String config.type] - (Optional) "js" or "wasm".
    + [page:String config.type] - (可选的) `"js"`或`"wasm"`。

    - Provides configuration for the decoder libraries. Configuration cannot be changed - after decoding begins. + 为解压缩库提供配置,在解压开始后不能修改。

    [method:this setWorkerLimit]( [param:Number workerLimit] )

    - [page:Number workerLimit] - Maximum number of workers to be allocated. Default is 4.
    + [page:Number workerLimit] - 可以分配的最大线程数。默认值为4。

    - Sets the maximum number of [link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers Web Workers] - to be used during decoding. A lower limit may be preferable if workers are also for other tasks - in the application. + 设置用于解码的[link:https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers Web Workers]的最大值。如果线程也用于其他的任务,给定更小的限制会更合理。 +

    [method:this preload]()

    - Requests the decoder libraries, if not already loaded. + 如果还没加载完成,则请求解压库。

    [method:this dispose]()

    - Disposes of the decoder resources and deallocates memory. The decoder - [link:https://github.com/google/draco/issues/349 cannot be reloaded afterward]. + 处理解压资源和释放的内存。在处理后,解码器 + [link:https://github.com/google/draco/issues/349 不能重新加载].

    -

    Source

    +

    源码

    [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/DRACOLoader.js examples/jsm/loaders/DRACOLoader.js] diff --git a/docs/examples/zh/loaders/FontLoader.html b/docs/examples/zh/loaders/FontLoader.html index e619061d8ae11e..427132c32abc45 100644 --- a/docs/examples/zh/loaders/FontLoader.html +++ b/docs/examples/zh/loaders/FontLoader.html @@ -18,6 +18,17 @@

    [name]

    你可以使用[link:https://gero3.github.io/facetype.js/ facetype.js]来在线转换字体。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { FontLoader } from 'three/addons/loaders/FontLoader.js'; + +

    代码示例

    diff --git a/docs/examples/zh/loaders/GLTFLoader.html b/docs/examples/zh/loaders/GLTFLoader.html index 2506626783f9bd..d8f58ef48354ec 100644 --- a/docs/examples/zh/loaders/GLTFLoader.html +++ b/docs/examples/zh/loaders/GLTFLoader.html @@ -24,6 +24,18 @@

    GLTF加载器([name])

    and they require special handling during the disposal process. More information in the [link:https://threejs.org/docs/#manual/en/introduction/How-to-dispose-of-objects How to dispose of objects] guide.

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; + + +

    扩展

    @@ -58,7 +70,7 @@

    扩展

    - 1需要[link:https://threejs.org/docs/#api/en/renderers/WebGLRenderer.physicallyCorrectLights physicallyCorrectLights]被启用。 + 1Requires [link:https://threejs.org/docs/#api/en/renderers/WebGLRenderer.useLegacyLights useLegacyLights] to be disabled.

    2支持UV变换,但存在一些重要的限制。 @@ -129,7 +141,7 @@

    纹理

    颜色空间并显示在屏幕上。除非你需要使用线性颜色空间进行后期处理,否则请在使用glTF的时候将[page:WebGLRenderer]进行如下配置:

    - renderer.outputEncoding = THREE.sRGBEncoding; + renderer.outputColorSpace = THREE.SRGBColorSpace;

    假设渲染器的配置如上所示,则GLTFLoader将可以正确地自动配置从.gltf或.glb文件中引用的纹理。 @@ -137,7 +149,7 @@

    纹理

    // If texture is used for color information, set colorspace. - texture.encoding = THREE.sRGBEncoding; + texture.colorSpace = THREE.SRGBColorSpace; // UVs use the convention that (0, 0) corresponds to the upper left corner of a texture. texture.flipY = false; diff --git a/docs/examples/zh/loaders/MMDLoader.html b/docs/examples/zh/loaders/MMDLoader.html index a395a5c3be1e56..039935d8150d42 100644 --- a/docs/examples/zh/loaders/MMDLoader.html +++ b/docs/examples/zh/loaders/MMDLoader.html @@ -15,7 +15,18 @@

    MMD加载器([name])

    [name]从MMD资源(例如PMD、PMX、VMD和VPD文件)中创建Three.js物体(对象)。 请参阅[page:MMDAnimationHelper]来了解MMD动画的处理,例如IK、Grant和Physics。

    - 如果你想要MMD资源的原始内容,请使用.loadPMD/PMX/VMD/VPD方法。 + 如果你想要MMD资源的原始内容,请使用.loadPMD/PMX/VMD/VPD方法。

    + +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { MMDLoader } from 'three/addons/loaders/MMDLoader.js'; +

    代码示例

    diff --git a/docs/examples/zh/loaders/MTLLoader.html b/docs/examples/zh/loaders/MTLLoader.html index 44259e09f104e4..ec111a3a839367 100644 --- a/docs/examples/zh/loaders/MTLLoader.html +++ b/docs/examples/zh/loaders/MTLLoader.html @@ -16,6 +16,17 @@

    MTL加载器([name])

    用于描述一个或多个 .OBJ 文件中物体表面着色(材质)属性。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { MTLLoader } from 'three/addons/loaders/MTLLoader.js'; + +

    构造函数

    [name]( [param:LoadingManager loadingManager] )

    diff --git a/docs/examples/zh/loaders/OBJLoader.html b/docs/examples/zh/loaders/OBJLoader.html index 8d42bc74ddc52a..759f5c144a5ded 100644 --- a/docs/examples/zh/loaders/OBJLoader.html +++ b/docs/examples/zh/loaders/OBJLoader.html @@ -17,6 +17,17 @@

    OBJ加载器([name])

    将使每个多边形定义为顶点列表的面以及纹理顶点。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { OBJLoader } from 'three/addons/loaders/OBJLoader.js'; + +

    代码示例

    diff --git a/docs/examples/zh/loaders/PCDLoader.html b/docs/examples/zh/loaders/PCDLoader.html index 6337160aaf1d2c..03b5c5e259bfcc 100644 --- a/docs/examples/zh/loaders/PCDLoader.html +++ b/docs/examples/zh/loaders/PCDLoader.html @@ -22,6 +22,17 @@

    [name]

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { PCDLoader } from 'three/addons/loaders/PCDLoader.js'; + +

    代码示例

    diff --git a/docs/examples/zh/loaders/PDBLoader.html b/docs/examples/zh/loaders/PDBLoader.html deleted file mode 100644 index a246fe35e7da9c..00000000000000 --- a/docs/examples/zh/loaders/PDBLoader.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - [page:Loader] → - -

    [name]

    - -

    A loader for loading a .pdb resource.
    - The [link:http://en.wikipedia.org/wiki/Protein_Data_Bank_(file_format) Protein Data Bank] file format is a textual file describing the three-dimensional structures of molecules. -

    - -

    代码示例

    - - - // instantiate a loader - const loader = new PDBLoader(); - - // load a PDB resource - loader.load( - // resource URL - 'models/pdb/caffeine.pdb', - // called when the resource is loaded - function ( pdb ) { - - const geometryAtoms = pdb.geometryAtoms; - const geometryBonds = pdb.geometryBonds; - const json = pdb.json; - - console.log( 'This molecule has ' + json.atoms.length + ' atoms' ); - - }, - // called when loading is in progresses - function ( xhr ) { - - console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' ); - - }, - // called when loading has errors - function ( error ) { - - console.log( 'An error happened' ); - - } - ); - - -

    例子

    -

    - [example:webgl_loader_pdb] -

    - -

    Constructor

    - -

    [name]( [param:LoadingManager manager] )

    -

    - [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. -

    -

    - Creates a new [name]. -

    - -

    Properties

    -

    See the base [page:Loader] class for common properties.

    - -

    Methods

    -

    See the base [page:Loader] class for common methods.

    - -

    [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

    -

    - [page:String url] — A string containing the path/URL of the .pdb file.
    - [page:Function onLoad] — (optional) A function to be called after loading is successfully completed. The function receives the object having the following properties. [page:BufferGeometry geometryAtoms], [page:BufferGeometry geometryBonds] and the [page:Object JSON] structure.
    - [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes.
    - [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives the error as an argument.
    -

    -

    - Begin loading from url and call onLoad with the parsed response content. -

    - -

    [method:Object parse]( [param:String text] )

    -

    - [page:String text] — The textual pdb structure to parse. -

    -

    - Parse a pdb text and return a JSON structure.
    -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PDBLoader.js examples/jsm/loaders/PDBLoader.js] -

    - - diff --git a/docs/examples/zh/loaders/PRWMLoader.html b/docs/examples/zh/loaders/PRWMLoader.html deleted file mode 100644 index bb3ca6f0a9b5fb..00000000000000 --- a/docs/examples/zh/loaders/PRWMLoader.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - [page:Loader] → - -

    [name]

    - -

    A loader for loading a .prwm resource.
    - Packed Raw WebGL Model is an open-source binary file format for nD geometries specifically designed for - JavaScript and WebGL with a strong focus on fast parsing (from 1ms to 0.1ms in Chrome 59 - on a MBP Late 2013). The parsing of PRWM file is especially fast when the endianness of the file is - the same as the endianness of the client platform. More information - on this [link:https://github.com/kchapelier/PRWM here]. -

    - -

    代码示例

    - - - // instantiate a loader - const loader = new PRWMLoader(); - - // load a resource - loader.load( - // resource URL - 'models/nefertiti.le.prwm', - // called when resource is loaded - function ( bufferGeometry ) { - - const object = new THREE.Mesh( bufferGeometry, new THREE.MeshNormalMaterial() ); - scene.add( object ); - - }, - // called when loading is in progresses - function ( xhr ) { - - console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' ); - - }, - // called when loading has errors - function ( error ) { - - console.log( 'An error happened' ); - - } - ); - - -

    例子

    -

    - [example:webgl_loader_prwm] -

    - -

    Constructor

    - -

    [name]( [param:LoadingManager manager] )

    -

    - [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. -

    -

    - Creates a new [name]. -

    - -

    Properties

    -

    See the base [page:Loader] class for common properties.

    - -

    Methods

    -

    See the base [page:Loader] class for common methods.

    - -

    [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

    -

    - [page:String url] — A string containing the path/URL of the .prwm file. Any * character in the URL will be automatically replaced by le or be depending on the platform endianness.
    - [page:Function onLoad] — (optional) A function to be called after the loading is successfully completed. The function receives the loaded [page:BufferGeometry] as an argument.
    - [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The function receives a XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes.
    - [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.
    -

    -

    - Begin loading from url and call onLoad with the parsed response content. -

    - -

    [method:BufferGeometry parse]( [param:ArrayBuffer arrayBuffer] )

    -

    - [page:ArrayBuffer arrayBuffer] — ArrayBuffer containing the prwm data. -

    -

    - Parse a prwm file passed as an ArrayBuffer and directly return an instance of [page:BufferGeometry]. -

    - -

    PRWMLoader.isBigEndianPlatform( )

    - -

    - Return true if the endianness of the platform is Big Endian, false otherwise. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PRWMLoader.js examples/jsm/loaders/PRWMLoader.js] -

    - - - diff --git a/docs/examples/zh/loaders/SVGLoader.html b/docs/examples/zh/loaders/SVGLoader.html index 272b58a21d4a1e..709ca254ef2960 100644 --- a/docs/examples/zh/loaders/SVGLoader.html +++ b/docs/examples/zh/loaders/SVGLoader.html @@ -11,10 +11,21 @@

    [name]

    -

    A loader for loading a .svg resource.
    - [link:https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Scalable Vector Graphics] is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation. +

    用于加载`.svg`资源的加载器
    + [link:https://en.wikipedia.org/wiki/Scalable_Vector_Graphics 可伸缩向量图形]是XML形式的矢量图形格式,用来描述二维矢量图形并支持交互和动画。

    +

    引用

    + +

    + [name]是附加功能,必须显示引用。 + 请参考[link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { SVGLoader } from 'three/addons/loaders/SVGLoader.js'; + +

    代码示例

    @@ -72,49 +83,50 @@

    代码示例

    );
    -

    例子

    +

    示例

    [example:webgl_loader_svg]

    -

    Constructor

    +

    构造函数

    [name]( [param:LoadingManager manager] )

    - [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. + [page:LoadingManager manager] — 加载器使用的[page:LoadingManager 加载器管理]。默认值为[page:LoadingManager THREE.DefaultLoadingManager]。

    - Creates a new [name]. + 创建一个新的[name]。

    -

    Properties

    -

    See the base [page:Loader] class for common properties.

    +

    属性

    +

    查看公共属性请参考基类[page:Loader]。

    -

    Methods

    -

    See the base [page:Loader] class for common methods.

    +

    方法

    +

    查看公共方法请参考基类[page:Loader]。

    [method:undefined load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

    - [page:String url] — A string containing the path/URL of the .svg file.
    - [page:Function onLoad] — (optional) A function to be called after loading is successfully completed. The function receives an array of [page:ShapePath] as an argument.
    - [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes.
    - [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives the error as an argument.
    + [page:String url] — 一个`.svg`文件的路径或者网络地址。
    + [page:Function onLoad] — (可选的)加载成功之后调用的函数。该函数以[page:ShapePath]为参数。
    + [page:Function onProgress] — (可选的)正在加载时调用的函数。参数为XMLHttpRequest实例,包含[page:Integer total]和[page:Integer loaded]。 + 如果服务没有设置Content-Length头,.[page:Integer total]的值为0。
    + [page:Function onError] — (可选的)加载出现错误时调用的函数。该函将错误信息作为参数。

    - Begin loading from url and call onLoad with the response content. + 根据请求的URL开始加载并根据返回内容调用onLoad。

    -

    Static Methods

    +

    静态方法

    [method:Array createShapes]( [param:ShapePath shape] )

    - [page:ShapePath shape] — A ShapePath from the array of [page:ShapePath], given as argument in the onLoad function for the load function of [page:SVGLoader].
    + [page:ShapePath shape] — 一个[page:ShapePath]的矢量图形数组,指定[page:SVGLoader]的onLoad函数的参数。

    - Returns one or more [page:Shape] objects created from the [param:ShapePath shape] provided as an argument in this function. + 返回一个或多个基于[param:ShapePath shape]的[page:Shape]对象,并作为该函数的一个参数返回。

    -

    Source

    +

    源码

    [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/SVGLoader.js examples/jsm/loaders/SVGLoader.js] diff --git a/docs/examples/zh/loaders/TGALoader.html b/docs/examples/zh/loaders/TGALoader.html index 38fbd7e67570e2..5fdd09f4b048af 100644 --- a/docs/examples/zh/loaders/TGALoader.html +++ b/docs/examples/zh/loaders/TGALoader.html @@ -11,10 +11,20 @@

    [name]

    -

    A loader for loading a .tga resource.
    - [link:https://en.wikipedia.org/wiki/Truevision_TGA TGA] is a raster graphics, image file format. +

    用于加载`.tga`资源的加载器。
    + [link:https://en.wikipedia.org/wiki/Truevision_TGA TGA]是光栅图形,图形文件格式。

    +

    引用

    + +

    + [name]是附加项,必须显示的引用。请参考[link:#manual/introduction/Installation Installation / Addons]。 +

    + + + import { TGALoader } from 'three/addons/loaders/TGALoader.js'; + +

    代码示例

    @@ -51,39 +61,40 @@

    代码示例

    } );
    -

    例子

    +

    示例

    [example:webgl_loader_texture_tga]

    -

    Constructor

    +

    构造函数

    [name]( [param:LoadingManager manager] )

    - [page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager]. + [page:LoadingManager manager] — 加载器使用的[page:LoadingManager loadingManager]。默认值为[page:LoadingManager THREE.DefaultLoadingManager]。

    - Creates a new [name]. + 创建新的[name].

    -

    Properties

    -

    See the base [page:Loader] class for common properties.

    +

    属性

    +

    查看公共属性请参考基类[page:Loader]。

    -

    Methods

    -

    See the base [page:Loader] class for common methods.

    +

    方法

    +

    查看公共方法请参考基类[page:Loader]。

    [method:DataTexture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )

    - [page:String url] — A string containing the path/URL of the .tga file.
    - [page:Function onLoad] — (optional) A function to be called after loading is successfully completed. The function receives loaded [page:DataTexture] as an argument.
    - [page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains .[page:Integer total] and .[page:Integer loaded] bytes.
    - [page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives the error as an argument.
    + [page:String url] — 一个`.tga`文件的路径或者网络地址。
    + [page:Function onLoad] — (可选的)加载成功之后调用的函数。该函数以[page:DataTexture]为参数。
    + [page:Function onProgress] — (可选的)正在加载时调用的函数。参数为XMLHttpRequest实例,包含[page:Integer total]和[page:Integer loaded]。 + 如果服务没有设置Content-Length头,.[page:Integer total]的值为0。
    + [page:Function onError] — (可选的)加载出现错误时调用的函数。该函将错误信息作为参数。

    - Begin loading from url and pass the loaded [page:DataTexture texture] to onLoad. The [page:DataTexture texture] is also directly returned for immediate use (but may not be fully loaded). + 开始加载[page:DataTexture texture]并传递给onLoad。即时引用会将[page:DataTexture texture]直接返回(不一定加载完成)。

    -

    Source

    +

    源码

    [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/TGALoader.js examples/jsm/loaders/TGALoader.js] diff --git a/docs/examples/zh/math/Lut.html b/docs/examples/zh/math/Lut.html deleted file mode 100644 index 10da356c661bdf..00000000000000 --- a/docs/examples/zh/math/Lut.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - -

    查找表([name])

    - -

    - 表示颜色表的查找表,用于从一个数据值的范围中确定颜色值。 -

    - - -

    代码示例

    - - const lut = new Lut( 'rainbow', 512 ); - const color = lut.getColor( 0.5 ); - - -

    构造函数

    - - -

    [name]( [param:String colormap], [param:Number count] )

    -

    - colormap - Sets a colormap from predefined colormaps. Available colormaps are: *rainbow*, *cooltowarm*, *blackbody*, *grayscale*. Default is *rainbow*.
    - count - Sets the number of colors used to represent the data array. Default is *32*. -

    - -

    属性

    - -

    [property:Array lut]

    -

    - The lookup table for the selected color map represented as an array of [page:Color]s. -

    - -

    [property:Array map]

    -

    - The currently selected color map. Default is the *rainbow* color map. -

    - -

    [property:Number minV]

    -

    - The minimum value to be represented with the lookup table. Default is *0*. -

    - -

    [property:Number maxV]

    -

    - The maximum value to be represented with the lookup table. Default is *1*. -

    - -

    [property:Number n]

    -

    - The number of colors of the current selected color map. Default is *32*. -

    - -

    方法

    - -

    [method:this copy]( [param:Lut lut] ) [param:Lut this]

    -

    - color — Lut to copy. -

    -

    - Copies the given lut. -

    - -

    [method:this addColorMap]( [param:String name], [param:Array arrayOfColors] )

    -

    - name — The name of the color map.
    - arrayOfColors — An array of color values. Each value is an array holding a threshold and the actual color value as a hexadecimal number. -

    -

    - Adds a color map to this [name] instance. -

    - -

    [method:HTMLCanvasElement createCanvas]()

    -

    - Creates a canvas in order to visualize the lookup table as a texture. -

    - -

    [method:Color getColor]( [param:Number alpha] )

    -

    - value -- the data value to be displayed as a color. -

    -

    - Returns an instance of [page:Color] for the given data value. -

    - -

    [method:this setColorMap]( [param:String colormap], [param:Number count] )

    -

    - colormap — The name of the color map.
    - count — The number of colors. Default is *32*. -

    -

    - Configure the lookup table for the given color map and number of colors. -

    - -

    [method:this setMin]( [param:Number minV] )

    -

    - minV — The minimum value to be represented with the lookup table -

    -

    - Sets this Lut with the minimum value to be represented. -

    - -

    [method:this setMax]( [param:Number maxV] )

    -

    - maxV — The maximum value to be represented with the lookup table. -

    -

    - Sets this Lut with the maximum value to be represented. -

    - -

    [method:HTMLCanvasElement updateCanvas]( [param:HTMLCanvasElement canvas] )

    -

    - Updates the canvas with the [name]'s data. -

    - -

    源码

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/Lut.js examples/jsm/math/Lut.js] -

    - - diff --git a/docs/examples/zh/math/MeshSurfaceSampler.html b/docs/examples/zh/math/MeshSurfaceSampler.html deleted file mode 100644 index bad7dd2b8a2711..00000000000000 --- a/docs/examples/zh/math/MeshSurfaceSampler.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    Utility class for sampling weighted random points on the surface of a mesh.

    - -

    Weighted sampling is useful for effects like heavier foliage growth in certain areas of terrain, or concentrated particle emissions from specific parts of a mesh. Vertex weights may be written programmatically, or painted by hand as vertex colors in 3D tools like Blender.

    - -

    代码示例

    - - - // Create a sampler for a Mesh surface. - const sampler = new MeshSurfaceSampler( surfaceMesh ) - .setWeightAttribute( 'color' ) - .build(); - - const sampleMesh = new THREE.InstancedMesh( sampleGeometry, sampleMaterial, 100 ); - - const _position = new THREE.Vector3(); - const _matrix = new THREE.Matrix4(); - - // Sample randomly from the surface, creating an instance of the sample - // geometry at each sample point. - for ( let i = 0; i < 100; i ++ ) { - - sampler.sample( _position ); - - _matrix.makeTranslation( _position.x, _position.y, _position.z ); - - mesh.setMatrixAt( i, _matrix ); - - } - - mesh.instanceMatrix.needsUpdate = true; - - scene.add( mesh ); - - -

    例子

    -

    - [example:webgl_instancing_scatter] -

    - -

    Constructor

    - -

    [name]( [param:Mesh mesh] )

    -

    - [page:Mesh mesh] — Surface mesh from which to sample. -

    -

    - Creates a new [name]. If the input geometry is indexed, a non-indexed copy is made. After construction, the sampler is not able to return samples until [page:MeshSurfaceSampler.build build] is called. -

    - -

    Methods

    - -

    [method:this setWeightAttribute]( [param:String name] )

    -

    - Specifies a vertex attribute to be used as a weight when sampling from the surface. Faces with higher weights are more likely to be sampled, and those with weights of zero will not be sampled at all. For vector attributes, only .x is used in sampling. -

    -

    If no weight attribute is selected, sampling is randomly distributed by area.

    - -

    [method:this build]()

    -

    - Processes the input geometry and prepares to return samples. Any configuration of the geometry or sampler must occur before this method is called. Time complexity is O(n) for a surface with n faces. -

    - -

    [method:this sample]( [param:Vector3 targetPosition], [param:Vector3 targetNormal], [param:Color targetColor] )

    -

    - Selects a random point on the surface of the input geometry, returning the position and optionally the normal vector and color at that point. Time complexity is O(log n) for a surface with n faces.

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/MeshSurfaceSampler.js examples/jsm/math/MeshSurfaceSampler.js] -

    - - diff --git a/docs/examples/zh/math/OBB.html b/docs/examples/zh/math/OBB.html deleted file mode 100644 index d3e1ce902951b7..00000000000000 --- a/docs/examples/zh/math/OBB.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - Represents an oriented bounding box (OBB) in 3D space. -

    - -

    Examples

    -

    - [example:webgl_math_obb] -

    - -

    Constructor

    - -

    [name]( [param:Vector3 center], [param:Vector3 halfSize], [param:Matrix3 rotation] )

    -

    - [page:Vector3 center] — The center of the [name]. (optional)
    - [page:Vector3 halfSize] — Positive halfwidth extents of the [name] along each axis. (optional)
    - [page:Matrix3 rotation] — The rotation of the [name]. (optional) -

    -

    - Creates a new [name]. -

    - -

    Properties

    - -

    [property:Vector3 center]

    -

    - The center of the [name]. Default is *( 0, 0, 0 )*. -

    - -

    [property:Vector3 halfSize]

    -

    - Positive halfwidth extents of the [name] along each axis. Default is *( 0, 0, 0 )*. -

    - -

    [property:Matrix3 rotation]

    -

    - The rotation of the [name]. Default is the identity matrix. -

    - -

    Methods

    - -

    [method:this applyMatrix4]( [param:Matrix4 matrix] )

    -

    - [page:Matrix4 matrix] — A 4x4 transformation matrix. -

    -

    - Applies the given transformation matrix to this [name]. This method can be used to transform the - bounding volume with the world matrix of a 3D object in order to keep both entities in sync. -

    - -

    [method:Vector3 clampPoint]( [param:Vector3 point], [param:Vector3 clampedPoint] )

    -

    - [page:Vector3 point] — The point that should be clamped within the bounds of this [name].
    - [page:Matrix3 clampedPoint] — The result will be copied into this vector. -

    -

    - Clamps the given point within the bounds of this [name]. -

    - -

    [method:OBB clone]()

    -

    - Creates a cloned [name] for this instance. -

    - -

    [method:Boolean containsPoint]( [param:Vector3 point] )

    -

    - [page:Vector3 point] — The point to test. -

    -

    - Whether the given point lies within this [name] or not. -

    - -

    [method:this copy]( [param:OBB obb] )

    -

    - [page:OBB obb] — The [name] to copy. -

    -

    - Copies the properties of the given [name] to this [name]. -

    - -

    [method:Boolean equals]( [param:OBB obb] )

    -

    - [page:OBB obb] — The [name] to test. -

    -

    - Whether the given [name] is equal to this [name] or not. -

    - -

    [method:this fromBox3]( [param:Box3 box3] )

    -

    - [page:Box3 box3] — An AABB. -

    -

    - Defines an [name] based on the given AABB. -

    - -

    [method:Vector3 getSize]( [param:Vector3 size] )

    -

    - [page:Vector3 size] — The result will be copied into this vector. -

    -

    - Returns the size of this [name] into the given vector. -

    - -

    [method:Boolean intersectsBox3]( [param:Box3 box3] )

    -

    - [page:Box3 box3] — The AABB to test. -

    -

    - Whether the given AABB intersects this [name] or not. -

    - -

    [method:Boolean intersectsSphere]( [param:Sphere sphere] )

    -

    - [page:Sphere sphere] — The bounding sphere to test. -

    -

    - Whether the given bounding sphere intersects this [name] or not. -

    - -

    [method:Boolean intersectsOBB]( [param:OBB obb], [param:Number epsilon] )

    -

    - [page:OBB obb] — The OBB to test.
    - [page:Number epsilon] — An optional numeric value to counteract arithmetic errors. Default is *Number.EPSILON*. -

    -

    - Whether the given [name] intersects this [name] or not. -

    - -

    [method:Boolean intersectsRay]( [param:Ray ray] )

    -

    - [page:Ray ray] — The ray to test. -

    -

    - Whether the given ray intersects this [name] or not. -

    - -

    [method:Vector3 intersectRay]( [param:Ray ray], [param:Vector3 intersectionPoint] )

    -

    - [page:Ray ray] — The ray to test.
    - [page:Vector3 intersectionPoint] — The result will be copied into this vector. -

    -

    - Performs a Ray/OBB intersection test and stores the intersection point to the given 3D vector. - If no intersection is detected, *null* is returned. -

    - -

    [method:this set]( [param:Vector3 center], [param:Vector3 halfSize], [param:Matrix3 rotation] )

    -

    - [page:Vector3 center] — The center of the [name].
    - [page:Vector3 halfSize] — Positive halfwidth extents of the [name] along each axis.
    - [page:Matrix3 rotation] — The rotation of the [name]. -

    -

    - Defines the [name] for the given values. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/OBB.js examples/jsm/math/OBB.js] -

    - - diff --git a/docs/examples/zh/math/convexhull/ConvexHull.html b/docs/examples/zh/math/convexhull/ConvexHull.html deleted file mode 100644 index cb71ff5f7369eb..00000000000000 --- a/docs/examples/zh/math/convexhull/ConvexHull.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - A convex hull class. Implements the Quickhull algorithm by: Dirk Gregorius. March 2014, Game Developers Conference: [link:http://media.steampowered.com/apps/valve/2014/DirkGregorius_ImplementingQuickHull.pdf Implementing QuickHull]. -

    - - -

    Constructor

    - - -

    [name]()

    -

    - Creates a new instance of [name]. -

    - -

    Properties

    - -

    [property:VertexList assigned]

    -

    - This [page:VertexList vertex list] holds all vertices that are assigned to a face. Default is an empty vertex list. -

    - -

    [property:Array faces]

    -

    - The generated faces of the convex hull. Default is an empty array. -

    - -

    [property:Array newFaces]

    -

    - This array holds the faces that are generated within a single iteration. Default is an empty array. -

    - -

    [property:Float tolerance]

    -

    - The epsilon value that is used for internal comparative operations. The calculation of this value depends on the size of the geometry. Default is -1. -

    - -

    [property:VertexList unassigned]

    -

    - This [page:VertexList vertex list] holds all vertices that are not assigned to a face. Default is an empty vertex list. -

    - -

    [property:Array vertices]

    -

    - The internal representation of the given geometry data (an array of [page:VertexNode vertices]). -

    - -

    Methods

    - -

    [method:HalfEdge addAdjoiningFace]( [param:VertexNode eyeVertex], [param:HalfEdge horizonEdge] )

    -

    - [page:VertexNode eyeVertex] - The vertex that is added to the hull.
    - [page:HalfEdge horizonEdge] - A single edge of the horizon.

    - - Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order. - All the half edges are created in CCW order thus the face is always pointing outside the hull -

    - -

    [method:this addNewFaces]( [param:VertexNode eyeVertex], [param:HalfEdge horizonEdge] )

    -

    - [page:VertexNode eyeVertex] - The vertex that is added to the hull.
    - [page:HalfEdge horizon] - An array of half-edges that form the horizon.

    - - Adds 'horizon.length' faces to the hull, each face will be linked with the horizon opposite face and the face on the left/right. -

    - -

    [method:this addVertexToFace]( [param:VertexNode vertex], [param:Face face] )

    -

    - [page:VertexNodeNode vertex] - The vertex to add.
    - [page:Face face] - The target face.

    - - Adds a vertex to the 'assigned' list of vertices and assigns it to the given face. -

    - -

    [method:this addVertexToHull]( [param:VertexNode eyeVertex] )

    -

    - [page:VertexNode eyeVertex] - The vertex that is added to the hull.

    - - Adds a vertex to the hull with the following algorithm -

      -
    • Compute the 'horizon' which is a chain of half edges. For an edge to belong to this group it must be the edge connecting a face that can see 'eyeVertex' and a face which cannot see 'eyeVertex'.
    • -
    • All the faces that can see 'eyeVertex' have its visible vertices removed from the assigned vertex list.
    • -
    • A new set of faces is created with each edge of the 'horizon' and 'eyeVertex'. Each face is connected with the opposite horizon face and the face on the left/right.
    • -
    • The vertices removed from all the visible faces are assigned to the new faces if possible.
    • -
    -

    - -

    [method:this cleanup]()

    - -

    Cleans up internal properties after computing the convex hull.

    - -

    [method:this compute]()

    - -

    Starts the execution of the quick hull algorithm.

    - -

    [method:Object computeExtremes]()

    - -

    Computes the extremes values (min/max vectors) which will be used to compute the inital hull.

    - -

    [method:this computeHorizon]( [param:Vector3 eyePoint], [param:HalfEdge crossEdge], [param:Face face], [param:Array horizon] )

    -

    - [page:Vector3 eyePoint] - The 3D-coordinates of a point.
    - [page:HalfEdge crossEdge] - The edge used to jump to the current face.
    - [page:Face face] - The current face being tested.
    - [page:Array horizon] - The edges that form part of the horizon in CCW order.

    - - Computes a chain of half edges in CCW order called the 'horizon'. For an edge to be part of the horizon it must join a face that can see 'eyePoint' and a face that cannot see 'eyePoint'. -

    - -

    [method:this computeInitialHull]()

    - -

    Computes the initial simplex assigning to its faces all the points that are candidates to form part of the hull.

    - -

    [method:this containsPoint]( [param:Vector3 point] )

    -

    - [page:Vector3 point] - A point in 3D space.

    - - Returns *true* if the given point is inside this convex hull. -

    - -

    [method:this deleteFaceVertices]( [param:Face face], [param:Face absorbingFace] )

    -

    - [page:Face face] - The given face.
    - [page:Face absorbingFace] - An optional face that tries to absorb the vertices of the first face.

    - - Removes all the visible vertices that 'face' is able to see. -

      -
    • If 'absorbingFace' doesn't exist, then all the removed vertices will be added to the 'unassigned' vertex list.
    • -
    • If 'absorbingFace' exists, then this method will assign all the vertices of 'face' that can see 'absorbingFace'.
    • -
    • If a vertex cannot see 'absorbingFace', it's added to the 'unassigned' vertex list.
    • -
    -

    - -

    [method:Vector3 intersectRay]( [param:Ray ray], [param:Vector3 target] )

    -

    - [page:Ray ray] - The given ray.
    - [page:Vector3 target] - The target vector representing the intersection point.

    - - Performs a ray intersection test with this convext hull. If no intersection is found, *null* is returned. -

    - -

    [method:Boolean intersectsRay]( [param:Ray ray] )

    -

    - [page:Ray ray] - The given ray.

    - - Returns *true* if the given ray intersects with this convex hull. -

    - -

    [method:this makeEmpty]()

    - -

    Makes this convex hull empty.

    - -

    [method:VertexNode nextVertexToAdd]()

    - -

    Finds the next vertex to create faces with the current hull. -

      -
    • Let the initial face be the first face existing in the 'assigned' vertex list.
    • -
    • If a face doesn't exist then return since there're no vertices left.
    • -
    • Otherwise for each vertex that face sees find the one furthest away from it.
    • -
    -

    - -

    [method:this reindexFaces]()

    - -

    Removes inactive (e.g. deleted) faces from the internal face list.

    - -

    [method:VertexNode removeAllVerticesFromFace]( [param:Face face] )

    -

    - [page:Face face] - The given face.

    - - Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertex list. -

    - -

    [method:this removeVertexFromFace]( [param:VertexNode vertex], [param:Face face] )

    -

    - [page:VertexNode vertex] - The vertex to remove.
    - [page:Face face] - The target face.

    - - Removes a vertex from the 'assigned' list of vertices and from the given face. It also makes sure that the link from 'face' to the first vertex it sees in 'assigned' is linked correctly after the removal. -

    - -

    [method:this resolveUnassignedPoints]( [param:Array newFaces] )

    -

    - [page:Face newFaces] - An array of new faces.

    - - Reassigns as many vertices as possible from the unassigned list to the new faces. -

    - -

    [method:this setFromObject]( [param:Object3D object] )

    -

    - [page:Object3D object] - [page:Object3D] to compute the convex hull of.

    - - Computes the convex hull of an [page:Object3D] (including its children),accounting for the world transforms of both the object and its childrens. -

    - -

    [method:this setFromPoints]( [param:Array points] )

    -

    - [page:Array points] - Array of [page:Vector3 Vector3s] that the resulting convex hull will contain.

    - - Computes to convex hull for the given array of points. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js] -

    - - diff --git a/docs/examples/zh/math/convexhull/Face.html b/docs/examples/zh/math/convexhull/Face.html deleted file mode 100644 index ff88d28edca285..00000000000000 --- a/docs/examples/zh/math/convexhull/Face.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - Represents a section bounded by a specific amount of half-edges. The current implmentation assumes that a face always consist of three edges. -

    - - -

    Constructor

    - - -

    [name]()

    -

    - Creates a new instance of [name]. -

    - -

    Properties

    - -

    [property:Vector3 normal]

    -

    - The normal vector of the face. Default is a [page:Vector3] at (0, 0, 0). -

    - -

    [property:Vector3 midpoint]

    -

    - The midpoint or centroid of the face. Default is a [page:Vector3] at (0, 0, 0). -

    - -

    [property:Float area]

    -

    - The area of the face. Default is 0. -

    - -

    [property:Float constant]

    -

    - Signed distance from face to the origin. Default is 0. -

    - -

    [property:VertexNode outside]

    -

    - Reference to a vertex in a vertex list this face can see. Default is null. -

    - -

    [property:Integer mark]

    -

    - Marks if a face is visible or deleted. Default is 'Visible'. -

    - -

    [property:HalfEdge edge]

    -

    - Reference to the base edge of a face. To retrieve all edges, you can use the 'next' reference of the current edge. Default is null. -

    - -

    Methods

    - -

    [method:Face create]( [param:VertexNode a], [param:VertexNode b], [param:VertexNode c] )

    -

    - [page:VertexNode a] - First vertex of the face.
    - [page:VertexNode b] - Second vertex of the face.
    - [page:VertexNode c] - Third vertex of the face.

    - - Creates a face. -

    - -

    [method:HalfEdge getEdge]( [param:Integer i] )

    -

    - [page:Integer i] - The index of the edge.

    - - Returns an edge by the given index. -

    - -

    [method:this compute] ()

    - -

    Computes all properties of the face.

    - -

    [method:Float distanceToPoint]( [param:Vector3 point] )

    -

    - [page:Vector3 point] - Any point in 3D space.

    - - Returns the signed distance from a given point to the plane representation of this face. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js] -

    - - diff --git a/docs/examples/zh/math/convexhull/HalfEdge.html b/docs/examples/zh/math/convexhull/HalfEdge.html deleted file mode 100644 index 3e2e6fefbe387e..00000000000000 --- a/docs/examples/zh/math/convexhull/HalfEdge.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - The basis for a half-edge data structure, also known as doubly connected edge list (DCEL).
    -

    - - -

    Constructor

    - - -

    [name]( [param:VertexNode vertex], [param:Face face] )

    -

    - [page:VertexNode vertex] - [page:VertexNode] A reference to its destination vertex.
    - [page:Face face] - [page:Face] A reference to its face.

    - - Creates a new instance of [name]. -

    -

    Properties

    - -

    [property:VertexNode vertex]

    -

    - Reference to the destination vertex. The origin vertex can be obtained by querying the destination of its twin, or of the previous half-edge. Default is undefined. -

    - -

    [property:HalfEdge prev]

    -

    - Reference to the previous half-edge of the same face. Default is null. -

    - -

    [property:HalfEdge next]

    -

    - Reference to the next half-edge of the same face. Default is null. -

    - -

    [property:HalfEdge twin]

    -

    - Reference to the twin half-edge to reach the opposite face. Default is null. -

    - -

    [property:Face face]

    -

    - Each half-edge bounds a single face and thus has a reference to that face. Default is undefined. -

    - -

    Methods

    - -

    [method:VertexNode head]()

    -

    Returns the destination vertex.

    - -

    [method:VertexNode tail]()

    -

    Returns the origin vertex.

    - -

    [method:Float length]()

    -

    Returns the [link:https://en.wikipedia.org/wiki/Euclidean_distance Euclidean length] - (straight-line length) of the edge.

    - -

    [method:Float lengthSquared]()

    -

    Returns the square of the [link:https://en.wikipedia.org/wiki/Euclidean_distance Euclidean length] - (straight-line length) of the edge.

    - -

    [method:this setTwin]( [param:HalfEdge edge] )

    -

    - [page:HalfEdge edge] - Any half-edge.

    - - Sets the twin edge of this half-edge. It also ensures that the twin reference of the given half-edge is correctly set. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js] -

    - - diff --git a/docs/examples/zh/math/convexhull/VertexList.html b/docs/examples/zh/math/convexhull/VertexList.html deleted file mode 100644 index 98b397243e4405..00000000000000 --- a/docs/examples/zh/math/convexhull/VertexList.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - A doubly linked list of vertices. -

    - - -

    Constructor

    - - -

    [name]()

    -

    - Creates a new instance of [name]. -

    - -

    Properties

    - -

    [property:VertexNode head]

    -

    - Reference to the first vertex of the linked list. Default is null. -

    - -

    [property:VertexNode tail]

    -

    - Reference to the last vertex of the linked list. Default is null. -

    - -

    Methods

    - -

    [method:VertexNode first]()

    -

    Returns the head reference.

    - -

    [method:VertexNode last]()

    -

    Returns the tail reference.

    - -

    [method:this clear]()

    -

    Clears the linked list.

    - -

    [method:this insertBefore]( [param:Vertex target], [param:Vertex vertex] )

    -

    - [page:Vertex target] - The target vertex. It's assumed that this vertex belongs to the linked list.
    - [page:Vertex vertex] - The vertex to insert.

    - - Inserts a vertex before a target vertex. -

    - -

    [method:this insertAfter]( [param:Vertex target], [param:Vertex vertex] )

    -

    - [page:Vertex target] - The target vertex. It's assumed that this vertex belongs to the linked list.
    - [page:Vertex vertex] - The vertex to insert.

    - - Inserts a vertex after a target vertex. -

    - -

    [method:this append]( [param:Vertex vertex] )

    -

    - [page:Vertex vertex] - The vertex to append.

    - - Appends a vertex to the end of the linked list. -

    - -

    [method:this appendChain]( [param:Vertex vertex] )

    -

    - [page:Vertex vertex] - The head vertex of a chain of vertices.

    - - Appends a chain of vertices where the given vertex is the head. -

    - -

    [method:this remove]( [param:Vertex vertex] )

    -

    - [page:Vertex vertex] - The vertex to remove.

    - - Removes a vertex from the linked list. -

    - -

    [method:this removeSubList]( [param:Vertex a], [param:Vertex b] )

    -

    - [page:Vertex a] - The head of the sublist.
    - [page:Vertex b] - The tail of the sublist.

    - - Removes a sublist of vertices from the linked list. -

    - -

    [method:Boolean isEmpty]()

    - -

    Returns true if the linked list is empty.

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js] -

    - - diff --git a/docs/examples/zh/math/convexhull/VertexNode.html b/docs/examples/zh/math/convexhull/VertexNode.html deleted file mode 100644 index 49c906a24a09a2..00000000000000 --- a/docs/examples/zh/math/convexhull/VertexNode.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - A vertex as a double linked list node. -

    - - -

    Constructor

    - - -

    [name]( [param:Vector3 point] )

    -

    - [page:Vector3 point] - [page:Vector3] A point (x, y, z) in 3D space.

    - - Creates a new instance of [name]. -

    - -

    Properties

    - -

    [property:Vector3 point]

    -

    - A point (x, y, z) in 3D space. Default is undefined. -

    - -

    [property:VertexNode prev]

    -

    - Reference to the previous vertex in the double linked list. Default is null. -

    - -

    [property:VertexNode next]

    -

    - Reference to the next vertex in the double linked list. Default is null. -

    - -

    [property:Face face]

    -

    - Reference to the face that is able to see this vertex. Default is undefined. -

    - -

    Source

    - -

    - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js] -

    - - diff --git a/docs/examples/zh/objects/Lensflare.html b/docs/examples/zh/objects/Lensflare.html index 92b7f56bb9a2ac..889bb915c97db7 100644 --- a/docs/examples/zh/objects/Lensflare.html +++ b/docs/examples/zh/objects/Lensflare.html @@ -15,6 +15,15 @@

    镜头光晕([name])

    创建一个模拟追踪着灯光的镜头光晕。 [name] can only be used when setting the *alpha* context parameter of [page:WebGLRenderer] to *true*.

    +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { Lensflare } from 'three/addons/objects/Lensflare.js'; + +

    代码示例

    diff --git a/docs/examples/zh/postprocessing/EffectComposer.html b/docs/examples/zh/postprocessing/EffectComposer.html index 89a07bb649eb0e..e70af3b73aedec 100644 --- a/docs/examples/zh/postprocessing/EffectComposer.html +++ b/docs/examples/zh/postprocessing/EffectComposer.html @@ -15,6 +15,17 @@

    效果合成器([name])

    后期处理过程根据它们添加/插入的顺序来执行,最后一个过程会被自动渲染到屏幕上。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; + +

    例子

    diff --git a/docs/examples/zh/renderers/CSS2DRenderer.html b/docs/examples/zh/renderers/CSS2DRenderer.html index 80c94a963ebb77..29a70c39c51952 100644 --- a/docs/examples/zh/renderers/CSS2DRenderer.html +++ b/docs/examples/zh/renderers/CSS2DRenderer.html @@ -10,9 +10,21 @@

    CSS 2D渲染器([name])

    [name]是[page:CSS3DRenderer](CSS 3D渲染器)的简化版本,唯一支持的变换是位移。

    - 如果你希望将三维物体和基于HTML的标签相结合,则这一渲染器将十分有用。在这里,各个DOM元素也被包含到一个*CSS2DObject*实例中,并被添加到场景图中。
    + 如果你希望将三维物体和基于HTML的标签相结合,则这一渲染器将十分有用。在这里,各个DOM元素也被包含到一个*CSS2DObject*实例中,并被添加到场景图中。

    + `[name]` only supports 100% browser and display zoom.

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { CSS2DRenderer } from 'three/addons/renderers/CSS2DRenderer.js'; + +

    例子

    diff --git a/docs/examples/zh/renderers/CSS3DRenderer.html b/docs/examples/zh/renderers/CSS3DRenderer.html index 46d24e576c88cc..ce80d98351b99c 100644 --- a/docs/examples/zh/renderers/CSS3DRenderer.html +++ b/docs/examples/zh/renderers/CSS3DRenderer.html @@ -19,10 +19,22 @@

    CSS 3D渲染器([name])

    • 它不可能使用*three.js*中的材质系统。
    • 同时也不可能使用几何体。
    • +
    • `[name]` only supports 100% browser and display zoom.
    因此,[name]仅仅关注普通的DOM元素,这些元素被包含到了特殊的对象中(*CSS3DObject*或者*CSS3DSprite*),然后被加入到场景图中。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { CSS3DRenderer } from 'three/addons/renderers/CSS3DRenderer.js'; + +

    例子

    diff --git a/docs/examples/zh/renderers/SVGRenderer.html b/docs/examples/zh/renderers/SVGRenderer.html index 2872e32f2b95db..869aaa95d3d557 100644 --- a/docs/examples/zh/renderers/SVGRenderer.html +++ b/docs/examples/zh/renderers/SVGRenderer.html @@ -33,6 +33,17 @@

    SVG渲染器([name])

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { SVGRenderer } from 'three/addons/renderers/SVGRenderer.js'; + +

    例子

    diff --git a/docs/examples/zh/utils/BufferGeometryUtils.html b/docs/examples/zh/utils/BufferGeometryUtils.html index 0b1c7701e40fe3..4e8c9bbc3ad9bc 100644 --- a/docs/examples/zh/utils/BufferGeometryUtils.html +++ b/docs/examples/zh/utils/BufferGeometryUtils.html @@ -13,6 +13,16 @@

    [name]

    一个包含 [page:BufferGeometry BufferGeometry] 实例的实用方法的类。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js'; +

    方法

    @@ -74,7 +84,7 @@

    [method:InterleavedBufferAttribute interleaveAttributes]( [param:Array attri

    -

    [method:BufferAttribute mergeBufferAttributes]( [param:Array attributes] )

    +

    [method:BufferAttribute mergeAttributes]( [param:Array attributes] )

    attributes -- 由 [page:BufferAttribute BufferAttribute] 实例组成的数组。

    @@ -83,7 +93,7 @@

    [method:BufferAttribute mergeBufferAttributes]( [param:Array attributes] ) -

    [method:BufferGeometry mergeBufferGeometries]( [param:Array geometries], [param:Boolean useGroups] )

    +

    [method:BufferGeometry mergeGeometries]( [param:Array geometries], [param:Boolean useGroups] )

    geometries -- 由 [page:BufferGeometry BufferGeometry] 实例的数组。
    useGroups -- 是否要为了合并几何体而产生组。

    diff --git a/docs/examples/zh/utils/SceneUtils.html b/docs/examples/zh/utils/SceneUtils.html index 2e8b1369823c19..9042684cf787e4 100644 --- a/docs/examples/zh/utils/SceneUtils.html +++ b/docs/examples/zh/utils/SceneUtils.html @@ -11,6 +11,16 @@

    场景工具([name])

    一个用于操控场景的实用类。

    +

    进口

    + +

    + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons]. +

    + + + import { SceneUtils } from 'three/addons/utils/SceneUtils.js'; +

    方法

    diff --git a/docs/examples/zh/utils/SkeletonUtils.html b/docs/examples/zh/utils/SkeletonUtils.html index 7f4de0e3366dad..a84332bd5a636a 100644 --- a/docs/examples/zh/utils/SkeletonUtils.html +++ b/docs/examples/zh/utils/SkeletonUtils.html @@ -11,36 +11,23 @@

    骨架工具([name])

    用于操控 [page:Skeleton]、 [page:SkinnedMesh]、和 [page:Bone] 的实用方法。

    -

    方法

    +

    进口

    -

    [method:Object3D clone]( [param:Object3D object] )

    - 克隆给定对象及其后代,确保任何 [page:SkinnedMesh] 实例都与其骨骼正确关联。同时,骨骼也会被克隆,且必须是传递给此方法的物体的后代。而其他数据,如几何形状和材料,是通过引用来实现重复使用的。 + [name] 是一个附加组件,必须显式导入。 + See [link:#manual/introduction/Installation Installation / Addons].

    -

    [method:Object findBoneTrackData]( [param:String name], [param:Array tracks] )

    -

    - -

    [method:Bone getBoneByName]( [param:String name], [param:Skeleton skeleton] )

    -

    + + import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js'; + -

    [method:Array getBones]( [param:Skeleton skeleton] )

    -

    - -

    [method:Array getEqualsBonesNames]( [param:Skeleton skeleton], [param:Skeleton targetSkeleton] )

    -

    - -

    [method:SkeletonHelper getHelperFromSkeleton]( [param:Skeleton skeleton] )

    -

    - -

    [method:Bone getNearestBone]( [param:Bone bone], [param:Array names] )

    -

    - -

    [method:Object getSkeletonOffsets]( [param:SkeletonHelper target], [param:SkeletonHelper source], [param:Object options] )

    -

    +

    方法

    -

    [method:this renameBones]( [param:Skeleton skeleton], [param:Array names] )

    -

    +

    [method:Object3D clone]( [param:Object3D object] )

    +

    + 克隆给定对象及其后代,确保任何 [page:SkinnedMesh] 实例都与其骨骼正确关联。同时,骨骼也会被克隆,且必须是传递给此方法的物体的后代。而其他数据,如几何形状和材料,是通过引用来实现重复使用的。 +

    [method:undefined retarget]( [param:SkeletonHelper target], [param:SkeletonHelper source], [param:Object options] )

    diff --git a/docs/index.html b/docs/index.html index 82213ad02af8c0..31f01fdea99811 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,7 +8,10 @@ - +
    diff --git a/docs/list.json b/docs/list.json index 6e1612d655d642..8ce2314ccb2198 100644 --- a/docs/list.json +++ b/docs/list.json @@ -5,10 +5,9 @@ "Manual": { "Getting Started": { - "Creating a scene": "manual/en/introduction/Creating-a-scene", "Installation": "manual/en/introduction/Installation", + "Creating a scene": "manual/en/introduction/Creating-a-scene", "WebGL compatibility check": "manual/en/introduction/WebGL-compatibility-check", - "How to run things locally": "manual/en/introduction/How-to-run-things-locally", "Drawing lines": "manual/en/introduction/Drawing-lines", "Creating text": "manual/en/introduction/Creating-text", "Loading 3D models": "manual/en/introduction/Loading-3D-models", @@ -18,17 +17,13 @@ }, "Next Steps": { - "How to update things": "manual/en/introduction/How-to-update-things", - "How to dispose of objects": "manual/en/introduction/How-to-dispose-of-objects", - "How to create VR content": "manual/en/introduction/How-to-create-VR-content", - "How to use post-processing": "manual/en/introduction/How-to-use-post-processing", + "Updating resources": "manual/en/introduction/How-to-update-things", + "Disposing resources": "manual/en/introduction/How-to-dispose-of-objects", + "Creating VR content": "manual/en/introduction/How-to-create-VR-content", + "Post-processing": "manual/en/introduction/How-to-use-post-processing", "Matrix transformations": "manual/en/introduction/Matrix-transformations", "Animation system": "manual/en/introduction/Animation-system", "Color management": "manual/en/introduction/Color-management" - }, - - "Build Tools": { - "Testing with NPM": "manual/en/buildTools/Testing-with-NPM" } }, @@ -340,6 +335,7 @@ "DragControls": "examples/en/controls/DragControls", "FirstPersonControls": "examples/en/controls/FirstPersonControls", "FlyControls": "examples/en/controls/FlyControls", + "MapControls": "examples/en/controls/MapControls", "OrbitControls": "examples/en/controls/OrbitControls", "PointerLockControls": "examples/en/controls/PointerLockControls", "TrackballControls": "examples/en/controls/TrackballControls", @@ -377,7 +373,6 @@ "OBJLoader": "examples/en/loaders/OBJLoader", "PCDLoader": "examples/en/loaders/PCDLoader", "PDBLoader": "examples/en/loaders/PDBLoader", - "PRWMLoader": "examples/en/loaders/PRWMLoader", "SVGLoader": "examples/en/loaders/SVGLoader", "TGALoader": "examples/en/loaders/TGALoader" }, @@ -445,10 +440,9 @@ "الكتيب": { "البدء": { - "إنشاء مشهد": "manual/ar/introduction/Creating-a-scene", "التثبيت": "manual/ar/introduction/Installation", + "إنشاء مشهد": "manual/ar/introduction/Creating-a-scene", "فحص توافق WebGL": "manual/ar/introduction/WebGL-compatibility-check", - "كيف تدير الأشياء محليًا": "manual/ar/introduction/How-to-run-things-locally", "رسم خطوط": "manual/ar/introduction/Drawing-lines", "إنشاء نص": "manual/ar/introduction/Creating-text", "تحميل نماذج ثلاثية الأبعاد": "manual/ar/introduction/Loading-3D-models", @@ -463,10 +457,6 @@ "كيفية استخدام المعالجة اللاحقة (post-processing)": "manual/ar/introduction/How-to-use-post-processing", "تحولات المصفوفة (Matrix transformations)": "manual/ar/introduction/Matrix-transformations", "نظام الحركات": "manual/ar/introduction/Animation-system" - }, - - "أدوات البناء": { - "الاختبار مع NPM": "manual/ar/buildTools/Testing-with-NPM" } }, @@ -504,7 +494,95 @@ "Cameras": { "ArrayCamera": "api/ar/cameras/ArrayCamera", "Camera": "api/ar/cameras/Camera", - "CubeCamera": "api/ar/cameras/CubeCamera" + "CubeCamera": "api/ar/cameras/CubeCamera", + "OrthographicCamera": "api/ar/cameras/OrthographicCamera", + "PerspectiveCamera": "api/ar/cameras/PerspectiveCamera", + "StereoCamera": "api/ar/cameras/StereoCamera" + }, + + "Constants": { + "Animation": "api/ar/constants/Animation", + "Core": "api/ar/constants/Core", + "CustomBlendingEquation": "api/ar/constants/CustomBlendingEquations", + "BufferAttributeUsage": "api/ar/constants/BufferAttributeUsage", + "Materials": "api/ar/constants/Materials", + "Renderer": "api/ar/constants/Renderer", + "Textures": "api/ar/constants/Textures" + }, + + "Core": { + "BufferAttribute": "api/ar/core/BufferAttribute", + "BufferGeometry": "api/ar/core/BufferGeometry", + "Clock": "api/ar/core/Clock", + "EventDispatcher": "api/ar/core/EventDispatcher", + "GLBufferAttribute": "api/ar/core/GLBufferAttribute", + "InstancedBufferAttribute": "api/ar/core/InstancedBufferAttribute", + "InstancedBufferGeometry": "api/ar/core/InstancedBufferGeometry", + "InstancedInterleavedBuffer": "api/ar/core/InstancedInterleavedBuffer", + "InterleavedBuffer": "api/ar/core/InterleavedBuffer", + "InterleavedBufferAttribute": "api/ar/core/InterleavedBufferAttribute", + "Layers": "api/ar/core/Layers", + "Object3D": "api/ar/core/Object3D", + "Raycaster": "api/ar/core/Raycaster", + "Uniform": "api/ar/core/Uniform" + }, + + "Core / BufferAttributes": { + "BufferAttribute Types": "api/ar/core/bufferAttributeTypes/BufferAttributeTypes" + }, + + "Extras": { + "DataUtils": "api/ar/extras/DataUtils", + "Earcut": "api/ar/extras/Earcut", + "ImageUtils": "api/ar/extras/ImageUtils", + "PMREMGenerator": "api/ar/extras/PMREMGenerator", + "ShapeUtils": "api/ar/extras/ShapeUtils" + }, + + "Extras / Core": { + "Curve": "api/ar/extras/core/Curve", + "CurvePath": "api/ar/extras/core/CurvePath", + "Interpolations": "api/ar/extras/core/Interpolations", + "Path": "api/ar/extras/core/Path", + "Shape": "api/ar/extras/core/Shape", + "ShapePath": "api/ar/extras/core/ShapePath" + }, + + "Extras / Curves": { + "ArcCurve": "api/ar/extras/curves/ArcCurve", + "CatmullRomCurve3": "api/ar/extras/curves/CatmullRomCurve3", + "CubicBezierCurve": "api/ar/extras/curves/CubicBezierCurve", + "CubicBezierCurve3": "api/ar/extras/curves/CubicBezierCurve3", + "EllipseCurve": "api/ar/extras/curves/EllipseCurve", + "LineCurve": "api/ar/extras/curves/LineCurve", + "LineCurve3": "api/ar/extras/curves/LineCurve3", + "QuadraticBezierCurve": "api/ar/extras/curves/QuadraticBezierCurve", + "QuadraticBezierCurve3": "api/ar/extras/curves/QuadraticBezierCurve3", + "SplineCurve": "api/ar/extras/curves/SplineCurve" + }, + + "Geometries": { + "BoxGeometry": "api/ar/geometries/BoxGeometry", + "CapsuleGeometry": "api/ar/geometries/CapsuleGeometry", + "CircleGeometry": "api/ar/geometries/CircleGeometry", + "ConeGeometry": "api/ar/geometries/ConeGeometry", + "CylinderGeometry": "api/ar/geometries/CylinderGeometry", + "DodecahedronGeometry": "api/ar/geometries/DodecahedronGeometry", + "EdgesGeometry": "api/ar/geometries/EdgesGeometry", + "ExtrudeGeometry": "api/ar/geometries/ExtrudeGeometry", + "IcosahedronGeometry": "api/ar/geometries/IcosahedronGeometry", + "LatheGeometry": "api/ar/geometries/LatheGeometry", + "OctahedronGeometry": "api/ar/geometries/OctahedronGeometry", + "PlaneGeometry": "api/ar/geometries/PlaneGeometry", + "PolyhedronGeometry": "api/ar/geometries/PolyhedronGeometry", + "RingGeometry": "api/ar/geometries/RingGeometry", + "ShapeGeometry": "api/ar/geometries/ShapeGeometry", + "SphereGeometry": "api/ar/geometries/SphereGeometry", + "TetrahedronGeometry": "api/ar/geometries/TetrahedronGeometry", + "TorusGeometry": "api/ar/geometries/TorusGeometry", + "TorusKnotGeometry": "api/ar/geometries/TorusKnotGeometry", + "TubeGeometry": "api/ar/geometries/TubeGeometry", + "WireframeGeometry": "api/ar/geometries/WireframeGeometry" } } @@ -516,10 +594,9 @@ "手册": { "起步": { - "创建一个场景": "manual/zh/introduction/Creating-a-scene", "安装": "manual/zh/introduction/Installation", + "创建一个场景": "manual/zh/introduction/Creating-a-scene", "WebGL兼容性检查": "manual/zh/introduction/WebGL-compatibility-check", - "如何在本地运行Three.js": "manual/zh/introduction/How-to-run-things-locally", "画线": "manual/zh/introduction/Drawing-lines", "创建文字": "manual/zh/introduction/Creating-text", "载入3D模型": "manual/zh/introduction/Loading-3D-models", @@ -534,10 +611,6 @@ "如何使用后期处理": "manual/zh/introduction/How-to-use-post-processing", "矩阵变换": "manual/zh/introduction/Matrix-transformations", "动画系统": "manual/zh/introduction/Animation-system" - }, - - "构建工具": { - "使用NPM进行测试": "manual/zh/buildTools/Testing-with-NPM" } }, @@ -612,6 +685,7 @@ }, "附件": { + "DataUtils": "api/zh/extras/DataUtils", "Earcut": "api/zh/extras/Earcut", "ImageUtils": "api/zh/extras/ImageUtils", "PMREMGenerator": "api/zh/extras/PMREMGenerator", @@ -642,6 +716,7 @@ "几何体": { "BoxGeometry": "api/zh/geometries/BoxGeometry", + "CapsuleGeometry": "api/zh/geometries/CapsuleGeometry", "CircleGeometry": "api/zh/geometries/CircleGeometry", "ConeGeometry": "api/zh/geometries/ConeGeometry", "CylinderGeometry": "api/zh/geometries/CylinderGeometry", @@ -790,6 +865,8 @@ }, "渲染器": { + "WebGL3DRenderTarget": "api/zh/renderers/WebGL3DRenderTarget", + "WebGLArrayRenderTarget": "api/zh/renderers/WebGLArrayRenderTarget", "WebGLMultipleRenderTargets": "api/zh/renderers/WebGLMultipleRenderTargets", "WebGLRenderer": "api/zh/renderers/WebGLRenderer", "WebGL1Renderer": "api/zh/renderers/WebGL1Renderer", @@ -833,12 +910,6 @@ "Addons": { - "动画": { - "CCDIKSolver": "examples/zh/animations/CCDIKSolver", - "MMDAnimationHelper": "examples/zh/animations/MMDAnimationHelper", - "MMDPhysics": "examples/zh/animations/MMDPhysics" - }, - "控制": { "DragControls": "examples/zh/controls/DragControls", "FirstPersonControls": "examples/zh/controls/FirstPersonControls", @@ -860,8 +931,7 @@ "LightProbeHelper": "examples/zh/helpers/LightProbeHelper", "PositionalAudioHelper": "examples/zh/helpers/PositionalAudioHelper", "RectAreaLightHelper": "examples/zh/helpers/RectAreaLightHelper", - "VertexNormalsHelper": "examples/zh/helpers/VertexNormalsHelper", - "VertexTangentsHelper": "examples/zh/helpers/VertexTangentsHelper" + "VertexNormalsHelper": "examples/zh/helpers/VertexNormalsHelper" }, "灯光": { @@ -869,15 +939,13 @@ }, "加载器": { - "DRACOLoader": "examples/zh/loaders/DRACOLoader", "FontLoader": "examples/zh/loaders/FontLoader", + "DracoLoader": "examples/zh/loaders/DracoLoader", "GLTFLoader": "examples/zh/loaders/GLTFLoader", "MMDLoader": "examples/zh/loaders/MMDLoader", "MTLLoader": "examples/zh/loaders/MTLLoader", "OBJLoader": "examples/zh/loaders/OBJLoader", "PCDLoader": "examples/zh/loaders/PCDLoader", - "PDBLoader": "examples/zh/loaders/PDBLoader", - "PRWMLoader": "examples/zh/loaders/PRWMLoader", "SVGLoader": "examples/zh/loaders/SVGLoader", "TGALoader": "examples/zh/loaders/TGALoader" }, @@ -890,26 +958,6 @@ "EffectComposer": "examples/zh/postprocessing/EffectComposer" }, - "导出器": { - "ColladaExporter": "examples/zh/exporters/ColladaExporter", - "GLTFExporter": "examples/zh/exporters/GLTFExporter", - "PLYExporter": "examples/zh/exporters/PLYExporter" - }, - - "数学库": { - "LookupTable": "examples/zh/math/Lut", - "MeshSurfaceSampler": "examples/zh/math/MeshSurfaceSampler", - "OBB": "examples/en/math/OBB" - }, - - "QuickHull": { - "Face": "examples/zh/math/convexhull/Face", - "HalfEdge": "examples/zh/math/convexhull/HalfEdge", - "ConvexHull": "examples/zh/math/convexhull/ConvexHull", - "VertexNode": "examples/zh/math/convexhull/VertexNode", - "VertexList": "examples/zh/math/convexhull/VertexList" - }, - "渲染器": { "CSS2DRenderer": "examples/zh/renderers/CSS2DRenderer", "CSS3DRenderer": "examples/zh/renderers/CSS3DRenderer", @@ -939,10 +987,9 @@ "매뉴얼": { "시작하기": { - "장면 만들기": "manual/ko/introduction/Creating-a-scene", "설치": "manual/ko/introduction/Installation", + "장면 만들기": "manual/ko/introduction/Creating-a-scene", "WebGL 호환성 검사": "manual/ko/introduction/WebGL-compatibility-check", - "로컬 환경에서 구동 방법": "manual/ko/introduction/How-to-run-things-locally", "선 그리기": "manual/ko/introduction/Drawing-lines", "텍스트 만들기": "manual/ko/introduction/Creating-text", "3D 모델 불러오기": "manual/ko/introduction/Loading-3D-models", @@ -957,11 +1004,6 @@ "후처리 사용 방법": "manual/ko/introduction/How-to-use-post-processing", "행렬 변환": "manual/ko/introduction/Matrix-transformations", "애니메이션 시스템": "manual/ko/introduction/Animation-system" - }, - - "빌드 도구": { - "NPM 테스트": "manual/ko/buildTools/Testing-with-NPM" - } }, @@ -1007,6 +1049,7 @@ "상수": { "Animation": "api/ko/constants/Animation", + "BufferAttributeUsage": "api/ko/constants/BufferAttributeUsage", "Core": "api/ko/constants/Core", "CustomBlendingEquation": "api/ko/constants/CustomBlendingEquations", "Materials": "api/ko/constants/Materials", @@ -1063,6 +1106,30 @@ "QuadraticBezierCurve": "api/ko/extras/curves/QuadraticBezierCurve", "QuadraticBezierCurve3": "api/ko/extras/curves/QuadraticBezierCurve3", "SplineCurve": "api/ko/extras/curves/SplineCurve" + }, + + "Geometries": { + "BoxGeometry": "api/ko/geometries/BoxGeometry", + "CapsuleGeometry": "api/ko/geometries/CapsuleGeometry", + "CircleGeometry": "api/ko/geometries/CircleGeometry", + "ConeGeometry": "api/ko/geometries/ConeGeometry", + "CylinderGeometry": "api/ko/geometries/CylinderGeometry", + "DodecahedronGeometry": "api/ko/geometries/DodecahedronGeometry", + "EdgesGeometry": "api/ko/geometries/EdgesGeometry", + "ExtrudeGeometry": "api/ko/geometries/ExtrudeGeometry", + "IcosahedronGeometry": "api/ko/geometries/IcosahedronGeometry", + "LatheGeometry": "api/ko/geometries/LatheGeometry", + "OctahedronGeometry": "api/ko/geometries/OctahedronGeometry", + "PlaneGeometry": "api/ko/geometries/PlaneGeometry", + "PolyhedronGeometry": "api/ko/geometries/PolyhedronGeometry", + "RingGeometry": "api/ko/geometries/RingGeometry", + "ShapeGeometry": "api/ko/geometries/ShapeGeometry", + "SphereGeometry": "api/ko/geometries/SphereGeometry", + "TetrahedronGeometry": "api/ko/geometries/TetrahedronGeometry", + "TorusGeometry": "api/ko/geometries/TorusGeometry", + "TorusKnotGeometry": "api/ko/geometries/TorusKnotGeometry", + "TubeGeometry": "api/ko/geometries/TubeGeometry", + "WireframeGeometry": "api/ko/geometries/WireframeGeometry" } }, @@ -1088,10 +1155,9 @@ "マニュアル": { "はじめてみましょう": { - "シーンの作成": "manual/ja/introduction/Creating-a-scene", "インストールの方法": "manual/ja/introduction/Installation", + "シーンの作成": "manual/ja/introduction/Creating-a-scene", "WebGLの互換性の確認": "manual/ja/introduction/WebGL-compatibility-check", - "localで実行する方法": "manual/ja/introduction/How-to-run-things-locally", "線を引く": "manual/ja/introduction/Drawing-lines", "テキストを作成する": "manual/ja/introduction/Creating-text", "3Dモデルをロードする": "manual/ja/introduction/Loading-3D-models", @@ -1107,10 +1173,6 @@ "post-processingの使い方": "manual/ja/introduction/How-to-use-post-processing", "行列の変換": "manual/ja/introduction/Matrix-transformations", "アニメーションシステム": "manual/ja/introduction/Animation-system" - }, - - "ビルドツール": { - "NPMでテストを実行する": "manual/ja/buildTools/Testing-with-NPM" } } @@ -1122,10 +1184,9 @@ "Manuale": { "Per iniziare": { - "Creare una scena": "manual/it/introduction/Creating-a-scene", "Installazione": "manual/it/introduction/Installation", + "Creare una scena": "manual/it/introduction/Creating-a-scene", "Controllo compatibilità WebGL": "manual/it/introduction/WebGL-compatibility-check", - "Esecuzione in locale": "manual/it/introduction/How-to-run-things-locally", "Disegnare linee": "manual/it/introduction/Drawing-lines", "Creare testo": "manual/it/introduction/Creating-text", "Caricare modelli 3D": "manual/it/introduction/Loading-3D-models", @@ -1142,10 +1203,6 @@ "Trasformazioni di matrici": "manual/it/introduction/Matrix-transformations", "Sistema di animazione": "manual/it/introduction/Animation-system", "Gestione del colore": "manual/it/introduction/Color-management" - }, - - "Strumenti di build": { - "Testare con NPM": "manual/it/buildTools/Testing-with-NPM" } }, @@ -1448,10 +1505,9 @@ "Manual": { "Comece a usar": { - "Criando uma cena": "manual/pt-br/introduction/Creating-a-scene", "Instalação": "manual/pt-br/introduction/Installation", + "Criando uma cena": "manual/pt-br/introduction/Creating-a-scene", "Compatibilidade WebGL": "manual/pt-br/introduction/WebGL-compatibility-check", - "Como executar localmente": "manual/pt-br/introduction/How-to-run-things-locally", "Desenhando linhas": "manual/pt-br/introduction/Drawing-lines", "Criando texto": "manual/pt-br/introduction/Creating-text", "Carregando modelos 3D": "manual/pt-br/introduction/Loading-3D-models", @@ -1468,10 +1524,6 @@ "Transformações de matriz": "manual/pt-br/introduction/Matrix-transformations", "Sistema de animação": "manual/pt-br/introduction/Animation-system", "Gerenciamento de cor": "manual/pt-br/introduction/Color-management" - }, - - "Ferramentas de Build": { - "Testando com NPM": "manual/pt-br/buildTools/Testing-with-NPM" } }, @@ -1534,10 +1586,9 @@ "Manuel": { "Débuter": { - "Créer une scène": "manual/fr/introduction/Creating-a-scene", "Installation": "manual/fr/introduction/Installation", + "Créer une scène": "manual/fr/introduction/Creating-a-scene", "Compatibilité WebGL": "manual/fr/introduction/WebGL-compatibility-check", - "Exécuter localement": "manual/fr/introduction/How-to-run-things-locally", "Dessiner des lignes": "manual/fr/introduction/Drawing-lines", "Créer un texte": "manual/fr/introduction/Creating-text", "Importer des modèles 3D": "manual/fr/introduction/Loading-3D-models", @@ -1554,17 +1605,8 @@ "Matrices de transformation": "manual/fr/introduction/Matrix-transformations", "Système d'animation": "manual/fr/introduction/Animation-system", "Gestion des couleurs": "manual/fr/introduction/Color-management" - }, - - "Outils de build": { - "Tests avec NPM": "manual/fr/buildTools/Testing-with-NPM" - }, - "Noyau": { - "BufferAttribute": "api/fr/core/BufferAttribute", - "BufferGeometry": "api/fr/core/BufferGeometry" } - }, "Référence": { @@ -1636,6 +1678,31 @@ "TorusKnotGeometry": "api/fr/geometries/TorusKnotGeometry", "TubeGeometry": "api/fr/geometries/TubeGeometry", "WireframeGeometry": "api/fr/geometries/WireframeGeometry" + }, + "Matériaux": { + "LineBasicMaterial": "api/fr/materials/LineBasicMaterial", + "LineDashedMaterial": "api/fr/materials/LineDashedMaterial", + "Material": "api/fr/materials/Material", + "MeshBasicMaterial": "api/fr/materials/MeshBasicMaterial", + "MeshDepthMaterial": "api/fr/materials/MeshDepthMaterial", + "MeshDistanceMaterial": "api/fr/materials/MeshDistanceMaterial", + "MeshLambertMaterial": "api/fr/materials/MeshLambertMaterial", + "MeshMatcapMaterial": "api/fr/materials/MeshMatcapMaterial", + "MeshNormalMaterial": "api/fr/materials/MeshNormalMaterial", + "MeshPhongMaterial": "api/fr/materials/MeshPhongMaterial", + "MeshPhysicalMaterial": "api/fr/materials/MeshPhysicalMaterial", + "MeshStandardMaterial": "api/fr/materials/MeshStandardMaterial", + "MeshToonMaterial": "api/fr/materials/MeshToonMaterial", + "PointsMaterial": "api/fr/materials/PointsMaterial", + "RawShaderMaterial": "api/fr/materials/RawShaderMaterial", + "ShaderMaterial": "api/fr/materials/ShaderMaterial", + "ShadowMaterial": "api/fr/materials/ShadowMaterial", + "SpriteMaterial": "api/fr/materials/SpriteMaterial" + }, + + "Noyau": { + "BufferAttribute": "api/fr/core/BufferAttribute", + "BufferGeometry": "api/fr/core/BufferGeometry" } } @@ -1647,10 +1714,9 @@ "Руководство": { "Приступая к работе": { - "Создание сцены": "manual/ru/introduction/Creating-a-scene", "Установка": "manual/ru/introduction/Installation", + "Создание сцены": "manual/ru/introduction/Creating-a-scene", "Проверка совместимости с WebGL": "manual/ru/introduction/WebGL-compatibility-check", - "Локальная разработка ": "manual/ru/introduction/How-to-run-things-locally", "Рисование линий": "manual/ru/introduction/Drawing-lines", "Создание текста": "manual/ru/introduction/Creating-text", "Загрузка 3D-моделей": "manual/ru/introduction/Loading-3D-models", @@ -1667,10 +1733,6 @@ "Matrix transformations": "manual/en/introduction/Matrix-transformations", "Animation system": "manual/en/introduction/Animation-system", "Color management": "manual/en/introduction/Color-management" - }, - - "Build Tools": { - "Testing with NPM": "manual/en/buildTools/Testing-with-NPM" } }, @@ -2019,7 +2081,6 @@ "OBJLoader": "examples/en/loaders/OBJLoader", "PCDLoader": "examples/en/loaders/PCDLoader", "PDBLoader": "examples/en/loaders/PDBLoader", - "PRWMLoader": "examples/en/loaders/PRWMLoader", "SVGLoader": "examples/en/loaders/SVGLoader", "TGALoader": "examples/en/loaders/TGALoader" }, diff --git a/docs/manual/ar/buildTools/Testing-with-NPM.html b/docs/manual/ar/buildTools/Testing-with-NPM.html deleted file mode 100644 index b21cadbdb2cb67..00000000000000 --- a/docs/manual/ar/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - - - -

    الاختبار مع NPM

    - -

    - يوضح هذه المقال كيفية الحصول على three.js في بيئة [link:https://nodejs.org/en/ node.js] حتى تتمكن من تنفيذ الاختبارات الآلية. يمكن إجراء الاختبارات على سطر الأوامر ، أو بواسطة أدوات CI الآلية مثل [link:https://travis-ci.org/ Travis]. -

    - -

    النسخة القصيرة

    - -

    - إذا كنت مرتاحًا مع node و npm ، - - $ npm install three --save-dev - - و من ثم قم بإضافة - - const THREE = require('three'); - - للاختبار الخاص بك. -

    - -

    إنشاء مشروع قابلة للاختبار من الصفر

    -

    - إذا لم تكن معتادًا على هذه الأدوات ، فإليك دليلًا سريعًا (بالنسبة لنظام التشغيل Linux ، ستكون عملية التثبيت مختلفة قليلاً باستخدام windows ، لكن أوامر NPM متطابقة). -

    - -

    الإعدادات الأساسية

    -
    -
      -
    1. - قم بتثبيت [link:https://www.npmjs.org/ npm] و nodejs. عادةً ما يبدو أقصر طريق كالأتي - -$ sudo apt-get install -y npm nodejs-legacy -# fix any problems with SSL in the default registry URL -$ npm config set registry http://registry.npmjs.org/ - -
    2. - -
    3. - أنشئ دليل مشروع جديد - - $ mkdir test-example; cd test-example - -
    4. - -
    5. - اطلب من npm إنشاء ملف مشروع جديد لك: - - $ npm init - - واقبل جميع الإعدادات الافتراضية عن طريق الضغط على Enter في جميع المطالبات ، سيؤدي هذا إلى إنشاء package.json. -

    6. - -
    7. - جرب وابدأ اختبار الميزة بـ - -$ npm test - - هذا سيفشل ، وهو أمر متوقع. إذا نظرت في package.json ، فإن تعريف البرنامج النصي للاختبار هو - - "test": "echo \"Error: no test specified\" && exit 1" - -
    8. - -
    -
    - -

    إضافة mocha

    -
    - سنقوم بإستخدام [link:https://mochajs.org/ mocha]. - -
      -
    1. - تثبيت mocha من خلال - -$ npm install mocha --save-dev - - لاحظ أنه تم إنشاء node_modules/ وتظهر تبعياتك هناك. لاحظ أيضًا أنه تم تحديث package.json: تمت إضافة خاصية devDependencies وتحديثها باستخدام --save-dev. -

    2. - -
    3. - قم بتحرير package.json لاستخدام mocha للاختبار. عندما يتم استدعاء الاختبار ، نريد فقط تشغيل المخاوي وتحديد مراسل مطول. بشكل افتراضي ، سيؤدي هذا إلى تشغيل أي شيء في test (لا يمكن تشغيل الدليل test في npm ERR! ، قم بإنشائه عبر اختبار mkdir) - - "test": "mocha --reporter list" - -
    4. - -
    5. - أعد الاختبار باستخدام - - $ npm test - - - يجب أن ينجح هذا الآن ، حيث يتم الإبلاغ عن 0 تمرير (1 جزء من الثانية) أو ما شابه. -
    6. - -
    -
    - -

    أضف three.js

    -
    -
      -
    1. - دعنا نسحب تبعية three.js لدينا مع - -$ npm install three --save-dev - -
        -
      • - إذا كنت بحاجة إلى إصدار مختلف ، فاستخدم - - $ npm show three versions - - لمعرفة ما هو متاح. لإخبار npm بالقيمة الصحيحة ، استخدم - - $ npm install three@0.84.0 --save - - (0.84.0 في هذا المثال). - حفظ يجعل هذا تبعية لهذا المشروع ، بدلاً من dev تبعية. انظر المستندات [link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json هنا] لمزيد من المعلومات. -
      • -
      -
    2. - -
    3. - سيبحث Mocha عن الاختبارات في test/ ، لذلك دعونا - - $ mkdir test - -
    4. - -
    5. - أخيرًا ، نحتاج بالفعل إلى اختبار JS للتشغيل. دعنا نضيف اختبارًا بسيطًا للتحقق من أن الكائن three.js متاح ويعمل. أنشئ test/verify-three.js تحتوي على: - -const THREE = require('three'); -const assert = require("assert"); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
    6. - -
    7. - أخيرًا ، دعنا نختبر مرة أخرى باستخدام $ npm اختبار. يجب أن يؤدي هذا إلى إجراء الاختبارات أعلاه وأن ينجح ، ويظهر شيئًا مثل: - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
    8. -
    -
    - -

    أضف الرمز الخاص بك

    -
    -

    عليك القيام بثلاثة أشياء:

    - -
      -
    1. - اكتب اختبارًا للسلوك المتوقع لشفرتك ، وضعه تحت test/. - هنا مثال من مشروع حقيقي - [link:https://github.com/air/encounter/blob/master/test/Physics-test.js هنا]. -
    2. - -
    3. - قم بتصدير الكود الوظيفي الخاص بك بطريقة يمكن للعقدة js رؤيتها ، لاستخدامها مع طلب. - شاهده [link:https://github.com/air/encounter/blob/master/js/Physics.js هنا]. -
    4. - -
    5. - اطلب الكود الخاص بك في ملف الاختبار ، بنفس الطريقة التي فعلنا بها require('three') في المثال أعلاه. -
    6. -
    - -

    - سيختلف البندان 2 و 3 بناءً على كيفية إدارتك للرمز. في مثال Physics.js الموضح أعلاه ، يكون جزء التصدير في النهاية. نقوم بتعيين كائن إلى module.exports: -

    - -//============================================================================= -// make available in nodejs -//============================================================================= -if (typeof exports !== 'undefined') -{ - module.exports = Physics; -} - -
    - -

    التعامل مع التبعيات (dependencies)

    -
    -

    - إذا كنت تستخدم بالفعل شيئًا ذكيًا مثل request.js أو browserify فتخط هذا الجزء. -

    -

    - عادةً ما يتم تشغيل مشروع three.js في المتصفح. يتم تحميل الوحدة النمطية عن طريق المتصفح الذي يقوم بتنفيذ مجموعة من علامات البرنامج النصي. فبالنسبة لملفاتك الفردية فلا داعي للقلق بشأن التبعيات. ومع ذلك ، في سياق nodejs ، لا يوجد index.html يربط كل شيء معًا ، لذلك يجب أن تكون واضحًا. -

    -

    - إذا كنت تقوم بتصدير وحدة تعتمد على ملفات أخرى ، فسيتعين عليك إخبار العقدة بتحميلها. - إليك طريقة واحدة: -

    -
      -
    1. - في بداية الوحدة النمطية الخاصة بك ، تحقق لمعرفة ما إذا كنت في بيئة nodejs. -
    2. -
    3. - إذا كان هذا هو الحال، فيتوجب عليك أن تعلن عن التبعيات الخاصة بك. -
    4. -
    5. - إذا لم يكن الأمر كذلك ، فمن المحتمل أنك في متصفح لذلك لا تحتاج إلى القيام بأي شيء آخر. -
    6. -
    - مثال لإستعمال Physics.js: - -//============================================================================= -// setup for server-side testing -//============================================================================= -if (typeof require === 'function') // test for nodejs environment -{ - const THREE = require('three'); - const MY3 = require('./MY3.js'); -} - -
    - - - diff --git a/docs/manual/ar/introduction/Creating-a-scene.html b/docs/manual/ar/introduction/Creating-a-scene.html index a096edf7cfaa56..9b4fabe5522a15 100644 --- a/docs/manual/ar/introduction/Creating-a-scene.html +++ b/docs/manual/ar/introduction/Creating-a-scene.html @@ -13,10 +13,7 @@

    إنشاء مشهد([name])

    قبل أن نبدأ

    -

    - قبل أن يمكنك إستعمال المكتبة, يجب أن توفر مكان لإظهار المشهد. قم بإنشاء ملف HTML يحتوي الشفرة البرمجية التالية - بصحبة نسخة من المكتبة [link:https://threejs.org/build/three.js three.js] في مجلد سمه js و من ثم فم بفتح الصفحة في المتصفح. -

    +

    قبل أن تتمكن من استخدام three.js ، تحتاج إلى مكان لعرضه. احفظ HTML التالي في ملف على جهاز الكمبيوتر الخاص بك وافتحه في المتصفح الخاص بك.

    <!DOCTYPE html> @@ -29,8 +26,9 @@

    قبل أن نبدأ

    </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + // Our Javascript will go here. </script> </body> @@ -218,7 +216,7 @@

    النتيجة

    - الشفرة البرمجية الكاملة في الأسفل إلى جانب محرر مباشر [link:https://jsfiddle.net/fxurzeb4/ live example]. + الشفرة البرمجية الكاملة في الأسفل إلى جانب محرر مباشر [link:https://jsfiddle.net/0c1oqf38/ live example]. أنت مدعو للعب بالأوامر البرمجية لكي تصبح صورة كيفية عملها أوضح من قبل.

    @@ -233,8 +231,9 @@

    النتيجة

    </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -256,7 +255,7 @@

    النتيجة

    cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/ar/introduction/FAQ.html b/docs/manual/ar/introduction/FAQ.html index 9ac15052afca33..712931047c67cd 100644 --- a/docs/manual/ar/introduction/FAQ.html +++ b/docs/manual/ar/introduction/FAQ.html @@ -53,9 +53,9 @@

    لماذا جزء من نموذجي غير مرئي؟

    material.side = THREE.DoubleSide

    -

    Why does three.js sometimes return strange results for invalid inputs?

    +

    لماذا يعيد three.js أحيانًا نتائج غريبة للإدخالات غير الصالحة؟

    - For performance reasons, three.js doesn't validate inputs in most cases. It's your app's responsibility to make sure that all inputs are valid. + لأسباب الأداء، لا يقوم three.js بالتحقق من صحة الإدخالات في معظم الحالات. من مسؤولية تطبيقك التأكد من صحة جميع الإدخالات.

    diff --git a/docs/manual/ar/introduction/How-to-run-things-locally.html b/docs/manual/ar/introduction/How-to-run-things-locally.html deleted file mode 100644 index 92c90ad3a9ef18..00000000000000 --- a/docs/manual/ar/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - -

    كيف تدير الأشياء محليًا

    -

    - إذا كنت تستخدم الأشكال الهندسية الإجرائية فقط ولا تقوم بتحميل أي مواد ، فيجب أن تعمل صفحات الويب مباشرة من نظام الملفات ، فقط انقر نقرًا مزدوجًا فوق ملف HTML في مدير الملفات - يجب أن يعرض محتوى الصفحة في المتصفح (سترى file:///yourFile.html في شريط العناوين). -

    - -

    المحتوى الذي تم تحميله من ملفات خارجية

    -
    -

    - إذا قمت بتحميل نماذج وأنسجة من ملفات خارجية ، نظرًا لقيود أمان المتصفحات [link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy] ، فسيفشل التحميل من نظام الملفات مع استثناء أمان. -

    - -

    هناك طريقتان لحل هذا:

    - -
      -
    1. - قم بتغيير أمان الملفات المحلية في المستعرض. يتيح لك ذلك الوصول إلى صفحتك على النحو التالي: file:///yourFile.html -
    2. -
    3. - قم بتشغيل الملفات من خادم ويب محلي. يتيح لك هذا الوصول إلى صفحتك على النحو التالي: http://localhost/yourFile.html -
    4. -
    - -

    - إذا كنت تستخدم الخيار 1 ، فاعلم أنك قد تفتح نفسك لبعض نقاط الضعف إذا كنت تستخدم نفس المتصفح لتصفح الويب. قد ترغب في إنشاء ملف تعريف / اختصار متصفح منفصل يستخدم فقط للتطور لتكون في مأمن. دعنا نمر إلى كل خيار على حدة. -

    -
    - - -

    قم بتشغيل خادم محلي

    -
    -

    - تحتوي العديد من لغات البرمجة على خوادم HTTP بسيطة مضمنة فيها. فهي ليست كاملة الميزات مثل خوادم الإنتاج مثل [link:https://www.apache.org/ Apache] أو [link:https://nginx.org NGINX] ، ولكن يجب أن تكون كافية لاختبار تطبيق three.js الخاص بك. -

    - -

    إضافات لمحررات الأكواد الأكثر إستعمالا

    -
    -

    تحتوي بعض برامج تحرير الأكواد على مكونات إضافية والتي ستنتج خادمًا بسيطًا عند الطلب.

    -
      -
    • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] لـ Visual Studio Code.
    • -
    • [link:https://atom.io/packages/atom-live-server Live Server] لـ Atom.
    • -
    -
    - -

    Servez

    -
    -

    - [link:https://greggman.github.io/servez Servez] هو خادم بسيط مع واجهة المستخدم. -

    -
    - -

    Node.js http-server

    -
    -

    يحتوي Node.js على حزمة خادم HTTP بسيطة. لتثبيت:

    - npm install http-server -g - -

    للتشغيل (من دليلك المحلي):

    - http-server . -p 8000 -
    - -

    خادم Python

    -
    -

    - إذا كان لديك [link:http://python.org/ Python] مثبتًا ، فيجب أن يكون كافيًا لتشغيل هذا من سطر أوامر (من دليل العمل الخاص بك): -

    - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

    سيخدم هذا الملفات من الدليل الحالي في المضيف المحلي تحت المنفذ 8000 ، كمثال في شريط العنوان اكتب:

    - - http://localhost:8000/ -
    - -

    خادم Ruby

    -
    -

    إذا قمت بتثبيت Ruby ، فيمكنك الحصول على نفس النتيجة بتشغيل هذا بدلاً من ذلك:

    - -ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
    - -

    خادم PHP

    -
    -

    تحتوي PHP أيضًا على خادم ويب مدمج ، بدءًا من php 5.4.0:

    - php -S localhost:8000 -
    - -

    Lighttpd

    -
    -

    - Lighttpd هو خادم ويب خفيف الوزن للغاية للأغراض العامة. سنغطي تثبيته على OSX مع HomeBrew هنا. على عكس الخوادم الأخرى التي تمت مناقشتها هنا ، فإن lighttpd هو خادم جاهز للإنتاج الكامل. -

    - -
      -
    1. - تثبيته بواسطة homebrew - brew install lighttpd -
    2. -
    3. - قم بإنشاء ملف ترتيب (configuration) يسمى lighttpd.conf في المجلد حيث تريد تشغيل خادم الويب الخاص بك. يوجد نموذج [link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration here]. -
    4. -
    5. - في ملف conf ، قم بتغيير server.document-root إلى الدليل الذي تريد خدمة الملفات منه. -
    6. -
    7. - شغله من خلال الأمر التالي: - lighttpd -f lighttpd.conf -
    8. -
    9. - انتقل إلى http://localhost:3000 وسيخدم الملفات الثابتة من الدليل الذي تختاره. -
    10. -
    -
    -

    IIS

    -
    -

    إذا كنت تستخدم Microsoft IIS كخادم ويب. الرجاء إضافة إعدادات نوع MIME فيما يتعلق بامتداد .fbx قبل التحميل.

    - File name extension: fbx MIME Type: text/plain -

    بشكل تلقائي ، يقوم IIS بحظر تنزيل ملفات .fbx و .obj. يجب عليك تعديل IIS لتمكين تنزيل هذا النوع من الملفات.

    -
    -

    - تمت مناقشة البدائل البسيطة الأخرى هنا [link:http://stackoverflow.com/q/12905426/24874 here] على Stack Overflow. -

    -
    - - - diff --git a/docs/manual/ar/introduction/How-to-update-things.html b/docs/manual/ar/introduction/How-to-update-things.html index 552910bcd7738f..7eacdcf408cd41 100644 --- a/docs/manual/ar/introduction/How-to-update-things.html +++ b/docs/manual/ar/introduction/How-to-update-things.html @@ -72,20 +72,17 @@

    BufferGeometry

    بعد ذلك سنضيف نقاطًا بشكل عشوائي إلى الخط باستخدام نمط مثل:

    -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); - x += ( Math.random() - 0.5 ) * 30; - y += ( Math.random() - 0.5 ) * 30; - z += ( Math.random() - 0.5 ) * 30; + x += ( Math.random() - 0.5 ) * 30; + y += ( Math.random() - 0.5 ) * 30; + z += ( Math.random() - 0.5 ) * 30; } @@ -99,7 +96,7 @@

    BufferGeometry

    إذا كنت تريد تغيير قيم بيانات الموضع بعد العرض الأول ، فأنت بحاجة إلى تعيين علامة needsUpdate على النحو التالي:

    -line.geometry.attributes.position.needsUpdate = true; // required after the first render +positionAttribute.needsUpdate = true; // required after the first render

    diff --git a/docs/manual/ar/introduction/Installation.html b/docs/manual/ar/introduction/Installation.html index 3286126daec76d..9fbf8a889a8eb0 100644 --- a/docs/manual/ar/introduction/Installation.html +++ b/docs/manual/ar/introduction/Installation.html @@ -85,7 +85,7 @@

    التثبيت من CDN أو استضافة ثابتة

    - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -126,7 +126,7 @@

    أمثلة

    - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -176,11 +176,11 @@

    خرائط الإستيراد

    Node.js

    - Because three.js is built for the web, it depends on browser and DOM APIs that don't always exist in Node.js. Some of these issues can be resolved by using shims like [link:https://github.com/stackgl/headless-gl headless-gl], or by replacing components like [page:TextureLoader] with custom alternatives. Other DOM APIs may be deeply intertwined with the code that uses them, and will be harder to work around. We welcome simple and maintainable pull requests to improve Node.js support, but recommend opening an issue to discuss your improvements first. + لأن three.js مبني للويب ، فهو يعتمد على واجهات برمجة تطبيقات المتصفح و DOM التي لا توجد دائمًا في Node.js. يمكن حل بعض هذه المشاكل باستخدام shims مثل [link:https://github.com/stackgl/headless-gl headless-gl] ، أو باستبدال المكونات مثل [page:TextureLoader] ببدائل مخصصة. قد تكون واجهات برمجة تطبيقات DOM الأخرى متشابكة بشكل عميق مع الكود الذي يستخدمها ، وسيكون من الصعب التغلب عليها. نرحب بطلبات السحب البسيطة والقابلة للصيانة لتحسين دعم Node.js ، ولكن نوصي بفتح مشكلة لمناقشة تحسيناتك أولاً.

    - Make sure to add `{ "type": "module" }` to your `package.json` to enable ES6 modules in your node project. + تأكد من إضافة `{ "type": "module" }` إلى `package.json` الخاص بك لتمكين وحدات ES6 في مشروع node الخاص بك.

    diff --git a/docs/manual/ar/introduction/Loading-3D-models.html b/docs/manual/ar/introduction/Loading-3D-models.html index 83296cfe1977d9..f5a385b9276ecc 100644 --- a/docs/manual/ar/introduction/Loading-3D-models.html +++ b/docs/manual/ar/introduction/Loading-3D-models.html @@ -24,7 +24,7 @@

    تحميل نماذج ثلاثية الأبعاد

    قبل أن نبدأ

    - إذا كنت جديدًا في تشغيل خادم محلي ، فابدأ بكيفية إدارة الأشياء محليًا [link:#manual/introduction/How-to-run-things-locally how to run things locally] أولاً. يمكن تجنب العديد من الأخطاء الشائعة أثناء عرض النماذج ثلاثية الأبعاد عن طريق استضافة الملفات بشكل صحيح. + إذا كنت جديدًا في تشغيل خادم محلي ، فابدأ بكيفية إدارة الأشياء محليًا [link:#manual/introduction/Installation installation] أولاً. يمكن تجنب العديد من الأخطاء الشائعة أثناء عرض النماذج ثلاثية الأبعاد عن طريق استضافة الملفات بشكل صحيح.

    سير العمل الموصى به

    diff --git a/docs/manual/ar/introduction/WebGL-compatibility-check.html b/docs/manual/ar/introduction/WebGL-compatibility-check.html index 4c38fca58c2914..a0100406ffb367 100644 --- a/docs/manual/ar/introduction/WebGL-compatibility-check.html +++ b/docs/manual/ar/introduction/WebGL-compatibility-check.html @@ -11,13 +11,12 @@

    فحص توافق WebGL

    على الرغم من أن هذه المشكلة أصبحت أقل وأقل ، إلا أن بعض الأجهزة أو المتصفحات قد لا تدعم WebGL. تتيح لك الطريقة التالية التحقق مما إذا كانت مدعومة وعرض رسالة للمستخدم إذا لم تكن مدعومة. -

    - -

    - أضف [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] إلى جافا سكريبت الخاص بك وقم بتشغيل ما يلي قبل محاولة تقديم أي شيء. + قم باستيراد وحدة الكشف عن دعم WebGL ، وقم بتشغيل ما يلي قبل محاولة عرض أي شيء.

    + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here diff --git a/docs/manual/en/buildTools/Testing-with-NPM.html b/docs/manual/en/buildTools/Testing-with-NPM.html deleted file mode 100644 index b05fc9166be5c1..00000000000000 --- a/docs/manual/en/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - - - - -

    [name]

    - -

    - This article shows how to get three.js into a [link:https://nodejs.org/en/ node.js] environment so that you - can execute automated tests. Tests can be run on the command line, or by automated - CI tools like [link:https://travis-ci.org/ Travis]. -

    - -

    The short version

    - -

    - If you're comfortable with node and npm, - - $ npm install three --save-dev - - and add - - const THREE = require('three'); - - to your test. -

    - -

    Create a testable project from scratch

    -

    - If you're not familiar with these tools, here's a quick guide (for linux, the installation process - will be slightly different using windows, but the NPM commands are identical). -

    - -

    Basic setup

    -
    -
      -
    1. - Install [link:https://www.npmjs.org/ npm] and nodejs. The shortest path typically looks something like - -$ sudo apt-get install -y npm nodejs-legacy -# fix any problems with SSL in the default registry URL -$ npm config set registry http://registry.npmjs.org/ - -
    2. - -
    3. - Make a new project directory - - $ mkdir test-example; cd test-example - -
    4. - -
    5. - Ask npm to create a new project file for you: - - $ npm init - - and accept all defaults by hitting Enter on all the prompts. - This will create package.json. -

    6. - -
    7. - Try and start the test feature with - -$ npm test - - This will fail, which is expected. - If you look in the package.json, the definition of the test script is - - "test": "echo \"Error: no test specified\" && exit 1" - -
    8. - -
    -
    - -

    Add mocha

    -
    - We're going to use [link:https://mochajs.org/ mocha]. - -
      -
    1. - Install mocha with - -$ npm install mocha --save-dev - - Notice that node_modules/ is created and your dependencies appear in there. - Also notice that your package.json has been updated: the property devDependencies - is added and updated by the use of --save-dev. -

    2. - -
    3. - Edit package.json to use mocha for testing. When test is invoked, we just want to run - mocha and specify a verbose reporter. By default this will run anything in test/ - (not having directory test/ can run into npm ERR!, create it by mkdir test) - - "test": "mocha --reporter list" - -
    4. - -
    5. - Rerun the test with - - $ npm test - - - This should now succeed, reporting 0 passing (1ms) - or similar. -
    6. - -
    -
    - -

    Add three.js

    -
    -
      -
    1. - Let's pull in our three.js dependency with - -$ npm install three --save-dev - -
        -
      • - If you need a different three version, use - - $ npm show three versions - - to see - what's available. To tell npm the right one, use - - $ npm install three@0.84.0 --save - - (0.84.0 in this example). --save makes this a dependency of this project, rather than - dev dependency. See the docs [link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json here] for more info. -
      • -
      -
    2. - -
    3. - Mocha will look for tests in test/, so let's - - $ mkdir test - -
    4. - -
    5. - Finally we actually need a JS test to run. Let's add a simple test that will verify that - the three.js object is available and working. Create test/verify-three.js containing: - -const THREE = require('three'); -const assert = require('assert'); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
    6. - -
    7. - Finally let's test again with $ npm test. This should run the tests above and succeed, - showing something like: - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
    8. -
    -
    - -

    Add your own code

    -
    - You need to do three things: - -
      -
    1. - Write a test for the expected behaviour of your code, and place it under test/. - [link:https://github.com/air/encounter/blob/master/test/Physics-test.js Here] is an example from a real project. -
    2. - -
    3. - Export your functional code in such a way that nodejs can see it, for use in conjunction with require. - See it [link:https://github.com/air/encounter/blob/master/js/Physics.js here]. -
    4. - -
    5. - Require your code into the test file, in the same way we did a require('three') in the example above. -
    6. -
    - -

    - Items 2 and 3 will vary depending on how you manage your code. In the example of Physics.js - given above, the export part is right at the end. We assign an object to module.exports: -

    - -//============================================================================= -// make available in nodejs -//============================================================================= -if (typeof exports !== 'undefined') -{ - module.exports = Physics; -} - -
    - -

    Dealing with dependencies

    -
    -

    - If you're already using something clever like require.js or browserify, skip this part. -

    -

    - Typically a three.js project is going to run in the browser. Module loading is hence done by - the browser executing a bunch of script tags. Your individual files don't have to worry - about dependencies. In a nodejs context however, there is no index.html binding everything - together, so you have to be explicit. -

    -

    - If you're exporting a module that depends on other files, you're going to have to tell node to load them. - Here is one approach: -

    -
      -
    1. - At the start of your module, check to see if you're in a nodejs environment. -
    2. -
    3. - If so, explicitly declare your dependencies. -
    4. -
    5. - If not, you're probably in a browser so you don't need to do anything else. -
    6. -
    - Example code from Physics.js: - -//============================================================================= -// setup for server-side testing -//============================================================================= -if (typeof require === 'function') // test for nodejs environment -{ - const THREE = require('three'); - const MY3 = require('./MY3.js'); -} - -
    - - - diff --git a/docs/manual/en/introduction/Color-management.html b/docs/manual/en/introduction/Color-management.html index 10ad2e65612d07..a6ba8095d431a7 100644 --- a/docs/manual/en/introduction/Color-management.html +++ b/docs/manual/en/introduction/Color-management.html @@ -156,13 +156,13 @@

    Input color space

    Colors supplied to three.js — from color pickers, textures, 3D models, and other sources — each have an associated color space. Those not already in the Linear-sRGB working color - space must be converted, and textures be given the correct texture.encoding assignment. + space must be converted, and textures be given the correct texture.colorSpace assignment. Certain conversions (for hexadecimal and CSS colors in sRGB) can be made automatically if - the legacy color management mode is disabled before initializing colors: + the THREE.ColorManagement API is enabled before initializing colors:

    -THREE.ColorManagement.legacyMode = false; +THREE.ColorManagement.enabled = true;
      @@ -177,14 +177,14 @@

      Input color space

    • Color textures: PNG or JPEG [page:Texture Textures] containing color information (like .map or .emissiveMap) use the closed domain sRGB color space, and must be annotated with - texture.encoding = sRGBEncoding. Formats like OpenEXR (sometimes used for .envMap or - .lightMap) use the Linear-sRGB color space indicated with texture.encoding = LinearEncoding, + texture.colorSpace = SRGBColorSpace. Formats like OpenEXR (sometimes used for .envMap or + .lightMap) use the Linear-sRGB color space indicated with texture.colorSpace = LinearSRGBColorSpace, and may contain values in the open domain [0,∞].
    • Non-color textures: Textures that do not store color information (like .normalMap or .roughnessMap) do not have an associated color space, and generally use the (default) texture - annotation of texture.encoding = LinearEncoding. In rare cases, non-color data + annotation of texture.colorSpace = NoColorSpace. In rare cases, non-color data may be represented with other nonlinear encodings for technical reasons.
    @@ -211,11 +211,11 @@

    Output color space

    Output to a display device, image, or video may involve conversion from the open domain Linear-sRGB working color space to another color space. This conversion may be performed in - the main render pass ([page:WebGLRenderer.outputEncoding]), or during post-processing. + the main render pass ([page:WebGLRenderer.outputColorSpace]), or during post-processing.

    -renderer.outputEncoding = THREE.sRGBEncoding; // optional with post-processing +renderer.outputColorSpace = THREE.SRGBColorSpace; // optional with post-processing
      @@ -242,6 +242,11 @@

      Output color space

      +

      + Custom materials based on [page:ShaderMaterial] and [page:RawShaderMaterial] have to implement their own output color space conversion. + For instances of `ShaderMaterial`, adding the `encodings_fragment` shader chunk to the fragment shader's `main()` function should be sufficient. +

      +

      Working with THREE.Color instances

      @@ -264,7 +269,7 @@

      Working with THREE.Color instances

      - With ColorManagement.legacyMode = false set (recommended), certain conversions + With ColorManagement.enabled = true set (recommended), certain conversions are made automatically. Because hexadecimal and CSS colors are generally sRGB, [page:Color] methods will automatically convert these inputs from sRGB to Linear-sRGB in setters, or convert from Linear-sRGB to sRGB when returning hexadecimal or CSS output from getters. diff --git a/docs/manual/en/introduction/Creating-a-scene.html b/docs/manual/en/introduction/Creating-a-scene.html index 7ee97b030982a4..0f5751481e4d4e 100644 --- a/docs/manual/en/introduction/Creating-a-scene.html +++ b/docs/manual/en/introduction/Creating-a-scene.html @@ -13,34 +13,19 @@

      [name]

      Before we start

      -

      Before you can use three.js, you need somewhere to display it. Save the following HTML to a file on your computer, along with a copy of [link:https://threejs.org/build/three.js three.js] in the js/ directory, and open it in your browser.

      - - - <!DOCTYPE html> - <html> - <head> - <meta charset="utf-8"> - <title>My first three.js app</title> - <style> - body { margin: 0; } - </style> - </head> - <body> - <script src="js/three.js"></script> - <script> - // Our Javascript will go here. - </script> - </body> - </html> - - -

      That's all. All the code below goes into the empty <script> tag.

      +

      + If you haven't yet, go through the [link:#manual/introduction/Installation Installation] guide. We'll assume you've already set up the same project structure (including index.html and main.js), have installed three.js, and are either running a build tool, or using a local server with a CDN and import maps. +

      Creating the scene

      To actually be able to display anything with three.js, we need three things: scene, camera and renderer, so that we can render the scene with camera.

      +

      main.js —

      + + import * as THREE from 'three'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -59,9 +44,7 @@

      Creating the scene

      The next two attributes are the `near` and `far` clipping plane. What that means, is that objects further away from the camera than the value of `far` or closer than `near` won't be rendered. You don't have to worry about this now, but you may want to use other values in your apps to get better performance.

      -

      Next up is the renderer. This is where the magic happens. In addition to the WebGLRenderer we use here, three.js comes with a few others, often used as fallbacks for users with older browsers or for those who don't have WebGL support for some reason.

      - -

      In addition to creating the renderer instance, we also need to set the size at which we want it to render our app. It's a good idea to use the width and height of the area we want to fill with our app - in this case, the width and height of the browser window. For performance intensive apps, you can also give `setSize` smaller values, like `window.innerWidth/2` and `window.innerHeight/2`, which will make the app render at quarter size.

      +

      Next up is the renderer. In addition to creating the renderer instance, we also need to set the size at which we want it to render our app. It's a good idea to use the width and height of the area we want to fill with our app - in this case, the width and height of the browser window. For performance intensive apps, you can also give `setSize` smaller values, like `window.innerWidth/2` and `window.innerHeight/2`, which will make the app render at quarter size.

      If you wish to keep the size of your app but render it at a lower resolution, you can do so by calling `setSize` with false as `updateStyle` (the third argument). For example, `setSize(window.innerWidth/2, window.innerHeight/2, false)` will render your app at half resolution, given that your <canvas> has 100% width and height.

      @@ -116,12 +99,14 @@

      Animating the cube

      The result

      Congratulations! You have now completed your first three.js application. It's simple, but you have to start somewhere.

      -

      The full code is available below and as an editable [link:https://jsfiddle.net/fxurzeb4/ live example]. Play around with it to get a better understanding of how it works.

      +

      The full code is available below and as an editable [link:https://jsfiddle.net/0c1oqf38/ live example]. Play around with it to get a better understanding of how it works.

      + +

      index.html —

      <!DOCTYPE html> <html> - <head> + <head lang="en"> <meta charset="utf-8"> <title>My first three.js app</title> <style> @@ -129,35 +114,40 @@

      The result

      </style> </head> <body> - <script src="js/three.js"></script> - <script> - const scene = new THREE.Scene(); - const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); + <script type="module" src="/main.js"></script> + </body> + </html> +
      - const renderer = new THREE.WebGLRenderer(); - renderer.setSize( window.innerWidth, window.innerHeight ); - document.body.appendChild( renderer.domElement ); +

      main.js —

      - const geometry = new THREE.BoxGeometry( 1, 1, 1 ); - const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); - const cube = new THREE.Mesh( geometry, material ); - scene.add( cube ); + + import * as THREE from 'three'; - camera.position.z = 5; + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); - function animate() { - requestAnimationFrame( animate ); + const renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); - cube.rotation.x += 0.01; - cube.rotation.y += 0.01; + const geometry = new THREE.BoxGeometry( 1, 1, 1 ); + const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); + const cube = new THREE.Mesh( geometry, material ); + scene.add( cube ); - renderer.render( scene, camera ); - }; + camera.position.z = 5; - animate(); - </script> - </body> - </html> + function animate() { + requestAnimationFrame( animate ); + + cube.rotation.x += 0.01; + cube.rotation.y += 0.01; + + renderer.render( scene, camera ); + } + + animate(); diff --git a/docs/manual/en/introduction/FAQ.html b/docs/manual/en/introduction/FAQ.html index 6ae4df13a6dc66..0ac0ffe4b65975 100644 --- a/docs/manual/en/introduction/FAQ.html +++ b/docs/manual/en/introduction/FAQ.html @@ -56,5 +56,10 @@

      Why does three.js sometimes return strange results for invalid inputs?

      For performance reasons, three.js doesn't validate inputs in most cases. It's your app's responsibility to make sure that all inputs are valid.

      + +

      Can I use three.js in Node.js?

      +

      + Because three.js is built for the web, it depends on browser and DOM APIs that don't always exist in Node.js. Some of these issues can be avoided by using shims like [link:https://github.com/stackgl/headless-gl headless-gl] and [link:https://github.com/rstacruz/jsdom-global jsdom-global], or by replacing components like [page:TextureLoader] with custom alternatives. Other DOM APIs may be deeply intertwined with the code that uses them, and will be harder to work around. We welcome simple and maintainable pull requests to improve Node.js support, but recommend opening an issue to discuss your improvements first. +

      diff --git a/docs/manual/en/introduction/How-to-run-things-locally.html b/docs/manual/en/introduction/How-to-run-things-locally.html deleted file mode 100644 index aa04361666d965..00000000000000 --- a/docs/manual/en/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - -

      [name]

      -

      - If you use just procedural geometries and don't load any textures, webpages should work - straight from the file system, just double-click on HTML file in a file manager and it - should appear working in the browser (you'll see file:///yourFile.html in the address bar). -

      - -

      Content loaded from external files

      -
      -

      - If you load models or textures from external files, due to browsers' [link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy] - security restrictions, loading from a file system will fail with a security exception. -

      - -

      - To solve this, run files from a local web server. This allows you to access your page as: -

      - -

      - http://localhost/yourFile.html -

      - -

      - While it is also possible to change browser security settings instead of running a local server, - we do not recommend that approach. Doing so may open your device up to vulnerabilities, if the - same browser is used for regular web surfing. Use of a local server is standard practice in - web development, and we explain how to install and use a local server below. -

      -
      - - -

      Run a local server

      -
      -

      - Many programming languages have simple HTTP servers built in. They are not as full featured as - production servers such as [link:https://www.apache.org/ Apache] or [link:https://nginx.org NGINX], however they should be sufficient for testing your - three.js application. -

      - -

      Plugins for popular code editors

      -
      -

      Some code editors have plugins which will spawn a simple server on demand.

      -
        -
      • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] for Visual Studio Code.
      • -
      • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] for Visual Studio Code.
      • -
      • [link:https://atom.io/packages/atom-live-server Live Server] for Atom.
      • -
      -
      - -

      Servez

      -
      -

      - [link:https://greggman.github.io/servez Servez] is a simple server with a GUI. -

      -
      - -

      Node.js five-server

      -
      -

      Development server with live reload capability. To install:

      - -# Remove live-server (if you have it) -npm -g rm live-server - -# Install five-server -npm -g i five-server - -# Update five-server (from time to time) -npm -g i five-server@latest - - -

      To run (from your local directory):

      - five-server . -p 8000 -
      - -

      Node.js http-server

      -
      -

      Node.js has a simple HTTP server package. To install:

      - npm install http-server -g - -

      To run (from your local directory):

      - http-server . -p 8000 -
      - -

      Python server

      -
      -

      - If you have [link:http://python.org/ Python] installed, it should be enough to run this - from a command line (from your working directory): -

      - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

      This will serve files from the current directory at localhost under port 8000, i.e in the address bar type:

      - - http://localhost:8000/ -
      - -

      Ruby server

      -
      -

      If you have Ruby installed, you can get the same result running this instead:

      - -ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
      - -

      PHP server

      -
      -

      PHP also has a built-in web server, starting with php 5.4.0:

      - php -S localhost:8000 -
      - -

      Lighttpd

      -
      -

      - Lighttpd is a very lightweight general purpose webserver. We'll cover installing it on OSX with - HomeBrew here. Unlike the other servers discussed here, lighttpd is a full fledged production - ready server. -

      - -
        -
      1. - Install it via homebrew - brew install lighttpd -
      2. -
      3. - Create a configuration file called lighttpd.conf in the directory where you want to run - your webserver. There is a sample [link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration here]. -
      4. -
      5. - In the conf file, change the server.document-root to the directory you want to serve files from. -
      6. -
      7. - Start it with - lighttpd -f lighttpd.conf -
      8. -
      9. - Navigate to http://localhost:3000/ and it will serve static files from the directory you - chose. -
      10. -
      -
      -

      IIS

      -
      -

      If you are using Microsoft IIS as web server. Please add a MIME type settings regarding .fbx extension before loading.

      - File name extension: fbx MIME Type: text/plain -

      By default, IIS blocks .fbx, .obj files downloads. You have to configure IIS to enable these kind of files can be download.

      -
      -

      - Other simple alternatives are [link:http://stackoverflow.com/q/12905426/24874 discussed here] - on Stack Overflow. -

      -
      - - - diff --git a/docs/manual/en/introduction/How-to-update-things.html b/docs/manual/en/introduction/How-to-update-things.html index aa805c2ac9e5c8..69bbd04d999903 100644 --- a/docs/manual/en/introduction/How-to-update-things.html +++ b/docs/manual/en/introduction/How-to-update-things.html @@ -80,16 +80,13 @@

      BufferGeometry

      Next we'll randomly add points to the line using a pattern like:

      -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); x += ( Math.random() - 0.5 ) * 30; y += ( Math.random() - 0.5 ) * 30; @@ -108,7 +105,7 @@

      BufferGeometry

      set the needsUpdate flag like so:

      -line.geometry.attributes.position.needsUpdate = true; // required after the first render +positionAttribute.needsUpdate = true; // required after the first render

      diff --git a/docs/manual/en/introduction/Installation.html b/docs/manual/en/introduction/Installation.html index 8aaaa73bd45c97..1d2feaf0b51ba6 100644 --- a/docs/manual/en/introduction/Installation.html +++ b/docs/manual/en/introduction/Installation.html @@ -9,150 +9,259 @@

      [name]

      -

      - You can install three.js with [link:https://www.npmjs.com/ npm] and modern build tools, or get started quickly with just static hosting or a CDN. For most users, installing from npm is the best choice. -

      +

      Project structure

      - Whichever you choose, be consistent and import all files from the same version of the library. Mixing files from different sources may cause duplicate code to be included, or even break the application in unexpected ways. + Every three.js project needs at least one HTML file to define the webpage, and a JavaScript file to run your three.js code. The structure and naming choices below aren't required, but will be used throughout this guide for consistency.

      +
        +
      • + index.html + + <!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="utf-8"> + <title>My first three.js app</title> + <style> + body { margin: 0; } + </style> + </head> + <body> + <script type="module" src="/main.js"></script> + </body> + </html> + +
      • +
      • + main.js + +import * as THREE from 'three'; + +... + +
      • +
      • + public/ +
          +
        • + The public/ folder is sometimes also called a "static" folder, because the files it contains are pushed to the website unchanged. Usually textures, audio, and 3D models will go here. +
        • +
        +
      • +
      +

      - All methods of installing three.js depend on ES modules (see [link:https://eloquentjavascript.net/10_modules.html#h_hF2FmOVxw7 Eloquent JavaScript: ECMAScript Modules]), which allow you to include only the parts of the library needed in the final project. + Now that we've set up the basic project structure, we need a way to run the project locally and access it through a web browser. Installation and local development can be accomplished with npm and a build tool, or by importing three.js from a CDN. Both options are explained in the sections below.

      -

      Install from npm

      +

      Option 1: Install with NPM and a build tool

      + +

      Development

      - To install the [link:https://www.npmjs.com/package/three three] npm module, open a terminal window in your project folder and run: + Installing from the [link:https://www.npmjs.com/ npm package registry] and using a [link:https://eloquentjavascript.net/10_modules.html#h_zWTXAU93DC build tool] is the recommended approach for most users — the more dependencies your project needs, the more likely you are to run into problems that the static hosting cannot easily resolve. With a build tool, importing local JavaScript files and npm packages should work out of the box, without import maps.

      - - npm install three - + +
        +
      1. + Install [link:https://nodejs.org/ Node.js]. We'll need it to load manage dependencies and to run our build tool. +
      2. +
      3. +

        + Install three.js and a build tool, [link:https://vitejs.dev/ Vite], using a [link:https://www.joshwcomeau.com/javascript/terminal-for-js-devs/ terminal] in your project folder. Vite will be used during development, but it isn't part of the final webpage. If you prefer to use another build tool, that's fine — we support modern build tools that can import [link:https://eloquentjavascript.net/10_modules.html#h_zWTXAU93DC ES Modules]. +

        + +# three.js +npm install --save three + +# vite +npm install --save-dev vite + + +
      4. +
      5. + From your terminal, run: + + npx vite + + +
      6. +
      7. + If everything went well, you'll see a URL like http://localhost:5173 appear in your terminal, and can open that URL to see your web application. +
      8. +

      - The package will be downloaded and installed. Then you're ready to import it in your code: + The page will be blank — you're ready to [link:#manual/introduction/Creating-a-scene create a scene].

      - - // Option 1: Import the entire three.js core library. - import * as THREE from 'three'; - - const scene = new THREE.Scene(); - +

      + If you want to learn more about these tools before you continue, see: +

      - // Option 2: Import just the parts you need. - import { Scene } from 'three'; +
        +
      • + [link:https://threejs-journey.com/lessons/local-server three.js journey: Local Server] +
      • +
      • + [link:https://vitejs.dev/guide/cli.html Vite: Command Line Interface] +
      • +
      • + [link:https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management MDN: Package management basics] +
      • +
      - const scene = new Scene(); -
      +

      Production

      - When installing from npm, you'll almost always use some sort of [link:https://eloquentjavascript.net/10_modules.html#h_zWTXAU93DC bundling tool] to combine all of the packages your project requires into a single JavaScript file. While any modern JavaScript bundler can be used with three.js, the most popular choice is [link:https://webpack.js.org/ webpack]. + Later, when you're ready to deploy your web application, you'll just need to tell Vite to run a production build — npx vite build. Everything used by the application will be compiled, optimized, and copied into the dist/ folder. The contents of that folder are ready to be hosted on your website.

      +

      Option 2: Import from a CDN

      + +

      Development

      + +

      Installing without build tools will require some changes to the project structure given above.

      + +
        +
      1. +

        + We imported code from 'three' (an npm package) in main.js, and web browsers don't know what that means. In index.html we'll need to add an [link:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap import map] defining where to get the package. Put the code below inside the <head></head> tag, after the styles. +

        + +<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> + +<script type="importmap"> + { + "imports": { + "three": "https://unpkg.com/three@<version>/build/three.module.js", + "three/addons/": "https://unpkg.com/three@<version>/examples/jsm/" + } + } +</script> + +

        + Don't forget to replace <version> with an actual version of three.js, like "v0.149.0". The most recent version can be found on the [link:https://www.npmjs.com/package/three?activeTab=versions npm version list]. Because import maps are [link:https://caniuse.com/import-maps not yet supported] by some major browsers, we include the polyfill es-module-shims.js. +

        +
      2. +
      3. +

        + We'll also need to run a local server to host these files at URL where the web browser can access them. While it's technically possible to double-click an HTML file and open it in your browser, important features that we'll later do not work when the page is opened this way, for security reasons. +

        +

        + Install [link:https://nodejs.org/ Node.js], then run [link:https://www.npmjs.com/package/serve serve] to start a local server in the project's directory: +

        + + npx serve . + +
      4. +
      5. + If everything went well, you'll see a URL like http://localhost:3000 appear in your terminal, and can open that URL to see your web application. +
      6. +
      +

      - Not all features are accessed directly through the three module (also called a "bare import"). Other popular parts of the library — such as controls, loaders, and post-processing effects — must be imported from the [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm examples/jsm] subfolder. To learn more, see Examples below. + The page will be blank — you're ready to [link:#manual/introduction/Creating-a-scene create a scene].

      - Learn more about npm modules from [link:https://eloquentjavascript.net/20_node.html#h_J6hW/SmL/a Eloquent JavaScript: Installing with npm]. + Many other local static servers are available — some use different languages instead of Node.js, and others are desktop applications. They all work basically the same way, and we've provided a few alternatives below.

      -

      Install from CDN or static hosting

      +
      + More local servers -

      - The three.js library can be used without any build system, either by uploading files to your own web server or by using an existing CDN. Because the library relies on ES modules, any script that references it must use type="module" as shown below. - It is also required to define an import map which resolves the bare module specifier `three`. -

      +

      Command Line

      - - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> +

      Command line local servers run from a terminal window. The associated programming language may need to be installed first.

      - <script type="importmap"> - { - "imports": { - "three": "https://unpkg.com/three@<version>/build/three.module.js" - } - } - </script> +
        +
      • npx http-server (Node.js)
      • +
      • npx five-server (Node.js)
      • +
      • python -m SimpleHTTPServer (Python 2.x)
      • +
      • python -m http.server (Python 3.x)
      • +
      • php -S localhost:8000 (PHP 5.4+)
      • +
      - <script type="module"> - import * as THREE from 'three'; +

      GUI

      - const scene = new THREE.Scene(); +

      GUI local servers run as an application window on your computer, and may have a user interface.

      - </script> -
      +
        +
      • [link:https://greggman.github.io/servez Servez]
      • +
      -

      - Since import maps are not yet supported by all browsers, it is necessary to add the polyfill *es-module-shims.js*. -

      +

      Code Editor Plugins

      -

      Addons

      +

      Some code editors have plugins that spawn a simple server on demand.

      -

      - The core of three.js is focused on the most important components of a 3D engine. Many other useful components — such as controls, loaders, and post-processing effects — are part of the [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm examples/jsm] directory. They are referred to as "addons" (previously called "examples"), because while you can use them off the shelf, they're also meant to be remixed and customized. These components are always kept in sync with the core library, whereas similar third-party packages on npm are maintained by different people and may not be up to date. -

      +
        +
      • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] for Visual Studio Code
      • +
      • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] for Visual Studio Code
      • +
      • [link:https://atom.io/packages/atom-live-server Live Server] for Atom
      • +
      -

      - Addons do not need to be installed separately, but do need to be imported separately. If three.js was installed with npm, you can load the [page:OrbitControls] component with: -

      - - import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; +
      - const controls = new OrbitControls( camera, renderer.domElement ); - +

      Production

      - If three.js was installed from a CDN, use the same code, but with `three/addons/` in the import map. + When you're ready to deploy your web application, push the source files to your web hosting provider — no need to build or compile anything. The downside of that tradeoff is that you'll need to be careful to keep the import map updated with any dependencies (and dependencies of dependencies!) that your application requires. If the CDN hosting your dependencies goes down temporarily, your website will stop working too.

      - - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> - - <script type="importmap"> - { - "imports": { - "three": "https://unpkg.com/three@<version>/build/three.module.js", - "three/addons/": "https://unpkg.com/three@<version>/examples/jsm/" - } - } - </script> - - <script type="module"> - - import * as THREE from 'three'; - import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; - - const controls = new OrbitControls( camera, renderer.domElement ); - - </script> - -

      - It's important that all files use the same version. Do not import different addons from different versions, or use addons from a different version than the three.js library itself. + IMPORTANT: Import all dependencies from the same version of three.js, and from the same CDN. Mixing files from different sources may cause duplicate code to be included, or even break the application in unexpected ways.

      -

      Compatibility

      +

      Addons

      -

      CommonJS imports

      +

      + Out of the box, three.js includes the fundamentals of a 3D engine. Other three.js components — such as controls, loaders, and post-processing effects — are part of the [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm addons/] directory. Addons do not need to be installed separately, but do need to be imported separately. +

      - While most modern JavaScript bundlers now support ES modules by default, some older build tools might not. In those cases you can likely configure the bundler to understand ES modules: [link:http://browserify.org/ Browserify] just needs the [link:https://github.com/babel/babelify babelify] plugin, for example. + The example below shows how to import three.js with the [page:OrbitControls] and [page:GLTFLoader] addons. Where necessary, this will also be mentioned in each addon's documentation or examples.

      -

      Node.js

      + +import * as THREE from 'three'; +import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; +import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; + +const controls = new OrbitControls( camera, renderer.domElement ); +const loader = new GLTFLoader(); +

      - Because three.js is built for the web, it depends on browser and DOM APIs that don't always exist in Node.js. Some of these issues can be resolved by using shims like [link:https://github.com/stackgl/headless-gl headless-gl], or by replacing components like [page:TextureLoader] with custom alternatives. Other DOM APIs may be deeply intertwined with the code that uses them, and will be harder to work around. We welcome simple and maintainable pull requests to improve Node.js support, but recommend opening an issue to discuss your improvements first. + Some excellent third-party projects are available for three.js, too. These need to be installed separately — see [link:#manual/introduction/Libraries-and-Plugins Libraries and Plugins].

      +

      Next Steps

      +

      - Make sure to add `{ "type": "module" }` to your `package.json` to enable ES6 modules in your node project. + You're now ready to [link:#manual/introduction/Creating-a-scene create a scene].

      diff --git a/docs/manual/en/introduction/Loading-3D-models.html b/docs/manual/en/introduction/Loading-3D-models.html index d0f7eb1a115b27..5c64c07a0f7f23 100644 --- a/docs/manual/en/introduction/Loading-3D-models.html +++ b/docs/manual/en/introduction/Loading-3D-models.html @@ -30,7 +30,7 @@

      Before we start

      If you're new to running a local server, begin with - [link:#manual/introduction/How-to-run-things-locally how to run things locally] + [link:#manual/introduction/Installation installation] first. Many common errors viewing 3D models can be avoided by hosting files correctly.

      diff --git a/docs/manual/en/introduction/WebGL-compatibility-check.html b/docs/manual/en/introduction/WebGL-compatibility-check.html index 10a36fe2c82134..a2c00fb88e4538 100644 --- a/docs/manual/en/introduction/WebGL-compatibility-check.html +++ b/docs/manual/en/introduction/WebGL-compatibility-check.html @@ -11,14 +11,12 @@

      [name]

      Even though this is becoming less and less of a problem, some devices or browsers may still not support WebGL. The following method allows you to check if it is supported and display a message to the user if it is not. -

      - -

      - Add [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] - to your javascript and run the following before attempting to render anything. + Import the WebGL support detection module, and run the following before attempting to render anything.

      + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here diff --git a/docs/manual/fr/buildTools/Testing-with-NPM.html b/docs/manual/fr/buildTools/Testing-with-NPM.html deleted file mode 100644 index 8c740bb26277c7..00000000000000 --- a/docs/manual/fr/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - - - - -

      Tests avec NPM ([name])

      - -

      - Ici vous sera expliqué comment obtenir three.js dans un environnement [link:https://nodejs.org/en/ node.js] pour que - vous puissez exécuter des tests automatisés. Les tests peuvent êtres lancés en lignes de commande, ou grâce à des - outils de CI automatisés comme [link:https://travis-ci.org/ Travis]. -

      - -

      La version courte

      - -

      - Si vous êtes à l'aise avec node et npm, - - $ npm install three --save-dev - - et ajoutez - - const THREE = require('three'); - - à votre test. -

      - -

      Créer un projet testable de zéro

      -

      - Si vous n'êtes pas familier avec ces outils, vous trouverez ici un guide rapide (pour linux, le processus d'installation - sera légèrement différent de celui pour Windows, mais les commandes NPM sont identiques). -

      - -

      Setup basique

      -
      -
        -
      1. - Installez [link:https://www.npmjs.org/ npm] et nodejs. La méthode la plus rapide ressemble généralement à - -$ sudo apt-get install -y npm nodejs-legacy -# fix any problems with SSL in the default registry URL -$ npm config set registry http://registry.npmjs.org/ - -
      2. - -
      3. - Créez un nouveau répertoire de projet - - $ mkdir test-example; cd test-example - -
      4. - -
      5. - Demandez à npm de créer un nouveau fichier de projet pour vous: - - $ npm init - - et acceptez tous les paramètres par défaut en appuyant sur Entrée à chaque prompt. - Cela créera package.json. -

      6. - -
      7. - Essayez la fonctionnalité de test avec - -$ npm test - - Cela va échouer, comme prévu. - Si vous jetez un coup d'oeil à votre package.json, la définition du test de script sera - - "test": "echo \"Error: no test specified\" && exit 1" - -
      8. - -
      -
      - -

      Ajouter mocha

      -
      - Nous allons utiliser [link:https://mochajs.org/ mocha]. - -
        -
      1. - Installez mocha avec - -$ npm install mocha --save-dev - - Remarquez que node_modules/ est créé et que vos dépendances y apparaissent. - Notez également que votre package.json a été mis à jour: la propriété devDependencies - est ajoutée et mis à jour par l'utilisation de --save-dev. -

      2. - -
      3. - Modifiez votre package.json pour qu'il utilise mocha pour effectuer les tests. Lorsqu'un test est invoqué, nous voulons simplement lancer - mocha et spécifier un verbose reporter. Par défaut cela lancera le contenu de test/ - (ne pas avoir de répertoire test/ peut causer une npm ERR!, créez le en utilisant mkdir test) - - "test": "mocha --reporter list" - -
      4. - -
      5. - Relancez les tests avec - - $ npm test - - - Cela doit maintenant réussir, signalant 0 passages (1ms) - ou similaire. -
      6. - -
      -
      - -

      Ajouter three.js

      -
      -
        -
      1. - Ajoutons notre dépendance de three.js avec - -$ npm install three --save-dev - -
          -
        • - Si vous avez besoin d'une version de three différente, utilisez - - $ npm show three versions - - pour voir - ce qui est disponible. Pour indiquer à npm la bonne, utilisez - - $ npm install three@0.84.0 --save - - (0.84.0 dans cet exemple). --save qui en fait une dépendance de ce projet, au lieu - d'une dépendance dev. Voir la documentation [link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json ici] pour plus d'informations. -
        • -
        -
      2. - -
      3. - Mocha cherche des tests dans test/, exécutons donc la commande - - $ mkdir test - -
      4. - -
      5. - Finalement, nous avons besoin d'un test JS à lancer. Ajoutons un test simple qui va vérifier que - l'objet three.js est disponible et fonctionnel. Créez test/verify-three.js contenant: - -const THREE = require('three'); -const assert = require('assert'); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
      6. - -
      7. - Finalement testons à nouveau avec $ npm test. Cela doit lancer le test ci-dessous et réussir, - affichant quelque chose du genre: - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
      8. -
      -
      - -

      Ajoutez votre propre code

      -
      - Vous devez faire trois choses: - -
        -
      1. - Écrivez un test pour un comportement attendu de votre code, et placez-le sous test/. - [link:https://github.com/air/encounter/blob/master/test/Physics-test.js Ici] vous trouverez un exemple issu d'un vrai projet. -
      2. - -
      3. - Exportez votre code de manière à ce que nodejs puisse le voir et l'utiliser quand la conjoncture le requiert. - Voir [link:https://github.com/air/encounter/blob/master/js/Physics.js ici]. -
      4. - -
      5. - Puis il faut require votre code dans le fichier de test, de la même manière que nous avons require('three') dans l'exemple au-dessus. -
      6. -
      - -

      - Les items 2 et 3 varient selon la façon dont vous organisez votre code. Dans l'exemple de Physics.js - montré plus-haut, la partie concernant l'export est à la toute fin. Nous assignons un objet à module.exports: -

      - -//============================================================================= -// make available in nodejs -//============================================================================= -if (typeof exports !== 'undefined') -{ - module.exports = Physics; -} - -
      - -

      Gérer les dépendances

      -
      -

      - Si vous utlisez déjà quelque chose d'astucieux comme require.js ou browserify, sautez cette partie. -

      -

      - Généralement un projet three.js s'exécute dans le navigateur. Le module de chargement est par conséquent réalisé par - le navigateur qui exécute un ensemble de scripts. Vos fichiers individuels n'ont pas à gérer les - dépendances. Dans un contexte nodejs, il n'y a pas d'index.html reliant tout - ensemble, vous devez donc être explicites. -

      -

      - Si vous exportez un module qui dépend d'autres fichiers, vous devrez dire à node de les charger. - Voici une approche: -

      -
        -
      1. - Au début de votre module, vérifiez si vous êtes dans un environnement nodejs. -
      2. -
      3. - Si c'est le cas, déclarez explicitement vos dépendances. -
      4. -
      5. - Si ce n'est pas le cas, vous êtes probablement dans un navigateur vous n'avez donc rien d'autre à faire. -
      6. -
      - Code d'exemple issu de Physics.js: - -//============================================================================= -// setup for server-side testing -//============================================================================= -if (typeof require === 'function') // test for nodejs environment -{ - const THREE = require('three'); - const MY3 = require('./MY3.js'); -} - -
      - - - diff --git a/docs/manual/fr/introduction/Color-management.html b/docs/manual/fr/introduction/Color-management.html index e6c63391e6d42f..eb4baf4b293be2 100644 --- a/docs/manual/fr/introduction/Color-management.html +++ b/docs/manual/fr/introduction/Color-management.html @@ -156,13 +156,13 @@

      Espaces colorimétriques d'entrée

      Les couleurs fournies à three.js — par les sélecteurs de couleurs, les textures, les modèles 3D, et d'autres sources — ont toutes un espace colorimétrique associé. Celles qui ne sont pas déjà dans l'espace colorimétrique sRGB-Linéaire - doivent-être converties, et les textures doivent recevoir les bonnes consignes de texture.encoding. + doivent-être converties, et les textures doivent recevoir les bonnes consignes de texture.colorSpace. Certaines conversions (pour l'héxadecimal et les couleurs CSS en sRGB) peuvent être automatisées si l'héritage de la gestion des couleurs est désactivé avant l'initialisation des couleurs:

      -THREE.ColorManagement.legacyMode = false; +THREE.ColorManagement.enabled = true;
        @@ -177,14 +177,14 @@

        Espaces colorimétriques d'entrée

      • Textures colorées: PNG ou JPEG [page:Texture Textures] contiennent des informations de couleurs (comme .map ou .emissiveMap) utilisant le domaine fermé de l'espace colorimétrique sRGB, et doivent être annotés avec - texture.encoding = sRGBEncoding. Des formats comme OpenEXR (parfois utilisés par .envMap pi - .lightMap) utilisent l'espace colorimétrique sRGB-Linéaire indiqué par texture.encoding = LinearEncoding, + texture.colorSpace = SRGBColorSpace. Des formats comme OpenEXR (parfois utilisés par .envMap pi + .lightMap) utilisent l'espace colorimétrique sRGB-Linéaire indiqué par texture.colorSpace = LinearSRGBColorSpace, et peuvent contenir des valeurs du domaine ouvert [0,∞].
      • Textures non-colorées: Les textures qui ne stockent aucune information de couleur (comme .normalMap ou .roughnessMap) n'ont pas d'espace colorimétrique associé, et utilisent généralement l'annotation de texture (par défaut) - texture.encoding = LinearEncoding. Dans de rares cas, les données ne concernant pas la couleur + texture.colorSpace = NoColorSpace. Dans de rares cas, les données ne concernant pas la couleur peuvent être représentées par d'autres encodages non-linéaires pour des raisons techniques.
      @@ -211,11 +211,11 @@

      L'espace colorimétrique de sortie

      La sortie d'un écran, d'une image, ou d'une vidéo peut impliquer la conversion depuis un espace colorimétrique sRGB-Linéaire au domaine ouvert vers un autre espace colorimétrique. Cette conversion peut être effectuée dans - le pass principal du moteur de rendu ([page:WebGLRenderer.outputEncoding]), ou durant le post-processing. + le pass principal du moteur de rendu ([page:WebGLRenderer.outputColorSpace]), ou durant le post-processing.

      -renderer.outputEncoding = THREE.sRGBEncoding; // optional with post-processing +renderer.outputColorSpace = THREE.SRGBColorSpace; // optional with post-processing
        @@ -242,6 +242,11 @@

        L'espace colorimétrique de sortie

        +

        + Custom materials based on [page:ShaderMaterial] and [page:RawShaderMaterial] have to implement their own output color space conversion. + For instances of `ShaderMaterial`, adding the `encodings_fragment` shader chunk to the fragment shader's `main()` function should be sufficient. +

        +

        Utiliser des instances de THREE.Color

        @@ -264,7 +269,7 @@

        Utiliser des instances de THREE.Color

        - Avec ColorManagement.legacyMode = false d'activé (recommandé), certaines conversions + Avec ColorManagement.enabled = true d'activé (recommandé), certaines conversions sont faites automatiquement. Parce que l'héxadécimal et les couleurs CSS sont généralement en sRGB, les méthodes [page:Color] vont automatiquement convertir ces entrées du sRGB au sRGB-Linéaire dans des setters, ou convertir depuis du sRGB-Linéaire au sRGB lors du renvoi de valeurs héxadécimales ou CSS depuis les getters. diff --git a/docs/manual/fr/introduction/Creating-a-scene.html b/docs/manual/fr/introduction/Creating-a-scene.html index 96b054512dae83..8548c4b31e1216 100644 --- a/docs/manual/fr/introduction/Creating-a-scene.html +++ b/docs/manual/fr/introduction/Creating-a-scene.html @@ -13,7 +13,7 @@

        Créer une scène ([name])

        Avant de commencer

        -

        Avant de pouvoir utiliser three.js, vous aurez besoin d'un endroit pour l'afficher. Enregistrez le code HTML suivant dans un fichier sur votre ordinateur, ainsi qu'une copie de three.js dans le dossier js/, et ouvrez-le dans votre navigateur.

        +

        Avant de pouvoir utiliser three.js, vous aurez besoin d'un endroit pour l'afficher. Enregistrez le code HTML suivant dans un fichier sur votre ordinateur et ouvrez-le dans votre navigateur.

        <!DOCTYPE html> @@ -26,8 +26,9 @@

        Avant de commencer

        </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + // Our Javascript will go here. </script> </body> @@ -59,9 +60,7 @@

        Créer la scène

        Les deux attributs suivants sont le `near` et le `far` du plan de coupe. Les objets plus loins de la caméra que la valeur `far` ou plus proches que `near` ne seront pas rendus. Vous n'avez pas besoin de vous préoccuper de ça pour l'instant, mais vous devriez ajuster ces valeurs dans vos applications afin d'obtenir de meilleures performances.

        -

        Ensuite vient le moteur de rendu. C'est là où la magie opère. En plus du WebGLRenderer que nous utilisons ici, three.js est livré avec quelques autres moteurs de rendu, principalement utilisés comme moteurs de support pour les utilisateurs avec des navigateurs plus anciens ou n'ayant pas de support de WebGL.

        - -

        En plus d'instancier le moteur de rendu, nous avons aussi besoin de définir la taille à laquelle doit-être effectué le rendu de l'application. Il est recommandé d'utiliser la largeur et la hauteur de la zone qu'est censée occuper l'application - dans ce cas, la largeur et la hauteur de la fenêtre du navigateur. Pour les applications gourmandes en ressources, vous pouvez aussi donner à `setSize` des valeurs plus petites, comme `window.innerWidth/2` et `window.innerHeight/2`, qui permettra d'effectuer le rendu à un quart de sa taille initiale.

        +

        Ensuite vient le moteur de rendu. En plus d'instancier le moteur de rendu, nous avons aussi besoin de définir la taille à laquelle doit-être effectué le rendu de l'application. Il est recommandé d'utiliser la largeur et la hauteur de la zone qu'est censée occuper l'application - dans ce cas, la largeur et la hauteur de la fenêtre du navigateur. Pour les applications gourmandes en ressources, vous pouvez aussi donner à `setSize` des valeurs plus petites, comme `window.innerWidth/2` et `window.innerHeight/2`, qui permettra d'effectuer le rendu à un quart de sa taille initiale.

        Si vous souhaitez conserver la taille de votre application mais effectuer un rendu avec une résolution plus faible, vous pouvez le faire appelant `setSize` avec false comme `updateStyle` (le troisième argument). Par exemple, `setSize(window.innerWidth/2, window.innerHeight/2, false)` effectuera un rendu de votre application à demi-résolution, en considérant que votre <canvas> a 100% de largeur et de hauteur.

        @@ -116,7 +115,7 @@

        Animer le cube

        Le résultat

        Félicitations! Vous avez maintenant terminé votre première application three.js. C'est trivial, mais il faut bien commencer quelque part.

        -

        Le code complet est disponible ci-dessous et ainsi que sous forme d'éditable [link:https://jsfiddle.net/fxurzeb4/ exemple live]. Amusez-vous avec pour avoir une meilleure idée de son fonctionnement.

        +

        Le code complet est disponible ci-dessous et ainsi que sous forme d'éditable [link:https://jsfiddle.net/0c1oqf38/ exemple live]. Amusez-vous avec pour avoir une meilleure idée de son fonctionnement.

        <!DOCTYPE html> @@ -129,8 +128,9 @@

        Le résultat

        </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -152,7 +152,7 @@

        Le résultat

        cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/fr/introduction/How-to-run-things-locally.html b/docs/manual/fr/introduction/How-to-run-things-locally.html deleted file mode 100644 index f7be7783c909dc..00000000000000 --- a/docs/manual/fr/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - -

        Exécuter localement ([name])

        -

        - Si vous n'utilisez que des formes procédurales et que vous ne chargez acune texture, vos pages web sont censées fonctionner - directement depuis le système de fichiers, vous n'avez qu'à double-cliquer sur le fichier HTML dans un explorateur de fichier et il - devrait apparaître en étant fonctionnel dans le navigateur (vous verrez file:///yourFile.html dans votre barre d'URL). -

        - -

        Contenu chargé depuis des fichiers externes

        -
        -

        - Si vous chargez des modèles ou des textures depuis des fichiers externes, à cause des restrictions de sécurité de la [link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy] des navigateurs, - charger depuis un système de fichiers échouera avec une security exception. -

        - -

        - Pour résoudre ce problème, exécutez vos fichiers depuis un serveur web local. Cela vous permettra d'accéder à votre page ainsi: -

        - -

        - http://localhost/yourFile.html -

        - -

        - Même s'il est également possible de changer les paramètres de sécurité du navigateur au lieu de faire tourner un serveur web local, - nous ne recommandons pas cette approche. Le faire pourrait exposer votre appareil à des vulnérabilités, si le - même navigateur est utilisé pour naviguer d'une manière classique sur le web. Utiliser un serveur local est une pratique standard dans - le développement web, et nous expliquons comment installer et utiliser un serveur local ci-dessous. -

        -
        - - -

        Créer un serveur local

        -
        -

        - Plusieurs langages de programmation ont un simple serveur HTTP d'intégré. Ils ne sont pas aussi fournis que - des serveurs de production comme [link:https://www.apache.org/ Apache] ou [link:https://nginx.org NGINX], néanmoins ils devraient être suffisants pour tester votre - application three.js. -

        - -

        Plugins pour les éditeurs de codes populaires

        -
        -

        Certains éditeurs de code ont des plugins qui créent un simple serveur à la demande.

        -
          -
        • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] pour Visual Studio Code.
        • -
        • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] pour Visual Studio Code.
        • -
        • [link:https://atom.io/packages/atom-live-server Live Server] pour Atom.
        • -
        -
        - -

        Servez

        -
        -

        - [link:https://greggman.github.io/servez Servez] est un serveur simple avec une interface graphique. -

        -
        - -

        Node.js five-server

        -
        -

        Serveur de développement avec capacité de redémarrage en direct. Pour l'installer:

        - -# Remove live-server (if you have it) -npm -g rm live-server - -# Install five-server -npm -g i five-server - -# Update five-server (from time to time) -npm -g i five-server@latest - - -

        Pour le lancer (depuis votre dossier local):

        - five-server . -p 8000 -
        - -

        Node.js http-server

        -
        -

        Node.js a un simple serveur de package HTTP. Pour l'installer:

        - npm install http-server -g - -

        Pour le lancer (depuis votre dossier local):

        - http-server . -p 8000 -
        - -

        Serveur Python

        -
        -

        - Si vous avez [link:http://python.org/ Python] d'installé, il devrait suffire pour exécuter - cela en ligne de commande (depuis votre dossier de travail): -

        - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

        Cela remontera les fichiers du dossier courant au localhost sur le port 8000, par exemple écrivez dans la barre d'URL:

        - - http://localhost:8000/ -
        - -

        Serveur Ruby

        -
        -

        Si vous avez Ruby d'installé, vous pouvez obtenir le même résultat en exécutant ceci à la place:

        - -ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
        - -

        Serveur PHP

        -
        -

        PHP a également un serveur web intégré, depuis la 5.4.0:

        - php -S localhost:8000 -
        - -

        Lighttpd

        -
        -

        - Lighttpd est un serveur web très léger pouvant servir pour des usages variés. Nous verrons comment l'installer sur OSX avec - HomeBrew ci-dessous. Contrairement aux autres serveurs cités ici, lighttpd est un serveur de production complet - et prêt à l'utilisation. -

        - -
          -
        1. - L'installer via homebrew - brew install lighttpd -
        2. -
        3. - Créez un fichier de configuration nommé lighttpd.conf dans le dossier où vous souhaitez exécuter votre - serveur web. Vous trouverez un exemple ici [link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration here]. -
        4. -
        5. - Dans le fichier de configuration, changez le server.document-root pour le dossier d'où vous souhaitez remonter les fichiers. -
        6. -
        7. - Lancez-le avec - lighttpd -f lighttpd.conf -
        8. -
        9. - Rendez-vous sur http://localhost:3000/ et vous-y retrouverez les fichiers statiques du dossier - choisi. -
        10. -
        -
        -

        IIS

        -
        -

        Si vous utilisez Microsoft IIS comme serveur web. Veuillez ajouter un type de paramètres MIME concernant l'extension .fbx avant de charger.

        - File name extension: fbx MIME Type: text/plain -

        Par défaut, IIS bloque le téléchargementt des fichiers .fbx, .obj. Vous devez configurer IIS pour autoriser le téléchargement de ce genre de fichiers.

        -
        -

        - D'autres alternatives simples sont [link:http://stackoverflow.com/q/12905426/24874 présentées ici] - sur Stack Overflow. -

        -
        - - - diff --git a/docs/manual/fr/introduction/How-to-update-things.html b/docs/manual/fr/introduction/How-to-update-things.html index 601b9052e95599..544e0074f2190b 100644 --- a/docs/manual/fr/introduction/How-to-update-things.html +++ b/docs/manual/fr/introduction/How-to-update-things.html @@ -80,20 +80,17 @@

        BufferGeometry

        Ensuite nous ajouterons aléatoirement des points à l'aide d'un pattern comme:

        -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); - x += ( Math.random() - 0.5 ) * 30; - y += ( Math.random() - 0.5 ) * 30; - z += ( Math.random() - 0.5 ) * 30; + x += ( Math.random() - 0.5 ) * 30; + y += ( Math.random() - 0.5 ) * 30; + z += ( Math.random() - 0.5 ) * 30; } @@ -108,7 +105,7 @@

        BufferGeometry

        set the needsUpdate flag like so:

        -line.geometry.attributes.position.needsUpdate = true; // required after the first render +positionAttribute.needsUpdate = true; // required after the first render

        diff --git a/docs/manual/fr/introduction/Installation.html b/docs/manual/fr/introduction/Installation.html index 685fabf36e3349..9796ba6943e428 100644 --- a/docs/manual/fr/introduction/Installation.html +++ b/docs/manual/fr/introduction/Installation.html @@ -68,7 +68,7 @@

        Installer depuis un CDN ou un hébergement statique

        - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -113,7 +113,7 @@

        Addons

        - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { diff --git a/docs/manual/fr/introduction/WebGL-compatibility-check.html b/docs/manual/fr/introduction/WebGL-compatibility-check.html index 9d2f58f101cb9f..9cd96aabc79cb6 100644 --- a/docs/manual/fr/introduction/WebGL-compatibility-check.html +++ b/docs/manual/fr/introduction/WebGL-compatibility-check.html @@ -11,14 +11,12 @@

        Compatibilité WebGL ([name])

        Même si le problème se présente de moins en moins, certains appareils ou navigateurs peuvent ne toujours pas supporter WebGL. La méthode suivante vous permet de vérifier si il est supporté et d'afficher un message à l'utilisateur si il ne l'est pas. -

        - -

        - Ajoutez [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] - à votre JavaScript et exécutez ce qui suit avant de tenter d'effectuer un rendu de quoi que ce soit. + Importez le module de détection de support WebGL et exécutez ce qui suit avant d'essayer de rendre quoi que ce soit.

        + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here diff --git a/docs/manual/it/buildTools/Testing-with-NPM.html b/docs/manual/it/buildTools/Testing-with-NPM.html deleted file mode 100644 index 2700cb4b1dc0cf..00000000000000 --- a/docs/manual/it/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - - - - -

        Testare con NPM ([name])

        - -

        - Questo articolo mostra come inserire three.js in un ambiente - [link:https://nodejs.org/en/ node.js] così che tu possa eseguire test - automatici. I test possono essere eseguiti da linea di comando o da - strumenti CI automatici come [link:https://travis-ci.org/ Travis]. -

        - -

        Versione breve

        - -

        - Se sei a tuo agio con node e npm, installa npm - $ npm install three --save-dev - e aggiungi - const THREE = require('three'); - al tuo test. -

        - -

        Creare un progetto testabile da zero

        -

        - Se non sei familiare con questi strumenti, ecco una guida rapida per - linux (il processo di installazione sarà leggermente diverso usando - Windows, ma i comandi NPM saranno uguali). -

        - -

        Configurazione di base

        -
        -
          -
        1. - Installa [link:https://www.npmjs.org/ npm] e nodejs. Il percorso più - breve in genere assomiglia a qualcosa del simile: - -$ sudo apt-get install -y npm nodejs-legacy -# fix any problems with SSL in the default registry URL -$ npm config set registry http://registry.npmjs.org/ - -
        2. - -
        3. - Crea una nuova cartella per il progetto - $ mkdir test-example; cd test-example -
        4. - -
        5. - Crea un nuovo file di progetto tramite npm: - $ npm init - e accetta tutti i valori suggeriti premendo Enter per ogni richiesta. - Con queste richieste si creerà il file package.json. -
        6. -
          - -
        7. - Prova ad avviare la funzione di test con: - $ npm test - fallirà, come ci aspettiamo. Se controlli nel file package.json la - definizione dello script di test è: - "test": "echo \"Error: no test specified\" && exit 1" -
        8. -
        -
        - -

        Aggiungere mocha

        -
        - Utilizzeremo [link:https://mochajs.org/ mocha]. - -
          -
        1. - Installare mocha con: - $ npm install mocha --save-dev - Si noti che è stata creata la cartella node_modules/ e le tue - dipendenze sono state installate al suo interno. Inoltre, si noti che - il file package.json è stato aggiornato: è stata aggiunta la proprietà - devDependencies, aggiornata dal comando --save-dev. -
        2. -
          - -
        3. - Modificare il file package.json per usare mocha per i test. Quando - viene invocato il test, vogliamo eseguire mocha e specificare un - reporter dettagliato. Per impostazione predefinita questo eseguirà - qualsiasi cosa nella cartella test/ (non avendo una cartella test/ si può - incorrere in un npm ERR!, bisogna crearla con il comando mkdir test) - "test": "mocha --reporter list" -
        4. - -
        5. - Rilanciare il test con: - $ npm test - - Adesso il test dovrebbe essere eseguito con successo, riportando "0 passing (1ms) or - similar". -
        6. -
        -
        - -

        Aggiungere three.js

        -
        -
          -
        1. - Inseriamo la nostra dipendenza three.js con il comando: - $ npm install three --save-dev -
            -
          • - Se hai bisogno di una versione di three.js diversa, usa - $ npm show three versions - per vedere quali sono le versioni disponibili. Per dire ad npm la versione - scelta, usa - $ npm install three@0.84.0 --save - (0.84.0 nell'esempio). --save fa sì che sia una dipendenza del - progetto piuttosto che una devDependecy. Per maggiori informazioni - consulta il documento - [link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json qui]. -
          • -
          -
        2. - -
        3. - Mocha cercherà i test nella cartella test/, quindi creiamola - $ mkdir test -
        4. - -
        5. - Infine abbiamo effettivamente bisogno di un test JS per l'esecuzione. - Aggiungiamo un semplice test il quale verificherà che l'oggetto - three.js sia disponibile e funzionante. Crea il file - test/verify-three.js contenente: - -const THREE = require('three'); -const assert = require('assert'); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
        6. - -
        7. - Adesso rieseguiamo il test con il comando $ npm test. Questo dovrebbe - eseguire i test sopra definiti e terminare con successo, mostrando qualcosa del tipo: - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
        8. -
        -
        - -

        Aggiungere il tuo codice

        -
        - Hai bisogno di fare tre cose: - -
          -
        1. - Scrivere un test per il comportamento che di aspetti dal tuo codice, e - metterlo all'interno della cartella test/. - [link:https://github.com/air/encounter/blob/master/test/Physics-test.js Qui] un esempio di un progetto reale. -
        2. - -
        3. - Esportare il tuo codice funzionale in modo tale che nodejs possa vederlo - per usarlo insieme a require. Controlla - [link:https://github.com/air/encounter/blob/master/js/Physics.js qui]. -
        4. - -
        5. - Richiamare il tuo codice nel file di test, allo stesso modo in cui - abbiamo fatto per richiamare three nell'esempio sopra `require('three')` -
        6. -
        - -

        - Il punto 2 e 3 saranno molto dipendenti da come hai gestito il tuo codice. - Nell'esempio di Physics.js fornito sopra, la parte di esportazione si trova giustamente - alla fine. Assegniamo un oggetto a module.exports: -

        - -//============================================================================= -// make available in nodejs -//============================================================================= -if (typeof exports !== 'undefined') { module.exports = Physics; } - -
        - -

        Affrontare le dipendenze

        -
        -

        - Se stai già utilizzando qualcosa di smart come require.js o browserify, - salta questa parte. -

        -

        - Tipicamente un progetto three.js verrà eseguito nel browser. Il caricamento - del modulo viene quindi eseguito dal browser che esegue una serie di tag - di script. I tuo singoli file non si devono preoccupare per le dipendenze. - Tuttavia, in un contesto nodejs non è presente il file index.html che lega tutto - insieme, quindi devi essere esplicito. -

        -

        - Se stai esportando un modulo che dipende da altri file, dovrai dire a node - di caricarli. Di seguito un approccio: -

        -
          -
        1. - All'inizio del tuo modulo, controlla se ti trovi in un ambiente nodejs. -
        2. -
        3. Se è così, dichiara esplicitamente le tue dipendenze.
        4. -
        5. - In caso contrario, probabilmente sei in un browser e quindi non devi fare - nient'altro. -
        6. -
        - Esempio di codice da Physics.js: - -//============================================================================= -// setup for server-side testing -//============================================================================= -if (typeof require === 'function') // test for nodejs environment { - const THREE = require('three'); const MY3 = require('./MY3.js'); } - -
        - - diff --git a/docs/manual/it/introduction/Color-management.html b/docs/manual/it/introduction/Color-management.html index 15bebacec206a3..b110a1b2891491 100644 --- a/docs/manual/it/introduction/Color-management.html +++ b/docs/manual/it/introduction/Color-management.html @@ -189,13 +189,13 @@

        Input color space

        3D e da altre risorse - hanno ciascuno uno spazio colore associato. Quelli che non sono già nello spazio colore di lavoro Linear-sRGB devono essere convertiti e alle texture deve essere assegnata la corretta assegnazione - texture.encoding. Alcune conversioni (per i colori esadecimali e + texture.colorSpace. Alcune conversioni (per i colori esadecimali e CSS in sRGB) possono essere effettuate automaticamente se la modalità di gestione del colore legacy è disabilitata prima dell'inizializzazione dei colori:

        - THREE.ColorManagement.legacyMode = false; + THREE.ColorManagement.enabled = true;
        • @@ -212,16 +212,16 @@

          Input color space

          Colori delle texture: Le [page:Texture Texture] PNG o JPEG contenti informazioni sul colore (come .map o .emissiveMap) usano lo spazio colore sRGB a dominio chiuso, e devono essere annotate con - texture.encoding = sRGBEncoding. I formati come OpenEXR (a volte + texture.colorSpace = SRGBColorSpace. I formati come OpenEXR (a volte usati per .envMap o .lightMap) utilizzano lo spazio colore Linear-sRGB - indicato con texture.encoding = LinearEncoding, e possono + indicato con texture.colorSpace = LinearSRGBColorSpace, e possono contenere valori nel dominio aperto [0,∞].
        • Texture non a colori: Le texture che non memorizzano informazioni relative ai colori (come .normalMap o .roughnessMap) non hanno associato uno spazio colore, e generalmente usano l'annotazione (predefinita) - texture.encoding = LinearEncoding. In rari casi, i dati non a + texture.colorSpace = NoColorSpace. In rari casi, i dati non a colori possono essere rappresentati con altre codifiche non lineari per motivi tecnici.
        • @@ -259,11 +259,11 @@

          Output color space

          può comportare la conversione dallo spazio colore di lavoro Linear-sRGB di dominio aperto a un altro spazio di colore. Questa conversione può essere eseguita nel passaggio di rendering principale - ([page:WebGLRenderer.outputEncoding]), o durante il post-processing. + ([page:WebGLRenderer.outputColorSpace]), o durante il post-processing.

          - renderer.outputEncoding = THREE.sRGBEncoding; // optional with post-processing + renderer.outputColorSpace = THREE.SRGBColorSpace; // optional with post-processing
            @@ -297,6 +297,11 @@

            Output color space

            +

            + Custom materials based on [page:ShaderMaterial] and [page:RawShaderMaterial] have to implement their own output color space conversion. + For instances of `ShaderMaterial`, adding the `encodings_fragment` shader chunk to the fragment shader's `main()` function should be sufficient. +

            +

            Lavorare con le istanze di THREE.Color

            @@ -320,7 +325,7 @@

            Lavorare con le istanze di THREE.Color

            - Con ColorManagement.legacyMode = false impostato (consigliato), + Con ColorManagement.enabled = true impostato (consigliato), alcune conversioni vengono effettuate automaticamente. Poiché i colori esadecimali e CSS sono generalmente sRGB, i metodi [page:Color] convertiranno automaticamente questi input da sRGB a Linear-sRGB nei diff --git a/docs/manual/it/introduction/Creating-a-scene.html b/docs/manual/it/introduction/Creating-a-scene.html index 9f105c7e44fba9..fc759f57d68745 100644 --- a/docs/manual/it/introduction/Creating-a-scene.html +++ b/docs/manual/it/introduction/Creating-a-scene.html @@ -16,8 +16,7 @@

            Creare una scena ([name])

            Prima di iniziare

            Prima di poter utilizzare three.js hai bisogno di un posto dove visualizzarlo. - Salva il seguente codice HTML in un file sul tuo computer insieme ad una copia - di [link:https://threejs.org/build/three.js three.js] nella cartella js/, e aprilo nel browser.

            + Salva il seguente codice HTML in un file sul tuo computer e aprilo nel browser.

            <!DOCTYPE html> @@ -30,8 +29,9 @@

            Prima di iniziare

            </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + // Il nostro Javascript andrà qui </script> </body> @@ -70,11 +70,7 @@

            Creare la scena

            rispetto al valore `near` non saranno renderizzati. Non è neccessario preoccuparsi di questo aspetto adesso, ma potresti voler usare altri valori nella tua applicazione per avere delle prestazioni migliori.

            -

            Il prossimo passo è il renderer. È qui che avviene la magia. Oltre al WebGLRenderer che usiamo qui, - three.js fornisce altri renderer, spesso usati come alternativa per utenti che usano browser più vecchi - o per quelli che, per qualche motivo, non hanno il supporto WebGL.

            - -

            Oltre a creare l'istanza del renderer, abbiamo bisogno di impostare le dimensioni con cui vogliamo che l'applicazione venga visualizzata. È una buona idea usare la larghezza e l'altezza dell'area che vogliamo riempire con la nostra applicazione - in questo caso, la larghezza e l'altezza della finestra del browser. Per le applicazioni ad alte prestazioni si possono dare a `setSize` dei valori più piccoli, come `window.innerWidth/2` e `window.innerHeight/2`, che faranno si che l'applicazione venga renderizzata ad una dimensione di un quarto.

            +

            Il prossimo passo è il renderer. È qui che avviene la magia. Oltre a creare l'istanza del renderer, abbiamo bisogno di impostare le dimensioni con cui vogliamo che l'applicazione venga visualizzata. È una buona idea usare la larghezza e l'altezza dell'area che vogliamo riempire con la nostra applicazione - in questo caso, la larghezza e l'altezza della finestra del browser. Per le applicazioni ad alte prestazioni si possono dare a `setSize` dei valori più piccoli, come `window.innerWidth/2` e `window.innerHeight/2`, che faranno si che l'applicazione venga renderizzata ad una dimensione di un quarto.

            Se si desidera mantenere la dimensione dell'applicazione ma visualizzarla ad una risoluzione minore, è possibile farlo aggiungendo a `setSize` il valore false, corrispondente a `updateStyle` (il terzo parametro). Per esempio, `setSize(window.innerWidth/2, window.innerHeight/2, false)` visualizzerà l'applicazione a metà risoluzione, dato che il <canvas> ha larghezza e altezza del 100%.

            @@ -137,7 +133,7 @@

            Animare il cubo

            Il risultato

            Congratulazioni! Hai completato la tua prima applicazione three.js. È semplice, ma da qualche parte devi pur iniziare.

            -

            Il codice completo è disponibile di seguito e come esempio modificabile [link:https://jsfiddle.net/fxurzeb4/ live example]. Giocaci per capire meglio come funziona.

            +

            Il codice completo è disponibile di seguito e come esempio modificabile [link:https://jsfiddle.net/0c1oqf38/ live example]. Giocaci per capire meglio come funziona.

            <!DOCTYPE html> @@ -150,8 +146,9 @@

            Il risultato

            </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -173,7 +170,7 @@

            Il risultato

            cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/it/introduction/How-to-run-things-locally.html b/docs/manual/it/introduction/How-to-run-things-locally.html deleted file mode 100644 index bb6826ce1bb327..00000000000000 --- a/docs/manual/it/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - -

            Esecuzione in locale ([name])

            -

            - Se si usano solo geometrie procedurali e non si caricano texture, le pagine web dovrebbero funzionare direttamente - dal file system, basta fare doppio click sul file HTML in un file manager e la pagina dovrebbe apparire funzionante nel browser - (si vedrà file:///yourFile.html nella barra degli indirizzi del browser). -

            - -

            Contenuto caricato da file esterni

            -
            -

            - Se si caricano modelli o texture da file esterni, a causa delle restrizioni di sicurezza del [link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy] del browser, - il caricamento da un file system fallirà con un'eccezione di sicurezza. -

            - -

            - Per risolvere questo problema, conviene eseguire i file da un server locale. Questo permette di accedere alla pagina come: -

            - -

            - http://localhost/yourFile.html -

            - -

            - Anche se è possibile cambiare le impostazioni di sicurezza del browser invece di lanciare un server in locale, - non lo raccomandiamo. Utilizzando questo approccio si potrebbe esporre il proprio dispositivo a molte vulnerabilità soprattutto se - lo stesso browser viene utilizzato per la regolare navigazione sul web. Usare un server locale è una pratica standard nello sviluppo - web. Qui sotto, spieghiamo come si installa e utilizza un server locale. -

            -
            - - -

            Eseguire un server locale

            -
            -

            - Molti linguaggi di programmazione hanno semplici server HTTP integrati. Non sono completi come i server di produzione - come ad esempio [link:https://www.apache.org/ Apache] o [link:https://nginx.org NGINX], ma sono sufficienti per testare la tua applicazione three.js. -

            - -

            Plugin per i principali editor

            -
            -

            Alcuni editor hanno plugin che genereranno un semplice server su richiesta.

            -
              -
            • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] per Visual Studio Code.
            • -
            • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] per Visual Studio Code.
            • -
            • [link:https://atom.io/packages/atom-live-server Live Server] per Atom.
            • -
            -
            - -

            Servez

            -
            -

            - [link:https://greggman.github.io/servez Servez] è un semplice server con GUI. -

            -
            - -

            Node.js five-server

            -
            -

            Server di sviluppo con un reload in tempo reale. Installazione:

            - -# Eliminare live-server (se è presente) -npm -g rm live-server - -# Installare five-server -npm -g i five-server - -# Aggiornare five-server (di volta in volta) -npm -g i five-server@latest - - -

            Esecuzione (dalla tua cartella locale):

            - five-server . -p 8000 -
            - -

            Node.js http-server

            -
            -

            Node.js ha un semplice server HTTP. Installazione:

            - npm install http-server -g - -

            Esecuzione (dalla tua cartella locale):

            - http-server . -p 8000 -
            - -

            Python server

            -
            -

            - Se hai installato [link:http://python.org/ Python], dovrebbe essere sufficiente eseguire - i seguenti comandi da terminale (dalla cartella di lavoro): -

            - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

            Questo servirà i file dalla cartella corrente a localhost sotto la porta 8000, cioè nella barra degli indirizzi digita:

            - - http://localhost:8000/ -
            - -

            Ruby server

            -
            -

            Se hai installato Ruby, puoi avere lo stesso risultato eseguendo il seguente comando:

            - -ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
            - -

            PHP server

            -
            -

            Anche PHP ha un server web integrato, a partire da php 5.4.0:

            - php -S localhost:8000 -
            - -

            Lighttpd

            -
            -

            - Lighttpd è un server web generico molto leggero. Tratteremo l'installazione su OSX con HomeBrew. - Diversamente dagli altri server di cui abbiamo discusso qui, lighttpd è un server di produzione completo - pronto per la produzione. -

            - -
              -
            1. - Installazione tramite homebrew - brew install lighttpd -
            2. -
            3. - Creare un file di configurazione chiamato lighttpd.conf nella cartella in cui vuoi eseguire il server. - [link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration Qui] trovi un esempio. -
            4. -
            5. - Nel file di configurazione deve essere cambiato il valore di server.document-root con la directory da cui vuoi servire i file. -
            6. -
            7. - Avvialo con - lighttpd -f lighttpd.conf -
            8. -
            9. - Inserisci l'indirizzo http://localhost:3000/ nella barra degli indirizzi del browser, questo servirà file statici - dalla cartella che hai scelto. -
            10. -
            -
            -

            IIS

            -
            -

            Se usi Microsoft IIS come web server. Per favore aggiungi le impostazioni del MIME type relative all'estensione .fbx prima del caricamento.

            - File name extension: fbx MIME Type: text/plain -

            Per impostazione predefinita IIS blocca i download di file .fbx, .obj. È necessario configurare IIS per abilitare il download di questo tipo di file

            -
            -

            - Altre semplici alternative sono [link:http://stackoverflow.com/q/12905426/24874 trattate qui] su Stack Overflow. -

            -
            - - - diff --git a/docs/manual/it/introduction/How-to-update-things.html b/docs/manual/it/introduction/How-to-update-things.html index 7910e7ad715af5..43973a84fcc424 100644 --- a/docs/manual/it/introduction/How-to-update-things.html +++ b/docs/manual/it/introduction/How-to-update-things.html @@ -79,20 +79,17 @@

            BufferGeometry

            Quindi, aggiungeremo punti alla linea in maniera random usando un pattern come questo:

            -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); - x += ( Math.random() - 0.5 ) * 30; - y += ( Math.random() - 0.5 ) * 30; - z += ( Math.random() - 0.5 ) * 30; + x += ( Math.random() - 0.5 ) * 30; + y += ( Math.random() - 0.5 ) * 30; + z += ( Math.random() - 0.5 ) * 30; } @@ -107,7 +104,7 @@

            BufferGeometry

            impostare il flag di needsUpdate come segue:

            -line.geometry.attributes.position.needsUpdate = true; // required after the first render +positionAttribute.needsUpdate = true; // required after the first render

            diff --git a/docs/manual/it/introduction/Installation.html b/docs/manual/it/introduction/Installation.html index bb9a82fa7a117b..6c3c457b5a2ac2 100644 --- a/docs/manual/it/introduction/Installation.html +++ b/docs/manual/it/introduction/Installation.html @@ -69,7 +69,7 @@

            Installazione da CDN o hosting statico

            - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -113,7 +113,7 @@

            Addons

            - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { diff --git a/docs/manual/it/introduction/Loading-3D-models.html b/docs/manual/it/introduction/Loading-3D-models.html index 0d293c82181622..6f2d29846321cc 100644 --- a/docs/manual/it/introduction/Loading-3D-models.html +++ b/docs/manual/it/introduction/Loading-3D-models.html @@ -27,7 +27,7 @@

            Prima di iniziare

            Se siete alle prime armi con la gestione di un server locale, - iniziate prima di tutto a capire [link:#manual/introduction/How-to-run-things-locally come gestire le cose a livello locale]. + iniziate prima di tutto a capire [link:#manual/introduction/Installation installation]. Molti errori comuni nella visualizzazione dei modelli 3D possono essere evitati gestendo correttamente l'hosting dei file.

            diff --git a/docs/manual/it/introduction/WebGL-compatibility-check.html b/docs/manual/it/introduction/WebGL-compatibility-check.html index f0097c4aaebf41..d6381db13769cf 100644 --- a/docs/manual/it/introduction/WebGL-compatibility-check.html +++ b/docs/manual/it/introduction/WebGL-compatibility-check.html @@ -8,17 +8,16 @@

            Controllo compatibilità WebGL ([name])

            -

            - Anche se questo sta diventano sempre meno un problema, alcuni dispositivi o browser potrebbero ancora non supportare WebGL. - Il seguente codice è utile per controllare se WebGL è supportato, infatti se non lo fosse viene mostrato un messaggio di errore all'utente. +

            + Anche se questo sta diventano sempre meno un problema, alcuni dispositivi o browser potrebbero ancora non supportare WebGL. + Il seguente codice è utile per controllare se WebGL è supportato, infatti se non lo fosse viene mostrato un messaggio di errore all'utente. + Importa il modulo di rilevamento del supporto WebGL ed esegui quanto segue prima di tentare di eseguire il rendering di qualsiasi cosa.

            -

            - Aggiungere il seguente link [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] - al file javascript ed inserire il seguente codice prima di provare a renderizzare qualsiasi cosa: -

            + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Avviare qui la funzione o altre inizializzazioni diff --git a/docs/manual/ja/buildTools/Testing-with-NPM.html b/docs/manual/ja/buildTools/Testing-with-NPM.html deleted file mode 100644 index 2be66f7900f4d4..00000000000000 --- a/docs/manual/ja/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - - - - -

            [name]

            - -

            - この記事ではhtree.jsを[link:https://nodejs.org/en/ node.js]環境で実行する方法について説明します。 node環境で実行すると、自動テストを実行できるようになります。 テストはコマンドラインから実行可能で、[link:https://travis-ci.org/ Travis]のような自動のCIツールからも実行できます。 -

            - -

            The short version(概略)

            - -

            - npmとnodeについて詳しい方は以下のコマンドを実行し - - $ npm install three --save-dev - それから以下のコードをテストに追加してください - - const THREE = require('three'); - -

            - -

            一からテスト可能なプロジェクトを作成する

            -

            - If you're not familiar with these tools, here's a quick guide (for linux, the installation process will be slightly different using windows, but the NPM commands are identical). もしツールについて詳しくないようであれば、簡単な説明があります(linuxでは、windowsとインストールのやり方が大きく異なります。しかしNPMコマンドはそれとは関係ありません)。 -

            - -

            Basic setup(基本的な設定)

            -
            -
              -
            1. - [link:https://www.npmjs.org/ npm]とnodejsをインストールします。 もっとも早い方法は、一般的に以下のように行うことです。 - -$ sudo apt-get install -y npm nodejs-legacy -# fix any problems with SSL in the default registry URL -$ npm config set registry http://registry.npmjs.org/ - -
            2. - -
            3. - 新しいプロジェクトのディレクトリを作成します。 - - $ mkdir test-example; cd test-example - -
            4. - -
            5. - npmに新しいプロジェクトfileを作成させます。 - - $ npm init - すべてのプロンプトでEnterを押すと全てデフォルトの設定になります。 こうすることでpackage.jsonが作成されます。 -

            6. - -
            7. - 以下のようにしてテスト機能を起動してみてください - -$ npm test - おそらくですが、これは失敗します。 package.jsonの中の、テスト用のスクリプトの定義はこのようになっています。 - - "test": "echo \"Error: no test specified\" && exit 1" - -
            8. - -
            -
            - -

            Add mocha(mochaの追加)

            -
            - [link:https://mochajs.org/ mocha]を使用していきます。 - -
              -
            1. - 以下のようにしてmochaをインストールします。 - -$ npm install mocha --save-dev - node_modulesディレクトリが作られていて、依存関係がそこに示されていることが分かるかと思います。 また、package.jsonが更新されていることも分かるでしょう。 devDependencies プロパティは、--save-dev の使用により追加・更新されます。 -

            2. - -
            3. - テストでmochaを使うためにpackage.jsonを編集してください。 これはtestが呼ばれた時に、mochaを実行して詳細をどこに報告するかを決めるためです。 デフォルトでは、testディレクトリにあるものはなんでも実行されます。(もしtestディレクトリがない場合npm ERRが発生する可能性があります。その場合はmkdir testを実行し、ディレクトリを作成してください) - - "test": "mocha --reporter list" - -
            4. - -
            5. - 以下のコマンドでテストをもう一度実行してみてください - - $ npm test - 今度はうまくいくはずです。0 passing (1ms)などと報告されるでしょう。 -
            6. - -
            -
            - -

            three.jsを追加する

            -
            -
              -
            1. - three.jsを依存ファイルに加えましょう。 - -$ npm install three --save-dev - -
                -
              • - もし違うバージョンのthreeが必要な場合は次のコマンドを使ってください。 - - $ npm show three versions - こうすると使用可能なバージョンが分かります。npmに使用したいバージョンを伝えましょう。 - - $ npm install three@0.84.0 --save - (この例では0.84.0をインストールしています)。--saveは、これをdevの依存関係ではなく、このプロジェクトの依存関係にします。詳しくは、ドキュメント([link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json here])をご覧ください。 -
              • -
              -
            2. - -
            3. - Mochaはtestディレクトリの中でテストを探します。それではtestディレクトリを作成しましょう。 - - $ mkdir test - -
            4. - -
            5. - 最終的には、実際に実行するJSのテストが必要です。 three.jsのオブジェクトが利用可能で動いていることを確かめるための簡単なテストを追加してみましょう。 以下のコードが書かれたtest/verify-three.jsを作成します。 - - - -const THREE = require('three'); -const assert = require('assert'); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
            6. - -
            7. - 最後に$npm testでもう一度testを行いましょう。上のテストが実行されて成功するはずで、結果は以下のようになるでしょう。 - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
            8. -
            -
            - -

            自分のコードを追加する

            -
            - 3つのことをやる必要があります。 - -
              -
            1. - 自分のコードに期待される動作についてテストを書き、それをtest/の下に置いてください。 ここ([link:https://github.com/air/encounter/blob/master/test/Physics-test.js Here])に実際のプロジェクトの例を置いておきます。 -
            2. - -
            3. - nodejsが機能的なコードを見られるようにエクスポートして、requireと組み合わせて使用します。こちら([link:https://github.com/air/encounter/blob/master/js/Physics.js here])をご覧ください。 -
            4. - -
            5. - 上記のサンプルコードでrequire('three')を行なったのと同じ方法で、 テストコードに、あなたが作成したコードをインポートする必要があります。 -
            6. -
            - -

            - 2と3の項目は、コードの管理方法によって異なります。上記のPhysics.jsの例では、exportの部分は最後の方にあります。 module.exportsにオブジェクトを割り当てています。 -

            - -//============================================================================= -// make available in nodejs -//============================================================================= -if (typeof exports !== 'undefined') -{ - module.exports = Physics; -} - -
            - -

            Dealing with dependencies(依存関係に対処する)

            -
            -

            - もしすでに、require.jsやborwserifyといった賢いツールを使っているようなら、この章は飛ばしてください。 -

            -

            - three.jsのプロジェクトはブラウザで実行するのが一般的です。そのため、モジュールのロードはブラウザによって行われ、たくさんのscriptタグが実行されます。一つのファイルであれば依存関係の心配をする必要はありません。 しかしながら、nodejsでは他の全てのものと結びつけられているindex.htmlがないので、 明示的にそうする必要があります。 -

            -

            - 他のファイルに依存するモジュールをexportする場合、nodeにそのファイルをロードするように伝えなくてはなりません。 以下に1つのアプローチを示します。 -

            -
              -
            1. - モジュールを始める時に、nodejs環境であるかを確かめます。 -
            2. -
            3. - もしそうであれば、依存関係を明示的に宣言します。 -
            4. -
            5. - もしnodejs環境でないならおそらくブラウザ環境ですので、特に他のことはしなくても良いです。 -
            6. -
            - Physics.jsからのサンプルコードを示しておきます。 - -//============================================================================= -// setup for server-side testing -//============================================================================= -if (typeof require === 'function') // test for nodejs environment -{ - const THREE = require('three'); - const MY3 = require('./MY3.js'); -} - -
            - - - - diff --git a/docs/manual/ja/introduction/Creating-a-scene.html b/docs/manual/ja/introduction/Creating-a-scene.html index 95e550aead7543..45bbf763d0e45d 100644 --- a/docs/manual/ja/introduction/Creating-a-scene.html +++ b/docs/manual/ja/introduction/Creating-a-scene.html @@ -13,7 +13,7 @@

            [name]

            始める前に

            -

            three.jsを使う前に、表示するための場所が必要です。以下のHTMLをPCのファイルに保存して、そのHTMLを保存したディレクトリにjs/ディレクトリを作成し[link:https://threejs.org/build/three.js three.js]のコピーを保存しておいてください。その後、保存したHTMLをブラウザで開いてください。

            +

            three.jsを使う前に、表示するための場所が必要です。Save the following HTML to a file on your computer and open it in your browser.

            <!DOCTYPE html> @@ -26,8 +26,9 @@

            始める前に

            </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + // Our Javascript will go here. </script> </body> @@ -116,7 +117,7 @@

            キューブのアニメーション

            成果

            おめでとうございます。これで初めてのthree.jsアプリが完成しました。簡単なことですが、誰でもはじめは初心者です。

            -

            今回使用したコードは[link:https://jsfiddle.net/mkba0ecu/ live example]にあり編集可能です。紹介したコードがどうやって動作するかをより理解するために、それを使って遊んでみてください。

            +

            今回使用したコードは[link:https://jsfiddle.net/0c1oqf38/ live example]にあり編集可能です。紹介したコードがどうやって動作するかをより理解するために、それを使って遊んでみてください。

            <!DOCTYPE html> @@ -128,8 +129,9 @@

            成果

            </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -151,7 +153,7 @@

            成果

            cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/ja/introduction/How-to-run-things-locally.html b/docs/manual/ja/introduction/How-to-run-things-locally.html deleted file mode 100644 index c9e9bc7e15e416..00000000000000 --- a/docs/manual/ja/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - -

            [name]

            -

            - テクスチャを呼び出さずに、ジオメトリを使うだけならウェブページをファイルシステムからそのまま動かすことができます。ファイルマネージャのHTMLファイルをダブルクリックすると、ブラウザで動作するはずです。(ブラウザのアドレスバーにはfile:///yourFile.htmlと表示されているでしょう) -

            - -

            外部のファイルからコンテンツを読み込む

            -
            -

            - 外部ファイルからテクスチャやモジュールを読み込む場合、ブラウザのセキュリティ制限によって、ファイルシステムからの読み込みは失敗します。 -

            - -

            これを解決するには2つの方法があります。

            - -
              -
            1. - ブラウザのローカルファイルに対するセキュリティ設定を変更することです。これによって、file:///yourFile.htmlといったローカルのファイルにアクセスできるようになります。 -
            2. -
            3. - もうひとつは、ローカルのサーバからファイルを起動することです。こうすることで、http://localhost/yourFile.htmlにアクセスできるようになります。 -
            4. -
            - -

            - 1つ目の方法を使う場合、いつも使用しているブラウザを使用すると、自ら脆弱性を露呈させかねないことに注意してください。念のため、ローカル開発専用のブラウザプロファイル/ショートカットを分けて作成しておいた方が良いかもしれません。それぞれのオプションを順番に紹介します。 -

            -
            - - -

            ローカルでサーバを動かす

            -
            -

            - ほとんどのプログラム言語は組み込みの簡単なHTTPサーバが使えます。こういった組み込みのサーバは、ApacheやNginxなどの本番用に使用されるサーバと比べると機能が少ないですが、three.jsを試してみるには十分な機能があります -

            - -

            コードエディタのプラグイン

            -
            -

            コードエディタの中には、オンデマンドでシンプルなサーバを起動するプラグインがありものがあります

            -
              -
            • Visual Studio Codeの[link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server]
            • -
            • Atomの[link:https://atom.io/packages/atom-live-server Live Server]
            • -
            -
            - -

            Servez

            -
            -

            - [link:https://greggman.github.io/servez Servez]はGUI で操作できるシンプルなサーバです。 -

            -
            - -

            Node.js http-server

            -
            -

            Node.jsにはシンプルなHTTPサーバーパッケージがあります。インストールするには以下のコマンドを実行してください。

            - npm install http-server -g - -

            ローカル環境で実行するには以下のようにしてください

            - http-server . -p 8000 -
            - -

            Python server

            -
            -

            - [link:http://python.org/ Python]がインストールされている場合、作業ディレクトリで以下のようにコマンドライン実行すれば、サーバを動かすことができます。 -

            - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

            - このようにすることで、ローカルホストのカレントディレクトリから8000番ポートでファイルが提供されます。提供されるファイルを見るためには、ブラウザのアドレスバーに以下のように入力してください。 -

            - - http://localhost:8000/ -
            - -

            Ruby server

            -
            -

            Rubyがインストールされている環境の場合、代わりに以下のコマンドを実行することでサーバを動かすことができます。

            - -ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
            - -

            PHP server

            -
            -

            PHPにも組み込みのwebサーバがあるので、phpの5.4.0で以下のように実行してみてください

            - php -S localhost:8000 -
            - -

            Lighttpd

            -
            -

            - Lighttpd は非常に軽量な汎用ウェブサーバです。ここではOSXにHomeBrewでインストールする方法を説明します。ここで説明した他のサーバとは異なり、lighttpd は本格的な本番環境に対応したサーバです。 -

            - -
              -
            1. - homebrewでLighttpdをインストールする - brew install lighttpd -
            2. -
            3. - ウェブサーバを動作させたいディレクトリにlighttpd.confという設定ファイルを作成します。 設定ファイルのサンプルはこちらにあります。: [link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration TutorialConfiguration] -
            4. -
            5. - 設定ファイルでserver.document-rootを提供したいファイルが置いてあるディレクトリに変更してください -
            6. -
            7. - Lighttpdは以下のコマンドで実行できます。 - lighttpd -f lighttpd.conf -
            8. -
            9. - http://localhost:3000/ に移動すると、選択したディレクトリから静的ファイルを提供します。 -
            10. -
            -
            -

            IIS

            -
            -

            - WebサーバにMicrosoft IISを使用している場合ロードする前に.fbx拡張子に関するMIMEタイプの設定を追加してください。 -

            - File name extension: fbx MIME Type: text/plain -

            - デフォルトではIISは.fbxや.objのファイルをダウンロードするのをブロックします。そのため、IISがそういったファイル(.fbxなど)をダウンロードできるように設定を変更する必要があります。 - -

            -
            -

            - 他のシンプルな方法はStack Overflowで議論されています: [link:http://stackoverflow.com/q/12905426/24874 Simple way] -

            -
            - - - - \ No newline at end of file diff --git a/docs/manual/ja/introduction/How-to-update-things.html b/docs/manual/ja/introduction/How-to-update-things.html index 70010bc4a45caf..630bb898bc4fc0 100644 --- a/docs/manual/ja/introduction/How-to-update-things.html +++ b/docs/manual/ja/introduction/How-to-update-things.html @@ -76,16 +76,13 @@

            BufferGeometry

            次に以下のようにして、線上にランダムに点を追加してみましょう。

            -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); x += ( Math.random() - 0.5 ) * 30; y += ( Math.random() - 0.5 ) * 30; @@ -103,7 +100,7 @@

            BufferGeometry

            最初の描画以降に位置データの値を変更したい場合は、needsUpdateをtrueにセットする必要があります。

            -line.geometry.attributes.position.needsUpdate = true; // required after the first render +positionAttribute.needsUpdate = true; // required after the first render

            diff --git a/docs/manual/ja/introduction/Installation.html b/docs/manual/ja/introduction/Installation.html index 980f947fb1da15..16654b7029c133 100644 --- a/docs/manual/ja/introduction/Installation.html +++ b/docs/manual/ja/introduction/Installation.html @@ -69,7 +69,7 @@

            CDNや静的ホスティングからインストールをする

            -<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> +<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -110,7 +110,7 @@

            Addons

            -<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> +<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { diff --git a/docs/manual/ja/introduction/Loading-3D-models.html b/docs/manual/ja/introduction/Loading-3D-models.html index 300844e02fb154..654c3ff7adcb2c 100644 --- a/docs/manual/ja/introduction/Loading-3D-models.html +++ b/docs/manual/ja/introduction/Loading-3D-models.html @@ -28,7 +28,7 @@

            始める前に

            もしthree.jsをローカルサーバで動かすのが初めてなら、 - [link:#manual/introduction/How-to-run-things-locally how to run things locally]を見てみてください。 + [link:#manual/introduction/Installation installation]を見てみてください。 3Dモデルを表示する際の多くの一般的なエラーはファイルを正しく配置することで防ぐことができます。

            diff --git a/docs/manual/ja/introduction/WebGL-compatibility-check.html b/docs/manual/ja/introduction/WebGL-compatibility-check.html index 9eff4e290daaa0..0e2c2b6f3aaae8 100644 --- a/docs/manual/ja/introduction/WebGL-compatibility-check.html +++ b/docs/manual/ja/introduction/WebGL-compatibility-check.html @@ -10,13 +10,12 @@

            [name]

            問題が少なくなってきたとはいえ、端末やブラウザによってはWebGLに対応していない場合があります。以下の方法で、ブラウザがWebGLをサポートしているかどうかを確認し、サポートされていない場合はユーザーにメッセージを表示することができます。 -

            - -

            - javascriptのコードに[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js]を付け加えて、何かを描画する前に以下のコードを実行してください。 + WebGL サポート検出モジュールをインポートし、レンダリングを試みる前に以下を実行します。

            + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here diff --git a/docs/manual/ko/buildTools/Testing-with-NPM.html b/docs/manual/ko/buildTools/Testing-with-NPM.html deleted file mode 100644 index e92cdf19bae82f..00000000000000 --- a/docs/manual/ko/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - - - - -

            NPM 테스트([name])

            - -

            - 이 문서에서는 [link:https://nodejs.org/en/ node.js] 환경에서 three.js를 사용해 자동 테스트를 진행해보는 방법을 알려드립니다. - 테스트는 커맨드 라인으로 실행이 가능하며 [link:https://travis-ci.org/ Travis]같은 CI 툴을 통해 자동으로 실행이 가능합니다. -

            - -

            간단한 버전

            - -

            - node와 npm이 친숙하다면, - - $ npm install three --save-dev - - 그리고 여기에 - - const THREE = require('three'); - - 를 추가합니다. -

            - -

            scratch에서 테스트 가능한 예제 만들기

            -

            - 이 툴들에 익숙치 않다면, 아래의 간단한 가이드(리눅스 기반으로, 윈도우에서의 설치 절차와는 조금 다릅니다. 하지만 NPM 커맨드는 같습니다)를 따라주세요. -

            - -

            기본 설치

            -
            -
              -
            1. - [link:https://www.npmjs.org/ npm] 과 nodejs를 설치합니다. 가장 짧은 설치 명령어는 다음과 같습니다. - -$ sudo apt-get install -y npm nodejs-legacy -# 기본 레지스트리 URL에서 SSL 문제가 생기면 수정해주세요 -$ npm config set registry http://registry.npmjs.org/ - -
            2. - -
            3. - 새 프로젝트 폴더를 만듭니다. - - $ mkdir test-example; cd test-example - -
            4. - -
            5. - npm에게 새 프로젝트 파일을 만들게 합니다: - - $ npm init - - 엔터를 계속 쳐서 기본 설정으로 동의 후 진행하세요. - 이 절차가 끝나면 package.json 파일이 생길 것입니다. -

            6. - -
            7. - 다음 코드로 테스트를 시작해 보세요 - -$ npm test - - 아마 실패가 뜰 것입니다. - package.json 파일을 보면, test 스크립트의 경로가 다음과 같이 되어 있을 것입니다. - - "test": "echo \"Error: no test specified\" && exit 1" - -
            8. - -
            -
            - -

            mocha 추가하기

            -
            - [link:https://mochajs.org/ mocha]를 사용할 것입니다. - -
              -
            1. - mocha는 아래 명령어로 설치합니다. - -$ npm install mocha --save-dev - - node_modules/이 생성되어 있고 파일들이 있어야 합니다. - 그리고 package.json의 내용이 업데이트 되었는지도 확인해봐야 합니다. - --save-dev를 통해 devDependencies 속성에 업데이트가 되어있어야 합니다. -

            2. - -
            3. - mocha가 동작하는지 확인하기 위해 package.json을 수정합니다. 우리가 하고자 하는 것은 test를 치면 mocha를 동작하고 여러 리포터를 확인하는 것입니다. - 기본적으로 이 명령어는 test/ 의 모든 것을 실행할 것입니다. - (test/ 폴더가 없다면 npm ERR!가 나올 것입니다, mkdir test로 만들어주세요) - - "test": "mocha --reporter list" - -
            4. - -
            5. - test를 다시 실행시킵니다. - - $ npm test - - - 아마 성공 메세지가 뜨고 0 passing (1ms)와 비슷한 문구가 뜰 것입니다. -
            6. - -
            -
            - -

            three.js 추가

            -
            -
              -
            1. - three.js를 다음과 같이 추가합니다. - -$ npm install three --save-dev - -
                -
              • - 다른 three 버전을 사용하려면, 아래 명령어를 입력하고 - - $ npm show three versions - - 사용 가능한 버전을 확인해, npm에게 특정 버전을 사용하라고 합니다. - - $ npm install three@0.84.0 --save - - (이 예제에서는 0.84.0 버전을 사용했습니다.). --save 는 dev 설정이 아닌 이 프로젝트의 의존성으로 추가하는 명령어입니다. - 여기([link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json link])에서 더 많은 내용을 확인하세요. -
              • -
              -
            2. - -
            3. - Mocha 는 test/에서 test를 찾을 것이기 때문에, 아래 명령어를 입력합니다. - - $ mkdir test - -
            4. - -
            5. - 이제 마지막으로 JS 테스트가 남았습니다. three.js가 잘 작동하는지 간단한 테스트를 통해 확인해 봅시다. - test/verify-three.js 파일을 만들고 안에 다음 내용을 넣어주세요: - -const THREE = require('three'); -const assert = require('assert'); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
            6. - -
            7. - 마지막으로 $ npm test로 확인해봅시다. 위의 테스트 파일을 성공적으로 실행시키고 다음과 같은 내용이 나올 것입니다. - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
            8. -
            -
            - -

            자신의 코드 추가하기

            -
            - 세 가지를 수행해야 합니다: - -
              -
            1. - 자신의 코드의 예상 결과가 들어있는 예제를 만들어, test/ 폴더 안에 두세요. - 여기([link:https://github.com/air/encounter/blob/master/test/Physics-test.js link])에서 진짜 프로젝트의 예제를 확인할 수 있습니다. -
            2. - -
            3. - nodeJS에서 알아볼 수 있는, require를 사용해 기능들을 내보내기 하세요. - 여기([link:https://github.com/air/encounter/blob/master/js/Physics.js link])를 참고하세요. -
            4. - -
            5. - 테스트 파일에서 코드를 불러오세요. 같은 방식으로 우리는 위의 예제에서 require('three')를 불러왔습니다. -
            6. -
            - -

            - 2번과 3번 과정은 자신의 코드를 어떻게 관리하는지에 따라 달려 있습니다. 위의 Physics.js 예제에서는 내보내기 부분이 맨 마지막에 있습니다. - module.exports에 할당했습니다. -

            - -//============================================================================= -// make available in nodejs -//============================================================================= -if (typeof exports !== 'undefined') -{ - module.exports = Physics; -} - -
            - -

            의존성 관리

            -
            -

            - require.js나 browserify같은 현명한 방법을 사용하고 있다면 이 부분은 넘어가세요. -

            -

            - 일반적으로 three.js 프로젝트는 브라우저에서 돌아가게 하기 위한 목적입니다. 따라서 모듈 로딩은 브라우저가 스크립트 태그를 실행함으로써 이루어집니다. - 개인 파일은 의존성에 대해 걱정하지 않아도 됩니다. 하지만 nodejs 환경에서는 모든 것을 묶어놓은 index.html이 없기 때문에, 분명히 해 둘 필요가 있습니다. -

            -

            - 다른 파일에 의존하는 모듈을 내보내기 할 때에는, node에 같이 내보내기하라고 알려줘야 합니다. - 그 방법 중 하나는 다음과 같습니다: -

            -
              -
            1. - 모듈의 시작 부분에서 nodejs 환경인지 체크합니다. -
            2. -
            3. - 만약 그렇다면 의존성을 명확하게 선언해줍니다. -
            4. -
            5. - 그렇지 않다면 브라우저 환경일 것이기 때문에 아무것도 할 것이 없습니다. -
            6. -
            - Physics.js의 예제입니다: - -//============================================================================= -// 서버사이드 테스트 설정 -//============================================================================= -if (typeof require === 'function') // nodejs 환경 테스트 -{ - const THREE = require('three'); - const MY3 = require('./MY3.js'); -} - -
            - - - diff --git a/docs/manual/ko/introduction/Creating-a-scene.html b/docs/manual/ko/introduction/Creating-a-scene.html index 09ca6ca6d4ab5f..bf05a0b9f36cf7 100644 --- a/docs/manual/ko/introduction/Creating-a-scene.html +++ b/docs/manual/ko/introduction/Creating-a-scene.html @@ -13,7 +13,7 @@

            장면 만들기([name])

            시작하기에 앞서

            -

            three.js를 사용하려면, 표시할 수 있는 공간이 필요합니다. 다음과 같이 HTML 파일을 만들고, js/ 디렉토리 안에 [link:https://threejs.org/build/three.js three.js] 파일을 만들고 연결시켜 웹 브라우저로 실행해주세요.

            +

            three.js를 사용하려면, 표시할 수 있는 공간이 필요합니다. Save the following HTML to a file on your computer and open it in your browser.

            <!DOCTYPE html> @@ -27,8 +27,9 @@

            시작하기에 앞서

            </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; +´ // Our Javascript will go here. </script> </body> @@ -117,7 +118,7 @@

            큐브 애니메이팅

            결과 화면

            축하합니다! 첫 three.js이 완성되었네요. 이제 본격적으로 시작해보면 됩니다.

            -

            전체 코드는 아래에 나와 있고 [link:https://jsfiddle.net/fxurzeb4/ live example]로도 확인해볼 수 있습니다. 잘 살펴보고 어떻게 구동되는지 확인해 보세요.

            +

            전체 코드는 아래에 나와 있고 [link:https://jsfiddle.net/0c1oqf38/ live example]로도 확인해볼 수 있습니다. 잘 살펴보고 어떻게 구동되는지 확인해 보세요.

            <!DOCTYPE html> @@ -131,8 +132,9 @@

            결과 화면

            </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -154,7 +156,7 @@

            결과 화면

            cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/ko/introduction/How-to-run-things-locally.html b/docs/manual/ko/introduction/How-to-run-things-locally.html deleted file mode 100644 index 07ee684db11be0..00000000000000 --- a/docs/manual/ko/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - -

            로컬 환경에서 구동 방법([name])

            -

            - 만약 procedural geometries 만을 사용하고 다른 텍스쳐를 불러오지 않았다면, 웹페이지는 파일 매니저에서 HTML파일을 더블클릭하는 즉시 작업을 시작할 것이고, - 브라우저에서 바로 작업되는 화면이 나타날 것입니다. (주소창에 file:///yourFile.html 를 치면 확인이 될 것입니다.). -

            - -

            외부 파일에서 컨텐츠 불러오기

            -
            -

            - 외부 파일에서 모델이나 텍스쳐를 불러올 경우, 브라우저의' [link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy] - 보안 제한때문에 파일 불러오기가 실패가 될 것입니다. -

            - -

            이 문제의 해결법은 두 가지가 있습니다.

            - -
              -
            1. - 브라우저에서 로컬 파일의 보안설정을 변경합니다. 이를 통해file:///yourFile.html로 들어가 확인할 수 있을 것입니다. -
            2. -
            3. - 파일을 로컬 웹 서버에서 돌리는 방법입니다. http://localhost/yourFile.html로 들어가 확인할 수 있을 것입니다. -
            4. -
            - -

            - 1번 방법을 쓸 때, 일반 웹서핑을 같은 방식으로 쓰게되면 보안적으로 취약해지는 점을 인지해야 합니다. 안전한 개발을 위해 - 각각의 브라우저 프로필, 바로가기를 만드는 것도 좋습니다. 차례대로 방법을 알아봅시다. -

            -
            - - -

            로컬 서버에서 실행

            -
            -

            - 많은 프로그래밍 언어는 기본적으로 간단한 HTTP 서버가 설치되어 있습니다. [link:https://www.apache.org/ Apache]나 [link:https://nginx.org NGINX]같은 프로덕션용 정도로 갖추어져 있지는 않지만, three.js를 테스트해보기에는 충분합니다. -

            - -

            유명 코드 에디터 관련 플러그인

            -
            -

            몇몇 코드 에디터들은 간단한 서버를 필요할 때 구축할 수 있게 플러그인을 마련해 두고 있습니다.

            -
              -
            • Visual Studio Code의 [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] - .
            • -
            • Atom의 [link:https://atom.io/packages/atom-live-server Live Server].
            • -
            -
            - -

            Servez

            -
            -

            - [link:https://greggman.github.io/servez Servez]는 GUI 환경의 간단한 서버입니다. -

            -
            - -

            Node.js http-server

            -
            -

            Node.js에는 간단한 HTTP 서버 패키지가 있습니다. 설치 방법:

            - npm install http-server -g - -

            실행 (로컬 저장소에서):

            - http-server . -p 8000 -
            - -

            Python 서버

            -
            -

            - [link:http://python.org/ Python]이 설치되어 있다면, 커맨드라인으로 충분히 실행할 수 있습니다. (작업 디렉토리 내에서): -

            - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

            이 코드는 현재 디렉토리의 파일들을 localhost 8000번 포트로 내보내 줄 것입니다. 주소 예시는 다음과 같습니다. -

            - - http://localhost:8000/ -
            - -

            Ruby 서버

            -
            -

            Ruby가 설치되어 있다면, 아래 코드를 사용하면 같은 결과를 확인할 수 있습니다.

            - -ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
            - -

            PHP 서버

            -
            -

            PHP도 내장된 웹서버가 있어, php 5.4.0부터 다음과 같이 활용 가능합니다:

            - php -S localhost:8000 -
            - -

            Lighttpd

            -
            -

            - Lighttpd는 일반적인 목적의 아주 가벼운 웹서버입니다. 여기서에는 Homebrew를 통해 OSX에 설치하는 예를 소개해 보겠습니다. - 다른 서버들과는 달리, lighttpd 프로덕션 서버로 사용될 모든 것이 갖추어져 있습니다. -

            - -
              -
            1. - homebrew를 통해 설치합니다. - brew install lighttpd -
            2. -
            3. - 웹서버에서 실행하고자 하는 디렉토리에 lighttpd.conf라는 설정파일을 만듭니다. - 예제는 여기([link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration link])에서 확인할 수 있습니다. -
            4. -
            5. - 설정 파일에서, server.document-root를 서버로 쓰고자 하는 디렉토리로 설정합니다. -
            6. -
            7. - 다음과 같이 실행합니다. - lighttpd -f lighttpd.conf -
            8. -
            9. - http://localhost:3000/ 로 들어가면 선택한 디렉토리의 파일들을 보여줄 것입니다. -
            10. -
            -
            -

            IIS

            -
            -

            마이크로소프트 IIS를 웹서버로 사용한다면, 실행하기에 앞서 .fbx 확장자와 관련된 MIME 타입 설정을 추가해야 합니다.

            - File name extension: fbx MIME Type: text/plain -

            기본적으로 IIS는 .fbx, .obj 파일의 다운로드를 막아 놓았습니다. IIS에서 이러한 파일들이 다운로드 될 수 있도록 설정해야 합니다.

            -
            -

            - 다른 간단한 방법으로는 Stack Overflow에서 논의된 내용([link:http://stackoverflow.com/q/12905426/24874 link])을 확인해 보세요. -

            -
            - - - - \ No newline at end of file diff --git a/docs/manual/ko/introduction/How-to-update-things.html b/docs/manual/ko/introduction/How-to-update-things.html index 2c170a88f4b978..748a453658d8d8 100644 --- a/docs/manual/ko/introduction/How-to-update-things.html +++ b/docs/manual/ko/introduction/How-to-update-things.html @@ -77,20 +77,17 @@

            BufferGeometry

            그 다음, 아래와 같은 패턴으로 무작위로 선에 점을 생성해 줄 것입니다:

            -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); - x += ( Math.random() - 0.5 ) * 30; - y += ( Math.random() - 0.5 ) * 30; - z += ( Math.random() - 0.5 ) * 30; + x += ( Math.random() - 0.5 ) * 30; + y += ( Math.random() - 0.5 ) * 30; + z += ( Math.random() - 0.5 ) * 30; } @@ -104,7 +101,7 @@

            BufferGeometry

            첫 렌더링 이후에 position 데이터 수치를 변경하고 싶다면, needsUpdate 플래그를 다음과 같이 설정해야 합니다:

            -line.geometry.attributes.position.needsUpdate = true; // required after the first render +positionAttribute.needsUpdate = true; // required after the first render

            diff --git a/docs/manual/ko/introduction/Installation.html b/docs/manual/ko/introduction/Installation.html index 0feb01f3884355..023627d39e950d 100644 --- a/docs/manual/ko/introduction/Installation.html +++ b/docs/manual/ko/introduction/Installation.html @@ -77,7 +77,7 @@

            static hosting 및 CDN을 통한 설치

            -<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> +<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -122,7 +122,7 @@

            Addons

            -<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> +<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { diff --git a/docs/manual/ko/introduction/Loading-3D-models.html b/docs/manual/ko/introduction/Loading-3D-models.html index cd410cda7309a6..12a4f05396d25f 100644 --- a/docs/manual/ko/introduction/Loading-3D-models.html +++ b/docs/manual/ko/introduction/Loading-3D-models.html @@ -27,7 +27,7 @@

            시작하기에 앞서

            로컬 서버를 돌리는 것이 처음이라면, - [link:#manual/introduction/How-to-run-things-locally how to run things locally] + [link:#manual/introduction/Installation installation] 를 먼저 확인하세요. 3D 모델의 대부분의 에러는 파일을 알맞게 호이스팅하는 것으로 해결할 수 있습니다.

            diff --git a/docs/manual/ko/introduction/WebGL-compatibility-check.html b/docs/manual/ko/introduction/WebGL-compatibility-check.html index 86c25ab993f440..1743d155994932 100644 --- a/docs/manual/ko/introduction/WebGL-compatibility-check.html +++ b/docs/manual/ko/introduction/WebGL-compatibility-check.html @@ -11,13 +11,12 @@

            WebGL 호환성 검사([name])

            아마 거의 문제가 되지 않을테지만, 몇몇 디바이스나 브라우저는 아직 WebGL을 지원하지 않습니다. 아래 메서드는 지원 여부를 체크해 가능한지 아닌지 메세지를 띄워줄 것입니다. -

            - -

            - [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js]를 스크립트에 추가하고 무언가를 렌더링하기 전에 아래 코드를 실행해보세요. + WebGL 지원 감지 모듈을 가져오고 렌더링을 시도하기 전에 다음을 실행하십시오.

            + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here diff --git a/docs/manual/pt-br/buildTools/Testing-with-NPM.html b/docs/manual/pt-br/buildTools/Testing-with-NPM.html deleted file mode 100644 index f56e18cf8ebb0d..00000000000000 --- a/docs/manual/pt-br/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - - - - -

            Testando com NPM

            - -

            - Este artigo mostra como colocar o three.js em um ambiente [link:https://nodejs.org/en/ node.js] para que você - possa executar testes automatizados. Os testes podem ser executados na linha de comando ou por - ferramentas de CI como [link:https://travis-ci.org/ Travis]. -

            - -

            A versão curta

            - -

            - Se você estiver confortável com node e npm, - - $ npm install three --save-dev - - e adicione - - const THREE = require('three'); - - para o seu teste. -

            - -

            Criar um projeto testável do zero

            -

            - Se você não estiver familiarizado com essas ferramentas, aqui está um guia rápido (para linux, o processo de instalação - será um pouco diferente do que usando o Windows, mas os comandos do NPM são idênticos). -

            - -

            Configuração básica

            -
            -
              -
            1. - Instale o [link:https://www.npmjs.org/ npm] e o nodejs. O caminho mais curto normalmente parece algo como - -$ sudo apt-get install -y npm nodejs-legacy -# fix any problems with SSL in the default registry URL -$ npm config set registry http://registry.npmjs.org/ - -
            2. - -
            3. - Crie um novo diretório de projeto - - $ mkdir test-example; cd test-example - -
            4. - -
            5. - Peça ao npm para criar um novo arquivo de projeto para você: - - $ npm init - - e aceite todas as opções default pressionando Enter em todos os prompts. - Isso criará o package.json. -

            6. - -
            7. - Experimente iniciar o recurso de teste com - -$ npm test - - Isso falhará, o que é esperado. - Se você olhar no package.json, a definição do script de teste é - - "test": "echo \"Error: no test specified\" && exit 1" - -
            8. - -
            -
            - -

            Adicionar mocha

            -
            - Vamos usar o [link:https://mochajs.org/mocha]. - -
              -
            1. - Instale o mocha com - -$ npm install mocha --save-dev - - Observe que a pasta node_modules/ é criada e suas dependências aparecem lá. - Observe também que seu package.json foi atualizado: a propriedade devDependencies - é adicionada e atualizada pelo uso de --save-dev. -

            2. - -
            3. - Edite o package.json para usar o mocha para teste. Quando o teste for chamado, queremos apenas executar - o mocha e especificar um relatório detalhado. Por padrão, isso executará qualquer coisa em test/ - (não ter a pasta test/ pode levar a um ERR! no npm, crie-a pelo comando mkdir test) - - "test": "mocha --reporter list" - -
            4. - -
            5. - Reexecute o teste com - - $ npm test - - Isso agora deve correr bem, reportando "0 passing (1ms)" - ou similar. -
            6. - -
            -
            - -

            Adicionar three.js

            -
            -
              -
            1. - Vamos baixar nossa dependência three.js com - -$ npm install three --save-dev - -
                -
              • - Se você precisar de uma versão diferente do three.js, use - - $ npm show three versions - - para listar o que está disponível. Para escolher pelo npm a versão correta, use - - $ npm install three@0.84.0 --save - - (0.84.0 nesse exemplo). --save torna isso uma dependência do projeto, em vez de - dependência dev. Veja os documentos [link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json aqui] para mais informações. -
              • -
              -
            2. - -
            3. - Mocha irá procurar por testes em test/, então vamos executar - - $ mkdir test - -
            4. - -
            5. - Finalmente, precisamos de um teste JS para ser executado. Vamos adicionar um teste simples que verificará que - o objeto three.js está disponível e funcionando. Crie test/verify-three.js contendo: - -const THREE = require('three'); -const assert = require('assert'); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
            6. - -
            7. - Finalmente vamos testar novamente com $ npm test. Isso deve executar os testes acima e ter sucesso, - mostrando algo como: - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
            8. -
            -
            - -

            Adicione seu próprio código

            -
            - Você precisa fazer três coisas: - -
              -
            1. - Escreva um teste para o comportamento esperado do seu código e coloque-o em test/. - [link:https://github.com/air/encounter/blob/master/test/Physics-test.js aqui] tem um exemplo de um projeto real. -
            2. - -
            3. - Exporte seu código funcional de forma que o nodejs possa vê-lo, para uso em conjunto com require. - Veja isso [link:https://github.com/air/encounter/blob/master/js/Physics.js aqui]. -
            4. - -
            5. - Requisite seu código no arquivo de teste, da mesma forma que fizemos um require('three') no exemplo acima. -
            6. -
            - -

            - Os itens 2 e 3 variam dependendo de como você gerencia seu código. No exemplo de Physics.js - dado acima, a parte de exportação está bem no final. Atribuímos um objeto a module.exports: -

            - -//============================================================================= -// make available in nodejs -//============================================================================= -if (typeof exports !== 'undefined') -{ - module.exports = Physics; -} - -
            - -

            Lidando com dependências

            -
            -

            - Se você já estiver usando algo como require.js ou browserify, pule esta parte. -

            -

            - Normalmente, um projeto three.js será executado no navegador. O carregamento do módulo é, portanto, feito pelo - navegador, executando um monte de tags de script. Seus arquivos individuais não precisam se preocupar - com dependências. No entanto, em um contexto nodejs, não há index.html vinculando tudo - junto, então você tem que ser explícito. -

            -

            - Se você estiver exportando um módulo que depende de outros arquivos, precisará dizer ao node para carregá-los. - Aqui está uma abordagem: -

            -
              -
            1. - No início do seu módulo, verifique se você está em um ambiente nodejs. -
            2. -
            3. - Em caso afirmativo, declare explicitamente suas dependências. -
            4. -
            5. - Caso contrário, você provavelmente está em um navegador, então não precisa fazer mais nada. -
            6. -
            - Código de exemplo de Physics.js: - -//============================================================================= -// setup for server-side testing -//============================================================================= -if (typeof require === 'function') // test for nodejs environment -{ - const THREE = require('three'); - const MY3 = require('./MY3.js'); -} - -
            - - - diff --git a/docs/manual/pt-br/introduction/Color-management.html b/docs/manual/pt-br/introduction/Color-management.html index 209cc3e8a0ab51..01cd9526a48cda 100644 --- a/docs/manual/pt-br/introduction/Color-management.html +++ b/docs/manual/pt-br/introduction/Color-management.html @@ -156,13 +156,13 @@

            Input do espaço de cores

            Cores fornecidas ao three.js — de seletores de cores, texturas, modelos 3D e outras fontes — cada um tem um espaço de cor associado. Aqueles que ainda não estão na cor de trabalho Linear-sRGB, - devem ser convertidos e as texturas devem receber a atribuição texture.encoding correta. + devem ser convertidos e as texturas devem receber a atribuição texture.colorSpace correta. Certas conversões (para cores hexadecimais e CSS em sRGB) podem ser feitas automaticamente se o modo de gerenciamento de cores herdado é desabilitado antes de inicializar as cores:

            -THREE.ColorManagement.legacyMode = false; +THREE.ColorManagement.enabled = true;
              @@ -177,14 +177,14 @@

              Input do espaço de cores

            • Texturas de cores: PNG ou JPEG [page:Texture Textures] contendo informações de cores (como .map ou .emissiveMap) usam o espaço de cores sRGB de domínio fechado e devem ser anotados com - texture.encoding = sRGBEncoding. Formatos como OpenEXR (às vezes usado para .envMap ou - .lightMap) usam o espaço de cores Linear-sRGB indicado com texture.encoding = LinearEncoding, + texture.colorSpace = SRGBColorSpace. Formatos como OpenEXR (às vezes usado para .envMap ou + .lightMap) usam o espaço de cores Linear-sRGB indicado com texture.colorSpace = LinearSRGBColorSpace, e podem conter valores no domínio aberto [0,∞].
            • Texturas não coloridas: Texturas que não armazenam informações de cores (como .normalMap ou .roughnessMap) não têm um espaço de cores associado e geralmente usam a textura (padrão) - como texture.encoding = LinearEncoding. Em casos raros, dados sem cor + como texture.colorSpace = NoColorSpace. Em casos raros, dados sem cor podem ser representados com outras codificações não lineares por motivos técnicos.
            @@ -211,11 +211,11 @@

            Output do espaço de cores

            A saída para um dispositivo de exibição, imagem ou vídeo pode envolver a conversão do domínio aberto do espaço de cores de trabalho linear-sRGB para outro espaço de cores. Essa conversão pode ser feita em - uma passagem de renderização principal ([page:WebGLRenderer.outputEncoding]), ou durante o pós-processamento. + uma passagem de renderização principal ([page:WebGLRenderer.outputColorSpace]), ou durante o pós-processamento.

            -renderer.outputEncoding = THREE.sRGBEncoding; // optional with post-processing +renderer.outputColorSpace = THREE.SRGBColorSpace; // optional with post-processing
              @@ -243,6 +243,11 @@

              Output do espaço de cores

              +

              + Custom materials based on [page:ShaderMaterial] and [page:RawShaderMaterial] have to implement their own output color space conversion. + For instances of `ShaderMaterial`, adding the `encodings_fragment` shader chunk to the fragment shader's `main()` function should be sufficient. +

              +

              Trabalhando com instâncias THREE.Color

              @@ -265,7 +270,7 @@

              Trabalhando com instâncias THREE.Color

              - Com ColorManagement.legacyMode = false definido (recomendado), determinadas conversões + Com ColorManagement.enabled = true definido (recomendado), determinadas conversões são feitas automaticamente. Como as cores hexadecimais e CSS geralmente são sRGB, métodos [page:Color] irão converter automaticamente essas entradas de sRGB para Linear-sRGB em setters, ou converter de Linear-sRGB para sRGB ao retornar hexadecimal ou CSS de getters. diff --git a/docs/manual/pt-br/introduction/Creating-a-scene.html b/docs/manual/pt-br/introduction/Creating-a-scene.html index 50b128dc98d4dd..9e63cc14ff64a2 100644 --- a/docs/manual/pt-br/introduction/Creating-a-scene.html +++ b/docs/manual/pt-br/introduction/Creating-a-scene.html @@ -13,7 +13,7 @@

              Criando uma cena

              Antes de começar

              -

              Antes de começar usar o three.js, você precisa de algum lugar para mostrá-lo. Salve o HTML abaixo em um arquivo no seu computador, junto com uma cópia do [link:https://threejs.org/build/three.js three.js] na pasta js/, e abra o arquivo no navegador.

              +

              Antes de começar usar o three.js, você precisa de algum lugar para mostrá-lo. Salve o HTML abaixo em um arquivo no seu computador e abra o arquivo no navegador.

              <!DOCTYPE html> @@ -26,8 +26,9 @@

              Antes de começar

              </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + // Our Javascript will go here. </script> </body> @@ -60,9 +61,7 @@

              Criando a cena

              Os próximos dois atributos são os planos de corte `near` e `far`. Isso significa que os objetos mais distantes da câmera do que o valor `far` ou mais próximos que o valor `near` não serão renderizados. Você não precisa se preocupar com isso agora, mas pode ser necessário usar outros valores em seus apps para obter uma melhor performance.

              -

              Em seguida temos o renderizador. É aqui que a mágica acontece. Além do WebGLRenderer que usamos aqui, three.js vem com alguns outros, frequentemente usados como substitutos para usuários com navegadores antigos ou para aqueles que não possuem suporte para WebGL por algum motivo.

              - -

              Além da criação da intância do renderizador, nós também precisamos configurar o tamanho em que queremos renderizar nossa aplicação. É uma boa ideia usar o comprimento e a altura da área que queremos preencher com nossa aplicação - no nosso caso, o comprimento e altura da janela do navegador. Para aplicativos de alto desempenho, você pode fornecer valores menores para o `setSize`, como `window.innerWidth/2` e `window.innerHeight/2`, o que fará com que a aplicação seja renderizada no tamanho de um quarto do original.

              +

              Em seguida temos o renderizador. É aqui que a mágica acontece. Além da criação da intância do renderizador, nós também precisamos configurar o tamanho em que queremos renderizar nossa aplicação. É uma boa ideia usar o comprimento e a altura da área que queremos preencher com nossa aplicação - no nosso caso, o comprimento e altura da janela do navegador. Para aplicativos de alto desempenho, você pode fornecer valores menores para o `setSize`, como `window.innerWidth/2` e `window.innerHeight/2`, o que fará com que a aplicação seja renderizada no tamanho de um quarto do original.

              Se você deseja manter o tamanho do seu aplicativo mas renderizá-lo em uma resolução mais baixa, você pode chamar o `setSize` passando false como `updateStyle` (o terceiro argumento). Por exemplo, `setSize(window.innerWidth/2, window.innerHeight/2, false)` irá renderizar sua aplicação na metade da resolução, já que seu elemento <canvas> tem 100% de comprimento e altura.

              @@ -118,7 +117,7 @@

              Animando o cubo

              O resultado

              Parabéns! Agora você concluiu seu primeiro aplicativo three.js. É simples, mas você tem que começar de algum lugar.

              -

              O código completo está disponível abaixo e como um [link:https://jsfiddle.net/fxurzeb4/ exemplo] editável. Brinque com ele para entender melhor como funciona.

              +

              O código completo está disponível abaixo e como um [link:https://jsfiddle.net/0c1oqf38/ exemplo] editável. Brinque com ele para entender melhor como funciona.

              <!DOCTYPE html> @@ -131,8 +130,9 @@

              O resultado

              </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -154,7 +154,7 @@

              O resultado

              cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/pt-br/introduction/How-to-run-things-locally.html b/docs/manual/pt-br/introduction/How-to-run-things-locally.html deleted file mode 100644 index f062fb4cc7d9f2..00000000000000 --- a/docs/manual/pt-br/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - - - -

              Como executar localmente

              - -

              - Se você usar apenas geometrias procedurais e não carregar nenhuma textura, - as páginas web devem funcionar direto do sistema de arquivos, bastando clicar duas vezes - no arquivo HTML em um gerenciador de arquivos para então funcionar no navegador (você verá file:///yourFile.html na barra de endereço). -

              - -

              Conteúdo carregado de arquivos externos

              - -
              -

              - Se você carregar modelos ou texturas de arquivos externos, devido a [link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy] - dos navegadores, o carregamento de um sistema de arquivos falhará com uma exceção de segurança. -

              - -

              - Para resolver isso, execute os arquivos de um servidor web local. Isso permitirá acessar a página por: -

              - -

              - http://localhost/yourFile.html -

              - -

              - Embora também seja possível alterar as configurações de segurança do navegador ao invés de executar - um servidor local, não recomendamos essa abordagem. Isso pode abrir seu dispositivo para vulnerabilidades, - se o mesmo navegador é usado para navegação regular na web. O uso de um servidor local é uma prática padrão - em desenvolvimento web e explicamos abaixo como instalar e usar um servidor local. -

              -
              - - -

              Rodando um servidor local

              -
              -

              - Muitas linguagens de programação têm servidores HTTP simples embutidos. Eles não são tão - completos quanto servidores de produção como o [link:https://www.apache.org/ Apache] ou o - [link:https://nginx.org NGINX], no entanto devem ser suficientes para testar sua aplicação three.js. -

              - -

              Plugins para editores populares de código

              -
              -

              - Alguns editores de código tem plugins que irão rodar um servidor simples. -

              -
                -
              • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] para Visual Studio Code.
              • -
              • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] para Visual Studio Code.
              • -
              • [link:https://atom.io/packages/atom-live-server Live Server] para Atom.
              • -
              -
              - -

              Servez

              -
              -

              - [link:https://greggman.github.io/servez Servez] é um servidor simples com uma interface gráfica. -

              -
              - -

              Node.js five-server

              -
              -

              - Servidor de desenvolvimento com live reload. Para instalar: -

              - -# Remove live-server (if you have it) -npm -g rm live-server - -# Install five-server -npm -g i five-server - -# Update five-server (from time to time) -npm -g i five-server@latest - - -

              Para executar (do seu diretório local):

              - five-server . -p 8000 -
              - -

              Node.js http-server

              -
              -

              - O Node.js tem um pacote simples de um servidor HTTP. Para instalar: -

              - npm install http-server -g - -

              Para executar (do seu diretório local):

              - http-server . -p 8000 -
              - -

              Servidor Python

              -
              -

              - Se você tem [link:http://python.org/ Python] instalado, deve ser suficiente para - executar esse comando (do seu diretório de trabalho): -

              - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

              Isso vai servir os arquivos do diretório atual para localhost na porta 8000, - isto é, na barra de endereço digite: -

              - - http://localhost:8000/ -
              - -

              Servidor Ruby

              -
              -

              - Se você tem Ruby instalado, você poder ter o mesmo resultado executando: -

              - - ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
              - -

              Servidor PHP

              -
              -

              PHP também tem um servidor web embutido, começando com php 5.4.0:

              - php -S localhost:8000 -
              - -

              Lighttpd

              -
              -

              - Lighttpd é um servidor web de uso geral muito leve. Abordaremos a instalação no OSX - com HomeBrew aqui. Ao contrário dos outros servidores discutidos, Lighttpd é um servidor - completo de produção. -

              - -
                -
              1. - Instale via homebrew - brew install lighttpd -
              2. -
              3. - Crie um arquivo de configuração chamado lighttpd.conf no diretório onde você irá executar - o servidor web. Um exemplo está [link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration aqui]. -
              4. -
              5. - No arquivo conf, mude o server.document-root para o diretório do qual você quer servir os arquivos. -
              6. -
              7. - Comece com - lighttpd -f lighttpd.conf -
              8. -
              9. - Navegue até http://localhost:8000/ e ele servirá os arquivos estáticos do diretório que você - escolheu. -
              10. -
              -
              -

              IIS

              -
              -

              - Se você estiver usando o Microsoft IIS como servidor web. Por favor adicione - configurações de tipo MIME em relação à extensão .fbx antes de carregar. -

              - File name extension: fbx MIME Type: text/plain -

              - Por padrão, o IIS bloqueia downloads de arquivos .fbx e .obj. Você tem que - configurar o IIS para habilitar que esse tipo de arquivo possa ser baixado. -

              -
              -

              - Outras alternativas simples são [link:http://stackoverflow.com/q/12905426/24874 discutidas aqui] no StackOverflow. -

              -
              - - - diff --git a/docs/manual/pt-br/introduction/How-to-update-things.html b/docs/manual/pt-br/introduction/How-to-update-things.html index b28f36f9f90a76..ada7574e838d2a 100644 --- a/docs/manual/pt-br/introduction/How-to-update-things.html +++ b/docs/manual/pt-br/introduction/How-to-update-things.html @@ -84,20 +84,17 @@

              BufferGeometry

              Em seguida, adicionaremos aleatoriamente pontos à linha usando um padrão como:

              -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); - x += ( Math.random() - 0.5 ) * 30; - y += ( Math.random() - 0.5 ) * 30; - z += ( Math.random() - 0.5 ) * 30; + x += ( Math.random() - 0.5 ) * 30; + y += ( Math.random() - 0.5 ) * 30; + z += ( Math.random() - 0.5 ) * 30; } @@ -112,7 +109,7 @@

              BufferGeometry

              definir a propriedade needsUpdate assim:

              -line.geometry.attributes.position.needsUpdate = true; // required after the first render +positionAttribute.needsUpdate = true; // required after the first render

              diff --git a/docs/manual/pt-br/introduction/Installation.html b/docs/manual/pt-br/introduction/Installation.html index 8fa7c182e7787f..f5548c24daa31a 100644 --- a/docs/manual/pt-br/introduction/Installation.html +++ b/docs/manual/pt-br/introduction/Installation.html @@ -53,7 +53,7 @@

              Instalar através de CDN ou hospedagem estática

              A biblioteca three.js pode ser utilizada sem nenhum sistema de build, seja fazendo o upload dos arquivos para seu próprio servidor web ou usando um CDN existente. Como a biblioteca depende dos ES modules, qualquer script que faça referência a eles deve usar type="module" como mostrado abaixo. Também é necessário definir um mapa de importação que resolva a importação direta do `three`.

              - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -99,7 +99,7 @@

              Addons

              Se o three.js foi instalado de um CDN, use o mesmo CDN para instalar outros componentes:

              - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { diff --git a/docs/manual/pt-br/introduction/Loading-3D-models.html b/docs/manual/pt-br/introduction/Loading-3D-models.html index cc47bb69a49161..f4351f3b8b486d 100644 --- a/docs/manual/pt-br/introduction/Loading-3D-models.html +++ b/docs/manual/pt-br/introduction/Loading-3D-models.html @@ -29,7 +29,7 @@

              Antes de começar

              Se você é iniciante na execução de um servidor local, comece com - [link:#manual/introduction/How-to-run-things-locally Como executar localmente] + [link:#manual/introduction/Installation installation] primeiro. Muitos erros comuns de visualização de modelos 3D podem ser evitados hospedando arquivos corretamente.

              diff --git a/docs/manual/pt-br/introduction/WebGL-compatibility-check.html b/docs/manual/pt-br/introduction/WebGL-compatibility-check.html index 93e327fdd521b1..fcb0d97cf51a91 100644 --- a/docs/manual/pt-br/introduction/WebGL-compatibility-check.html +++ b/docs/manual/pt-br/introduction/WebGL-compatibility-check.html @@ -10,14 +10,14 @@

              Compatibilidade WebGL

              - Mesmo que isso esteja se tornando um problema cada vez menor, alguns dispositivos ou navegadores podem ainda não suportar WebGL. O método a seguir permite verificar se há suporte e exibe uma mensagem para o usuário se não existir. -

              - -

              - Adicione [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] ao seu JavaScript e execute o seguinte código antes de tentar renderizar qualquer coisa. + Mesmo que isso esteja se tornando um problema cada vez menor, alguns dispositivos ou navegadores podem ainda não suportar WebGL. + O método a seguir permite verificar se há suporte e exibe uma mensagem para o usuário se não existir. + Importe o módulo de detecção de suporte WebGL e execute o seguinte antes de tentar renderizar qualquer coisa.

              + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Initiate function or other initializations here diff --git a/docs/manual/ru/introduction/Creating-a-scene.html b/docs/manual/ru/introduction/Creating-a-scene.html index 8aa955e64e63cf..2adc7aa3e46039 100644 --- a/docs/manual/ru/introduction/Creating-a-scene.html +++ b/docs/manual/ru/introduction/Creating-a-scene.html @@ -14,7 +14,7 @@

              Создание сцены

              Прежде чем мы начнем

              - Прежде чем вы сможете использовать three.js , вам нужно где-то его отобразить. Сохраните следующий HTML-код в файл на вашем компьютере вместе с копией [link:https://threejs.org/build/three.js three.js] в каталоге js/ и откройте его в своем браузере. + Прежде чем вы сможете использовать three.js , вам нужно где-то его отобразить. Save the following HTML to a file on your computer and open it in your browser.

              @@ -28,8 +28,9 @@

              Прежде чем мы начнем

              </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + // Наш Javascript будет здесь.. </script> </body> @@ -115,7 +116,7 @@

              Результат

              Поздравляю! Теперь вы завершили свой первый three.js применение. Это просто, но вы должны с чего-то начать.

              -

              Полный код доступен ниже и доступен для редактирования [link:https://jsfiddle.net/fxurzeb4/ live example]. Поиграйте с ним, чтобы лучше понять, как он работает.

              +

              Полный код доступен ниже и доступен для редактирования [link:https://jsfiddle.net/0c1oqf38/ live example]. Поиграйте с ним, чтобы лучше понять, как он работает.

              <!DOCTYPE html> @@ -128,8 +129,9 @@

              Результат

              </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -151,7 +153,7 @@

              Результат

              cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/ru/introduction/How-to-run-things-locally.html b/docs/manual/ru/introduction/How-to-run-things-locally.html deleted file mode 100644 index 291166d06ecad4..00000000000000 --- a/docs/manual/ru/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - -

              Локальная разработка ([name])

              -

              - Если вы используете только процедурную геометрию и не загружаете никаких текстур, веб-страницы должны работать - прямо из файловой системы, просто дважды щелкните по HTML-файлу в файловом менеджере, и он - должен появиться в браузере (вы увидите file:///вашФайл.html в адресной строке). -

              - -

              Контент загружен из внешних файлов

              -
              -

              - Если вы загружаете модели или текстуры из внешних файлов, из-за того, что браузеры - [link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy](политика одинакового происхождения) - ограничения безопасности, загрузка из файловой системы завершится ошибкой с исключением безопасности. -

              - -

              - Чтобы решить эту проблему, запустите файлы с локального веб-сервера. Это позволит вам получить доступ к вашей - странице как: -

              - -

              - http://localhost/yourFile.html -

              - -

              - Хотя также можно изменить настройки безопасности браузера вместо запуска локального сервера, - мы не рекомендуем такой подход. Это может открыть ваше устройство для уязвимостей, если - тот же браузер используется для обычного веб-серфинга. Использование локального сервера является стандартной - практикой в - веб-разработки, и ниже мы объясним, как установить и использовать локальный сервер. -

              -
              - - -

              Запуск локального сервера

              -
              -

              - Многие языки программирования имеют встроенные простые HTTP-серверы. Они не так полнофункциональны, как - рабочие серверы, такие как [link:https://www.apache.org/ Apache] или [link:https://nginx.org NGINX], однако их - должно быть достаточно для тестирования вашего - three.js приложение. -

              - -

              Плагины для популярных редакторов кода

              -
              -

              В некоторых редакторах кода есть плагины, которые по запросу создают простой сервер.

              -
                -
              • [link:https://marketplace.visualstudio.com/items?itemName=yandeu.five-server Five Server] для Visual - Studio Code. -
              • -
              • [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] для Visual - Studio Code. -
              • -
              • [link:https://atom.io/packages/atom-live-server Live Server] для Atom.
              • -
              • для ide от jetbrains уже все из коробки (как всегда)
              • -
              -
              - -

              Servez

              -
              -

              - [link:https://greggman.github.io/servez Servez] это простой сервер с графическим интерфейсом. -

              -
              - -

              Node.js five-server

              -
              -

              Сервер разработки с возможностью горячей перезагрузки. Установка:

              - - - # Удалите live-server (если он у вас есть) - npm -g rm live-server - - # Установите five-server - npm -g i five-server - - # Обновление five-server (иногда) - npm -g i five-server@latest - - -

              Для запуска (из вашей локальной директории):

              - five-server . -p 8000 -
              - -

              Node.js http-server

              -
              -

              Node.js имеет простой пакет HTTP-сервера. Установка:

              - npm install http-server -g - -

              Для запуска (из вашей локальной директории):

              - http-server . -p 8000 -
              - -

              Python сервер

              -
              -

              - Если у вас установлен [link:http://python.org/ Python], этого должно быть достаточно для запуска - из командной строки (из вашей локальной директории): -

              - - //Python 2.x - python -m SimpleHTTPServer - - //Python 3.x - python -m http.server - - -

              Это поднимет сервер для файлов из текущего каталога на localhost на порте 8000, т.е. в адресной строке - введите:

              - - http://localhost:8000/ -
              - -

              Ruby сервер

              -
              -

              Если у вас установлен Ruby, вы можете получить тот же результат, выполнив:

              - - ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
              - -

              PHP сервер

              -
              -

              PHP также имеет встроенный веб-сервер, начиная с php 5.4.0:

              - php -S localhost:8000 -
              - -

              Lighttpd

              -
              -

              - Lighttpd - это очень легкий веб-сервер общего назначения. Мы рассмотрим установку его на OSX с помощью - HomeBrew. В отличие от других серверов, обсуждаемых здесь, lighttpd является полноценным прод. сервером. -

              - -
                -
              1. - Установка с помощью homebrew - brew install lighttpd -
              2. -
              3. - Создайте конфигурационный файл с именем lighttpd.conf в каталоге, в котором вы хотите запустить - ваш веб-сервер. Пример [link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration - here]. -
              4. -
              5. - В файле conf измените корневой каталог server.document на каталог, из которого вы хотите обслуживать - файлы. -
              6. -
              7. - Запуск - lighttpd -f lighttpd.conf -
              8. -
              9. - Перейдите в http://localhost:3000/ и он будет обслуживать статические файлы из каталога, который вы - выбрали. -
              10. -
              -
              -

              IIS

              -
              -

              Если вы используете Microsoft IIS в качестве веб-сервера. Пожалуйста, добавьте настройки типа MIME для - расширения .fbx перед загрузкой.

              - File name extension: fbx MIME Type: text/plain -

              По умолчанию IIS блокирует загрузку файлов .fbx, .obj. Вы должны настроить IIS, чтобы такие файлы можно было - загружать.

              -
              -

              - Другими простыми альтернативами являются [link:http://stackoverflow.com/q/12905426/24874 discussed - here](обсуждается здесь) - на Stack Overflow. -

              -
              - - - diff --git a/docs/manual/ru/introduction/Installation.html b/docs/manual/ru/introduction/Installation.html index c79b43221257c4..663783a29fc8b2 100644 --- a/docs/manual/ru/introduction/Installation.html +++ b/docs/manual/ru/introduction/Installation.html @@ -92,7 +92,7 @@

              Установка с CDN или статического хостинга - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -143,7 +143,7 @@

              Дополнения

              - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { diff --git a/docs/manual/ru/introduction/Loading-3D-models.html b/docs/manual/ru/introduction/Loading-3D-models.html index 0e95b7849bb7ea..1391f1a3ec1167 100644 --- a/docs/manual/ru/introduction/Loading-3D-models.html +++ b/docs/manual/ru/introduction/Loading-3D-models.html @@ -30,7 +30,7 @@

              Если вы новичок в управлении локальным сервером, начните с раздела - [link:#manual/introduction/How-to-run-things-locally how to run things locally] (Локальная разработка). + [link:#manual/introduction/Installation installation] (Локальная разработка). Многих распространенных ошибок при просмотре 3D-моделей можно избежать, правильно разместив файлы.

              diff --git a/docs/manual/ru/introduction/WebGL-compatibility-check.html b/docs/manual/ru/introduction/WebGL-compatibility-check.html index 3ceef1f546f1e2..9852f465884f8e 100644 --- a/docs/manual/ru/introduction/WebGL-compatibility-check.html +++ b/docs/manual/ru/introduction/WebGL-compatibility-check.html @@ -11,14 +11,12 @@

              Проверка совместимости с WebGL ([name])

              Несмотря на то, что это становится все менее и менее серьезной проблемой, но все еще некоторые устройства или браузеры могут не поддерживать WebGL. Следующий метод позволяет вам проверить, поддерживается ли он, и отобразить сообщение пользователю, если это не так. -

              - -

              - Добавьте [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/capabilities/WebGL.js] - к вашему javascript и выполните следующее, прежде чем пытаться что-либо отобразить. + Импортируйте модуль обнаружения поддержки WebGL и выполните следующее, прежде чем пытаться что-либо отобразить.

              + import WebGL from 'three/addons/capabilities/WebGL.js'; + if ( WebGL.isWebGLAvailable() ) { // Инициализируйте функцию или другие инициализации здесь diff --git a/docs/manual/zh/buildTools/Testing-with-NPM.html b/docs/manual/zh/buildTools/Testing-with-NPM.html deleted file mode 100644 index e5572b33b68b6b..00000000000000 --- a/docs/manual/zh/buildTools/Testing-with-NPM.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - - - -

              使用NPM进行测试([name])

              - -

              - 这篇文章展示了如何将three.js置入[link:https://nodejs.org/en/ node.js]环境中, - 这样你就可以执行自动化测试了。测试可以通过命令行或者类似[link:https://travis-ci.org/ Travis]的CI工具来运行。 -

              - -

              一句话概括

              - -

              - 如果你习惯使用node和npm, - - $ npm install three --save-dev - - 并将 - - const THREE = require('three'); - - 添加到你的测试中。 -

              - -

              从头创建一个可测试的项目

              -

              - 如果你不太熟悉这些工具,下面是一个快速入门。(基于linux,在windows上的安装过程会稍稍有点不一样,不过NPM指令是相同的。) -

              - -

              基本设置

              -
              -
                -
              1. - 安装[link:https://www.npmjs.org/ npm]和nodejs。最简单的方式一般像这样 - -$ sudo apt-get install -y npm nodejs-legacy -# 修复默认registry URL中任何SSL的问题 -$ npm config set registry http://registry.npmjs.org/ - -
              2. - -
              3. - 新建一个项目路径 - - $ mkdir test-example; cd test-example - -
              4. - -
              5. - 让npm为你创建一份新的项目文件: - - $ npm init - - 在所有出现的提示中敲击回车键来接受默认值。 - 这样,一份package.json就建立好了。 -

              6. - -
              7. - 尝试启动测试功能 - -$ npm test - - 当然,这一定会失败。 - 如果你检查一下package.json,test script的定义是这样的 - - "test": "echo \"Error: no test specified\" && exit 1" - -
              8. - -
              -
              - -

              添加mocha

              -
              - 我们将使用[link:https://mochajs.org/ mocha]。 - -
                -
              1. - 安装mocha - -$ npm install mocha --save-dev - - 你会注意到 node_modules/ 被创建了,并且你的依赖都出现在了这里面。 - 还有你的package.json被更新了,--save-dev指令向其中加入并更新了devDependencies属性。 -

              2. - -
              3. - 编辑package.json来使用mocha进行测试。当调用测试的时候,我们只想运行mocha并且生成一份详细的报告。 - 默认情况下这会运行 test/ 中的任何东西。 - (如果项目中没有 test/ 目录的话,会导致npm报错。你可以通过mkdir test来创建这个目录) - - "test": "mocha --reporter list" - -
              4. - -
              5. - 重新运行测试 - - $ npm test - - - 现在应该就能成功执行了,生成类似 0 passing (1ms) 的报告。 -
              6. - -
              -
              - -

              添加three.js

              -
              -
                -
              1. - 现在添加我们的three.js依赖 - -$ npm install three --save-dev - -
                  -
                • - 如果你需要three.js的其他版本,使用 - - $ npm show three versions - - 来确认哪些是可用的。要让npm使用正确的版本,执行 - - $ npm install three@0.84.0 --save - - (例子中用的是0.84.0)。 --save 指令将此加入项目的dependency而不是dev dependency。 - 更多信息请参阅[link:https://docs.npmjs.com/cli/v8/configuring-npm/package-json 这份文档]。 -
                • -
                -
              2. - -
              3. - Mocha会在 test/ 目录中寻找测试文件,所以我们先创建这个目录: - - $ mkdir test - -
              4. - -
              5. - 最后我们需要一份JS测试文件来运行。我们就添加一段简单的测试程序,这段程序会检验three.js对象是否能正常工作。 - 在 test/ 目录下创建verify-three.js包含以下代码: - -const THREE = require('three'); -const assert = require("assert"); - -describe('The THREE object', function() { - it('should have a defined BasicShadowMap constant', function() { - assert.notEqual('undefined', THREE.BasicShadowMap); - }), - - it('should be able to construct a Vector3 with default of x=0', function() { - const vec3 = new THREE.Vector3(); - assert.equal(0, vec3.x); - }) -}) - -
              6. - -
              7. - 最后再次通过$ npm test来测试。这次应该能正确执行上面的代码,并且返回类似: - -The THREE object should have a defined BasicShadowMap constant: 0ms -The THREE object should be able to construct a Vector3 with default of x=0: 0ms -2 passing (8ms) - -
              8. -
              -
              - -

              加入你自己的代码

              -
              - 你需要做下面三件事: - -
                -
              1. - 为你的代码写一段测试程序来检验期望结果,并把它放在 test/ 目录下。 - [link:https://github.com/air/encounter/blob/master/test/Physics-test.js 这里]有一个实际项目的例子。 -
              2. - -
              3. - 将你的代码以nodejs承认的方式导出,即可以通过require的方式引用。 - 参考[link:https://github.com/air/encounter/blob/master/js/Physics.js 这份代码]。 -
              4. - -
              5. - 在测试程序中通过require引入你自己的代码,就像上面例子中我们通过require('three')来引入一样。 -
              6. -
              - -

              - 第2、3条会根据你组织代码的方式而改变。在上面给出的Physics.js的例子中,导出的部分在代码的最末尾。 - 我们将module.exports赋值为一个对象: -

              - -//============================================================================= -// 为了在nodejs中可用 -//============================================================================= -if (typeof exports !== 'undefined') -{ - module.exports = Physics; -} - -
              - -

              处理依赖

              -
              -

              - 如果你已经在使用require.js或者browserify之类的便捷工具,就跳过这个部分。 -

              -

              - 一般来说,一个three.js项目将在浏览器中运行,浏览器会通过执行一系列script标签来加载模块。 - 你自己的文件不用考虑依赖的问题。然而在nodejs环境中,没有一个关联所有文件的index.html,所以你需要显式地加载。 -

              -

              - 如果你要导出的模块还依赖其他文件,你需要告诉node去加载它们。下面是一种方式: -

              -
                -
              1. - 在你的模块顶部,检查是否处于nodejs环境中。 -
              2. -
              3. - 如果是,那就显式地声明你的依赖。 -
              4. -
              5. - 如果不是,你多半处于浏览器环境中。这时候你不需要做任何多余操作。 -
              6. -
              - 用Physics.js中的代码举例: - -//============================================================================= -// 服务器端测试配置 -//============================================================================= -if (typeof require === 'function') // 检测nodejs环境 -{ - const THREE = require('three'); - const MY3 = require('./MY3.js'); -} - -
              - - - diff --git a/docs/manual/zh/introduction/Creating-a-scene.html b/docs/manual/zh/introduction/Creating-a-scene.html index 051e2a6a1aca69..2af530429d0ed3 100644 --- a/docs/manual/zh/introduction/Creating-a-scene.html +++ b/docs/manual/zh/introduction/Creating-a-scene.html @@ -13,7 +13,7 @@

              创建一个场景([name])

              开始之前

              - 在开始使用three.js之前,你需要一个地方来显示它。将下列HTML代码保存为你电脑上的一个HTML文件,同时将[link:https://threejs.org/build/three.js three.js]复制到该HTML文件所在的目录下的js/目录下,然后在你的浏览器中打开这个HTML文件。 + 在开始使用three.js之前,你需要一个地方来显示它。将下列HTML代码保存为你电脑上的一个HTML文件然后在你的浏览器中打开这个HTML文件。

              <!DOCTYPE html> @@ -26,8 +26,9 @@

              开始之前

              </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + // Our Javascript will go here. </script> </body> @@ -117,7 +118,7 @@

              使立方体动起来

              结果

              祝贺你!你现在已经成功完成了你的第一个Three.js应用程序。虽然它很简单,但现在你已经有了一个入门的起点。

              -

              下面是完整的代码,可在[link:https://jsfiddle.net/fxurzeb4/ live example]运行、编辑;运行或者修改代码有助于你更好的理解它是如何工作的。

              +

              下面是完整的代码,可在[link:https://jsfiddle.net/0c1oqf38/ live example]运行、编辑;运行或者修改代码有助于你更好的理解它是如何工作的。

              <html> @@ -129,8 +130,9 @@

              结果

              </style> </head> <body> - <script src="js/three.js"></script> - <script> + <script type="module"> + import * as THREE from 'https://unpkg.com/three/build/three.module.js'; + const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); @@ -152,7 +154,7 @@

              结果

              cube.rotation.y += 0.01; renderer.render( scene, camera ); - }; + } animate(); </script> diff --git a/docs/manual/zh/introduction/How-to-run-things-locally.html b/docs/manual/zh/introduction/How-to-run-things-locally.html deleted file mode 100644 index e0ed4b461e9c98..00000000000000 --- a/docs/manual/zh/introduction/How-to-run-things-locally.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - -

              如何在本地运行Three.js([name])

              -

              - 倘若你只是使用Three.js库中所提供的几何体,且不载入任何纹理贴图,则网页是可以从本地的文件系统中打开,并且是能够直接运行的,只需在文件管理器中双击HTML文件,它就可以在浏览器中进行显示。 - (此时你将在地址栏中看到类似这样的URL:file:///yourFile.html) - -

              - -

              从外部文件载入的内容

              -
              -

              - 倘若你需要从外部文件里载入几何体或是纹理贴图,由于浏览器[link:http://en.wikipedia.org/wiki/Same_origin_policy same origin policy](同源策略)的安全限制,从本地文件系统载入外部文件将会失败,同时抛出安全性异常。 -

              - -

              这里有两种方法来解决这个问题:

              - -
                -
              1. - 在浏览器中改变本地文件的安全策略,这将使你可以通过file:///yourFile.html来直接运行本地文件系统中的文件。 -
              2. -
              3. - 从本地的服务器运行文件,这可以让你通过http://localhost/yourFile.html来访问运行在本地服务器上的文件。 -
              4. -
              - -

              - 倘若你选择第一种方法,请小心,倘若你使用同一个浏览器来进行日常网络冲浪,你将可能会触发一些漏洞。 - 你或许可以创建一个用于开发环境的独立的浏览器配置文件或者快捷方式,仅仅用于本地开发;这将使得日常使用环境与开发环境相分离,以保证日常使用环境的安全性。 - 接下来,我们来看一看除此之外的别的方法。 -

              -
              - - -

              运行一个本地的服务器

              -
              -

              - 很多的编程语言都具有一个内置的简易HTTP服务器。它们的功能并不像能够被用于生产环境的服务器,例如[link:https://www.apache.org/ Apache] 或者 [link:https://nginx.org NGINX]那样完善, - 但对于你来测试three.js应用程序来说,它们就已经足够了。 -

              - -

              流行的代码编辑器插件

              -
              -

              一些代码编辑器具有插件,可以根据需要生成简单的服务器。

              -
                -
              • Visual Studio Code [link:https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer Live Server] 插件。
              • -
              • Atom [link:https://atom.io/packages/atom-live-server Live Server] 插件。
              • -
              -
              - -

              Servez

              -
              -

              - [link:https://greggman.github.io/servez Servez] 一个具有界面的简单服务器。 -

              -
              - -

              Node.js server

              -
              -

              Node.js 具有一个简单的HTTP服务器包,如需安装,请执行:

              - npm install http-server -g - -

              若要从本地目录下运行,请执行:

              - http-server . -p 8000 -
              - -

              Python server

              -
              -

              - 如果你已经安装好了[link:http://python.org/ Python],只需要从命令行里便可以运行它(从工作目录): -

              - -//Python 2.x -python -m SimpleHTTPServer - -//Python 3.x -python -m http.server - - -

              这将会在为当前目录在8000端口创建一个服务器,也就是说你可以在地址栏里输入这个地址来访问已经创建好的服务器:

              - - http://localhost:8000/ -
              - -

              Ruby server

              -
              -

              如果你已经安装好了Ruby,通过执行下列命也可以创建同样的服务器:

              - -ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start" - -
              - -

              PHP server

              -
              -

              PHP自从5.4.0版本开始,就内置了一个Web服务器:

              - php -S localhost:8000 -
              - -

              Lighttpd

              -
              -

              - Lighttpd是一个轻量级的通用Web服务器,在这里,我们将介绍如何在OS X上使用HomeBrew来安装它。 - 和我们在这里讨论的其他服务器不同,lighttpd是一个成熟的、准用于生产环境的服务器。 -

              - -
                -
              1. - 通过HomeBrew安装lighttpd - brew install lighttpd -
              2. -
              3. - 在你希望作为服务器来运行的目录里,创建一个名为lighttpd.conf的配置文件。 - 这是一个配置文件的样本:[link:http://redmine.lighttpd.net/projects/lighttpd/wiki/TutorialConfiguration TutorialConfiguration]。 -
              4. -
              5. - 在配置文件里,将server.document-root更改为你将要创建的服务器中的文件的所在的目录。 -
              6. -
              7. - 通过这个命令来启动: - lighttpd -f lighttpd.conf -
              8. -
              9. - 使用浏览器打开http://localhost:3000/,然后服务器将可以从你所选择的目录中向你提供静态文件。 -
              10. -
              -
              -

              IIS

              -
              -

              如果你正在使用Microsoft IIS来作为网站服务器,在服务器载入之前,请为.fbx扩展名增加MIME类型。

              - File name extension: fbx MIME Type: text/plain -

              在默认情况下,IIS阻止 .fbx、 .obj 文件的下载,因此你必须对IIS进行配置,使得这些类型的文件可以被下载。

              -
              - -

              - 其它简单的替代方案你可以在Stack Overflow上找到:[link:http://stackoverflow.com/q/12905426/24874 click here]。 -

              -
              - - - diff --git a/docs/manual/zh/introduction/How-to-update-things.html b/docs/manual/zh/introduction/How-to-update-things.html index 96265cc7c8721f..bdf69d3f45dd58 100644 --- a/docs/manual/zh/introduction/How-to-update-things.html +++ b/docs/manual/zh/introduction/How-to-update-things.html @@ -76,20 +76,17 @@

              BufferGeometry

              然后我们随机增加顶点到line中,以这样的一种方式:

              -const positions = line.geometry.attributes.position.array; +const positionAttribute = line.geometry.getAttribute( 'position' ); -let x, y, z, index; -x = y = z = index = 0; +let x = 0, y = 0, z = 0; -for ( let i = 0, l = MAX_POINTS; i < l; i ++ ) { +for ( let i = 0; i < positionAttribute.count; i ++ ) { - positions[ index ++ ] = x; - positions[ index ++ ] = y; - positions[ index ++ ] = z; + positionAttribute.setXYZ( i, x, y, z ); - x += ( Math.random() - 0.5 ) * 30; - y += ( Math.random() - 0.5 ) * 30; - z += ( Math.random() - 0.5 ) * 30; + x += ( Math.random() - 0.5 ) * 30; + y += ( Math.random() - 0.5 ) * 30; + z += ( Math.random() - 0.5 ) * 30; } @@ -103,7 +100,7 @@

              BufferGeometry

              如果要在第一次渲染后更改position数值,则需要像这样设置needsUpdate标志:

              -line.geometry.attributes.position.needsUpdate = true; // 需要加在第一次渲染之后 +positionAttribute.needsUpdate = true; // 需要加在第一次渲染之后

              diff --git a/docs/manual/zh/introduction/Installation.html b/docs/manual/zh/introduction/Installation.html index 68d9e914a17e69..ca8829aee1623b 100644 --- a/docs/manual/zh/introduction/Installation.html +++ b/docs/manual/zh/introduction/Installation.html @@ -67,7 +67,7 @@

              从CDN或静态主机安装

              - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -108,7 +108,7 @@

              Addons

              - <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> + <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> <script type="importmap"> { @@ -154,11 +154,11 @@

              Import maps

              Node.js

              - Because three.js is built for the web, it depends on browser and DOM APIs that don't always exist in Node.js. Some of these issues can be resolved by using shims like [link:https://github.com/stackgl/headless-gl headless-gl], or by replacing components like [page:TextureLoader] with custom alternatives. Other DOM APIs may be deeply intertwined with the code that uses them, and will be harder to work around. We welcome simple and maintainable pull requests to improve Node.js support, but recommend opening an issue to discuss your improvements first. + 由于 three.js 是为 Web 构建的, 因此它依赖于浏览器和 DOM 的 API ,但这些 API 在 Node.js 里不一定存在。这些问题中有的可以使用 [link:https://github.com/stackgl/headless-gl headless-gl] 等 shims 来解决,或者用自定义的替代方案来替换像 [page:TextureLoader] 这样的组件。其他 DOM API 可能与使用它们的代码强相关,因此将更难以解决。我们欢迎简单且易于维护的 pull request 来改进对 Node.js 的支持,但建议先打开问题来讨论您的改进。

              - Make sure to add `{ "type": "module" }` to your `package.json` to enable ES6 modules in your node project. + 确保在您的 package.json 文件中添加 { "type": "module" },以在您的 Node.js 项目中启用 ES6 模块。

              diff --git a/docs/manual/zh/introduction/Loading-3D-models.html b/docs/manual/zh/introduction/Loading-3D-models.html index eec092662d967b..04d13d07664b83 100644 --- a/docs/manual/zh/introduction/Loading-3D-models.html +++ b/docs/manual/zh/introduction/Loading-3D-models.html @@ -25,7 +25,7 @@

              载入3D模型([name])

              在开始之前

              - 如果你是第一次运行一个本地服务器,可以先阅读[link:#manual/introduction/How-to-run-things-locally how to run things locally]。 + 如果你是第一次运行一个本地服务器,可以先阅读[link:#manual/introduction/Installation installation]。 正确地托管文件,可以避免很多查看3D模型时的常见错误。

              diff --git a/docs/page.css b/docs/page.css index 6e305348320db6..19241e2faa86d6 100644 --- a/docs/page.css +++ b/docs/page.css @@ -115,7 +115,8 @@ p, div, table, ol, -ul { +ul, +summary { margin-top: 16px; margin-bottom: 16px; } diff --git a/docs/page.js b/docs/page.js index 92b7e407670573..a8ee9c3d0714e4 100644 --- a/docs/page.js +++ b/docs/page.js @@ -1,27 +1,22 @@ if ( ! window.frameElement && window.location.protocol !== 'file:' ) { - // If the page is not yet displayed as an iframe of the index page (navigation panel/working links), - // redirect to the index page (using the current URL without extension as the new fragment). - // If this URL itself has a fragment, append it with a dot (since '#' in a URL fragment is not allowed). + // navigates to docs home if direct access, e.g. + // https://mrdoob.github.io/three.js/docs/api/en/audio/Audio.html#filter + // ->https://mrdoob.github.io/three.js/docs/#api/en/audio/Audio.filter - let href = window.location.href; - const splitIndex = href.lastIndexOf( '/docs/' ) + 6; - const docsBaseURL = href.slice( 0, splitIndex ); + const url = new URL( window.location.href ); - let hash = window.location.hash; + // hash route, e.g. #api/en/audio/Audio.filter + url.hash = url.pathname.replace( /\/docs\/(.*?)(?:\.html)?$/, '$1' ) + url.hash.replace( '#', '.' ); - if ( hash !== '' ) { + // docs home, e.g. https://mrdoob.github.io/three.js/docs/ + url.pathname = url.pathname.replace( /(\/docs\/).*$/, '$1' ); - href = href.replace( hash, '' ); - hash = hash.replace( '#', '.' ); + window.location.replace( url ); - } - - const extension = href.split( '.' ).pop(); - const end = ( extension === 'html' ) ? - 5 : href.length; - const pathSnippet = href.slice( splitIndex, end ); +} else { - window.location.replace( docsBaseURL + '#' + pathSnippet + hash ); + document.addEventListener( 'DOMContentLoaded', onDocumentLoad, { once: true } ); } @@ -66,12 +61,12 @@ function onDocumentLoad() { // text = text.replace( /\[member:.([\w]+) ([\w\.\s]+)\]/gi, "$2" ); text = text.replace( /\[(member|property|method|param):([\w]+)\]/gi, '[$1:$2 $2]' ); // [member:name] to [member:name title] - text = text.replace( /\[(?:member|property|method):([\w]+) ([\w\.\s]+)\]\s*(\(.*\))?/gi, ` .$2 $3 : $1` ); + text = text.replace( /\[(?:member|property|method):([\w]+) ([\w\.\s]+)\]\s*(\([\s\S]*?\))?/gi, ` .$2 $3 : $1` ); text = text.replace( /\[param:([\w\.]+) ([\w\.\s]+)\]/gi, '$2 : $1' ); // [param:name title] text = text.replace( /\[link:([\w\:\/\.\-\_\(\)\?\#\=\!\~]+)\]/gi, '$1' ); // [link:url] text = text.replace( /\[link:([\w:/.\-_()?#=!~]+) ([\w\p{L}:/.\-_'\s]+)\]/giu, '$2' ); // [link:url title] - text = text.replace( /\*([\w\d\"\-\(][\w\d\ \/\+\-\(\)\=\,\."]*[\w\d\"\)]|\w)\*/gi, '$1' ); // *text* + text = text.replace( /\*([\u4e00-\u9fa5\w\d\-\(\"\(\“][\u4e00-\u9fa5\w\d\ \/\+\-\(\)\=\,\.\(\)\,\。"]*[\u4e00-\u9fa5\w\d\"\)\”\)]|\w)\*/gi, '$1' ); // *text* text = text.replace( /\`(.*?)\`/gi, '$1' ); // `code` text = text.replace( /\[example:([\w\_]+)\]/gi, '[example:$1 $1]' ); // [example:name] to [example:name title] @@ -172,5 +167,3 @@ function onDocumentLoad() { document.head.appendChild( prettify ); } - -document.addEventListener( 'DOMContentLoaded', onDocumentLoad, false ); diff --git a/docs/scenes/bones-browser.html b/docs/scenes/bones-browser.html index 4695eb29a5753d..cac044ee1e3147 100644 --- a/docs/scenes/bones-browser.html +++ b/docs/scenes/bones-browser.html @@ -25,7 +25,7 @@ - + + + + + diff --git a/examples/css3d_molecules.html b/examples/css3d_molecules.html index 3b9cd1ada9fae7..22cc7125b60537 100644 --- a/examples/css3d_molecules.html +++ b/examples/css3d_molecules.html @@ -24,7 +24,7 @@ - + + diff --git a/examples/css3d_periodictable.html b/examples/css3d_periodictable.html index 9eded885dc66e3..5e29fe62de5417 100644 --- a/examples/css3d_periodictable.html +++ b/examples/css3d_periodictable.html @@ -93,7 +93,7 @@ - + + diff --git a/examples/css3d_sprites.html b/examples/css3d_sprites.html index 9ab141990d1c2a..e678fabc27d088 100644 --- a/examples/css3d_sprites.html +++ b/examples/css3d_sprites.html @@ -22,7 +22,7 @@ - + + + + + + + + + + + + + + - - - - - - - diff --git a/examples/misc_exporter_draco.html b/examples/misc_exporter_draco.html index fd5c8682e73ed8..102955d222af89 100644 --- a/examples/misc_exporter_draco.html +++ b/examples/misc_exporter_draco.html @@ -15,7 +15,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -104,7 +110,7 @@ - + + + + @@ -121,6 +127,10 @@ precision highp float; + vec4 LinearTosRGB( in vec4 value ) { + return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a ); + } + uniform sampler2D diffuseMap; in vec2 vUv; @@ -157,13 +167,15 @@ fragColor = vec4( texture( diffuseMap, vUv ).rgb * lightWeighting.rgb, 1.0 ); + fragColor = LinearTosRGB( fragColor ); + } - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - diff --git a/examples/webgl_geometry_extrude_splines.html b/examples/webgl_geometry_extrude_splines.html index ca461f5b1390f8..121cb75d8f0c70 100644 --- a/examples/webgl_geometry_extrude_splines.html +++ b/examples/webgl_geometry_extrude_splines.html @@ -24,7 +24,7 @@ - + + + + + + + + + + + + + + + + + - - - - - - - diff --git a/examples/webgl_instancing_performance.html b/examples/webgl_instancing_performance.html index 4308ccba7d8506..bffa9564213e3b 100644 --- a/examples/webgl_instancing_performance.html +++ b/examples/webgl_instancing_performance.html @@ -28,7 +28,7 @@ - + + + + + + + + + + + + + - - - - - - - diff --git a/examples/webgl_lightprobe.html b/examples/webgl_lightprobe.html index 9cc623fa1a8ccf..75ef5e6646fdb9 100644 --- a/examples/webgl_lightprobe.html +++ b/examples/webgl_lightprobe.html @@ -14,7 +14,7 @@ - + + + + + + + + + + + + + - - - - - - diff --git a/examples/webgl_loader_3dm.html b/examples/webgl_loader_3dm.html index cb29ca9b88fb57..df66b9e9195ea9 100644 --- a/examples/webgl_loader_3dm.html +++ b/examples/webgl_loader_3dm.html @@ -34,7 +34,7 @@
              - + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/webgl_loader_gltf_avif.html b/examples/webgl_loader_gltf_avif.html index 0f4e5e32de2f8c..336462b64dc426 100644 --- a/examples/webgl_loader_gltf_avif.html +++ b/examples/webgl_loader_gltf_avif.html @@ -3,31 +3,30 @@ three.js webgl - GLTFloader + EXT_texture_avif - + +
              - three.js - - GLTFLoader + - EXT_texture_avif
              + three.js - GLTFLoader + + EXT_texture_avif
              + Forest House by peachyroyalty
              - + + + + + + + + + + + diff --git a/examples/webgl_loader_gltf_sheen.html b/examples/webgl_loader_gltf_sheen.html index 309f800959b08f..71e40d45ccef05 100644 --- a/examples/webgl_loader_gltf_sheen.html +++ b/examples/webgl_loader_gltf_sheen.html @@ -20,7 +20,7 @@ - + + + + diff --git a/examples/webgl_loader_imagebitmap.html b/examples/webgl_loader_imagebitmap.html index fa013996144894..39b11646fb2a83 100644 --- a/examples/webgl_loader_imagebitmap.html +++ b/examples/webgl_loader_imagebitmap.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + + + - - - - - - - diff --git a/examples/webgl_loader_stl.html b/examples/webgl_loader_stl.html index 69648179e1c358..94d2d8c68f3606 100644 --- a/examples/webgl_loader_stl.html +++ b/examples/webgl_loader_stl.html @@ -15,7 +15,7 @@ - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - diff --git a/examples/webgl_materials_blending.html b/examples/webgl_materials_blending.html index 22a10e6f28b065..c64b51f5bda708 100644 --- a/examples/webgl_materials_blending.html +++ b/examples/webgl_materials_blending.html @@ -10,7 +10,7 @@ - + + + + + + + + + + + + + + diff --git a/examples/webgl_materials_envmaps_hdr.html b/examples/webgl_materials_envmaps_hdr.html index ac125b71d48dff..854ce499359fff 100644 --- a/examples/webgl_materials_envmaps_hdr.html +++ b/examples/webgl_materials_envmaps_hdr.html @@ -16,7 +16,7 @@ - + + + + + + + - - - - - - - diff --git a/examples/webgl_materials_physical_transmission.html b/examples/webgl_materials_physical_transmission.html index b0271b68410490..2b6c49599f772a 100644 --- a/examples/webgl_materials_physical_transmission.html +++ b/examples/webgl_materials_physical_transmission.html @@ -13,7 +13,7 @@ - + + + + + + + diff --git a/examples/webgl_materials_pmrem_dynamic.html b/examples/webgl_materials_pmrem_dynamic.html deleted file mode 100644 index 3edd12405d4455..00000000000000 --- a/examples/webgl_materials_pmrem_dynamic.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - three.js webgl - materials - dynamic cube reflection - - - - - - - -
              three.js webgl - materials - dynamic cube reflection
              Photo by Jón Ragnarsson.
              - - - - - diff --git a/examples/webgl_materials_standard.html b/examples/webgl_materials_standard.html deleted file mode 100644 index 4cca914c314fb4..00000000000000 --- a/examples/webgl_materials_standard.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - three.js webgl - materials - standard - - - - - - -
              - three.js - webgl physically based material
              - Cerberus(FFVII Gun) model by Andrew Maximov. -
              - - - - - - - - - - - diff --git a/examples/webgl_materials_subsurface_scattering.html b/examples/webgl_materials_subsurface_scattering.html index 67ac3b7a746eaa..75fc5a455dbe51 100644 --- a/examples/webgl_materials_subsurface_scattering.html +++ b/examples/webgl_materials_subsurface_scattering.html @@ -16,7 +16,7 @@ - + + + + + + + + - - - - - - - diff --git a/examples/webgl_materials_variations_lambert.html b/examples/webgl_materials_variations_lambert.html deleted file mode 100644 index b5029458c8507f..00000000000000 --- a/examples/webgl_materials_variations_lambert.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - three.js webgl - materials - - - - - - -
              -
              three.js - Lambert Material Variantions by Ben Houston.
              - - - - - - - - - - - diff --git a/examples/webgl_materials_variations_phong.html b/examples/webgl_materials_variations_phong.html deleted file mode 100644 index 32de1cb23c9f74..00000000000000 --- a/examples/webgl_materials_variations_phong.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - three.js webgl - materials - - - - - - -
              -
              three.js - Phong Material Variantions by Ben Houston.
              - - - - - - - - - - - diff --git a/examples/webgl_materials_variations_physical.html b/examples/webgl_materials_variations_physical.html deleted file mode 100644 index 7af9591d542808..00000000000000 --- a/examples/webgl_materials_variations_physical.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - three.js webgl - materials - - - - - - -
              -
              three.js - Physical Material Variations by Ben Houston.

              - Note: Every second sphere has an IBL environment map on it.
              - - - - - - - - - - - diff --git a/examples/webgl_materials_variations_standard.html b/examples/webgl_materials_variations_standard.html deleted file mode 100644 index 1f7700bd2c65d5..00000000000000 --- a/examples/webgl_materials_variations_standard.html +++ /dev/null @@ -1,232 +0,0 @@ - - - - three.js webgl - materials - - - - - - -
              -
              three.js - Standard Material Variations by Ben Houston.

              - Note: Every second sphere has an IBL environment map on it.
              - - - - - - - - - - - diff --git a/examples/webgl_materials_video.html b/examples/webgl_materials_video.html index 8a572084c262f6..819dd6c4d87b83 100644 --- a/examples/webgl_materials_video.html +++ b/examples/webgl_materials_video.html @@ -25,7 +25,7 @@ - + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/webgl_multiple_canvases_circle.html b/examples/webgl_multiple_canvases_circle.html deleted file mode 100644 index d3cc6e01f61483..00000000000000 --- a/examples/webgl_multiple_canvases_circle.html +++ /dev/null @@ -1,323 +0,0 @@ - - - - three.js webgl - multiple canvases - circle - - - - - - - -
              -
              -
              - - - - - -
              -
              -
              - -
              three.js webgl - multiple canvases - circle
              -
              -
              - Google's Liquid Galaxy simulator.
              - Here 5 monitors are simulated using 3d css. WebGL is then rendered onto each one. -
              -
              - - - - - - - - - - diff --git a/examples/webgl_multiple_canvases_complex.html b/examples/webgl_multiple_canvases_complex.html deleted file mode 100644 index 65858247743011..00000000000000 --- a/examples/webgl_multiple_canvases_complex.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - three.js webgl - multiple canvases - complex - - - - - - - -
              - - - -
              -
              three.js webgl - multiple canvases - complex
              - - - - - - - - - - - diff --git a/examples/webgl_multiple_canvases_grid.html b/examples/webgl_multiple_canvases_grid.html deleted file mode 100644 index 87cf05536bd7d4..00000000000000 --- a/examples/webgl_multiple_canvases_grid.html +++ /dev/null @@ -1,278 +0,0 @@ - - - - three.js webgl - multiple canvases - grid - - - - - - -
              -
              -
              -
              - - -
              -
              - - -
              -
              -
              -
              -
              three.js webgl - multiple canvases - grid
              - - - - - - - - - - - diff --git a/examples/webgl_multiple_elements.html b/examples/webgl_multiple_elements.html index a7d208f14dfcf4..9f9ebd1148a9b8 100644 --- a/examples/webgl_multiple_elements.html +++ b/examples/webgl_multiple_elements.html @@ -65,7 +65,7 @@ - + + - - - - - - - diff --git a/examples/webgl_multiple_scenes_comparison.html b/examples/webgl_multiple_scenes_comparison.html index eeaa048ea92a65..b64354c43f9e95 100644 --- a/examples/webgl_multiple_scenes_comparison.html +++ b/examples/webgl_multiple_scenes_comparison.html @@ -40,7 +40,7 @@ - + + + + + + + + + + - - - - - - - diff --git a/examples/webgl_nodes_points.html b/examples/webgl_nodes_points.html index 5aceb1666ee9f9..8b5a571b40d9d1 100644 --- a/examples/webgl_nodes_points.html +++ b/examples/webgl_nodes_points.html @@ -14,7 +14,7 @@ - + + + - - - - - - - diff --git a/examples/webgl_performance_shader.html b/examples/webgl_performance_shader.html deleted file mode 100644 index 2bb806d3ff538c..00000000000000 --- a/examples/webgl_performance_shader.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - three.js webgl - materials - shaders [lava] - - - - - - -
              -
              three.js - shader material demo. featuring lava shader by TheGameMaker
              - - - - - - - - - - - - - - - diff --git a/examples/webgl_performance_static.html b/examples/webgl_performance_static.html deleted file mode 100644 index 08a2c4c697c631..00000000000000 --- a/examples/webgl_performance_static.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - three.js webgl - performance [static] - - - - - - - - - - - - - - - - - diff --git a/examples/webgl_pmrem_test.html b/examples/webgl_pmrem_test.html index 5126768014ab3f..8de1dd384416ff 100644 --- a/examples/webgl_pmrem_test.html +++ b/examples/webgl_pmrem_test.html @@ -21,7 +21,7 @@ - + + + + + + + + + + + + + + + + + + + - - - - + diff --git a/examples/webgl_postprocessing_procedural.html b/examples/webgl_postprocessing_procedural.html index cabd25bec74cb2..fc51620518e689 100644 --- a/examples/webgl_postprocessing_procedural.html +++ b/examples/webgl_postprocessing_procedural.html @@ -56,7 +56,7 @@ - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - diff --git a/examples/webgl_shader_lava.html b/examples/webgl_shader_lava.html index 32c4e31a5c3887..22f75492f85511 100644 --- a/examples/webgl_shader_lava.html +++ b/examples/webgl_shader_lava.html @@ -76,7 +76,7 @@ - + + + - - - - - - - diff --git a/examples/webgl_shadow_contact.html b/examples/webgl_shadow_contact.html index 0d7b6375f63b0d..fd9e55feaad0a6 100644 --- a/examples/webgl_shadow_contact.html +++ b/examples/webgl_shadow_contact.html @@ -21,7 +21,7 @@

    - + + + + + + + + + + + - - - - - - diff --git a/examples/webgl_sprites.html b/examples/webgl_sprites.html index 83131d5bad20a1..76559ad770579b 100644 --- a/examples/webgl_sprites.html +++ b/examples/webgl_sprites.html @@ -14,7 +14,7 @@ - + + + - - - - - - diff --git a/examples/webgl_tonemapping.html b/examples/webgl_tonemapping.html index 07245a0bfe5e76..1bebf22a3254e0 100644 --- a/examples/webgl_tonemapping.html +++ b/examples/webgl_tonemapping.html @@ -12,12 +12,12 @@ three.js - Tone Mapping
    Battle Damaged Sci-fi Helmet by theblueturtle_
    - Venice Sunset by HDRI Haven + Venice Sunset from HDRI Haven - + - - - - - - - diff --git a/examples/webgl_video_kinect.html b/examples/webgl_video_kinect.html index b39885aab765d0..4cf433ae8e5f9e 100644 --- a/examples/webgl_video_kinect.html +++ b/examples/webgl_video_kinect.html @@ -70,7 +70,7 @@ - + + + + + + + + + + + + diff --git a/examples/webgpu_compute.html b/examples/webgpu_compute.html index 3e4c257c35148a..90cd3b3260f8de 100644 --- a/examples/webgpu_compute.html +++ b/examples/webgpu_compute.html @@ -11,7 +11,7 @@ three.js WebGPU - Compute - + + + + + + + + + + + + @@ -32,12 +31,11 @@ + + + + + + diff --git a/examples/webgpu_materials.html b/examples/webgpu_materials.html index 43666c6b1117ba..942d393f39c542 100644 --- a/examples/webgpu_materials.html +++ b/examples/webgpu_materials.html @@ -12,7 +12,7 @@ three.js WebGPU - Materials - + + + + + + + + diff --git a/examples/webgpu_nodes_playground.html b/examples/webgpu_nodes_playground.html deleted file mode 100644 index ad2e26f6904516..00000000000000 --- a/examples/webgpu_nodes_playground.html +++ /dev/null @@ -1,225 +0,0 @@ - - - - three.js - webgpu - node playground - - - - - - - - - - - - - - - - diff --git a/examples/webgpu_particles.html b/examples/webgpu_particles.html index 1aac062c740901..d1fbb41adfc21c 100644 --- a/examples/webgpu_particles.html +++ b/examples/webgpu_particles.html @@ -11,7 +11,7 @@ three.js WebGPU - Particles - + + + diff --git a/examples/webgpu_shadowmap.html b/examples/webgpu_shadowmap.html new file mode 100644 index 00000000000000..fe5590d68d7060 --- /dev/null +++ b/examples/webgpu_shadowmap.html @@ -0,0 +1,188 @@ + + + + three.js webgpu - shadow map + + + + + +
    + three.js - webgpu shadow map +
    + + + + + + + + + + diff --git a/examples/webgpu_skinning.html b/examples/webgpu_skinning.html index 2a7a24abba482b..a02ca8e45020b1 100644 --- a/examples/webgpu_skinning.html +++ b/examples/webgpu_skinning.html @@ -12,7 +12,7 @@ three.js WebGPU - Skinning - + + + + + - - - - - - diff --git a/examples/webxr_ar_hittest.html b/examples/webxr_ar_hittest.html index 6455204131e961..838cf3bf01ab9d 100644 --- a/examples/webxr_ar_hittest.html +++ b/examples/webxr_ar_hittest.html @@ -14,7 +14,7 @@ - + + - - - - - - diff --git a/examples/webxr_ar_plane_detection.html b/examples/webxr_ar_plane_detection.html index 61c32ca411e166..0e430d4ba65492 100644 --- a/examples/webxr_ar_plane_detection.html +++ b/examples/webxr_ar_plane_detection.html @@ -14,7 +14,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/manual/en/rendering-on-demand.html b/manual/en/rendering-on-demand.html index 6e057c29daafe7..9dce3061cb9a8d 100644 --- a/manual/en/rendering-on-demand.html +++ b/manual/en/rendering-on-demand.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - diff --git a/manual/examples/lots-of-objects-morphtargets.html b/manual/examples/lots-of-objects-morphtargets.html index a733ae2e8c2e9e..0fd552ac8c2f1f 100644 --- a/manual/examples/lots-of-objects-morphtargets.html +++ b/manual/examples/lots-of-objects-morphtargets.html @@ -43,7 +43,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/manual/examples/resources/editor.js b/manual/examples/resources/editor.js index f3ad317679d73b..23fc40181e104c 100644 --- a/manual/examples/resources/editor.js +++ b/manual/examples/resources/editor.js @@ -1711,7 +1711,9 @@ async function openInStackBlitz() { g.setPosition = false; const url = getSourceBlobFromEditor(); - g.iframe.src = url; + // g.iframe.src = url; + // work around firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1828286 + g.iframe.contentWindow.location.replace(url); } @@ -1959,7 +1961,7 @@ async function openInStackBlitz() { } else { applySubstitutions(); - require.config( { paths: { 'vs': '/manual/3rdparty/monaco-editor/min/vs' } } ); + require.config( { paths: { 'vs': 'https://unpkg.com/monaco-editor@0.34.1/min/vs' } } ); require( [ 'vs/editor/editor.main' ], main ); } diff --git a/manual/examples/responsive-hd-dpi.html b/manual/examples/responsive-hd-dpi.html index febc7574094c34..998c004b97b1aa 100644 --- a/manual/examples/responsive-hd-dpi.html +++ b/manual/examples/responsive-hd-dpi.html @@ -22,7 +22,7 @@ - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/manual/fr/rendering-on-demand.html b/manual/fr/rendering-on-demand.html index d078bc34523c42..d06afe29925851 100644 --- a/manual/fr/rendering-on-demand.html +++ b/manual/fr/rendering-on-demand.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + +
    @@ -492,17 +495,21 @@

    three.js

    // We can have 2 hashes. One for the main page, one for the page it's referencing // In other words // #en/somePage#someSectionOfPage - const subHash = splitHash[0].indexOf('#'); + const subHash = splitHash[ 0 ].indexOf( '#' ); let src; - if (subHash >= 0) { - const beforeSubHash = splitHash[0].slice(0, subHash); - const afterSubHash = splitHash[0].slice(subHash); + if ( subHash >= 0 ) { + + const beforeSubHash = splitHash[ 0 ].slice( 0, subHash ); + const afterSubHash = splitHash[ 0 ].slice( subHash ); src = `${beforeSubHash}.html${afterSubHash}${splitHash[ 1 ]}`; + } else { + src = splitHash[ 0 ] + '.html' + splitHash[ 1 ]; + } - iframe.src = src; // lgtm[js/client-side-unvalidated-url-redirection] + iframe.src = src; // lgtm[js/client-side-unvalidated-url-redirection] iframe.style.display = 'unset'; } else { diff --git a/manual/ja/align-html-elements-to-3d.html b/manual/ja/align-html-elements-to-3d.html index 9dafe73dc6e2a8..d533cb518d9718 100644 --- a/manual/ja/align-html-elements-to-3d.html +++ b/manual/ja/align-html-elements-to-3d.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/manual/ja/rendering-on-demand.html b/manual/ja/rendering-on-demand.html index a0cc18e41a5fe1..b4ac4261c1ee72 100644 --- a/manual/ja/rendering-on-demand.html +++ b/manual/ja/rendering-on-demand.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/manual/ko/rendering-on-demand.html b/manual/ko/rendering-on-demand.html index ef0b5ce5faa302..698e48e7a807ec 100644 --- a/manual/ko/rendering-on-demand.html +++ b/manual/ko/rendering-on-demand.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/manual/ru/rendering-on-demand.html b/manual/ru/rendering-on-demand.html index 71d346a6a41ba5..5c7beaaaa1c686 100644 --- a/manual/ru/rendering-on-demand.html +++ b/manual/ru/rendering-on-demand.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/manual/zh/rendering-on-demand.html b/manual/zh/rendering-on-demand.html index df6e61236c432f..76824c768f3377 100644 --- a/manual/zh/rendering-on-demand.html +++ b/manual/zh/rendering-on-demand.html @@ -13,7 +13,7 @@ - + + + + + + + + + + + + + + + + + diff --git a/playground/fonts/tabler-icons/tabler-icons.min.css b/playground/fonts/tabler-icons/tabler-icons.min.css new file mode 100644 index 00000000000000..9afc0bc97916c4 --- /dev/null +++ b/playground/fonts/tabler-icons/tabler-icons.min.css @@ -0,0 +1,4 @@ +/*! + * Tabler Icons 2.11.0 by tabler - https://tabler.io + * License - https://github.com/tabler/tabler-icons/blob/master/LICENSE + */@font-face{font-family:"tabler-icons";font-style:normal;font-weight:400;src:url("./fonts/tabler-icons.eot?v2.11.0");src:url("./fonts/tabler-icons.eot?#iefix-v2.11.0") format("embedded-opentype"),url("./fonts/tabler-icons.woff2?v2.11.0") format("woff2"),url("./fonts/tabler-icons.woff?") format("woff"),url("./fonts/tabler-icons.ttf?v2.11.0") format("truetype")}.ti{font-family:"tabler-icons" !important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ti-123:before{content:"\f554"}.ti-24-hours:before{content:"\f5e7"}.ti-2fa:before{content:"\eca0"}.ti-360:before{content:"\f62f"}.ti-360-view:before{content:"\f566"}.ti-3d-cube-sphere:before{content:"\ecd7"}.ti-3d-cube-sphere-off:before{content:"\f3b5"}.ti-3d-rotate:before{content:"\f020"}.ti-a-b:before{content:"\ec36"}.ti-a-b-2:before{content:"\f25f"}.ti-a-b-off:before{content:"\f0a6"}.ti-abacus:before{content:"\f05c"}.ti-abacus-off:before{content:"\f3b6"}.ti-abc:before{content:"\f567"}.ti-access-point:before{content:"\ed1b"}.ti-access-point-off:before{content:"\ed1a"}.ti-accessible:before{content:"\eba9"}.ti-accessible-off:before{content:"\f0a7"}.ti-accessible-off-filled:before{content:"\f6ea"}.ti-activity:before{content:"\ed23"}.ti-activity-heartbeat:before{content:"\f0db"}.ti-ad:before{content:"\ea02"}.ti-ad-2:before{content:"\ef1f"}.ti-ad-circle:before{content:"\f79e"}.ti-ad-circle-filled:before{content:"\f7d3"}.ti-ad-circle-off:before{content:"\f79d"}.ti-ad-filled:before{content:"\f6eb"}.ti-ad-off:before{content:"\f3b7"}.ti-address-book:before{content:"\f021"}.ti-address-book-off:before{content:"\f3b8"}.ti-adjustments:before{content:"\ea03"}.ti-adjustments-alt:before{content:"\ec37"}.ti-adjustments-bolt:before{content:"\f7fb"}.ti-adjustments-cancel:before{content:"\f7fc"}.ti-adjustments-check:before{content:"\f7fd"}.ti-adjustments-code:before{content:"\f7fe"}.ti-adjustments-cog:before{content:"\f7ff"}.ti-adjustments-dollar:before{content:"\f800"}.ti-adjustments-down:before{content:"\f801"}.ti-adjustments-exclamation:before{content:"\f802"}.ti-adjustments-filled:before{content:"\f6ec"}.ti-adjustments-heart:before{content:"\f803"}.ti-adjustments-horizontal:before{content:"\ec38"}.ti-adjustments-minus:before{content:"\f804"}.ti-adjustments-off:before{content:"\f0a8"}.ti-adjustments-pause:before{content:"\f805"}.ti-adjustments-pin:before{content:"\f806"}.ti-adjustments-plus:before{content:"\f807"}.ti-adjustments-question:before{content:"\f808"}.ti-adjustments-search:before{content:"\f809"}.ti-adjustments-share:before{content:"\f80a"}.ti-adjustments-star:before{content:"\f80b"}.ti-adjustments-up:before{content:"\f80c"}.ti-adjustments-x:before{content:"\f80d"}.ti-aerial-lift:before{content:"\edfe"}.ti-affiliate:before{content:"\edff"}.ti-affiliate-filled:before{content:"\f6ed"}.ti-air-balloon:before{content:"\f4a6"}.ti-air-conditioning:before{content:"\f3a2"}.ti-air-conditioning-disabled:before{content:"\f542"}.ti-alarm:before{content:"\ea04"}.ti-alarm-filled:before{content:"\f709"}.ti-alarm-minus:before{content:"\f630"}.ti-alarm-minus-filled:before{content:"\f70a"}.ti-alarm-off:before{content:"\f0a9"}.ti-alarm-plus:before{content:"\f631"}.ti-alarm-plus-filled:before{content:"\f70b"}.ti-alarm-snooze:before{content:"\f632"}.ti-alarm-snooze-filled:before{content:"\f70c"}.ti-album:before{content:"\f022"}.ti-album-off:before{content:"\f3b9"}.ti-alert-circle:before{content:"\ea05"}.ti-alert-circle-filled:before{content:"\f6ee"}.ti-alert-hexagon:before{content:"\f80e"}.ti-alert-octagon:before{content:"\ecc6"}.ti-alert-octagon-filled:before{content:"\f6ef"}.ti-alert-small:before{content:"\f80f"}.ti-alert-square:before{content:"\f811"}.ti-alert-square-rounded:before{content:"\f810"}.ti-alert-triangle:before{content:"\ea06"}.ti-alert-triangle-filled:before{content:"\f6f0"}.ti-alien:before{content:"\ebde"}.ti-alien-filled:before{content:"\f70d"}.ti-align-box-bottom-center:before{content:"\f530"}.ti-align-box-bottom-center-filled:before{content:"\f70e"}.ti-align-box-bottom-left:before{content:"\f531"}.ti-align-box-bottom-left-filled:before{content:"\f70f"}.ti-align-box-bottom-right:before{content:"\f532"}.ti-align-box-bottom-right-filled:before{content:"\f710"}.ti-align-box-center-middle:before{content:"\f79f"}.ti-align-box-center-middle-filled:before{content:"\f7d4"}.ti-align-box-left-bottom:before{content:"\f533"}.ti-align-box-left-bottom-filled:before{content:"\f711"}.ti-align-box-left-middle:before{content:"\f534"}.ti-align-box-left-middle-filled:before{content:"\f712"}.ti-align-box-left-top:before{content:"\f535"}.ti-align-box-left-top-filled:before{content:"\f713"}.ti-align-box-right-bottom:before{content:"\f536"}.ti-align-box-right-bottom-filled:before{content:"\f714"}.ti-align-box-right-middle:before{content:"\f537"}.ti-align-box-right-middle-filled:before{content:"\f7d5"}.ti-align-box-right-top:before{content:"\f538"}.ti-align-box-right-top-filled:before{content:"\f715"}.ti-align-box-top-center:before{content:"\f539"}.ti-align-box-top-center-filled:before{content:"\f716"}.ti-align-box-top-left:before{content:"\f53a"}.ti-align-box-top-left-filled:before{content:"\f717"}.ti-align-box-top-right:before{content:"\f53b"}.ti-align-box-top-right-filled:before{content:"\f718"}.ti-align-center:before{content:"\ea07"}.ti-align-justified:before{content:"\ea08"}.ti-align-left:before{content:"\ea09"}.ti-align-right:before{content:"\ea0a"}.ti-alpha:before{content:"\f543"}.ti-alphabet-cyrillic:before{content:"\f1df"}.ti-alphabet-greek:before{content:"\f1e0"}.ti-alphabet-latin:before{content:"\f1e1"}.ti-ambulance:before{content:"\ebf5"}.ti-ampersand:before{content:"\f229"}.ti-analyze:before{content:"\f3a3"}.ti-analyze-filled:before{content:"\f719"}.ti-analyze-off:before{content:"\f3ba"}.ti-anchor:before{content:"\eb76"}.ti-anchor-off:before{content:"\f0f7"}.ti-angle:before{content:"\ef20"}.ti-ankh:before{content:"\f1cd"}.ti-antenna:before{content:"\f094"}.ti-antenna-bars-1:before{content:"\ecc7"}.ti-antenna-bars-2:before{content:"\ecc8"}.ti-antenna-bars-3:before{content:"\ecc9"}.ti-antenna-bars-4:before{content:"\ecca"}.ti-antenna-bars-5:before{content:"\eccb"}.ti-antenna-bars-off:before{content:"\f0aa"}.ti-antenna-off:before{content:"\f3bb"}.ti-aperture:before{content:"\eb58"}.ti-aperture-off:before{content:"\f3bc"}.ti-api:before{content:"\effd"}.ti-api-app:before{content:"\effc"}.ti-api-app-off:before{content:"\f0ab"}.ti-api-off:before{content:"\f0f8"}.ti-app-window:before{content:"\efe6"}.ti-app-window-filled:before{content:"\f71a"}.ti-apple:before{content:"\ef21"}.ti-apps:before{content:"\ebb6"}.ti-apps-filled:before{content:"\f6f1"}.ti-apps-off:before{content:"\f0ac"}.ti-archive:before{content:"\ea0b"}.ti-archive-off:before{content:"\f0ad"}.ti-armchair:before{content:"\ef9e"}.ti-armchair-2:before{content:"\efe7"}.ti-armchair-2-off:before{content:"\f3bd"}.ti-armchair-off:before{content:"\f3be"}.ti-arrow-autofit-content:before{content:"\ef31"}.ti-arrow-autofit-content-filled:before{content:"\f6f2"}.ti-arrow-autofit-down:before{content:"\ef32"}.ti-arrow-autofit-height:before{content:"\ef33"}.ti-arrow-autofit-left:before{content:"\ef34"}.ti-arrow-autofit-right:before{content:"\ef35"}.ti-arrow-autofit-up:before{content:"\ef36"}.ti-arrow-autofit-width:before{content:"\ef37"}.ti-arrow-back:before{content:"\ea0c"}.ti-arrow-back-up:before{content:"\eb77"}.ti-arrow-back-up-double:before{content:"\f9ec"}.ti-arrow-badge-down:before{content:"\f60b"}.ti-arrow-badge-down-filled:before{content:"\f7d6"}.ti-arrow-badge-left:before{content:"\f60c"}.ti-arrow-badge-left-filled:before{content:"\f7d7"}.ti-arrow-badge-right:before{content:"\f60d"}.ti-arrow-badge-right-filled:before{content:"\f7d8"}.ti-arrow-badge-up:before{content:"\f60e"}.ti-arrow-badge-up-filled:before{content:"\f7d9"}.ti-arrow-bar-down:before{content:"\ea0d"}.ti-arrow-bar-left:before{content:"\ea0e"}.ti-arrow-bar-right:before{content:"\ea0f"}.ti-arrow-bar-to-down:before{content:"\ec88"}.ti-arrow-bar-to-left:before{content:"\ec89"}.ti-arrow-bar-to-right:before{content:"\ec8a"}.ti-arrow-bar-to-up:before{content:"\ec8b"}.ti-arrow-bar-up:before{content:"\ea10"}.ti-arrow-bear-left:before{content:"\f045"}.ti-arrow-bear-left-2:before{content:"\f044"}.ti-arrow-bear-right:before{content:"\f047"}.ti-arrow-bear-right-2:before{content:"\f046"}.ti-arrow-big-down:before{content:"\edda"}.ti-arrow-big-down-filled:before{content:"\f6c6"}.ti-arrow-big-down-line:before{content:"\efe8"}.ti-arrow-big-down-line-filled:before{content:"\f6c7"}.ti-arrow-big-down-lines:before{content:"\efe9"}.ti-arrow-big-down-lines-filled:before{content:"\f6c8"}.ti-arrow-big-left:before{content:"\eddb"}.ti-arrow-big-left-filled:before{content:"\f6c9"}.ti-arrow-big-left-line:before{content:"\efea"}.ti-arrow-big-left-line-filled:before{content:"\f6ca"}.ti-arrow-big-left-lines:before{content:"\efeb"}.ti-arrow-big-left-lines-filled:before{content:"\f6cb"}.ti-arrow-big-right:before{content:"\eddc"}.ti-arrow-big-right-filled:before{content:"\f6cc"}.ti-arrow-big-right-line:before{content:"\efec"}.ti-arrow-big-right-line-filled:before{content:"\f6cd"}.ti-arrow-big-right-lines:before{content:"\efed"}.ti-arrow-big-right-lines-filled:before{content:"\f6ce"}.ti-arrow-big-up:before{content:"\eddd"}.ti-arrow-big-up-filled:before{content:"\f6cf"}.ti-arrow-big-up-line:before{content:"\efee"}.ti-arrow-big-up-line-filled:before{content:"\f6d0"}.ti-arrow-big-up-lines:before{content:"\efef"}.ti-arrow-big-up-lines-filled:before{content:"\f6d1"}.ti-arrow-bounce:before{content:"\f3a4"}.ti-arrow-curve-left:before{content:"\f048"}.ti-arrow-curve-right:before{content:"\f049"}.ti-arrow-down:before{content:"\ea16"}.ti-arrow-down-bar:before{content:"\ed98"}.ti-arrow-down-circle:before{content:"\ea11"}.ti-arrow-down-left:before{content:"\ea13"}.ti-arrow-down-left-circle:before{content:"\ea12"}.ti-arrow-down-rhombus:before{content:"\f61d"}.ti-arrow-down-right:before{content:"\ea15"}.ti-arrow-down-right-circle:before{content:"\ea14"}.ti-arrow-down-square:before{content:"\ed9a"}.ti-arrow-down-tail:before{content:"\ed9b"}.ti-arrow-elbow-left:before{content:"\f9ed"}.ti-arrow-elbow-right:before{content:"\f9ee"}.ti-arrow-fork:before{content:"\f04a"}.ti-arrow-forward:before{content:"\ea17"}.ti-arrow-forward-up:before{content:"\eb78"}.ti-arrow-forward-up-double:before{content:"\f9ef"}.ti-arrow-guide:before{content:"\f22a"}.ti-arrow-iteration:before{content:"\f578"}.ti-arrow-left:before{content:"\ea19"}.ti-arrow-left-bar:before{content:"\ed9c"}.ti-arrow-left-circle:before{content:"\ea18"}.ti-arrow-left-rhombus:before{content:"\f61e"}.ti-arrow-left-right:before{content:"\f04b"}.ti-arrow-left-square:before{content:"\ed9d"}.ti-arrow-left-tail:before{content:"\ed9e"}.ti-arrow-loop-left:before{content:"\ed9f"}.ti-arrow-loop-left-2:before{content:"\f04c"}.ti-arrow-loop-right:before{content:"\eda0"}.ti-arrow-loop-right-2:before{content:"\f04d"}.ti-arrow-merge:before{content:"\f04e"}.ti-arrow-merge-both:before{content:"\f23b"}.ti-arrow-merge-left:before{content:"\f23c"}.ti-arrow-merge-right:before{content:"\f23d"}.ti-arrow-move-down:before{content:"\f2ba"}.ti-arrow-move-left:before{content:"\f2bb"}.ti-arrow-move-right:before{content:"\f2bc"}.ti-arrow-move-up:before{content:"\f2bd"}.ti-arrow-narrow-down:before{content:"\ea1a"}.ti-arrow-narrow-left:before{content:"\ea1b"}.ti-arrow-narrow-right:before{content:"\ea1c"}.ti-arrow-narrow-up:before{content:"\ea1d"}.ti-arrow-ramp-left:before{content:"\ed3c"}.ti-arrow-ramp-left-2:before{content:"\f04f"}.ti-arrow-ramp-left-3:before{content:"\f050"}.ti-arrow-ramp-right:before{content:"\ed3d"}.ti-arrow-ramp-right-2:before{content:"\f051"}.ti-arrow-ramp-right-3:before{content:"\f052"}.ti-arrow-right:before{content:"\ea1f"}.ti-arrow-right-bar:before{content:"\eda1"}.ti-arrow-right-circle:before{content:"\ea1e"}.ti-arrow-right-rhombus:before{content:"\f61f"}.ti-arrow-right-square:before{content:"\eda2"}.ti-arrow-right-tail:before{content:"\eda3"}.ti-arrow-rotary-first-left:before{content:"\f053"}.ti-arrow-rotary-first-right:before{content:"\f054"}.ti-arrow-rotary-last-left:before{content:"\f055"}.ti-arrow-rotary-last-right:before{content:"\f056"}.ti-arrow-rotary-left:before{content:"\f057"}.ti-arrow-rotary-right:before{content:"\f058"}.ti-arrow-rotary-straight:before{content:"\f059"}.ti-arrow-roundabout-left:before{content:"\f22b"}.ti-arrow-roundabout-right:before{content:"\f22c"}.ti-arrow-sharp-turn-left:before{content:"\f05a"}.ti-arrow-sharp-turn-right:before{content:"\f05b"}.ti-arrow-up:before{content:"\ea25"}.ti-arrow-up-bar:before{content:"\eda4"}.ti-arrow-up-circle:before{content:"\ea20"}.ti-arrow-up-left:before{content:"\ea22"}.ti-arrow-up-left-circle:before{content:"\ea21"}.ti-arrow-up-rhombus:before{content:"\f620"}.ti-arrow-up-right:before{content:"\ea24"}.ti-arrow-up-right-circle:before{content:"\ea23"}.ti-arrow-up-square:before{content:"\eda6"}.ti-arrow-up-tail:before{content:"\eda7"}.ti-arrow-wave-left-down:before{content:"\eda8"}.ti-arrow-wave-left-up:before{content:"\eda9"}.ti-arrow-wave-right-down:before{content:"\edaa"}.ti-arrow-wave-right-up:before{content:"\edab"}.ti-arrow-zig-zag:before{content:"\f4a7"}.ti-arrows-cross:before{content:"\effe"}.ti-arrows-diagonal:before{content:"\ea27"}.ti-arrows-diagonal-2:before{content:"\ea26"}.ti-arrows-diagonal-minimize:before{content:"\ef39"}.ti-arrows-diagonal-minimize-2:before{content:"\ef38"}.ti-arrows-diff:before{content:"\f296"}.ti-arrows-double-ne-sw:before{content:"\edde"}.ti-arrows-double-nw-se:before{content:"\eddf"}.ti-arrows-double-se-nw:before{content:"\ede0"}.ti-arrows-double-sw-ne:before{content:"\ede1"}.ti-arrows-down:before{content:"\edad"}.ti-arrows-down-up:before{content:"\edac"}.ti-arrows-exchange:before{content:"\f1f4"}.ti-arrows-exchange-2:before{content:"\f1f3"}.ti-arrows-horizontal:before{content:"\eb59"}.ti-arrows-join:before{content:"\edaf"}.ti-arrows-join-2:before{content:"\edae"}.ti-arrows-left:before{content:"\edb1"}.ti-arrows-left-down:before{content:"\ee00"}.ti-arrows-left-right:before{content:"\edb0"}.ti-arrows-maximize:before{content:"\ea28"}.ti-arrows-minimize:before{content:"\ea29"}.ti-arrows-move:before{content:"\f22f"}.ti-arrows-move-horizontal:before{content:"\f22d"}.ti-arrows-move-vertical:before{content:"\f22e"}.ti-arrows-random:before{content:"\f095"}.ti-arrows-right:before{content:"\edb3"}.ti-arrows-right-down:before{content:"\ee01"}.ti-arrows-right-left:before{content:"\edb2"}.ti-arrows-shuffle:before{content:"\f000"}.ti-arrows-shuffle-2:before{content:"\efff"}.ti-arrows-sort:before{content:"\eb5a"}.ti-arrows-split:before{content:"\edb5"}.ti-arrows-split-2:before{content:"\edb4"}.ti-arrows-transfer-down:before{content:"\f2cc"}.ti-arrows-transfer-up:before{content:"\f2cd"}.ti-arrows-up:before{content:"\edb7"}.ti-arrows-up-down:before{content:"\edb6"}.ti-arrows-up-left:before{content:"\ee02"}.ti-arrows-up-right:before{content:"\ee03"}.ti-arrows-vertical:before{content:"\eb5b"}.ti-artboard:before{content:"\ea2a"}.ti-artboard-off:before{content:"\f0ae"}.ti-article:before{content:"\f1e2"}.ti-article-filled-filled:before{content:"\f7da"}.ti-article-off:before{content:"\f3bf"}.ti-aspect-ratio:before{content:"\ed30"}.ti-aspect-ratio-filled:before{content:"\f7db"}.ti-aspect-ratio-off:before{content:"\f0af"}.ti-assembly:before{content:"\f24d"}.ti-assembly-off:before{content:"\f3c0"}.ti-asset:before{content:"\f1ce"}.ti-asterisk:before{content:"\efd5"}.ti-asterisk-simple:before{content:"\efd4"}.ti-at:before{content:"\ea2b"}.ti-at-off:before{content:"\f0b0"}.ti-atom:before{content:"\eb79"}.ti-atom-2:before{content:"\ebdf"}.ti-atom-2-filled:before{content:"\f71b"}.ti-atom-off:before{content:"\f0f9"}.ti-augmented-reality:before{content:"\f023"}.ti-augmented-reality-2:before{content:"\f37e"}.ti-augmented-reality-off:before{content:"\f3c1"}.ti-award:before{content:"\ea2c"}.ti-award-filled:before{content:"\f71c"}.ti-award-off:before{content:"\f0fa"}.ti-axe:before{content:"\ef9f"}.ti-axis-x:before{content:"\ef45"}.ti-axis-y:before{content:"\ef46"}.ti-baby-bottle:before{content:"\f5d2"}.ti-baby-carriage:before{content:"\f05d"}.ti-backhoe:before{content:"\ed86"}.ti-backpack:before{content:"\ef47"}.ti-backpack-off:before{content:"\f3c2"}.ti-backspace:before{content:"\ea2d"}.ti-backspace-filled:before{content:"\f7dc"}.ti-badge:before{content:"\efc2"}.ti-badge-3d:before{content:"\f555"}.ti-badge-4k:before{content:"\f556"}.ti-badge-8k:before{content:"\f557"}.ti-badge-ad:before{content:"\f558"}.ti-badge-ar:before{content:"\f559"}.ti-badge-cc:before{content:"\f55a"}.ti-badge-filled:before{content:"\f667"}.ti-badge-hd:before{content:"\f55b"}.ti-badge-off:before{content:"\f0fb"}.ti-badge-sd:before{content:"\f55c"}.ti-badge-tm:before{content:"\f55d"}.ti-badge-vo:before{content:"\f55e"}.ti-badge-vr:before{content:"\f55f"}.ti-badge-wc:before{content:"\f560"}.ti-badges:before{content:"\efc3"}.ti-badges-filled:before{content:"\f7dd"}.ti-badges-off:before{content:"\f0fc"}.ti-baguette:before{content:"\f3a5"}.ti-ball-american-football:before{content:"\ee04"}.ti-ball-american-football-off:before{content:"\f3c3"}.ti-ball-baseball:before{content:"\efa0"}.ti-ball-basketball:before{content:"\ec28"}.ti-ball-bowling:before{content:"\ec29"}.ti-ball-football:before{content:"\ee06"}.ti-ball-football-off:before{content:"\ee05"}.ti-ball-tennis:before{content:"\ec2a"}.ti-ball-volleyball:before{content:"\ec2b"}.ti-balloon:before{content:"\ef3a"}.ti-balloon-off:before{content:"\f0fd"}.ti-ballpen:before{content:"\f06e"}.ti-ballpen-off:before{content:"\f0b1"}.ti-ban:before{content:"\ea2e"}.ti-bandage:before{content:"\eb7a"}.ti-bandage-filled:before{content:"\f7de"}.ti-bandage-off:before{content:"\f3c4"}.ti-barbell:before{content:"\eff0"}.ti-barbell-off:before{content:"\f0b2"}.ti-barcode:before{content:"\ebc6"}.ti-barcode-off:before{content:"\f0b3"}.ti-barrel:before{content:"\f0b4"}.ti-barrel-off:before{content:"\f0fe"}.ti-barrier-block:before{content:"\f00e"}.ti-barrier-block-off:before{content:"\f0b5"}.ti-baseline:before{content:"\f024"}.ti-baseline-density-large:before{content:"\f9f0"}.ti-baseline-density-medium:before{content:"\f9f1"}.ti-baseline-density-small:before{content:"\f9f2"}.ti-basket:before{content:"\ebe1"}.ti-basket-filled:before{content:"\f7df"}.ti-basket-off:before{content:"\f0b6"}.ti-bat:before{content:"\f284"}.ti-bath:before{content:"\ef48"}.ti-bath-filled:before{content:"\f71d"}.ti-bath-off:before{content:"\f0ff"}.ti-battery:before{content:"\ea34"}.ti-battery-1:before{content:"\ea2f"}.ti-battery-1-filled:before{content:"\f71e"}.ti-battery-2:before{content:"\ea30"}.ti-battery-2-filled:before{content:"\f71f"}.ti-battery-3:before{content:"\ea31"}.ti-battery-3-filled:before{content:"\f720"}.ti-battery-4:before{content:"\ea32"}.ti-battery-4-filled:before{content:"\f721"}.ti-battery-automotive:before{content:"\ee07"}.ti-battery-charging:before{content:"\ea33"}.ti-battery-charging-2:before{content:"\ef3b"}.ti-battery-eco:before{content:"\ef3c"}.ti-battery-filled:before{content:"\f668"}.ti-battery-off:before{content:"\ed1c"}.ti-beach:before{content:"\ef3d"}.ti-beach-off:before{content:"\f0b7"}.ti-bed:before{content:"\eb5c"}.ti-bed-filled:before{content:"\f7e0"}.ti-bed-off:before{content:"\f100"}.ti-beer:before{content:"\efa1"}.ti-beer-filled:before{content:"\f7e1"}.ti-beer-off:before{content:"\f101"}.ti-bell:before{content:"\ea35"}.ti-bell-bolt:before{content:"\f812"}.ti-bell-cancel:before{content:"\f813"}.ti-bell-check:before{content:"\f814"}.ti-bell-code:before{content:"\f815"}.ti-bell-cog:before{content:"\f816"}.ti-bell-dollar:before{content:"\f817"}.ti-bell-down:before{content:"\f818"}.ti-bell-exclamation:before{content:"\f819"}.ti-bell-filled:before{content:"\f669"}.ti-bell-heart:before{content:"\f81a"}.ti-bell-minus:before{content:"\ede2"}.ti-bell-minus-filled:before{content:"\f722"}.ti-bell-off:before{content:"\ece9"}.ti-bell-pause:before{content:"\f81b"}.ti-bell-pin:before{content:"\f81c"}.ti-bell-plus:before{content:"\ede3"}.ti-bell-plus-filled:before{content:"\f723"}.ti-bell-question:before{content:"\f81d"}.ti-bell-ringing:before{content:"\ed07"}.ti-bell-ringing-2:before{content:"\ede4"}.ti-bell-ringing-2-filled:before{content:"\f724"}.ti-bell-ringing-filled:before{content:"\f725"}.ti-bell-school:before{content:"\f05e"}.ti-bell-search:before{content:"\f81e"}.ti-bell-share:before{content:"\f81f"}.ti-bell-star:before{content:"\f820"}.ti-bell-up:before{content:"\f821"}.ti-bell-x:before{content:"\ede5"}.ti-bell-x-filled:before{content:"\f726"}.ti-bell-z:before{content:"\eff1"}.ti-bell-z-filled:before{content:"\f727"}.ti-beta:before{content:"\f544"}.ti-bible:before{content:"\efc4"}.ti-bike:before{content:"\ea36"}.ti-bike-off:before{content:"\f0b8"}.ti-binary:before{content:"\ee08"}.ti-binary-off:before{content:"\f3c5"}.ti-binary-tree:before{content:"\f5d4"}.ti-binary-tree-2:before{content:"\f5d3"}.ti-biohazard:before{content:"\ecb8"}.ti-biohazard-off:before{content:"\f0b9"}.ti-blade:before{content:"\f4bd"}.ti-blade-filled:before{content:"\f7e2"}.ti-bleach:before{content:"\f2f3"}.ti-bleach-chlorine:before{content:"\f2f0"}.ti-bleach-no-chlorine:before{content:"\f2f1"}.ti-bleach-off:before{content:"\f2f2"}.ti-blockquote:before{content:"\ee09"}.ti-bluetooth:before{content:"\ea37"}.ti-bluetooth-connected:before{content:"\ecea"}.ti-bluetooth-off:before{content:"\eceb"}.ti-bluetooth-x:before{content:"\f081"}.ti-blur:before{content:"\ef8c"}.ti-blur-off:before{content:"\f3c6"}.ti-bmp:before{content:"\f3a6"}.ti-bold:before{content:"\eb7b"}.ti-bold-off:before{content:"\f0ba"}.ti-bolt:before{content:"\ea38"}.ti-bolt-off:before{content:"\ecec"}.ti-bomb:before{content:"\f59c"}.ti-bone:before{content:"\edb8"}.ti-bone-off:before{content:"\f0bb"}.ti-bong:before{content:"\f3a7"}.ti-bong-off:before{content:"\f3c7"}.ti-book:before{content:"\ea39"}.ti-book-2:before{content:"\efc5"}.ti-book-download:before{content:"\f070"}.ti-book-off:before{content:"\f0bc"}.ti-book-upload:before{content:"\f071"}.ti-bookmark:before{content:"\ea3a"}.ti-bookmark-off:before{content:"\eced"}.ti-bookmarks:before{content:"\ed08"}.ti-bookmarks-off:before{content:"\f0bd"}.ti-books:before{content:"\eff2"}.ti-books-off:before{content:"\f0be"}.ti-border-all:before{content:"\ea3b"}.ti-border-bottom:before{content:"\ea3c"}.ti-border-corners:before{content:"\f7a0"}.ti-border-horizontal:before{content:"\ea3d"}.ti-border-inner:before{content:"\ea3e"}.ti-border-left:before{content:"\ea3f"}.ti-border-none:before{content:"\ea40"}.ti-border-outer:before{content:"\ea41"}.ti-border-radius:before{content:"\eb7c"}.ti-border-right:before{content:"\ea42"}.ti-border-sides:before{content:"\f7a1"}.ti-border-style:before{content:"\ee0a"}.ti-border-style-2:before{content:"\ef22"}.ti-border-top:before{content:"\ea43"}.ti-border-vertical:before{content:"\ea44"}.ti-bottle:before{content:"\ef0b"}.ti-bottle-off:before{content:"\f3c8"}.ti-bounce-left:before{content:"\f59d"}.ti-bounce-right:before{content:"\f59e"}.ti-bow:before{content:"\f096"}.ti-bowl:before{content:"\f4fa"}.ti-box:before{content:"\ea45"}.ti-box-align-bottom:before{content:"\f2a8"}.ti-box-align-bottom-left:before{content:"\f2ce"}.ti-box-align-bottom-right:before{content:"\f2cf"}.ti-box-align-left:before{content:"\f2a9"}.ti-box-align-right:before{content:"\f2aa"}.ti-box-align-top:before{content:"\f2ab"}.ti-box-align-top-left:before{content:"\f2d0"}.ti-box-align-top-right:before{content:"\f2d1"}.ti-box-margin:before{content:"\ee0b"}.ti-box-model:before{content:"\ee0c"}.ti-box-model-2:before{content:"\ef23"}.ti-box-model-2-off:before{content:"\f3c9"}.ti-box-model-off:before{content:"\f3ca"}.ti-box-multiple:before{content:"\ee17"}.ti-box-multiple-0:before{content:"\ee0d"}.ti-box-multiple-1:before{content:"\ee0e"}.ti-box-multiple-2:before{content:"\ee0f"}.ti-box-multiple-3:before{content:"\ee10"}.ti-box-multiple-4:before{content:"\ee11"}.ti-box-multiple-5:before{content:"\ee12"}.ti-box-multiple-6:before{content:"\ee13"}.ti-box-multiple-7:before{content:"\ee14"}.ti-box-multiple-8:before{content:"\ee15"}.ti-box-multiple-9:before{content:"\ee16"}.ti-box-off:before{content:"\f102"}.ti-box-padding:before{content:"\ee18"}.ti-box-seam:before{content:"\f561"}.ti-braces:before{content:"\ebcc"}.ti-braces-off:before{content:"\f0bf"}.ti-brackets:before{content:"\ebcd"}.ti-brackets-contain:before{content:"\f1e5"}.ti-brackets-contain-end:before{content:"\f1e3"}.ti-brackets-contain-start:before{content:"\f1e4"}.ti-brackets-off:before{content:"\f0c0"}.ti-braille:before{content:"\f545"}.ti-brain:before{content:"\f59f"}.ti-brand-4chan:before{content:"\f494"}.ti-brand-abstract:before{content:"\f495"}.ti-brand-adobe:before{content:"\f0dc"}.ti-brand-adonis-js:before{content:"\f496"}.ti-brand-airbnb:before{content:"\ed68"}.ti-brand-airtable:before{content:"\ef6a"}.ti-brand-algolia:before{content:"\f390"}.ti-brand-alipay:before{content:"\f7a2"}.ti-brand-alpine-js:before{content:"\f324"}.ti-brand-amazon:before{content:"\f230"}.ti-brand-amd:before{content:"\f653"}.ti-brand-amigo:before{content:"\f5f9"}.ti-brand-among-us:before{content:"\f205"}.ti-brand-android:before{content:"\ec16"}.ti-brand-angular:before{content:"\ef6b"}.ti-brand-ao3:before{content:"\f5e8"}.ti-brand-appgallery:before{content:"\f231"}.ti-brand-apple:before{content:"\ec17"}.ti-brand-apple-arcade:before{content:"\ed69"}.ti-brand-apple-podcast:before{content:"\f1e6"}.ti-brand-appstore:before{content:"\ed24"}.ti-brand-asana:before{content:"\edc5"}.ti-brand-backbone:before{content:"\f325"}.ti-brand-badoo:before{content:"\f206"}.ti-brand-baidu:before{content:"\f5e9"}.ti-brand-bandcamp:before{content:"\f207"}.ti-brand-bandlab:before{content:"\f5fa"}.ti-brand-beats:before{content:"\f208"}.ti-brand-behance:before{content:"\ec6e"}.ti-brand-bilibili:before{content:"\f6d2"}.ti-brand-binance:before{content:"\f5a0"}.ti-brand-bing:before{content:"\edc6"}.ti-brand-bitbucket:before{content:"\edc7"}.ti-brand-blackberry:before{content:"\f568"}.ti-brand-blender:before{content:"\f326"}.ti-brand-blogger:before{content:"\f35a"}.ti-brand-booking:before{content:"\edc8"}.ti-brand-bootstrap:before{content:"\ef3e"}.ti-brand-bulma:before{content:"\f327"}.ti-brand-bumble:before{content:"\f5fb"}.ti-brand-bunpo:before{content:"\f4cf"}.ti-brand-c-sharp:before{content:"\f003"}.ti-brand-cake:before{content:"\f7a3"}.ti-brand-cakephp:before{content:"\f7af"}.ti-brand-campaignmonitor:before{content:"\f328"}.ti-brand-carbon:before{content:"\f348"}.ti-brand-cashapp:before{content:"\f391"}.ti-brand-chrome:before{content:"\ec18"}.ti-brand-citymapper:before{content:"\f5fc"}.ti-brand-codecov:before{content:"\f329"}.ti-brand-codepen:before{content:"\ec6f"}.ti-brand-codesandbox:before{content:"\ed6a"}.ti-brand-cohost:before{content:"\f5d5"}.ti-brand-coinbase:before{content:"\f209"}.ti-brand-comedy-central:before{content:"\f217"}.ti-brand-coreos:before{content:"\f5fd"}.ti-brand-couchdb:before{content:"\f60f"}.ti-brand-couchsurfing:before{content:"\f392"}.ti-brand-cpp:before{content:"\f5fe"}.ti-brand-crunchbase:before{content:"\f7e3"}.ti-brand-css3:before{content:"\ed6b"}.ti-brand-ctemplar:before{content:"\f4d0"}.ti-brand-cucumber:before{content:"\ef6c"}.ti-brand-cupra:before{content:"\f4d1"}.ti-brand-cypress:before{content:"\f333"}.ti-brand-d3:before{content:"\f24e"}.ti-brand-days-counter:before{content:"\f4d2"}.ti-brand-dcos:before{content:"\f32a"}.ti-brand-debian:before{content:"\ef57"}.ti-brand-deezer:before{content:"\f78b"}.ti-brand-deliveroo:before{content:"\f4d3"}.ti-brand-deno:before{content:"\f24f"}.ti-brand-denodo:before{content:"\f610"}.ti-brand-deviantart:before{content:"\ecfb"}.ti-brand-dingtalk:before{content:"\f5ea"}.ti-brand-discord:before{content:"\ece3"}.ti-brand-discord-filled:before{content:"\f7e4"}.ti-brand-disney:before{content:"\f20a"}.ti-brand-disqus:before{content:"\edc9"}.ti-brand-django:before{content:"\f349"}.ti-brand-docker:before{content:"\edca"}.ti-brand-doctrine:before{content:"\ef6d"}.ti-brand-dolby-digital:before{content:"\f4d4"}.ti-brand-douban:before{content:"\f5ff"}.ti-brand-dribbble:before{content:"\ec19"}.ti-brand-dribbble-filled:before{content:"\f7e5"}.ti-brand-drops:before{content:"\f4d5"}.ti-brand-drupal:before{content:"\f393"}.ti-brand-edge:before{content:"\ecfc"}.ti-brand-elastic:before{content:"\f611"}.ti-brand-ember:before{content:"\f497"}.ti-brand-envato:before{content:"\f394"}.ti-brand-etsy:before{content:"\f654"}.ti-brand-evernote:before{content:"\f600"}.ti-brand-facebook:before{content:"\ec1a"}.ti-brand-facebook-filled:before{content:"\f7e6"}.ti-brand-figma:before{content:"\ec93"}.ti-brand-finder:before{content:"\f218"}.ti-brand-firebase:before{content:"\ef6e"}.ti-brand-firefox:before{content:"\ecfd"}.ti-brand-fiverr:before{content:"\f7a4"}.ti-brand-flickr:before{content:"\ecfe"}.ti-brand-flightradar24:before{content:"\f4d6"}.ti-brand-flipboard:before{content:"\f20b"}.ti-brand-flutter:before{content:"\f395"}.ti-brand-fortnite:before{content:"\f260"}.ti-brand-foursquare:before{content:"\ecff"}.ti-brand-framer:before{content:"\ec1b"}.ti-brand-framer-motion:before{content:"\f78c"}.ti-brand-funimation:before{content:"\f655"}.ti-brand-gatsby:before{content:"\f396"}.ti-brand-git:before{content:"\ef6f"}.ti-brand-github:before{content:"\ec1c"}.ti-brand-github-copilot:before{content:"\f4a8"}.ti-brand-github-filled:before{content:"\f7e7"}.ti-brand-gitlab:before{content:"\ec1d"}.ti-brand-gmail:before{content:"\efa2"}.ti-brand-golang:before{content:"\f78d"}.ti-brand-google:before{content:"\ec1f"}.ti-brand-google-analytics:before{content:"\edcb"}.ti-brand-google-big-query:before{content:"\f612"}.ti-brand-google-drive:before{content:"\ec1e"}.ti-brand-google-fit:before{content:"\f297"}.ti-brand-google-home:before{content:"\f601"}.ti-brand-google-one:before{content:"\f232"}.ti-brand-google-photos:before{content:"\f20c"}.ti-brand-google-play:before{content:"\ed25"}.ti-brand-google-podcasts:before{content:"\f656"}.ti-brand-grammarly:before{content:"\f32b"}.ti-brand-graphql:before{content:"\f32c"}.ti-brand-gravatar:before{content:"\edcc"}.ti-brand-grindr:before{content:"\f20d"}.ti-brand-guardian:before{content:"\f4fb"}.ti-brand-gumroad:before{content:"\f5d6"}.ti-brand-hbo:before{content:"\f657"}.ti-brand-headlessui:before{content:"\f32d"}.ti-brand-hipchat:before{content:"\edcd"}.ti-brand-html5:before{content:"\ed6c"}.ti-brand-inertia:before{content:"\f34a"}.ti-brand-instagram:before{content:"\ec20"}.ti-brand-intercom:before{content:"\f1cf"}.ti-brand-javascript:before{content:"\ef0c"}.ti-brand-juejin:before{content:"\f7b0"}.ti-brand-kickstarter:before{content:"\edce"}.ti-brand-kotlin:before{content:"\ed6d"}.ti-brand-laravel:before{content:"\f34b"}.ti-brand-lastfm:before{content:"\f001"}.ti-brand-line:before{content:"\f7e8"}.ti-brand-linkedin:before{content:"\ec8c"}.ti-brand-linktree:before{content:"\f1e7"}.ti-brand-linqpad:before{content:"\f562"}.ti-brand-loom:before{content:"\ef70"}.ti-brand-mailgun:before{content:"\f32e"}.ti-brand-mantine:before{content:"\f32f"}.ti-brand-mastercard:before{content:"\ef49"}.ti-brand-mastodon:before{content:"\f250"}.ti-brand-matrix:before{content:"\f5eb"}.ti-brand-mcdonalds:before{content:"\f251"}.ti-brand-medium:before{content:"\ec70"}.ti-brand-mercedes:before{content:"\f072"}.ti-brand-messenger:before{content:"\ec71"}.ti-brand-meta:before{content:"\efb0"}.ti-brand-miniprogram:before{content:"\f602"}.ti-brand-mixpanel:before{content:"\f397"}.ti-brand-monday:before{content:"\f219"}.ti-brand-mongodb:before{content:"\f613"}.ti-brand-my-oppo:before{content:"\f4d7"}.ti-brand-mysql:before{content:"\f614"}.ti-brand-national-geographic:before{content:"\f603"}.ti-brand-nem:before{content:"\f5a1"}.ti-brand-netbeans:before{content:"\ef71"}.ti-brand-netease-music:before{content:"\f604"}.ti-brand-netflix:before{content:"\edcf"}.ti-brand-nexo:before{content:"\f5a2"}.ti-brand-nextcloud:before{content:"\f4d8"}.ti-brand-nextjs:before{content:"\f0dd"}.ti-brand-nord-vpn:before{content:"\f37f"}.ti-brand-notion:before{content:"\ef7b"}.ti-brand-npm:before{content:"\f569"}.ti-brand-nuxt:before{content:"\f0de"}.ti-brand-nytimes:before{content:"\ef8d"}.ti-brand-office:before{content:"\f398"}.ti-brand-ok-ru:before{content:"\f399"}.ti-brand-onedrive:before{content:"\f5d7"}.ti-brand-onlyfans:before{content:"\f605"}.ti-brand-open-source:before{content:"\edd0"}.ti-brand-openai:before{content:"\f78e"}.ti-brand-openvpn:before{content:"\f39a"}.ti-brand-opera:before{content:"\ec21"}.ti-brand-pagekit:before{content:"\edd1"}.ti-brand-patreon:before{content:"\edd2"}.ti-brand-paypal:before{content:"\ec22"}.ti-brand-paypal-filled:before{content:"\f7e9"}.ti-brand-paypay:before{content:"\f5ec"}.ti-brand-peanut:before{content:"\f39b"}.ti-brand-pepsi:before{content:"\f261"}.ti-brand-php:before{content:"\ef72"}.ti-brand-picsart:before{content:"\f4d9"}.ti-brand-pinterest:before{content:"\ec8d"}.ti-brand-planetscale:before{content:"\f78f"}.ti-brand-pocket:before{content:"\ed00"}.ti-brand-polymer:before{content:"\f498"}.ti-brand-powershell:before{content:"\f5ed"}.ti-brand-prisma:before{content:"\f499"}.ti-brand-producthunt:before{content:"\edd3"}.ti-brand-pushbullet:before{content:"\f330"}.ti-brand-pushover:before{content:"\f20e"}.ti-brand-python:before{content:"\ed01"}.ti-brand-qq:before{content:"\f606"}.ti-brand-radix-ui:before{content:"\f790"}.ti-brand-react:before{content:"\f34c"}.ti-brand-react-native:before{content:"\ef73"}.ti-brand-reason:before{content:"\f49a"}.ti-brand-reddit:before{content:"\ec8e"}.ti-brand-redhat:before{content:"\f331"}.ti-brand-redux:before{content:"\f3a8"}.ti-brand-revolut:before{content:"\f4da"}.ti-brand-safari:before{content:"\ec23"}.ti-brand-samsungpass:before{content:"\f4db"}.ti-brand-sass:before{content:"\edd4"}.ti-brand-sentry:before{content:"\edd5"}.ti-brand-sharik:before{content:"\f4dc"}.ti-brand-shazam:before{content:"\edd6"}.ti-brand-shopee:before{content:"\f252"}.ti-brand-sketch:before{content:"\ec24"}.ti-brand-skype:before{content:"\ed02"}.ti-brand-slack:before{content:"\ec72"}.ti-brand-snapchat:before{content:"\ec25"}.ti-brand-snapseed:before{content:"\f253"}.ti-brand-snowflake:before{content:"\f615"}.ti-brand-socket-io:before{content:"\f49b"}.ti-brand-solidjs:before{content:"\f5ee"}.ti-brand-soundcloud:before{content:"\ed6e"}.ti-brand-spacehey:before{content:"\f4fc"}.ti-brand-spotify:before{content:"\ed03"}.ti-brand-stackoverflow:before{content:"\ef58"}.ti-brand-stackshare:before{content:"\f607"}.ti-brand-steam:before{content:"\ed6f"}.ti-brand-storybook:before{content:"\f332"}.ti-brand-storytel:before{content:"\f608"}.ti-brand-strava:before{content:"\f254"}.ti-brand-stripe:before{content:"\edd7"}.ti-brand-sublime-text:before{content:"\ef74"}.ti-brand-sugarizer:before{content:"\f7a5"}.ti-brand-supabase:before{content:"\f6d3"}.ti-brand-superhuman:before{content:"\f50c"}.ti-brand-supernova:before{content:"\f49c"}.ti-brand-surfshark:before{content:"\f255"}.ti-brand-svelte:before{content:"\f0df"}.ti-brand-symfony:before{content:"\f616"}.ti-brand-tabler:before{content:"\ec8f"}.ti-brand-tailwind:before{content:"\eca1"}.ti-brand-taobao:before{content:"\f5ef"}.ti-brand-ted:before{content:"\f658"}.ti-brand-telegram:before{content:"\ec26"}.ti-brand-tether:before{content:"\f5a3"}.ti-brand-threejs:before{content:"\f5f0"}.ti-brand-tidal:before{content:"\ed70"}.ti-brand-tikto-filled:before{content:"\f7ea"}.ti-brand-tiktok:before{content:"\ec73"}.ti-brand-tinder:before{content:"\ed71"}.ti-brand-topbuzz:before{content:"\f50d"}.ti-brand-torchain:before{content:"\f5a4"}.ti-brand-toyota:before{content:"\f262"}.ti-brand-trello:before{content:"\f39d"}.ti-brand-tripadvisor:before{content:"\f002"}.ti-brand-tumblr:before{content:"\ed04"}.ti-brand-twilio:before{content:"\f617"}.ti-brand-twitch:before{content:"\ed05"}.ti-brand-twitter:before{content:"\ec27"}.ti-brand-twitter-filled:before{content:"\f7eb"}.ti-brand-typescript:before{content:"\f5f1"}.ti-brand-uber:before{content:"\ef75"}.ti-brand-ubuntu:before{content:"\ef59"}.ti-brand-unity:before{content:"\f49d"}.ti-brand-unsplash:before{content:"\edd8"}.ti-brand-upwork:before{content:"\f39e"}.ti-brand-valorant:before{content:"\f39f"}.ti-brand-vercel:before{content:"\ef24"}.ti-brand-vimeo:before{content:"\ed06"}.ti-brand-vinted:before{content:"\f20f"}.ti-brand-visa:before{content:"\f380"}.ti-brand-visual-studio:before{content:"\ef76"}.ti-brand-vite:before{content:"\f5f2"}.ti-brand-vivaldi:before{content:"\f210"}.ti-brand-vk:before{content:"\ed72"}.ti-brand-volkswagen:before{content:"\f50e"}.ti-brand-vsco:before{content:"\f334"}.ti-brand-vscode:before{content:"\f3a0"}.ti-brand-vue:before{content:"\f0e0"}.ti-brand-walmart:before{content:"\f211"}.ti-brand-waze:before{content:"\f5d8"}.ti-brand-webflow:before{content:"\f2d2"}.ti-brand-wechat:before{content:"\f5f3"}.ti-brand-weibo:before{content:"\f609"}.ti-brand-whatsapp:before{content:"\ec74"}.ti-brand-windows:before{content:"\ecd8"}.ti-brand-windy:before{content:"\f4dd"}.ti-brand-wish:before{content:"\f212"}.ti-brand-wix:before{content:"\f3a1"}.ti-brand-wordpress:before{content:"\f2d3"}.ti-brand-xbox:before{content:"\f298"}.ti-brand-xing:before{content:"\f21a"}.ti-brand-yahoo:before{content:"\ed73"}.ti-brand-yatse:before{content:"\f213"}.ti-brand-ycombinator:before{content:"\edd9"}.ti-brand-youtube:before{content:"\ec90"}.ti-brand-youtube-kids:before{content:"\f214"}.ti-brand-zalando:before{content:"\f49e"}.ti-brand-zapier:before{content:"\f49f"}.ti-brand-zeit:before{content:"\f335"}.ti-brand-zhihu:before{content:"\f60a"}.ti-brand-zoom:before{content:"\f215"}.ti-brand-zulip:before{content:"\f4de"}.ti-brand-zwift:before{content:"\f216"}.ti-bread:before{content:"\efa3"}.ti-bread-off:before{content:"\f3cb"}.ti-briefcase:before{content:"\ea46"}.ti-briefcase-off:before{content:"\f3cc"}.ti-brightness:before{content:"\eb7f"}.ti-brightness-2:before{content:"\ee19"}.ti-brightness-down:before{content:"\eb7d"}.ti-brightness-half:before{content:"\ee1a"}.ti-brightness-off:before{content:"\f3cd"}.ti-brightness-up:before{content:"\eb7e"}.ti-broadcast:before{content:"\f1e9"}.ti-broadcast-off:before{content:"\f1e8"}.ti-browser:before{content:"\ebb7"}.ti-browser-check:before{content:"\efd6"}.ti-browser-off:before{content:"\f0c1"}.ti-browser-plus:before{content:"\efd7"}.ti-browser-x:before{content:"\efd8"}.ti-brush:before{content:"\ebb8"}.ti-brush-off:before{content:"\f0c2"}.ti-bucket:before{content:"\ea47"}.ti-bucket-droplet:before{content:"\f56a"}.ti-bucket-off:before{content:"\f103"}.ti-bug:before{content:"\ea48"}.ti-bug-off:before{content:"\f0c3"}.ti-building:before{content:"\ea4f"}.ti-building-arch:before{content:"\ea49"}.ti-building-bank:before{content:"\ebe2"}.ti-building-bridge:before{content:"\ea4b"}.ti-building-bridge-2:before{content:"\ea4a"}.ti-building-broadcast-tower:before{content:"\f4be"}.ti-building-carousel:before{content:"\ed87"}.ti-building-castle:before{content:"\ed88"}.ti-building-church:before{content:"\ea4c"}.ti-building-circus:before{content:"\f4bf"}.ti-building-community:before{content:"\ebf6"}.ti-building-cottage:before{content:"\ee1b"}.ti-building-estate:before{content:"\f5a5"}.ti-building-factory:before{content:"\ee1c"}.ti-building-factory-2:before{content:"\f082"}.ti-building-fortress:before{content:"\ed89"}.ti-building-hospital:before{content:"\ea4d"}.ti-building-lighthouse:before{content:"\ed8a"}.ti-building-monument:before{content:"\ed26"}.ti-building-pavilion:before{content:"\ebf7"}.ti-building-skyscraper:before{content:"\ec39"}.ti-building-stadium:before{content:"\f641"}.ti-building-store:before{content:"\ea4e"}.ti-building-tunnel:before{content:"\f5a6"}.ti-building-warehouse:before{content:"\ebe3"}.ti-building-wind-turbine:before{content:"\f4c0"}.ti-bulb:before{content:"\ea51"}.ti-bulb-filled:before{content:"\f66a"}.ti-bulb-off:before{content:"\ea50"}.ti-bulldozer:before{content:"\ee1d"}.ti-bus:before{content:"\ebe4"}.ti-bus-off:before{content:"\f3ce"}.ti-bus-stop:before{content:"\f2d4"}.ti-businessplan:before{content:"\ee1e"}.ti-butterfly:before{content:"\efd9"}.ti-cactus:before{content:"\f21b"}.ti-cactus-off:before{content:"\f3cf"}.ti-cake:before{content:"\f00f"}.ti-cake-off:before{content:"\f104"}.ti-calculator:before{content:"\eb80"}.ti-calculator-off:before{content:"\f0c4"}.ti-calendar:before{content:"\ea53"}.ti-calendar-bolt:before{content:"\f822"}.ti-calendar-cancel:before{content:"\f823"}.ti-calendar-check:before{content:"\f824"}.ti-calendar-code:before{content:"\f825"}.ti-calendar-cog:before{content:"\f826"}.ti-calendar-dollar:before{content:"\f827"}.ti-calendar-down:before{content:"\f828"}.ti-calendar-due:before{content:"\f621"}.ti-calendar-event:before{content:"\ea52"}.ti-calendar-exclamation:before{content:"\f829"}.ti-calendar-heart:before{content:"\f82a"}.ti-calendar-minus:before{content:"\ebb9"}.ti-calendar-off:before{content:"\ee1f"}.ti-calendar-pause:before{content:"\f82b"}.ti-calendar-pin:before{content:"\f82c"}.ti-calendar-plus:before{content:"\ebba"}.ti-calendar-question:before{content:"\f82d"}.ti-calendar-search:before{content:"\f82e"}.ti-calendar-share:before{content:"\f82f"}.ti-calendar-star:before{content:"\f830"}.ti-calendar-stats:before{content:"\ee20"}.ti-calendar-time:before{content:"\ee21"}.ti-calendar-up:before{content:"\f831"}.ti-calendar-x:before{content:"\f832"}.ti-camera:before{content:"\ea54"}.ti-camera-bolt:before{content:"\f833"}.ti-camera-cancel:before{content:"\f834"}.ti-camera-check:before{content:"\f835"}.ti-camera-code:before{content:"\f836"}.ti-camera-cog:before{content:"\f837"}.ti-camera-dollar:before{content:"\f838"}.ti-camera-down:before{content:"\f839"}.ti-camera-exclamation:before{content:"\f83a"}.ti-camera-heart:before{content:"\f83b"}.ti-camera-minus:before{content:"\ec3a"}.ti-camera-off:before{content:"\ecee"}.ti-camera-pause:before{content:"\f83c"}.ti-camera-pin:before{content:"\f83d"}.ti-camera-plus:before{content:"\ec3b"}.ti-camera-question:before{content:"\f83e"}.ti-camera-rotate:before{content:"\ee22"}.ti-camera-search:before{content:"\f83f"}.ti-camera-selfie:before{content:"\ee23"}.ti-camera-share:before{content:"\f840"}.ti-camera-star:before{content:"\f841"}.ti-camera-up:before{content:"\f842"}.ti-camera-x:before{content:"\f843"}.ti-campfire:before{content:"\f5a7"}.ti-candle:before{content:"\efc6"}.ti-candy:before{content:"\ef0d"}.ti-candy-off:before{content:"\f0c5"}.ti-cane:before{content:"\f50f"}.ti-cannabis:before{content:"\f4c1"}.ti-capture:before{content:"\ec3c"}.ti-capture-off:before{content:"\f0c6"}.ti-car:before{content:"\ebbb"}.ti-car-crane:before{content:"\ef25"}.ti-car-crash:before{content:"\efa4"}.ti-car-off:before{content:"\f0c7"}.ti-car-turbine:before{content:"\f4fd"}.ti-caravan:before{content:"\ec7c"}.ti-cardboards:before{content:"\ed74"}.ti-cardboards-off:before{content:"\f0c8"}.ti-cards:before{content:"\f510"}.ti-caret-down:before{content:"\eb5d"}.ti-caret-left:before{content:"\eb5e"}.ti-caret-right:before{content:"\eb5f"}.ti-caret-up:before{content:"\eb60"}.ti-carousel-horizontal:before{content:"\f659"}.ti-carousel-vertical:before{content:"\f65a"}.ti-carrot:before{content:"\f21c"}.ti-carrot-off:before{content:"\f3d0"}.ti-cash:before{content:"\ea55"}.ti-cash-banknote:before{content:"\ee25"}.ti-cash-banknote-off:before{content:"\ee24"}.ti-cash-off:before{content:"\f105"}.ti-cast:before{content:"\ea56"}.ti-cast-off:before{content:"\f0c9"}.ti-cat:before{content:"\f65b"}.ti-category:before{content:"\f1f6"}.ti-category-2:before{content:"\f1f5"}.ti-ce:before{content:"\ed75"}.ti-ce-off:before{content:"\f0ca"}.ti-cell:before{content:"\f05f"}.ti-cell-signal-1:before{content:"\f083"}.ti-cell-signal-2:before{content:"\f084"}.ti-cell-signal-3:before{content:"\f085"}.ti-cell-signal-4:before{content:"\f086"}.ti-cell-signal-5:before{content:"\f087"}.ti-cell-signal-off:before{content:"\f088"}.ti-certificate:before{content:"\ed76"}.ti-certificate-2:before{content:"\f073"}.ti-certificate-2-off:before{content:"\f0cb"}.ti-certificate-off:before{content:"\f0cc"}.ti-chair-director:before{content:"\f2d5"}.ti-chalkboard:before{content:"\f34d"}.ti-chalkboard-off:before{content:"\f3d1"}.ti-charging-pile:before{content:"\ee26"}.ti-chart-arcs:before{content:"\ee28"}.ti-chart-arcs-3:before{content:"\ee27"}.ti-chart-area:before{content:"\ea58"}.ti-chart-area-filled:before{content:"\f66b"}.ti-chart-area-line:before{content:"\ea57"}.ti-chart-area-line-filled:before{content:"\f66c"}.ti-chart-arrows:before{content:"\ee2a"}.ti-chart-arrows-vertical:before{content:"\ee29"}.ti-chart-bar:before{content:"\ea59"}.ti-chart-bar-off:before{content:"\f3d2"}.ti-chart-bubble:before{content:"\ec75"}.ti-chart-bubble-filled:before{content:"\f66d"}.ti-chart-candle:before{content:"\ea5a"}.ti-chart-candle-filled:before{content:"\f66e"}.ti-chart-circles:before{content:"\ee2b"}.ti-chart-donut:before{content:"\ea5b"}.ti-chart-donut-2:before{content:"\ee2c"}.ti-chart-donut-3:before{content:"\ee2d"}.ti-chart-donut-4:before{content:"\ee2e"}.ti-chart-donut-filled:before{content:"\f66f"}.ti-chart-dots:before{content:"\ee2f"}.ti-chart-dots-2:before{content:"\f097"}.ti-chart-dots-3:before{content:"\f098"}.ti-chart-grid-dots:before{content:"\f4c2"}.ti-chart-histogram:before{content:"\f65c"}.ti-chart-infographic:before{content:"\ee30"}.ti-chart-line:before{content:"\ea5c"}.ti-chart-pie:before{content:"\ea5d"}.ti-chart-pie-2:before{content:"\ee31"}.ti-chart-pie-3:before{content:"\ee32"}.ti-chart-pie-4:before{content:"\ee33"}.ti-chart-pie-filled:before{content:"\f670"}.ti-chart-pie-off:before{content:"\f3d3"}.ti-chart-ppf:before{content:"\f618"}.ti-chart-radar:before{content:"\ed77"}.ti-chart-sankey:before{content:"\f619"}.ti-chart-treemap:before{content:"\f381"}.ti-check:before{content:"\ea5e"}.ti-checkbox:before{content:"\eba6"}.ti-checklist:before{content:"\f074"}.ti-checks:before{content:"\ebaa"}.ti-checkup-list:before{content:"\ef5a"}.ti-cheese:before{content:"\ef26"}.ti-chef-hat:before{content:"\f21d"}.ti-chef-hat-off:before{content:"\f3d4"}.ti-cherry:before{content:"\f511"}.ti-cherry-filled:before{content:"\f728"}.ti-chess:before{content:"\f382"}.ti-chess-bishop:before{content:"\f56b"}.ti-chess-bishop-filled:before{content:"\f729"}.ti-chess-filled:before{content:"\f72a"}.ti-chess-king:before{content:"\f56c"}.ti-chess-king-filled:before{content:"\f72b"}.ti-chess-knight:before{content:"\f56d"}.ti-chess-knight-filled:before{content:"\f72c"}.ti-chess-queen:before{content:"\f56e"}.ti-chess-queen-filled:before{content:"\f72d"}.ti-chess-rook:before{content:"\f56f"}.ti-chess-rook-filled:before{content:"\f72e"}.ti-chevron-down:before{content:"\ea5f"}.ti-chevron-down-left:before{content:"\ed09"}.ti-chevron-down-right:before{content:"\ed0a"}.ti-chevron-left:before{content:"\ea60"}.ti-chevron-right:before{content:"\ea61"}.ti-chevron-up:before{content:"\ea62"}.ti-chevron-up-left:before{content:"\ed0b"}.ti-chevron-up-right:before{content:"\ed0c"}.ti-chevrons-down:before{content:"\ea63"}.ti-chevrons-down-left:before{content:"\ed0d"}.ti-chevrons-down-right:before{content:"\ed0e"}.ti-chevrons-left:before{content:"\ea64"}.ti-chevrons-right:before{content:"\ea65"}.ti-chevrons-up:before{content:"\ea66"}.ti-chevrons-up-left:before{content:"\ed0f"}.ti-chevrons-up-right:before{content:"\ed10"}.ti-chisel:before{content:"\f383"}.ti-christmas-tree:before{content:"\ed78"}.ti-christmas-tree-off:before{content:"\f3d5"}.ti-circle:before{content:"\ea6b"}.ti-circle-0-filled:before{content:"\f72f"}.ti-circle-1-filled:before{content:"\f730"}.ti-circle-2-filled:before{content:"\f731"}.ti-circle-3-filled:before{content:"\f732"}.ti-circle-4-filled:before{content:"\f733"}.ti-circle-5-filled:before{content:"\f734"}.ti-circle-6-filled:before{content:"\f735"}.ti-circle-7-filled:before{content:"\f736"}.ti-circle-8-filled:before{content:"\f737"}.ti-circle-9-filled:before{content:"\f738"}.ti-circle-arrow-down:before{content:"\f6f9"}.ti-circle-arrow-down-filled:before{content:"\f6f4"}.ti-circle-arrow-down-left:before{content:"\f6f6"}.ti-circle-arrow-down-left-filled:before{content:"\f6f5"}.ti-circle-arrow-down-right:before{content:"\f6f8"}.ti-circle-arrow-down-right-filled:before{content:"\f6f7"}.ti-circle-arrow-left:before{content:"\f6fb"}.ti-circle-arrow-left-filled:before{content:"\f6fa"}.ti-circle-arrow-right:before{content:"\f6fd"}.ti-circle-arrow-right-filled:before{content:"\f6fc"}.ti-circle-arrow-up:before{content:"\f703"}.ti-circle-arrow-up-filled:before{content:"\f6fe"}.ti-circle-arrow-up-left:before{content:"\f700"}.ti-circle-arrow-up-left-filled:before{content:"\f6ff"}.ti-circle-arrow-up-right:before{content:"\f702"}.ti-circle-arrow-up-right-filled:before{content:"\f701"}.ti-circle-caret-down:before{content:"\f4a9"}.ti-circle-caret-left:before{content:"\f4aa"}.ti-circle-caret-right:before{content:"\f4ab"}.ti-circle-caret-up:before{content:"\f4ac"}.ti-circle-check:before{content:"\ea67"}.ti-circle-check-filled:before{content:"\f704"}.ti-circle-chevron-down:before{content:"\f622"}.ti-circle-chevron-left:before{content:"\f623"}.ti-circle-chevron-right:before{content:"\f624"}.ti-circle-chevron-up:before{content:"\f625"}.ti-circle-chevrons-down:before{content:"\f642"}.ti-circle-chevrons-left:before{content:"\f643"}.ti-circle-chevrons-right:before{content:"\f644"}.ti-circle-chevrons-up:before{content:"\f645"}.ti-circle-dashed:before{content:"\ed27"}.ti-circle-dot:before{content:"\efb1"}.ti-circle-dot-filled:before{content:"\f705"}.ti-circle-dotted:before{content:"\ed28"}.ti-circle-filled:before{content:"\f671"}.ti-circle-half:before{content:"\ee3f"}.ti-circle-half-2:before{content:"\eff3"}.ti-circle-half-vertical:before{content:"\ee3e"}.ti-circle-key:before{content:"\f633"}.ti-circle-key-filled:before{content:"\f706"}.ti-circle-letter-a:before{content:"\f441"}.ti-circle-letter-b:before{content:"\f442"}.ti-circle-letter-c:before{content:"\f443"}.ti-circle-letter-d:before{content:"\f444"}.ti-circle-letter-e:before{content:"\f445"}.ti-circle-letter-f:before{content:"\f446"}.ti-circle-letter-g:before{content:"\f447"}.ti-circle-letter-h:before{content:"\f448"}.ti-circle-letter-i:before{content:"\f449"}.ti-circle-letter-j:before{content:"\f44a"}.ti-circle-letter-k:before{content:"\f44b"}.ti-circle-letter-l:before{content:"\f44c"}.ti-circle-letter-m:before{content:"\f44d"}.ti-circle-letter-n:before{content:"\f44e"}.ti-circle-letter-o:before{content:"\f44f"}.ti-circle-letter-p:before{content:"\f450"}.ti-circle-letter-q:before{content:"\f451"}.ti-circle-letter-r:before{content:"\f452"}.ti-circle-letter-s:before{content:"\f453"}.ti-circle-letter-t:before{content:"\f454"}.ti-circle-letter-u:before{content:"\f455"}.ti-circle-letter-v:before{content:"\f4ad"}.ti-circle-letter-w:before{content:"\f456"}.ti-circle-letter-x:before{content:"\f4ae"}.ti-circle-letter-y:before{content:"\f457"}.ti-circle-letter-z:before{content:"\f458"}.ti-circle-minus:before{content:"\ea68"}.ti-circle-number-0:before{content:"\ee34"}.ti-circle-number-1:before{content:"\ee35"}.ti-circle-number-2:before{content:"\ee36"}.ti-circle-number-3:before{content:"\ee37"}.ti-circle-number-4:before{content:"\ee38"}.ti-circle-number-5:before{content:"\ee39"}.ti-circle-number-6:before{content:"\ee3a"}.ti-circle-number-7:before{content:"\ee3b"}.ti-circle-number-8:before{content:"\ee3c"}.ti-circle-number-9:before{content:"\ee3d"}.ti-circle-off:before{content:"\ee40"}.ti-circle-plus:before{content:"\ea69"}.ti-circle-rectangle:before{content:"\f010"}.ti-circle-rectangle-off:before{content:"\f0cd"}.ti-circle-square:before{content:"\ece4"}.ti-circle-triangle:before{content:"\f011"}.ti-circle-x:before{content:"\ea6a"}.ti-circle-x-filled:before{content:"\f739"}.ti-circles:before{content:"\ece5"}.ti-circles-filled:before{content:"\f672"}.ti-circles-relation:before{content:"\f4c3"}.ti-circuit-ammeter:before{content:"\f271"}.ti-circuit-battery:before{content:"\f272"}.ti-circuit-bulb:before{content:"\f273"}.ti-circuit-capacitor:before{content:"\f275"}.ti-circuit-capacitor-polarized:before{content:"\f274"}.ti-circuit-cell:before{content:"\f277"}.ti-circuit-cell-plus:before{content:"\f276"}.ti-circuit-changeover:before{content:"\f278"}.ti-circuit-diode:before{content:"\f27a"}.ti-circuit-diode-zener:before{content:"\f279"}.ti-circuit-ground:before{content:"\f27c"}.ti-circuit-ground-digital:before{content:"\f27b"}.ti-circuit-inductor:before{content:"\f27d"}.ti-circuit-motor:before{content:"\f27e"}.ti-circuit-pushbutton:before{content:"\f27f"}.ti-circuit-resistor:before{content:"\f280"}.ti-circuit-switch-closed:before{content:"\f281"}.ti-circuit-switch-open:before{content:"\f282"}.ti-circuit-voltmeter:before{content:"\f283"}.ti-clear-all:before{content:"\ee41"}.ti-clear-formatting:before{content:"\ebe5"}.ti-click:before{content:"\ebbc"}.ti-clipboard:before{content:"\ea6f"}.ti-clipboard-check:before{content:"\ea6c"}.ti-clipboard-copy:before{content:"\f299"}.ti-clipboard-data:before{content:"\f563"}.ti-clipboard-heart:before{content:"\f34e"}.ti-clipboard-list:before{content:"\ea6d"}.ti-clipboard-off:before{content:"\f0ce"}.ti-clipboard-plus:before{content:"\efb2"}.ti-clipboard-text:before{content:"\f089"}.ti-clipboard-typography:before{content:"\f34f"}.ti-clipboard-x:before{content:"\ea6e"}.ti-clock:before{content:"\ea70"}.ti-clock-2:before{content:"\f099"}.ti-clock-bolt:before{content:"\f844"}.ti-clock-cancel:before{content:"\f546"}.ti-clock-check:before{content:"\f7c1"}.ti-clock-code:before{content:"\f845"}.ti-clock-cog:before{content:"\f7c2"}.ti-clock-dollar:before{content:"\f846"}.ti-clock-down:before{content:"\f7c3"}.ti-clock-edit:before{content:"\f547"}.ti-clock-exclamation:before{content:"\f847"}.ti-clock-filled:before{content:"\f73a"}.ti-clock-heart:before{content:"\f7c4"}.ti-clock-hour-1:before{content:"\f313"}.ti-clock-hour-10:before{content:"\f314"}.ti-clock-hour-11:before{content:"\f315"}.ti-clock-hour-12:before{content:"\f316"}.ti-clock-hour-2:before{content:"\f317"}.ti-clock-hour-3:before{content:"\f318"}.ti-clock-hour-4:before{content:"\f319"}.ti-clock-hour-5:before{content:"\f31a"}.ti-clock-hour-6:before{content:"\f31b"}.ti-clock-hour-7:before{content:"\f31c"}.ti-clock-hour-8:before{content:"\f31d"}.ti-clock-hour-9:before{content:"\f31e"}.ti-clock-minus:before{content:"\f848"}.ti-clock-off:before{content:"\f0cf"}.ti-clock-pause:before{content:"\f548"}.ti-clock-pin:before{content:"\f849"}.ti-clock-play:before{content:"\f549"}.ti-clock-plus:before{content:"\f7c5"}.ti-clock-question:before{content:"\f7c6"}.ti-clock-record:before{content:"\f54a"}.ti-clock-search:before{content:"\f7c7"}.ti-clock-share:before{content:"\f84a"}.ti-clock-shield:before{content:"\f7c8"}.ti-clock-star:before{content:"\f7c9"}.ti-clock-stop:before{content:"\f54b"}.ti-clock-up:before{content:"\f7ca"}.ti-clock-x:before{content:"\f7cb"}.ti-clothes-rack:before{content:"\f285"}.ti-clothes-rack-off:before{content:"\f3d6"}.ti-cloud:before{content:"\ea76"}.ti-cloud-bolt:before{content:"\f84b"}.ti-cloud-cancel:before{content:"\f84c"}.ti-cloud-check:before{content:"\f84d"}.ti-cloud-code:before{content:"\f84e"}.ti-cloud-cog:before{content:"\f84f"}.ti-cloud-computing:before{content:"\f1d0"}.ti-cloud-data-connection:before{content:"\f1d1"}.ti-cloud-dollar:before{content:"\f850"}.ti-cloud-down:before{content:"\f851"}.ti-cloud-download:before{content:"\ea71"}.ti-cloud-exclamation:before{content:"\f852"}.ti-cloud-filled:before{content:"\f673"}.ti-cloud-fog:before{content:"\ecd9"}.ti-cloud-heart:before{content:"\f853"}.ti-cloud-lock:before{content:"\efdb"}.ti-cloud-lock-open:before{content:"\efda"}.ti-cloud-minus:before{content:"\f854"}.ti-cloud-off:before{content:"\ed3e"}.ti-cloud-pause:before{content:"\f855"}.ti-cloud-pin:before{content:"\f856"}.ti-cloud-plus:before{content:"\f857"}.ti-cloud-question:before{content:"\f858"}.ti-cloud-rain:before{content:"\ea72"}.ti-cloud-search:before{content:"\f859"}.ti-cloud-share:before{content:"\f85a"}.ti-cloud-snow:before{content:"\ea73"}.ti-cloud-star:before{content:"\f85b"}.ti-cloud-storm:before{content:"\ea74"}.ti-cloud-up:before{content:"\f85c"}.ti-cloud-upload:before{content:"\ea75"}.ti-cloud-x:before{content:"\f85d"}.ti-clover:before{content:"\f1ea"}.ti-clover-2:before{content:"\f21e"}.ti-clubs:before{content:"\eff4"}.ti-clubs-filled:before{content:"\f674"}.ti-code:before{content:"\ea77"}.ti-code-asterix:before{content:"\f312"}.ti-code-circle:before{content:"\f4ff"}.ti-code-circle-2:before{content:"\f4fe"}.ti-code-dots:before{content:"\f61a"}.ti-code-minus:before{content:"\ee42"}.ti-code-off:before{content:"\f0d0"}.ti-code-plus:before{content:"\ee43"}.ti-coffee:before{content:"\ef0e"}.ti-coffee-off:before{content:"\f106"}.ti-coffin:before{content:"\f579"}.ti-coin:before{content:"\eb82"}.ti-coin-bitcoin:before{content:"\f2be"}.ti-coin-euro:before{content:"\f2bf"}.ti-coin-monero:before{content:"\f4a0"}.ti-coin-off:before{content:"\f0d1"}.ti-coin-pound:before{content:"\f2c0"}.ti-coin-rupee:before{content:"\f2c1"}.ti-coin-yen:before{content:"\f2c2"}.ti-coin-yuan:before{content:"\f2c3"}.ti-coins:before{content:"\f65d"}.ti-color-filter:before{content:"\f5a8"}.ti-color-picker:before{content:"\ebe6"}.ti-color-picker-off:before{content:"\f0d2"}.ti-color-swatch:before{content:"\eb61"}.ti-color-swatch-off:before{content:"\f0d3"}.ti-column-insert-left:before{content:"\ee44"}.ti-column-insert-right:before{content:"\ee45"}.ti-columns:before{content:"\eb83"}.ti-columns-1:before{content:"\f6d4"}.ti-columns-2:before{content:"\f6d5"}.ti-columns-3:before{content:"\f6d6"}.ti-columns-off:before{content:"\f0d4"}.ti-comet:before{content:"\ec76"}.ti-command:before{content:"\ea78"}.ti-command-off:before{content:"\f3d7"}.ti-compass:before{content:"\ea79"}.ti-compass-off:before{content:"\f0d5"}.ti-components:before{content:"\efa5"}.ti-components-off:before{content:"\f0d6"}.ti-cone:before{content:"\efdd"}.ti-cone-2:before{content:"\efdc"}.ti-cone-off:before{content:"\f3d8"}.ti-confetti:before{content:"\ee46"}.ti-confetti-off:before{content:"\f3d9"}.ti-confucius:before{content:"\f58a"}.ti-container:before{content:"\ee47"}.ti-container-off:before{content:"\f107"}.ti-contrast:before{content:"\ec4e"}.ti-contrast-2:before{content:"\efc7"}.ti-contrast-2-off:before{content:"\f3da"}.ti-contrast-off:before{content:"\f3db"}.ti-cooker:before{content:"\f57a"}.ti-cookie:before{content:"\ef0f"}.ti-cookie-man:before{content:"\f4c4"}.ti-cookie-off:before{content:"\f0d7"}.ti-copy:before{content:"\ea7a"}.ti-copy-off:before{content:"\f0d8"}.ti-copyleft:before{content:"\ec3d"}.ti-copyleft-filled:before{content:"\f73b"}.ti-copyleft-off:before{content:"\f0d9"}.ti-copyright:before{content:"\ea7b"}.ti-copyright-filled:before{content:"\f73c"}.ti-copyright-off:before{content:"\f0da"}.ti-corner-down-left:before{content:"\ea7c"}.ti-corner-down-left-double:before{content:"\ee48"}.ti-corner-down-right:before{content:"\ea7d"}.ti-corner-down-right-double:before{content:"\ee49"}.ti-corner-left-down:before{content:"\ea7e"}.ti-corner-left-down-double:before{content:"\ee4a"}.ti-corner-left-up:before{content:"\ea7f"}.ti-corner-left-up-double:before{content:"\ee4b"}.ti-corner-right-down:before{content:"\ea80"}.ti-corner-right-down-double:before{content:"\ee4c"}.ti-corner-right-up:before{content:"\ea81"}.ti-corner-right-up-double:before{content:"\ee4d"}.ti-corner-up-left:before{content:"\ea82"}.ti-corner-up-left-double:before{content:"\ee4e"}.ti-corner-up-right:before{content:"\ea83"}.ti-corner-up-right-double:before{content:"\ee4f"}.ti-cpu:before{content:"\ef8e"}.ti-cpu-2:before{content:"\f075"}.ti-cpu-off:before{content:"\f108"}.ti-crane:before{content:"\ef27"}.ti-crane-off:before{content:"\f109"}.ti-creative-commons:before{content:"\efb3"}.ti-creative-commons-by:before{content:"\f21f"}.ti-creative-commons-nc:before{content:"\f220"}.ti-creative-commons-nd:before{content:"\f221"}.ti-creative-commons-off:before{content:"\f10a"}.ti-creative-commons-sa:before{content:"\f222"}.ti-creative-commons-zero:before{content:"\f223"}.ti-credit-card:before{content:"\ea84"}.ti-credit-card-off:before{content:"\ed11"}.ti-cricket:before{content:"\f09a"}.ti-crop:before{content:"\ea85"}.ti-cross:before{content:"\ef8f"}.ti-cross-filled:before{content:"\f675"}.ti-cross-off:before{content:"\f10b"}.ti-crosshair:before{content:"\ec3e"}.ti-crown:before{content:"\ed12"}.ti-crown-off:before{content:"\ee50"}.ti-crutches:before{content:"\ef5b"}.ti-crutches-off:before{content:"\f10c"}.ti-crystal-ball:before{content:"\f57b"}.ti-csv:before{content:"\f791"}.ti-cube-send:before{content:"\f61b"}.ti-cube-unfolded:before{content:"\f61c"}.ti-cup:before{content:"\ef28"}.ti-cup-off:before{content:"\f10d"}.ti-curling:before{content:"\efc8"}.ti-curly-loop:before{content:"\ecda"}.ti-currency:before{content:"\efa6"}.ti-currency-afghani:before{content:"\f65e"}.ti-currency-bahraini:before{content:"\ee51"}.ti-currency-baht:before{content:"\f08a"}.ti-currency-bitcoin:before{content:"\ebab"}.ti-currency-cent:before{content:"\ee53"}.ti-currency-dinar:before{content:"\ee54"}.ti-currency-dirham:before{content:"\ee55"}.ti-currency-dogecoin:before{content:"\ef4b"}.ti-currency-dollar:before{content:"\eb84"}.ti-currency-dollar-australian:before{content:"\ee56"}.ti-currency-dollar-brunei:before{content:"\f36c"}.ti-currency-dollar-canadian:before{content:"\ee57"}.ti-currency-dollar-guyanese:before{content:"\f36d"}.ti-currency-dollar-off:before{content:"\f3dc"}.ti-currency-dollar-singapore:before{content:"\ee58"}.ti-currency-dollar-zimbabwean:before{content:"\f36e"}.ti-currency-dong:before{content:"\f36f"}.ti-currency-dram:before{content:"\f370"}.ti-currency-ethereum:before{content:"\ee59"}.ti-currency-euro:before{content:"\eb85"}.ti-currency-euro-off:before{content:"\f3dd"}.ti-currency-forint:before{content:"\ee5a"}.ti-currency-frank:before{content:"\ee5b"}.ti-currency-guarani:before{content:"\f371"}.ti-currency-hryvnia:before{content:"\f372"}.ti-currency-kip:before{content:"\f373"}.ti-currency-krone-czech:before{content:"\ee5c"}.ti-currency-krone-danish:before{content:"\ee5d"}.ti-currency-krone-swedish:before{content:"\ee5e"}.ti-currency-lari:before{content:"\f374"}.ti-currency-leu:before{content:"\ee5f"}.ti-currency-lira:before{content:"\ee60"}.ti-currency-litecoin:before{content:"\ee61"}.ti-currency-lyd:before{content:"\f375"}.ti-currency-manat:before{content:"\f376"}.ti-currency-monero:before{content:"\f377"}.ti-currency-naira:before{content:"\ee62"}.ti-currency-nano:before{content:"\f7a6"}.ti-currency-off:before{content:"\f3de"}.ti-currency-paanga:before{content:"\f378"}.ti-currency-peso:before{content:"\f65f"}.ti-currency-pound:before{content:"\ebac"}.ti-currency-pound-off:before{content:"\f3df"}.ti-currency-quetzal:before{content:"\f379"}.ti-currency-real:before{content:"\ee63"}.ti-currency-renminbi:before{content:"\ee64"}.ti-currency-ripple:before{content:"\ee65"}.ti-currency-riyal:before{content:"\ee66"}.ti-currency-rubel:before{content:"\ee67"}.ti-currency-rufiyaa:before{content:"\f37a"}.ti-currency-rupee:before{content:"\ebad"}.ti-currency-rupee-nepalese:before{content:"\f37b"}.ti-currency-shekel:before{content:"\ee68"}.ti-currency-solana:before{content:"\f4a1"}.ti-currency-som:before{content:"\f37c"}.ti-currency-taka:before{content:"\ee69"}.ti-currency-tenge:before{content:"\f37d"}.ti-currency-tugrik:before{content:"\ee6a"}.ti-currency-won:before{content:"\ee6b"}.ti-currency-yen:before{content:"\ebae"}.ti-currency-yen-off:before{content:"\f3e0"}.ti-currency-yuan:before{content:"\f29a"}.ti-currency-zloty:before{content:"\ee6c"}.ti-current-location:before{content:"\ecef"}.ti-current-location-off:before{content:"\f10e"}.ti-cursor-off:before{content:"\f10f"}.ti-cursor-text:before{content:"\ee6d"}.ti-cut:before{content:"\ea86"}.ti-cylinder:before{content:"\f54c"}.ti-dashboard:before{content:"\ea87"}.ti-dashboard-off:before{content:"\f3e1"}.ti-database:before{content:"\ea88"}.ti-database-export:before{content:"\ee6e"}.ti-database-import:before{content:"\ee6f"}.ti-database-off:before{content:"\ee70"}.ti-deer:before{content:"\f4c5"}.ti-delta:before{content:"\f53c"}.ti-dental:before{content:"\f025"}.ti-dental-broken:before{content:"\f286"}.ti-dental-off:before{content:"\f110"}.ti-deselect:before{content:"\f9f3"}.ti-details:before{content:"\ee71"}.ti-details-off:before{content:"\f3e2"}.ti-device-airpods:before{content:"\f5a9"}.ti-device-airpods-case:before{content:"\f646"}.ti-device-analytics:before{content:"\ee72"}.ti-device-audio-tape:before{content:"\ee73"}.ti-device-camera-phone:before{content:"\f233"}.ti-device-cctv:before{content:"\ee74"}.ti-device-cctv-off:before{content:"\f3e3"}.ti-device-computer-camera:before{content:"\ee76"}.ti-device-computer-camera-off:before{content:"\ee75"}.ti-device-desktop:before{content:"\ea89"}.ti-device-desktop-analytics:before{content:"\ee77"}.ti-device-desktop-bolt:before{content:"\f85e"}.ti-device-desktop-cancel:before{content:"\f85f"}.ti-device-desktop-check:before{content:"\f860"}.ti-device-desktop-code:before{content:"\f861"}.ti-device-desktop-cog:before{content:"\f862"}.ti-device-desktop-dollar:before{content:"\f863"}.ti-device-desktop-down:before{content:"\f864"}.ti-device-desktop-exclamation:before{content:"\f865"}.ti-device-desktop-heart:before{content:"\f866"}.ti-device-desktop-minus:before{content:"\f867"}.ti-device-desktop-off:before{content:"\ee78"}.ti-device-desktop-pause:before{content:"\f868"}.ti-device-desktop-pin:before{content:"\f869"}.ti-device-desktop-plus:before{content:"\f86a"}.ti-device-desktop-question:before{content:"\f86b"}.ti-device-desktop-search:before{content:"\f86c"}.ti-device-desktop-share:before{content:"\f86d"}.ti-device-desktop-star:before{content:"\f86e"}.ti-device-desktop-up:before{content:"\f86f"}.ti-device-desktop-x:before{content:"\f870"}.ti-device-floppy:before{content:"\eb62"}.ti-device-gamepad:before{content:"\eb63"}.ti-device-gamepad-2:before{content:"\f1d2"}.ti-device-heart-monitor:before{content:"\f060"}.ti-device-imac:before{content:"\f7a7"}.ti-device-imac-bolt:before{content:"\f871"}.ti-device-imac-cancel:before{content:"\f872"}.ti-device-imac-check:before{content:"\f873"}.ti-device-imac-code:before{content:"\f874"}.ti-device-imac-cog:before{content:"\f875"}.ti-device-imac-dollar:before{content:"\f876"}.ti-device-imac-down:before{content:"\f877"}.ti-device-imac-exclamation:before{content:"\f878"}.ti-device-imac-heart:before{content:"\f879"}.ti-device-imac-minus:before{content:"\f87a"}.ti-device-imac-off:before{content:"\f87b"}.ti-device-imac-pause:before{content:"\f87c"}.ti-device-imac-pin:before{content:"\f87d"}.ti-device-imac-plus:before{content:"\f87e"}.ti-device-imac-question:before{content:"\f87f"}.ti-device-imac-search:before{content:"\f880"}.ti-device-imac-share:before{content:"\f881"}.ti-device-imac-star:before{content:"\f882"}.ti-device-imac-up:before{content:"\f883"}.ti-device-imac-x:before{content:"\f884"}.ti-device-ipad:before{content:"\f648"}.ti-device-ipad-bolt:before{content:"\f885"}.ti-device-ipad-cancel:before{content:"\f886"}.ti-device-ipad-check:before{content:"\f887"}.ti-device-ipad-code:before{content:"\f888"}.ti-device-ipad-cog:before{content:"\f889"}.ti-device-ipad-dollar:before{content:"\f88a"}.ti-device-ipad-down:before{content:"\f88b"}.ti-device-ipad-exclamation:before{content:"\f88c"}.ti-device-ipad-heart:before{content:"\f88d"}.ti-device-ipad-horizontal:before{content:"\f647"}.ti-device-ipad-horizontal-bolt:before{content:"\f88e"}.ti-device-ipad-horizontal-cancel:before{content:"\f88f"}.ti-device-ipad-horizontal-check:before{content:"\f890"}.ti-device-ipad-horizontal-code:before{content:"\f891"}.ti-device-ipad-horizontal-cog:before{content:"\f892"}.ti-device-ipad-horizontal-dollar:before{content:"\f893"}.ti-device-ipad-horizontal-down:before{content:"\f894"}.ti-device-ipad-horizontal-exclamation:before{content:"\f895"}.ti-device-ipad-horizontal-heart:before{content:"\f896"}.ti-device-ipad-horizontal-minus:before{content:"\f897"}.ti-device-ipad-horizontal-off:before{content:"\f898"}.ti-device-ipad-horizontal-pause:before{content:"\f899"}.ti-device-ipad-horizontal-pin:before{content:"\f89a"}.ti-device-ipad-horizontal-plus:before{content:"\f89b"}.ti-device-ipad-horizontal-question:before{content:"\f89c"}.ti-device-ipad-horizontal-search:before{content:"\f89d"}.ti-device-ipad-horizontal-share:before{content:"\f89e"}.ti-device-ipad-horizontal-star:before{content:"\f89f"}.ti-device-ipad-horizontal-up:before{content:"\f8a0"}.ti-device-ipad-horizontal-x:before{content:"\f8a1"}.ti-device-ipad-minus:before{content:"\f8a2"}.ti-device-ipad-off:before{content:"\f8a3"}.ti-device-ipad-pause:before{content:"\f8a4"}.ti-device-ipad-pin:before{content:"\f8a5"}.ti-device-ipad-plus:before{content:"\f8a6"}.ti-device-ipad-question:before{content:"\f8a7"}.ti-device-ipad-search:before{content:"\f8a8"}.ti-device-ipad-share:before{content:"\f8a9"}.ti-device-ipad-star:before{content:"\f8aa"}.ti-device-ipad-up:before{content:"\f8ab"}.ti-device-ipad-x:before{content:"\f8ac"}.ti-device-landline-phone:before{content:"\f649"}.ti-device-laptop:before{content:"\eb64"}.ti-device-laptop-off:before{content:"\f061"}.ti-device-mobile:before{content:"\ea8a"}.ti-device-mobile-bolt:before{content:"\f8ad"}.ti-device-mobile-cancel:before{content:"\f8ae"}.ti-device-mobile-charging:before{content:"\f224"}.ti-device-mobile-check:before{content:"\f8af"}.ti-device-mobile-code:before{content:"\f8b0"}.ti-device-mobile-cog:before{content:"\f8b1"}.ti-device-mobile-dollar:before{content:"\f8b2"}.ti-device-mobile-down:before{content:"\f8b3"}.ti-device-mobile-exclamation:before{content:"\f8b4"}.ti-device-mobile-heart:before{content:"\f8b5"}.ti-device-mobile-message:before{content:"\ee79"}.ti-device-mobile-minus:before{content:"\f8b6"}.ti-device-mobile-off:before{content:"\f062"}.ti-device-mobile-pause:before{content:"\f8b7"}.ti-device-mobile-pin:before{content:"\f8b8"}.ti-device-mobile-plus:before{content:"\f8b9"}.ti-device-mobile-question:before{content:"\f8ba"}.ti-device-mobile-rotated:before{content:"\ecdb"}.ti-device-mobile-search:before{content:"\f8bb"}.ti-device-mobile-share:before{content:"\f8bc"}.ti-device-mobile-star:before{content:"\f8bd"}.ti-device-mobile-up:before{content:"\f8be"}.ti-device-mobile-vibration:before{content:"\eb86"}.ti-device-mobile-x:before{content:"\f8bf"}.ti-device-nintendo:before{content:"\f026"}.ti-device-nintendo-off:before{content:"\f111"}.ti-device-remote:before{content:"\f792"}.ti-device-sd-card:before{content:"\f384"}.ti-device-sim:before{content:"\f4b2"}.ti-device-sim-1:before{content:"\f4af"}.ti-device-sim-2:before{content:"\f4b0"}.ti-device-sim-3:before{content:"\f4b1"}.ti-device-speaker:before{content:"\ea8b"}.ti-device-speaker-off:before{content:"\f112"}.ti-device-tablet:before{content:"\ea8c"}.ti-device-tablet-bolt:before{content:"\f8c0"}.ti-device-tablet-cancel:before{content:"\f8c1"}.ti-device-tablet-check:before{content:"\f8c2"}.ti-device-tablet-code:before{content:"\f8c3"}.ti-device-tablet-cog:before{content:"\f8c4"}.ti-device-tablet-dollar:before{content:"\f8c5"}.ti-device-tablet-down:before{content:"\f8c6"}.ti-device-tablet-exclamation:before{content:"\f8c7"}.ti-device-tablet-heart:before{content:"\f8c8"}.ti-device-tablet-minus:before{content:"\f8c9"}.ti-device-tablet-off:before{content:"\f063"}.ti-device-tablet-pause:before{content:"\f8ca"}.ti-device-tablet-pin:before{content:"\f8cb"}.ti-device-tablet-plus:before{content:"\f8cc"}.ti-device-tablet-question:before{content:"\f8cd"}.ti-device-tablet-search:before{content:"\f8ce"}.ti-device-tablet-share:before{content:"\f8cf"}.ti-device-tablet-star:before{content:"\f8d0"}.ti-device-tablet-up:before{content:"\f8d1"}.ti-device-tablet-x:before{content:"\f8d2"}.ti-device-tv:before{content:"\ea8d"}.ti-device-tv-off:before{content:"\f064"}.ti-device-tv-old:before{content:"\f1d3"}.ti-device-watch:before{content:"\ebf9"}.ti-device-watch-bolt:before{content:"\f8d3"}.ti-device-watch-cancel:before{content:"\f8d4"}.ti-device-watch-check:before{content:"\f8d5"}.ti-device-watch-code:before{content:"\f8d6"}.ti-device-watch-cog:before{content:"\f8d7"}.ti-device-watch-dollar:before{content:"\f8d8"}.ti-device-watch-down:before{content:"\f8d9"}.ti-device-watch-exclamation:before{content:"\f8da"}.ti-device-watch-heart:before{content:"\f8db"}.ti-device-watch-minus:before{content:"\f8dc"}.ti-device-watch-off:before{content:"\f065"}.ti-device-watch-pause:before{content:"\f8dd"}.ti-device-watch-pin:before{content:"\f8de"}.ti-device-watch-plus:before{content:"\f8df"}.ti-device-watch-question:before{content:"\f8e0"}.ti-device-watch-search:before{content:"\f8e1"}.ti-device-watch-share:before{content:"\f8e2"}.ti-device-watch-star:before{content:"\f8e3"}.ti-device-watch-stats:before{content:"\ef7d"}.ti-device-watch-stats-2:before{content:"\ef7c"}.ti-device-watch-up:before{content:"\f8e4"}.ti-device-watch-x:before{content:"\f8e5"}.ti-devices:before{content:"\eb87"}.ti-devices-2:before{content:"\ed29"}.ti-devices-bolt:before{content:"\f8e6"}.ti-devices-cancel:before{content:"\f8e7"}.ti-devices-check:before{content:"\f8e8"}.ti-devices-code:before{content:"\f8e9"}.ti-devices-cog:before{content:"\f8ea"}.ti-devices-dollar:before{content:"\f8eb"}.ti-devices-down:before{content:"\f8ec"}.ti-devices-exclamation:before{content:"\f8ed"}.ti-devices-heart:before{content:"\f8ee"}.ti-devices-minus:before{content:"\f8ef"}.ti-devices-off:before{content:"\f3e4"}.ti-devices-pause:before{content:"\f8f0"}.ti-devices-pc:before{content:"\ee7a"}.ti-devices-pc-off:before{content:"\f113"}.ti-devices-pin:before{content:"\f8f1"}.ti-devices-plus:before{content:"\f8f2"}.ti-devices-question:before{content:"\f8f3"}.ti-devices-search:before{content:"\f8f4"}.ti-devices-share:before{content:"\f8f5"}.ti-devices-star:before{content:"\f8f6"}.ti-devices-up:before{content:"\f8f7"}.ti-devices-x:before{content:"\f8f8"}.ti-dialpad:before{content:"\f067"}.ti-dialpad-off:before{content:"\f114"}.ti-diamond:before{content:"\eb65"}.ti-diamond-filled:before{content:"\f73d"}.ti-diamond-off:before{content:"\f115"}.ti-diamonds:before{content:"\eff5"}.ti-diamonds-filled:before{content:"\f676"}.ti-dice:before{content:"\eb66"}.ti-dice-1:before{content:"\f08b"}.ti-dice-1-filled:before{content:"\f73e"}.ti-dice-2:before{content:"\f08c"}.ti-dice-2-filled:before{content:"\f73f"}.ti-dice-3:before{content:"\f08d"}.ti-dice-3-filled:before{content:"\f740"}.ti-dice-4:before{content:"\f08e"}.ti-dice-4-filled:before{content:"\f741"}.ti-dice-5:before{content:"\f08f"}.ti-dice-5-filled:before{content:"\f742"}.ti-dice-6:before{content:"\f090"}.ti-dice-6-filled:before{content:"\f743"}.ti-dice-filled:before{content:"\f744"}.ti-dimensions:before{content:"\ee7b"}.ti-direction:before{content:"\ebfb"}.ti-direction-horizontal:before{content:"\ebfa"}.ti-direction-sign:before{content:"\f1f7"}.ti-direction-sign-filled:before{content:"\f745"}.ti-direction-sign-off:before{content:"\f3e5"}.ti-directions:before{content:"\ea8e"}.ti-directions-off:before{content:"\f116"}.ti-disabled:before{content:"\ea8f"}.ti-disabled-2:before{content:"\ebaf"}.ti-disabled-off:before{content:"\f117"}.ti-disc:before{content:"\ea90"}.ti-disc-golf:before{content:"\f385"}.ti-disc-off:before{content:"\f118"}.ti-discount:before{content:"\ebbd"}.ti-discount-2:before{content:"\ee7c"}.ti-discount-2-off:before{content:"\f3e6"}.ti-discount-check:before{content:"\f1f8"}.ti-discount-check-filled:before{content:"\f746"}.ti-discount-off:before{content:"\f3e7"}.ti-divide:before{content:"\ed5c"}.ti-dna:before{content:"\ee7d"}.ti-dna-2:before{content:"\ef5c"}.ti-dna-2-off:before{content:"\f119"}.ti-dna-off:before{content:"\f11a"}.ti-dog:before{content:"\f660"}.ti-dog-bowl:before{content:"\ef29"}.ti-door:before{content:"\ef4e"}.ti-door-enter:before{content:"\ef4c"}.ti-door-exit:before{content:"\ef4d"}.ti-door-off:before{content:"\f11b"}.ti-dots:before{content:"\ea95"}.ti-dots-circle-horizontal:before{content:"\ea91"}.ti-dots-diagonal:before{content:"\ea93"}.ti-dots-diagonal-2:before{content:"\ea92"}.ti-dots-vertical:before{content:"\ea94"}.ti-download:before{content:"\ea96"}.ti-download-off:before{content:"\f11c"}.ti-drag-drop:before{content:"\eb89"}.ti-drag-drop-2:before{content:"\eb88"}.ti-drone:before{content:"\ed79"}.ti-drone-off:before{content:"\ee7e"}.ti-drop-circle:before{content:"\efde"}.ti-droplet:before{content:"\ea97"}.ti-droplet-bolt:before{content:"\f8f9"}.ti-droplet-cancel:before{content:"\f8fa"}.ti-droplet-check:before{content:"\f8fb"}.ti-droplet-code:before{content:"\f8fc"}.ti-droplet-cog:before{content:"\f8fd"}.ti-droplet-dollar:before{content:"\f8fe"}.ti-droplet-down:before{content:"\f8ff"}.ti-droplet-exclamation:before{content:"\f900"}.ti-droplet-filled:before{content:"\ee80"}.ti-droplet-filled-2:before{content:"\ee7f"}.ti-droplet-half:before{content:"\ee82"}.ti-droplet-half-2:before{content:"\ee81"}.ti-droplet-half-filled:before{content:"\f6c5"}.ti-droplet-heart:before{content:"\f901"}.ti-droplet-minus:before{content:"\f902"}.ti-droplet-off:before{content:"\ee83"}.ti-droplet-pause:before{content:"\f903"}.ti-droplet-pin:before{content:"\f904"}.ti-droplet-plus:before{content:"\f905"}.ti-droplet-question:before{content:"\f906"}.ti-droplet-search:before{content:"\f907"}.ti-droplet-share:before{content:"\f908"}.ti-droplet-star:before{content:"\f909"}.ti-droplet-up:before{content:"\f90a"}.ti-droplet-x:before{content:"\f90b"}.ti-e-passport:before{content:"\f4df"}.ti-ear:before{content:"\ebce"}.ti-ear-off:before{content:"\ee84"}.ti-ease-in:before{content:"\f573"}.ti-ease-in-control-point:before{content:"\f570"}.ti-ease-in-out:before{content:"\f572"}.ti-ease-in-out-control-points:before{content:"\f571"}.ti-ease-out:before{content:"\f575"}.ti-ease-out-control-point:before{content:"\f574"}.ti-edit:before{content:"\ea98"}.ti-edit-circle:before{content:"\ee85"}.ti-edit-circle-off:before{content:"\f11d"}.ti-edit-off:before{content:"\f11e"}.ti-egg:before{content:"\eb8a"}.ti-egg-cracked:before{content:"\f2d6"}.ti-egg-filled:before{content:"\f678"}.ti-egg-fried:before{content:"\f386"}.ti-egg-off:before{content:"\f11f"}.ti-eggs:before{content:"\f500"}.ti-elevator:before{content:"\efdf"}.ti-elevator-off:before{content:"\f3e8"}.ti-emergency-bed:before{content:"\ef5d"}.ti-empathize:before{content:"\f29b"}.ti-empathize-off:before{content:"\f3e9"}.ti-emphasis:before{content:"\ebcf"}.ti-engine:before{content:"\ef7e"}.ti-engine-off:before{content:"\f120"}.ti-equal:before{content:"\ee87"}.ti-equal-double:before{content:"\f4e1"}.ti-equal-not:before{content:"\ee86"}.ti-eraser:before{content:"\eb8b"}.ti-eraser-off:before{content:"\f121"}.ti-error-404:before{content:"\f027"}.ti-error-404-off:before{content:"\f122"}.ti-exchange:before{content:"\ebe7"}.ti-exchange-off:before{content:"\f123"}.ti-exclamation-circle:before{content:"\f634"}.ti-exclamation-mark:before{content:"\efb4"}.ti-exclamation-mark-off:before{content:"\f124"}.ti-explicit:before{content:"\f256"}.ti-explicit-off:before{content:"\f3ea"}.ti-exposure:before{content:"\eb8c"}.ti-exposure-0:before{content:"\f29c"}.ti-exposure-minus-1:before{content:"\f29d"}.ti-exposure-minus-2:before{content:"\f29e"}.ti-exposure-off:before{content:"\f3eb"}.ti-exposure-plus-1:before{content:"\f29f"}.ti-exposure-plus-2:before{content:"\f2a0"}.ti-external-link:before{content:"\ea99"}.ti-external-link-off:before{content:"\f125"}.ti-eye:before{content:"\ea9a"}.ti-eye-check:before{content:"\ee88"}.ti-eye-closed:before{content:"\f7ec"}.ti-eye-cog:before{content:"\f7ed"}.ti-eye-edit:before{content:"\f7ee"}.ti-eye-exclamation:before{content:"\f7ef"}.ti-eye-filled:before{content:"\f679"}.ti-eye-heart:before{content:"\f7f0"}.ti-eye-off:before{content:"\ecf0"}.ti-eye-table:before{content:"\ef5e"}.ti-eye-x:before{content:"\f7f1"}.ti-eyeglass:before{content:"\ee8a"}.ti-eyeglass-2:before{content:"\ee89"}.ti-eyeglass-off:before{content:"\f126"}.ti-face-id:before{content:"\ea9b"}.ti-face-id-error:before{content:"\efa7"}.ti-face-mask:before{content:"\efb5"}.ti-face-mask-off:before{content:"\f127"}.ti-fall:before{content:"\ecb9"}.ti-feather:before{content:"\ee8b"}.ti-feather-off:before{content:"\f128"}.ti-fence:before{content:"\ef2a"}.ti-fence-off:before{content:"\f129"}.ti-fidget-spinner:before{content:"\f068"}.ti-file:before{content:"\eaa4"}.ti-file-3d:before{content:"\f032"}.ti-file-alert:before{content:"\ede6"}.ti-file-analytics:before{content:"\ede7"}.ti-file-arrow-left:before{content:"\f033"}.ti-file-arrow-right:before{content:"\f034"}.ti-file-barcode:before{content:"\f035"}.ti-file-broken:before{content:"\f501"}.ti-file-certificate:before{content:"\ed4d"}.ti-file-chart:before{content:"\f036"}.ti-file-check:before{content:"\ea9c"}.ti-file-code:before{content:"\ebd0"}.ti-file-code-2:before{content:"\ede8"}.ti-file-database:before{content:"\f037"}.ti-file-delta:before{content:"\f53d"}.ti-file-description:before{content:"\f028"}.ti-file-diff:before{content:"\ecf1"}.ti-file-digit:before{content:"\efa8"}.ti-file-dislike:before{content:"\ed2a"}.ti-file-dollar:before{content:"\efe0"}.ti-file-dots:before{content:"\f038"}.ti-file-download:before{content:"\ea9d"}.ti-file-euro:before{content:"\efe1"}.ti-file-export:before{content:"\ede9"}.ti-file-filled:before{content:"\f747"}.ti-file-function:before{content:"\f53e"}.ti-file-horizontal:before{content:"\ebb0"}.ti-file-import:before{content:"\edea"}.ti-file-infinity:before{content:"\f502"}.ti-file-info:before{content:"\edec"}.ti-file-invoice:before{content:"\eb67"}.ti-file-lambda:before{content:"\f53f"}.ti-file-like:before{content:"\ed2b"}.ti-file-minus:before{content:"\ea9e"}.ti-file-music:before{content:"\ea9f"}.ti-file-off:before{content:"\ecf2"}.ti-file-orientation:before{content:"\f2a1"}.ti-file-pencil:before{content:"\f039"}.ti-file-percent:before{content:"\f540"}.ti-file-phone:before{content:"\ecdc"}.ti-file-plus:before{content:"\eaa0"}.ti-file-power:before{content:"\f03a"}.ti-file-report:before{content:"\eded"}.ti-file-rss:before{content:"\f03b"}.ti-file-scissors:before{content:"\f03c"}.ti-file-search:before{content:"\ed5d"}.ti-file-settings:before{content:"\f029"}.ti-file-shredder:before{content:"\eaa1"}.ti-file-signal:before{content:"\f03d"}.ti-file-spreadsheet:before{content:"\f03e"}.ti-file-stack:before{content:"\f503"}.ti-file-star:before{content:"\f03f"}.ti-file-symlink:before{content:"\ed53"}.ti-file-text:before{content:"\eaa2"}.ti-file-time:before{content:"\f040"}.ti-file-typography:before{content:"\f041"}.ti-file-unknown:before{content:"\f042"}.ti-file-upload:before{content:"\ec91"}.ti-file-vector:before{content:"\f043"}.ti-file-x:before{content:"\eaa3"}.ti-file-x-filled:before{content:"\f748"}.ti-file-zip:before{content:"\ed4e"}.ti-files:before{content:"\edef"}.ti-files-off:before{content:"\edee"}.ti-filter:before{content:"\eaa5"}.ti-filter-off:before{content:"\ed2c"}.ti-filters:before{content:"\f793"}.ti-fingerprint:before{content:"\ebd1"}.ti-fingerprint-off:before{content:"\f12a"}.ti-fire-hydrant:before{content:"\f3a9"}.ti-fire-hydrant-off:before{content:"\f3ec"}.ti-firetruck:before{content:"\ebe8"}.ti-first-aid-kit:before{content:"\ef5f"}.ti-first-aid-kit-off:before{content:"\f3ed"}.ti-fish:before{content:"\ef2b"}.ti-fish-bone:before{content:"\f287"}.ti-fish-christianity:before{content:"\f58b"}.ti-fish-hook:before{content:"\f1f9"}.ti-fish-hook-off:before{content:"\f3ee"}.ti-fish-off:before{content:"\f12b"}.ti-flag:before{content:"\eaa6"}.ti-flag-2:before{content:"\ee8c"}.ti-flag-2-filled:before{content:"\f707"}.ti-flag-2-off:before{content:"\f12c"}.ti-flag-3:before{content:"\ee8d"}.ti-flag-3-filled:before{content:"\f708"}.ti-flag-filled:before{content:"\f67a"}.ti-flag-off:before{content:"\f12d"}.ti-flame:before{content:"\ec2c"}.ti-flame-off:before{content:"\f12e"}.ti-flare:before{content:"\ee8e"}.ti-flask:before{content:"\ebd2"}.ti-flask-2:before{content:"\ef60"}.ti-flask-2-off:before{content:"\f12f"}.ti-flask-off:before{content:"\f130"}.ti-flip-flops:before{content:"\f564"}.ti-flip-horizontal:before{content:"\eaa7"}.ti-flip-vertical:before{content:"\eaa8"}.ti-float-center:before{content:"\ebb1"}.ti-float-left:before{content:"\ebb2"}.ti-float-none:before{content:"\ed13"}.ti-float-right:before{content:"\ebb3"}.ti-flower:before{content:"\eff6"}.ti-flower-off:before{content:"\f131"}.ti-focus:before{content:"\eb8d"}.ti-focus-2:before{content:"\ebd3"}.ti-focus-centered:before{content:"\f02a"}.ti-fold:before{content:"\ed56"}.ti-fold-down:before{content:"\ed54"}.ti-fold-up:before{content:"\ed55"}.ti-folder:before{content:"\eaad"}.ti-folder-bolt:before{content:"\f90c"}.ti-folder-cancel:before{content:"\f90d"}.ti-folder-check:before{content:"\f90e"}.ti-folder-code:before{content:"\f90f"}.ti-folder-cog:before{content:"\f910"}.ti-folder-dollar:before{content:"\f911"}.ti-folder-down:before{content:"\f912"}.ti-folder-exclamation:before{content:"\f913"}.ti-folder-filled:before{content:"\f749"}.ti-folder-heart:before{content:"\f914"}.ti-folder-minus:before{content:"\eaaa"}.ti-folder-off:before{content:"\ed14"}.ti-folder-pause:before{content:"\f915"}.ti-folder-pin:before{content:"\f916"}.ti-folder-plus:before{content:"\eaab"}.ti-folder-question:before{content:"\f917"}.ti-folder-search:before{content:"\f918"}.ti-folder-share:before{content:"\f919"}.ti-folder-star:before{content:"\f91a"}.ti-folder-symlink:before{content:"\f91b"}.ti-folder-up:before{content:"\f91c"}.ti-folder-x:before{content:"\eaac"}.ti-folders:before{content:"\eaae"}.ti-folders-off:before{content:"\f133"}.ti-forbid:before{content:"\ebd5"}.ti-forbid-2:before{content:"\ebd4"}.ti-forklift:before{content:"\ebe9"}.ti-forms:before{content:"\ee8f"}.ti-fountain:before{content:"\f09b"}.ti-fountain-off:before{content:"\f134"}.ti-frame:before{content:"\eaaf"}.ti-frame-off:before{content:"\f135"}.ti-free-rights:before{content:"\efb6"}.ti-fridge:before{content:"\f1fa"}.ti-fridge-off:before{content:"\f3ef"}.ti-friends:before{content:"\eab0"}.ti-friends-off:before{content:"\f136"}.ti-function:before{content:"\f225"}.ti-function-off:before{content:"\f3f0"}.ti-garden-cart:before{content:"\f23e"}.ti-garden-cart-off:before{content:"\f3f1"}.ti-gas-station:before{content:"\ec7d"}.ti-gas-station-off:before{content:"\f137"}.ti-gauge:before{content:"\eab1"}.ti-gauge-off:before{content:"\f138"}.ti-gavel:before{content:"\ef90"}.ti-gender-agender:before{content:"\f0e1"}.ti-gender-androgyne:before{content:"\f0e2"}.ti-gender-bigender:before{content:"\f0e3"}.ti-gender-demiboy:before{content:"\f0e4"}.ti-gender-demigirl:before{content:"\f0e5"}.ti-gender-epicene:before{content:"\f0e6"}.ti-gender-female:before{content:"\f0e7"}.ti-gender-femme:before{content:"\f0e8"}.ti-gender-genderfluid:before{content:"\f0e9"}.ti-gender-genderless:before{content:"\f0ea"}.ti-gender-genderqueer:before{content:"\f0eb"}.ti-gender-hermaphrodite:before{content:"\f0ec"}.ti-gender-intergender:before{content:"\f0ed"}.ti-gender-male:before{content:"\f0ee"}.ti-gender-neutrois:before{content:"\f0ef"}.ti-gender-third:before{content:"\f0f0"}.ti-gender-transgender:before{content:"\f0f1"}.ti-gender-trasvesti:before{content:"\f0f2"}.ti-geometry:before{content:"\ee90"}.ti-ghost:before{content:"\eb8e"}.ti-ghost-2:before{content:"\f57c"}.ti-ghost-2-filled:before{content:"\f74a"}.ti-ghost-filled:before{content:"\f74b"}.ti-ghost-off:before{content:"\f3f2"}.ti-gif:before{content:"\f257"}.ti-gift:before{content:"\eb68"}.ti-gift-card:before{content:"\f3aa"}.ti-gift-off:before{content:"\f3f3"}.ti-git-branch:before{content:"\eab2"}.ti-git-branch-deleted:before{content:"\f57d"}.ti-git-cherry-pick:before{content:"\f57e"}.ti-git-commit:before{content:"\eab3"}.ti-git-compare:before{content:"\eab4"}.ti-git-fork:before{content:"\eb8f"}.ti-git-merge:before{content:"\eab5"}.ti-git-pull-request:before{content:"\eab6"}.ti-git-pull-request-closed:before{content:"\ef7f"}.ti-git-pull-request-draft:before{content:"\efb7"}.ti-gizmo:before{content:"\f02b"}.ti-glass:before{content:"\eab8"}.ti-glass-full:before{content:"\eab7"}.ti-glass-off:before{content:"\ee91"}.ti-globe:before{content:"\eab9"}.ti-globe-off:before{content:"\f139"}.ti-go-game:before{content:"\f512"}.ti-golf:before{content:"\ed8c"}.ti-golf-off:before{content:"\f13a"}.ti-gps:before{content:"\ed7a"}.ti-gradienter:before{content:"\f3ab"}.ti-grain:before{content:"\ee92"}.ti-graph:before{content:"\f288"}.ti-graph-off:before{content:"\f3f4"}.ti-grave:before{content:"\f580"}.ti-grave-2:before{content:"\f57f"}.ti-grid-dots:before{content:"\eaba"}.ti-grid-pattern:before{content:"\efc9"}.ti-grill:before{content:"\efa9"}.ti-grill-fork:before{content:"\f35b"}.ti-grill-off:before{content:"\f3f5"}.ti-grill-spatula:before{content:"\f35c"}.ti-grip-horizontal:before{content:"\ec00"}.ti-grip-vertical:before{content:"\ec01"}.ti-growth:before{content:"\ee93"}.ti-guitar-pick:before{content:"\f4c6"}.ti-guitar-pick-filled:before{content:"\f67b"}.ti-h-1:before{content:"\ec94"}.ti-h-2:before{content:"\ec95"}.ti-h-3:before{content:"\ec96"}.ti-h-4:before{content:"\ec97"}.ti-h-5:before{content:"\ec98"}.ti-h-6:before{content:"\ec99"}.ti-hammer:before{content:"\ef91"}.ti-hammer-off:before{content:"\f13c"}.ti-hand-click:before{content:"\ef4f"}.ti-hand-finger:before{content:"\ee94"}.ti-hand-finger-off:before{content:"\f13d"}.ti-hand-grab:before{content:"\f091"}.ti-hand-little-finger:before{content:"\ee95"}.ti-hand-middle-finger:before{content:"\ec2d"}.ti-hand-move:before{content:"\ef50"}.ti-hand-off:before{content:"\ed15"}.ti-hand-ring-finger:before{content:"\ee96"}.ti-hand-rock:before{content:"\ee97"}.ti-hand-sanitizer:before{content:"\f5f4"}.ti-hand-stop:before{content:"\ec2e"}.ti-hand-three-fingers:before{content:"\ee98"}.ti-hand-two-fingers:before{content:"\ee99"}.ti-hanger:before{content:"\ee9a"}.ti-hanger-2:before{content:"\f09c"}.ti-hanger-off:before{content:"\f13e"}.ti-hash:before{content:"\eabc"}.ti-haze:before{content:"\efaa"}.ti-heading:before{content:"\ee9b"}.ti-heading-off:before{content:"\f13f"}.ti-headphones:before{content:"\eabd"}.ti-headphones-off:before{content:"\ed1d"}.ti-headset:before{content:"\eb90"}.ti-headset-off:before{content:"\f3f6"}.ti-health-recognition:before{content:"\f1fb"}.ti-heart:before{content:"\eabe"}.ti-heart-broken:before{content:"\ecba"}.ti-heart-filled:before{content:"\f67c"}.ti-heart-handshake:before{content:"\f0f3"}.ti-heart-minus:before{content:"\f140"}.ti-heart-off:before{content:"\f141"}.ti-heart-plus:before{content:"\f142"}.ti-heart-rate-monitor:before{content:"\ef61"}.ti-heartbeat:before{content:"\ef92"}.ti-hearts:before{content:"\f387"}.ti-hearts-off:before{content:"\f3f7"}.ti-helicopter:before{content:"\ed8e"}.ti-helicopter-landing:before{content:"\ed8d"}.ti-helmet:before{content:"\efca"}.ti-helmet-off:before{content:"\f143"}.ti-help:before{content:"\eabf"}.ti-help-circle:before{content:"\f91d"}.ti-help-hexagon:before{content:"\f7a8"}.ti-help-octagon:before{content:"\f7a9"}.ti-help-off:before{content:"\f3f8"}.ti-help-small:before{content:"\f91e"}.ti-help-square:before{content:"\f920"}.ti-help-square-rounded:before{content:"\f91f"}.ti-help-triangle:before{content:"\f921"}.ti-hexagon:before{content:"\ec02"}.ti-hexagon-0-filled:before{content:"\f74c"}.ti-hexagon-1-filled:before{content:"\f74d"}.ti-hexagon-2-filled:before{content:"\f74e"}.ti-hexagon-3-filled:before{content:"\f74f"}.ti-hexagon-3d:before{content:"\f4c7"}.ti-hexagon-4-filled:before{content:"\f750"}.ti-hexagon-5-filled:before{content:"\f751"}.ti-hexagon-6-filled:before{content:"\f752"}.ti-hexagon-7-filled:before{content:"\f753"}.ti-hexagon-8-filled:before{content:"\f754"}.ti-hexagon-9-filled:before{content:"\f755"}.ti-hexagon-filled:before{content:"\f67d"}.ti-hexagon-letter-a:before{content:"\f463"}.ti-hexagon-letter-b:before{content:"\f464"}.ti-hexagon-letter-c:before{content:"\f465"}.ti-hexagon-letter-d:before{content:"\f466"}.ti-hexagon-letter-e:before{content:"\f467"}.ti-hexagon-letter-f:before{content:"\f468"}.ti-hexagon-letter-g:before{content:"\f469"}.ti-hexagon-letter-h:before{content:"\f46a"}.ti-hexagon-letter-i:before{content:"\f46b"}.ti-hexagon-letter-j:before{content:"\f46c"}.ti-hexagon-letter-k:before{content:"\f46d"}.ti-hexagon-letter-l:before{content:"\f46e"}.ti-hexagon-letter-m:before{content:"\f46f"}.ti-hexagon-letter-n:before{content:"\f470"}.ti-hexagon-letter-o:before{content:"\f471"}.ti-hexagon-letter-p:before{content:"\f472"}.ti-hexagon-letter-q:before{content:"\f473"}.ti-hexagon-letter-r:before{content:"\f474"}.ti-hexagon-letter-s:before{content:"\f475"}.ti-hexagon-letter-t:before{content:"\f476"}.ti-hexagon-letter-u:before{content:"\f477"}.ti-hexagon-letter-v:before{content:"\f4b3"}.ti-hexagon-letter-w:before{content:"\f478"}.ti-hexagon-letter-x:before{content:"\f479"}.ti-hexagon-letter-y:before{content:"\f47a"}.ti-hexagon-letter-z:before{content:"\f47b"}.ti-hexagon-number-0:before{content:"\f459"}.ti-hexagon-number-1:before{content:"\f45a"}.ti-hexagon-number-2:before{content:"\f45b"}.ti-hexagon-number-3:before{content:"\f45c"}.ti-hexagon-number-4:before{content:"\f45d"}.ti-hexagon-number-5:before{content:"\f45e"}.ti-hexagon-number-6:before{content:"\f45f"}.ti-hexagon-number-7:before{content:"\f460"}.ti-hexagon-number-8:before{content:"\f461"}.ti-hexagon-number-9:before{content:"\f462"}.ti-hexagon-off:before{content:"\ee9c"}.ti-hexagons:before{content:"\f09d"}.ti-hexagons-off:before{content:"\f3f9"}.ti-hierarchy:before{content:"\ee9e"}.ti-hierarchy-2:before{content:"\ee9d"}.ti-hierarchy-3:before{content:"\f289"}.ti-hierarchy-off:before{content:"\f3fa"}.ti-highlight:before{content:"\ef3f"}.ti-highlight-off:before{content:"\f144"}.ti-history:before{content:"\ebea"}.ti-history-off:before{content:"\f3fb"}.ti-history-toggle:before{content:"\f1fc"}.ti-home:before{content:"\eac1"}.ti-home-2:before{content:"\eac0"}.ti-home-bolt:before{content:"\f336"}.ti-home-cancel:before{content:"\f350"}.ti-home-check:before{content:"\f337"}.ti-home-cog:before{content:"\f338"}.ti-home-dollar:before{content:"\f339"}.ti-home-dot:before{content:"\f33a"}.ti-home-down:before{content:"\f33b"}.ti-home-eco:before{content:"\f351"}.ti-home-edit:before{content:"\f352"}.ti-home-exclamation:before{content:"\f33c"}.ti-home-hand:before{content:"\f504"}.ti-home-heart:before{content:"\f353"}.ti-home-infinity:before{content:"\f505"}.ti-home-link:before{content:"\f354"}.ti-home-minus:before{content:"\f33d"}.ti-home-move:before{content:"\f33e"}.ti-home-off:before{content:"\f145"}.ti-home-plus:before{content:"\f33f"}.ti-home-question:before{content:"\f340"}.ti-home-ribbon:before{content:"\f355"}.ti-home-search:before{content:"\f341"}.ti-home-share:before{content:"\f342"}.ti-home-shield:before{content:"\f343"}.ti-home-signal:before{content:"\f356"}.ti-home-star:before{content:"\f344"}.ti-home-stats:before{content:"\f345"}.ti-home-up:before{content:"\f346"}.ti-home-x:before{content:"\f347"}.ti-horse-toy:before{content:"\f28a"}.ti-hotel-service:before{content:"\ef80"}.ti-hourglass:before{content:"\ef93"}.ti-hourglass-empty:before{content:"\f146"}.ti-hourglass-filled:before{content:"\f756"}.ti-hourglass-high:before{content:"\f092"}.ti-hourglass-low:before{content:"\f093"}.ti-hourglass-off:before{content:"\f147"}.ti-html:before{content:"\f7b1"}.ti-ice-cream:before{content:"\eac2"}.ti-ice-cream-2:before{content:"\ee9f"}.ti-ice-cream-off:before{content:"\f148"}.ti-ice-skating:before{content:"\efcb"}.ti-icons:before{content:"\f1d4"}.ti-icons-off:before{content:"\f3fc"}.ti-id:before{content:"\eac3"}.ti-id-badge:before{content:"\eff7"}.ti-id-badge-2:before{content:"\f076"}.ti-id-badge-off:before{content:"\f3fd"}.ti-id-off:before{content:"\f149"}.ti-inbox:before{content:"\eac4"}.ti-inbox-off:before{content:"\f14a"}.ti-indent-decrease:before{content:"\eb91"}.ti-indent-increase:before{content:"\eb92"}.ti-infinity:before{content:"\eb69"}.ti-infinity-off:before{content:"\f3fe"}.ti-info-circle:before{content:"\eac5"}.ti-info-circle-filled:before{content:"\f6d8"}.ti-info-hexagon:before{content:"\f7aa"}.ti-info-octagon:before{content:"\f7ab"}.ti-info-small:before{content:"\f922"}.ti-info-square:before{content:"\eac6"}.ti-info-square-rounded:before{content:"\f635"}.ti-info-square-rounded-filled:before{content:"\f6d9"}.ti-info-triangle:before{content:"\f923"}.ti-inner-shadow-bottom:before{content:"\f520"}.ti-inner-shadow-bottom-filled:before{content:"\f757"}.ti-inner-shadow-bottom-left:before{content:"\f51e"}.ti-inner-shadow-bottom-left-filled:before{content:"\f758"}.ti-inner-shadow-bottom-right:before{content:"\f51f"}.ti-inner-shadow-bottom-right-filled:before{content:"\f759"}.ti-inner-shadow-left:before{content:"\f521"}.ti-inner-shadow-left-filled:before{content:"\f75a"}.ti-inner-shadow-right:before{content:"\f522"}.ti-inner-shadow-right-filled:before{content:"\f75b"}.ti-inner-shadow-top:before{content:"\f525"}.ti-inner-shadow-top-filled:before{content:"\f75c"}.ti-inner-shadow-top-left:before{content:"\f523"}.ti-inner-shadow-top-left-filled:before{content:"\f75d"}.ti-inner-shadow-top-right:before{content:"\f524"}.ti-inner-shadow-top-right-filled:before{content:"\f75e"}.ti-input-search:before{content:"\f2a2"}.ti-ironing-1:before{content:"\f2f4"}.ti-ironing-2:before{content:"\f2f5"}.ti-ironing-3:before{content:"\f2f6"}.ti-ironing-off:before{content:"\f2f7"}.ti-ironing-steam:before{content:"\f2f9"}.ti-ironing-steam-off:before{content:"\f2f8"}.ti-italic:before{content:"\eb93"}.ti-jacket:before{content:"\f661"}.ti-jetpack:before{content:"\f581"}.ti-jewish-star:before{content:"\f3ff"}.ti-jewish-star-filled:before{content:"\f67e"}.ti-jpg:before{content:"\f3ac"}.ti-json:before{content:"\f7b2"}.ti-jump-rope:before{content:"\ed8f"}.ti-karate:before{content:"\ed32"}.ti-kayak:before{content:"\f1d6"}.ti-kering:before{content:"\efb8"}.ti-key:before{content:"\eac7"}.ti-key-off:before{content:"\f14b"}.ti-keyboard:before{content:"\ebd6"}.ti-keyboard-hide:before{content:"\ec7e"}.ti-keyboard-off:before{content:"\eea0"}.ti-keyboard-show:before{content:"\ec7f"}.ti-keyframe:before{content:"\f576"}.ti-keyframe-align-center:before{content:"\f582"}.ti-keyframe-align-horizontal:before{content:"\f583"}.ti-keyframe-align-vertical:before{content:"\f584"}.ti-keyframes:before{content:"\f585"}.ti-ladder:before{content:"\efe2"}.ti-ladder-off:before{content:"\f14c"}.ti-lambda:before{content:"\f541"}.ti-lamp:before{content:"\efab"}.ti-lamp-2:before{content:"\f09e"}.ti-lamp-off:before{content:"\f14d"}.ti-language:before{content:"\ebbe"}.ti-language-hiragana:before{content:"\ef77"}.ti-language-katakana:before{content:"\ef78"}.ti-language-off:before{content:"\f14e"}.ti-lasso:before{content:"\efac"}.ti-lasso-off:before{content:"\f14f"}.ti-lasso-polygon:before{content:"\f388"}.ti-layers-difference:before{content:"\eac8"}.ti-layers-intersect:before{content:"\eac9"}.ti-layers-intersect-2:before{content:"\eff8"}.ti-layers-linked:before{content:"\eea1"}.ti-layers-off:before{content:"\f150"}.ti-layers-subtract:before{content:"\eaca"}.ti-layers-union:before{content:"\eacb"}.ti-layout:before{content:"\eadb"}.ti-layout-2:before{content:"\eacc"}.ti-layout-align-bottom:before{content:"\eacd"}.ti-layout-align-center:before{content:"\eace"}.ti-layout-align-left:before{content:"\eacf"}.ti-layout-align-middle:before{content:"\ead0"}.ti-layout-align-right:before{content:"\ead1"}.ti-layout-align-top:before{content:"\ead2"}.ti-layout-board:before{content:"\ef95"}.ti-layout-board-split:before{content:"\ef94"}.ti-layout-bottombar:before{content:"\ead3"}.ti-layout-bottombar-collapse:before{content:"\f28b"}.ti-layout-bottombar-expand:before{content:"\f28c"}.ti-layout-cards:before{content:"\ec13"}.ti-layout-collage:before{content:"\f389"}.ti-layout-columns:before{content:"\ead4"}.ti-layout-dashboard:before{content:"\f02c"}.ti-layout-distribute-horizontal:before{content:"\ead5"}.ti-layout-distribute-vertical:before{content:"\ead6"}.ti-layout-grid:before{content:"\edba"}.ti-layout-grid-add:before{content:"\edb9"}.ti-layout-kanban:before{content:"\ec3f"}.ti-layout-list:before{content:"\ec14"}.ti-layout-navbar:before{content:"\ead7"}.ti-layout-navbar-collapse:before{content:"\f28d"}.ti-layout-navbar-expand:before{content:"\f28e"}.ti-layout-off:before{content:"\f151"}.ti-layout-rows:before{content:"\ead8"}.ti-layout-sidebar:before{content:"\eada"}.ti-layout-sidebar-left-collapse:before{content:"\f004"}.ti-layout-sidebar-left-expand:before{content:"\f005"}.ti-layout-sidebar-right:before{content:"\ead9"}.ti-layout-sidebar-right-collapse:before{content:"\f006"}.ti-layout-sidebar-right-expand:before{content:"\f007"}.ti-leaf:before{content:"\ed4f"}.ti-leaf-off:before{content:"\f400"}.ti-lego:before{content:"\eadc"}.ti-lego-off:before{content:"\f401"}.ti-lemon:before{content:"\ef10"}.ti-lemon-2:before{content:"\ef81"}.ti-letter-a:before{content:"\ec50"}.ti-letter-b:before{content:"\ec51"}.ti-letter-c:before{content:"\ec52"}.ti-letter-case:before{content:"\eea5"}.ti-letter-case-lower:before{content:"\eea2"}.ti-letter-case-toggle:before{content:"\eea3"}.ti-letter-case-upper:before{content:"\eea4"}.ti-letter-d:before{content:"\ec53"}.ti-letter-e:before{content:"\ec54"}.ti-letter-f:before{content:"\ec55"}.ti-letter-g:before{content:"\ec56"}.ti-letter-h:before{content:"\ec57"}.ti-letter-i:before{content:"\ec58"}.ti-letter-j:before{content:"\ec59"}.ti-letter-k:before{content:"\ec5a"}.ti-letter-l:before{content:"\ec5b"}.ti-letter-m:before{content:"\ec5c"}.ti-letter-n:before{content:"\ec5d"}.ti-letter-o:before{content:"\ec5e"}.ti-letter-p:before{content:"\ec5f"}.ti-letter-q:before{content:"\ec60"}.ti-letter-r:before{content:"\ec61"}.ti-letter-s:before{content:"\ec62"}.ti-letter-spacing:before{content:"\eea6"}.ti-letter-t:before{content:"\ec63"}.ti-letter-u:before{content:"\ec64"}.ti-letter-v:before{content:"\ec65"}.ti-letter-w:before{content:"\ec66"}.ti-letter-x:before{content:"\ec67"}.ti-letter-y:before{content:"\ec68"}.ti-letter-z:before{content:"\ec69"}.ti-license:before{content:"\ebc0"}.ti-license-off:before{content:"\f153"}.ti-lifebuoy:before{content:"\eadd"}.ti-lifebuoy-off:before{content:"\f154"}.ti-lighter:before{content:"\f794"}.ti-line:before{content:"\ec40"}.ti-line-dashed:before{content:"\eea7"}.ti-line-dotted:before{content:"\eea8"}.ti-line-height:before{content:"\eb94"}.ti-link:before{content:"\eade"}.ti-link-off:before{content:"\f402"}.ti-list:before{content:"\eb6b"}.ti-list-check:before{content:"\eb6a"}.ti-list-details:before{content:"\ef40"}.ti-list-numbers:before{content:"\ef11"}.ti-list-search:before{content:"\eea9"}.ti-live-photo:before{content:"\eadf"}.ti-live-photo-off:before{content:"\f403"}.ti-live-view:before{content:"\ec6b"}.ti-loader:before{content:"\eca3"}.ti-loader-2:before{content:"\f226"}.ti-loader-3:before{content:"\f513"}.ti-loader-quarter:before{content:"\eca2"}.ti-location:before{content:"\eae0"}.ti-location-broken:before{content:"\f2c4"}.ti-location-filled:before{content:"\f67f"}.ti-location-off:before{content:"\f155"}.ti-lock:before{content:"\eae2"}.ti-lock-access:before{content:"\eeaa"}.ti-lock-access-off:before{content:"\f404"}.ti-lock-bolt:before{content:"\f924"}.ti-lock-cancel:before{content:"\f925"}.ti-lock-check:before{content:"\f926"}.ti-lock-code:before{content:"\f927"}.ti-lock-cog:before{content:"\f928"}.ti-lock-dollar:before{content:"\f929"}.ti-lock-down:before{content:"\f92a"}.ti-lock-exclamation:before{content:"\f92b"}.ti-lock-heart:before{content:"\f92c"}.ti-lock-minus:before{content:"\f92d"}.ti-lock-off:before{content:"\ed1e"}.ti-lock-open:before{content:"\eae1"}.ti-lock-open-off:before{content:"\f156"}.ti-lock-pause:before{content:"\f92e"}.ti-lock-pin:before{content:"\f92f"}.ti-lock-plus:before{content:"\f930"}.ti-lock-question:before{content:"\f931"}.ti-lock-search:before{content:"\f932"}.ti-lock-share:before{content:"\f933"}.ti-lock-square:before{content:"\ef51"}.ti-lock-square-rounded:before{content:"\f636"}.ti-lock-square-rounded-filled:before{content:"\f6da"}.ti-lock-star:before{content:"\f934"}.ti-lock-up:before{content:"\f935"}.ti-lock-x:before{content:"\f936"}.ti-logic-and:before{content:"\f240"}.ti-logic-buffer:before{content:"\f241"}.ti-logic-nand:before{content:"\f242"}.ti-logic-nor:before{content:"\f243"}.ti-logic-not:before{content:"\f244"}.ti-logic-or:before{content:"\f245"}.ti-logic-xnor:before{content:"\f246"}.ti-logic-xor:before{content:"\f247"}.ti-login:before{content:"\eba7"}.ti-logout:before{content:"\eba8"}.ti-lollipop:before{content:"\efcc"}.ti-lollipop-off:before{content:"\f157"}.ti-luggage:before{content:"\efad"}.ti-luggage-off:before{content:"\f158"}.ti-lungs:before{content:"\ef62"}.ti-lungs-off:before{content:"\f405"}.ti-macro:before{content:"\eeab"}.ti-macro-off:before{content:"\f406"}.ti-magnet:before{content:"\eae3"}.ti-magnet-off:before{content:"\f159"}.ti-mail:before{content:"\eae5"}.ti-mail-bolt:before{content:"\f937"}.ti-mail-cancel:before{content:"\f938"}.ti-mail-check:before{content:"\f939"}.ti-mail-code:before{content:"\f93a"}.ti-mail-cog:before{content:"\f93b"}.ti-mail-dollar:before{content:"\f93c"}.ti-mail-down:before{content:"\f93d"}.ti-mail-exclamation:before{content:"\f93e"}.ti-mail-fast:before{content:"\f069"}.ti-mail-forward:before{content:"\eeac"}.ti-mail-heart:before{content:"\f93f"}.ti-mail-minus:before{content:"\f940"}.ti-mail-off:before{content:"\f15a"}.ti-mail-opened:before{content:"\eae4"}.ti-mail-pause:before{content:"\f941"}.ti-mail-pin:before{content:"\f942"}.ti-mail-plus:before{content:"\f943"}.ti-mail-question:before{content:"\f944"}.ti-mail-search:before{content:"\f945"}.ti-mail-share:before{content:"\f946"}.ti-mail-star:before{content:"\f947"}.ti-mail-up:before{content:"\f948"}.ti-mail-x:before{content:"\f949"}.ti-mailbox:before{content:"\eead"}.ti-mailbox-off:before{content:"\f15b"}.ti-man:before{content:"\eae6"}.ti-manual-gearbox:before{content:"\ed7b"}.ti-map:before{content:"\eae9"}.ti-map-2:before{content:"\eae7"}.ti-map-off:before{content:"\f15c"}.ti-map-pin:before{content:"\eae8"}.ti-map-pin-bolt:before{content:"\f94a"}.ti-map-pin-cancel:before{content:"\f94b"}.ti-map-pin-check:before{content:"\f94c"}.ti-map-pin-code:before{content:"\f94d"}.ti-map-pin-cog:before{content:"\f94e"}.ti-map-pin-dollar:before{content:"\f94f"}.ti-map-pin-down:before{content:"\f950"}.ti-map-pin-exclamation:before{content:"\f951"}.ti-map-pin-filled:before{content:"\f680"}.ti-map-pin-heart:before{content:"\f952"}.ti-map-pin-minus:before{content:"\f953"}.ti-map-pin-off:before{content:"\ecf3"}.ti-map-pin-pause:before{content:"\f954"}.ti-map-pin-pin:before{content:"\f955"}.ti-map-pin-plus:before{content:"\f956"}.ti-map-pin-question:before{content:"\f957"}.ti-map-pin-search:before{content:"\f958"}.ti-map-pin-share:before{content:"\f795"}.ti-map-pin-star:before{content:"\f959"}.ti-map-pin-up:before{content:"\f95a"}.ti-map-pin-x:before{content:"\f95b"}.ti-map-pins:before{content:"\ed5e"}.ti-map-search:before{content:"\ef82"}.ti-markdown:before{content:"\ec41"}.ti-markdown-off:before{content:"\f407"}.ti-marquee:before{content:"\ec77"}.ti-marquee-2:before{content:"\eeae"}.ti-marquee-off:before{content:"\f15d"}.ti-mars:before{content:"\ec80"}.ti-mask:before{content:"\eeb0"}.ti-mask-off:before{content:"\eeaf"}.ti-masks-theater:before{content:"\f263"}.ti-masks-theater-off:before{content:"\f408"}.ti-massage:before{content:"\eeb1"}.ti-matchstick:before{content:"\f577"}.ti-math:before{content:"\ebeb"}.ti-math-1-divide-2:before{content:"\f4e2"}.ti-math-1-divide-3:before{content:"\f4e3"}.ti-math-avg:before{content:"\f0f4"}.ti-math-equal-greater:before{content:"\f4e4"}.ti-math-equal-lower:before{content:"\f4e5"}.ti-math-function:before{content:"\eeb2"}.ti-math-function-off:before{content:"\f15e"}.ti-math-function-y:before{content:"\f4e6"}.ti-math-greater:before{content:"\f4e7"}.ti-math-integral:before{content:"\f4e9"}.ti-math-integral-x:before{content:"\f4e8"}.ti-math-integrals:before{content:"\f4ea"}.ti-math-lower:before{content:"\f4eb"}.ti-math-max:before{content:"\f0f5"}.ti-math-min:before{content:"\f0f6"}.ti-math-not:before{content:"\f4ec"}.ti-math-off:before{content:"\f409"}.ti-math-pi:before{content:"\f4ee"}.ti-math-pi-divide-2:before{content:"\f4ed"}.ti-math-symbols:before{content:"\eeb3"}.ti-math-x-divide-2:before{content:"\f4ef"}.ti-math-x-divide-y:before{content:"\f4f1"}.ti-math-x-divide-y-2:before{content:"\f4f0"}.ti-math-x-minus-x:before{content:"\f4f2"}.ti-math-x-minus-y:before{content:"\f4f3"}.ti-math-x-plus-x:before{content:"\f4f4"}.ti-math-x-plus-y:before{content:"\f4f5"}.ti-math-xy:before{content:"\f4f6"}.ti-math-y-minus-y:before{content:"\f4f7"}.ti-math-y-plus-y:before{content:"\f4f8"}.ti-maximize:before{content:"\eaea"}.ti-maximize-off:before{content:"\f15f"}.ti-meat:before{content:"\ef12"}.ti-meat-off:before{content:"\f40a"}.ti-medal:before{content:"\ec78"}.ti-medal-2:before{content:"\efcd"}.ti-medical-cross:before{content:"\ec2f"}.ti-medical-cross-filled:before{content:"\f681"}.ti-medical-cross-off:before{content:"\f160"}.ti-medicine-syrup:before{content:"\ef63"}.ti-meeple:before{content:"\f514"}.ti-menorah:before{content:"\f58c"}.ti-menu:before{content:"\eaeb"}.ti-menu-2:before{content:"\ec42"}.ti-menu-order:before{content:"\f5f5"}.ti-message:before{content:"\eaef"}.ti-message-2:before{content:"\eaec"}.ti-message-2-bolt:before{content:"\f95c"}.ti-message-2-cancel:before{content:"\f95d"}.ti-message-2-check:before{content:"\f95e"}.ti-message-2-code:before{content:"\f012"}.ti-message-2-cog:before{content:"\f95f"}.ti-message-2-dollar:before{content:"\f960"}.ti-message-2-down:before{content:"\f961"}.ti-message-2-exclamation:before{content:"\f962"}.ti-message-2-heart:before{content:"\f963"}.ti-message-2-minus:before{content:"\f964"}.ti-message-2-off:before{content:"\f40b"}.ti-message-2-pause:before{content:"\f965"}.ti-message-2-pin:before{content:"\f966"}.ti-message-2-plus:before{content:"\f967"}.ti-message-2-question:before{content:"\f968"}.ti-message-2-search:before{content:"\f969"}.ti-message-2-share:before{content:"\f077"}.ti-message-2-star:before{content:"\f96a"}.ti-message-2-up:before{content:"\f96b"}.ti-message-2-x:before{content:"\f96c"}.ti-message-bolt:before{content:"\f96d"}.ti-message-cancel:before{content:"\f96e"}.ti-message-chatbot:before{content:"\f38a"}.ti-message-check:before{content:"\f96f"}.ti-message-circle:before{content:"\eaed"}.ti-message-circle-2:before{content:"\ed3f"}.ti-message-circle-2-filled:before{content:"\f682"}.ti-message-circle-bolt:before{content:"\f970"}.ti-message-circle-cancel:before{content:"\f971"}.ti-message-circle-check:before{content:"\f972"}.ti-message-circle-code:before{content:"\f973"}.ti-message-circle-cog:before{content:"\f974"}.ti-message-circle-dollar:before{content:"\f975"}.ti-message-circle-down:before{content:"\f976"}.ti-message-circle-exclamation:before{content:"\f977"}.ti-message-circle-heart:before{content:"\f978"}.ti-message-circle-minus:before{content:"\f979"}.ti-message-circle-off:before{content:"\ed40"}.ti-message-circle-pause:before{content:"\f97a"}.ti-message-circle-pin:before{content:"\f97b"}.ti-message-circle-plus:before{content:"\f97c"}.ti-message-circle-question:before{content:"\f97d"}.ti-message-circle-search:before{content:"\f97e"}.ti-message-circle-share:before{content:"\f97f"}.ti-message-circle-star:before{content:"\f980"}.ti-message-circle-up:before{content:"\f981"}.ti-message-circle-x:before{content:"\f982"}.ti-message-code:before{content:"\f013"}.ti-message-cog:before{content:"\f983"}.ti-message-dollar:before{content:"\f984"}.ti-message-dots:before{content:"\eaee"}.ti-message-down:before{content:"\f985"}.ti-message-exclamation:before{content:"\f986"}.ti-message-forward:before{content:"\f28f"}.ti-message-heart:before{content:"\f987"}.ti-message-language:before{content:"\efae"}.ti-message-minus:before{content:"\f988"}.ti-message-off:before{content:"\ed41"}.ti-message-pause:before{content:"\f989"}.ti-message-pin:before{content:"\f98a"}.ti-message-plus:before{content:"\ec9a"}.ti-message-question:before{content:"\f98b"}.ti-message-report:before{content:"\ec9b"}.ti-message-search:before{content:"\f98c"}.ti-message-share:before{content:"\f078"}.ti-message-star:before{content:"\f98d"}.ti-message-up:before{content:"\f98e"}.ti-message-x:before{content:"\f98f"}.ti-messages:before{content:"\eb6c"}.ti-messages-off:before{content:"\ed42"}.ti-meteor:before{content:"\f1fd"}.ti-meteor-off:before{content:"\f40c"}.ti-mickey:before{content:"\f2a3"}.ti-mickey-filled:before{content:"\f683"}.ti-microphone:before{content:"\eaf0"}.ti-microphone-2:before{content:"\ef2c"}.ti-microphone-2-off:before{content:"\f40d"}.ti-microphone-off:before{content:"\ed16"}.ti-microscope:before{content:"\ef64"}.ti-microscope-off:before{content:"\f40e"}.ti-microwave:before{content:"\f248"}.ti-microwave-off:before{content:"\f264"}.ti-military-award:before{content:"\f079"}.ti-military-rank:before{content:"\efcf"}.ti-milk:before{content:"\ef13"}.ti-milk-off:before{content:"\f40f"}.ti-milkshake:before{content:"\f4c8"}.ti-minimize:before{content:"\eaf1"}.ti-minus:before{content:"\eaf2"}.ti-minus-vertical:before{content:"\eeb4"}.ti-mist:before{content:"\ec30"}.ti-mist-off:before{content:"\f410"}.ti-mobiledata:before{content:"\f9f5"}.ti-mobiledata-off:before{content:"\f9f4"}.ti-moneybag:before{content:"\f506"}.ti-mood-angry:before{content:"\f2de"}.ti-mood-annoyed:before{content:"\f2e0"}.ti-mood-annoyed-2:before{content:"\f2df"}.ti-mood-boy:before{content:"\ed2d"}.ti-mood-check:before{content:"\f7b3"}.ti-mood-cog:before{content:"\f7b4"}.ti-mood-confuzed:before{content:"\eaf3"}.ti-mood-confuzed-filled:before{content:"\f7f2"}.ti-mood-crazy-happy:before{content:"\ed90"}.ti-mood-cry:before{content:"\ecbb"}.ti-mood-dollar:before{content:"\f7b5"}.ti-mood-empty:before{content:"\eeb5"}.ti-mood-empty-filled:before{content:"\f7f3"}.ti-mood-happy:before{content:"\eaf4"}.ti-mood-happy-filled:before{content:"\f7f4"}.ti-mood-heart:before{content:"\f7b6"}.ti-mood-kid:before{content:"\ec03"}.ti-mood-kid-filled:before{content:"\f7f5"}.ti-mood-look-left:before{content:"\f2c5"}.ti-mood-look-right:before{content:"\f2c6"}.ti-mood-minus:before{content:"\f7b7"}.ti-mood-nerd:before{content:"\f2e1"}.ti-mood-nervous:before{content:"\ef96"}.ti-mood-neutral:before{content:"\eaf5"}.ti-mood-neutral-filled:before{content:"\f7f6"}.ti-mood-off:before{content:"\f161"}.ti-mood-pin:before{content:"\f7b8"}.ti-mood-plus:before{content:"\f7b9"}.ti-mood-sad:before{content:"\eaf6"}.ti-mood-sad-2:before{content:"\f2e2"}.ti-mood-sad-dizzy:before{content:"\f2e3"}.ti-mood-sad-filled:before{content:"\f7f7"}.ti-mood-sad-squint:before{content:"\f2e4"}.ti-mood-search:before{content:"\f7ba"}.ti-mood-sick:before{content:"\f2e5"}.ti-mood-silence:before{content:"\f2e6"}.ti-mood-sing:before{content:"\f2c7"}.ti-mood-smile:before{content:"\eaf7"}.ti-mood-smile-beam:before{content:"\f2e7"}.ti-mood-smile-dizzy:before{content:"\f2e8"}.ti-mood-smile-filled:before{content:"\f7f8"}.ti-mood-suprised:before{content:"\ec04"}.ti-mood-tongue:before{content:"\eb95"}.ti-mood-tongue-wink:before{content:"\f2ea"}.ti-mood-tongue-wink-2:before{content:"\f2e9"}.ti-mood-unamused:before{content:"\f2eb"}.ti-mood-up:before{content:"\f7bb"}.ti-mood-wink:before{content:"\f2ed"}.ti-mood-wink-2:before{content:"\f2ec"}.ti-mood-wrrr:before{content:"\f2ee"}.ti-mood-x:before{content:"\f7bc"}.ti-mood-xd:before{content:"\f2ef"}.ti-moon:before{content:"\eaf8"}.ti-moon-2:before{content:"\ece6"}.ti-moon-filled:before{content:"\f684"}.ti-moon-off:before{content:"\f162"}.ti-moon-stars:before{content:"\ece7"}.ti-moped:before{content:"\ecbc"}.ti-motorbike:before{content:"\eeb6"}.ti-mountain:before{content:"\ef97"}.ti-mountain-off:before{content:"\f411"}.ti-mouse:before{content:"\eaf9"}.ti-mouse-2:before{content:"\f1d7"}.ti-mouse-off:before{content:"\f163"}.ti-moustache:before{content:"\f4c9"}.ti-movie:before{content:"\eafa"}.ti-movie-off:before{content:"\f164"}.ti-mug:before{content:"\eafb"}.ti-mug-off:before{content:"\f165"}.ti-multiplier-0-5x:before{content:"\ef41"}.ti-multiplier-1-5x:before{content:"\ef42"}.ti-multiplier-1x:before{content:"\ef43"}.ti-multiplier-2x:before{content:"\ef44"}.ti-mushroom:before{content:"\ef14"}.ti-mushroom-filled:before{content:"\f7f9"}.ti-mushroom-off:before{content:"\f412"}.ti-music:before{content:"\eafc"}.ti-music-off:before{content:"\f166"}.ti-navigation:before{content:"\f2c8"}.ti-navigation-filled:before{content:"\f685"}.ti-navigation-off:before{content:"\f413"}.ti-needle:before{content:"\f508"}.ti-needle-thread:before{content:"\f507"}.ti-network:before{content:"\f09f"}.ti-network-off:before{content:"\f414"}.ti-new-section:before{content:"\ebc1"}.ti-news:before{content:"\eafd"}.ti-news-off:before{content:"\f167"}.ti-nfc:before{content:"\eeb7"}.ti-nfc-off:before{content:"\f168"}.ti-no-copyright:before{content:"\efb9"}.ti-no-creative-commons:before{content:"\efba"}.ti-no-derivatives:before{content:"\efbb"}.ti-north-star:before{content:"\f014"}.ti-note:before{content:"\eb6d"}.ti-note-off:before{content:"\f169"}.ti-notebook:before{content:"\eb96"}.ti-notebook-off:before{content:"\f415"}.ti-notes:before{content:"\eb6e"}.ti-notes-off:before{content:"\f16a"}.ti-notification:before{content:"\eafe"}.ti-notification-off:before{content:"\f16b"}.ti-number:before{content:"\f1fe"}.ti-number-0:before{content:"\edf0"}.ti-number-1:before{content:"\edf1"}.ti-number-2:before{content:"\edf2"}.ti-number-3:before{content:"\edf3"}.ti-number-4:before{content:"\edf4"}.ti-number-5:before{content:"\edf5"}.ti-number-6:before{content:"\edf6"}.ti-number-7:before{content:"\edf7"}.ti-number-8:before{content:"\edf8"}.ti-number-9:before{content:"\edf9"}.ti-numbers:before{content:"\f015"}.ti-nurse:before{content:"\ef65"}.ti-octagon:before{content:"\ecbd"}.ti-octagon-filled:before{content:"\f686"}.ti-octagon-off:before{content:"\eeb8"}.ti-old:before{content:"\eeb9"}.ti-olympics:before{content:"\eeba"}.ti-olympics-off:before{content:"\f416"}.ti-om:before{content:"\f58d"}.ti-omega:before{content:"\eb97"}.ti-outbound:before{content:"\f249"}.ti-outlet:before{content:"\ebd7"}.ti-oval:before{content:"\f02e"}.ti-oval-filled:before{content:"\f687"}.ti-oval-vertical:before{content:"\f02d"}.ti-oval-vertical-filled:before{content:"\f688"}.ti-overline:before{content:"\eebb"}.ti-package:before{content:"\eaff"}.ti-package-export:before{content:"\f07a"}.ti-package-import:before{content:"\f07b"}.ti-package-off:before{content:"\f16c"}.ti-packages:before{content:"\f2c9"}.ti-pacman:before{content:"\eebc"}.ti-page-break:before{content:"\ec81"}.ti-paint:before{content:"\eb00"}.ti-paint-filled:before{content:"\f75f"}.ti-paint-off:before{content:"\f16d"}.ti-palette:before{content:"\eb01"}.ti-palette-off:before{content:"\f16e"}.ti-panorama-horizontal:before{content:"\ed33"}.ti-panorama-horizontal-off:before{content:"\f417"}.ti-panorama-vertical:before{content:"\ed34"}.ti-panorama-vertical-off:before{content:"\f418"}.ti-paper-bag:before{content:"\f02f"}.ti-paper-bag-off:before{content:"\f16f"}.ti-paperclip:before{content:"\eb02"}.ti-parachute:before{content:"\ed7c"}.ti-parachute-off:before{content:"\f170"}.ti-parentheses:before{content:"\ebd8"}.ti-parentheses-off:before{content:"\f171"}.ti-parking:before{content:"\eb03"}.ti-parking-off:before{content:"\f172"}.ti-password:before{content:"\f4ca"}.ti-paw:before{content:"\eff9"}.ti-paw-filled:before{content:"\f689"}.ti-paw-off:before{content:"\f419"}.ti-pdf:before{content:"\f7ac"}.ti-peace:before{content:"\ecbe"}.ti-pencil:before{content:"\eb04"}.ti-pencil-minus:before{content:"\f1eb"}.ti-pencil-off:before{content:"\f173"}.ti-pencil-plus:before{content:"\f1ec"}.ti-pennant:before{content:"\ed7d"}.ti-pennant-2:before{content:"\f06a"}.ti-pennant-2-filled:before{content:"\f68a"}.ti-pennant-filled:before{content:"\f68b"}.ti-pennant-off:before{content:"\f174"}.ti-pentagon:before{content:"\efe3"}.ti-pentagon-filled:before{content:"\f68c"}.ti-pentagon-off:before{content:"\f41a"}.ti-pentagram:before{content:"\f586"}.ti-pepper:before{content:"\ef15"}.ti-pepper-off:before{content:"\f175"}.ti-percentage:before{content:"\ecf4"}.ti-perfume:before{content:"\f509"}.ti-perspective:before{content:"\eebd"}.ti-perspective-off:before{content:"\f176"}.ti-phone:before{content:"\eb09"}.ti-phone-call:before{content:"\eb05"}.ti-phone-calling:before{content:"\ec43"}.ti-phone-check:before{content:"\ec05"}.ti-phone-incoming:before{content:"\eb06"}.ti-phone-off:before{content:"\ecf5"}.ti-phone-outgoing:before{content:"\eb07"}.ti-phone-pause:before{content:"\eb08"}.ti-phone-plus:before{content:"\ec06"}.ti-phone-x:before{content:"\ec07"}.ti-photo:before{content:"\eb0a"}.ti-photo-bolt:before{content:"\f990"}.ti-photo-cancel:before{content:"\f35d"}.ti-photo-check:before{content:"\f35e"}.ti-photo-code:before{content:"\f991"}.ti-photo-cog:before{content:"\f992"}.ti-photo-dollar:before{content:"\f993"}.ti-photo-down:before{content:"\f35f"}.ti-photo-edit:before{content:"\f360"}.ti-photo-exclamation:before{content:"\f994"}.ti-photo-heart:before{content:"\f361"}.ti-photo-minus:before{content:"\f362"}.ti-photo-off:before{content:"\ecf6"}.ti-photo-pause:before{content:"\f995"}.ti-photo-pin:before{content:"\f996"}.ti-photo-plus:before{content:"\f363"}.ti-photo-question:before{content:"\f997"}.ti-photo-search:before{content:"\f364"}.ti-photo-sensor:before{content:"\f798"}.ti-photo-sensor-2:before{content:"\f796"}.ti-photo-sensor-3:before{content:"\f797"}.ti-photo-share:before{content:"\f998"}.ti-photo-shield:before{content:"\f365"}.ti-photo-star:before{content:"\f366"}.ti-photo-up:before{content:"\f38b"}.ti-photo-x:before{content:"\f367"}.ti-physotherapist:before{content:"\eebe"}.ti-picture-in-picture:before{content:"\ed35"}.ti-picture-in-picture-off:before{content:"\ed43"}.ti-picture-in-picture-on:before{content:"\ed44"}.ti-picture-in-picture-top:before{content:"\efe4"}.ti-pig:before{content:"\ef52"}.ti-pig-money:before{content:"\f38c"}.ti-pig-off:before{content:"\f177"}.ti-pilcrow:before{content:"\f5f6"}.ti-pill:before{content:"\ec44"}.ti-pill-off:before{content:"\f178"}.ti-pills:before{content:"\ef66"}.ti-pin:before{content:"\ec9c"}.ti-pin-filled:before{content:"\f68d"}.ti-ping-pong:before{content:"\f38d"}.ti-pinned:before{content:"\ed60"}.ti-pinned-filled:before{content:"\f68e"}.ti-pinned-off:before{content:"\ed5f"}.ti-pizza:before{content:"\edbb"}.ti-pizza-off:before{content:"\f179"}.ti-placeholder:before{content:"\f626"}.ti-plane:before{content:"\eb6f"}.ti-plane-arrival:before{content:"\eb99"}.ti-plane-departure:before{content:"\eb9a"}.ti-plane-inflight:before{content:"\ef98"}.ti-plane-off:before{content:"\f17a"}.ti-plane-tilt:before{content:"\f1ed"}.ti-planet:before{content:"\ec08"}.ti-planet-off:before{content:"\f17b"}.ti-plant:before{content:"\ed50"}.ti-plant-2:before{content:"\ed7e"}.ti-plant-2-off:before{content:"\f17c"}.ti-plant-off:before{content:"\f17d"}.ti-play-card:before{content:"\eebf"}.ti-play-card-off:before{content:"\f17e"}.ti-player-eject:before{content:"\efbc"}.ti-player-eject-filled:before{content:"\f68f"}.ti-player-pause:before{content:"\ed45"}.ti-player-pause-filled:before{content:"\f690"}.ti-player-play:before{content:"\ed46"}.ti-player-play-filled:before{content:"\f691"}.ti-player-record:before{content:"\ed47"}.ti-player-record-filled:before{content:"\f692"}.ti-player-skip-back:before{content:"\ed48"}.ti-player-skip-back-filled:before{content:"\f693"}.ti-player-skip-forward:before{content:"\ed49"}.ti-player-skip-forward-filled:before{content:"\f694"}.ti-player-stop:before{content:"\ed4a"}.ti-player-stop-filled:before{content:"\f695"}.ti-player-track-next:before{content:"\ed4b"}.ti-player-track-next-filled:before{content:"\f696"}.ti-player-track-prev:before{content:"\ed4c"}.ti-player-track-prev-filled:before{content:"\f697"}.ti-playlist:before{content:"\eec0"}.ti-playlist-add:before{content:"\f008"}.ti-playlist-off:before{content:"\f17f"}.ti-playlist-x:before{content:"\f009"}.ti-playstation-circle:before{content:"\f2ad"}.ti-playstation-square:before{content:"\f2ae"}.ti-playstation-triangle:before{content:"\f2af"}.ti-playstation-x:before{content:"\f2b0"}.ti-plug:before{content:"\ebd9"}.ti-plug-connected:before{content:"\f00a"}.ti-plug-connected-x:before{content:"\f0a0"}.ti-plug-off:before{content:"\f180"}.ti-plug-x:before{content:"\f0a1"}.ti-plus:before{content:"\eb0b"}.ti-plus-equal:before{content:"\f7ad"}.ti-plus-minus:before{content:"\f7ae"}.ti-png:before{content:"\f3ad"}.ti-podium:before{content:"\f1d8"}.ti-podium-off:before{content:"\f41b"}.ti-point:before{content:"\eb0c"}.ti-point-filled:before{content:"\f698"}.ti-point-off:before{content:"\f181"}.ti-pointer:before{content:"\f265"}.ti-pointer-bolt:before{content:"\f999"}.ti-pointer-cancel:before{content:"\f99a"}.ti-pointer-check:before{content:"\f99b"}.ti-pointer-code:before{content:"\f99c"}.ti-pointer-cog:before{content:"\f99d"}.ti-pointer-dollar:before{content:"\f99e"}.ti-pointer-down:before{content:"\f99f"}.ti-pointer-exclamation:before{content:"\f9a0"}.ti-pointer-heart:before{content:"\f9a1"}.ti-pointer-minus:before{content:"\f9a2"}.ti-pointer-off:before{content:"\f9a3"}.ti-pointer-pause:before{content:"\f9a4"}.ti-pointer-pin:before{content:"\f9a5"}.ti-pointer-plus:before{content:"\f9a6"}.ti-pointer-question:before{content:"\f9a7"}.ti-pointer-search:before{content:"\f9a8"}.ti-pointer-share:before{content:"\f9a9"}.ti-pointer-star:before{content:"\f9aa"}.ti-pointer-up:before{content:"\f9ab"}.ti-pointer-x:before{content:"\f9ac"}.ti-pokeball:before{content:"\eec1"}.ti-pokeball-off:before{content:"\f41c"}.ti-poker-chip:before{content:"\f515"}.ti-polaroid:before{content:"\eec2"}.ti-polygon:before{content:"\efd0"}.ti-polygon-off:before{content:"\f182"}.ti-poo:before{content:"\f258"}.ti-pool:before{content:"\ed91"}.ti-pool-off:before{content:"\f41d"}.ti-power:before{content:"\eb0d"}.ti-pray:before{content:"\ecbf"}.ti-premium-rights:before{content:"\efbd"}.ti-prescription:before{content:"\ef99"}.ti-presentation:before{content:"\eb70"}.ti-presentation-analytics:before{content:"\eec3"}.ti-presentation-off:before{content:"\f183"}.ti-printer:before{content:"\eb0e"}.ti-printer-off:before{content:"\f184"}.ti-prison:before{content:"\ef79"}.ti-prompt:before{content:"\eb0f"}.ti-propeller:before{content:"\eec4"}.ti-propeller-off:before{content:"\f185"}.ti-pumpkin-scary:before{content:"\f587"}.ti-puzzle:before{content:"\eb10"}.ti-puzzle-2:before{content:"\ef83"}.ti-puzzle-filled:before{content:"\f699"}.ti-puzzle-off:before{content:"\f186"}.ti-pyramid:before{content:"\eec5"}.ti-pyramid-off:before{content:"\f187"}.ti-qrcode:before{content:"\eb11"}.ti-qrcode-off:before{content:"\f41e"}.ti-question-mark:before{content:"\ec9d"}.ti-quote:before{content:"\efbe"}.ti-quote-off:before{content:"\f188"}.ti-radar:before{content:"\f017"}.ti-radar-2:before{content:"\f016"}.ti-radar-off:before{content:"\f41f"}.ti-radio:before{content:"\ef2d"}.ti-radio-off:before{content:"\f420"}.ti-radioactive:before{content:"\ecc0"}.ti-radioactive-filled:before{content:"\f760"}.ti-radioactive-off:before{content:"\f189"}.ti-radius-bottom-left:before{content:"\eec6"}.ti-radius-bottom-right:before{content:"\eec7"}.ti-radius-top-left:before{content:"\eec8"}.ti-radius-top-right:before{content:"\eec9"}.ti-rainbow:before{content:"\edbc"}.ti-rainbow-off:before{content:"\f18a"}.ti-rating-12-plus:before{content:"\f266"}.ti-rating-14-plus:before{content:"\f267"}.ti-rating-16-plus:before{content:"\f268"}.ti-rating-18-plus:before{content:"\f269"}.ti-rating-21-plus:before{content:"\f26a"}.ti-razor:before{content:"\f4b5"}.ti-razor-electric:before{content:"\f4b4"}.ti-receipt:before{content:"\edfd"}.ti-receipt-2:before{content:"\edfa"}.ti-receipt-off:before{content:"\edfb"}.ti-receipt-refund:before{content:"\edfc"}.ti-receipt-tax:before{content:"\edbd"}.ti-recharging:before{content:"\eeca"}.ti-record-mail:before{content:"\eb12"}.ti-record-mail-off:before{content:"\f18b"}.ti-rectangle:before{content:"\ed37"}.ti-rectangle-filled:before{content:"\f69a"}.ti-rectangle-vertical:before{content:"\ed36"}.ti-rectangle-vertical-filled:before{content:"\f69b"}.ti-recycle:before{content:"\eb9b"}.ti-recycle-off:before{content:"\f18c"}.ti-refresh:before{content:"\eb13"}.ti-refresh-alert:before{content:"\ed57"}.ti-refresh-dot:before{content:"\efbf"}.ti-refresh-off:before{content:"\f18d"}.ti-regex:before{content:"\f31f"}.ti-regex-off:before{content:"\f421"}.ti-registered:before{content:"\eb14"}.ti-relation-many-to-many:before{content:"\ed7f"}.ti-relation-one-to-many:before{content:"\ed80"}.ti-relation-one-to-one:before{content:"\ed81"}.ti-reload:before{content:"\f3ae"}.ti-repeat:before{content:"\eb72"}.ti-repeat-off:before{content:"\f18e"}.ti-repeat-once:before{content:"\eb71"}.ti-replace:before{content:"\ebc7"}.ti-replace-filled:before{content:"\f69c"}.ti-replace-off:before{content:"\f422"}.ti-report:before{content:"\eece"}.ti-report-analytics:before{content:"\eecb"}.ti-report-medical:before{content:"\eecc"}.ti-report-money:before{content:"\eecd"}.ti-report-off:before{content:"\f18f"}.ti-report-search:before{content:"\ef84"}.ti-reserved-line:before{content:"\f9f6"}.ti-resize:before{content:"\eecf"}.ti-ribbon-health:before{content:"\f58e"}.ti-ripple:before{content:"\ed82"}.ti-ripple-off:before{content:"\f190"}.ti-road:before{content:"\f018"}.ti-road-off:before{content:"\f191"}.ti-road-sign:before{content:"\ecdd"}.ti-robot:before{content:"\f00b"}.ti-robot-off:before{content:"\f192"}.ti-rocket:before{content:"\ec45"}.ti-rocket-off:before{content:"\f193"}.ti-roller-skating:before{content:"\efd1"}.ti-rollercoaster:before{content:"\f0a2"}.ti-rollercoaster-off:before{content:"\f423"}.ti-rosette:before{content:"\f599"}.ti-rosette-filled:before{content:"\f69d"}.ti-rosette-number-0:before{content:"\f58f"}.ti-rosette-number-1:before{content:"\f590"}.ti-rosette-number-2:before{content:"\f591"}.ti-rosette-number-3:before{content:"\f592"}.ti-rosette-number-4:before{content:"\f593"}.ti-rosette-number-5:before{content:"\f594"}.ti-rosette-number-6:before{content:"\f595"}.ti-rosette-number-7:before{content:"\f596"}.ti-rosette-number-8:before{content:"\f597"}.ti-rosette-number-9:before{content:"\f598"}.ti-rotate:before{content:"\eb16"}.ti-rotate-2:before{content:"\ebb4"}.ti-rotate-360:before{content:"\ef85"}.ti-rotate-clockwise:before{content:"\eb15"}.ti-rotate-clockwise-2:before{content:"\ebb5"}.ti-rotate-dot:before{content:"\efe5"}.ti-rotate-rectangle:before{content:"\ec15"}.ti-route:before{content:"\eb17"}.ti-route-2:before{content:"\f4b6"}.ti-route-off:before{content:"\f194"}.ti-router:before{content:"\eb18"}.ti-router-off:before{content:"\f424"}.ti-row-insert-bottom:before{content:"\eed0"}.ti-row-insert-top:before{content:"\eed1"}.ti-rss:before{content:"\eb19"}.ti-rubber-stamp:before{content:"\f5ab"}.ti-rubber-stamp-off:before{content:"\f5aa"}.ti-ruler:before{content:"\eb1a"}.ti-ruler-2:before{content:"\eed2"}.ti-ruler-2-off:before{content:"\f195"}.ti-ruler-3:before{content:"\f290"}.ti-ruler-measure:before{content:"\f291"}.ti-ruler-off:before{content:"\f196"}.ti-run:before{content:"\ec82"}.ti-s-turn-down:before{content:"\f516"}.ti-s-turn-left:before{content:"\f517"}.ti-s-turn-right:before{content:"\f518"}.ti-s-turn-up:before{content:"\f519"}.ti-sailboat:before{content:"\ec83"}.ti-sailboat-2:before{content:"\f5f7"}.ti-sailboat-off:before{content:"\f425"}.ti-salad:before{content:"\f50a"}.ti-salt:before{content:"\ef16"}.ti-satellite:before{content:"\eed3"}.ti-satellite-off:before{content:"\f197"}.ti-sausage:before{content:"\ef17"}.ti-scale:before{content:"\ebc2"}.ti-scale-off:before{content:"\f198"}.ti-scale-outline:before{content:"\ef53"}.ti-scale-outline-off:before{content:"\f199"}.ti-scan:before{content:"\ebc8"}.ti-scan-eye:before{content:"\f1ff"}.ti-schema:before{content:"\f200"}.ti-schema-off:before{content:"\f426"}.ti-school:before{content:"\ecf7"}.ti-school-bell:before{content:"\f64a"}.ti-school-off:before{content:"\f19a"}.ti-scissors:before{content:"\eb1b"}.ti-scissors-off:before{content:"\f19b"}.ti-scooter:before{content:"\ec6c"}.ti-scooter-electric:before{content:"\ecc1"}.ti-screen-share:before{content:"\ed18"}.ti-screen-share-off:before{content:"\ed17"}.ti-screenshot:before{content:"\f201"}.ti-scribble:before{content:"\f0a3"}.ti-scribble-off:before{content:"\f427"}.ti-script:before{content:"\f2da"}.ti-script-minus:before{content:"\f2d7"}.ti-script-plus:before{content:"\f2d8"}.ti-script-x:before{content:"\f2d9"}.ti-scuba-mask:before{content:"\eed4"}.ti-scuba-mask-off:before{content:"\f428"}.ti-sdk:before{content:"\f3af"}.ti-search:before{content:"\eb1c"}.ti-search-off:before{content:"\f19c"}.ti-section:before{content:"\eed5"}.ti-section-sign:before{content:"\f019"}.ti-seeding:before{content:"\ed51"}.ti-seeding-off:before{content:"\f19d"}.ti-select:before{content:"\ec9e"}.ti-select-all:before{content:"\f9f7"}.ti-selector:before{content:"\eb1d"}.ti-send:before{content:"\eb1e"}.ti-send-off:before{content:"\f429"}.ti-seo:before{content:"\f26b"}.ti-separator:before{content:"\ebda"}.ti-separator-horizontal:before{content:"\ec79"}.ti-separator-vertical:before{content:"\ec7a"}.ti-server:before{content:"\eb1f"}.ti-server-2:before{content:"\f07c"}.ti-server-bolt:before{content:"\f320"}.ti-server-cog:before{content:"\f321"}.ti-server-off:before{content:"\f19e"}.ti-servicemark:before{content:"\ec09"}.ti-settings:before{content:"\eb20"}.ti-settings-2:before{content:"\f5ac"}.ti-settings-automation:before{content:"\eed6"}.ti-settings-bolt:before{content:"\f9ad"}.ti-settings-cancel:before{content:"\f9ae"}.ti-settings-check:before{content:"\f9af"}.ti-settings-code:before{content:"\f9b0"}.ti-settings-cog:before{content:"\f9b1"}.ti-settings-dollar:before{content:"\f9b2"}.ti-settings-down:before{content:"\f9b3"}.ti-settings-exclamation:before{content:"\f9b4"}.ti-settings-filled:before{content:"\f69e"}.ti-settings-heart:before{content:"\f9b5"}.ti-settings-minus:before{content:"\f9b6"}.ti-settings-off:before{content:"\f19f"}.ti-settings-pause:before{content:"\f9b7"}.ti-settings-pin:before{content:"\f9b8"}.ti-settings-plus:before{content:"\f9b9"}.ti-settings-question:before{content:"\f9ba"}.ti-settings-search:before{content:"\f9bb"}.ti-settings-share:before{content:"\f9bc"}.ti-settings-star:before{content:"\f9bd"}.ti-settings-up:before{content:"\f9be"}.ti-settings-x:before{content:"\f9bf"}.ti-shadow:before{content:"\eed8"}.ti-shadow-off:before{content:"\eed7"}.ti-shape:before{content:"\eb9c"}.ti-shape-2:before{content:"\eed9"}.ti-shape-3:before{content:"\eeda"}.ti-shape-off:before{content:"\f1a0"}.ti-share:before{content:"\eb21"}.ti-share-2:before{content:"\f799"}.ti-share-3:before{content:"\f7bd"}.ti-share-off:before{content:"\f1a1"}.ti-shield:before{content:"\eb24"}.ti-shield-bolt:before{content:"\f9c0"}.ti-shield-cancel:before{content:"\f9c1"}.ti-shield-check:before{content:"\eb22"}.ti-shield-check-filled:before{content:"\f761"}.ti-shield-checkered:before{content:"\ef9a"}.ti-shield-checkered-filled:before{content:"\f762"}.ti-shield-chevron:before{content:"\ef9b"}.ti-shield-code:before{content:"\f9c2"}.ti-shield-cog:before{content:"\f9c3"}.ti-shield-dollar:before{content:"\f9c4"}.ti-shield-down:before{content:"\f9c5"}.ti-shield-exclamation:before{content:"\f9c6"}.ti-shield-filled:before{content:"\f69f"}.ti-shield-half:before{content:"\f358"}.ti-shield-half-filled:before{content:"\f357"}.ti-shield-heart:before{content:"\f9c7"}.ti-shield-lock:before{content:"\ed58"}.ti-shield-lock-filled:before{content:"\f763"}.ti-shield-minus:before{content:"\f9c8"}.ti-shield-off:before{content:"\ecf8"}.ti-shield-pause:before{content:"\f9c9"}.ti-shield-pin:before{content:"\f9ca"}.ti-shield-plus:before{content:"\f9cb"}.ti-shield-question:before{content:"\f9cc"}.ti-shield-search:before{content:"\f9cd"}.ti-shield-share:before{content:"\f9ce"}.ti-shield-star:before{content:"\f9cf"}.ti-shield-up:before{content:"\f9d0"}.ti-shield-x:before{content:"\eb23"}.ti-ship:before{content:"\ec84"}.ti-ship-off:before{content:"\f42a"}.ti-shirt:before{content:"\ec0a"}.ti-shirt-filled:before{content:"\f6a0"}.ti-shirt-off:before{content:"\f1a2"}.ti-shirt-sport:before{content:"\f26c"}.ti-shoe:before{content:"\efd2"}.ti-shoe-off:before{content:"\f1a4"}.ti-shopping-bag:before{content:"\f5f8"}.ti-shopping-cart:before{content:"\eb25"}.ti-shopping-cart-discount:before{content:"\eedb"}.ti-shopping-cart-off:before{content:"\eedc"}.ti-shopping-cart-plus:before{content:"\eedd"}.ti-shopping-cart-x:before{content:"\eede"}.ti-shovel:before{content:"\f1d9"}.ti-shredder:before{content:"\eedf"}.ti-sign-left:before{content:"\f06b"}.ti-sign-left-filled:before{content:"\f6a1"}.ti-sign-right:before{content:"\f06c"}.ti-sign-right-filled:before{content:"\f6a2"}.ti-signal-2g:before{content:"\f79a"}.ti-signal-3g:before{content:"\f1ee"}.ti-signal-4g:before{content:"\f1ef"}.ti-signal-4g-plus:before{content:"\f259"}.ti-signal-5g:before{content:"\f1f0"}.ti-signal-6g:before{content:"\f9f8"}.ti-signal-e:before{content:"\f9f9"}.ti-signal-g:before{content:"\f9fa"}.ti-signal-h:before{content:"\f9fc"}.ti-signal-h-plus:before{content:"\f9fb"}.ti-signal-lte:before{content:"\f9fd"}.ti-signature:before{content:"\eee0"}.ti-signature-off:before{content:"\f1a5"}.ti-sitemap:before{content:"\eb9d"}.ti-sitemap-off:before{content:"\f1a6"}.ti-skateboard:before{content:"\ecc2"}.ti-skateboard-off:before{content:"\f42b"}.ti-skull:before{content:"\f292"}.ti-slash:before{content:"\f4f9"}.ti-slashes:before{content:"\f588"}.ti-sleigh:before{content:"\ef9c"}.ti-slice:before{content:"\ebdb"}.ti-slideshow:before{content:"\ebc9"}.ti-smart-home:before{content:"\ecde"}.ti-smart-home-off:before{content:"\f1a7"}.ti-smoking:before{content:"\ecc4"}.ti-smoking-no:before{content:"\ecc3"}.ti-snowflake:before{content:"\ec0b"}.ti-snowflake-off:before{content:"\f1a8"}.ti-snowman:before{content:"\f26d"}.ti-soccer-field:before{content:"\ed92"}.ti-social:before{content:"\ebec"}.ti-social-off:before{content:"\f1a9"}.ti-sock:before{content:"\eee1"}.ti-sofa:before{content:"\efaf"}.ti-sofa-off:before{content:"\f42c"}.ti-solar-panel:before{content:"\f7bf"}.ti-solar-panel-2:before{content:"\f7be"}.ti-sort-0-9:before{content:"\f54d"}.ti-sort-9-0:before{content:"\f54e"}.ti-sort-a-z:before{content:"\f54f"}.ti-sort-ascending:before{content:"\eb26"}.ti-sort-ascending-2:before{content:"\eee2"}.ti-sort-ascending-letters:before{content:"\ef18"}.ti-sort-ascending-numbers:before{content:"\ef19"}.ti-sort-descending:before{content:"\eb27"}.ti-sort-descending-2:before{content:"\eee3"}.ti-sort-descending-letters:before{content:"\ef1a"}.ti-sort-descending-numbers:before{content:"\ef1b"}.ti-sort-z-a:before{content:"\f550"}.ti-sos:before{content:"\f24a"}.ti-soup:before{content:"\ef2e"}.ti-soup-off:before{content:"\f42d"}.ti-source-code:before{content:"\f4a2"}.ti-space:before{content:"\ec0c"}.ti-space-off:before{content:"\f1aa"}.ti-spacing-horizontal:before{content:"\ef54"}.ti-spacing-vertical:before{content:"\ef55"}.ti-spade:before{content:"\effa"}.ti-spade-filled:before{content:"\f6a3"}.ti-sparkles:before{content:"\f6d7"}.ti-speakerphone:before{content:"\ed61"}.ti-speedboat:before{content:"\ed93"}.ti-spider:before{content:"\f293"}.ti-spiral:before{content:"\f294"}.ti-spiral-off:before{content:"\f42e"}.ti-sport-billard:before{content:"\eee4"}.ti-spray:before{content:"\f50b"}.ti-spy:before{content:"\f227"}.ti-spy-off:before{content:"\f42f"}.ti-sql:before{content:"\f7c0"}.ti-square:before{content:"\eb2c"}.ti-square-0-filled:before{content:"\f764"}.ti-square-1-filled:before{content:"\f765"}.ti-square-2-filled:before{content:"\f7fa"}.ti-square-3-filled:before{content:"\f766"}.ti-square-4-filled:before{content:"\f767"}.ti-square-5-filled:before{content:"\f768"}.ti-square-6-filled:before{content:"\f769"}.ti-square-7-filled:before{content:"\f76a"}.ti-square-8-filled:before{content:"\f76b"}.ti-square-9-filled:before{content:"\f76c"}.ti-square-arrow-down:before{content:"\f4b7"}.ti-square-arrow-left:before{content:"\f4b8"}.ti-square-arrow-right:before{content:"\f4b9"}.ti-square-arrow-up:before{content:"\f4ba"}.ti-square-asterisk:before{content:"\f01a"}.ti-square-check:before{content:"\eb28"}.ti-square-check-filled:before{content:"\f76d"}.ti-square-chevron-down:before{content:"\f627"}.ti-square-chevron-left:before{content:"\f628"}.ti-square-chevron-right:before{content:"\f629"}.ti-square-chevron-up:before{content:"\f62a"}.ti-square-chevrons-down:before{content:"\f64b"}.ti-square-chevrons-left:before{content:"\f64c"}.ti-square-chevrons-right:before{content:"\f64d"}.ti-square-chevrons-up:before{content:"\f64e"}.ti-square-dot:before{content:"\ed59"}.ti-square-f0:before{content:"\f526"}.ti-square-f0-filled:before{content:"\f76e"}.ti-square-f1:before{content:"\f527"}.ti-square-f1-filled:before{content:"\f76f"}.ti-square-f2:before{content:"\f528"}.ti-square-f2-filled:before{content:"\f770"}.ti-square-f3:before{content:"\f529"}.ti-square-f3-filled:before{content:"\f771"}.ti-square-f4:before{content:"\f52a"}.ti-square-f4-filled:before{content:"\f772"}.ti-square-f5:before{content:"\f52b"}.ti-square-f5-filled:before{content:"\f773"}.ti-square-f6:before{content:"\f52c"}.ti-square-f6-filled:before{content:"\f774"}.ti-square-f7:before{content:"\f52d"}.ti-square-f7-filled:before{content:"\f775"}.ti-square-f8:before{content:"\f52e"}.ti-square-f8-filled:before{content:"\f776"}.ti-square-f9:before{content:"\f52f"}.ti-square-f9-filled:before{content:"\f777"}.ti-square-forbid:before{content:"\ed5b"}.ti-square-forbid-2:before{content:"\ed5a"}.ti-square-half:before{content:"\effb"}.ti-square-key:before{content:"\f638"}.ti-square-letter-a:before{content:"\f47c"}.ti-square-letter-b:before{content:"\f47d"}.ti-square-letter-c:before{content:"\f47e"}.ti-square-letter-d:before{content:"\f47f"}.ti-square-letter-e:before{content:"\f480"}.ti-square-letter-f:before{content:"\f481"}.ti-square-letter-g:before{content:"\f482"}.ti-square-letter-h:before{content:"\f483"}.ti-square-letter-i:before{content:"\f484"}.ti-square-letter-j:before{content:"\f485"}.ti-square-letter-k:before{content:"\f486"}.ti-square-letter-l:before{content:"\f487"}.ti-square-letter-m:before{content:"\f488"}.ti-square-letter-n:before{content:"\f489"}.ti-square-letter-o:before{content:"\f48a"}.ti-square-letter-p:before{content:"\f48b"}.ti-square-letter-q:before{content:"\f48c"}.ti-square-letter-r:before{content:"\f48d"}.ti-square-letter-s:before{content:"\f48e"}.ti-square-letter-t:before{content:"\f48f"}.ti-square-letter-u:before{content:"\f490"}.ti-square-letter-v:before{content:"\f4bb"}.ti-square-letter-w:before{content:"\f491"}.ti-square-letter-x:before{content:"\f4bc"}.ti-square-letter-y:before{content:"\f492"}.ti-square-letter-z:before{content:"\f493"}.ti-square-minus:before{content:"\eb29"}.ti-square-number-0:before{content:"\eee5"}.ti-square-number-1:before{content:"\eee6"}.ti-square-number-2:before{content:"\eee7"}.ti-square-number-3:before{content:"\eee8"}.ti-square-number-4:before{content:"\eee9"}.ti-square-number-5:before{content:"\eeea"}.ti-square-number-6:before{content:"\eeeb"}.ti-square-number-7:before{content:"\eeec"}.ti-square-number-8:before{content:"\eeed"}.ti-square-number-9:before{content:"\eeee"}.ti-square-off:before{content:"\eeef"}.ti-square-plus:before{content:"\eb2a"}.ti-square-root:before{content:"\eef1"}.ti-square-root-2:before{content:"\eef0"}.ti-square-rotated:before{content:"\ecdf"}.ti-square-rotated-filled:before{content:"\f6a4"}.ti-square-rotated-forbid:before{content:"\f01c"}.ti-square-rotated-forbid-2:before{content:"\f01b"}.ti-square-rotated-off:before{content:"\eef2"}.ti-square-rounded:before{content:"\f59a"}.ti-square-rounded-arrow-down:before{content:"\f639"}.ti-square-rounded-arrow-down-filled:before{content:"\f6db"}.ti-square-rounded-arrow-left:before{content:"\f63a"}.ti-square-rounded-arrow-left-filled:before{content:"\f6dc"}.ti-square-rounded-arrow-right:before{content:"\f63b"}.ti-square-rounded-arrow-right-filled:before{content:"\f6dd"}.ti-square-rounded-arrow-up:before{content:"\f63c"}.ti-square-rounded-arrow-up-filled:before{content:"\f6de"}.ti-square-rounded-check:before{content:"\f63d"}.ti-square-rounded-check-filled:before{content:"\f6df"}.ti-square-rounded-chevron-down:before{content:"\f62b"}.ti-square-rounded-chevron-down-filled:before{content:"\f6e0"}.ti-square-rounded-chevron-left:before{content:"\f62c"}.ti-square-rounded-chevron-left-filled:before{content:"\f6e1"}.ti-square-rounded-chevron-right:before{content:"\f62d"}.ti-square-rounded-chevron-right-filled:before{content:"\f6e2"}.ti-square-rounded-chevron-up:before{content:"\f62e"}.ti-square-rounded-chevron-up-filled:before{content:"\f6e3"}.ti-square-rounded-chevrons-down:before{content:"\f64f"}.ti-square-rounded-chevrons-down-filled:before{content:"\f6e4"}.ti-square-rounded-chevrons-left:before{content:"\f650"}.ti-square-rounded-chevrons-left-filled:before{content:"\f6e5"}.ti-square-rounded-chevrons-right:before{content:"\f651"}.ti-square-rounded-chevrons-right-filled:before{content:"\f6e6"}.ti-square-rounded-chevrons-up:before{content:"\f652"}.ti-square-rounded-chevrons-up-filled:before{content:"\f6e7"}.ti-square-rounded-filled:before{content:"\f6a5"}.ti-square-rounded-letter-a:before{content:"\f5ae"}.ti-square-rounded-letter-b:before{content:"\f5af"}.ti-square-rounded-letter-c:before{content:"\f5b0"}.ti-square-rounded-letter-d:before{content:"\f5b1"}.ti-square-rounded-letter-e:before{content:"\f5b2"}.ti-square-rounded-letter-f:before{content:"\f5b3"}.ti-square-rounded-letter-g:before{content:"\f5b4"}.ti-square-rounded-letter-h:before{content:"\f5b5"}.ti-square-rounded-letter-i:before{content:"\f5b6"}.ti-square-rounded-letter-j:before{content:"\f5b7"}.ti-square-rounded-letter-k:before{content:"\f5b8"}.ti-square-rounded-letter-l:before{content:"\f5b9"}.ti-square-rounded-letter-m:before{content:"\f5ba"}.ti-square-rounded-letter-n:before{content:"\f5bb"}.ti-square-rounded-letter-o:before{content:"\f5bc"}.ti-square-rounded-letter-p:before{content:"\f5bd"}.ti-square-rounded-letter-q:before{content:"\f5be"}.ti-square-rounded-letter-r:before{content:"\f5bf"}.ti-square-rounded-letter-s:before{content:"\f5c0"}.ti-square-rounded-letter-t:before{content:"\f5c1"}.ti-square-rounded-letter-u:before{content:"\f5c2"}.ti-square-rounded-letter-v:before{content:"\f5c3"}.ti-square-rounded-letter-w:before{content:"\f5c4"}.ti-square-rounded-letter-x:before{content:"\f5c5"}.ti-square-rounded-letter-y:before{content:"\f5c6"}.ti-square-rounded-letter-z:before{content:"\f5c7"}.ti-square-rounded-minus:before{content:"\f63e"}.ti-square-rounded-number-0:before{content:"\f5c8"}.ti-square-rounded-number-0-filled:before{content:"\f778"}.ti-square-rounded-number-1:before{content:"\f5c9"}.ti-square-rounded-number-1-filled:before{content:"\f779"}.ti-square-rounded-number-2:before{content:"\f5ca"}.ti-square-rounded-number-2-filled:before{content:"\f77a"}.ti-square-rounded-number-3:before{content:"\f5cb"}.ti-square-rounded-number-3-filled:before{content:"\f77b"}.ti-square-rounded-number-4:before{content:"\f5cc"}.ti-square-rounded-number-4-filled:before{content:"\f77c"}.ti-square-rounded-number-5:before{content:"\f5cd"}.ti-square-rounded-number-5-filled:before{content:"\f77d"}.ti-square-rounded-number-6:before{content:"\f5ce"}.ti-square-rounded-number-6-filled:before{content:"\f77e"}.ti-square-rounded-number-7:before{content:"\f5cf"}.ti-square-rounded-number-7-filled:before{content:"\f77f"}.ti-square-rounded-number-8:before{content:"\f5d0"}.ti-square-rounded-number-8-filled:before{content:"\f780"}.ti-square-rounded-number-9:before{content:"\f5d1"}.ti-square-rounded-number-9-filled:before{content:"\f781"}.ti-square-rounded-plus:before{content:"\f63f"}.ti-square-rounded-plus-filled:before{content:"\f6e8"}.ti-square-rounded-x:before{content:"\f640"}.ti-square-rounded-x-filled:before{content:"\f6e9"}.ti-square-toggle:before{content:"\eef4"}.ti-square-toggle-horizontal:before{content:"\eef3"}.ti-square-x:before{content:"\eb2b"}.ti-squares-diagonal:before{content:"\eef5"}.ti-squares-filled:before{content:"\eef6"}.ti-stack:before{content:"\eb2d"}.ti-stack-2:before{content:"\eef7"}.ti-stack-3:before{content:"\ef9d"}.ti-stack-pop:before{content:"\f234"}.ti-stack-push:before{content:"\f235"}.ti-stairs:before{content:"\eca6"}.ti-stairs-down:before{content:"\eca4"}.ti-stairs-up:before{content:"\eca5"}.ti-star:before{content:"\eb2e"}.ti-star-filled:before{content:"\f6a6"}.ti-star-half:before{content:"\ed19"}.ti-star-half-filled:before{content:"\f6a7"}.ti-star-off:before{content:"\ed62"}.ti-stars:before{content:"\ed38"}.ti-stars-filled:before{content:"\f6a8"}.ti-stars-off:before{content:"\f430"}.ti-status-change:before{content:"\f3b0"}.ti-steam:before{content:"\f24b"}.ti-steering-wheel:before{content:"\ec7b"}.ti-steering-wheel-off:before{content:"\f431"}.ti-step-into:before{content:"\ece0"}.ti-step-out:before{content:"\ece1"}.ti-stereo-glasses:before{content:"\f4cb"}.ti-stethoscope:before{content:"\edbe"}.ti-stethoscope-off:before{content:"\f432"}.ti-sticker:before{content:"\eb2f"}.ti-storm:before{content:"\f24c"}.ti-storm-off:before{content:"\f433"}.ti-stretching:before{content:"\f2db"}.ti-strikethrough:before{content:"\eb9e"}.ti-submarine:before{content:"\ed94"}.ti-subscript:before{content:"\eb9f"}.ti-subtask:before{content:"\ec9f"}.ti-sum:before{content:"\eb73"}.ti-sum-off:before{content:"\f1ab"}.ti-sun:before{content:"\eb30"}.ti-sun-filled:before{content:"\f6a9"}.ti-sun-high:before{content:"\f236"}.ti-sun-low:before{content:"\f237"}.ti-sun-moon:before{content:"\f4a3"}.ti-sun-off:before{content:"\ed63"}.ti-sun-wind:before{content:"\f238"}.ti-sunglasses:before{content:"\f239"}.ti-sunrise:before{content:"\ef1c"}.ti-sunset:before{content:"\ec31"}.ti-sunset-2:before{content:"\f23a"}.ti-superscript:before{content:"\eba0"}.ti-svg:before{content:"\f25a"}.ti-swimming:before{content:"\ec92"}.ti-swipe:before{content:"\f551"}.ti-switch:before{content:"\eb33"}.ti-switch-2:before{content:"\edbf"}.ti-switch-3:before{content:"\edc0"}.ti-switch-horizontal:before{content:"\eb31"}.ti-switch-vertical:before{content:"\eb32"}.ti-sword:before{content:"\f030"}.ti-sword-off:before{content:"\f434"}.ti-swords:before{content:"\f132"}.ti-table:before{content:"\eba1"}.ti-table-alias:before{content:"\f25b"}.ti-table-export:before{content:"\eef8"}.ti-table-filled:before{content:"\f782"}.ti-table-import:before{content:"\eef9"}.ti-table-off:before{content:"\eefa"}.ti-table-options:before{content:"\f25c"}.ti-table-shortcut:before{content:"\f25d"}.ti-tag:before{content:"\eb34"}.ti-tag-off:before{content:"\efc0"}.ti-tags:before{content:"\ef86"}.ti-tags-off:before{content:"\efc1"}.ti-tallymark-1:before{content:"\ec46"}.ti-tallymark-2:before{content:"\ec47"}.ti-tallymark-3:before{content:"\ec48"}.ti-tallymark-4:before{content:"\ec49"}.ti-tallymarks:before{content:"\ec4a"}.ti-tank:before{content:"\ed95"}.ti-target:before{content:"\eb35"}.ti-target-arrow:before{content:"\f51a"}.ti-target-off:before{content:"\f1ad"}.ti-teapot:before{content:"\f552"}.ti-telescope:before{content:"\f07d"}.ti-telescope-off:before{content:"\f1ae"}.ti-temperature:before{content:"\eb38"}.ti-temperature-celsius:before{content:"\eb36"}.ti-temperature-fahrenheit:before{content:"\eb37"}.ti-temperature-minus:before{content:"\ebed"}.ti-temperature-off:before{content:"\f1af"}.ti-temperature-plus:before{content:"\ebee"}.ti-template:before{content:"\eb39"}.ti-template-off:before{content:"\f1b0"}.ti-tent:before{content:"\eefb"}.ti-tent-off:before{content:"\f435"}.ti-terminal:before{content:"\ebdc"}.ti-terminal-2:before{content:"\ebef"}.ti-test-pipe:before{content:"\eb3a"}.ti-test-pipe-2:before{content:"\f0a4"}.ti-test-pipe-off:before{content:"\f1b1"}.ti-tex:before{content:"\f4e0"}.ti-text-caption:before{content:"\f4a4"}.ti-text-color:before{content:"\f2dc"}.ti-text-decrease:before{content:"\f202"}.ti-text-direction-ltr:before{content:"\eefc"}.ti-text-direction-rtl:before{content:"\eefd"}.ti-text-increase:before{content:"\f203"}.ti-text-orientation:before{content:"\f2a4"}.ti-text-plus:before{content:"\f2a5"}.ti-text-recognition:before{content:"\f204"}.ti-text-resize:before{content:"\ef87"}.ti-text-size:before{content:"\f2b1"}.ti-text-spellcheck:before{content:"\f2a6"}.ti-text-wrap:before{content:"\ebdd"}.ti-text-wrap-disabled:before{content:"\eca7"}.ti-texture:before{content:"\f51b"}.ti-theater:before{content:"\f79b"}.ti-thermometer:before{content:"\ef67"}.ti-thumb-down:before{content:"\eb3b"}.ti-thumb-down-filled:before{content:"\f6aa"}.ti-thumb-down-off:before{content:"\f436"}.ti-thumb-up:before{content:"\eb3c"}.ti-thumb-up-filled:before{content:"\f6ab"}.ti-thumb-up-off:before{content:"\f437"}.ti-tic-tac:before{content:"\f51c"}.ti-ticket:before{content:"\eb3d"}.ti-ticket-off:before{content:"\f1b2"}.ti-tie:before{content:"\f07e"}.ti-tilde:before{content:"\f4a5"}.ti-tilt-shift:before{content:"\eefe"}.ti-tilt-shift-off:before{content:"\f1b3"}.ti-timeline:before{content:"\f031"}.ti-timeline-event:before{content:"\f553"}.ti-timeline-event-exclamation:before{content:"\f662"}.ti-timeline-event-minus:before{content:"\f663"}.ti-timeline-event-plus:before{content:"\f664"}.ti-timeline-event-text:before{content:"\f665"}.ti-timeline-event-x:before{content:"\f666"}.ti-tir:before{content:"\ebf0"}.ti-toggle-left:before{content:"\eb3e"}.ti-toggle-right:before{content:"\eb3f"}.ti-toilet-paper:before{content:"\efd3"}.ti-toilet-paper-off:before{content:"\f1b4"}.ti-tool:before{content:"\eb40"}.ti-tools:before{content:"\ebca"}.ti-tools-kitchen:before{content:"\ed64"}.ti-tools-kitchen-2:before{content:"\eeff"}.ti-tools-kitchen-2-off:before{content:"\f1b5"}.ti-tools-kitchen-off:before{content:"\f1b6"}.ti-tools-off:before{content:"\f1b7"}.ti-tooltip:before{content:"\f2dd"}.ti-topology-bus:before{content:"\f5d9"}.ti-topology-complex:before{content:"\f5da"}.ti-topology-full:before{content:"\f5dc"}.ti-topology-full-hierarchy:before{content:"\f5db"}.ti-topology-ring:before{content:"\f5df"}.ti-topology-ring-2:before{content:"\f5dd"}.ti-topology-ring-3:before{content:"\f5de"}.ti-topology-star:before{content:"\f5e5"}.ti-topology-star-2:before{content:"\f5e0"}.ti-topology-star-3:before{content:"\f5e1"}.ti-topology-star-ring:before{content:"\f5e4"}.ti-topology-star-ring-2:before{content:"\f5e2"}.ti-topology-star-ring-3:before{content:"\f5e3"}.ti-torii:before{content:"\f59b"}.ti-tornado:before{content:"\ece2"}.ti-tournament:before{content:"\ecd0"}.ti-tower:before{content:"\f2cb"}.ti-tower-off:before{content:"\f2ca"}.ti-track:before{content:"\ef00"}.ti-tractor:before{content:"\ec0d"}.ti-trademark:before{content:"\ec0e"}.ti-traffic-cone:before{content:"\ec0f"}.ti-traffic-cone-off:before{content:"\f1b8"}.ti-traffic-lights:before{content:"\ed39"}.ti-traffic-lights-off:before{content:"\f1b9"}.ti-train:before{content:"\ed96"}.ti-transfer-in:before{content:"\ef2f"}.ti-transfer-out:before{content:"\ef30"}.ti-transform:before{content:"\f38e"}.ti-transform-filled:before{content:"\f6ac"}.ti-transition-bottom:before{content:"\f2b2"}.ti-transition-left:before{content:"\f2b3"}.ti-transition-right:before{content:"\f2b4"}.ti-transition-top:before{content:"\f2b5"}.ti-trash:before{content:"\eb41"}.ti-trash-filled:before{content:"\f783"}.ti-trash-off:before{content:"\ed65"}.ti-trash-x:before{content:"\ef88"}.ti-trash-x-filled:before{content:"\f784"}.ti-tree:before{content:"\ef01"}.ti-trees:before{content:"\ec10"}.ti-trekking:before{content:"\f5ad"}.ti-trending-down:before{content:"\eb42"}.ti-trending-down-2:before{content:"\edc1"}.ti-trending-down-3:before{content:"\edc2"}.ti-trending-up:before{content:"\eb43"}.ti-trending-up-2:before{content:"\edc3"}.ti-trending-up-3:before{content:"\edc4"}.ti-triangle:before{content:"\eb44"}.ti-triangle-filled:before{content:"\f6ad"}.ti-triangle-inverted:before{content:"\f01d"}.ti-triangle-inverted-filled:before{content:"\f6ae"}.ti-triangle-off:before{content:"\ef02"}.ti-triangle-square-circle:before{content:"\ece8"}.ti-triangles:before{content:"\f0a5"}.ti-trident:before{content:"\ecc5"}.ti-trolley:before{content:"\f4cc"}.ti-trophy:before{content:"\eb45"}.ti-trophy-filled:before{content:"\f6af"}.ti-trophy-off:before{content:"\f438"}.ti-trowel:before{content:"\f368"}.ti-truck:before{content:"\ebc4"}.ti-truck-delivery:before{content:"\ec4b"}.ti-truck-loading:before{content:"\f1da"}.ti-truck-off:before{content:"\ef03"}.ti-truck-return:before{content:"\ec4c"}.ti-txt:before{content:"\f3b1"}.ti-typography:before{content:"\ebc5"}.ti-typography-off:before{content:"\f1ba"}.ti-ufo:before{content:"\f26f"}.ti-ufo-off:before{content:"\f26e"}.ti-umbrella:before{content:"\ebf1"}.ti-umbrella-filled:before{content:"\f6b0"}.ti-umbrella-off:before{content:"\f1bb"}.ti-underline:before{content:"\eba2"}.ti-unlink:before{content:"\eb46"}.ti-upload:before{content:"\eb47"}.ti-urgent:before{content:"\eb48"}.ti-usb:before{content:"\f00c"}.ti-user:before{content:"\eb4d"}.ti-user-bolt:before{content:"\f9d1"}.ti-user-cancel:before{content:"\f9d2"}.ti-user-check:before{content:"\eb49"}.ti-user-circle:before{content:"\ef68"}.ti-user-code:before{content:"\f9d3"}.ti-user-cog:before{content:"\f9d4"}.ti-user-dollar:before{content:"\f9d5"}.ti-user-down:before{content:"\f9d6"}.ti-user-edit:before{content:"\f7cc"}.ti-user-exclamation:before{content:"\ec12"}.ti-user-heart:before{content:"\f7cd"}.ti-user-minus:before{content:"\eb4a"}.ti-user-off:before{content:"\ecf9"}.ti-user-pause:before{content:"\f9d7"}.ti-user-pin:before{content:"\f7ce"}.ti-user-plus:before{content:"\eb4b"}.ti-user-question:before{content:"\f7cf"}.ti-user-search:before{content:"\ef89"}.ti-user-share:before{content:"\f9d8"}.ti-user-shield:before{content:"\f7d0"}.ti-user-star:before{content:"\f7d1"}.ti-user-up:before{content:"\f7d2"}.ti-user-x:before{content:"\eb4c"}.ti-users:before{content:"\ebf2"}.ti-uv-index:before{content:"\f3b2"}.ti-ux-circle:before{content:"\f369"}.ti-vaccine:before{content:"\ef04"}.ti-vaccine-bottle:before{content:"\ef69"}.ti-vaccine-bottle-off:before{content:"\f439"}.ti-vaccine-off:before{content:"\f1bc"}.ti-vacuum-cleaner:before{content:"\f5e6"}.ti-variable:before{content:"\ef05"}.ti-variable-minus:before{content:"\f36a"}.ti-variable-off:before{content:"\f1bd"}.ti-variable-plus:before{content:"\f36b"}.ti-vector:before{content:"\eca9"}.ti-vector-bezier:before{content:"\ef1d"}.ti-vector-bezier-2:before{content:"\f1a3"}.ti-vector-bezier-arc:before{content:"\f4cd"}.ti-vector-bezier-circle:before{content:"\f4ce"}.ti-vector-off:before{content:"\f1be"}.ti-vector-spline:before{content:"\f565"}.ti-vector-triangle:before{content:"\eca8"}.ti-vector-triangle-off:before{content:"\f1bf"}.ti-venus:before{content:"\ec86"}.ti-versions:before{content:"\ed52"}.ti-versions-filled:before{content:"\f6b1"}.ti-versions-off:before{content:"\f1c0"}.ti-video:before{content:"\ed22"}.ti-video-minus:before{content:"\ed1f"}.ti-video-off:before{content:"\ed20"}.ti-video-plus:before{content:"\ed21"}.ti-view-360:before{content:"\ed84"}.ti-view-360-off:before{content:"\f1c1"}.ti-viewfinder:before{content:"\eb4e"}.ti-viewfinder-off:before{content:"\f1c2"}.ti-viewport-narrow:before{content:"\ebf3"}.ti-viewport-wide:before{content:"\ebf4"}.ti-vinyl:before{content:"\f00d"}.ti-vip:before{content:"\f3b3"}.ti-vip-off:before{content:"\f43a"}.ti-virus:before{content:"\eb74"}.ti-virus-off:before{content:"\ed66"}.ti-virus-search:before{content:"\ed67"}.ti-vocabulary:before{content:"\ef1e"}.ti-vocabulary-off:before{content:"\f43b"}.ti-volcano:before{content:"\f79c"}.ti-volume:before{content:"\eb51"}.ti-volume-2:before{content:"\eb4f"}.ti-volume-3:before{content:"\eb50"}.ti-volume-off:before{content:"\f1c3"}.ti-walk:before{content:"\ec87"}.ti-wall:before{content:"\ef7a"}.ti-wall-off:before{content:"\f43c"}.ti-wallet:before{content:"\eb75"}.ti-wallet-off:before{content:"\f1c4"}.ti-wallpaper:before{content:"\ef56"}.ti-wallpaper-off:before{content:"\f1c5"}.ti-wand:before{content:"\ebcb"}.ti-wand-off:before{content:"\f1c6"}.ti-wash:before{content:"\f311"}.ti-wash-dry:before{content:"\f304"}.ti-wash-dry-1:before{content:"\f2fa"}.ti-wash-dry-2:before{content:"\f2fb"}.ti-wash-dry-3:before{content:"\f2fc"}.ti-wash-dry-a:before{content:"\f2fd"}.ti-wash-dry-dip:before{content:"\f2fe"}.ti-wash-dry-f:before{content:"\f2ff"}.ti-wash-dry-hang:before{content:"\f300"}.ti-wash-dry-off:before{content:"\f301"}.ti-wash-dry-p:before{content:"\f302"}.ti-wash-dry-shade:before{content:"\f303"}.ti-wash-dry-w:before{content:"\f322"}.ti-wash-dryclean:before{content:"\f305"}.ti-wash-dryclean-off:before{content:"\f323"}.ti-wash-gentle:before{content:"\f306"}.ti-wash-machine:before{content:"\f25e"}.ti-wash-off:before{content:"\f307"}.ti-wash-press:before{content:"\f308"}.ti-wash-temperature-1:before{content:"\f309"}.ti-wash-temperature-2:before{content:"\f30a"}.ti-wash-temperature-3:before{content:"\f30b"}.ti-wash-temperature-4:before{content:"\f30c"}.ti-wash-temperature-5:before{content:"\f30d"}.ti-wash-temperature-6:before{content:"\f30e"}.ti-wash-tumble-dry:before{content:"\f30f"}.ti-wash-tumble-off:before{content:"\f310"}.ti-wave-saw-tool:before{content:"\ecd3"}.ti-wave-sine:before{content:"\ecd4"}.ti-wave-square:before{content:"\ecd5"}.ti-webhook:before{content:"\f01e"}.ti-webhook-off:before{content:"\f43d"}.ti-weight:before{content:"\f589"}.ti-wheelchair:before{content:"\f1db"}.ti-wheelchair-off:before{content:"\f43e"}.ti-whirl:before{content:"\f51d"}.ti-wifi:before{content:"\eb52"}.ti-wifi-0:before{content:"\eba3"}.ti-wifi-1:before{content:"\eba4"}.ti-wifi-2:before{content:"\eba5"}.ti-wifi-off:before{content:"\ecfa"}.ti-wind:before{content:"\ec34"}.ti-wind-off:before{content:"\f1c7"}.ti-windmill:before{content:"\ed85"}.ti-windmill-filled:before{content:"\f6b2"}.ti-windmill-off:before{content:"\f1c8"}.ti-window:before{content:"\ef06"}.ti-window-maximize:before{content:"\f1f1"}.ti-window-minimize:before{content:"\f1f2"}.ti-window-off:before{content:"\f1c9"}.ti-windsock:before{content:"\f06d"}.ti-wiper:before{content:"\ecab"}.ti-wiper-wash:before{content:"\ecaa"}.ti-woman:before{content:"\eb53"}.ti-wood:before{content:"\f359"}.ti-world:before{content:"\eb54"}.ti-world-bolt:before{content:"\f9d9"}.ti-world-cancel:before{content:"\f9da"}.ti-world-check:before{content:"\f9db"}.ti-world-code:before{content:"\f9dc"}.ti-world-cog:before{content:"\f9dd"}.ti-world-dollar:before{content:"\f9de"}.ti-world-down:before{content:"\f9df"}.ti-world-download:before{content:"\ef8a"}.ti-world-exclamation:before{content:"\f9e0"}.ti-world-heart:before{content:"\f9e1"}.ti-world-latitude:before{content:"\ed2e"}.ti-world-longitude:before{content:"\ed2f"}.ti-world-minus:before{content:"\f9e2"}.ti-world-off:before{content:"\f1ca"}.ti-world-pause:before{content:"\f9e3"}.ti-world-pin:before{content:"\f9e4"}.ti-world-plus:before{content:"\f9e5"}.ti-world-question:before{content:"\f9e6"}.ti-world-search:before{content:"\f9e7"}.ti-world-share:before{content:"\f9e8"}.ti-world-star:before{content:"\f9e9"}.ti-world-up:before{content:"\f9ea"}.ti-world-upload:before{content:"\ef8b"}.ti-world-www:before{content:"\f38f"}.ti-world-x:before{content:"\f9eb"}.ti-wrecking-ball:before{content:"\ed97"}.ti-writing:before{content:"\ef08"}.ti-writing-off:before{content:"\f1cb"}.ti-writing-sign:before{content:"\ef07"}.ti-writing-sign-off:before{content:"\f1cc"}.ti-x:before{content:"\eb55"}.ti-xbox-a:before{content:"\f2b6"}.ti-xbox-b:before{content:"\f2b7"}.ti-xbox-x:before{content:"\f2b8"}.ti-xbox-y:before{content:"\f2b9"}.ti-yin-yang:before{content:"\ec35"}.ti-yin-yang-filled:before{content:"\f785"}.ti-yoga:before{content:"\f01f"}.ti-zeppelin:before{content:"\f270"}.ti-zeppelin-off:before{content:"\f43f"}.ti-zip:before{content:"\f3b4"}.ti-zodiac-aquarius:before{content:"\ecac"}.ti-zodiac-aries:before{content:"\ecad"}.ti-zodiac-cancer:before{content:"\ecae"}.ti-zodiac-capricorn:before{content:"\ecaf"}.ti-zodiac-gemini:before{content:"\ecb0"}.ti-zodiac-leo:before{content:"\ecb1"}.ti-zodiac-libra:before{content:"\ecb2"}.ti-zodiac-pisces:before{content:"\ecb3"}.ti-zodiac-sagittarius:before{content:"\ecb4"}.ti-zodiac-scorpio:before{content:"\ecb5"}.ti-zodiac-taurus:before{content:"\ecb6"}.ti-zodiac-virgo:before{content:"\ecb7"}.ti-zoom-cancel:before{content:"\ec4d"}.ti-zoom-check:before{content:"\ef09"}.ti-zoom-check-filled:before{content:"\f786"}.ti-zoom-code:before{content:"\f07f"}.ti-zoom-exclamation:before{content:"\f080"}.ti-zoom-filled:before{content:"\f787"}.ti-zoom-in:before{content:"\eb56"}.ti-zoom-in-area:before{content:"\f1dc"}.ti-zoom-in-area-filled:before{content:"\f788"}.ti-zoom-in-filled:before{content:"\f789"}.ti-zoom-money:before{content:"\ef0a"}.ti-zoom-out:before{content:"\eb57"}.ti-zoom-out-area:before{content:"\f1dd"}.ti-zoom-out-filled:before{content:"\f78a"}.ti-zoom-pan:before{content:"\f1de"}.ti-zoom-question:before{content:"\edeb"}.ti-zoom-replace:before{content:"\f2a7"}.ti-zoom-reset:before{content:"\f295"}.ti-zzz:before{content:"\f228"}.ti-zzz-off:before{content:"\f440"}/*# sourceMappingURL=tabler-icons.min.css.map */ diff --git a/playground/fonts/tabler-icons/tabler-icons.scss b/playground/fonts/tabler-icons/tabler-icons.scss new file mode 100644 index 00000000000000..f1d8511a8ba068 --- /dev/null +++ b/playground/fonts/tabler-icons/tabler-icons.scss @@ -0,0 +1,8094 @@ +/*! + * Tabler Icons 2.11.0 by tabler - https://tabler.io + * License - https://github.com/tabler/tabler-icons/blob/master/LICENSE + */ +$ti-font-family: 'tabler-icons' !default; +$ti-font-path: './fonts' !default; +$ti-font-display: null !default; +$ti-prefix: 'ti' !default; + +@font-face { + font-family: $ti-font-family; + font-style: normal; + font-weight: 400; + font-display: $ti-font-display; + src: url('#{$ti-font-path}/tabler-icons.eot?v2.11.0'); + src: url('#{$ti-font-path}/tabler-icons.eot?#iefix-v2.11.0') format('embedded-opentype'), + url('#{$ti-font-path}/tabler-icons.woff2?v2.11.0') format('woff2'), + url('#{$ti-font-path}/tabler-icons.woff?') format('woff'), + url('#{$ti-font-path}/tabler-icons.ttf?v2.11.0') format('truetype'); +} + +.#{$ti-prefix} { + font-family: $ti-font-family !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +@function unicode($str) { + @return unquote("\"")+unquote(str-insert($str, "\\", 1))+unquote("\"") +} + + +$ti-icon-123: unicode('f554'); +$ti-icon-24-hours: unicode('f5e7'); +$ti-icon-2fa: unicode('eca0'); +$ti-icon-360: unicode('f62f'); +$ti-icon-360-view: unicode('f566'); +$ti-icon-3d-cube-sphere: unicode('ecd7'); +$ti-icon-3d-cube-sphere-off: unicode('f3b5'); +$ti-icon-3d-rotate: unicode('f020'); +$ti-icon-a-b: unicode('ec36'); +$ti-icon-a-b-2: unicode('f25f'); +$ti-icon-a-b-off: unicode('f0a6'); +$ti-icon-abacus: unicode('f05c'); +$ti-icon-abacus-off: unicode('f3b6'); +$ti-icon-abc: unicode('f567'); +$ti-icon-access-point: unicode('ed1b'); +$ti-icon-access-point-off: unicode('ed1a'); +$ti-icon-accessible: unicode('eba9'); +$ti-icon-accessible-off: unicode('f0a7'); +$ti-icon-accessible-off-filled: unicode('f6ea'); +$ti-icon-activity: unicode('ed23'); +$ti-icon-activity-heartbeat: unicode('f0db'); +$ti-icon-ad: unicode('ea02'); +$ti-icon-ad-2: unicode('ef1f'); +$ti-icon-ad-circle: unicode('f79e'); +$ti-icon-ad-circle-filled: unicode('f7d3'); +$ti-icon-ad-circle-off: unicode('f79d'); +$ti-icon-ad-filled: unicode('f6eb'); +$ti-icon-ad-off: unicode('f3b7'); +$ti-icon-address-book: unicode('f021'); +$ti-icon-address-book-off: unicode('f3b8'); +$ti-icon-adjustments: unicode('ea03'); +$ti-icon-adjustments-alt: unicode('ec37'); +$ti-icon-adjustments-bolt: unicode('f7fb'); +$ti-icon-adjustments-cancel: unicode('f7fc'); +$ti-icon-adjustments-check: unicode('f7fd'); +$ti-icon-adjustments-code: unicode('f7fe'); +$ti-icon-adjustments-cog: unicode('f7ff'); +$ti-icon-adjustments-dollar: unicode('f800'); +$ti-icon-adjustments-down: unicode('f801'); +$ti-icon-adjustments-exclamation: unicode('f802'); +$ti-icon-adjustments-filled: unicode('f6ec'); +$ti-icon-adjustments-heart: unicode('f803'); +$ti-icon-adjustments-horizontal: unicode('ec38'); +$ti-icon-adjustments-minus: unicode('f804'); +$ti-icon-adjustments-off: unicode('f0a8'); +$ti-icon-adjustments-pause: unicode('f805'); +$ti-icon-adjustments-pin: unicode('f806'); +$ti-icon-adjustments-plus: unicode('f807'); +$ti-icon-adjustments-question: unicode('f808'); +$ti-icon-adjustments-search: unicode('f809'); +$ti-icon-adjustments-share: unicode('f80a'); +$ti-icon-adjustments-star: unicode('f80b'); +$ti-icon-adjustments-up: unicode('f80c'); +$ti-icon-adjustments-x: unicode('f80d'); +$ti-icon-aerial-lift: unicode('edfe'); +$ti-icon-affiliate: unicode('edff'); +$ti-icon-affiliate-filled: unicode('f6ed'); +$ti-icon-air-balloon: unicode('f4a6'); +$ti-icon-air-conditioning: unicode('f3a2'); +$ti-icon-air-conditioning-disabled: unicode('f542'); +$ti-icon-alarm: unicode('ea04'); +$ti-icon-alarm-filled: unicode('f709'); +$ti-icon-alarm-minus: unicode('f630'); +$ti-icon-alarm-minus-filled: unicode('f70a'); +$ti-icon-alarm-off: unicode('f0a9'); +$ti-icon-alarm-plus: unicode('f631'); +$ti-icon-alarm-plus-filled: unicode('f70b'); +$ti-icon-alarm-snooze: unicode('f632'); +$ti-icon-alarm-snooze-filled: unicode('f70c'); +$ti-icon-album: unicode('f022'); +$ti-icon-album-off: unicode('f3b9'); +$ti-icon-alert-circle: unicode('ea05'); +$ti-icon-alert-circle-filled: unicode('f6ee'); +$ti-icon-alert-hexagon: unicode('f80e'); +$ti-icon-alert-octagon: unicode('ecc6'); +$ti-icon-alert-octagon-filled: unicode('f6ef'); +$ti-icon-alert-small: unicode('f80f'); +$ti-icon-alert-square: unicode('f811'); +$ti-icon-alert-square-rounded: unicode('f810'); +$ti-icon-alert-triangle: unicode('ea06'); +$ti-icon-alert-triangle-filled: unicode('f6f0'); +$ti-icon-alien: unicode('ebde'); +$ti-icon-alien-filled: unicode('f70d'); +$ti-icon-align-box-bottom-center: unicode('f530'); +$ti-icon-align-box-bottom-center-filled: unicode('f70e'); +$ti-icon-align-box-bottom-left: unicode('f531'); +$ti-icon-align-box-bottom-left-filled: unicode('f70f'); +$ti-icon-align-box-bottom-right: unicode('f532'); +$ti-icon-align-box-bottom-right-filled: unicode('f710'); +$ti-icon-align-box-center-middle: unicode('f79f'); +$ti-icon-align-box-center-middle-filled: unicode('f7d4'); +$ti-icon-align-box-left-bottom: unicode('f533'); +$ti-icon-align-box-left-bottom-filled: unicode('f711'); +$ti-icon-align-box-left-middle: unicode('f534'); +$ti-icon-align-box-left-middle-filled: unicode('f712'); +$ti-icon-align-box-left-top: unicode('f535'); +$ti-icon-align-box-left-top-filled: unicode('f713'); +$ti-icon-align-box-right-bottom: unicode('f536'); +$ti-icon-align-box-right-bottom-filled: unicode('f714'); +$ti-icon-align-box-right-middle: unicode('f537'); +$ti-icon-align-box-right-middle-filled: unicode('f7d5'); +$ti-icon-align-box-right-top: unicode('f538'); +$ti-icon-align-box-right-top-filled: unicode('f715'); +$ti-icon-align-box-top-center: unicode('f539'); +$ti-icon-align-box-top-center-filled: unicode('f716'); +$ti-icon-align-box-top-left: unicode('f53a'); +$ti-icon-align-box-top-left-filled: unicode('f717'); +$ti-icon-align-box-top-right: unicode('f53b'); +$ti-icon-align-box-top-right-filled: unicode('f718'); +$ti-icon-align-center: unicode('ea07'); +$ti-icon-align-justified: unicode('ea08'); +$ti-icon-align-left: unicode('ea09'); +$ti-icon-align-right: unicode('ea0a'); +$ti-icon-alpha: unicode('f543'); +$ti-icon-alphabet-cyrillic: unicode('f1df'); +$ti-icon-alphabet-greek: unicode('f1e0'); +$ti-icon-alphabet-latin: unicode('f1e1'); +$ti-icon-ambulance: unicode('ebf5'); +$ti-icon-ampersand: unicode('f229'); +$ti-icon-analyze: unicode('f3a3'); +$ti-icon-analyze-filled: unicode('f719'); +$ti-icon-analyze-off: unicode('f3ba'); +$ti-icon-anchor: unicode('eb76'); +$ti-icon-anchor-off: unicode('f0f7'); +$ti-icon-angle: unicode('ef20'); +$ti-icon-ankh: unicode('f1cd'); +$ti-icon-antenna: unicode('f094'); +$ti-icon-antenna-bars-1: unicode('ecc7'); +$ti-icon-antenna-bars-2: unicode('ecc8'); +$ti-icon-antenna-bars-3: unicode('ecc9'); +$ti-icon-antenna-bars-4: unicode('ecca'); +$ti-icon-antenna-bars-5: unicode('eccb'); +$ti-icon-antenna-bars-off: unicode('f0aa'); +$ti-icon-antenna-off: unicode('f3bb'); +$ti-icon-aperture: unicode('eb58'); +$ti-icon-aperture-off: unicode('f3bc'); +$ti-icon-api: unicode('effd'); +$ti-icon-api-app: unicode('effc'); +$ti-icon-api-app-off: unicode('f0ab'); +$ti-icon-api-off: unicode('f0f8'); +$ti-icon-app-window: unicode('efe6'); +$ti-icon-app-window-filled: unicode('f71a'); +$ti-icon-apple: unicode('ef21'); +$ti-icon-apps: unicode('ebb6'); +$ti-icon-apps-filled: unicode('f6f1'); +$ti-icon-apps-off: unicode('f0ac'); +$ti-icon-archive: unicode('ea0b'); +$ti-icon-archive-off: unicode('f0ad'); +$ti-icon-armchair: unicode('ef9e'); +$ti-icon-armchair-2: unicode('efe7'); +$ti-icon-armchair-2-off: unicode('f3bd'); +$ti-icon-armchair-off: unicode('f3be'); +$ti-icon-arrow-autofit-content: unicode('ef31'); +$ti-icon-arrow-autofit-content-filled: unicode('f6f2'); +$ti-icon-arrow-autofit-down: unicode('ef32'); +$ti-icon-arrow-autofit-height: unicode('ef33'); +$ti-icon-arrow-autofit-left: unicode('ef34'); +$ti-icon-arrow-autofit-right: unicode('ef35'); +$ti-icon-arrow-autofit-up: unicode('ef36'); +$ti-icon-arrow-autofit-width: unicode('ef37'); +$ti-icon-arrow-back: unicode('ea0c'); +$ti-icon-arrow-back-up: unicode('eb77'); +$ti-icon-arrow-back-up-double: unicode('f9ec'); +$ti-icon-arrow-badge-down: unicode('f60b'); +$ti-icon-arrow-badge-down-filled: unicode('f7d6'); +$ti-icon-arrow-badge-left: unicode('f60c'); +$ti-icon-arrow-badge-left-filled: unicode('f7d7'); +$ti-icon-arrow-badge-right: unicode('f60d'); +$ti-icon-arrow-badge-right-filled: unicode('f7d8'); +$ti-icon-arrow-badge-up: unicode('f60e'); +$ti-icon-arrow-badge-up-filled: unicode('f7d9'); +$ti-icon-arrow-bar-down: unicode('ea0d'); +$ti-icon-arrow-bar-left: unicode('ea0e'); +$ti-icon-arrow-bar-right: unicode('ea0f'); +$ti-icon-arrow-bar-to-down: unicode('ec88'); +$ti-icon-arrow-bar-to-left: unicode('ec89'); +$ti-icon-arrow-bar-to-right: unicode('ec8a'); +$ti-icon-arrow-bar-to-up: unicode('ec8b'); +$ti-icon-arrow-bar-up: unicode('ea10'); +$ti-icon-arrow-bear-left: unicode('f045'); +$ti-icon-arrow-bear-left-2: unicode('f044'); +$ti-icon-arrow-bear-right: unicode('f047'); +$ti-icon-arrow-bear-right-2: unicode('f046'); +$ti-icon-arrow-big-down: unicode('edda'); +$ti-icon-arrow-big-down-filled: unicode('f6c6'); +$ti-icon-arrow-big-down-line: unicode('efe8'); +$ti-icon-arrow-big-down-line-filled: unicode('f6c7'); +$ti-icon-arrow-big-down-lines: unicode('efe9'); +$ti-icon-arrow-big-down-lines-filled: unicode('f6c8'); +$ti-icon-arrow-big-left: unicode('eddb'); +$ti-icon-arrow-big-left-filled: unicode('f6c9'); +$ti-icon-arrow-big-left-line: unicode('efea'); +$ti-icon-arrow-big-left-line-filled: unicode('f6ca'); +$ti-icon-arrow-big-left-lines: unicode('efeb'); +$ti-icon-arrow-big-left-lines-filled: unicode('f6cb'); +$ti-icon-arrow-big-right: unicode('eddc'); +$ti-icon-arrow-big-right-filled: unicode('f6cc'); +$ti-icon-arrow-big-right-line: unicode('efec'); +$ti-icon-arrow-big-right-line-filled: unicode('f6cd'); +$ti-icon-arrow-big-right-lines: unicode('efed'); +$ti-icon-arrow-big-right-lines-filled: unicode('f6ce'); +$ti-icon-arrow-big-up: unicode('eddd'); +$ti-icon-arrow-big-up-filled: unicode('f6cf'); +$ti-icon-arrow-big-up-line: unicode('efee'); +$ti-icon-arrow-big-up-line-filled: unicode('f6d0'); +$ti-icon-arrow-big-up-lines: unicode('efef'); +$ti-icon-arrow-big-up-lines-filled: unicode('f6d1'); +$ti-icon-arrow-bounce: unicode('f3a4'); +$ti-icon-arrow-curve-left: unicode('f048'); +$ti-icon-arrow-curve-right: unicode('f049'); +$ti-icon-arrow-down: unicode('ea16'); +$ti-icon-arrow-down-bar: unicode('ed98'); +$ti-icon-arrow-down-circle: unicode('ea11'); +$ti-icon-arrow-down-left: unicode('ea13'); +$ti-icon-arrow-down-left-circle: unicode('ea12'); +$ti-icon-arrow-down-rhombus: unicode('f61d'); +$ti-icon-arrow-down-right: unicode('ea15'); +$ti-icon-arrow-down-right-circle: unicode('ea14'); +$ti-icon-arrow-down-square: unicode('ed9a'); +$ti-icon-arrow-down-tail: unicode('ed9b'); +$ti-icon-arrow-elbow-left: unicode('f9ed'); +$ti-icon-arrow-elbow-right: unicode('f9ee'); +$ti-icon-arrow-fork: unicode('f04a'); +$ti-icon-arrow-forward: unicode('ea17'); +$ti-icon-arrow-forward-up: unicode('eb78'); +$ti-icon-arrow-forward-up-double: unicode('f9ef'); +$ti-icon-arrow-guide: unicode('f22a'); +$ti-icon-arrow-iteration: unicode('f578'); +$ti-icon-arrow-left: unicode('ea19'); +$ti-icon-arrow-left-bar: unicode('ed9c'); +$ti-icon-arrow-left-circle: unicode('ea18'); +$ti-icon-arrow-left-rhombus: unicode('f61e'); +$ti-icon-arrow-left-right: unicode('f04b'); +$ti-icon-arrow-left-square: unicode('ed9d'); +$ti-icon-arrow-left-tail: unicode('ed9e'); +$ti-icon-arrow-loop-left: unicode('ed9f'); +$ti-icon-arrow-loop-left-2: unicode('f04c'); +$ti-icon-arrow-loop-right: unicode('eda0'); +$ti-icon-arrow-loop-right-2: unicode('f04d'); +$ti-icon-arrow-merge: unicode('f04e'); +$ti-icon-arrow-merge-both: unicode('f23b'); +$ti-icon-arrow-merge-left: unicode('f23c'); +$ti-icon-arrow-merge-right: unicode('f23d'); +$ti-icon-arrow-move-down: unicode('f2ba'); +$ti-icon-arrow-move-left: unicode('f2bb'); +$ti-icon-arrow-move-right: unicode('f2bc'); +$ti-icon-arrow-move-up: unicode('f2bd'); +$ti-icon-arrow-narrow-down: unicode('ea1a'); +$ti-icon-arrow-narrow-left: unicode('ea1b'); +$ti-icon-arrow-narrow-right: unicode('ea1c'); +$ti-icon-arrow-narrow-up: unicode('ea1d'); +$ti-icon-arrow-ramp-left: unicode('ed3c'); +$ti-icon-arrow-ramp-left-2: unicode('f04f'); +$ti-icon-arrow-ramp-left-3: unicode('f050'); +$ti-icon-arrow-ramp-right: unicode('ed3d'); +$ti-icon-arrow-ramp-right-2: unicode('f051'); +$ti-icon-arrow-ramp-right-3: unicode('f052'); +$ti-icon-arrow-right: unicode('ea1f'); +$ti-icon-arrow-right-bar: unicode('eda1'); +$ti-icon-arrow-right-circle: unicode('ea1e'); +$ti-icon-arrow-right-rhombus: unicode('f61f'); +$ti-icon-arrow-right-square: unicode('eda2'); +$ti-icon-arrow-right-tail: unicode('eda3'); +$ti-icon-arrow-rotary-first-left: unicode('f053'); +$ti-icon-arrow-rotary-first-right: unicode('f054'); +$ti-icon-arrow-rotary-last-left: unicode('f055'); +$ti-icon-arrow-rotary-last-right: unicode('f056'); +$ti-icon-arrow-rotary-left: unicode('f057'); +$ti-icon-arrow-rotary-right: unicode('f058'); +$ti-icon-arrow-rotary-straight: unicode('f059'); +$ti-icon-arrow-roundabout-left: unicode('f22b'); +$ti-icon-arrow-roundabout-right: unicode('f22c'); +$ti-icon-arrow-sharp-turn-left: unicode('f05a'); +$ti-icon-arrow-sharp-turn-right: unicode('f05b'); +$ti-icon-arrow-up: unicode('ea25'); +$ti-icon-arrow-up-bar: unicode('eda4'); +$ti-icon-arrow-up-circle: unicode('ea20'); +$ti-icon-arrow-up-left: unicode('ea22'); +$ti-icon-arrow-up-left-circle: unicode('ea21'); +$ti-icon-arrow-up-rhombus: unicode('f620'); +$ti-icon-arrow-up-right: unicode('ea24'); +$ti-icon-arrow-up-right-circle: unicode('ea23'); +$ti-icon-arrow-up-square: unicode('eda6'); +$ti-icon-arrow-up-tail: unicode('eda7'); +$ti-icon-arrow-wave-left-down: unicode('eda8'); +$ti-icon-arrow-wave-left-up: unicode('eda9'); +$ti-icon-arrow-wave-right-down: unicode('edaa'); +$ti-icon-arrow-wave-right-up: unicode('edab'); +$ti-icon-arrow-zig-zag: unicode('f4a7'); +$ti-icon-arrows-cross: unicode('effe'); +$ti-icon-arrows-diagonal: unicode('ea27'); +$ti-icon-arrows-diagonal-2: unicode('ea26'); +$ti-icon-arrows-diagonal-minimize: unicode('ef39'); +$ti-icon-arrows-diagonal-minimize-2: unicode('ef38'); +$ti-icon-arrows-diff: unicode('f296'); +$ti-icon-arrows-double-ne-sw: unicode('edde'); +$ti-icon-arrows-double-nw-se: unicode('eddf'); +$ti-icon-arrows-double-se-nw: unicode('ede0'); +$ti-icon-arrows-double-sw-ne: unicode('ede1'); +$ti-icon-arrows-down: unicode('edad'); +$ti-icon-arrows-down-up: unicode('edac'); +$ti-icon-arrows-exchange: unicode('f1f4'); +$ti-icon-arrows-exchange-2: unicode('f1f3'); +$ti-icon-arrows-horizontal: unicode('eb59'); +$ti-icon-arrows-join: unicode('edaf'); +$ti-icon-arrows-join-2: unicode('edae'); +$ti-icon-arrows-left: unicode('edb1'); +$ti-icon-arrows-left-down: unicode('ee00'); +$ti-icon-arrows-left-right: unicode('edb0'); +$ti-icon-arrows-maximize: unicode('ea28'); +$ti-icon-arrows-minimize: unicode('ea29'); +$ti-icon-arrows-move: unicode('f22f'); +$ti-icon-arrows-move-horizontal: unicode('f22d'); +$ti-icon-arrows-move-vertical: unicode('f22e'); +$ti-icon-arrows-random: unicode('f095'); +$ti-icon-arrows-right: unicode('edb3'); +$ti-icon-arrows-right-down: unicode('ee01'); +$ti-icon-arrows-right-left: unicode('edb2'); +$ti-icon-arrows-shuffle: unicode('f000'); +$ti-icon-arrows-shuffle-2: unicode('efff'); +$ti-icon-arrows-sort: unicode('eb5a'); +$ti-icon-arrows-split: unicode('edb5'); +$ti-icon-arrows-split-2: unicode('edb4'); +$ti-icon-arrows-transfer-down: unicode('f2cc'); +$ti-icon-arrows-transfer-up: unicode('f2cd'); +$ti-icon-arrows-up: unicode('edb7'); +$ti-icon-arrows-up-down: unicode('edb6'); +$ti-icon-arrows-up-left: unicode('ee02'); +$ti-icon-arrows-up-right: unicode('ee03'); +$ti-icon-arrows-vertical: unicode('eb5b'); +$ti-icon-artboard: unicode('ea2a'); +$ti-icon-artboard-off: unicode('f0ae'); +$ti-icon-article: unicode('f1e2'); +$ti-icon-article-filled-filled: unicode('f7da'); +$ti-icon-article-off: unicode('f3bf'); +$ti-icon-aspect-ratio: unicode('ed30'); +$ti-icon-aspect-ratio-filled: unicode('f7db'); +$ti-icon-aspect-ratio-off: unicode('f0af'); +$ti-icon-assembly: unicode('f24d'); +$ti-icon-assembly-off: unicode('f3c0'); +$ti-icon-asset: unicode('f1ce'); +$ti-icon-asterisk: unicode('efd5'); +$ti-icon-asterisk-simple: unicode('efd4'); +$ti-icon-at: unicode('ea2b'); +$ti-icon-at-off: unicode('f0b0'); +$ti-icon-atom: unicode('eb79'); +$ti-icon-atom-2: unicode('ebdf'); +$ti-icon-atom-2-filled: unicode('f71b'); +$ti-icon-atom-off: unicode('f0f9'); +$ti-icon-augmented-reality: unicode('f023'); +$ti-icon-augmented-reality-2: unicode('f37e'); +$ti-icon-augmented-reality-off: unicode('f3c1'); +$ti-icon-award: unicode('ea2c'); +$ti-icon-award-filled: unicode('f71c'); +$ti-icon-award-off: unicode('f0fa'); +$ti-icon-axe: unicode('ef9f'); +$ti-icon-axis-x: unicode('ef45'); +$ti-icon-axis-y: unicode('ef46'); +$ti-icon-baby-bottle: unicode('f5d2'); +$ti-icon-baby-carriage: unicode('f05d'); +$ti-icon-backhoe: unicode('ed86'); +$ti-icon-backpack: unicode('ef47'); +$ti-icon-backpack-off: unicode('f3c2'); +$ti-icon-backspace: unicode('ea2d'); +$ti-icon-backspace-filled: unicode('f7dc'); +$ti-icon-badge: unicode('efc2'); +$ti-icon-badge-3d: unicode('f555'); +$ti-icon-badge-4k: unicode('f556'); +$ti-icon-badge-8k: unicode('f557'); +$ti-icon-badge-ad: unicode('f558'); +$ti-icon-badge-ar: unicode('f559'); +$ti-icon-badge-cc: unicode('f55a'); +$ti-icon-badge-filled: unicode('f667'); +$ti-icon-badge-hd: unicode('f55b'); +$ti-icon-badge-off: unicode('f0fb'); +$ti-icon-badge-sd: unicode('f55c'); +$ti-icon-badge-tm: unicode('f55d'); +$ti-icon-badge-vo: unicode('f55e'); +$ti-icon-badge-vr: unicode('f55f'); +$ti-icon-badge-wc: unicode('f560'); +$ti-icon-badges: unicode('efc3'); +$ti-icon-badges-filled: unicode('f7dd'); +$ti-icon-badges-off: unicode('f0fc'); +$ti-icon-baguette: unicode('f3a5'); +$ti-icon-ball-american-football: unicode('ee04'); +$ti-icon-ball-american-football-off: unicode('f3c3'); +$ti-icon-ball-baseball: unicode('efa0'); +$ti-icon-ball-basketball: unicode('ec28'); +$ti-icon-ball-bowling: unicode('ec29'); +$ti-icon-ball-football: unicode('ee06'); +$ti-icon-ball-football-off: unicode('ee05'); +$ti-icon-ball-tennis: unicode('ec2a'); +$ti-icon-ball-volleyball: unicode('ec2b'); +$ti-icon-balloon: unicode('ef3a'); +$ti-icon-balloon-off: unicode('f0fd'); +$ti-icon-ballpen: unicode('f06e'); +$ti-icon-ballpen-off: unicode('f0b1'); +$ti-icon-ban: unicode('ea2e'); +$ti-icon-bandage: unicode('eb7a'); +$ti-icon-bandage-filled: unicode('f7de'); +$ti-icon-bandage-off: unicode('f3c4'); +$ti-icon-barbell: unicode('eff0'); +$ti-icon-barbell-off: unicode('f0b2'); +$ti-icon-barcode: unicode('ebc6'); +$ti-icon-barcode-off: unicode('f0b3'); +$ti-icon-barrel: unicode('f0b4'); +$ti-icon-barrel-off: unicode('f0fe'); +$ti-icon-barrier-block: unicode('f00e'); +$ti-icon-barrier-block-off: unicode('f0b5'); +$ti-icon-baseline: unicode('f024'); +$ti-icon-baseline-density-large: unicode('f9f0'); +$ti-icon-baseline-density-medium: unicode('f9f1'); +$ti-icon-baseline-density-small: unicode('f9f2'); +$ti-icon-basket: unicode('ebe1'); +$ti-icon-basket-filled: unicode('f7df'); +$ti-icon-basket-off: unicode('f0b6'); +$ti-icon-bat: unicode('f284'); +$ti-icon-bath: unicode('ef48'); +$ti-icon-bath-filled: unicode('f71d'); +$ti-icon-bath-off: unicode('f0ff'); +$ti-icon-battery: unicode('ea34'); +$ti-icon-battery-1: unicode('ea2f'); +$ti-icon-battery-1-filled: unicode('f71e'); +$ti-icon-battery-2: unicode('ea30'); +$ti-icon-battery-2-filled: unicode('f71f'); +$ti-icon-battery-3: unicode('ea31'); +$ti-icon-battery-3-filled: unicode('f720'); +$ti-icon-battery-4: unicode('ea32'); +$ti-icon-battery-4-filled: unicode('f721'); +$ti-icon-battery-automotive: unicode('ee07'); +$ti-icon-battery-charging: unicode('ea33'); +$ti-icon-battery-charging-2: unicode('ef3b'); +$ti-icon-battery-eco: unicode('ef3c'); +$ti-icon-battery-filled: unicode('f668'); +$ti-icon-battery-off: unicode('ed1c'); +$ti-icon-beach: unicode('ef3d'); +$ti-icon-beach-off: unicode('f0b7'); +$ti-icon-bed: unicode('eb5c'); +$ti-icon-bed-filled: unicode('f7e0'); +$ti-icon-bed-off: unicode('f100'); +$ti-icon-beer: unicode('efa1'); +$ti-icon-beer-filled: unicode('f7e1'); +$ti-icon-beer-off: unicode('f101'); +$ti-icon-bell: unicode('ea35'); +$ti-icon-bell-bolt: unicode('f812'); +$ti-icon-bell-cancel: unicode('f813'); +$ti-icon-bell-check: unicode('f814'); +$ti-icon-bell-code: unicode('f815'); +$ti-icon-bell-cog: unicode('f816'); +$ti-icon-bell-dollar: unicode('f817'); +$ti-icon-bell-down: unicode('f818'); +$ti-icon-bell-exclamation: unicode('f819'); +$ti-icon-bell-filled: unicode('f669'); +$ti-icon-bell-heart: unicode('f81a'); +$ti-icon-bell-minus: unicode('ede2'); +$ti-icon-bell-minus-filled: unicode('f722'); +$ti-icon-bell-off: unicode('ece9'); +$ti-icon-bell-pause: unicode('f81b'); +$ti-icon-bell-pin: unicode('f81c'); +$ti-icon-bell-plus: unicode('ede3'); +$ti-icon-bell-plus-filled: unicode('f723'); +$ti-icon-bell-question: unicode('f81d'); +$ti-icon-bell-ringing: unicode('ed07'); +$ti-icon-bell-ringing-2: unicode('ede4'); +$ti-icon-bell-ringing-2-filled: unicode('f724'); +$ti-icon-bell-ringing-filled: unicode('f725'); +$ti-icon-bell-school: unicode('f05e'); +$ti-icon-bell-search: unicode('f81e'); +$ti-icon-bell-share: unicode('f81f'); +$ti-icon-bell-star: unicode('f820'); +$ti-icon-bell-up: unicode('f821'); +$ti-icon-bell-x: unicode('ede5'); +$ti-icon-bell-x-filled: unicode('f726'); +$ti-icon-bell-z: unicode('eff1'); +$ti-icon-bell-z-filled: unicode('f727'); +$ti-icon-beta: unicode('f544'); +$ti-icon-bible: unicode('efc4'); +$ti-icon-bike: unicode('ea36'); +$ti-icon-bike-off: unicode('f0b8'); +$ti-icon-binary: unicode('ee08'); +$ti-icon-binary-off: unicode('f3c5'); +$ti-icon-binary-tree: unicode('f5d4'); +$ti-icon-binary-tree-2: unicode('f5d3'); +$ti-icon-biohazard: unicode('ecb8'); +$ti-icon-biohazard-off: unicode('f0b9'); +$ti-icon-blade: unicode('f4bd'); +$ti-icon-blade-filled: unicode('f7e2'); +$ti-icon-bleach: unicode('f2f3'); +$ti-icon-bleach-chlorine: unicode('f2f0'); +$ti-icon-bleach-no-chlorine: unicode('f2f1'); +$ti-icon-bleach-off: unicode('f2f2'); +$ti-icon-blockquote: unicode('ee09'); +$ti-icon-bluetooth: unicode('ea37'); +$ti-icon-bluetooth-connected: unicode('ecea'); +$ti-icon-bluetooth-off: unicode('eceb'); +$ti-icon-bluetooth-x: unicode('f081'); +$ti-icon-blur: unicode('ef8c'); +$ti-icon-blur-off: unicode('f3c6'); +$ti-icon-bmp: unicode('f3a6'); +$ti-icon-bold: unicode('eb7b'); +$ti-icon-bold-off: unicode('f0ba'); +$ti-icon-bolt: unicode('ea38'); +$ti-icon-bolt-off: unicode('ecec'); +$ti-icon-bomb: unicode('f59c'); +$ti-icon-bone: unicode('edb8'); +$ti-icon-bone-off: unicode('f0bb'); +$ti-icon-bong: unicode('f3a7'); +$ti-icon-bong-off: unicode('f3c7'); +$ti-icon-book: unicode('ea39'); +$ti-icon-book-2: unicode('efc5'); +$ti-icon-book-download: unicode('f070'); +$ti-icon-book-off: unicode('f0bc'); +$ti-icon-book-upload: unicode('f071'); +$ti-icon-bookmark: unicode('ea3a'); +$ti-icon-bookmark-off: unicode('eced'); +$ti-icon-bookmarks: unicode('ed08'); +$ti-icon-bookmarks-off: unicode('f0bd'); +$ti-icon-books: unicode('eff2'); +$ti-icon-books-off: unicode('f0be'); +$ti-icon-border-all: unicode('ea3b'); +$ti-icon-border-bottom: unicode('ea3c'); +$ti-icon-border-corners: unicode('f7a0'); +$ti-icon-border-horizontal: unicode('ea3d'); +$ti-icon-border-inner: unicode('ea3e'); +$ti-icon-border-left: unicode('ea3f'); +$ti-icon-border-none: unicode('ea40'); +$ti-icon-border-outer: unicode('ea41'); +$ti-icon-border-radius: unicode('eb7c'); +$ti-icon-border-right: unicode('ea42'); +$ti-icon-border-sides: unicode('f7a1'); +$ti-icon-border-style: unicode('ee0a'); +$ti-icon-border-style-2: unicode('ef22'); +$ti-icon-border-top: unicode('ea43'); +$ti-icon-border-vertical: unicode('ea44'); +$ti-icon-bottle: unicode('ef0b'); +$ti-icon-bottle-off: unicode('f3c8'); +$ti-icon-bounce-left: unicode('f59d'); +$ti-icon-bounce-right: unicode('f59e'); +$ti-icon-bow: unicode('f096'); +$ti-icon-bowl: unicode('f4fa'); +$ti-icon-box: unicode('ea45'); +$ti-icon-box-align-bottom: unicode('f2a8'); +$ti-icon-box-align-bottom-left: unicode('f2ce'); +$ti-icon-box-align-bottom-right: unicode('f2cf'); +$ti-icon-box-align-left: unicode('f2a9'); +$ti-icon-box-align-right: unicode('f2aa'); +$ti-icon-box-align-top: unicode('f2ab'); +$ti-icon-box-align-top-left: unicode('f2d0'); +$ti-icon-box-align-top-right: unicode('f2d1'); +$ti-icon-box-margin: unicode('ee0b'); +$ti-icon-box-model: unicode('ee0c'); +$ti-icon-box-model-2: unicode('ef23'); +$ti-icon-box-model-2-off: unicode('f3c9'); +$ti-icon-box-model-off: unicode('f3ca'); +$ti-icon-box-multiple: unicode('ee17'); +$ti-icon-box-multiple-0: unicode('ee0d'); +$ti-icon-box-multiple-1: unicode('ee0e'); +$ti-icon-box-multiple-2: unicode('ee0f'); +$ti-icon-box-multiple-3: unicode('ee10'); +$ti-icon-box-multiple-4: unicode('ee11'); +$ti-icon-box-multiple-5: unicode('ee12'); +$ti-icon-box-multiple-6: unicode('ee13'); +$ti-icon-box-multiple-7: unicode('ee14'); +$ti-icon-box-multiple-8: unicode('ee15'); +$ti-icon-box-multiple-9: unicode('ee16'); +$ti-icon-box-off: unicode('f102'); +$ti-icon-box-padding: unicode('ee18'); +$ti-icon-box-seam: unicode('f561'); +$ti-icon-braces: unicode('ebcc'); +$ti-icon-braces-off: unicode('f0bf'); +$ti-icon-brackets: unicode('ebcd'); +$ti-icon-brackets-contain: unicode('f1e5'); +$ti-icon-brackets-contain-end: unicode('f1e3'); +$ti-icon-brackets-contain-start: unicode('f1e4'); +$ti-icon-brackets-off: unicode('f0c0'); +$ti-icon-braille: unicode('f545'); +$ti-icon-brain: unicode('f59f'); +$ti-icon-brand-4chan: unicode('f494'); +$ti-icon-brand-abstract: unicode('f495'); +$ti-icon-brand-adobe: unicode('f0dc'); +$ti-icon-brand-adonis-js: unicode('f496'); +$ti-icon-brand-airbnb: unicode('ed68'); +$ti-icon-brand-airtable: unicode('ef6a'); +$ti-icon-brand-algolia: unicode('f390'); +$ti-icon-brand-alipay: unicode('f7a2'); +$ti-icon-brand-alpine-js: unicode('f324'); +$ti-icon-brand-amazon: unicode('f230'); +$ti-icon-brand-amd: unicode('f653'); +$ti-icon-brand-amigo: unicode('f5f9'); +$ti-icon-brand-among-us: unicode('f205'); +$ti-icon-brand-android: unicode('ec16'); +$ti-icon-brand-angular: unicode('ef6b'); +$ti-icon-brand-ao3: unicode('f5e8'); +$ti-icon-brand-appgallery: unicode('f231'); +$ti-icon-brand-apple: unicode('ec17'); +$ti-icon-brand-apple-arcade: unicode('ed69'); +$ti-icon-brand-apple-podcast: unicode('f1e6'); +$ti-icon-brand-appstore: unicode('ed24'); +$ti-icon-brand-asana: unicode('edc5'); +$ti-icon-brand-backbone: unicode('f325'); +$ti-icon-brand-badoo: unicode('f206'); +$ti-icon-brand-baidu: unicode('f5e9'); +$ti-icon-brand-bandcamp: unicode('f207'); +$ti-icon-brand-bandlab: unicode('f5fa'); +$ti-icon-brand-beats: unicode('f208'); +$ti-icon-brand-behance: unicode('ec6e'); +$ti-icon-brand-bilibili: unicode('f6d2'); +$ti-icon-brand-binance: unicode('f5a0'); +$ti-icon-brand-bing: unicode('edc6'); +$ti-icon-brand-bitbucket: unicode('edc7'); +$ti-icon-brand-blackberry: unicode('f568'); +$ti-icon-brand-blender: unicode('f326'); +$ti-icon-brand-blogger: unicode('f35a'); +$ti-icon-brand-booking: unicode('edc8'); +$ti-icon-brand-bootstrap: unicode('ef3e'); +$ti-icon-brand-bulma: unicode('f327'); +$ti-icon-brand-bumble: unicode('f5fb'); +$ti-icon-brand-bunpo: unicode('f4cf'); +$ti-icon-brand-c-sharp: unicode('f003'); +$ti-icon-brand-cake: unicode('f7a3'); +$ti-icon-brand-cakephp: unicode('f7af'); +$ti-icon-brand-campaignmonitor: unicode('f328'); +$ti-icon-brand-carbon: unicode('f348'); +$ti-icon-brand-cashapp: unicode('f391'); +$ti-icon-brand-chrome: unicode('ec18'); +$ti-icon-brand-citymapper: unicode('f5fc'); +$ti-icon-brand-codecov: unicode('f329'); +$ti-icon-brand-codepen: unicode('ec6f'); +$ti-icon-brand-codesandbox: unicode('ed6a'); +$ti-icon-brand-cohost: unicode('f5d5'); +$ti-icon-brand-coinbase: unicode('f209'); +$ti-icon-brand-comedy-central: unicode('f217'); +$ti-icon-brand-coreos: unicode('f5fd'); +$ti-icon-brand-couchdb: unicode('f60f'); +$ti-icon-brand-couchsurfing: unicode('f392'); +$ti-icon-brand-cpp: unicode('f5fe'); +$ti-icon-brand-crunchbase: unicode('f7e3'); +$ti-icon-brand-css3: unicode('ed6b'); +$ti-icon-brand-ctemplar: unicode('f4d0'); +$ti-icon-brand-cucumber: unicode('ef6c'); +$ti-icon-brand-cupra: unicode('f4d1'); +$ti-icon-brand-cypress: unicode('f333'); +$ti-icon-brand-d3: unicode('f24e'); +$ti-icon-brand-days-counter: unicode('f4d2'); +$ti-icon-brand-dcos: unicode('f32a'); +$ti-icon-brand-debian: unicode('ef57'); +$ti-icon-brand-deezer: unicode('f78b'); +$ti-icon-brand-deliveroo: unicode('f4d3'); +$ti-icon-brand-deno: unicode('f24f'); +$ti-icon-brand-denodo: unicode('f610'); +$ti-icon-brand-deviantart: unicode('ecfb'); +$ti-icon-brand-dingtalk: unicode('f5ea'); +$ti-icon-brand-discord: unicode('ece3'); +$ti-icon-brand-discord-filled: unicode('f7e4'); +$ti-icon-brand-disney: unicode('f20a'); +$ti-icon-brand-disqus: unicode('edc9'); +$ti-icon-brand-django: unicode('f349'); +$ti-icon-brand-docker: unicode('edca'); +$ti-icon-brand-doctrine: unicode('ef6d'); +$ti-icon-brand-dolby-digital: unicode('f4d4'); +$ti-icon-brand-douban: unicode('f5ff'); +$ti-icon-brand-dribbble: unicode('ec19'); +$ti-icon-brand-dribbble-filled: unicode('f7e5'); +$ti-icon-brand-drops: unicode('f4d5'); +$ti-icon-brand-drupal: unicode('f393'); +$ti-icon-brand-edge: unicode('ecfc'); +$ti-icon-brand-elastic: unicode('f611'); +$ti-icon-brand-ember: unicode('f497'); +$ti-icon-brand-envato: unicode('f394'); +$ti-icon-brand-etsy: unicode('f654'); +$ti-icon-brand-evernote: unicode('f600'); +$ti-icon-brand-facebook: unicode('ec1a'); +$ti-icon-brand-facebook-filled: unicode('f7e6'); +$ti-icon-brand-figma: unicode('ec93'); +$ti-icon-brand-finder: unicode('f218'); +$ti-icon-brand-firebase: unicode('ef6e'); +$ti-icon-brand-firefox: unicode('ecfd'); +$ti-icon-brand-fiverr: unicode('f7a4'); +$ti-icon-brand-flickr: unicode('ecfe'); +$ti-icon-brand-flightradar24: unicode('f4d6'); +$ti-icon-brand-flipboard: unicode('f20b'); +$ti-icon-brand-flutter: unicode('f395'); +$ti-icon-brand-fortnite: unicode('f260'); +$ti-icon-brand-foursquare: unicode('ecff'); +$ti-icon-brand-framer: unicode('ec1b'); +$ti-icon-brand-framer-motion: unicode('f78c'); +$ti-icon-brand-funimation: unicode('f655'); +$ti-icon-brand-gatsby: unicode('f396'); +$ti-icon-brand-git: unicode('ef6f'); +$ti-icon-brand-github: unicode('ec1c'); +$ti-icon-brand-github-copilot: unicode('f4a8'); +$ti-icon-brand-github-filled: unicode('f7e7'); +$ti-icon-brand-gitlab: unicode('ec1d'); +$ti-icon-brand-gmail: unicode('efa2'); +$ti-icon-brand-golang: unicode('f78d'); +$ti-icon-brand-google: unicode('ec1f'); +$ti-icon-brand-google-analytics: unicode('edcb'); +$ti-icon-brand-google-big-query: unicode('f612'); +$ti-icon-brand-google-drive: unicode('ec1e'); +$ti-icon-brand-google-fit: unicode('f297'); +$ti-icon-brand-google-home: unicode('f601'); +$ti-icon-brand-google-one: unicode('f232'); +$ti-icon-brand-google-photos: unicode('f20c'); +$ti-icon-brand-google-play: unicode('ed25'); +$ti-icon-brand-google-podcasts: unicode('f656'); +$ti-icon-brand-grammarly: unicode('f32b'); +$ti-icon-brand-graphql: unicode('f32c'); +$ti-icon-brand-gravatar: unicode('edcc'); +$ti-icon-brand-grindr: unicode('f20d'); +$ti-icon-brand-guardian: unicode('f4fb'); +$ti-icon-brand-gumroad: unicode('f5d6'); +$ti-icon-brand-hbo: unicode('f657'); +$ti-icon-brand-headlessui: unicode('f32d'); +$ti-icon-brand-hipchat: unicode('edcd'); +$ti-icon-brand-html5: unicode('ed6c'); +$ti-icon-brand-inertia: unicode('f34a'); +$ti-icon-brand-instagram: unicode('ec20'); +$ti-icon-brand-intercom: unicode('f1cf'); +$ti-icon-brand-javascript: unicode('ef0c'); +$ti-icon-brand-juejin: unicode('f7b0'); +$ti-icon-brand-kickstarter: unicode('edce'); +$ti-icon-brand-kotlin: unicode('ed6d'); +$ti-icon-brand-laravel: unicode('f34b'); +$ti-icon-brand-lastfm: unicode('f001'); +$ti-icon-brand-line: unicode('f7e8'); +$ti-icon-brand-linkedin: unicode('ec8c'); +$ti-icon-brand-linktree: unicode('f1e7'); +$ti-icon-brand-linqpad: unicode('f562'); +$ti-icon-brand-loom: unicode('ef70'); +$ti-icon-brand-mailgun: unicode('f32e'); +$ti-icon-brand-mantine: unicode('f32f'); +$ti-icon-brand-mastercard: unicode('ef49'); +$ti-icon-brand-mastodon: unicode('f250'); +$ti-icon-brand-matrix: unicode('f5eb'); +$ti-icon-brand-mcdonalds: unicode('f251'); +$ti-icon-brand-medium: unicode('ec70'); +$ti-icon-brand-mercedes: unicode('f072'); +$ti-icon-brand-messenger: unicode('ec71'); +$ti-icon-brand-meta: unicode('efb0'); +$ti-icon-brand-miniprogram: unicode('f602'); +$ti-icon-brand-mixpanel: unicode('f397'); +$ti-icon-brand-monday: unicode('f219'); +$ti-icon-brand-mongodb: unicode('f613'); +$ti-icon-brand-my-oppo: unicode('f4d7'); +$ti-icon-brand-mysql: unicode('f614'); +$ti-icon-brand-national-geographic: unicode('f603'); +$ti-icon-brand-nem: unicode('f5a1'); +$ti-icon-brand-netbeans: unicode('ef71'); +$ti-icon-brand-netease-music: unicode('f604'); +$ti-icon-brand-netflix: unicode('edcf'); +$ti-icon-brand-nexo: unicode('f5a2'); +$ti-icon-brand-nextcloud: unicode('f4d8'); +$ti-icon-brand-nextjs: unicode('f0dd'); +$ti-icon-brand-nord-vpn: unicode('f37f'); +$ti-icon-brand-notion: unicode('ef7b'); +$ti-icon-brand-npm: unicode('f569'); +$ti-icon-brand-nuxt: unicode('f0de'); +$ti-icon-brand-nytimes: unicode('ef8d'); +$ti-icon-brand-office: unicode('f398'); +$ti-icon-brand-ok-ru: unicode('f399'); +$ti-icon-brand-onedrive: unicode('f5d7'); +$ti-icon-brand-onlyfans: unicode('f605'); +$ti-icon-brand-open-source: unicode('edd0'); +$ti-icon-brand-openai: unicode('f78e'); +$ti-icon-brand-openvpn: unicode('f39a'); +$ti-icon-brand-opera: unicode('ec21'); +$ti-icon-brand-pagekit: unicode('edd1'); +$ti-icon-brand-patreon: unicode('edd2'); +$ti-icon-brand-paypal: unicode('ec22'); +$ti-icon-brand-paypal-filled: unicode('f7e9'); +$ti-icon-brand-paypay: unicode('f5ec'); +$ti-icon-brand-peanut: unicode('f39b'); +$ti-icon-brand-pepsi: unicode('f261'); +$ti-icon-brand-php: unicode('ef72'); +$ti-icon-brand-picsart: unicode('f4d9'); +$ti-icon-brand-pinterest: unicode('ec8d'); +$ti-icon-brand-planetscale: unicode('f78f'); +$ti-icon-brand-pocket: unicode('ed00'); +$ti-icon-brand-polymer: unicode('f498'); +$ti-icon-brand-powershell: unicode('f5ed'); +$ti-icon-brand-prisma: unicode('f499'); +$ti-icon-brand-producthunt: unicode('edd3'); +$ti-icon-brand-pushbullet: unicode('f330'); +$ti-icon-brand-pushover: unicode('f20e'); +$ti-icon-brand-python: unicode('ed01'); +$ti-icon-brand-qq: unicode('f606'); +$ti-icon-brand-radix-ui: unicode('f790'); +$ti-icon-brand-react: unicode('f34c'); +$ti-icon-brand-react-native: unicode('ef73'); +$ti-icon-brand-reason: unicode('f49a'); +$ti-icon-brand-reddit: unicode('ec8e'); +$ti-icon-brand-redhat: unicode('f331'); +$ti-icon-brand-redux: unicode('f3a8'); +$ti-icon-brand-revolut: unicode('f4da'); +$ti-icon-brand-safari: unicode('ec23'); +$ti-icon-brand-samsungpass: unicode('f4db'); +$ti-icon-brand-sass: unicode('edd4'); +$ti-icon-brand-sentry: unicode('edd5'); +$ti-icon-brand-sharik: unicode('f4dc'); +$ti-icon-brand-shazam: unicode('edd6'); +$ti-icon-brand-shopee: unicode('f252'); +$ti-icon-brand-sketch: unicode('ec24'); +$ti-icon-brand-skype: unicode('ed02'); +$ti-icon-brand-slack: unicode('ec72'); +$ti-icon-brand-snapchat: unicode('ec25'); +$ti-icon-brand-snapseed: unicode('f253'); +$ti-icon-brand-snowflake: unicode('f615'); +$ti-icon-brand-socket-io: unicode('f49b'); +$ti-icon-brand-solidjs: unicode('f5ee'); +$ti-icon-brand-soundcloud: unicode('ed6e'); +$ti-icon-brand-spacehey: unicode('f4fc'); +$ti-icon-brand-spotify: unicode('ed03'); +$ti-icon-brand-stackoverflow: unicode('ef58'); +$ti-icon-brand-stackshare: unicode('f607'); +$ti-icon-brand-steam: unicode('ed6f'); +$ti-icon-brand-storybook: unicode('f332'); +$ti-icon-brand-storytel: unicode('f608'); +$ti-icon-brand-strava: unicode('f254'); +$ti-icon-brand-stripe: unicode('edd7'); +$ti-icon-brand-sublime-text: unicode('ef74'); +$ti-icon-brand-sugarizer: unicode('f7a5'); +$ti-icon-brand-supabase: unicode('f6d3'); +$ti-icon-brand-superhuman: unicode('f50c'); +$ti-icon-brand-supernova: unicode('f49c'); +$ti-icon-brand-surfshark: unicode('f255'); +$ti-icon-brand-svelte: unicode('f0df'); +$ti-icon-brand-symfony: unicode('f616'); +$ti-icon-brand-tabler: unicode('ec8f'); +$ti-icon-brand-tailwind: unicode('eca1'); +$ti-icon-brand-taobao: unicode('f5ef'); +$ti-icon-brand-ted: unicode('f658'); +$ti-icon-brand-telegram: unicode('ec26'); +$ti-icon-brand-tether: unicode('f5a3'); +$ti-icon-brand-threejs: unicode('f5f0'); +$ti-icon-brand-tidal: unicode('ed70'); +$ti-icon-brand-tikto-filled: unicode('f7ea'); +$ti-icon-brand-tiktok: unicode('ec73'); +$ti-icon-brand-tinder: unicode('ed71'); +$ti-icon-brand-topbuzz: unicode('f50d'); +$ti-icon-brand-torchain: unicode('f5a4'); +$ti-icon-brand-toyota: unicode('f262'); +$ti-icon-brand-trello: unicode('f39d'); +$ti-icon-brand-tripadvisor: unicode('f002'); +$ti-icon-brand-tumblr: unicode('ed04'); +$ti-icon-brand-twilio: unicode('f617'); +$ti-icon-brand-twitch: unicode('ed05'); +$ti-icon-brand-twitter: unicode('ec27'); +$ti-icon-brand-twitter-filled: unicode('f7eb'); +$ti-icon-brand-typescript: unicode('f5f1'); +$ti-icon-brand-uber: unicode('ef75'); +$ti-icon-brand-ubuntu: unicode('ef59'); +$ti-icon-brand-unity: unicode('f49d'); +$ti-icon-brand-unsplash: unicode('edd8'); +$ti-icon-brand-upwork: unicode('f39e'); +$ti-icon-brand-valorant: unicode('f39f'); +$ti-icon-brand-vercel: unicode('ef24'); +$ti-icon-brand-vimeo: unicode('ed06'); +$ti-icon-brand-vinted: unicode('f20f'); +$ti-icon-brand-visa: unicode('f380'); +$ti-icon-brand-visual-studio: unicode('ef76'); +$ti-icon-brand-vite: unicode('f5f2'); +$ti-icon-brand-vivaldi: unicode('f210'); +$ti-icon-brand-vk: unicode('ed72'); +$ti-icon-brand-volkswagen: unicode('f50e'); +$ti-icon-brand-vsco: unicode('f334'); +$ti-icon-brand-vscode: unicode('f3a0'); +$ti-icon-brand-vue: unicode('f0e0'); +$ti-icon-brand-walmart: unicode('f211'); +$ti-icon-brand-waze: unicode('f5d8'); +$ti-icon-brand-webflow: unicode('f2d2'); +$ti-icon-brand-wechat: unicode('f5f3'); +$ti-icon-brand-weibo: unicode('f609'); +$ti-icon-brand-whatsapp: unicode('ec74'); +$ti-icon-brand-windows: unicode('ecd8'); +$ti-icon-brand-windy: unicode('f4dd'); +$ti-icon-brand-wish: unicode('f212'); +$ti-icon-brand-wix: unicode('f3a1'); +$ti-icon-brand-wordpress: unicode('f2d3'); +$ti-icon-brand-xbox: unicode('f298'); +$ti-icon-brand-xing: unicode('f21a'); +$ti-icon-brand-yahoo: unicode('ed73'); +$ti-icon-brand-yatse: unicode('f213'); +$ti-icon-brand-ycombinator: unicode('edd9'); +$ti-icon-brand-youtube: unicode('ec90'); +$ti-icon-brand-youtube-kids: unicode('f214'); +$ti-icon-brand-zalando: unicode('f49e'); +$ti-icon-brand-zapier: unicode('f49f'); +$ti-icon-brand-zeit: unicode('f335'); +$ti-icon-brand-zhihu: unicode('f60a'); +$ti-icon-brand-zoom: unicode('f215'); +$ti-icon-brand-zulip: unicode('f4de'); +$ti-icon-brand-zwift: unicode('f216'); +$ti-icon-bread: unicode('efa3'); +$ti-icon-bread-off: unicode('f3cb'); +$ti-icon-briefcase: unicode('ea46'); +$ti-icon-briefcase-off: unicode('f3cc'); +$ti-icon-brightness: unicode('eb7f'); +$ti-icon-brightness-2: unicode('ee19'); +$ti-icon-brightness-down: unicode('eb7d'); +$ti-icon-brightness-half: unicode('ee1a'); +$ti-icon-brightness-off: unicode('f3cd'); +$ti-icon-brightness-up: unicode('eb7e'); +$ti-icon-broadcast: unicode('f1e9'); +$ti-icon-broadcast-off: unicode('f1e8'); +$ti-icon-browser: unicode('ebb7'); +$ti-icon-browser-check: unicode('efd6'); +$ti-icon-browser-off: unicode('f0c1'); +$ti-icon-browser-plus: unicode('efd7'); +$ti-icon-browser-x: unicode('efd8'); +$ti-icon-brush: unicode('ebb8'); +$ti-icon-brush-off: unicode('f0c2'); +$ti-icon-bucket: unicode('ea47'); +$ti-icon-bucket-droplet: unicode('f56a'); +$ti-icon-bucket-off: unicode('f103'); +$ti-icon-bug: unicode('ea48'); +$ti-icon-bug-off: unicode('f0c3'); +$ti-icon-building: unicode('ea4f'); +$ti-icon-building-arch: unicode('ea49'); +$ti-icon-building-bank: unicode('ebe2'); +$ti-icon-building-bridge: unicode('ea4b'); +$ti-icon-building-bridge-2: unicode('ea4a'); +$ti-icon-building-broadcast-tower: unicode('f4be'); +$ti-icon-building-carousel: unicode('ed87'); +$ti-icon-building-castle: unicode('ed88'); +$ti-icon-building-church: unicode('ea4c'); +$ti-icon-building-circus: unicode('f4bf'); +$ti-icon-building-community: unicode('ebf6'); +$ti-icon-building-cottage: unicode('ee1b'); +$ti-icon-building-estate: unicode('f5a5'); +$ti-icon-building-factory: unicode('ee1c'); +$ti-icon-building-factory-2: unicode('f082'); +$ti-icon-building-fortress: unicode('ed89'); +$ti-icon-building-hospital: unicode('ea4d'); +$ti-icon-building-lighthouse: unicode('ed8a'); +$ti-icon-building-monument: unicode('ed26'); +$ti-icon-building-pavilion: unicode('ebf7'); +$ti-icon-building-skyscraper: unicode('ec39'); +$ti-icon-building-stadium: unicode('f641'); +$ti-icon-building-store: unicode('ea4e'); +$ti-icon-building-tunnel: unicode('f5a6'); +$ti-icon-building-warehouse: unicode('ebe3'); +$ti-icon-building-wind-turbine: unicode('f4c0'); +$ti-icon-bulb: unicode('ea51'); +$ti-icon-bulb-filled: unicode('f66a'); +$ti-icon-bulb-off: unicode('ea50'); +$ti-icon-bulldozer: unicode('ee1d'); +$ti-icon-bus: unicode('ebe4'); +$ti-icon-bus-off: unicode('f3ce'); +$ti-icon-bus-stop: unicode('f2d4'); +$ti-icon-businessplan: unicode('ee1e'); +$ti-icon-butterfly: unicode('efd9'); +$ti-icon-cactus: unicode('f21b'); +$ti-icon-cactus-off: unicode('f3cf'); +$ti-icon-cake: unicode('f00f'); +$ti-icon-cake-off: unicode('f104'); +$ti-icon-calculator: unicode('eb80'); +$ti-icon-calculator-off: unicode('f0c4'); +$ti-icon-calendar: unicode('ea53'); +$ti-icon-calendar-bolt: unicode('f822'); +$ti-icon-calendar-cancel: unicode('f823'); +$ti-icon-calendar-check: unicode('f824'); +$ti-icon-calendar-code: unicode('f825'); +$ti-icon-calendar-cog: unicode('f826'); +$ti-icon-calendar-dollar: unicode('f827'); +$ti-icon-calendar-down: unicode('f828'); +$ti-icon-calendar-due: unicode('f621'); +$ti-icon-calendar-event: unicode('ea52'); +$ti-icon-calendar-exclamation: unicode('f829'); +$ti-icon-calendar-heart: unicode('f82a'); +$ti-icon-calendar-minus: unicode('ebb9'); +$ti-icon-calendar-off: unicode('ee1f'); +$ti-icon-calendar-pause: unicode('f82b'); +$ti-icon-calendar-pin: unicode('f82c'); +$ti-icon-calendar-plus: unicode('ebba'); +$ti-icon-calendar-question: unicode('f82d'); +$ti-icon-calendar-search: unicode('f82e'); +$ti-icon-calendar-share: unicode('f82f'); +$ti-icon-calendar-star: unicode('f830'); +$ti-icon-calendar-stats: unicode('ee20'); +$ti-icon-calendar-time: unicode('ee21'); +$ti-icon-calendar-up: unicode('f831'); +$ti-icon-calendar-x: unicode('f832'); +$ti-icon-camera: unicode('ea54'); +$ti-icon-camera-bolt: unicode('f833'); +$ti-icon-camera-cancel: unicode('f834'); +$ti-icon-camera-check: unicode('f835'); +$ti-icon-camera-code: unicode('f836'); +$ti-icon-camera-cog: unicode('f837'); +$ti-icon-camera-dollar: unicode('f838'); +$ti-icon-camera-down: unicode('f839'); +$ti-icon-camera-exclamation: unicode('f83a'); +$ti-icon-camera-heart: unicode('f83b'); +$ti-icon-camera-minus: unicode('ec3a'); +$ti-icon-camera-off: unicode('ecee'); +$ti-icon-camera-pause: unicode('f83c'); +$ti-icon-camera-pin: unicode('f83d'); +$ti-icon-camera-plus: unicode('ec3b'); +$ti-icon-camera-question: unicode('f83e'); +$ti-icon-camera-rotate: unicode('ee22'); +$ti-icon-camera-search: unicode('f83f'); +$ti-icon-camera-selfie: unicode('ee23'); +$ti-icon-camera-share: unicode('f840'); +$ti-icon-camera-star: unicode('f841'); +$ti-icon-camera-up: unicode('f842'); +$ti-icon-camera-x: unicode('f843'); +$ti-icon-campfire: unicode('f5a7'); +$ti-icon-candle: unicode('efc6'); +$ti-icon-candy: unicode('ef0d'); +$ti-icon-candy-off: unicode('f0c5'); +$ti-icon-cane: unicode('f50f'); +$ti-icon-cannabis: unicode('f4c1'); +$ti-icon-capture: unicode('ec3c'); +$ti-icon-capture-off: unicode('f0c6'); +$ti-icon-car: unicode('ebbb'); +$ti-icon-car-crane: unicode('ef25'); +$ti-icon-car-crash: unicode('efa4'); +$ti-icon-car-off: unicode('f0c7'); +$ti-icon-car-turbine: unicode('f4fd'); +$ti-icon-caravan: unicode('ec7c'); +$ti-icon-cardboards: unicode('ed74'); +$ti-icon-cardboards-off: unicode('f0c8'); +$ti-icon-cards: unicode('f510'); +$ti-icon-caret-down: unicode('eb5d'); +$ti-icon-caret-left: unicode('eb5e'); +$ti-icon-caret-right: unicode('eb5f'); +$ti-icon-caret-up: unicode('eb60'); +$ti-icon-carousel-horizontal: unicode('f659'); +$ti-icon-carousel-vertical: unicode('f65a'); +$ti-icon-carrot: unicode('f21c'); +$ti-icon-carrot-off: unicode('f3d0'); +$ti-icon-cash: unicode('ea55'); +$ti-icon-cash-banknote: unicode('ee25'); +$ti-icon-cash-banknote-off: unicode('ee24'); +$ti-icon-cash-off: unicode('f105'); +$ti-icon-cast: unicode('ea56'); +$ti-icon-cast-off: unicode('f0c9'); +$ti-icon-cat: unicode('f65b'); +$ti-icon-category: unicode('f1f6'); +$ti-icon-category-2: unicode('f1f5'); +$ti-icon-ce: unicode('ed75'); +$ti-icon-ce-off: unicode('f0ca'); +$ti-icon-cell: unicode('f05f'); +$ti-icon-cell-signal-1: unicode('f083'); +$ti-icon-cell-signal-2: unicode('f084'); +$ti-icon-cell-signal-3: unicode('f085'); +$ti-icon-cell-signal-4: unicode('f086'); +$ti-icon-cell-signal-5: unicode('f087'); +$ti-icon-cell-signal-off: unicode('f088'); +$ti-icon-certificate: unicode('ed76'); +$ti-icon-certificate-2: unicode('f073'); +$ti-icon-certificate-2-off: unicode('f0cb'); +$ti-icon-certificate-off: unicode('f0cc'); +$ti-icon-chair-director: unicode('f2d5'); +$ti-icon-chalkboard: unicode('f34d'); +$ti-icon-chalkboard-off: unicode('f3d1'); +$ti-icon-charging-pile: unicode('ee26'); +$ti-icon-chart-arcs: unicode('ee28'); +$ti-icon-chart-arcs-3: unicode('ee27'); +$ti-icon-chart-area: unicode('ea58'); +$ti-icon-chart-area-filled: unicode('f66b'); +$ti-icon-chart-area-line: unicode('ea57'); +$ti-icon-chart-area-line-filled: unicode('f66c'); +$ti-icon-chart-arrows: unicode('ee2a'); +$ti-icon-chart-arrows-vertical: unicode('ee29'); +$ti-icon-chart-bar: unicode('ea59'); +$ti-icon-chart-bar-off: unicode('f3d2'); +$ti-icon-chart-bubble: unicode('ec75'); +$ti-icon-chart-bubble-filled: unicode('f66d'); +$ti-icon-chart-candle: unicode('ea5a'); +$ti-icon-chart-candle-filled: unicode('f66e'); +$ti-icon-chart-circles: unicode('ee2b'); +$ti-icon-chart-donut: unicode('ea5b'); +$ti-icon-chart-donut-2: unicode('ee2c'); +$ti-icon-chart-donut-3: unicode('ee2d'); +$ti-icon-chart-donut-4: unicode('ee2e'); +$ti-icon-chart-donut-filled: unicode('f66f'); +$ti-icon-chart-dots: unicode('ee2f'); +$ti-icon-chart-dots-2: unicode('f097'); +$ti-icon-chart-dots-3: unicode('f098'); +$ti-icon-chart-grid-dots: unicode('f4c2'); +$ti-icon-chart-histogram: unicode('f65c'); +$ti-icon-chart-infographic: unicode('ee30'); +$ti-icon-chart-line: unicode('ea5c'); +$ti-icon-chart-pie: unicode('ea5d'); +$ti-icon-chart-pie-2: unicode('ee31'); +$ti-icon-chart-pie-3: unicode('ee32'); +$ti-icon-chart-pie-4: unicode('ee33'); +$ti-icon-chart-pie-filled: unicode('f670'); +$ti-icon-chart-pie-off: unicode('f3d3'); +$ti-icon-chart-ppf: unicode('f618'); +$ti-icon-chart-radar: unicode('ed77'); +$ti-icon-chart-sankey: unicode('f619'); +$ti-icon-chart-treemap: unicode('f381'); +$ti-icon-check: unicode('ea5e'); +$ti-icon-checkbox: unicode('eba6'); +$ti-icon-checklist: unicode('f074'); +$ti-icon-checks: unicode('ebaa'); +$ti-icon-checkup-list: unicode('ef5a'); +$ti-icon-cheese: unicode('ef26'); +$ti-icon-chef-hat: unicode('f21d'); +$ti-icon-chef-hat-off: unicode('f3d4'); +$ti-icon-cherry: unicode('f511'); +$ti-icon-cherry-filled: unicode('f728'); +$ti-icon-chess: unicode('f382'); +$ti-icon-chess-bishop: unicode('f56b'); +$ti-icon-chess-bishop-filled: unicode('f729'); +$ti-icon-chess-filled: unicode('f72a'); +$ti-icon-chess-king: unicode('f56c'); +$ti-icon-chess-king-filled: unicode('f72b'); +$ti-icon-chess-knight: unicode('f56d'); +$ti-icon-chess-knight-filled: unicode('f72c'); +$ti-icon-chess-queen: unicode('f56e'); +$ti-icon-chess-queen-filled: unicode('f72d'); +$ti-icon-chess-rook: unicode('f56f'); +$ti-icon-chess-rook-filled: unicode('f72e'); +$ti-icon-chevron-down: unicode('ea5f'); +$ti-icon-chevron-down-left: unicode('ed09'); +$ti-icon-chevron-down-right: unicode('ed0a'); +$ti-icon-chevron-left: unicode('ea60'); +$ti-icon-chevron-right: unicode('ea61'); +$ti-icon-chevron-up: unicode('ea62'); +$ti-icon-chevron-up-left: unicode('ed0b'); +$ti-icon-chevron-up-right: unicode('ed0c'); +$ti-icon-chevrons-down: unicode('ea63'); +$ti-icon-chevrons-down-left: unicode('ed0d'); +$ti-icon-chevrons-down-right: unicode('ed0e'); +$ti-icon-chevrons-left: unicode('ea64'); +$ti-icon-chevrons-right: unicode('ea65'); +$ti-icon-chevrons-up: unicode('ea66'); +$ti-icon-chevrons-up-left: unicode('ed0f'); +$ti-icon-chevrons-up-right: unicode('ed10'); +$ti-icon-chisel: unicode('f383'); +$ti-icon-christmas-tree: unicode('ed78'); +$ti-icon-christmas-tree-off: unicode('f3d5'); +$ti-icon-circle: unicode('ea6b'); +$ti-icon-circle-0-filled: unicode('f72f'); +$ti-icon-circle-1-filled: unicode('f730'); +$ti-icon-circle-2-filled: unicode('f731'); +$ti-icon-circle-3-filled: unicode('f732'); +$ti-icon-circle-4-filled: unicode('f733'); +$ti-icon-circle-5-filled: unicode('f734'); +$ti-icon-circle-6-filled: unicode('f735'); +$ti-icon-circle-7-filled: unicode('f736'); +$ti-icon-circle-8-filled: unicode('f737'); +$ti-icon-circle-9-filled: unicode('f738'); +$ti-icon-circle-arrow-down: unicode('f6f9'); +$ti-icon-circle-arrow-down-filled: unicode('f6f4'); +$ti-icon-circle-arrow-down-left: unicode('f6f6'); +$ti-icon-circle-arrow-down-left-filled: unicode('f6f5'); +$ti-icon-circle-arrow-down-right: unicode('f6f8'); +$ti-icon-circle-arrow-down-right-filled: unicode('f6f7'); +$ti-icon-circle-arrow-left: unicode('f6fb'); +$ti-icon-circle-arrow-left-filled: unicode('f6fa'); +$ti-icon-circle-arrow-right: unicode('f6fd'); +$ti-icon-circle-arrow-right-filled: unicode('f6fc'); +$ti-icon-circle-arrow-up: unicode('f703'); +$ti-icon-circle-arrow-up-filled: unicode('f6fe'); +$ti-icon-circle-arrow-up-left: unicode('f700'); +$ti-icon-circle-arrow-up-left-filled: unicode('f6ff'); +$ti-icon-circle-arrow-up-right: unicode('f702'); +$ti-icon-circle-arrow-up-right-filled: unicode('f701'); +$ti-icon-circle-caret-down: unicode('f4a9'); +$ti-icon-circle-caret-left: unicode('f4aa'); +$ti-icon-circle-caret-right: unicode('f4ab'); +$ti-icon-circle-caret-up: unicode('f4ac'); +$ti-icon-circle-check: unicode('ea67'); +$ti-icon-circle-check-filled: unicode('f704'); +$ti-icon-circle-chevron-down: unicode('f622'); +$ti-icon-circle-chevron-left: unicode('f623'); +$ti-icon-circle-chevron-right: unicode('f624'); +$ti-icon-circle-chevron-up: unicode('f625'); +$ti-icon-circle-chevrons-down: unicode('f642'); +$ti-icon-circle-chevrons-left: unicode('f643'); +$ti-icon-circle-chevrons-right: unicode('f644'); +$ti-icon-circle-chevrons-up: unicode('f645'); +$ti-icon-circle-dashed: unicode('ed27'); +$ti-icon-circle-dot: unicode('efb1'); +$ti-icon-circle-dot-filled: unicode('f705'); +$ti-icon-circle-dotted: unicode('ed28'); +$ti-icon-circle-filled: unicode('f671'); +$ti-icon-circle-half: unicode('ee3f'); +$ti-icon-circle-half-2: unicode('eff3'); +$ti-icon-circle-half-vertical: unicode('ee3e'); +$ti-icon-circle-key: unicode('f633'); +$ti-icon-circle-key-filled: unicode('f706'); +$ti-icon-circle-letter-a: unicode('f441'); +$ti-icon-circle-letter-b: unicode('f442'); +$ti-icon-circle-letter-c: unicode('f443'); +$ti-icon-circle-letter-d: unicode('f444'); +$ti-icon-circle-letter-e: unicode('f445'); +$ti-icon-circle-letter-f: unicode('f446'); +$ti-icon-circle-letter-g: unicode('f447'); +$ti-icon-circle-letter-h: unicode('f448'); +$ti-icon-circle-letter-i: unicode('f449'); +$ti-icon-circle-letter-j: unicode('f44a'); +$ti-icon-circle-letter-k: unicode('f44b'); +$ti-icon-circle-letter-l: unicode('f44c'); +$ti-icon-circle-letter-m: unicode('f44d'); +$ti-icon-circle-letter-n: unicode('f44e'); +$ti-icon-circle-letter-o: unicode('f44f'); +$ti-icon-circle-letter-p: unicode('f450'); +$ti-icon-circle-letter-q: unicode('f451'); +$ti-icon-circle-letter-r: unicode('f452'); +$ti-icon-circle-letter-s: unicode('f453'); +$ti-icon-circle-letter-t: unicode('f454'); +$ti-icon-circle-letter-u: unicode('f455'); +$ti-icon-circle-letter-v: unicode('f4ad'); +$ti-icon-circle-letter-w: unicode('f456'); +$ti-icon-circle-letter-x: unicode('f4ae'); +$ti-icon-circle-letter-y: unicode('f457'); +$ti-icon-circle-letter-z: unicode('f458'); +$ti-icon-circle-minus: unicode('ea68'); +$ti-icon-circle-number-0: unicode('ee34'); +$ti-icon-circle-number-1: unicode('ee35'); +$ti-icon-circle-number-2: unicode('ee36'); +$ti-icon-circle-number-3: unicode('ee37'); +$ti-icon-circle-number-4: unicode('ee38'); +$ti-icon-circle-number-5: unicode('ee39'); +$ti-icon-circle-number-6: unicode('ee3a'); +$ti-icon-circle-number-7: unicode('ee3b'); +$ti-icon-circle-number-8: unicode('ee3c'); +$ti-icon-circle-number-9: unicode('ee3d'); +$ti-icon-circle-off: unicode('ee40'); +$ti-icon-circle-plus: unicode('ea69'); +$ti-icon-circle-rectangle: unicode('f010'); +$ti-icon-circle-rectangle-off: unicode('f0cd'); +$ti-icon-circle-square: unicode('ece4'); +$ti-icon-circle-triangle: unicode('f011'); +$ti-icon-circle-x: unicode('ea6a'); +$ti-icon-circle-x-filled: unicode('f739'); +$ti-icon-circles: unicode('ece5'); +$ti-icon-circles-filled: unicode('f672'); +$ti-icon-circles-relation: unicode('f4c3'); +$ti-icon-circuit-ammeter: unicode('f271'); +$ti-icon-circuit-battery: unicode('f272'); +$ti-icon-circuit-bulb: unicode('f273'); +$ti-icon-circuit-capacitor: unicode('f275'); +$ti-icon-circuit-capacitor-polarized: unicode('f274'); +$ti-icon-circuit-cell: unicode('f277'); +$ti-icon-circuit-cell-plus: unicode('f276'); +$ti-icon-circuit-changeover: unicode('f278'); +$ti-icon-circuit-diode: unicode('f27a'); +$ti-icon-circuit-diode-zener: unicode('f279'); +$ti-icon-circuit-ground: unicode('f27c'); +$ti-icon-circuit-ground-digital: unicode('f27b'); +$ti-icon-circuit-inductor: unicode('f27d'); +$ti-icon-circuit-motor: unicode('f27e'); +$ti-icon-circuit-pushbutton: unicode('f27f'); +$ti-icon-circuit-resistor: unicode('f280'); +$ti-icon-circuit-switch-closed: unicode('f281'); +$ti-icon-circuit-switch-open: unicode('f282'); +$ti-icon-circuit-voltmeter: unicode('f283'); +$ti-icon-clear-all: unicode('ee41'); +$ti-icon-clear-formatting: unicode('ebe5'); +$ti-icon-click: unicode('ebbc'); +$ti-icon-clipboard: unicode('ea6f'); +$ti-icon-clipboard-check: unicode('ea6c'); +$ti-icon-clipboard-copy: unicode('f299'); +$ti-icon-clipboard-data: unicode('f563'); +$ti-icon-clipboard-heart: unicode('f34e'); +$ti-icon-clipboard-list: unicode('ea6d'); +$ti-icon-clipboard-off: unicode('f0ce'); +$ti-icon-clipboard-plus: unicode('efb2'); +$ti-icon-clipboard-text: unicode('f089'); +$ti-icon-clipboard-typography: unicode('f34f'); +$ti-icon-clipboard-x: unicode('ea6e'); +$ti-icon-clock: unicode('ea70'); +$ti-icon-clock-2: unicode('f099'); +$ti-icon-clock-bolt: unicode('f844'); +$ti-icon-clock-cancel: unicode('f546'); +$ti-icon-clock-check: unicode('f7c1'); +$ti-icon-clock-code: unicode('f845'); +$ti-icon-clock-cog: unicode('f7c2'); +$ti-icon-clock-dollar: unicode('f846'); +$ti-icon-clock-down: unicode('f7c3'); +$ti-icon-clock-edit: unicode('f547'); +$ti-icon-clock-exclamation: unicode('f847'); +$ti-icon-clock-filled: unicode('f73a'); +$ti-icon-clock-heart: unicode('f7c4'); +$ti-icon-clock-hour-1: unicode('f313'); +$ti-icon-clock-hour-10: unicode('f314'); +$ti-icon-clock-hour-11: unicode('f315'); +$ti-icon-clock-hour-12: unicode('f316'); +$ti-icon-clock-hour-2: unicode('f317'); +$ti-icon-clock-hour-3: unicode('f318'); +$ti-icon-clock-hour-4: unicode('f319'); +$ti-icon-clock-hour-5: unicode('f31a'); +$ti-icon-clock-hour-6: unicode('f31b'); +$ti-icon-clock-hour-7: unicode('f31c'); +$ti-icon-clock-hour-8: unicode('f31d'); +$ti-icon-clock-hour-9: unicode('f31e'); +$ti-icon-clock-minus: unicode('f848'); +$ti-icon-clock-off: unicode('f0cf'); +$ti-icon-clock-pause: unicode('f548'); +$ti-icon-clock-pin: unicode('f849'); +$ti-icon-clock-play: unicode('f549'); +$ti-icon-clock-plus: unicode('f7c5'); +$ti-icon-clock-question: unicode('f7c6'); +$ti-icon-clock-record: unicode('f54a'); +$ti-icon-clock-search: unicode('f7c7'); +$ti-icon-clock-share: unicode('f84a'); +$ti-icon-clock-shield: unicode('f7c8'); +$ti-icon-clock-star: unicode('f7c9'); +$ti-icon-clock-stop: unicode('f54b'); +$ti-icon-clock-up: unicode('f7ca'); +$ti-icon-clock-x: unicode('f7cb'); +$ti-icon-clothes-rack: unicode('f285'); +$ti-icon-clothes-rack-off: unicode('f3d6'); +$ti-icon-cloud: unicode('ea76'); +$ti-icon-cloud-bolt: unicode('f84b'); +$ti-icon-cloud-cancel: unicode('f84c'); +$ti-icon-cloud-check: unicode('f84d'); +$ti-icon-cloud-code: unicode('f84e'); +$ti-icon-cloud-cog: unicode('f84f'); +$ti-icon-cloud-computing: unicode('f1d0'); +$ti-icon-cloud-data-connection: unicode('f1d1'); +$ti-icon-cloud-dollar: unicode('f850'); +$ti-icon-cloud-down: unicode('f851'); +$ti-icon-cloud-download: unicode('ea71'); +$ti-icon-cloud-exclamation: unicode('f852'); +$ti-icon-cloud-filled: unicode('f673'); +$ti-icon-cloud-fog: unicode('ecd9'); +$ti-icon-cloud-heart: unicode('f853'); +$ti-icon-cloud-lock: unicode('efdb'); +$ti-icon-cloud-lock-open: unicode('efda'); +$ti-icon-cloud-minus: unicode('f854'); +$ti-icon-cloud-off: unicode('ed3e'); +$ti-icon-cloud-pause: unicode('f855'); +$ti-icon-cloud-pin: unicode('f856'); +$ti-icon-cloud-plus: unicode('f857'); +$ti-icon-cloud-question: unicode('f858'); +$ti-icon-cloud-rain: unicode('ea72'); +$ti-icon-cloud-search: unicode('f859'); +$ti-icon-cloud-share: unicode('f85a'); +$ti-icon-cloud-snow: unicode('ea73'); +$ti-icon-cloud-star: unicode('f85b'); +$ti-icon-cloud-storm: unicode('ea74'); +$ti-icon-cloud-up: unicode('f85c'); +$ti-icon-cloud-upload: unicode('ea75'); +$ti-icon-cloud-x: unicode('f85d'); +$ti-icon-clover: unicode('f1ea'); +$ti-icon-clover-2: unicode('f21e'); +$ti-icon-clubs: unicode('eff4'); +$ti-icon-clubs-filled: unicode('f674'); +$ti-icon-code: unicode('ea77'); +$ti-icon-code-asterix: unicode('f312'); +$ti-icon-code-circle: unicode('f4ff'); +$ti-icon-code-circle-2: unicode('f4fe'); +$ti-icon-code-dots: unicode('f61a'); +$ti-icon-code-minus: unicode('ee42'); +$ti-icon-code-off: unicode('f0d0'); +$ti-icon-code-plus: unicode('ee43'); +$ti-icon-coffee: unicode('ef0e'); +$ti-icon-coffee-off: unicode('f106'); +$ti-icon-coffin: unicode('f579'); +$ti-icon-coin: unicode('eb82'); +$ti-icon-coin-bitcoin: unicode('f2be'); +$ti-icon-coin-euro: unicode('f2bf'); +$ti-icon-coin-monero: unicode('f4a0'); +$ti-icon-coin-off: unicode('f0d1'); +$ti-icon-coin-pound: unicode('f2c0'); +$ti-icon-coin-rupee: unicode('f2c1'); +$ti-icon-coin-yen: unicode('f2c2'); +$ti-icon-coin-yuan: unicode('f2c3'); +$ti-icon-coins: unicode('f65d'); +$ti-icon-color-filter: unicode('f5a8'); +$ti-icon-color-picker: unicode('ebe6'); +$ti-icon-color-picker-off: unicode('f0d2'); +$ti-icon-color-swatch: unicode('eb61'); +$ti-icon-color-swatch-off: unicode('f0d3'); +$ti-icon-column-insert-left: unicode('ee44'); +$ti-icon-column-insert-right: unicode('ee45'); +$ti-icon-columns: unicode('eb83'); +$ti-icon-columns-1: unicode('f6d4'); +$ti-icon-columns-2: unicode('f6d5'); +$ti-icon-columns-3: unicode('f6d6'); +$ti-icon-columns-off: unicode('f0d4'); +$ti-icon-comet: unicode('ec76'); +$ti-icon-command: unicode('ea78'); +$ti-icon-command-off: unicode('f3d7'); +$ti-icon-compass: unicode('ea79'); +$ti-icon-compass-off: unicode('f0d5'); +$ti-icon-components: unicode('efa5'); +$ti-icon-components-off: unicode('f0d6'); +$ti-icon-cone: unicode('efdd'); +$ti-icon-cone-2: unicode('efdc'); +$ti-icon-cone-off: unicode('f3d8'); +$ti-icon-confetti: unicode('ee46'); +$ti-icon-confetti-off: unicode('f3d9'); +$ti-icon-confucius: unicode('f58a'); +$ti-icon-container: unicode('ee47'); +$ti-icon-container-off: unicode('f107'); +$ti-icon-contrast: unicode('ec4e'); +$ti-icon-contrast-2: unicode('efc7'); +$ti-icon-contrast-2-off: unicode('f3da'); +$ti-icon-contrast-off: unicode('f3db'); +$ti-icon-cooker: unicode('f57a'); +$ti-icon-cookie: unicode('ef0f'); +$ti-icon-cookie-man: unicode('f4c4'); +$ti-icon-cookie-off: unicode('f0d7'); +$ti-icon-copy: unicode('ea7a'); +$ti-icon-copy-off: unicode('f0d8'); +$ti-icon-copyleft: unicode('ec3d'); +$ti-icon-copyleft-filled: unicode('f73b'); +$ti-icon-copyleft-off: unicode('f0d9'); +$ti-icon-copyright: unicode('ea7b'); +$ti-icon-copyright-filled: unicode('f73c'); +$ti-icon-copyright-off: unicode('f0da'); +$ti-icon-corner-down-left: unicode('ea7c'); +$ti-icon-corner-down-left-double: unicode('ee48'); +$ti-icon-corner-down-right: unicode('ea7d'); +$ti-icon-corner-down-right-double: unicode('ee49'); +$ti-icon-corner-left-down: unicode('ea7e'); +$ti-icon-corner-left-down-double: unicode('ee4a'); +$ti-icon-corner-left-up: unicode('ea7f'); +$ti-icon-corner-left-up-double: unicode('ee4b'); +$ti-icon-corner-right-down: unicode('ea80'); +$ti-icon-corner-right-down-double: unicode('ee4c'); +$ti-icon-corner-right-up: unicode('ea81'); +$ti-icon-corner-right-up-double: unicode('ee4d'); +$ti-icon-corner-up-left: unicode('ea82'); +$ti-icon-corner-up-left-double: unicode('ee4e'); +$ti-icon-corner-up-right: unicode('ea83'); +$ti-icon-corner-up-right-double: unicode('ee4f'); +$ti-icon-cpu: unicode('ef8e'); +$ti-icon-cpu-2: unicode('f075'); +$ti-icon-cpu-off: unicode('f108'); +$ti-icon-crane: unicode('ef27'); +$ti-icon-crane-off: unicode('f109'); +$ti-icon-creative-commons: unicode('efb3'); +$ti-icon-creative-commons-by: unicode('f21f'); +$ti-icon-creative-commons-nc: unicode('f220'); +$ti-icon-creative-commons-nd: unicode('f221'); +$ti-icon-creative-commons-off: unicode('f10a'); +$ti-icon-creative-commons-sa: unicode('f222'); +$ti-icon-creative-commons-zero: unicode('f223'); +$ti-icon-credit-card: unicode('ea84'); +$ti-icon-credit-card-off: unicode('ed11'); +$ti-icon-cricket: unicode('f09a'); +$ti-icon-crop: unicode('ea85'); +$ti-icon-cross: unicode('ef8f'); +$ti-icon-cross-filled: unicode('f675'); +$ti-icon-cross-off: unicode('f10b'); +$ti-icon-crosshair: unicode('ec3e'); +$ti-icon-crown: unicode('ed12'); +$ti-icon-crown-off: unicode('ee50'); +$ti-icon-crutches: unicode('ef5b'); +$ti-icon-crutches-off: unicode('f10c'); +$ti-icon-crystal-ball: unicode('f57b'); +$ti-icon-csv: unicode('f791'); +$ti-icon-cube-send: unicode('f61b'); +$ti-icon-cube-unfolded: unicode('f61c'); +$ti-icon-cup: unicode('ef28'); +$ti-icon-cup-off: unicode('f10d'); +$ti-icon-curling: unicode('efc8'); +$ti-icon-curly-loop: unicode('ecda'); +$ti-icon-currency: unicode('efa6'); +$ti-icon-currency-afghani: unicode('f65e'); +$ti-icon-currency-bahraini: unicode('ee51'); +$ti-icon-currency-baht: unicode('f08a'); +$ti-icon-currency-bitcoin: unicode('ebab'); +$ti-icon-currency-cent: unicode('ee53'); +$ti-icon-currency-dinar: unicode('ee54'); +$ti-icon-currency-dirham: unicode('ee55'); +$ti-icon-currency-dogecoin: unicode('ef4b'); +$ti-icon-currency-dollar: unicode('eb84'); +$ti-icon-currency-dollar-australian: unicode('ee56'); +$ti-icon-currency-dollar-brunei: unicode('f36c'); +$ti-icon-currency-dollar-canadian: unicode('ee57'); +$ti-icon-currency-dollar-guyanese: unicode('f36d'); +$ti-icon-currency-dollar-off: unicode('f3dc'); +$ti-icon-currency-dollar-singapore: unicode('ee58'); +$ti-icon-currency-dollar-zimbabwean: unicode('f36e'); +$ti-icon-currency-dong: unicode('f36f'); +$ti-icon-currency-dram: unicode('f370'); +$ti-icon-currency-ethereum: unicode('ee59'); +$ti-icon-currency-euro: unicode('eb85'); +$ti-icon-currency-euro-off: unicode('f3dd'); +$ti-icon-currency-forint: unicode('ee5a'); +$ti-icon-currency-frank: unicode('ee5b'); +$ti-icon-currency-guarani: unicode('f371'); +$ti-icon-currency-hryvnia: unicode('f372'); +$ti-icon-currency-kip: unicode('f373'); +$ti-icon-currency-krone-czech: unicode('ee5c'); +$ti-icon-currency-krone-danish: unicode('ee5d'); +$ti-icon-currency-krone-swedish: unicode('ee5e'); +$ti-icon-currency-lari: unicode('f374'); +$ti-icon-currency-leu: unicode('ee5f'); +$ti-icon-currency-lira: unicode('ee60'); +$ti-icon-currency-litecoin: unicode('ee61'); +$ti-icon-currency-lyd: unicode('f375'); +$ti-icon-currency-manat: unicode('f376'); +$ti-icon-currency-monero: unicode('f377'); +$ti-icon-currency-naira: unicode('ee62'); +$ti-icon-currency-nano: unicode('f7a6'); +$ti-icon-currency-off: unicode('f3de'); +$ti-icon-currency-paanga: unicode('f378'); +$ti-icon-currency-peso: unicode('f65f'); +$ti-icon-currency-pound: unicode('ebac'); +$ti-icon-currency-pound-off: unicode('f3df'); +$ti-icon-currency-quetzal: unicode('f379'); +$ti-icon-currency-real: unicode('ee63'); +$ti-icon-currency-renminbi: unicode('ee64'); +$ti-icon-currency-ripple: unicode('ee65'); +$ti-icon-currency-riyal: unicode('ee66'); +$ti-icon-currency-rubel: unicode('ee67'); +$ti-icon-currency-rufiyaa: unicode('f37a'); +$ti-icon-currency-rupee: unicode('ebad'); +$ti-icon-currency-rupee-nepalese: unicode('f37b'); +$ti-icon-currency-shekel: unicode('ee68'); +$ti-icon-currency-solana: unicode('f4a1'); +$ti-icon-currency-som: unicode('f37c'); +$ti-icon-currency-taka: unicode('ee69'); +$ti-icon-currency-tenge: unicode('f37d'); +$ti-icon-currency-tugrik: unicode('ee6a'); +$ti-icon-currency-won: unicode('ee6b'); +$ti-icon-currency-yen: unicode('ebae'); +$ti-icon-currency-yen-off: unicode('f3e0'); +$ti-icon-currency-yuan: unicode('f29a'); +$ti-icon-currency-zloty: unicode('ee6c'); +$ti-icon-current-location: unicode('ecef'); +$ti-icon-current-location-off: unicode('f10e'); +$ti-icon-cursor-off: unicode('f10f'); +$ti-icon-cursor-text: unicode('ee6d'); +$ti-icon-cut: unicode('ea86'); +$ti-icon-cylinder: unicode('f54c'); +$ti-icon-dashboard: unicode('ea87'); +$ti-icon-dashboard-off: unicode('f3e1'); +$ti-icon-database: unicode('ea88'); +$ti-icon-database-export: unicode('ee6e'); +$ti-icon-database-import: unicode('ee6f'); +$ti-icon-database-off: unicode('ee70'); +$ti-icon-deer: unicode('f4c5'); +$ti-icon-delta: unicode('f53c'); +$ti-icon-dental: unicode('f025'); +$ti-icon-dental-broken: unicode('f286'); +$ti-icon-dental-off: unicode('f110'); +$ti-icon-deselect: unicode('f9f3'); +$ti-icon-details: unicode('ee71'); +$ti-icon-details-off: unicode('f3e2'); +$ti-icon-device-airpods: unicode('f5a9'); +$ti-icon-device-airpods-case: unicode('f646'); +$ti-icon-device-analytics: unicode('ee72'); +$ti-icon-device-audio-tape: unicode('ee73'); +$ti-icon-device-camera-phone: unicode('f233'); +$ti-icon-device-cctv: unicode('ee74'); +$ti-icon-device-cctv-off: unicode('f3e3'); +$ti-icon-device-computer-camera: unicode('ee76'); +$ti-icon-device-computer-camera-off: unicode('ee75'); +$ti-icon-device-desktop: unicode('ea89'); +$ti-icon-device-desktop-analytics: unicode('ee77'); +$ti-icon-device-desktop-bolt: unicode('f85e'); +$ti-icon-device-desktop-cancel: unicode('f85f'); +$ti-icon-device-desktop-check: unicode('f860'); +$ti-icon-device-desktop-code: unicode('f861'); +$ti-icon-device-desktop-cog: unicode('f862'); +$ti-icon-device-desktop-dollar: unicode('f863'); +$ti-icon-device-desktop-down: unicode('f864'); +$ti-icon-device-desktop-exclamation: unicode('f865'); +$ti-icon-device-desktop-heart: unicode('f866'); +$ti-icon-device-desktop-minus: unicode('f867'); +$ti-icon-device-desktop-off: unicode('ee78'); +$ti-icon-device-desktop-pause: unicode('f868'); +$ti-icon-device-desktop-pin: unicode('f869'); +$ti-icon-device-desktop-plus: unicode('f86a'); +$ti-icon-device-desktop-question: unicode('f86b'); +$ti-icon-device-desktop-search: unicode('f86c'); +$ti-icon-device-desktop-share: unicode('f86d'); +$ti-icon-device-desktop-star: unicode('f86e'); +$ti-icon-device-desktop-up: unicode('f86f'); +$ti-icon-device-desktop-x: unicode('f870'); +$ti-icon-device-floppy: unicode('eb62'); +$ti-icon-device-gamepad: unicode('eb63'); +$ti-icon-device-gamepad-2: unicode('f1d2'); +$ti-icon-device-heart-monitor: unicode('f060'); +$ti-icon-device-imac: unicode('f7a7'); +$ti-icon-device-imac-bolt: unicode('f871'); +$ti-icon-device-imac-cancel: unicode('f872'); +$ti-icon-device-imac-check: unicode('f873'); +$ti-icon-device-imac-code: unicode('f874'); +$ti-icon-device-imac-cog: unicode('f875'); +$ti-icon-device-imac-dollar: unicode('f876'); +$ti-icon-device-imac-down: unicode('f877'); +$ti-icon-device-imac-exclamation: unicode('f878'); +$ti-icon-device-imac-heart: unicode('f879'); +$ti-icon-device-imac-minus: unicode('f87a'); +$ti-icon-device-imac-off: unicode('f87b'); +$ti-icon-device-imac-pause: unicode('f87c'); +$ti-icon-device-imac-pin: unicode('f87d'); +$ti-icon-device-imac-plus: unicode('f87e'); +$ti-icon-device-imac-question: unicode('f87f'); +$ti-icon-device-imac-search: unicode('f880'); +$ti-icon-device-imac-share: unicode('f881'); +$ti-icon-device-imac-star: unicode('f882'); +$ti-icon-device-imac-up: unicode('f883'); +$ti-icon-device-imac-x: unicode('f884'); +$ti-icon-device-ipad: unicode('f648'); +$ti-icon-device-ipad-bolt: unicode('f885'); +$ti-icon-device-ipad-cancel: unicode('f886'); +$ti-icon-device-ipad-check: unicode('f887'); +$ti-icon-device-ipad-code: unicode('f888'); +$ti-icon-device-ipad-cog: unicode('f889'); +$ti-icon-device-ipad-dollar: unicode('f88a'); +$ti-icon-device-ipad-down: unicode('f88b'); +$ti-icon-device-ipad-exclamation: unicode('f88c'); +$ti-icon-device-ipad-heart: unicode('f88d'); +$ti-icon-device-ipad-horizontal: unicode('f647'); +$ti-icon-device-ipad-horizontal-bolt: unicode('f88e'); +$ti-icon-device-ipad-horizontal-cancel: unicode('f88f'); +$ti-icon-device-ipad-horizontal-check: unicode('f890'); +$ti-icon-device-ipad-horizontal-code: unicode('f891'); +$ti-icon-device-ipad-horizontal-cog: unicode('f892'); +$ti-icon-device-ipad-horizontal-dollar: unicode('f893'); +$ti-icon-device-ipad-horizontal-down: unicode('f894'); +$ti-icon-device-ipad-horizontal-exclamation: unicode('f895'); +$ti-icon-device-ipad-horizontal-heart: unicode('f896'); +$ti-icon-device-ipad-horizontal-minus: unicode('f897'); +$ti-icon-device-ipad-horizontal-off: unicode('f898'); +$ti-icon-device-ipad-horizontal-pause: unicode('f899'); +$ti-icon-device-ipad-horizontal-pin: unicode('f89a'); +$ti-icon-device-ipad-horizontal-plus: unicode('f89b'); +$ti-icon-device-ipad-horizontal-question: unicode('f89c'); +$ti-icon-device-ipad-horizontal-search: unicode('f89d'); +$ti-icon-device-ipad-horizontal-share: unicode('f89e'); +$ti-icon-device-ipad-horizontal-star: unicode('f89f'); +$ti-icon-device-ipad-horizontal-up: unicode('f8a0'); +$ti-icon-device-ipad-horizontal-x: unicode('f8a1'); +$ti-icon-device-ipad-minus: unicode('f8a2'); +$ti-icon-device-ipad-off: unicode('f8a3'); +$ti-icon-device-ipad-pause: unicode('f8a4'); +$ti-icon-device-ipad-pin: unicode('f8a5'); +$ti-icon-device-ipad-plus: unicode('f8a6'); +$ti-icon-device-ipad-question: unicode('f8a7'); +$ti-icon-device-ipad-search: unicode('f8a8'); +$ti-icon-device-ipad-share: unicode('f8a9'); +$ti-icon-device-ipad-star: unicode('f8aa'); +$ti-icon-device-ipad-up: unicode('f8ab'); +$ti-icon-device-ipad-x: unicode('f8ac'); +$ti-icon-device-landline-phone: unicode('f649'); +$ti-icon-device-laptop: unicode('eb64'); +$ti-icon-device-laptop-off: unicode('f061'); +$ti-icon-device-mobile: unicode('ea8a'); +$ti-icon-device-mobile-bolt: unicode('f8ad'); +$ti-icon-device-mobile-cancel: unicode('f8ae'); +$ti-icon-device-mobile-charging: unicode('f224'); +$ti-icon-device-mobile-check: unicode('f8af'); +$ti-icon-device-mobile-code: unicode('f8b0'); +$ti-icon-device-mobile-cog: unicode('f8b1'); +$ti-icon-device-mobile-dollar: unicode('f8b2'); +$ti-icon-device-mobile-down: unicode('f8b3'); +$ti-icon-device-mobile-exclamation: unicode('f8b4'); +$ti-icon-device-mobile-heart: unicode('f8b5'); +$ti-icon-device-mobile-message: unicode('ee79'); +$ti-icon-device-mobile-minus: unicode('f8b6'); +$ti-icon-device-mobile-off: unicode('f062'); +$ti-icon-device-mobile-pause: unicode('f8b7'); +$ti-icon-device-mobile-pin: unicode('f8b8'); +$ti-icon-device-mobile-plus: unicode('f8b9'); +$ti-icon-device-mobile-question: unicode('f8ba'); +$ti-icon-device-mobile-rotated: unicode('ecdb'); +$ti-icon-device-mobile-search: unicode('f8bb'); +$ti-icon-device-mobile-share: unicode('f8bc'); +$ti-icon-device-mobile-star: unicode('f8bd'); +$ti-icon-device-mobile-up: unicode('f8be'); +$ti-icon-device-mobile-vibration: unicode('eb86'); +$ti-icon-device-mobile-x: unicode('f8bf'); +$ti-icon-device-nintendo: unicode('f026'); +$ti-icon-device-nintendo-off: unicode('f111'); +$ti-icon-device-remote: unicode('f792'); +$ti-icon-device-sd-card: unicode('f384'); +$ti-icon-device-sim: unicode('f4b2'); +$ti-icon-device-sim-1: unicode('f4af'); +$ti-icon-device-sim-2: unicode('f4b0'); +$ti-icon-device-sim-3: unicode('f4b1'); +$ti-icon-device-speaker: unicode('ea8b'); +$ti-icon-device-speaker-off: unicode('f112'); +$ti-icon-device-tablet: unicode('ea8c'); +$ti-icon-device-tablet-bolt: unicode('f8c0'); +$ti-icon-device-tablet-cancel: unicode('f8c1'); +$ti-icon-device-tablet-check: unicode('f8c2'); +$ti-icon-device-tablet-code: unicode('f8c3'); +$ti-icon-device-tablet-cog: unicode('f8c4'); +$ti-icon-device-tablet-dollar: unicode('f8c5'); +$ti-icon-device-tablet-down: unicode('f8c6'); +$ti-icon-device-tablet-exclamation: unicode('f8c7'); +$ti-icon-device-tablet-heart: unicode('f8c8'); +$ti-icon-device-tablet-minus: unicode('f8c9'); +$ti-icon-device-tablet-off: unicode('f063'); +$ti-icon-device-tablet-pause: unicode('f8ca'); +$ti-icon-device-tablet-pin: unicode('f8cb'); +$ti-icon-device-tablet-plus: unicode('f8cc'); +$ti-icon-device-tablet-question: unicode('f8cd'); +$ti-icon-device-tablet-search: unicode('f8ce'); +$ti-icon-device-tablet-share: unicode('f8cf'); +$ti-icon-device-tablet-star: unicode('f8d0'); +$ti-icon-device-tablet-up: unicode('f8d1'); +$ti-icon-device-tablet-x: unicode('f8d2'); +$ti-icon-device-tv: unicode('ea8d'); +$ti-icon-device-tv-off: unicode('f064'); +$ti-icon-device-tv-old: unicode('f1d3'); +$ti-icon-device-watch: unicode('ebf9'); +$ti-icon-device-watch-bolt: unicode('f8d3'); +$ti-icon-device-watch-cancel: unicode('f8d4'); +$ti-icon-device-watch-check: unicode('f8d5'); +$ti-icon-device-watch-code: unicode('f8d6'); +$ti-icon-device-watch-cog: unicode('f8d7'); +$ti-icon-device-watch-dollar: unicode('f8d8'); +$ti-icon-device-watch-down: unicode('f8d9'); +$ti-icon-device-watch-exclamation: unicode('f8da'); +$ti-icon-device-watch-heart: unicode('f8db'); +$ti-icon-device-watch-minus: unicode('f8dc'); +$ti-icon-device-watch-off: unicode('f065'); +$ti-icon-device-watch-pause: unicode('f8dd'); +$ti-icon-device-watch-pin: unicode('f8de'); +$ti-icon-device-watch-plus: unicode('f8df'); +$ti-icon-device-watch-question: unicode('f8e0'); +$ti-icon-device-watch-search: unicode('f8e1'); +$ti-icon-device-watch-share: unicode('f8e2'); +$ti-icon-device-watch-star: unicode('f8e3'); +$ti-icon-device-watch-stats: unicode('ef7d'); +$ti-icon-device-watch-stats-2: unicode('ef7c'); +$ti-icon-device-watch-up: unicode('f8e4'); +$ti-icon-device-watch-x: unicode('f8e5'); +$ti-icon-devices: unicode('eb87'); +$ti-icon-devices-2: unicode('ed29'); +$ti-icon-devices-bolt: unicode('f8e6'); +$ti-icon-devices-cancel: unicode('f8e7'); +$ti-icon-devices-check: unicode('f8e8'); +$ti-icon-devices-code: unicode('f8e9'); +$ti-icon-devices-cog: unicode('f8ea'); +$ti-icon-devices-dollar: unicode('f8eb'); +$ti-icon-devices-down: unicode('f8ec'); +$ti-icon-devices-exclamation: unicode('f8ed'); +$ti-icon-devices-heart: unicode('f8ee'); +$ti-icon-devices-minus: unicode('f8ef'); +$ti-icon-devices-off: unicode('f3e4'); +$ti-icon-devices-pause: unicode('f8f0'); +$ti-icon-devices-pc: unicode('ee7a'); +$ti-icon-devices-pc-off: unicode('f113'); +$ti-icon-devices-pin: unicode('f8f1'); +$ti-icon-devices-plus: unicode('f8f2'); +$ti-icon-devices-question: unicode('f8f3'); +$ti-icon-devices-search: unicode('f8f4'); +$ti-icon-devices-share: unicode('f8f5'); +$ti-icon-devices-star: unicode('f8f6'); +$ti-icon-devices-up: unicode('f8f7'); +$ti-icon-devices-x: unicode('f8f8'); +$ti-icon-dialpad: unicode('f067'); +$ti-icon-dialpad-off: unicode('f114'); +$ti-icon-diamond: unicode('eb65'); +$ti-icon-diamond-filled: unicode('f73d'); +$ti-icon-diamond-off: unicode('f115'); +$ti-icon-diamonds: unicode('eff5'); +$ti-icon-diamonds-filled: unicode('f676'); +$ti-icon-dice: unicode('eb66'); +$ti-icon-dice-1: unicode('f08b'); +$ti-icon-dice-1-filled: unicode('f73e'); +$ti-icon-dice-2: unicode('f08c'); +$ti-icon-dice-2-filled: unicode('f73f'); +$ti-icon-dice-3: unicode('f08d'); +$ti-icon-dice-3-filled: unicode('f740'); +$ti-icon-dice-4: unicode('f08e'); +$ti-icon-dice-4-filled: unicode('f741'); +$ti-icon-dice-5: unicode('f08f'); +$ti-icon-dice-5-filled: unicode('f742'); +$ti-icon-dice-6: unicode('f090'); +$ti-icon-dice-6-filled: unicode('f743'); +$ti-icon-dice-filled: unicode('f744'); +$ti-icon-dimensions: unicode('ee7b'); +$ti-icon-direction: unicode('ebfb'); +$ti-icon-direction-horizontal: unicode('ebfa'); +$ti-icon-direction-sign: unicode('f1f7'); +$ti-icon-direction-sign-filled: unicode('f745'); +$ti-icon-direction-sign-off: unicode('f3e5'); +$ti-icon-directions: unicode('ea8e'); +$ti-icon-directions-off: unicode('f116'); +$ti-icon-disabled: unicode('ea8f'); +$ti-icon-disabled-2: unicode('ebaf'); +$ti-icon-disabled-off: unicode('f117'); +$ti-icon-disc: unicode('ea90'); +$ti-icon-disc-golf: unicode('f385'); +$ti-icon-disc-off: unicode('f118'); +$ti-icon-discount: unicode('ebbd'); +$ti-icon-discount-2: unicode('ee7c'); +$ti-icon-discount-2-off: unicode('f3e6'); +$ti-icon-discount-check: unicode('f1f8'); +$ti-icon-discount-check-filled: unicode('f746'); +$ti-icon-discount-off: unicode('f3e7'); +$ti-icon-divide: unicode('ed5c'); +$ti-icon-dna: unicode('ee7d'); +$ti-icon-dna-2: unicode('ef5c'); +$ti-icon-dna-2-off: unicode('f119'); +$ti-icon-dna-off: unicode('f11a'); +$ti-icon-dog: unicode('f660'); +$ti-icon-dog-bowl: unicode('ef29'); +$ti-icon-door: unicode('ef4e'); +$ti-icon-door-enter: unicode('ef4c'); +$ti-icon-door-exit: unicode('ef4d'); +$ti-icon-door-off: unicode('f11b'); +$ti-icon-dots: unicode('ea95'); +$ti-icon-dots-circle-horizontal: unicode('ea91'); +$ti-icon-dots-diagonal: unicode('ea93'); +$ti-icon-dots-diagonal-2: unicode('ea92'); +$ti-icon-dots-vertical: unicode('ea94'); +$ti-icon-download: unicode('ea96'); +$ti-icon-download-off: unicode('f11c'); +$ti-icon-drag-drop: unicode('eb89'); +$ti-icon-drag-drop-2: unicode('eb88'); +$ti-icon-drone: unicode('ed79'); +$ti-icon-drone-off: unicode('ee7e'); +$ti-icon-drop-circle: unicode('efde'); +$ti-icon-droplet: unicode('ea97'); +$ti-icon-droplet-bolt: unicode('f8f9'); +$ti-icon-droplet-cancel: unicode('f8fa'); +$ti-icon-droplet-check: unicode('f8fb'); +$ti-icon-droplet-code: unicode('f8fc'); +$ti-icon-droplet-cog: unicode('f8fd'); +$ti-icon-droplet-dollar: unicode('f8fe'); +$ti-icon-droplet-down: unicode('f8ff'); +$ti-icon-droplet-exclamation: unicode('f900'); +$ti-icon-droplet-filled: unicode('ee80'); +$ti-icon-droplet-filled-2: unicode('ee7f'); +$ti-icon-droplet-half: unicode('ee82'); +$ti-icon-droplet-half-2: unicode('ee81'); +$ti-icon-droplet-half-filled: unicode('f6c5'); +$ti-icon-droplet-heart: unicode('f901'); +$ti-icon-droplet-minus: unicode('f902'); +$ti-icon-droplet-off: unicode('ee83'); +$ti-icon-droplet-pause: unicode('f903'); +$ti-icon-droplet-pin: unicode('f904'); +$ti-icon-droplet-plus: unicode('f905'); +$ti-icon-droplet-question: unicode('f906'); +$ti-icon-droplet-search: unicode('f907'); +$ti-icon-droplet-share: unicode('f908'); +$ti-icon-droplet-star: unicode('f909'); +$ti-icon-droplet-up: unicode('f90a'); +$ti-icon-droplet-x: unicode('f90b'); +$ti-icon-e-passport: unicode('f4df'); +$ti-icon-ear: unicode('ebce'); +$ti-icon-ear-off: unicode('ee84'); +$ti-icon-ease-in: unicode('f573'); +$ti-icon-ease-in-control-point: unicode('f570'); +$ti-icon-ease-in-out: unicode('f572'); +$ti-icon-ease-in-out-control-points: unicode('f571'); +$ti-icon-ease-out: unicode('f575'); +$ti-icon-ease-out-control-point: unicode('f574'); +$ti-icon-edit: unicode('ea98'); +$ti-icon-edit-circle: unicode('ee85'); +$ti-icon-edit-circle-off: unicode('f11d'); +$ti-icon-edit-off: unicode('f11e'); +$ti-icon-egg: unicode('eb8a'); +$ti-icon-egg-cracked: unicode('f2d6'); +$ti-icon-egg-filled: unicode('f678'); +$ti-icon-egg-fried: unicode('f386'); +$ti-icon-egg-off: unicode('f11f'); +$ti-icon-eggs: unicode('f500'); +$ti-icon-elevator: unicode('efdf'); +$ti-icon-elevator-off: unicode('f3e8'); +$ti-icon-emergency-bed: unicode('ef5d'); +$ti-icon-empathize: unicode('f29b'); +$ti-icon-empathize-off: unicode('f3e9'); +$ti-icon-emphasis: unicode('ebcf'); +$ti-icon-engine: unicode('ef7e'); +$ti-icon-engine-off: unicode('f120'); +$ti-icon-equal: unicode('ee87'); +$ti-icon-equal-double: unicode('f4e1'); +$ti-icon-equal-not: unicode('ee86'); +$ti-icon-eraser: unicode('eb8b'); +$ti-icon-eraser-off: unicode('f121'); +$ti-icon-error-404: unicode('f027'); +$ti-icon-error-404-off: unicode('f122'); +$ti-icon-exchange: unicode('ebe7'); +$ti-icon-exchange-off: unicode('f123'); +$ti-icon-exclamation-circle: unicode('f634'); +$ti-icon-exclamation-mark: unicode('efb4'); +$ti-icon-exclamation-mark-off: unicode('f124'); +$ti-icon-explicit: unicode('f256'); +$ti-icon-explicit-off: unicode('f3ea'); +$ti-icon-exposure: unicode('eb8c'); +$ti-icon-exposure-0: unicode('f29c'); +$ti-icon-exposure-minus-1: unicode('f29d'); +$ti-icon-exposure-minus-2: unicode('f29e'); +$ti-icon-exposure-off: unicode('f3eb'); +$ti-icon-exposure-plus-1: unicode('f29f'); +$ti-icon-exposure-plus-2: unicode('f2a0'); +$ti-icon-external-link: unicode('ea99'); +$ti-icon-external-link-off: unicode('f125'); +$ti-icon-eye: unicode('ea9a'); +$ti-icon-eye-check: unicode('ee88'); +$ti-icon-eye-closed: unicode('f7ec'); +$ti-icon-eye-cog: unicode('f7ed'); +$ti-icon-eye-edit: unicode('f7ee'); +$ti-icon-eye-exclamation: unicode('f7ef'); +$ti-icon-eye-filled: unicode('f679'); +$ti-icon-eye-heart: unicode('f7f0'); +$ti-icon-eye-off: unicode('ecf0'); +$ti-icon-eye-table: unicode('ef5e'); +$ti-icon-eye-x: unicode('f7f1'); +$ti-icon-eyeglass: unicode('ee8a'); +$ti-icon-eyeglass-2: unicode('ee89'); +$ti-icon-eyeglass-off: unicode('f126'); +$ti-icon-face-id: unicode('ea9b'); +$ti-icon-face-id-error: unicode('efa7'); +$ti-icon-face-mask: unicode('efb5'); +$ti-icon-face-mask-off: unicode('f127'); +$ti-icon-fall: unicode('ecb9'); +$ti-icon-feather: unicode('ee8b'); +$ti-icon-feather-off: unicode('f128'); +$ti-icon-fence: unicode('ef2a'); +$ti-icon-fence-off: unicode('f129'); +$ti-icon-fidget-spinner: unicode('f068'); +$ti-icon-file: unicode('eaa4'); +$ti-icon-file-3d: unicode('f032'); +$ti-icon-file-alert: unicode('ede6'); +$ti-icon-file-analytics: unicode('ede7'); +$ti-icon-file-arrow-left: unicode('f033'); +$ti-icon-file-arrow-right: unicode('f034'); +$ti-icon-file-barcode: unicode('f035'); +$ti-icon-file-broken: unicode('f501'); +$ti-icon-file-certificate: unicode('ed4d'); +$ti-icon-file-chart: unicode('f036'); +$ti-icon-file-check: unicode('ea9c'); +$ti-icon-file-code: unicode('ebd0'); +$ti-icon-file-code-2: unicode('ede8'); +$ti-icon-file-database: unicode('f037'); +$ti-icon-file-delta: unicode('f53d'); +$ti-icon-file-description: unicode('f028'); +$ti-icon-file-diff: unicode('ecf1'); +$ti-icon-file-digit: unicode('efa8'); +$ti-icon-file-dislike: unicode('ed2a'); +$ti-icon-file-dollar: unicode('efe0'); +$ti-icon-file-dots: unicode('f038'); +$ti-icon-file-download: unicode('ea9d'); +$ti-icon-file-euro: unicode('efe1'); +$ti-icon-file-export: unicode('ede9'); +$ti-icon-file-filled: unicode('f747'); +$ti-icon-file-function: unicode('f53e'); +$ti-icon-file-horizontal: unicode('ebb0'); +$ti-icon-file-import: unicode('edea'); +$ti-icon-file-infinity: unicode('f502'); +$ti-icon-file-info: unicode('edec'); +$ti-icon-file-invoice: unicode('eb67'); +$ti-icon-file-lambda: unicode('f53f'); +$ti-icon-file-like: unicode('ed2b'); +$ti-icon-file-minus: unicode('ea9e'); +$ti-icon-file-music: unicode('ea9f'); +$ti-icon-file-off: unicode('ecf2'); +$ti-icon-file-orientation: unicode('f2a1'); +$ti-icon-file-pencil: unicode('f039'); +$ti-icon-file-percent: unicode('f540'); +$ti-icon-file-phone: unicode('ecdc'); +$ti-icon-file-plus: unicode('eaa0'); +$ti-icon-file-power: unicode('f03a'); +$ti-icon-file-report: unicode('eded'); +$ti-icon-file-rss: unicode('f03b'); +$ti-icon-file-scissors: unicode('f03c'); +$ti-icon-file-search: unicode('ed5d'); +$ti-icon-file-settings: unicode('f029'); +$ti-icon-file-shredder: unicode('eaa1'); +$ti-icon-file-signal: unicode('f03d'); +$ti-icon-file-spreadsheet: unicode('f03e'); +$ti-icon-file-stack: unicode('f503'); +$ti-icon-file-star: unicode('f03f'); +$ti-icon-file-symlink: unicode('ed53'); +$ti-icon-file-text: unicode('eaa2'); +$ti-icon-file-time: unicode('f040'); +$ti-icon-file-typography: unicode('f041'); +$ti-icon-file-unknown: unicode('f042'); +$ti-icon-file-upload: unicode('ec91'); +$ti-icon-file-vector: unicode('f043'); +$ti-icon-file-x: unicode('eaa3'); +$ti-icon-file-x-filled: unicode('f748'); +$ti-icon-file-zip: unicode('ed4e'); +$ti-icon-files: unicode('edef'); +$ti-icon-files-off: unicode('edee'); +$ti-icon-filter: unicode('eaa5'); +$ti-icon-filter-off: unicode('ed2c'); +$ti-icon-filters: unicode('f793'); +$ti-icon-fingerprint: unicode('ebd1'); +$ti-icon-fingerprint-off: unicode('f12a'); +$ti-icon-fire-hydrant: unicode('f3a9'); +$ti-icon-fire-hydrant-off: unicode('f3ec'); +$ti-icon-firetruck: unicode('ebe8'); +$ti-icon-first-aid-kit: unicode('ef5f'); +$ti-icon-first-aid-kit-off: unicode('f3ed'); +$ti-icon-fish: unicode('ef2b'); +$ti-icon-fish-bone: unicode('f287'); +$ti-icon-fish-christianity: unicode('f58b'); +$ti-icon-fish-hook: unicode('f1f9'); +$ti-icon-fish-hook-off: unicode('f3ee'); +$ti-icon-fish-off: unicode('f12b'); +$ti-icon-flag: unicode('eaa6'); +$ti-icon-flag-2: unicode('ee8c'); +$ti-icon-flag-2-filled: unicode('f707'); +$ti-icon-flag-2-off: unicode('f12c'); +$ti-icon-flag-3: unicode('ee8d'); +$ti-icon-flag-3-filled: unicode('f708'); +$ti-icon-flag-filled: unicode('f67a'); +$ti-icon-flag-off: unicode('f12d'); +$ti-icon-flame: unicode('ec2c'); +$ti-icon-flame-off: unicode('f12e'); +$ti-icon-flare: unicode('ee8e'); +$ti-icon-flask: unicode('ebd2'); +$ti-icon-flask-2: unicode('ef60'); +$ti-icon-flask-2-off: unicode('f12f'); +$ti-icon-flask-off: unicode('f130'); +$ti-icon-flip-flops: unicode('f564'); +$ti-icon-flip-horizontal: unicode('eaa7'); +$ti-icon-flip-vertical: unicode('eaa8'); +$ti-icon-float-center: unicode('ebb1'); +$ti-icon-float-left: unicode('ebb2'); +$ti-icon-float-none: unicode('ed13'); +$ti-icon-float-right: unicode('ebb3'); +$ti-icon-flower: unicode('eff6'); +$ti-icon-flower-off: unicode('f131'); +$ti-icon-focus: unicode('eb8d'); +$ti-icon-focus-2: unicode('ebd3'); +$ti-icon-focus-centered: unicode('f02a'); +$ti-icon-fold: unicode('ed56'); +$ti-icon-fold-down: unicode('ed54'); +$ti-icon-fold-up: unicode('ed55'); +$ti-icon-folder: unicode('eaad'); +$ti-icon-folder-bolt: unicode('f90c'); +$ti-icon-folder-cancel: unicode('f90d'); +$ti-icon-folder-check: unicode('f90e'); +$ti-icon-folder-code: unicode('f90f'); +$ti-icon-folder-cog: unicode('f910'); +$ti-icon-folder-dollar: unicode('f911'); +$ti-icon-folder-down: unicode('f912'); +$ti-icon-folder-exclamation: unicode('f913'); +$ti-icon-folder-filled: unicode('f749'); +$ti-icon-folder-heart: unicode('f914'); +$ti-icon-folder-minus: unicode('eaaa'); +$ti-icon-folder-off: unicode('ed14'); +$ti-icon-folder-pause: unicode('f915'); +$ti-icon-folder-pin: unicode('f916'); +$ti-icon-folder-plus: unicode('eaab'); +$ti-icon-folder-question: unicode('f917'); +$ti-icon-folder-search: unicode('f918'); +$ti-icon-folder-share: unicode('f919'); +$ti-icon-folder-star: unicode('f91a'); +$ti-icon-folder-symlink: unicode('f91b'); +$ti-icon-folder-up: unicode('f91c'); +$ti-icon-folder-x: unicode('eaac'); +$ti-icon-folders: unicode('eaae'); +$ti-icon-folders-off: unicode('f133'); +$ti-icon-forbid: unicode('ebd5'); +$ti-icon-forbid-2: unicode('ebd4'); +$ti-icon-forklift: unicode('ebe9'); +$ti-icon-forms: unicode('ee8f'); +$ti-icon-fountain: unicode('f09b'); +$ti-icon-fountain-off: unicode('f134'); +$ti-icon-frame: unicode('eaaf'); +$ti-icon-frame-off: unicode('f135'); +$ti-icon-free-rights: unicode('efb6'); +$ti-icon-fridge: unicode('f1fa'); +$ti-icon-fridge-off: unicode('f3ef'); +$ti-icon-friends: unicode('eab0'); +$ti-icon-friends-off: unicode('f136'); +$ti-icon-function: unicode('f225'); +$ti-icon-function-off: unicode('f3f0'); +$ti-icon-garden-cart: unicode('f23e'); +$ti-icon-garden-cart-off: unicode('f3f1'); +$ti-icon-gas-station: unicode('ec7d'); +$ti-icon-gas-station-off: unicode('f137'); +$ti-icon-gauge: unicode('eab1'); +$ti-icon-gauge-off: unicode('f138'); +$ti-icon-gavel: unicode('ef90'); +$ti-icon-gender-agender: unicode('f0e1'); +$ti-icon-gender-androgyne: unicode('f0e2'); +$ti-icon-gender-bigender: unicode('f0e3'); +$ti-icon-gender-demiboy: unicode('f0e4'); +$ti-icon-gender-demigirl: unicode('f0e5'); +$ti-icon-gender-epicene: unicode('f0e6'); +$ti-icon-gender-female: unicode('f0e7'); +$ti-icon-gender-femme: unicode('f0e8'); +$ti-icon-gender-genderfluid: unicode('f0e9'); +$ti-icon-gender-genderless: unicode('f0ea'); +$ti-icon-gender-genderqueer: unicode('f0eb'); +$ti-icon-gender-hermaphrodite: unicode('f0ec'); +$ti-icon-gender-intergender: unicode('f0ed'); +$ti-icon-gender-male: unicode('f0ee'); +$ti-icon-gender-neutrois: unicode('f0ef'); +$ti-icon-gender-third: unicode('f0f0'); +$ti-icon-gender-transgender: unicode('f0f1'); +$ti-icon-gender-trasvesti: unicode('f0f2'); +$ti-icon-geometry: unicode('ee90'); +$ti-icon-ghost: unicode('eb8e'); +$ti-icon-ghost-2: unicode('f57c'); +$ti-icon-ghost-2-filled: unicode('f74a'); +$ti-icon-ghost-filled: unicode('f74b'); +$ti-icon-ghost-off: unicode('f3f2'); +$ti-icon-gif: unicode('f257'); +$ti-icon-gift: unicode('eb68'); +$ti-icon-gift-card: unicode('f3aa'); +$ti-icon-gift-off: unicode('f3f3'); +$ti-icon-git-branch: unicode('eab2'); +$ti-icon-git-branch-deleted: unicode('f57d'); +$ti-icon-git-cherry-pick: unicode('f57e'); +$ti-icon-git-commit: unicode('eab3'); +$ti-icon-git-compare: unicode('eab4'); +$ti-icon-git-fork: unicode('eb8f'); +$ti-icon-git-merge: unicode('eab5'); +$ti-icon-git-pull-request: unicode('eab6'); +$ti-icon-git-pull-request-closed: unicode('ef7f'); +$ti-icon-git-pull-request-draft: unicode('efb7'); +$ti-icon-gizmo: unicode('f02b'); +$ti-icon-glass: unicode('eab8'); +$ti-icon-glass-full: unicode('eab7'); +$ti-icon-glass-off: unicode('ee91'); +$ti-icon-globe: unicode('eab9'); +$ti-icon-globe-off: unicode('f139'); +$ti-icon-go-game: unicode('f512'); +$ti-icon-golf: unicode('ed8c'); +$ti-icon-golf-off: unicode('f13a'); +$ti-icon-gps: unicode('ed7a'); +$ti-icon-gradienter: unicode('f3ab'); +$ti-icon-grain: unicode('ee92'); +$ti-icon-graph: unicode('f288'); +$ti-icon-graph-off: unicode('f3f4'); +$ti-icon-grave: unicode('f580'); +$ti-icon-grave-2: unicode('f57f'); +$ti-icon-grid-dots: unicode('eaba'); +$ti-icon-grid-pattern: unicode('efc9'); +$ti-icon-grill: unicode('efa9'); +$ti-icon-grill-fork: unicode('f35b'); +$ti-icon-grill-off: unicode('f3f5'); +$ti-icon-grill-spatula: unicode('f35c'); +$ti-icon-grip-horizontal: unicode('ec00'); +$ti-icon-grip-vertical: unicode('ec01'); +$ti-icon-growth: unicode('ee93'); +$ti-icon-guitar-pick: unicode('f4c6'); +$ti-icon-guitar-pick-filled: unicode('f67b'); +$ti-icon-h-1: unicode('ec94'); +$ti-icon-h-2: unicode('ec95'); +$ti-icon-h-3: unicode('ec96'); +$ti-icon-h-4: unicode('ec97'); +$ti-icon-h-5: unicode('ec98'); +$ti-icon-h-6: unicode('ec99'); +$ti-icon-hammer: unicode('ef91'); +$ti-icon-hammer-off: unicode('f13c'); +$ti-icon-hand-click: unicode('ef4f'); +$ti-icon-hand-finger: unicode('ee94'); +$ti-icon-hand-finger-off: unicode('f13d'); +$ti-icon-hand-grab: unicode('f091'); +$ti-icon-hand-little-finger: unicode('ee95'); +$ti-icon-hand-middle-finger: unicode('ec2d'); +$ti-icon-hand-move: unicode('ef50'); +$ti-icon-hand-off: unicode('ed15'); +$ti-icon-hand-ring-finger: unicode('ee96'); +$ti-icon-hand-rock: unicode('ee97'); +$ti-icon-hand-sanitizer: unicode('f5f4'); +$ti-icon-hand-stop: unicode('ec2e'); +$ti-icon-hand-three-fingers: unicode('ee98'); +$ti-icon-hand-two-fingers: unicode('ee99'); +$ti-icon-hanger: unicode('ee9a'); +$ti-icon-hanger-2: unicode('f09c'); +$ti-icon-hanger-off: unicode('f13e'); +$ti-icon-hash: unicode('eabc'); +$ti-icon-haze: unicode('efaa'); +$ti-icon-heading: unicode('ee9b'); +$ti-icon-heading-off: unicode('f13f'); +$ti-icon-headphones: unicode('eabd'); +$ti-icon-headphones-off: unicode('ed1d'); +$ti-icon-headset: unicode('eb90'); +$ti-icon-headset-off: unicode('f3f6'); +$ti-icon-health-recognition: unicode('f1fb'); +$ti-icon-heart: unicode('eabe'); +$ti-icon-heart-broken: unicode('ecba'); +$ti-icon-heart-filled: unicode('f67c'); +$ti-icon-heart-handshake: unicode('f0f3'); +$ti-icon-heart-minus: unicode('f140'); +$ti-icon-heart-off: unicode('f141'); +$ti-icon-heart-plus: unicode('f142'); +$ti-icon-heart-rate-monitor: unicode('ef61'); +$ti-icon-heartbeat: unicode('ef92'); +$ti-icon-hearts: unicode('f387'); +$ti-icon-hearts-off: unicode('f3f7'); +$ti-icon-helicopter: unicode('ed8e'); +$ti-icon-helicopter-landing: unicode('ed8d'); +$ti-icon-helmet: unicode('efca'); +$ti-icon-helmet-off: unicode('f143'); +$ti-icon-help: unicode('eabf'); +$ti-icon-help-circle: unicode('f91d'); +$ti-icon-help-hexagon: unicode('f7a8'); +$ti-icon-help-octagon: unicode('f7a9'); +$ti-icon-help-off: unicode('f3f8'); +$ti-icon-help-small: unicode('f91e'); +$ti-icon-help-square: unicode('f920'); +$ti-icon-help-square-rounded: unicode('f91f'); +$ti-icon-help-triangle: unicode('f921'); +$ti-icon-hexagon: unicode('ec02'); +$ti-icon-hexagon-0-filled: unicode('f74c'); +$ti-icon-hexagon-1-filled: unicode('f74d'); +$ti-icon-hexagon-2-filled: unicode('f74e'); +$ti-icon-hexagon-3-filled: unicode('f74f'); +$ti-icon-hexagon-3d: unicode('f4c7'); +$ti-icon-hexagon-4-filled: unicode('f750'); +$ti-icon-hexagon-5-filled: unicode('f751'); +$ti-icon-hexagon-6-filled: unicode('f752'); +$ti-icon-hexagon-7-filled: unicode('f753'); +$ti-icon-hexagon-8-filled: unicode('f754'); +$ti-icon-hexagon-9-filled: unicode('f755'); +$ti-icon-hexagon-filled: unicode('f67d'); +$ti-icon-hexagon-letter-a: unicode('f463'); +$ti-icon-hexagon-letter-b: unicode('f464'); +$ti-icon-hexagon-letter-c: unicode('f465'); +$ti-icon-hexagon-letter-d: unicode('f466'); +$ti-icon-hexagon-letter-e: unicode('f467'); +$ti-icon-hexagon-letter-f: unicode('f468'); +$ti-icon-hexagon-letter-g: unicode('f469'); +$ti-icon-hexagon-letter-h: unicode('f46a'); +$ti-icon-hexagon-letter-i: unicode('f46b'); +$ti-icon-hexagon-letter-j: unicode('f46c'); +$ti-icon-hexagon-letter-k: unicode('f46d'); +$ti-icon-hexagon-letter-l: unicode('f46e'); +$ti-icon-hexagon-letter-m: unicode('f46f'); +$ti-icon-hexagon-letter-n: unicode('f470'); +$ti-icon-hexagon-letter-o: unicode('f471'); +$ti-icon-hexagon-letter-p: unicode('f472'); +$ti-icon-hexagon-letter-q: unicode('f473'); +$ti-icon-hexagon-letter-r: unicode('f474'); +$ti-icon-hexagon-letter-s: unicode('f475'); +$ti-icon-hexagon-letter-t: unicode('f476'); +$ti-icon-hexagon-letter-u: unicode('f477'); +$ti-icon-hexagon-letter-v: unicode('f4b3'); +$ti-icon-hexagon-letter-w: unicode('f478'); +$ti-icon-hexagon-letter-x: unicode('f479'); +$ti-icon-hexagon-letter-y: unicode('f47a'); +$ti-icon-hexagon-letter-z: unicode('f47b'); +$ti-icon-hexagon-number-0: unicode('f459'); +$ti-icon-hexagon-number-1: unicode('f45a'); +$ti-icon-hexagon-number-2: unicode('f45b'); +$ti-icon-hexagon-number-3: unicode('f45c'); +$ti-icon-hexagon-number-4: unicode('f45d'); +$ti-icon-hexagon-number-5: unicode('f45e'); +$ti-icon-hexagon-number-6: unicode('f45f'); +$ti-icon-hexagon-number-7: unicode('f460'); +$ti-icon-hexagon-number-8: unicode('f461'); +$ti-icon-hexagon-number-9: unicode('f462'); +$ti-icon-hexagon-off: unicode('ee9c'); +$ti-icon-hexagons: unicode('f09d'); +$ti-icon-hexagons-off: unicode('f3f9'); +$ti-icon-hierarchy: unicode('ee9e'); +$ti-icon-hierarchy-2: unicode('ee9d'); +$ti-icon-hierarchy-3: unicode('f289'); +$ti-icon-hierarchy-off: unicode('f3fa'); +$ti-icon-highlight: unicode('ef3f'); +$ti-icon-highlight-off: unicode('f144'); +$ti-icon-history: unicode('ebea'); +$ti-icon-history-off: unicode('f3fb'); +$ti-icon-history-toggle: unicode('f1fc'); +$ti-icon-home: unicode('eac1'); +$ti-icon-home-2: unicode('eac0'); +$ti-icon-home-bolt: unicode('f336'); +$ti-icon-home-cancel: unicode('f350'); +$ti-icon-home-check: unicode('f337'); +$ti-icon-home-cog: unicode('f338'); +$ti-icon-home-dollar: unicode('f339'); +$ti-icon-home-dot: unicode('f33a'); +$ti-icon-home-down: unicode('f33b'); +$ti-icon-home-eco: unicode('f351'); +$ti-icon-home-edit: unicode('f352'); +$ti-icon-home-exclamation: unicode('f33c'); +$ti-icon-home-hand: unicode('f504'); +$ti-icon-home-heart: unicode('f353'); +$ti-icon-home-infinity: unicode('f505'); +$ti-icon-home-link: unicode('f354'); +$ti-icon-home-minus: unicode('f33d'); +$ti-icon-home-move: unicode('f33e'); +$ti-icon-home-off: unicode('f145'); +$ti-icon-home-plus: unicode('f33f'); +$ti-icon-home-question: unicode('f340'); +$ti-icon-home-ribbon: unicode('f355'); +$ti-icon-home-search: unicode('f341'); +$ti-icon-home-share: unicode('f342'); +$ti-icon-home-shield: unicode('f343'); +$ti-icon-home-signal: unicode('f356'); +$ti-icon-home-star: unicode('f344'); +$ti-icon-home-stats: unicode('f345'); +$ti-icon-home-up: unicode('f346'); +$ti-icon-home-x: unicode('f347'); +$ti-icon-horse-toy: unicode('f28a'); +$ti-icon-hotel-service: unicode('ef80'); +$ti-icon-hourglass: unicode('ef93'); +$ti-icon-hourglass-empty: unicode('f146'); +$ti-icon-hourglass-filled: unicode('f756'); +$ti-icon-hourglass-high: unicode('f092'); +$ti-icon-hourglass-low: unicode('f093'); +$ti-icon-hourglass-off: unicode('f147'); +$ti-icon-html: unicode('f7b1'); +$ti-icon-ice-cream: unicode('eac2'); +$ti-icon-ice-cream-2: unicode('ee9f'); +$ti-icon-ice-cream-off: unicode('f148'); +$ti-icon-ice-skating: unicode('efcb'); +$ti-icon-icons: unicode('f1d4'); +$ti-icon-icons-off: unicode('f3fc'); +$ti-icon-id: unicode('eac3'); +$ti-icon-id-badge: unicode('eff7'); +$ti-icon-id-badge-2: unicode('f076'); +$ti-icon-id-badge-off: unicode('f3fd'); +$ti-icon-id-off: unicode('f149'); +$ti-icon-inbox: unicode('eac4'); +$ti-icon-inbox-off: unicode('f14a'); +$ti-icon-indent-decrease: unicode('eb91'); +$ti-icon-indent-increase: unicode('eb92'); +$ti-icon-infinity: unicode('eb69'); +$ti-icon-infinity-off: unicode('f3fe'); +$ti-icon-info-circle: unicode('eac5'); +$ti-icon-info-circle-filled: unicode('f6d8'); +$ti-icon-info-hexagon: unicode('f7aa'); +$ti-icon-info-octagon: unicode('f7ab'); +$ti-icon-info-small: unicode('f922'); +$ti-icon-info-square: unicode('eac6'); +$ti-icon-info-square-rounded: unicode('f635'); +$ti-icon-info-square-rounded-filled: unicode('f6d9'); +$ti-icon-info-triangle: unicode('f923'); +$ti-icon-inner-shadow-bottom: unicode('f520'); +$ti-icon-inner-shadow-bottom-filled: unicode('f757'); +$ti-icon-inner-shadow-bottom-left: unicode('f51e'); +$ti-icon-inner-shadow-bottom-left-filled: unicode('f758'); +$ti-icon-inner-shadow-bottom-right: unicode('f51f'); +$ti-icon-inner-shadow-bottom-right-filled: unicode('f759'); +$ti-icon-inner-shadow-left: unicode('f521'); +$ti-icon-inner-shadow-left-filled: unicode('f75a'); +$ti-icon-inner-shadow-right: unicode('f522'); +$ti-icon-inner-shadow-right-filled: unicode('f75b'); +$ti-icon-inner-shadow-top: unicode('f525'); +$ti-icon-inner-shadow-top-filled: unicode('f75c'); +$ti-icon-inner-shadow-top-left: unicode('f523'); +$ti-icon-inner-shadow-top-left-filled: unicode('f75d'); +$ti-icon-inner-shadow-top-right: unicode('f524'); +$ti-icon-inner-shadow-top-right-filled: unicode('f75e'); +$ti-icon-input-search: unicode('f2a2'); +$ti-icon-ironing-1: unicode('f2f4'); +$ti-icon-ironing-2: unicode('f2f5'); +$ti-icon-ironing-3: unicode('f2f6'); +$ti-icon-ironing-off: unicode('f2f7'); +$ti-icon-ironing-steam: unicode('f2f9'); +$ti-icon-ironing-steam-off: unicode('f2f8'); +$ti-icon-italic: unicode('eb93'); +$ti-icon-jacket: unicode('f661'); +$ti-icon-jetpack: unicode('f581'); +$ti-icon-jewish-star: unicode('f3ff'); +$ti-icon-jewish-star-filled: unicode('f67e'); +$ti-icon-jpg: unicode('f3ac'); +$ti-icon-json: unicode('f7b2'); +$ti-icon-jump-rope: unicode('ed8f'); +$ti-icon-karate: unicode('ed32'); +$ti-icon-kayak: unicode('f1d6'); +$ti-icon-kering: unicode('efb8'); +$ti-icon-key: unicode('eac7'); +$ti-icon-key-off: unicode('f14b'); +$ti-icon-keyboard: unicode('ebd6'); +$ti-icon-keyboard-hide: unicode('ec7e'); +$ti-icon-keyboard-off: unicode('eea0'); +$ti-icon-keyboard-show: unicode('ec7f'); +$ti-icon-keyframe: unicode('f576'); +$ti-icon-keyframe-align-center: unicode('f582'); +$ti-icon-keyframe-align-horizontal: unicode('f583'); +$ti-icon-keyframe-align-vertical: unicode('f584'); +$ti-icon-keyframes: unicode('f585'); +$ti-icon-ladder: unicode('efe2'); +$ti-icon-ladder-off: unicode('f14c'); +$ti-icon-lambda: unicode('f541'); +$ti-icon-lamp: unicode('efab'); +$ti-icon-lamp-2: unicode('f09e'); +$ti-icon-lamp-off: unicode('f14d'); +$ti-icon-language: unicode('ebbe'); +$ti-icon-language-hiragana: unicode('ef77'); +$ti-icon-language-katakana: unicode('ef78'); +$ti-icon-language-off: unicode('f14e'); +$ti-icon-lasso: unicode('efac'); +$ti-icon-lasso-off: unicode('f14f'); +$ti-icon-lasso-polygon: unicode('f388'); +$ti-icon-layers-difference: unicode('eac8'); +$ti-icon-layers-intersect: unicode('eac9'); +$ti-icon-layers-intersect-2: unicode('eff8'); +$ti-icon-layers-linked: unicode('eea1'); +$ti-icon-layers-off: unicode('f150'); +$ti-icon-layers-subtract: unicode('eaca'); +$ti-icon-layers-union: unicode('eacb'); +$ti-icon-layout: unicode('eadb'); +$ti-icon-layout-2: unicode('eacc'); +$ti-icon-layout-align-bottom: unicode('eacd'); +$ti-icon-layout-align-center: unicode('eace'); +$ti-icon-layout-align-left: unicode('eacf'); +$ti-icon-layout-align-middle: unicode('ead0'); +$ti-icon-layout-align-right: unicode('ead1'); +$ti-icon-layout-align-top: unicode('ead2'); +$ti-icon-layout-board: unicode('ef95'); +$ti-icon-layout-board-split: unicode('ef94'); +$ti-icon-layout-bottombar: unicode('ead3'); +$ti-icon-layout-bottombar-collapse: unicode('f28b'); +$ti-icon-layout-bottombar-expand: unicode('f28c'); +$ti-icon-layout-cards: unicode('ec13'); +$ti-icon-layout-collage: unicode('f389'); +$ti-icon-layout-columns: unicode('ead4'); +$ti-icon-layout-dashboard: unicode('f02c'); +$ti-icon-layout-distribute-horizontal: unicode('ead5'); +$ti-icon-layout-distribute-vertical: unicode('ead6'); +$ti-icon-layout-grid: unicode('edba'); +$ti-icon-layout-grid-add: unicode('edb9'); +$ti-icon-layout-kanban: unicode('ec3f'); +$ti-icon-layout-list: unicode('ec14'); +$ti-icon-layout-navbar: unicode('ead7'); +$ti-icon-layout-navbar-collapse: unicode('f28d'); +$ti-icon-layout-navbar-expand: unicode('f28e'); +$ti-icon-layout-off: unicode('f151'); +$ti-icon-layout-rows: unicode('ead8'); +$ti-icon-layout-sidebar: unicode('eada'); +$ti-icon-layout-sidebar-left-collapse: unicode('f004'); +$ti-icon-layout-sidebar-left-expand: unicode('f005'); +$ti-icon-layout-sidebar-right: unicode('ead9'); +$ti-icon-layout-sidebar-right-collapse: unicode('f006'); +$ti-icon-layout-sidebar-right-expand: unicode('f007'); +$ti-icon-leaf: unicode('ed4f'); +$ti-icon-leaf-off: unicode('f400'); +$ti-icon-lego: unicode('eadc'); +$ti-icon-lego-off: unicode('f401'); +$ti-icon-lemon: unicode('ef10'); +$ti-icon-lemon-2: unicode('ef81'); +$ti-icon-letter-a: unicode('ec50'); +$ti-icon-letter-b: unicode('ec51'); +$ti-icon-letter-c: unicode('ec52'); +$ti-icon-letter-case: unicode('eea5'); +$ti-icon-letter-case-lower: unicode('eea2'); +$ti-icon-letter-case-toggle: unicode('eea3'); +$ti-icon-letter-case-upper: unicode('eea4'); +$ti-icon-letter-d: unicode('ec53'); +$ti-icon-letter-e: unicode('ec54'); +$ti-icon-letter-f: unicode('ec55'); +$ti-icon-letter-g: unicode('ec56'); +$ti-icon-letter-h: unicode('ec57'); +$ti-icon-letter-i: unicode('ec58'); +$ti-icon-letter-j: unicode('ec59'); +$ti-icon-letter-k: unicode('ec5a'); +$ti-icon-letter-l: unicode('ec5b'); +$ti-icon-letter-m: unicode('ec5c'); +$ti-icon-letter-n: unicode('ec5d'); +$ti-icon-letter-o: unicode('ec5e'); +$ti-icon-letter-p: unicode('ec5f'); +$ti-icon-letter-q: unicode('ec60'); +$ti-icon-letter-r: unicode('ec61'); +$ti-icon-letter-s: unicode('ec62'); +$ti-icon-letter-spacing: unicode('eea6'); +$ti-icon-letter-t: unicode('ec63'); +$ti-icon-letter-u: unicode('ec64'); +$ti-icon-letter-v: unicode('ec65'); +$ti-icon-letter-w: unicode('ec66'); +$ti-icon-letter-x: unicode('ec67'); +$ti-icon-letter-y: unicode('ec68'); +$ti-icon-letter-z: unicode('ec69'); +$ti-icon-license: unicode('ebc0'); +$ti-icon-license-off: unicode('f153'); +$ti-icon-lifebuoy: unicode('eadd'); +$ti-icon-lifebuoy-off: unicode('f154'); +$ti-icon-lighter: unicode('f794'); +$ti-icon-line: unicode('ec40'); +$ti-icon-line-dashed: unicode('eea7'); +$ti-icon-line-dotted: unicode('eea8'); +$ti-icon-line-height: unicode('eb94'); +$ti-icon-link: unicode('eade'); +$ti-icon-link-off: unicode('f402'); +$ti-icon-list: unicode('eb6b'); +$ti-icon-list-check: unicode('eb6a'); +$ti-icon-list-details: unicode('ef40'); +$ti-icon-list-numbers: unicode('ef11'); +$ti-icon-list-search: unicode('eea9'); +$ti-icon-live-photo: unicode('eadf'); +$ti-icon-live-photo-off: unicode('f403'); +$ti-icon-live-view: unicode('ec6b'); +$ti-icon-loader: unicode('eca3'); +$ti-icon-loader-2: unicode('f226'); +$ti-icon-loader-3: unicode('f513'); +$ti-icon-loader-quarter: unicode('eca2'); +$ti-icon-location: unicode('eae0'); +$ti-icon-location-broken: unicode('f2c4'); +$ti-icon-location-filled: unicode('f67f'); +$ti-icon-location-off: unicode('f155'); +$ti-icon-lock: unicode('eae2'); +$ti-icon-lock-access: unicode('eeaa'); +$ti-icon-lock-access-off: unicode('f404'); +$ti-icon-lock-bolt: unicode('f924'); +$ti-icon-lock-cancel: unicode('f925'); +$ti-icon-lock-check: unicode('f926'); +$ti-icon-lock-code: unicode('f927'); +$ti-icon-lock-cog: unicode('f928'); +$ti-icon-lock-dollar: unicode('f929'); +$ti-icon-lock-down: unicode('f92a'); +$ti-icon-lock-exclamation: unicode('f92b'); +$ti-icon-lock-heart: unicode('f92c'); +$ti-icon-lock-minus: unicode('f92d'); +$ti-icon-lock-off: unicode('ed1e'); +$ti-icon-lock-open: unicode('eae1'); +$ti-icon-lock-open-off: unicode('f156'); +$ti-icon-lock-pause: unicode('f92e'); +$ti-icon-lock-pin: unicode('f92f'); +$ti-icon-lock-plus: unicode('f930'); +$ti-icon-lock-question: unicode('f931'); +$ti-icon-lock-search: unicode('f932'); +$ti-icon-lock-share: unicode('f933'); +$ti-icon-lock-square: unicode('ef51'); +$ti-icon-lock-square-rounded: unicode('f636'); +$ti-icon-lock-square-rounded-filled: unicode('f6da'); +$ti-icon-lock-star: unicode('f934'); +$ti-icon-lock-up: unicode('f935'); +$ti-icon-lock-x: unicode('f936'); +$ti-icon-logic-and: unicode('f240'); +$ti-icon-logic-buffer: unicode('f241'); +$ti-icon-logic-nand: unicode('f242'); +$ti-icon-logic-nor: unicode('f243'); +$ti-icon-logic-not: unicode('f244'); +$ti-icon-logic-or: unicode('f245'); +$ti-icon-logic-xnor: unicode('f246'); +$ti-icon-logic-xor: unicode('f247'); +$ti-icon-login: unicode('eba7'); +$ti-icon-logout: unicode('eba8'); +$ti-icon-lollipop: unicode('efcc'); +$ti-icon-lollipop-off: unicode('f157'); +$ti-icon-luggage: unicode('efad'); +$ti-icon-luggage-off: unicode('f158'); +$ti-icon-lungs: unicode('ef62'); +$ti-icon-lungs-off: unicode('f405'); +$ti-icon-macro: unicode('eeab'); +$ti-icon-macro-off: unicode('f406'); +$ti-icon-magnet: unicode('eae3'); +$ti-icon-magnet-off: unicode('f159'); +$ti-icon-mail: unicode('eae5'); +$ti-icon-mail-bolt: unicode('f937'); +$ti-icon-mail-cancel: unicode('f938'); +$ti-icon-mail-check: unicode('f939'); +$ti-icon-mail-code: unicode('f93a'); +$ti-icon-mail-cog: unicode('f93b'); +$ti-icon-mail-dollar: unicode('f93c'); +$ti-icon-mail-down: unicode('f93d'); +$ti-icon-mail-exclamation: unicode('f93e'); +$ti-icon-mail-fast: unicode('f069'); +$ti-icon-mail-forward: unicode('eeac'); +$ti-icon-mail-heart: unicode('f93f'); +$ti-icon-mail-minus: unicode('f940'); +$ti-icon-mail-off: unicode('f15a'); +$ti-icon-mail-opened: unicode('eae4'); +$ti-icon-mail-pause: unicode('f941'); +$ti-icon-mail-pin: unicode('f942'); +$ti-icon-mail-plus: unicode('f943'); +$ti-icon-mail-question: unicode('f944'); +$ti-icon-mail-search: unicode('f945'); +$ti-icon-mail-share: unicode('f946'); +$ti-icon-mail-star: unicode('f947'); +$ti-icon-mail-up: unicode('f948'); +$ti-icon-mail-x: unicode('f949'); +$ti-icon-mailbox: unicode('eead'); +$ti-icon-mailbox-off: unicode('f15b'); +$ti-icon-man: unicode('eae6'); +$ti-icon-manual-gearbox: unicode('ed7b'); +$ti-icon-map: unicode('eae9'); +$ti-icon-map-2: unicode('eae7'); +$ti-icon-map-off: unicode('f15c'); +$ti-icon-map-pin: unicode('eae8'); +$ti-icon-map-pin-bolt: unicode('f94a'); +$ti-icon-map-pin-cancel: unicode('f94b'); +$ti-icon-map-pin-check: unicode('f94c'); +$ti-icon-map-pin-code: unicode('f94d'); +$ti-icon-map-pin-cog: unicode('f94e'); +$ti-icon-map-pin-dollar: unicode('f94f'); +$ti-icon-map-pin-down: unicode('f950'); +$ti-icon-map-pin-exclamation: unicode('f951'); +$ti-icon-map-pin-filled: unicode('f680'); +$ti-icon-map-pin-heart: unicode('f952'); +$ti-icon-map-pin-minus: unicode('f953'); +$ti-icon-map-pin-off: unicode('ecf3'); +$ti-icon-map-pin-pause: unicode('f954'); +$ti-icon-map-pin-pin: unicode('f955'); +$ti-icon-map-pin-plus: unicode('f956'); +$ti-icon-map-pin-question: unicode('f957'); +$ti-icon-map-pin-search: unicode('f958'); +$ti-icon-map-pin-share: unicode('f795'); +$ti-icon-map-pin-star: unicode('f959'); +$ti-icon-map-pin-up: unicode('f95a'); +$ti-icon-map-pin-x: unicode('f95b'); +$ti-icon-map-pins: unicode('ed5e'); +$ti-icon-map-search: unicode('ef82'); +$ti-icon-markdown: unicode('ec41'); +$ti-icon-markdown-off: unicode('f407'); +$ti-icon-marquee: unicode('ec77'); +$ti-icon-marquee-2: unicode('eeae'); +$ti-icon-marquee-off: unicode('f15d'); +$ti-icon-mars: unicode('ec80'); +$ti-icon-mask: unicode('eeb0'); +$ti-icon-mask-off: unicode('eeaf'); +$ti-icon-masks-theater: unicode('f263'); +$ti-icon-masks-theater-off: unicode('f408'); +$ti-icon-massage: unicode('eeb1'); +$ti-icon-matchstick: unicode('f577'); +$ti-icon-math: unicode('ebeb'); +$ti-icon-math-1-divide-2: unicode('f4e2'); +$ti-icon-math-1-divide-3: unicode('f4e3'); +$ti-icon-math-avg: unicode('f0f4'); +$ti-icon-math-equal-greater: unicode('f4e4'); +$ti-icon-math-equal-lower: unicode('f4e5'); +$ti-icon-math-function: unicode('eeb2'); +$ti-icon-math-function-off: unicode('f15e'); +$ti-icon-math-function-y: unicode('f4e6'); +$ti-icon-math-greater: unicode('f4e7'); +$ti-icon-math-integral: unicode('f4e9'); +$ti-icon-math-integral-x: unicode('f4e8'); +$ti-icon-math-integrals: unicode('f4ea'); +$ti-icon-math-lower: unicode('f4eb'); +$ti-icon-math-max: unicode('f0f5'); +$ti-icon-math-min: unicode('f0f6'); +$ti-icon-math-not: unicode('f4ec'); +$ti-icon-math-off: unicode('f409'); +$ti-icon-math-pi: unicode('f4ee'); +$ti-icon-math-pi-divide-2: unicode('f4ed'); +$ti-icon-math-symbols: unicode('eeb3'); +$ti-icon-math-x-divide-2: unicode('f4ef'); +$ti-icon-math-x-divide-y: unicode('f4f1'); +$ti-icon-math-x-divide-y-2: unicode('f4f0'); +$ti-icon-math-x-minus-x: unicode('f4f2'); +$ti-icon-math-x-minus-y: unicode('f4f3'); +$ti-icon-math-x-plus-x: unicode('f4f4'); +$ti-icon-math-x-plus-y: unicode('f4f5'); +$ti-icon-math-xy: unicode('f4f6'); +$ti-icon-math-y-minus-y: unicode('f4f7'); +$ti-icon-math-y-plus-y: unicode('f4f8'); +$ti-icon-maximize: unicode('eaea'); +$ti-icon-maximize-off: unicode('f15f'); +$ti-icon-meat: unicode('ef12'); +$ti-icon-meat-off: unicode('f40a'); +$ti-icon-medal: unicode('ec78'); +$ti-icon-medal-2: unicode('efcd'); +$ti-icon-medical-cross: unicode('ec2f'); +$ti-icon-medical-cross-filled: unicode('f681'); +$ti-icon-medical-cross-off: unicode('f160'); +$ti-icon-medicine-syrup: unicode('ef63'); +$ti-icon-meeple: unicode('f514'); +$ti-icon-menorah: unicode('f58c'); +$ti-icon-menu: unicode('eaeb'); +$ti-icon-menu-2: unicode('ec42'); +$ti-icon-menu-order: unicode('f5f5'); +$ti-icon-message: unicode('eaef'); +$ti-icon-message-2: unicode('eaec'); +$ti-icon-message-2-bolt: unicode('f95c'); +$ti-icon-message-2-cancel: unicode('f95d'); +$ti-icon-message-2-check: unicode('f95e'); +$ti-icon-message-2-code: unicode('f012'); +$ti-icon-message-2-cog: unicode('f95f'); +$ti-icon-message-2-dollar: unicode('f960'); +$ti-icon-message-2-down: unicode('f961'); +$ti-icon-message-2-exclamation: unicode('f962'); +$ti-icon-message-2-heart: unicode('f963'); +$ti-icon-message-2-minus: unicode('f964'); +$ti-icon-message-2-off: unicode('f40b'); +$ti-icon-message-2-pause: unicode('f965'); +$ti-icon-message-2-pin: unicode('f966'); +$ti-icon-message-2-plus: unicode('f967'); +$ti-icon-message-2-question: unicode('f968'); +$ti-icon-message-2-search: unicode('f969'); +$ti-icon-message-2-share: unicode('f077'); +$ti-icon-message-2-star: unicode('f96a'); +$ti-icon-message-2-up: unicode('f96b'); +$ti-icon-message-2-x: unicode('f96c'); +$ti-icon-message-bolt: unicode('f96d'); +$ti-icon-message-cancel: unicode('f96e'); +$ti-icon-message-chatbot: unicode('f38a'); +$ti-icon-message-check: unicode('f96f'); +$ti-icon-message-circle: unicode('eaed'); +$ti-icon-message-circle-2: unicode('ed3f'); +$ti-icon-message-circle-2-filled: unicode('f682'); +$ti-icon-message-circle-bolt: unicode('f970'); +$ti-icon-message-circle-cancel: unicode('f971'); +$ti-icon-message-circle-check: unicode('f972'); +$ti-icon-message-circle-code: unicode('f973'); +$ti-icon-message-circle-cog: unicode('f974'); +$ti-icon-message-circle-dollar: unicode('f975'); +$ti-icon-message-circle-down: unicode('f976'); +$ti-icon-message-circle-exclamation: unicode('f977'); +$ti-icon-message-circle-heart: unicode('f978'); +$ti-icon-message-circle-minus: unicode('f979'); +$ti-icon-message-circle-off: unicode('ed40'); +$ti-icon-message-circle-pause: unicode('f97a'); +$ti-icon-message-circle-pin: unicode('f97b'); +$ti-icon-message-circle-plus: unicode('f97c'); +$ti-icon-message-circle-question: unicode('f97d'); +$ti-icon-message-circle-search: unicode('f97e'); +$ti-icon-message-circle-share: unicode('f97f'); +$ti-icon-message-circle-star: unicode('f980'); +$ti-icon-message-circle-up: unicode('f981'); +$ti-icon-message-circle-x: unicode('f982'); +$ti-icon-message-code: unicode('f013'); +$ti-icon-message-cog: unicode('f983'); +$ti-icon-message-dollar: unicode('f984'); +$ti-icon-message-dots: unicode('eaee'); +$ti-icon-message-down: unicode('f985'); +$ti-icon-message-exclamation: unicode('f986'); +$ti-icon-message-forward: unicode('f28f'); +$ti-icon-message-heart: unicode('f987'); +$ti-icon-message-language: unicode('efae'); +$ti-icon-message-minus: unicode('f988'); +$ti-icon-message-off: unicode('ed41'); +$ti-icon-message-pause: unicode('f989'); +$ti-icon-message-pin: unicode('f98a'); +$ti-icon-message-plus: unicode('ec9a'); +$ti-icon-message-question: unicode('f98b'); +$ti-icon-message-report: unicode('ec9b'); +$ti-icon-message-search: unicode('f98c'); +$ti-icon-message-share: unicode('f078'); +$ti-icon-message-star: unicode('f98d'); +$ti-icon-message-up: unicode('f98e'); +$ti-icon-message-x: unicode('f98f'); +$ti-icon-messages: unicode('eb6c'); +$ti-icon-messages-off: unicode('ed42'); +$ti-icon-meteor: unicode('f1fd'); +$ti-icon-meteor-off: unicode('f40c'); +$ti-icon-mickey: unicode('f2a3'); +$ti-icon-mickey-filled: unicode('f683'); +$ti-icon-microphone: unicode('eaf0'); +$ti-icon-microphone-2: unicode('ef2c'); +$ti-icon-microphone-2-off: unicode('f40d'); +$ti-icon-microphone-off: unicode('ed16'); +$ti-icon-microscope: unicode('ef64'); +$ti-icon-microscope-off: unicode('f40e'); +$ti-icon-microwave: unicode('f248'); +$ti-icon-microwave-off: unicode('f264'); +$ti-icon-military-award: unicode('f079'); +$ti-icon-military-rank: unicode('efcf'); +$ti-icon-milk: unicode('ef13'); +$ti-icon-milk-off: unicode('f40f'); +$ti-icon-milkshake: unicode('f4c8'); +$ti-icon-minimize: unicode('eaf1'); +$ti-icon-minus: unicode('eaf2'); +$ti-icon-minus-vertical: unicode('eeb4'); +$ti-icon-mist: unicode('ec30'); +$ti-icon-mist-off: unicode('f410'); +$ti-icon-mobiledata: unicode('f9f5'); +$ti-icon-mobiledata-off: unicode('f9f4'); +$ti-icon-moneybag: unicode('f506'); +$ti-icon-mood-angry: unicode('f2de'); +$ti-icon-mood-annoyed: unicode('f2e0'); +$ti-icon-mood-annoyed-2: unicode('f2df'); +$ti-icon-mood-boy: unicode('ed2d'); +$ti-icon-mood-check: unicode('f7b3'); +$ti-icon-mood-cog: unicode('f7b4'); +$ti-icon-mood-confuzed: unicode('eaf3'); +$ti-icon-mood-confuzed-filled: unicode('f7f2'); +$ti-icon-mood-crazy-happy: unicode('ed90'); +$ti-icon-mood-cry: unicode('ecbb'); +$ti-icon-mood-dollar: unicode('f7b5'); +$ti-icon-mood-empty: unicode('eeb5'); +$ti-icon-mood-empty-filled: unicode('f7f3'); +$ti-icon-mood-happy: unicode('eaf4'); +$ti-icon-mood-happy-filled: unicode('f7f4'); +$ti-icon-mood-heart: unicode('f7b6'); +$ti-icon-mood-kid: unicode('ec03'); +$ti-icon-mood-kid-filled: unicode('f7f5'); +$ti-icon-mood-look-left: unicode('f2c5'); +$ti-icon-mood-look-right: unicode('f2c6'); +$ti-icon-mood-minus: unicode('f7b7'); +$ti-icon-mood-nerd: unicode('f2e1'); +$ti-icon-mood-nervous: unicode('ef96'); +$ti-icon-mood-neutral: unicode('eaf5'); +$ti-icon-mood-neutral-filled: unicode('f7f6'); +$ti-icon-mood-off: unicode('f161'); +$ti-icon-mood-pin: unicode('f7b8'); +$ti-icon-mood-plus: unicode('f7b9'); +$ti-icon-mood-sad: unicode('eaf6'); +$ti-icon-mood-sad-2: unicode('f2e2'); +$ti-icon-mood-sad-dizzy: unicode('f2e3'); +$ti-icon-mood-sad-filled: unicode('f7f7'); +$ti-icon-mood-sad-squint: unicode('f2e4'); +$ti-icon-mood-search: unicode('f7ba'); +$ti-icon-mood-sick: unicode('f2e5'); +$ti-icon-mood-silence: unicode('f2e6'); +$ti-icon-mood-sing: unicode('f2c7'); +$ti-icon-mood-smile: unicode('eaf7'); +$ti-icon-mood-smile-beam: unicode('f2e7'); +$ti-icon-mood-smile-dizzy: unicode('f2e8'); +$ti-icon-mood-smile-filled: unicode('f7f8'); +$ti-icon-mood-suprised: unicode('ec04'); +$ti-icon-mood-tongue: unicode('eb95'); +$ti-icon-mood-tongue-wink: unicode('f2ea'); +$ti-icon-mood-tongue-wink-2: unicode('f2e9'); +$ti-icon-mood-unamused: unicode('f2eb'); +$ti-icon-mood-up: unicode('f7bb'); +$ti-icon-mood-wink: unicode('f2ed'); +$ti-icon-mood-wink-2: unicode('f2ec'); +$ti-icon-mood-wrrr: unicode('f2ee'); +$ti-icon-mood-x: unicode('f7bc'); +$ti-icon-mood-xd: unicode('f2ef'); +$ti-icon-moon: unicode('eaf8'); +$ti-icon-moon-2: unicode('ece6'); +$ti-icon-moon-filled: unicode('f684'); +$ti-icon-moon-off: unicode('f162'); +$ti-icon-moon-stars: unicode('ece7'); +$ti-icon-moped: unicode('ecbc'); +$ti-icon-motorbike: unicode('eeb6'); +$ti-icon-mountain: unicode('ef97'); +$ti-icon-mountain-off: unicode('f411'); +$ti-icon-mouse: unicode('eaf9'); +$ti-icon-mouse-2: unicode('f1d7'); +$ti-icon-mouse-off: unicode('f163'); +$ti-icon-moustache: unicode('f4c9'); +$ti-icon-movie: unicode('eafa'); +$ti-icon-movie-off: unicode('f164'); +$ti-icon-mug: unicode('eafb'); +$ti-icon-mug-off: unicode('f165'); +$ti-icon-multiplier-0-5x: unicode('ef41'); +$ti-icon-multiplier-1-5x: unicode('ef42'); +$ti-icon-multiplier-1x: unicode('ef43'); +$ti-icon-multiplier-2x: unicode('ef44'); +$ti-icon-mushroom: unicode('ef14'); +$ti-icon-mushroom-filled: unicode('f7f9'); +$ti-icon-mushroom-off: unicode('f412'); +$ti-icon-music: unicode('eafc'); +$ti-icon-music-off: unicode('f166'); +$ti-icon-navigation: unicode('f2c8'); +$ti-icon-navigation-filled: unicode('f685'); +$ti-icon-navigation-off: unicode('f413'); +$ti-icon-needle: unicode('f508'); +$ti-icon-needle-thread: unicode('f507'); +$ti-icon-network: unicode('f09f'); +$ti-icon-network-off: unicode('f414'); +$ti-icon-new-section: unicode('ebc1'); +$ti-icon-news: unicode('eafd'); +$ti-icon-news-off: unicode('f167'); +$ti-icon-nfc: unicode('eeb7'); +$ti-icon-nfc-off: unicode('f168'); +$ti-icon-no-copyright: unicode('efb9'); +$ti-icon-no-creative-commons: unicode('efba'); +$ti-icon-no-derivatives: unicode('efbb'); +$ti-icon-north-star: unicode('f014'); +$ti-icon-note: unicode('eb6d'); +$ti-icon-note-off: unicode('f169'); +$ti-icon-notebook: unicode('eb96'); +$ti-icon-notebook-off: unicode('f415'); +$ti-icon-notes: unicode('eb6e'); +$ti-icon-notes-off: unicode('f16a'); +$ti-icon-notification: unicode('eafe'); +$ti-icon-notification-off: unicode('f16b'); +$ti-icon-number: unicode('f1fe'); +$ti-icon-number-0: unicode('edf0'); +$ti-icon-number-1: unicode('edf1'); +$ti-icon-number-2: unicode('edf2'); +$ti-icon-number-3: unicode('edf3'); +$ti-icon-number-4: unicode('edf4'); +$ti-icon-number-5: unicode('edf5'); +$ti-icon-number-6: unicode('edf6'); +$ti-icon-number-7: unicode('edf7'); +$ti-icon-number-8: unicode('edf8'); +$ti-icon-number-9: unicode('edf9'); +$ti-icon-numbers: unicode('f015'); +$ti-icon-nurse: unicode('ef65'); +$ti-icon-octagon: unicode('ecbd'); +$ti-icon-octagon-filled: unicode('f686'); +$ti-icon-octagon-off: unicode('eeb8'); +$ti-icon-old: unicode('eeb9'); +$ti-icon-olympics: unicode('eeba'); +$ti-icon-olympics-off: unicode('f416'); +$ti-icon-om: unicode('f58d'); +$ti-icon-omega: unicode('eb97'); +$ti-icon-outbound: unicode('f249'); +$ti-icon-outlet: unicode('ebd7'); +$ti-icon-oval: unicode('f02e'); +$ti-icon-oval-filled: unicode('f687'); +$ti-icon-oval-vertical: unicode('f02d'); +$ti-icon-oval-vertical-filled: unicode('f688'); +$ti-icon-overline: unicode('eebb'); +$ti-icon-package: unicode('eaff'); +$ti-icon-package-export: unicode('f07a'); +$ti-icon-package-import: unicode('f07b'); +$ti-icon-package-off: unicode('f16c'); +$ti-icon-packages: unicode('f2c9'); +$ti-icon-pacman: unicode('eebc'); +$ti-icon-page-break: unicode('ec81'); +$ti-icon-paint: unicode('eb00'); +$ti-icon-paint-filled: unicode('f75f'); +$ti-icon-paint-off: unicode('f16d'); +$ti-icon-palette: unicode('eb01'); +$ti-icon-palette-off: unicode('f16e'); +$ti-icon-panorama-horizontal: unicode('ed33'); +$ti-icon-panorama-horizontal-off: unicode('f417'); +$ti-icon-panorama-vertical: unicode('ed34'); +$ti-icon-panorama-vertical-off: unicode('f418'); +$ti-icon-paper-bag: unicode('f02f'); +$ti-icon-paper-bag-off: unicode('f16f'); +$ti-icon-paperclip: unicode('eb02'); +$ti-icon-parachute: unicode('ed7c'); +$ti-icon-parachute-off: unicode('f170'); +$ti-icon-parentheses: unicode('ebd8'); +$ti-icon-parentheses-off: unicode('f171'); +$ti-icon-parking: unicode('eb03'); +$ti-icon-parking-off: unicode('f172'); +$ti-icon-password: unicode('f4ca'); +$ti-icon-paw: unicode('eff9'); +$ti-icon-paw-filled: unicode('f689'); +$ti-icon-paw-off: unicode('f419'); +$ti-icon-pdf: unicode('f7ac'); +$ti-icon-peace: unicode('ecbe'); +$ti-icon-pencil: unicode('eb04'); +$ti-icon-pencil-minus: unicode('f1eb'); +$ti-icon-pencil-off: unicode('f173'); +$ti-icon-pencil-plus: unicode('f1ec'); +$ti-icon-pennant: unicode('ed7d'); +$ti-icon-pennant-2: unicode('f06a'); +$ti-icon-pennant-2-filled: unicode('f68a'); +$ti-icon-pennant-filled: unicode('f68b'); +$ti-icon-pennant-off: unicode('f174'); +$ti-icon-pentagon: unicode('efe3'); +$ti-icon-pentagon-filled: unicode('f68c'); +$ti-icon-pentagon-off: unicode('f41a'); +$ti-icon-pentagram: unicode('f586'); +$ti-icon-pepper: unicode('ef15'); +$ti-icon-pepper-off: unicode('f175'); +$ti-icon-percentage: unicode('ecf4'); +$ti-icon-perfume: unicode('f509'); +$ti-icon-perspective: unicode('eebd'); +$ti-icon-perspective-off: unicode('f176'); +$ti-icon-phone: unicode('eb09'); +$ti-icon-phone-call: unicode('eb05'); +$ti-icon-phone-calling: unicode('ec43'); +$ti-icon-phone-check: unicode('ec05'); +$ti-icon-phone-incoming: unicode('eb06'); +$ti-icon-phone-off: unicode('ecf5'); +$ti-icon-phone-outgoing: unicode('eb07'); +$ti-icon-phone-pause: unicode('eb08'); +$ti-icon-phone-plus: unicode('ec06'); +$ti-icon-phone-x: unicode('ec07'); +$ti-icon-photo: unicode('eb0a'); +$ti-icon-photo-bolt: unicode('f990'); +$ti-icon-photo-cancel: unicode('f35d'); +$ti-icon-photo-check: unicode('f35e'); +$ti-icon-photo-code: unicode('f991'); +$ti-icon-photo-cog: unicode('f992'); +$ti-icon-photo-dollar: unicode('f993'); +$ti-icon-photo-down: unicode('f35f'); +$ti-icon-photo-edit: unicode('f360'); +$ti-icon-photo-exclamation: unicode('f994'); +$ti-icon-photo-heart: unicode('f361'); +$ti-icon-photo-minus: unicode('f362'); +$ti-icon-photo-off: unicode('ecf6'); +$ti-icon-photo-pause: unicode('f995'); +$ti-icon-photo-pin: unicode('f996'); +$ti-icon-photo-plus: unicode('f363'); +$ti-icon-photo-question: unicode('f997'); +$ti-icon-photo-search: unicode('f364'); +$ti-icon-photo-sensor: unicode('f798'); +$ti-icon-photo-sensor-2: unicode('f796'); +$ti-icon-photo-sensor-3: unicode('f797'); +$ti-icon-photo-share: unicode('f998'); +$ti-icon-photo-shield: unicode('f365'); +$ti-icon-photo-star: unicode('f366'); +$ti-icon-photo-up: unicode('f38b'); +$ti-icon-photo-x: unicode('f367'); +$ti-icon-physotherapist: unicode('eebe'); +$ti-icon-picture-in-picture: unicode('ed35'); +$ti-icon-picture-in-picture-off: unicode('ed43'); +$ti-icon-picture-in-picture-on: unicode('ed44'); +$ti-icon-picture-in-picture-top: unicode('efe4'); +$ti-icon-pig: unicode('ef52'); +$ti-icon-pig-money: unicode('f38c'); +$ti-icon-pig-off: unicode('f177'); +$ti-icon-pilcrow: unicode('f5f6'); +$ti-icon-pill: unicode('ec44'); +$ti-icon-pill-off: unicode('f178'); +$ti-icon-pills: unicode('ef66'); +$ti-icon-pin: unicode('ec9c'); +$ti-icon-pin-filled: unicode('f68d'); +$ti-icon-ping-pong: unicode('f38d'); +$ti-icon-pinned: unicode('ed60'); +$ti-icon-pinned-filled: unicode('f68e'); +$ti-icon-pinned-off: unicode('ed5f'); +$ti-icon-pizza: unicode('edbb'); +$ti-icon-pizza-off: unicode('f179'); +$ti-icon-placeholder: unicode('f626'); +$ti-icon-plane: unicode('eb6f'); +$ti-icon-plane-arrival: unicode('eb99'); +$ti-icon-plane-departure: unicode('eb9a'); +$ti-icon-plane-inflight: unicode('ef98'); +$ti-icon-plane-off: unicode('f17a'); +$ti-icon-plane-tilt: unicode('f1ed'); +$ti-icon-planet: unicode('ec08'); +$ti-icon-planet-off: unicode('f17b'); +$ti-icon-plant: unicode('ed50'); +$ti-icon-plant-2: unicode('ed7e'); +$ti-icon-plant-2-off: unicode('f17c'); +$ti-icon-plant-off: unicode('f17d'); +$ti-icon-play-card: unicode('eebf'); +$ti-icon-play-card-off: unicode('f17e'); +$ti-icon-player-eject: unicode('efbc'); +$ti-icon-player-eject-filled: unicode('f68f'); +$ti-icon-player-pause: unicode('ed45'); +$ti-icon-player-pause-filled: unicode('f690'); +$ti-icon-player-play: unicode('ed46'); +$ti-icon-player-play-filled: unicode('f691'); +$ti-icon-player-record: unicode('ed47'); +$ti-icon-player-record-filled: unicode('f692'); +$ti-icon-player-skip-back: unicode('ed48'); +$ti-icon-player-skip-back-filled: unicode('f693'); +$ti-icon-player-skip-forward: unicode('ed49'); +$ti-icon-player-skip-forward-filled: unicode('f694'); +$ti-icon-player-stop: unicode('ed4a'); +$ti-icon-player-stop-filled: unicode('f695'); +$ti-icon-player-track-next: unicode('ed4b'); +$ti-icon-player-track-next-filled: unicode('f696'); +$ti-icon-player-track-prev: unicode('ed4c'); +$ti-icon-player-track-prev-filled: unicode('f697'); +$ti-icon-playlist: unicode('eec0'); +$ti-icon-playlist-add: unicode('f008'); +$ti-icon-playlist-off: unicode('f17f'); +$ti-icon-playlist-x: unicode('f009'); +$ti-icon-playstation-circle: unicode('f2ad'); +$ti-icon-playstation-square: unicode('f2ae'); +$ti-icon-playstation-triangle: unicode('f2af'); +$ti-icon-playstation-x: unicode('f2b0'); +$ti-icon-plug: unicode('ebd9'); +$ti-icon-plug-connected: unicode('f00a'); +$ti-icon-plug-connected-x: unicode('f0a0'); +$ti-icon-plug-off: unicode('f180'); +$ti-icon-plug-x: unicode('f0a1'); +$ti-icon-plus: unicode('eb0b'); +$ti-icon-plus-equal: unicode('f7ad'); +$ti-icon-plus-minus: unicode('f7ae'); +$ti-icon-png: unicode('f3ad'); +$ti-icon-podium: unicode('f1d8'); +$ti-icon-podium-off: unicode('f41b'); +$ti-icon-point: unicode('eb0c'); +$ti-icon-point-filled: unicode('f698'); +$ti-icon-point-off: unicode('f181'); +$ti-icon-pointer: unicode('f265'); +$ti-icon-pointer-bolt: unicode('f999'); +$ti-icon-pointer-cancel: unicode('f99a'); +$ti-icon-pointer-check: unicode('f99b'); +$ti-icon-pointer-code: unicode('f99c'); +$ti-icon-pointer-cog: unicode('f99d'); +$ti-icon-pointer-dollar: unicode('f99e'); +$ti-icon-pointer-down: unicode('f99f'); +$ti-icon-pointer-exclamation: unicode('f9a0'); +$ti-icon-pointer-heart: unicode('f9a1'); +$ti-icon-pointer-minus: unicode('f9a2'); +$ti-icon-pointer-off: unicode('f9a3'); +$ti-icon-pointer-pause: unicode('f9a4'); +$ti-icon-pointer-pin: unicode('f9a5'); +$ti-icon-pointer-plus: unicode('f9a6'); +$ti-icon-pointer-question: unicode('f9a7'); +$ti-icon-pointer-search: unicode('f9a8'); +$ti-icon-pointer-share: unicode('f9a9'); +$ti-icon-pointer-star: unicode('f9aa'); +$ti-icon-pointer-up: unicode('f9ab'); +$ti-icon-pointer-x: unicode('f9ac'); +$ti-icon-pokeball: unicode('eec1'); +$ti-icon-pokeball-off: unicode('f41c'); +$ti-icon-poker-chip: unicode('f515'); +$ti-icon-polaroid: unicode('eec2'); +$ti-icon-polygon: unicode('efd0'); +$ti-icon-polygon-off: unicode('f182'); +$ti-icon-poo: unicode('f258'); +$ti-icon-pool: unicode('ed91'); +$ti-icon-pool-off: unicode('f41d'); +$ti-icon-power: unicode('eb0d'); +$ti-icon-pray: unicode('ecbf'); +$ti-icon-premium-rights: unicode('efbd'); +$ti-icon-prescription: unicode('ef99'); +$ti-icon-presentation: unicode('eb70'); +$ti-icon-presentation-analytics: unicode('eec3'); +$ti-icon-presentation-off: unicode('f183'); +$ti-icon-printer: unicode('eb0e'); +$ti-icon-printer-off: unicode('f184'); +$ti-icon-prison: unicode('ef79'); +$ti-icon-prompt: unicode('eb0f'); +$ti-icon-propeller: unicode('eec4'); +$ti-icon-propeller-off: unicode('f185'); +$ti-icon-pumpkin-scary: unicode('f587'); +$ti-icon-puzzle: unicode('eb10'); +$ti-icon-puzzle-2: unicode('ef83'); +$ti-icon-puzzle-filled: unicode('f699'); +$ti-icon-puzzle-off: unicode('f186'); +$ti-icon-pyramid: unicode('eec5'); +$ti-icon-pyramid-off: unicode('f187'); +$ti-icon-qrcode: unicode('eb11'); +$ti-icon-qrcode-off: unicode('f41e'); +$ti-icon-question-mark: unicode('ec9d'); +$ti-icon-quote: unicode('efbe'); +$ti-icon-quote-off: unicode('f188'); +$ti-icon-radar: unicode('f017'); +$ti-icon-radar-2: unicode('f016'); +$ti-icon-radar-off: unicode('f41f'); +$ti-icon-radio: unicode('ef2d'); +$ti-icon-radio-off: unicode('f420'); +$ti-icon-radioactive: unicode('ecc0'); +$ti-icon-radioactive-filled: unicode('f760'); +$ti-icon-radioactive-off: unicode('f189'); +$ti-icon-radius-bottom-left: unicode('eec6'); +$ti-icon-radius-bottom-right: unicode('eec7'); +$ti-icon-radius-top-left: unicode('eec8'); +$ti-icon-radius-top-right: unicode('eec9'); +$ti-icon-rainbow: unicode('edbc'); +$ti-icon-rainbow-off: unicode('f18a'); +$ti-icon-rating-12-plus: unicode('f266'); +$ti-icon-rating-14-plus: unicode('f267'); +$ti-icon-rating-16-plus: unicode('f268'); +$ti-icon-rating-18-plus: unicode('f269'); +$ti-icon-rating-21-plus: unicode('f26a'); +$ti-icon-razor: unicode('f4b5'); +$ti-icon-razor-electric: unicode('f4b4'); +$ti-icon-receipt: unicode('edfd'); +$ti-icon-receipt-2: unicode('edfa'); +$ti-icon-receipt-off: unicode('edfb'); +$ti-icon-receipt-refund: unicode('edfc'); +$ti-icon-receipt-tax: unicode('edbd'); +$ti-icon-recharging: unicode('eeca'); +$ti-icon-record-mail: unicode('eb12'); +$ti-icon-record-mail-off: unicode('f18b'); +$ti-icon-rectangle: unicode('ed37'); +$ti-icon-rectangle-filled: unicode('f69a'); +$ti-icon-rectangle-vertical: unicode('ed36'); +$ti-icon-rectangle-vertical-filled: unicode('f69b'); +$ti-icon-recycle: unicode('eb9b'); +$ti-icon-recycle-off: unicode('f18c'); +$ti-icon-refresh: unicode('eb13'); +$ti-icon-refresh-alert: unicode('ed57'); +$ti-icon-refresh-dot: unicode('efbf'); +$ti-icon-refresh-off: unicode('f18d'); +$ti-icon-regex: unicode('f31f'); +$ti-icon-regex-off: unicode('f421'); +$ti-icon-registered: unicode('eb14'); +$ti-icon-relation-many-to-many: unicode('ed7f'); +$ti-icon-relation-one-to-many: unicode('ed80'); +$ti-icon-relation-one-to-one: unicode('ed81'); +$ti-icon-reload: unicode('f3ae'); +$ti-icon-repeat: unicode('eb72'); +$ti-icon-repeat-off: unicode('f18e'); +$ti-icon-repeat-once: unicode('eb71'); +$ti-icon-replace: unicode('ebc7'); +$ti-icon-replace-filled: unicode('f69c'); +$ti-icon-replace-off: unicode('f422'); +$ti-icon-report: unicode('eece'); +$ti-icon-report-analytics: unicode('eecb'); +$ti-icon-report-medical: unicode('eecc'); +$ti-icon-report-money: unicode('eecd'); +$ti-icon-report-off: unicode('f18f'); +$ti-icon-report-search: unicode('ef84'); +$ti-icon-reserved-line: unicode('f9f6'); +$ti-icon-resize: unicode('eecf'); +$ti-icon-ribbon-health: unicode('f58e'); +$ti-icon-ripple: unicode('ed82'); +$ti-icon-ripple-off: unicode('f190'); +$ti-icon-road: unicode('f018'); +$ti-icon-road-off: unicode('f191'); +$ti-icon-road-sign: unicode('ecdd'); +$ti-icon-robot: unicode('f00b'); +$ti-icon-robot-off: unicode('f192'); +$ti-icon-rocket: unicode('ec45'); +$ti-icon-rocket-off: unicode('f193'); +$ti-icon-roller-skating: unicode('efd1'); +$ti-icon-rollercoaster: unicode('f0a2'); +$ti-icon-rollercoaster-off: unicode('f423'); +$ti-icon-rosette: unicode('f599'); +$ti-icon-rosette-filled: unicode('f69d'); +$ti-icon-rosette-number-0: unicode('f58f'); +$ti-icon-rosette-number-1: unicode('f590'); +$ti-icon-rosette-number-2: unicode('f591'); +$ti-icon-rosette-number-3: unicode('f592'); +$ti-icon-rosette-number-4: unicode('f593'); +$ti-icon-rosette-number-5: unicode('f594'); +$ti-icon-rosette-number-6: unicode('f595'); +$ti-icon-rosette-number-7: unicode('f596'); +$ti-icon-rosette-number-8: unicode('f597'); +$ti-icon-rosette-number-9: unicode('f598'); +$ti-icon-rotate: unicode('eb16'); +$ti-icon-rotate-2: unicode('ebb4'); +$ti-icon-rotate-360: unicode('ef85'); +$ti-icon-rotate-clockwise: unicode('eb15'); +$ti-icon-rotate-clockwise-2: unicode('ebb5'); +$ti-icon-rotate-dot: unicode('efe5'); +$ti-icon-rotate-rectangle: unicode('ec15'); +$ti-icon-route: unicode('eb17'); +$ti-icon-route-2: unicode('f4b6'); +$ti-icon-route-off: unicode('f194'); +$ti-icon-router: unicode('eb18'); +$ti-icon-router-off: unicode('f424'); +$ti-icon-row-insert-bottom: unicode('eed0'); +$ti-icon-row-insert-top: unicode('eed1'); +$ti-icon-rss: unicode('eb19'); +$ti-icon-rubber-stamp: unicode('f5ab'); +$ti-icon-rubber-stamp-off: unicode('f5aa'); +$ti-icon-ruler: unicode('eb1a'); +$ti-icon-ruler-2: unicode('eed2'); +$ti-icon-ruler-2-off: unicode('f195'); +$ti-icon-ruler-3: unicode('f290'); +$ti-icon-ruler-measure: unicode('f291'); +$ti-icon-ruler-off: unicode('f196'); +$ti-icon-run: unicode('ec82'); +$ti-icon-s-turn-down: unicode('f516'); +$ti-icon-s-turn-left: unicode('f517'); +$ti-icon-s-turn-right: unicode('f518'); +$ti-icon-s-turn-up: unicode('f519'); +$ti-icon-sailboat: unicode('ec83'); +$ti-icon-sailboat-2: unicode('f5f7'); +$ti-icon-sailboat-off: unicode('f425'); +$ti-icon-salad: unicode('f50a'); +$ti-icon-salt: unicode('ef16'); +$ti-icon-satellite: unicode('eed3'); +$ti-icon-satellite-off: unicode('f197'); +$ti-icon-sausage: unicode('ef17'); +$ti-icon-scale: unicode('ebc2'); +$ti-icon-scale-off: unicode('f198'); +$ti-icon-scale-outline: unicode('ef53'); +$ti-icon-scale-outline-off: unicode('f199'); +$ti-icon-scan: unicode('ebc8'); +$ti-icon-scan-eye: unicode('f1ff'); +$ti-icon-schema: unicode('f200'); +$ti-icon-schema-off: unicode('f426'); +$ti-icon-school: unicode('ecf7'); +$ti-icon-school-bell: unicode('f64a'); +$ti-icon-school-off: unicode('f19a'); +$ti-icon-scissors: unicode('eb1b'); +$ti-icon-scissors-off: unicode('f19b'); +$ti-icon-scooter: unicode('ec6c'); +$ti-icon-scooter-electric: unicode('ecc1'); +$ti-icon-screen-share: unicode('ed18'); +$ti-icon-screen-share-off: unicode('ed17'); +$ti-icon-screenshot: unicode('f201'); +$ti-icon-scribble: unicode('f0a3'); +$ti-icon-scribble-off: unicode('f427'); +$ti-icon-script: unicode('f2da'); +$ti-icon-script-minus: unicode('f2d7'); +$ti-icon-script-plus: unicode('f2d8'); +$ti-icon-script-x: unicode('f2d9'); +$ti-icon-scuba-mask: unicode('eed4'); +$ti-icon-scuba-mask-off: unicode('f428'); +$ti-icon-sdk: unicode('f3af'); +$ti-icon-search: unicode('eb1c'); +$ti-icon-search-off: unicode('f19c'); +$ti-icon-section: unicode('eed5'); +$ti-icon-section-sign: unicode('f019'); +$ti-icon-seeding: unicode('ed51'); +$ti-icon-seeding-off: unicode('f19d'); +$ti-icon-select: unicode('ec9e'); +$ti-icon-select-all: unicode('f9f7'); +$ti-icon-selector: unicode('eb1d'); +$ti-icon-send: unicode('eb1e'); +$ti-icon-send-off: unicode('f429'); +$ti-icon-seo: unicode('f26b'); +$ti-icon-separator: unicode('ebda'); +$ti-icon-separator-horizontal: unicode('ec79'); +$ti-icon-separator-vertical: unicode('ec7a'); +$ti-icon-server: unicode('eb1f'); +$ti-icon-server-2: unicode('f07c'); +$ti-icon-server-bolt: unicode('f320'); +$ti-icon-server-cog: unicode('f321'); +$ti-icon-server-off: unicode('f19e'); +$ti-icon-servicemark: unicode('ec09'); +$ti-icon-settings: unicode('eb20'); +$ti-icon-settings-2: unicode('f5ac'); +$ti-icon-settings-automation: unicode('eed6'); +$ti-icon-settings-bolt: unicode('f9ad'); +$ti-icon-settings-cancel: unicode('f9ae'); +$ti-icon-settings-check: unicode('f9af'); +$ti-icon-settings-code: unicode('f9b0'); +$ti-icon-settings-cog: unicode('f9b1'); +$ti-icon-settings-dollar: unicode('f9b2'); +$ti-icon-settings-down: unicode('f9b3'); +$ti-icon-settings-exclamation: unicode('f9b4'); +$ti-icon-settings-filled: unicode('f69e'); +$ti-icon-settings-heart: unicode('f9b5'); +$ti-icon-settings-minus: unicode('f9b6'); +$ti-icon-settings-off: unicode('f19f'); +$ti-icon-settings-pause: unicode('f9b7'); +$ti-icon-settings-pin: unicode('f9b8'); +$ti-icon-settings-plus: unicode('f9b9'); +$ti-icon-settings-question: unicode('f9ba'); +$ti-icon-settings-search: unicode('f9bb'); +$ti-icon-settings-share: unicode('f9bc'); +$ti-icon-settings-star: unicode('f9bd'); +$ti-icon-settings-up: unicode('f9be'); +$ti-icon-settings-x: unicode('f9bf'); +$ti-icon-shadow: unicode('eed8'); +$ti-icon-shadow-off: unicode('eed7'); +$ti-icon-shape: unicode('eb9c'); +$ti-icon-shape-2: unicode('eed9'); +$ti-icon-shape-3: unicode('eeda'); +$ti-icon-shape-off: unicode('f1a0'); +$ti-icon-share: unicode('eb21'); +$ti-icon-share-2: unicode('f799'); +$ti-icon-share-3: unicode('f7bd'); +$ti-icon-share-off: unicode('f1a1'); +$ti-icon-shield: unicode('eb24'); +$ti-icon-shield-bolt: unicode('f9c0'); +$ti-icon-shield-cancel: unicode('f9c1'); +$ti-icon-shield-check: unicode('eb22'); +$ti-icon-shield-check-filled: unicode('f761'); +$ti-icon-shield-checkered: unicode('ef9a'); +$ti-icon-shield-checkered-filled: unicode('f762'); +$ti-icon-shield-chevron: unicode('ef9b'); +$ti-icon-shield-code: unicode('f9c2'); +$ti-icon-shield-cog: unicode('f9c3'); +$ti-icon-shield-dollar: unicode('f9c4'); +$ti-icon-shield-down: unicode('f9c5'); +$ti-icon-shield-exclamation: unicode('f9c6'); +$ti-icon-shield-filled: unicode('f69f'); +$ti-icon-shield-half: unicode('f358'); +$ti-icon-shield-half-filled: unicode('f357'); +$ti-icon-shield-heart: unicode('f9c7'); +$ti-icon-shield-lock: unicode('ed58'); +$ti-icon-shield-lock-filled: unicode('f763'); +$ti-icon-shield-minus: unicode('f9c8'); +$ti-icon-shield-off: unicode('ecf8'); +$ti-icon-shield-pause: unicode('f9c9'); +$ti-icon-shield-pin: unicode('f9ca'); +$ti-icon-shield-plus: unicode('f9cb'); +$ti-icon-shield-question: unicode('f9cc'); +$ti-icon-shield-search: unicode('f9cd'); +$ti-icon-shield-share: unicode('f9ce'); +$ti-icon-shield-star: unicode('f9cf'); +$ti-icon-shield-up: unicode('f9d0'); +$ti-icon-shield-x: unicode('eb23'); +$ti-icon-ship: unicode('ec84'); +$ti-icon-ship-off: unicode('f42a'); +$ti-icon-shirt: unicode('ec0a'); +$ti-icon-shirt-filled: unicode('f6a0'); +$ti-icon-shirt-off: unicode('f1a2'); +$ti-icon-shirt-sport: unicode('f26c'); +$ti-icon-shoe: unicode('efd2'); +$ti-icon-shoe-off: unicode('f1a4'); +$ti-icon-shopping-bag: unicode('f5f8'); +$ti-icon-shopping-cart: unicode('eb25'); +$ti-icon-shopping-cart-discount: unicode('eedb'); +$ti-icon-shopping-cart-off: unicode('eedc'); +$ti-icon-shopping-cart-plus: unicode('eedd'); +$ti-icon-shopping-cart-x: unicode('eede'); +$ti-icon-shovel: unicode('f1d9'); +$ti-icon-shredder: unicode('eedf'); +$ti-icon-sign-left: unicode('f06b'); +$ti-icon-sign-left-filled: unicode('f6a1'); +$ti-icon-sign-right: unicode('f06c'); +$ti-icon-sign-right-filled: unicode('f6a2'); +$ti-icon-signal-2g: unicode('f79a'); +$ti-icon-signal-3g: unicode('f1ee'); +$ti-icon-signal-4g: unicode('f1ef'); +$ti-icon-signal-4g-plus: unicode('f259'); +$ti-icon-signal-5g: unicode('f1f0'); +$ti-icon-signal-6g: unicode('f9f8'); +$ti-icon-signal-e: unicode('f9f9'); +$ti-icon-signal-g: unicode('f9fa'); +$ti-icon-signal-h: unicode('f9fc'); +$ti-icon-signal-h-plus: unicode('f9fb'); +$ti-icon-signal-lte: unicode('f9fd'); +$ti-icon-signature: unicode('eee0'); +$ti-icon-signature-off: unicode('f1a5'); +$ti-icon-sitemap: unicode('eb9d'); +$ti-icon-sitemap-off: unicode('f1a6'); +$ti-icon-skateboard: unicode('ecc2'); +$ti-icon-skateboard-off: unicode('f42b'); +$ti-icon-skull: unicode('f292'); +$ti-icon-slash: unicode('f4f9'); +$ti-icon-slashes: unicode('f588'); +$ti-icon-sleigh: unicode('ef9c'); +$ti-icon-slice: unicode('ebdb'); +$ti-icon-slideshow: unicode('ebc9'); +$ti-icon-smart-home: unicode('ecde'); +$ti-icon-smart-home-off: unicode('f1a7'); +$ti-icon-smoking: unicode('ecc4'); +$ti-icon-smoking-no: unicode('ecc3'); +$ti-icon-snowflake: unicode('ec0b'); +$ti-icon-snowflake-off: unicode('f1a8'); +$ti-icon-snowman: unicode('f26d'); +$ti-icon-soccer-field: unicode('ed92'); +$ti-icon-social: unicode('ebec'); +$ti-icon-social-off: unicode('f1a9'); +$ti-icon-sock: unicode('eee1'); +$ti-icon-sofa: unicode('efaf'); +$ti-icon-sofa-off: unicode('f42c'); +$ti-icon-solar-panel: unicode('f7bf'); +$ti-icon-solar-panel-2: unicode('f7be'); +$ti-icon-sort-0-9: unicode('f54d'); +$ti-icon-sort-9-0: unicode('f54e'); +$ti-icon-sort-a-z: unicode('f54f'); +$ti-icon-sort-ascending: unicode('eb26'); +$ti-icon-sort-ascending-2: unicode('eee2'); +$ti-icon-sort-ascending-letters: unicode('ef18'); +$ti-icon-sort-ascending-numbers: unicode('ef19'); +$ti-icon-sort-descending: unicode('eb27'); +$ti-icon-sort-descending-2: unicode('eee3'); +$ti-icon-sort-descending-letters: unicode('ef1a'); +$ti-icon-sort-descending-numbers: unicode('ef1b'); +$ti-icon-sort-z-a: unicode('f550'); +$ti-icon-sos: unicode('f24a'); +$ti-icon-soup: unicode('ef2e'); +$ti-icon-soup-off: unicode('f42d'); +$ti-icon-source-code: unicode('f4a2'); +$ti-icon-space: unicode('ec0c'); +$ti-icon-space-off: unicode('f1aa'); +$ti-icon-spacing-horizontal: unicode('ef54'); +$ti-icon-spacing-vertical: unicode('ef55'); +$ti-icon-spade: unicode('effa'); +$ti-icon-spade-filled: unicode('f6a3'); +$ti-icon-sparkles: unicode('f6d7'); +$ti-icon-speakerphone: unicode('ed61'); +$ti-icon-speedboat: unicode('ed93'); +$ti-icon-spider: unicode('f293'); +$ti-icon-spiral: unicode('f294'); +$ti-icon-spiral-off: unicode('f42e'); +$ti-icon-sport-billard: unicode('eee4'); +$ti-icon-spray: unicode('f50b'); +$ti-icon-spy: unicode('f227'); +$ti-icon-spy-off: unicode('f42f'); +$ti-icon-sql: unicode('f7c0'); +$ti-icon-square: unicode('eb2c'); +$ti-icon-square-0-filled: unicode('f764'); +$ti-icon-square-1-filled: unicode('f765'); +$ti-icon-square-2-filled: unicode('f7fa'); +$ti-icon-square-3-filled: unicode('f766'); +$ti-icon-square-4-filled: unicode('f767'); +$ti-icon-square-5-filled: unicode('f768'); +$ti-icon-square-6-filled: unicode('f769'); +$ti-icon-square-7-filled: unicode('f76a'); +$ti-icon-square-8-filled: unicode('f76b'); +$ti-icon-square-9-filled: unicode('f76c'); +$ti-icon-square-arrow-down: unicode('f4b7'); +$ti-icon-square-arrow-left: unicode('f4b8'); +$ti-icon-square-arrow-right: unicode('f4b9'); +$ti-icon-square-arrow-up: unicode('f4ba'); +$ti-icon-square-asterisk: unicode('f01a'); +$ti-icon-square-check: unicode('eb28'); +$ti-icon-square-check-filled: unicode('f76d'); +$ti-icon-square-chevron-down: unicode('f627'); +$ti-icon-square-chevron-left: unicode('f628'); +$ti-icon-square-chevron-right: unicode('f629'); +$ti-icon-square-chevron-up: unicode('f62a'); +$ti-icon-square-chevrons-down: unicode('f64b'); +$ti-icon-square-chevrons-left: unicode('f64c'); +$ti-icon-square-chevrons-right: unicode('f64d'); +$ti-icon-square-chevrons-up: unicode('f64e'); +$ti-icon-square-dot: unicode('ed59'); +$ti-icon-square-f0: unicode('f526'); +$ti-icon-square-f0-filled: unicode('f76e'); +$ti-icon-square-f1: unicode('f527'); +$ti-icon-square-f1-filled: unicode('f76f'); +$ti-icon-square-f2: unicode('f528'); +$ti-icon-square-f2-filled: unicode('f770'); +$ti-icon-square-f3: unicode('f529'); +$ti-icon-square-f3-filled: unicode('f771'); +$ti-icon-square-f4: unicode('f52a'); +$ti-icon-square-f4-filled: unicode('f772'); +$ti-icon-square-f5: unicode('f52b'); +$ti-icon-square-f5-filled: unicode('f773'); +$ti-icon-square-f6: unicode('f52c'); +$ti-icon-square-f6-filled: unicode('f774'); +$ti-icon-square-f7: unicode('f52d'); +$ti-icon-square-f7-filled: unicode('f775'); +$ti-icon-square-f8: unicode('f52e'); +$ti-icon-square-f8-filled: unicode('f776'); +$ti-icon-square-f9: unicode('f52f'); +$ti-icon-square-f9-filled: unicode('f777'); +$ti-icon-square-forbid: unicode('ed5b'); +$ti-icon-square-forbid-2: unicode('ed5a'); +$ti-icon-square-half: unicode('effb'); +$ti-icon-square-key: unicode('f638'); +$ti-icon-square-letter-a: unicode('f47c'); +$ti-icon-square-letter-b: unicode('f47d'); +$ti-icon-square-letter-c: unicode('f47e'); +$ti-icon-square-letter-d: unicode('f47f'); +$ti-icon-square-letter-e: unicode('f480'); +$ti-icon-square-letter-f: unicode('f481'); +$ti-icon-square-letter-g: unicode('f482'); +$ti-icon-square-letter-h: unicode('f483'); +$ti-icon-square-letter-i: unicode('f484'); +$ti-icon-square-letter-j: unicode('f485'); +$ti-icon-square-letter-k: unicode('f486'); +$ti-icon-square-letter-l: unicode('f487'); +$ti-icon-square-letter-m: unicode('f488'); +$ti-icon-square-letter-n: unicode('f489'); +$ti-icon-square-letter-o: unicode('f48a'); +$ti-icon-square-letter-p: unicode('f48b'); +$ti-icon-square-letter-q: unicode('f48c'); +$ti-icon-square-letter-r: unicode('f48d'); +$ti-icon-square-letter-s: unicode('f48e'); +$ti-icon-square-letter-t: unicode('f48f'); +$ti-icon-square-letter-u: unicode('f490'); +$ti-icon-square-letter-v: unicode('f4bb'); +$ti-icon-square-letter-w: unicode('f491'); +$ti-icon-square-letter-x: unicode('f4bc'); +$ti-icon-square-letter-y: unicode('f492'); +$ti-icon-square-letter-z: unicode('f493'); +$ti-icon-square-minus: unicode('eb29'); +$ti-icon-square-number-0: unicode('eee5'); +$ti-icon-square-number-1: unicode('eee6'); +$ti-icon-square-number-2: unicode('eee7'); +$ti-icon-square-number-3: unicode('eee8'); +$ti-icon-square-number-4: unicode('eee9'); +$ti-icon-square-number-5: unicode('eeea'); +$ti-icon-square-number-6: unicode('eeeb'); +$ti-icon-square-number-7: unicode('eeec'); +$ti-icon-square-number-8: unicode('eeed'); +$ti-icon-square-number-9: unicode('eeee'); +$ti-icon-square-off: unicode('eeef'); +$ti-icon-square-plus: unicode('eb2a'); +$ti-icon-square-root: unicode('eef1'); +$ti-icon-square-root-2: unicode('eef0'); +$ti-icon-square-rotated: unicode('ecdf'); +$ti-icon-square-rotated-filled: unicode('f6a4'); +$ti-icon-square-rotated-forbid: unicode('f01c'); +$ti-icon-square-rotated-forbid-2: unicode('f01b'); +$ti-icon-square-rotated-off: unicode('eef2'); +$ti-icon-square-rounded: unicode('f59a'); +$ti-icon-square-rounded-arrow-down: unicode('f639'); +$ti-icon-square-rounded-arrow-down-filled: unicode('f6db'); +$ti-icon-square-rounded-arrow-left: unicode('f63a'); +$ti-icon-square-rounded-arrow-left-filled: unicode('f6dc'); +$ti-icon-square-rounded-arrow-right: unicode('f63b'); +$ti-icon-square-rounded-arrow-right-filled: unicode('f6dd'); +$ti-icon-square-rounded-arrow-up: unicode('f63c'); +$ti-icon-square-rounded-arrow-up-filled: unicode('f6de'); +$ti-icon-square-rounded-check: unicode('f63d'); +$ti-icon-square-rounded-check-filled: unicode('f6df'); +$ti-icon-square-rounded-chevron-down: unicode('f62b'); +$ti-icon-square-rounded-chevron-down-filled: unicode('f6e0'); +$ti-icon-square-rounded-chevron-left: unicode('f62c'); +$ti-icon-square-rounded-chevron-left-filled: unicode('f6e1'); +$ti-icon-square-rounded-chevron-right: unicode('f62d'); +$ti-icon-square-rounded-chevron-right-filled: unicode('f6e2'); +$ti-icon-square-rounded-chevron-up: unicode('f62e'); +$ti-icon-square-rounded-chevron-up-filled: unicode('f6e3'); +$ti-icon-square-rounded-chevrons-down: unicode('f64f'); +$ti-icon-square-rounded-chevrons-down-filled: unicode('f6e4'); +$ti-icon-square-rounded-chevrons-left: unicode('f650'); +$ti-icon-square-rounded-chevrons-left-filled: unicode('f6e5'); +$ti-icon-square-rounded-chevrons-right: unicode('f651'); +$ti-icon-square-rounded-chevrons-right-filled: unicode('f6e6'); +$ti-icon-square-rounded-chevrons-up: unicode('f652'); +$ti-icon-square-rounded-chevrons-up-filled: unicode('f6e7'); +$ti-icon-square-rounded-filled: unicode('f6a5'); +$ti-icon-square-rounded-letter-a: unicode('f5ae'); +$ti-icon-square-rounded-letter-b: unicode('f5af'); +$ti-icon-square-rounded-letter-c: unicode('f5b0'); +$ti-icon-square-rounded-letter-d: unicode('f5b1'); +$ti-icon-square-rounded-letter-e: unicode('f5b2'); +$ti-icon-square-rounded-letter-f: unicode('f5b3'); +$ti-icon-square-rounded-letter-g: unicode('f5b4'); +$ti-icon-square-rounded-letter-h: unicode('f5b5'); +$ti-icon-square-rounded-letter-i: unicode('f5b6'); +$ti-icon-square-rounded-letter-j: unicode('f5b7'); +$ti-icon-square-rounded-letter-k: unicode('f5b8'); +$ti-icon-square-rounded-letter-l: unicode('f5b9'); +$ti-icon-square-rounded-letter-m: unicode('f5ba'); +$ti-icon-square-rounded-letter-n: unicode('f5bb'); +$ti-icon-square-rounded-letter-o: unicode('f5bc'); +$ti-icon-square-rounded-letter-p: unicode('f5bd'); +$ti-icon-square-rounded-letter-q: unicode('f5be'); +$ti-icon-square-rounded-letter-r: unicode('f5bf'); +$ti-icon-square-rounded-letter-s: unicode('f5c0'); +$ti-icon-square-rounded-letter-t: unicode('f5c1'); +$ti-icon-square-rounded-letter-u: unicode('f5c2'); +$ti-icon-square-rounded-letter-v: unicode('f5c3'); +$ti-icon-square-rounded-letter-w: unicode('f5c4'); +$ti-icon-square-rounded-letter-x: unicode('f5c5'); +$ti-icon-square-rounded-letter-y: unicode('f5c6'); +$ti-icon-square-rounded-letter-z: unicode('f5c7'); +$ti-icon-square-rounded-minus: unicode('f63e'); +$ti-icon-square-rounded-number-0: unicode('f5c8'); +$ti-icon-square-rounded-number-0-filled: unicode('f778'); +$ti-icon-square-rounded-number-1: unicode('f5c9'); +$ti-icon-square-rounded-number-1-filled: unicode('f779'); +$ti-icon-square-rounded-number-2: unicode('f5ca'); +$ti-icon-square-rounded-number-2-filled: unicode('f77a'); +$ti-icon-square-rounded-number-3: unicode('f5cb'); +$ti-icon-square-rounded-number-3-filled: unicode('f77b'); +$ti-icon-square-rounded-number-4: unicode('f5cc'); +$ti-icon-square-rounded-number-4-filled: unicode('f77c'); +$ti-icon-square-rounded-number-5: unicode('f5cd'); +$ti-icon-square-rounded-number-5-filled: unicode('f77d'); +$ti-icon-square-rounded-number-6: unicode('f5ce'); +$ti-icon-square-rounded-number-6-filled: unicode('f77e'); +$ti-icon-square-rounded-number-7: unicode('f5cf'); +$ti-icon-square-rounded-number-7-filled: unicode('f77f'); +$ti-icon-square-rounded-number-8: unicode('f5d0'); +$ti-icon-square-rounded-number-8-filled: unicode('f780'); +$ti-icon-square-rounded-number-9: unicode('f5d1'); +$ti-icon-square-rounded-number-9-filled: unicode('f781'); +$ti-icon-square-rounded-plus: unicode('f63f'); +$ti-icon-square-rounded-plus-filled: unicode('f6e8'); +$ti-icon-square-rounded-x: unicode('f640'); +$ti-icon-square-rounded-x-filled: unicode('f6e9'); +$ti-icon-square-toggle: unicode('eef4'); +$ti-icon-square-toggle-horizontal: unicode('eef3'); +$ti-icon-square-x: unicode('eb2b'); +$ti-icon-squares-diagonal: unicode('eef5'); +$ti-icon-squares-filled: unicode('eef6'); +$ti-icon-stack: unicode('eb2d'); +$ti-icon-stack-2: unicode('eef7'); +$ti-icon-stack-3: unicode('ef9d'); +$ti-icon-stack-pop: unicode('f234'); +$ti-icon-stack-push: unicode('f235'); +$ti-icon-stairs: unicode('eca6'); +$ti-icon-stairs-down: unicode('eca4'); +$ti-icon-stairs-up: unicode('eca5'); +$ti-icon-star: unicode('eb2e'); +$ti-icon-star-filled: unicode('f6a6'); +$ti-icon-star-half: unicode('ed19'); +$ti-icon-star-half-filled: unicode('f6a7'); +$ti-icon-star-off: unicode('ed62'); +$ti-icon-stars: unicode('ed38'); +$ti-icon-stars-filled: unicode('f6a8'); +$ti-icon-stars-off: unicode('f430'); +$ti-icon-status-change: unicode('f3b0'); +$ti-icon-steam: unicode('f24b'); +$ti-icon-steering-wheel: unicode('ec7b'); +$ti-icon-steering-wheel-off: unicode('f431'); +$ti-icon-step-into: unicode('ece0'); +$ti-icon-step-out: unicode('ece1'); +$ti-icon-stereo-glasses: unicode('f4cb'); +$ti-icon-stethoscope: unicode('edbe'); +$ti-icon-stethoscope-off: unicode('f432'); +$ti-icon-sticker: unicode('eb2f'); +$ti-icon-storm: unicode('f24c'); +$ti-icon-storm-off: unicode('f433'); +$ti-icon-stretching: unicode('f2db'); +$ti-icon-strikethrough: unicode('eb9e'); +$ti-icon-submarine: unicode('ed94'); +$ti-icon-subscript: unicode('eb9f'); +$ti-icon-subtask: unicode('ec9f'); +$ti-icon-sum: unicode('eb73'); +$ti-icon-sum-off: unicode('f1ab'); +$ti-icon-sun: unicode('eb30'); +$ti-icon-sun-filled: unicode('f6a9'); +$ti-icon-sun-high: unicode('f236'); +$ti-icon-sun-low: unicode('f237'); +$ti-icon-sun-moon: unicode('f4a3'); +$ti-icon-sun-off: unicode('ed63'); +$ti-icon-sun-wind: unicode('f238'); +$ti-icon-sunglasses: unicode('f239'); +$ti-icon-sunrise: unicode('ef1c'); +$ti-icon-sunset: unicode('ec31'); +$ti-icon-sunset-2: unicode('f23a'); +$ti-icon-superscript: unicode('eba0'); +$ti-icon-svg: unicode('f25a'); +$ti-icon-swimming: unicode('ec92'); +$ti-icon-swipe: unicode('f551'); +$ti-icon-switch: unicode('eb33'); +$ti-icon-switch-2: unicode('edbf'); +$ti-icon-switch-3: unicode('edc0'); +$ti-icon-switch-horizontal: unicode('eb31'); +$ti-icon-switch-vertical: unicode('eb32'); +$ti-icon-sword: unicode('f030'); +$ti-icon-sword-off: unicode('f434'); +$ti-icon-swords: unicode('f132'); +$ti-icon-table: unicode('eba1'); +$ti-icon-table-alias: unicode('f25b'); +$ti-icon-table-export: unicode('eef8'); +$ti-icon-table-filled: unicode('f782'); +$ti-icon-table-import: unicode('eef9'); +$ti-icon-table-off: unicode('eefa'); +$ti-icon-table-options: unicode('f25c'); +$ti-icon-table-shortcut: unicode('f25d'); +$ti-icon-tag: unicode('eb34'); +$ti-icon-tag-off: unicode('efc0'); +$ti-icon-tags: unicode('ef86'); +$ti-icon-tags-off: unicode('efc1'); +$ti-icon-tallymark-1: unicode('ec46'); +$ti-icon-tallymark-2: unicode('ec47'); +$ti-icon-tallymark-3: unicode('ec48'); +$ti-icon-tallymark-4: unicode('ec49'); +$ti-icon-tallymarks: unicode('ec4a'); +$ti-icon-tank: unicode('ed95'); +$ti-icon-target: unicode('eb35'); +$ti-icon-target-arrow: unicode('f51a'); +$ti-icon-target-off: unicode('f1ad'); +$ti-icon-teapot: unicode('f552'); +$ti-icon-telescope: unicode('f07d'); +$ti-icon-telescope-off: unicode('f1ae'); +$ti-icon-temperature: unicode('eb38'); +$ti-icon-temperature-celsius: unicode('eb36'); +$ti-icon-temperature-fahrenheit: unicode('eb37'); +$ti-icon-temperature-minus: unicode('ebed'); +$ti-icon-temperature-off: unicode('f1af'); +$ti-icon-temperature-plus: unicode('ebee'); +$ti-icon-template: unicode('eb39'); +$ti-icon-template-off: unicode('f1b0'); +$ti-icon-tent: unicode('eefb'); +$ti-icon-tent-off: unicode('f435'); +$ti-icon-terminal: unicode('ebdc'); +$ti-icon-terminal-2: unicode('ebef'); +$ti-icon-test-pipe: unicode('eb3a'); +$ti-icon-test-pipe-2: unicode('f0a4'); +$ti-icon-test-pipe-off: unicode('f1b1'); +$ti-icon-tex: unicode('f4e0'); +$ti-icon-text-caption: unicode('f4a4'); +$ti-icon-text-color: unicode('f2dc'); +$ti-icon-text-decrease: unicode('f202'); +$ti-icon-text-direction-ltr: unicode('eefc'); +$ti-icon-text-direction-rtl: unicode('eefd'); +$ti-icon-text-increase: unicode('f203'); +$ti-icon-text-orientation: unicode('f2a4'); +$ti-icon-text-plus: unicode('f2a5'); +$ti-icon-text-recognition: unicode('f204'); +$ti-icon-text-resize: unicode('ef87'); +$ti-icon-text-size: unicode('f2b1'); +$ti-icon-text-spellcheck: unicode('f2a6'); +$ti-icon-text-wrap: unicode('ebdd'); +$ti-icon-text-wrap-disabled: unicode('eca7'); +$ti-icon-texture: unicode('f51b'); +$ti-icon-theater: unicode('f79b'); +$ti-icon-thermometer: unicode('ef67'); +$ti-icon-thumb-down: unicode('eb3b'); +$ti-icon-thumb-down-filled: unicode('f6aa'); +$ti-icon-thumb-down-off: unicode('f436'); +$ti-icon-thumb-up: unicode('eb3c'); +$ti-icon-thumb-up-filled: unicode('f6ab'); +$ti-icon-thumb-up-off: unicode('f437'); +$ti-icon-tic-tac: unicode('f51c'); +$ti-icon-ticket: unicode('eb3d'); +$ti-icon-ticket-off: unicode('f1b2'); +$ti-icon-tie: unicode('f07e'); +$ti-icon-tilde: unicode('f4a5'); +$ti-icon-tilt-shift: unicode('eefe'); +$ti-icon-tilt-shift-off: unicode('f1b3'); +$ti-icon-timeline: unicode('f031'); +$ti-icon-timeline-event: unicode('f553'); +$ti-icon-timeline-event-exclamation: unicode('f662'); +$ti-icon-timeline-event-minus: unicode('f663'); +$ti-icon-timeline-event-plus: unicode('f664'); +$ti-icon-timeline-event-text: unicode('f665'); +$ti-icon-timeline-event-x: unicode('f666'); +$ti-icon-tir: unicode('ebf0'); +$ti-icon-toggle-left: unicode('eb3e'); +$ti-icon-toggle-right: unicode('eb3f'); +$ti-icon-toilet-paper: unicode('efd3'); +$ti-icon-toilet-paper-off: unicode('f1b4'); +$ti-icon-tool: unicode('eb40'); +$ti-icon-tools: unicode('ebca'); +$ti-icon-tools-kitchen: unicode('ed64'); +$ti-icon-tools-kitchen-2: unicode('eeff'); +$ti-icon-tools-kitchen-2-off: unicode('f1b5'); +$ti-icon-tools-kitchen-off: unicode('f1b6'); +$ti-icon-tools-off: unicode('f1b7'); +$ti-icon-tooltip: unicode('f2dd'); +$ti-icon-topology-bus: unicode('f5d9'); +$ti-icon-topology-complex: unicode('f5da'); +$ti-icon-topology-full: unicode('f5dc'); +$ti-icon-topology-full-hierarchy: unicode('f5db'); +$ti-icon-topology-ring: unicode('f5df'); +$ti-icon-topology-ring-2: unicode('f5dd'); +$ti-icon-topology-ring-3: unicode('f5de'); +$ti-icon-topology-star: unicode('f5e5'); +$ti-icon-topology-star-2: unicode('f5e0'); +$ti-icon-topology-star-3: unicode('f5e1'); +$ti-icon-topology-star-ring: unicode('f5e4'); +$ti-icon-topology-star-ring-2: unicode('f5e2'); +$ti-icon-topology-star-ring-3: unicode('f5e3'); +$ti-icon-torii: unicode('f59b'); +$ti-icon-tornado: unicode('ece2'); +$ti-icon-tournament: unicode('ecd0'); +$ti-icon-tower: unicode('f2cb'); +$ti-icon-tower-off: unicode('f2ca'); +$ti-icon-track: unicode('ef00'); +$ti-icon-tractor: unicode('ec0d'); +$ti-icon-trademark: unicode('ec0e'); +$ti-icon-traffic-cone: unicode('ec0f'); +$ti-icon-traffic-cone-off: unicode('f1b8'); +$ti-icon-traffic-lights: unicode('ed39'); +$ti-icon-traffic-lights-off: unicode('f1b9'); +$ti-icon-train: unicode('ed96'); +$ti-icon-transfer-in: unicode('ef2f'); +$ti-icon-transfer-out: unicode('ef30'); +$ti-icon-transform: unicode('f38e'); +$ti-icon-transform-filled: unicode('f6ac'); +$ti-icon-transition-bottom: unicode('f2b2'); +$ti-icon-transition-left: unicode('f2b3'); +$ti-icon-transition-right: unicode('f2b4'); +$ti-icon-transition-top: unicode('f2b5'); +$ti-icon-trash: unicode('eb41'); +$ti-icon-trash-filled: unicode('f783'); +$ti-icon-trash-off: unicode('ed65'); +$ti-icon-trash-x: unicode('ef88'); +$ti-icon-trash-x-filled: unicode('f784'); +$ti-icon-tree: unicode('ef01'); +$ti-icon-trees: unicode('ec10'); +$ti-icon-trekking: unicode('f5ad'); +$ti-icon-trending-down: unicode('eb42'); +$ti-icon-trending-down-2: unicode('edc1'); +$ti-icon-trending-down-3: unicode('edc2'); +$ti-icon-trending-up: unicode('eb43'); +$ti-icon-trending-up-2: unicode('edc3'); +$ti-icon-trending-up-3: unicode('edc4'); +$ti-icon-triangle: unicode('eb44'); +$ti-icon-triangle-filled: unicode('f6ad'); +$ti-icon-triangle-inverted: unicode('f01d'); +$ti-icon-triangle-inverted-filled: unicode('f6ae'); +$ti-icon-triangle-off: unicode('ef02'); +$ti-icon-triangle-square-circle: unicode('ece8'); +$ti-icon-triangles: unicode('f0a5'); +$ti-icon-trident: unicode('ecc5'); +$ti-icon-trolley: unicode('f4cc'); +$ti-icon-trophy: unicode('eb45'); +$ti-icon-trophy-filled: unicode('f6af'); +$ti-icon-trophy-off: unicode('f438'); +$ti-icon-trowel: unicode('f368'); +$ti-icon-truck: unicode('ebc4'); +$ti-icon-truck-delivery: unicode('ec4b'); +$ti-icon-truck-loading: unicode('f1da'); +$ti-icon-truck-off: unicode('ef03'); +$ti-icon-truck-return: unicode('ec4c'); +$ti-icon-txt: unicode('f3b1'); +$ti-icon-typography: unicode('ebc5'); +$ti-icon-typography-off: unicode('f1ba'); +$ti-icon-ufo: unicode('f26f'); +$ti-icon-ufo-off: unicode('f26e'); +$ti-icon-umbrella: unicode('ebf1'); +$ti-icon-umbrella-filled: unicode('f6b0'); +$ti-icon-umbrella-off: unicode('f1bb'); +$ti-icon-underline: unicode('eba2'); +$ti-icon-unlink: unicode('eb46'); +$ti-icon-upload: unicode('eb47'); +$ti-icon-urgent: unicode('eb48'); +$ti-icon-usb: unicode('f00c'); +$ti-icon-user: unicode('eb4d'); +$ti-icon-user-bolt: unicode('f9d1'); +$ti-icon-user-cancel: unicode('f9d2'); +$ti-icon-user-check: unicode('eb49'); +$ti-icon-user-circle: unicode('ef68'); +$ti-icon-user-code: unicode('f9d3'); +$ti-icon-user-cog: unicode('f9d4'); +$ti-icon-user-dollar: unicode('f9d5'); +$ti-icon-user-down: unicode('f9d6'); +$ti-icon-user-edit: unicode('f7cc'); +$ti-icon-user-exclamation: unicode('ec12'); +$ti-icon-user-heart: unicode('f7cd'); +$ti-icon-user-minus: unicode('eb4a'); +$ti-icon-user-off: unicode('ecf9'); +$ti-icon-user-pause: unicode('f9d7'); +$ti-icon-user-pin: unicode('f7ce'); +$ti-icon-user-plus: unicode('eb4b'); +$ti-icon-user-question: unicode('f7cf'); +$ti-icon-user-search: unicode('ef89'); +$ti-icon-user-share: unicode('f9d8'); +$ti-icon-user-shield: unicode('f7d0'); +$ti-icon-user-star: unicode('f7d1'); +$ti-icon-user-up: unicode('f7d2'); +$ti-icon-user-x: unicode('eb4c'); +$ti-icon-users: unicode('ebf2'); +$ti-icon-uv-index: unicode('f3b2'); +$ti-icon-ux-circle: unicode('f369'); +$ti-icon-vaccine: unicode('ef04'); +$ti-icon-vaccine-bottle: unicode('ef69'); +$ti-icon-vaccine-bottle-off: unicode('f439'); +$ti-icon-vaccine-off: unicode('f1bc'); +$ti-icon-vacuum-cleaner: unicode('f5e6'); +$ti-icon-variable: unicode('ef05'); +$ti-icon-variable-minus: unicode('f36a'); +$ti-icon-variable-off: unicode('f1bd'); +$ti-icon-variable-plus: unicode('f36b'); +$ti-icon-vector: unicode('eca9'); +$ti-icon-vector-bezier: unicode('ef1d'); +$ti-icon-vector-bezier-2: unicode('f1a3'); +$ti-icon-vector-bezier-arc: unicode('f4cd'); +$ti-icon-vector-bezier-circle: unicode('f4ce'); +$ti-icon-vector-off: unicode('f1be'); +$ti-icon-vector-spline: unicode('f565'); +$ti-icon-vector-triangle: unicode('eca8'); +$ti-icon-vector-triangle-off: unicode('f1bf'); +$ti-icon-venus: unicode('ec86'); +$ti-icon-versions: unicode('ed52'); +$ti-icon-versions-filled: unicode('f6b1'); +$ti-icon-versions-off: unicode('f1c0'); +$ti-icon-video: unicode('ed22'); +$ti-icon-video-minus: unicode('ed1f'); +$ti-icon-video-off: unicode('ed20'); +$ti-icon-video-plus: unicode('ed21'); +$ti-icon-view-360: unicode('ed84'); +$ti-icon-view-360-off: unicode('f1c1'); +$ti-icon-viewfinder: unicode('eb4e'); +$ti-icon-viewfinder-off: unicode('f1c2'); +$ti-icon-viewport-narrow: unicode('ebf3'); +$ti-icon-viewport-wide: unicode('ebf4'); +$ti-icon-vinyl: unicode('f00d'); +$ti-icon-vip: unicode('f3b3'); +$ti-icon-vip-off: unicode('f43a'); +$ti-icon-virus: unicode('eb74'); +$ti-icon-virus-off: unicode('ed66'); +$ti-icon-virus-search: unicode('ed67'); +$ti-icon-vocabulary: unicode('ef1e'); +$ti-icon-vocabulary-off: unicode('f43b'); +$ti-icon-volcano: unicode('f79c'); +$ti-icon-volume: unicode('eb51'); +$ti-icon-volume-2: unicode('eb4f'); +$ti-icon-volume-3: unicode('eb50'); +$ti-icon-volume-off: unicode('f1c3'); +$ti-icon-walk: unicode('ec87'); +$ti-icon-wall: unicode('ef7a'); +$ti-icon-wall-off: unicode('f43c'); +$ti-icon-wallet: unicode('eb75'); +$ti-icon-wallet-off: unicode('f1c4'); +$ti-icon-wallpaper: unicode('ef56'); +$ti-icon-wallpaper-off: unicode('f1c5'); +$ti-icon-wand: unicode('ebcb'); +$ti-icon-wand-off: unicode('f1c6'); +$ti-icon-wash: unicode('f311'); +$ti-icon-wash-dry: unicode('f304'); +$ti-icon-wash-dry-1: unicode('f2fa'); +$ti-icon-wash-dry-2: unicode('f2fb'); +$ti-icon-wash-dry-3: unicode('f2fc'); +$ti-icon-wash-dry-a: unicode('f2fd'); +$ti-icon-wash-dry-dip: unicode('f2fe'); +$ti-icon-wash-dry-f: unicode('f2ff'); +$ti-icon-wash-dry-hang: unicode('f300'); +$ti-icon-wash-dry-off: unicode('f301'); +$ti-icon-wash-dry-p: unicode('f302'); +$ti-icon-wash-dry-shade: unicode('f303'); +$ti-icon-wash-dry-w: unicode('f322'); +$ti-icon-wash-dryclean: unicode('f305'); +$ti-icon-wash-dryclean-off: unicode('f323'); +$ti-icon-wash-gentle: unicode('f306'); +$ti-icon-wash-machine: unicode('f25e'); +$ti-icon-wash-off: unicode('f307'); +$ti-icon-wash-press: unicode('f308'); +$ti-icon-wash-temperature-1: unicode('f309'); +$ti-icon-wash-temperature-2: unicode('f30a'); +$ti-icon-wash-temperature-3: unicode('f30b'); +$ti-icon-wash-temperature-4: unicode('f30c'); +$ti-icon-wash-temperature-5: unicode('f30d'); +$ti-icon-wash-temperature-6: unicode('f30e'); +$ti-icon-wash-tumble-dry: unicode('f30f'); +$ti-icon-wash-tumble-off: unicode('f310'); +$ti-icon-wave-saw-tool: unicode('ecd3'); +$ti-icon-wave-sine: unicode('ecd4'); +$ti-icon-wave-square: unicode('ecd5'); +$ti-icon-webhook: unicode('f01e'); +$ti-icon-webhook-off: unicode('f43d'); +$ti-icon-weight: unicode('f589'); +$ti-icon-wheelchair: unicode('f1db'); +$ti-icon-wheelchair-off: unicode('f43e'); +$ti-icon-whirl: unicode('f51d'); +$ti-icon-wifi: unicode('eb52'); +$ti-icon-wifi-0: unicode('eba3'); +$ti-icon-wifi-1: unicode('eba4'); +$ti-icon-wifi-2: unicode('eba5'); +$ti-icon-wifi-off: unicode('ecfa'); +$ti-icon-wind: unicode('ec34'); +$ti-icon-wind-off: unicode('f1c7'); +$ti-icon-windmill: unicode('ed85'); +$ti-icon-windmill-filled: unicode('f6b2'); +$ti-icon-windmill-off: unicode('f1c8'); +$ti-icon-window: unicode('ef06'); +$ti-icon-window-maximize: unicode('f1f1'); +$ti-icon-window-minimize: unicode('f1f2'); +$ti-icon-window-off: unicode('f1c9'); +$ti-icon-windsock: unicode('f06d'); +$ti-icon-wiper: unicode('ecab'); +$ti-icon-wiper-wash: unicode('ecaa'); +$ti-icon-woman: unicode('eb53'); +$ti-icon-wood: unicode('f359'); +$ti-icon-world: unicode('eb54'); +$ti-icon-world-bolt: unicode('f9d9'); +$ti-icon-world-cancel: unicode('f9da'); +$ti-icon-world-check: unicode('f9db'); +$ti-icon-world-code: unicode('f9dc'); +$ti-icon-world-cog: unicode('f9dd'); +$ti-icon-world-dollar: unicode('f9de'); +$ti-icon-world-down: unicode('f9df'); +$ti-icon-world-download: unicode('ef8a'); +$ti-icon-world-exclamation: unicode('f9e0'); +$ti-icon-world-heart: unicode('f9e1'); +$ti-icon-world-latitude: unicode('ed2e'); +$ti-icon-world-longitude: unicode('ed2f'); +$ti-icon-world-minus: unicode('f9e2'); +$ti-icon-world-off: unicode('f1ca'); +$ti-icon-world-pause: unicode('f9e3'); +$ti-icon-world-pin: unicode('f9e4'); +$ti-icon-world-plus: unicode('f9e5'); +$ti-icon-world-question: unicode('f9e6'); +$ti-icon-world-search: unicode('f9e7'); +$ti-icon-world-share: unicode('f9e8'); +$ti-icon-world-star: unicode('f9e9'); +$ti-icon-world-up: unicode('f9ea'); +$ti-icon-world-upload: unicode('ef8b'); +$ti-icon-world-www: unicode('f38f'); +$ti-icon-world-x: unicode('f9eb'); +$ti-icon-wrecking-ball: unicode('ed97'); +$ti-icon-writing: unicode('ef08'); +$ti-icon-writing-off: unicode('f1cb'); +$ti-icon-writing-sign: unicode('ef07'); +$ti-icon-writing-sign-off: unicode('f1cc'); +$ti-icon-x: unicode('eb55'); +$ti-icon-xbox-a: unicode('f2b6'); +$ti-icon-xbox-b: unicode('f2b7'); +$ti-icon-xbox-x: unicode('f2b8'); +$ti-icon-xbox-y: unicode('f2b9'); +$ti-icon-yin-yang: unicode('ec35'); +$ti-icon-yin-yang-filled: unicode('f785'); +$ti-icon-yoga: unicode('f01f'); +$ti-icon-zeppelin: unicode('f270'); +$ti-icon-zeppelin-off: unicode('f43f'); +$ti-icon-zip: unicode('f3b4'); +$ti-icon-zodiac-aquarius: unicode('ecac'); +$ti-icon-zodiac-aries: unicode('ecad'); +$ti-icon-zodiac-cancer: unicode('ecae'); +$ti-icon-zodiac-capricorn: unicode('ecaf'); +$ti-icon-zodiac-gemini: unicode('ecb0'); +$ti-icon-zodiac-leo: unicode('ecb1'); +$ti-icon-zodiac-libra: unicode('ecb2'); +$ti-icon-zodiac-pisces: unicode('ecb3'); +$ti-icon-zodiac-sagittarius: unicode('ecb4'); +$ti-icon-zodiac-scorpio: unicode('ecb5'); +$ti-icon-zodiac-taurus: unicode('ecb6'); +$ti-icon-zodiac-virgo: unicode('ecb7'); +$ti-icon-zoom-cancel: unicode('ec4d'); +$ti-icon-zoom-check: unicode('ef09'); +$ti-icon-zoom-check-filled: unicode('f786'); +$ti-icon-zoom-code: unicode('f07f'); +$ti-icon-zoom-exclamation: unicode('f080'); +$ti-icon-zoom-filled: unicode('f787'); +$ti-icon-zoom-in: unicode('eb56'); +$ti-icon-zoom-in-area: unicode('f1dc'); +$ti-icon-zoom-in-area-filled: unicode('f788'); +$ti-icon-zoom-in-filled: unicode('f789'); +$ti-icon-zoom-money: unicode('ef0a'); +$ti-icon-zoom-out: unicode('eb57'); +$ti-icon-zoom-out-area: unicode('f1dd'); +$ti-icon-zoom-out-filled: unicode('f78a'); +$ti-icon-zoom-pan: unicode('f1de'); +$ti-icon-zoom-question: unicode('edeb'); +$ti-icon-zoom-replace: unicode('f2a7'); +$ti-icon-zoom-reset: unicode('f295'); +$ti-icon-zzz: unicode('f228'); +$ti-icon-zzz-off: unicode('f440'); + + +.#{$ti-prefix}-123:before { content: $ti-icon-123; } +.#{$ti-prefix}-24-hours:before { content: $ti-icon-24-hours; } +.#{$ti-prefix}-2fa:before { content: $ti-icon-2fa; } +.#{$ti-prefix}-360:before { content: $ti-icon-360; } +.#{$ti-prefix}-360-view:before { content: $ti-icon-360-view; } +.#{$ti-prefix}-3d-cube-sphere:before { content: $ti-icon-3d-cube-sphere; } +.#{$ti-prefix}-3d-cube-sphere-off:before { content: $ti-icon-3d-cube-sphere-off; } +.#{$ti-prefix}-3d-rotate:before { content: $ti-icon-3d-rotate; } +.#{$ti-prefix}-a-b:before { content: $ti-icon-a-b; } +.#{$ti-prefix}-a-b-2:before { content: $ti-icon-a-b-2; } +.#{$ti-prefix}-a-b-off:before { content: $ti-icon-a-b-off; } +.#{$ti-prefix}-abacus:before { content: $ti-icon-abacus; } +.#{$ti-prefix}-abacus-off:before { content: $ti-icon-abacus-off; } +.#{$ti-prefix}-abc:before { content: $ti-icon-abc; } +.#{$ti-prefix}-access-point:before { content: $ti-icon-access-point; } +.#{$ti-prefix}-access-point-off:before { content: $ti-icon-access-point-off; } +.#{$ti-prefix}-accessible:before { content: $ti-icon-accessible; } +.#{$ti-prefix}-accessible-off:before { content: $ti-icon-accessible-off; } +.#{$ti-prefix}-accessible-off-filled:before { content: $ti-icon-accessible-off-filled; } +.#{$ti-prefix}-activity:before { content: $ti-icon-activity; } +.#{$ti-prefix}-activity-heartbeat:before { content: $ti-icon-activity-heartbeat; } +.#{$ti-prefix}-ad:before { content: $ti-icon-ad; } +.#{$ti-prefix}-ad-2:before { content: $ti-icon-ad-2; } +.#{$ti-prefix}-ad-circle:before { content: $ti-icon-ad-circle; } +.#{$ti-prefix}-ad-circle-filled:before { content: $ti-icon-ad-circle-filled; } +.#{$ti-prefix}-ad-circle-off:before { content: $ti-icon-ad-circle-off; } +.#{$ti-prefix}-ad-filled:before { content: $ti-icon-ad-filled; } +.#{$ti-prefix}-ad-off:before { content: $ti-icon-ad-off; } +.#{$ti-prefix}-address-book:before { content: $ti-icon-address-book; } +.#{$ti-prefix}-address-book-off:before { content: $ti-icon-address-book-off; } +.#{$ti-prefix}-adjustments:before { content: $ti-icon-adjustments; } +.#{$ti-prefix}-adjustments-alt:before { content: $ti-icon-adjustments-alt; } +.#{$ti-prefix}-adjustments-bolt:before { content: $ti-icon-adjustments-bolt; } +.#{$ti-prefix}-adjustments-cancel:before { content: $ti-icon-adjustments-cancel; } +.#{$ti-prefix}-adjustments-check:before { content: $ti-icon-adjustments-check; } +.#{$ti-prefix}-adjustments-code:before { content: $ti-icon-adjustments-code; } +.#{$ti-prefix}-adjustments-cog:before { content: $ti-icon-adjustments-cog; } +.#{$ti-prefix}-adjustments-dollar:before { content: $ti-icon-adjustments-dollar; } +.#{$ti-prefix}-adjustments-down:before { content: $ti-icon-adjustments-down; } +.#{$ti-prefix}-adjustments-exclamation:before { content: $ti-icon-adjustments-exclamation; } +.#{$ti-prefix}-adjustments-filled:before { content: $ti-icon-adjustments-filled; } +.#{$ti-prefix}-adjustments-heart:before { content: $ti-icon-adjustments-heart; } +.#{$ti-prefix}-adjustments-horizontal:before { content: $ti-icon-adjustments-horizontal; } +.#{$ti-prefix}-adjustments-minus:before { content: $ti-icon-adjustments-minus; } +.#{$ti-prefix}-adjustments-off:before { content: $ti-icon-adjustments-off; } +.#{$ti-prefix}-adjustments-pause:before { content: $ti-icon-adjustments-pause; } +.#{$ti-prefix}-adjustments-pin:before { content: $ti-icon-adjustments-pin; } +.#{$ti-prefix}-adjustments-plus:before { content: $ti-icon-adjustments-plus; } +.#{$ti-prefix}-adjustments-question:before { content: $ti-icon-adjustments-question; } +.#{$ti-prefix}-adjustments-search:before { content: $ti-icon-adjustments-search; } +.#{$ti-prefix}-adjustments-share:before { content: $ti-icon-adjustments-share; } +.#{$ti-prefix}-adjustments-star:before { content: $ti-icon-adjustments-star; } +.#{$ti-prefix}-adjustments-up:before { content: $ti-icon-adjustments-up; } +.#{$ti-prefix}-adjustments-x:before { content: $ti-icon-adjustments-x; } +.#{$ti-prefix}-aerial-lift:before { content: $ti-icon-aerial-lift; } +.#{$ti-prefix}-affiliate:before { content: $ti-icon-affiliate; } +.#{$ti-prefix}-affiliate-filled:before { content: $ti-icon-affiliate-filled; } +.#{$ti-prefix}-air-balloon:before { content: $ti-icon-air-balloon; } +.#{$ti-prefix}-air-conditioning:before { content: $ti-icon-air-conditioning; } +.#{$ti-prefix}-air-conditioning-disabled:before { content: $ti-icon-air-conditioning-disabled; } +.#{$ti-prefix}-alarm:before { content: $ti-icon-alarm; } +.#{$ti-prefix}-alarm-filled:before { content: $ti-icon-alarm-filled; } +.#{$ti-prefix}-alarm-minus:before { content: $ti-icon-alarm-minus; } +.#{$ti-prefix}-alarm-minus-filled:before { content: $ti-icon-alarm-minus-filled; } +.#{$ti-prefix}-alarm-off:before { content: $ti-icon-alarm-off; } +.#{$ti-prefix}-alarm-plus:before { content: $ti-icon-alarm-plus; } +.#{$ti-prefix}-alarm-plus-filled:before { content: $ti-icon-alarm-plus-filled; } +.#{$ti-prefix}-alarm-snooze:before { content: $ti-icon-alarm-snooze; } +.#{$ti-prefix}-alarm-snooze-filled:before { content: $ti-icon-alarm-snooze-filled; } +.#{$ti-prefix}-album:before { content: $ti-icon-album; } +.#{$ti-prefix}-album-off:before { content: $ti-icon-album-off; } +.#{$ti-prefix}-alert-circle:before { content: $ti-icon-alert-circle; } +.#{$ti-prefix}-alert-circle-filled:before { content: $ti-icon-alert-circle-filled; } +.#{$ti-prefix}-alert-hexagon:before { content: $ti-icon-alert-hexagon; } +.#{$ti-prefix}-alert-octagon:before { content: $ti-icon-alert-octagon; } +.#{$ti-prefix}-alert-octagon-filled:before { content: $ti-icon-alert-octagon-filled; } +.#{$ti-prefix}-alert-small:before { content: $ti-icon-alert-small; } +.#{$ti-prefix}-alert-square:before { content: $ti-icon-alert-square; } +.#{$ti-prefix}-alert-square-rounded:before { content: $ti-icon-alert-square-rounded; } +.#{$ti-prefix}-alert-triangle:before { content: $ti-icon-alert-triangle; } +.#{$ti-prefix}-alert-triangle-filled:before { content: $ti-icon-alert-triangle-filled; } +.#{$ti-prefix}-alien:before { content: $ti-icon-alien; } +.#{$ti-prefix}-alien-filled:before { content: $ti-icon-alien-filled; } +.#{$ti-prefix}-align-box-bottom-center:before { content: $ti-icon-align-box-bottom-center; } +.#{$ti-prefix}-align-box-bottom-center-filled:before { content: $ti-icon-align-box-bottom-center-filled; } +.#{$ti-prefix}-align-box-bottom-left:before { content: $ti-icon-align-box-bottom-left; } +.#{$ti-prefix}-align-box-bottom-left-filled:before { content: $ti-icon-align-box-bottom-left-filled; } +.#{$ti-prefix}-align-box-bottom-right:before { content: $ti-icon-align-box-bottom-right; } +.#{$ti-prefix}-align-box-bottom-right-filled:before { content: $ti-icon-align-box-bottom-right-filled; } +.#{$ti-prefix}-align-box-center-middle:before { content: $ti-icon-align-box-center-middle; } +.#{$ti-prefix}-align-box-center-middle-filled:before { content: $ti-icon-align-box-center-middle-filled; } +.#{$ti-prefix}-align-box-left-bottom:before { content: $ti-icon-align-box-left-bottom; } +.#{$ti-prefix}-align-box-left-bottom-filled:before { content: $ti-icon-align-box-left-bottom-filled; } +.#{$ti-prefix}-align-box-left-middle:before { content: $ti-icon-align-box-left-middle; } +.#{$ti-prefix}-align-box-left-middle-filled:before { content: $ti-icon-align-box-left-middle-filled; } +.#{$ti-prefix}-align-box-left-top:before { content: $ti-icon-align-box-left-top; } +.#{$ti-prefix}-align-box-left-top-filled:before { content: $ti-icon-align-box-left-top-filled; } +.#{$ti-prefix}-align-box-right-bottom:before { content: $ti-icon-align-box-right-bottom; } +.#{$ti-prefix}-align-box-right-bottom-filled:before { content: $ti-icon-align-box-right-bottom-filled; } +.#{$ti-prefix}-align-box-right-middle:before { content: $ti-icon-align-box-right-middle; } +.#{$ti-prefix}-align-box-right-middle-filled:before { content: $ti-icon-align-box-right-middle-filled; } +.#{$ti-prefix}-align-box-right-top:before { content: $ti-icon-align-box-right-top; } +.#{$ti-prefix}-align-box-right-top-filled:before { content: $ti-icon-align-box-right-top-filled; } +.#{$ti-prefix}-align-box-top-center:before { content: $ti-icon-align-box-top-center; } +.#{$ti-prefix}-align-box-top-center-filled:before { content: $ti-icon-align-box-top-center-filled; } +.#{$ti-prefix}-align-box-top-left:before { content: $ti-icon-align-box-top-left; } +.#{$ti-prefix}-align-box-top-left-filled:before { content: $ti-icon-align-box-top-left-filled; } +.#{$ti-prefix}-align-box-top-right:before { content: $ti-icon-align-box-top-right; } +.#{$ti-prefix}-align-box-top-right-filled:before { content: $ti-icon-align-box-top-right-filled; } +.#{$ti-prefix}-align-center:before { content: $ti-icon-align-center; } +.#{$ti-prefix}-align-justified:before { content: $ti-icon-align-justified; } +.#{$ti-prefix}-align-left:before { content: $ti-icon-align-left; } +.#{$ti-prefix}-align-right:before { content: $ti-icon-align-right; } +.#{$ti-prefix}-alpha:before { content: $ti-icon-alpha; } +.#{$ti-prefix}-alphabet-cyrillic:before { content: $ti-icon-alphabet-cyrillic; } +.#{$ti-prefix}-alphabet-greek:before { content: $ti-icon-alphabet-greek; } +.#{$ti-prefix}-alphabet-latin:before { content: $ti-icon-alphabet-latin; } +.#{$ti-prefix}-ambulance:before { content: $ti-icon-ambulance; } +.#{$ti-prefix}-ampersand:before { content: $ti-icon-ampersand; } +.#{$ti-prefix}-analyze:before { content: $ti-icon-analyze; } +.#{$ti-prefix}-analyze-filled:before { content: $ti-icon-analyze-filled; } +.#{$ti-prefix}-analyze-off:before { content: $ti-icon-analyze-off; } +.#{$ti-prefix}-anchor:before { content: $ti-icon-anchor; } +.#{$ti-prefix}-anchor-off:before { content: $ti-icon-anchor-off; } +.#{$ti-prefix}-angle:before { content: $ti-icon-angle; } +.#{$ti-prefix}-ankh:before { content: $ti-icon-ankh; } +.#{$ti-prefix}-antenna:before { content: $ti-icon-antenna; } +.#{$ti-prefix}-antenna-bars-1:before { content: $ti-icon-antenna-bars-1; } +.#{$ti-prefix}-antenna-bars-2:before { content: $ti-icon-antenna-bars-2; } +.#{$ti-prefix}-antenna-bars-3:before { content: $ti-icon-antenna-bars-3; } +.#{$ti-prefix}-antenna-bars-4:before { content: $ti-icon-antenna-bars-4; } +.#{$ti-prefix}-antenna-bars-5:before { content: $ti-icon-antenna-bars-5; } +.#{$ti-prefix}-antenna-bars-off:before { content: $ti-icon-antenna-bars-off; } +.#{$ti-prefix}-antenna-off:before { content: $ti-icon-antenna-off; } +.#{$ti-prefix}-aperture:before { content: $ti-icon-aperture; } +.#{$ti-prefix}-aperture-off:before { content: $ti-icon-aperture-off; } +.#{$ti-prefix}-api:before { content: $ti-icon-api; } +.#{$ti-prefix}-api-app:before { content: $ti-icon-api-app; } +.#{$ti-prefix}-api-app-off:before { content: $ti-icon-api-app-off; } +.#{$ti-prefix}-api-off:before { content: $ti-icon-api-off; } +.#{$ti-prefix}-app-window:before { content: $ti-icon-app-window; } +.#{$ti-prefix}-app-window-filled:before { content: $ti-icon-app-window-filled; } +.#{$ti-prefix}-apple:before { content: $ti-icon-apple; } +.#{$ti-prefix}-apps:before { content: $ti-icon-apps; } +.#{$ti-prefix}-apps-filled:before { content: $ti-icon-apps-filled; } +.#{$ti-prefix}-apps-off:before { content: $ti-icon-apps-off; } +.#{$ti-prefix}-archive:before { content: $ti-icon-archive; } +.#{$ti-prefix}-archive-off:before { content: $ti-icon-archive-off; } +.#{$ti-prefix}-armchair:before { content: $ti-icon-armchair; } +.#{$ti-prefix}-armchair-2:before { content: $ti-icon-armchair-2; } +.#{$ti-prefix}-armchair-2-off:before { content: $ti-icon-armchair-2-off; } +.#{$ti-prefix}-armchair-off:before { content: $ti-icon-armchair-off; } +.#{$ti-prefix}-arrow-autofit-content:before { content: $ti-icon-arrow-autofit-content; } +.#{$ti-prefix}-arrow-autofit-content-filled:before { content: $ti-icon-arrow-autofit-content-filled; } +.#{$ti-prefix}-arrow-autofit-down:before { content: $ti-icon-arrow-autofit-down; } +.#{$ti-prefix}-arrow-autofit-height:before { content: $ti-icon-arrow-autofit-height; } +.#{$ti-prefix}-arrow-autofit-left:before { content: $ti-icon-arrow-autofit-left; } +.#{$ti-prefix}-arrow-autofit-right:before { content: $ti-icon-arrow-autofit-right; } +.#{$ti-prefix}-arrow-autofit-up:before { content: $ti-icon-arrow-autofit-up; } +.#{$ti-prefix}-arrow-autofit-width:before { content: $ti-icon-arrow-autofit-width; } +.#{$ti-prefix}-arrow-back:before { content: $ti-icon-arrow-back; } +.#{$ti-prefix}-arrow-back-up:before { content: $ti-icon-arrow-back-up; } +.#{$ti-prefix}-arrow-back-up-double:before { content: $ti-icon-arrow-back-up-double; } +.#{$ti-prefix}-arrow-badge-down:before { content: $ti-icon-arrow-badge-down; } +.#{$ti-prefix}-arrow-badge-down-filled:before { content: $ti-icon-arrow-badge-down-filled; } +.#{$ti-prefix}-arrow-badge-left:before { content: $ti-icon-arrow-badge-left; } +.#{$ti-prefix}-arrow-badge-left-filled:before { content: $ti-icon-arrow-badge-left-filled; } +.#{$ti-prefix}-arrow-badge-right:before { content: $ti-icon-arrow-badge-right; } +.#{$ti-prefix}-arrow-badge-right-filled:before { content: $ti-icon-arrow-badge-right-filled; } +.#{$ti-prefix}-arrow-badge-up:before { content: $ti-icon-arrow-badge-up; } +.#{$ti-prefix}-arrow-badge-up-filled:before { content: $ti-icon-arrow-badge-up-filled; } +.#{$ti-prefix}-arrow-bar-down:before { content: $ti-icon-arrow-bar-down; } +.#{$ti-prefix}-arrow-bar-left:before { content: $ti-icon-arrow-bar-left; } +.#{$ti-prefix}-arrow-bar-right:before { content: $ti-icon-arrow-bar-right; } +.#{$ti-prefix}-arrow-bar-to-down:before { content: $ti-icon-arrow-bar-to-down; } +.#{$ti-prefix}-arrow-bar-to-left:before { content: $ti-icon-arrow-bar-to-left; } +.#{$ti-prefix}-arrow-bar-to-right:before { content: $ti-icon-arrow-bar-to-right; } +.#{$ti-prefix}-arrow-bar-to-up:before { content: $ti-icon-arrow-bar-to-up; } +.#{$ti-prefix}-arrow-bar-up:before { content: $ti-icon-arrow-bar-up; } +.#{$ti-prefix}-arrow-bear-left:before { content: $ti-icon-arrow-bear-left; } +.#{$ti-prefix}-arrow-bear-left-2:before { content: $ti-icon-arrow-bear-left-2; } +.#{$ti-prefix}-arrow-bear-right:before { content: $ti-icon-arrow-bear-right; } +.#{$ti-prefix}-arrow-bear-right-2:before { content: $ti-icon-arrow-bear-right-2; } +.#{$ti-prefix}-arrow-big-down:before { content: $ti-icon-arrow-big-down; } +.#{$ti-prefix}-arrow-big-down-filled:before { content: $ti-icon-arrow-big-down-filled; } +.#{$ti-prefix}-arrow-big-down-line:before { content: $ti-icon-arrow-big-down-line; } +.#{$ti-prefix}-arrow-big-down-line-filled:before { content: $ti-icon-arrow-big-down-line-filled; } +.#{$ti-prefix}-arrow-big-down-lines:before { content: $ti-icon-arrow-big-down-lines; } +.#{$ti-prefix}-arrow-big-down-lines-filled:before { content: $ti-icon-arrow-big-down-lines-filled; } +.#{$ti-prefix}-arrow-big-left:before { content: $ti-icon-arrow-big-left; } +.#{$ti-prefix}-arrow-big-left-filled:before { content: $ti-icon-arrow-big-left-filled; } +.#{$ti-prefix}-arrow-big-left-line:before { content: $ti-icon-arrow-big-left-line; } +.#{$ti-prefix}-arrow-big-left-line-filled:before { content: $ti-icon-arrow-big-left-line-filled; } +.#{$ti-prefix}-arrow-big-left-lines:before { content: $ti-icon-arrow-big-left-lines; } +.#{$ti-prefix}-arrow-big-left-lines-filled:before { content: $ti-icon-arrow-big-left-lines-filled; } +.#{$ti-prefix}-arrow-big-right:before { content: $ti-icon-arrow-big-right; } +.#{$ti-prefix}-arrow-big-right-filled:before { content: $ti-icon-arrow-big-right-filled; } +.#{$ti-prefix}-arrow-big-right-line:before { content: $ti-icon-arrow-big-right-line; } +.#{$ti-prefix}-arrow-big-right-line-filled:before { content: $ti-icon-arrow-big-right-line-filled; } +.#{$ti-prefix}-arrow-big-right-lines:before { content: $ti-icon-arrow-big-right-lines; } +.#{$ti-prefix}-arrow-big-right-lines-filled:before { content: $ti-icon-arrow-big-right-lines-filled; } +.#{$ti-prefix}-arrow-big-up:before { content: $ti-icon-arrow-big-up; } +.#{$ti-prefix}-arrow-big-up-filled:before { content: $ti-icon-arrow-big-up-filled; } +.#{$ti-prefix}-arrow-big-up-line:before { content: $ti-icon-arrow-big-up-line; } +.#{$ti-prefix}-arrow-big-up-line-filled:before { content: $ti-icon-arrow-big-up-line-filled; } +.#{$ti-prefix}-arrow-big-up-lines:before { content: $ti-icon-arrow-big-up-lines; } +.#{$ti-prefix}-arrow-big-up-lines-filled:before { content: $ti-icon-arrow-big-up-lines-filled; } +.#{$ti-prefix}-arrow-bounce:before { content: $ti-icon-arrow-bounce; } +.#{$ti-prefix}-arrow-curve-left:before { content: $ti-icon-arrow-curve-left; } +.#{$ti-prefix}-arrow-curve-right:before { content: $ti-icon-arrow-curve-right; } +.#{$ti-prefix}-arrow-down:before { content: $ti-icon-arrow-down; } +.#{$ti-prefix}-arrow-down-bar:before { content: $ti-icon-arrow-down-bar; } +.#{$ti-prefix}-arrow-down-circle:before { content: $ti-icon-arrow-down-circle; } +.#{$ti-prefix}-arrow-down-left:before { content: $ti-icon-arrow-down-left; } +.#{$ti-prefix}-arrow-down-left-circle:before { content: $ti-icon-arrow-down-left-circle; } +.#{$ti-prefix}-arrow-down-rhombus:before { content: $ti-icon-arrow-down-rhombus; } +.#{$ti-prefix}-arrow-down-right:before { content: $ti-icon-arrow-down-right; } +.#{$ti-prefix}-arrow-down-right-circle:before { content: $ti-icon-arrow-down-right-circle; } +.#{$ti-prefix}-arrow-down-square:before { content: $ti-icon-arrow-down-square; } +.#{$ti-prefix}-arrow-down-tail:before { content: $ti-icon-arrow-down-tail; } +.#{$ti-prefix}-arrow-elbow-left:before { content: $ti-icon-arrow-elbow-left; } +.#{$ti-prefix}-arrow-elbow-right:before { content: $ti-icon-arrow-elbow-right; } +.#{$ti-prefix}-arrow-fork:before { content: $ti-icon-arrow-fork; } +.#{$ti-prefix}-arrow-forward:before { content: $ti-icon-arrow-forward; } +.#{$ti-prefix}-arrow-forward-up:before { content: $ti-icon-arrow-forward-up; } +.#{$ti-prefix}-arrow-forward-up-double:before { content: $ti-icon-arrow-forward-up-double; } +.#{$ti-prefix}-arrow-guide:before { content: $ti-icon-arrow-guide; } +.#{$ti-prefix}-arrow-iteration:before { content: $ti-icon-arrow-iteration; } +.#{$ti-prefix}-arrow-left:before { content: $ti-icon-arrow-left; } +.#{$ti-prefix}-arrow-left-bar:before { content: $ti-icon-arrow-left-bar; } +.#{$ti-prefix}-arrow-left-circle:before { content: $ti-icon-arrow-left-circle; } +.#{$ti-prefix}-arrow-left-rhombus:before { content: $ti-icon-arrow-left-rhombus; } +.#{$ti-prefix}-arrow-left-right:before { content: $ti-icon-arrow-left-right; } +.#{$ti-prefix}-arrow-left-square:before { content: $ti-icon-arrow-left-square; } +.#{$ti-prefix}-arrow-left-tail:before { content: $ti-icon-arrow-left-tail; } +.#{$ti-prefix}-arrow-loop-left:before { content: $ti-icon-arrow-loop-left; } +.#{$ti-prefix}-arrow-loop-left-2:before { content: $ti-icon-arrow-loop-left-2; } +.#{$ti-prefix}-arrow-loop-right:before { content: $ti-icon-arrow-loop-right; } +.#{$ti-prefix}-arrow-loop-right-2:before { content: $ti-icon-arrow-loop-right-2; } +.#{$ti-prefix}-arrow-merge:before { content: $ti-icon-arrow-merge; } +.#{$ti-prefix}-arrow-merge-both:before { content: $ti-icon-arrow-merge-both; } +.#{$ti-prefix}-arrow-merge-left:before { content: $ti-icon-arrow-merge-left; } +.#{$ti-prefix}-arrow-merge-right:before { content: $ti-icon-arrow-merge-right; } +.#{$ti-prefix}-arrow-move-down:before { content: $ti-icon-arrow-move-down; } +.#{$ti-prefix}-arrow-move-left:before { content: $ti-icon-arrow-move-left; } +.#{$ti-prefix}-arrow-move-right:before { content: $ti-icon-arrow-move-right; } +.#{$ti-prefix}-arrow-move-up:before { content: $ti-icon-arrow-move-up; } +.#{$ti-prefix}-arrow-narrow-down:before { content: $ti-icon-arrow-narrow-down; } +.#{$ti-prefix}-arrow-narrow-left:before { content: $ti-icon-arrow-narrow-left; } +.#{$ti-prefix}-arrow-narrow-right:before { content: $ti-icon-arrow-narrow-right; } +.#{$ti-prefix}-arrow-narrow-up:before { content: $ti-icon-arrow-narrow-up; } +.#{$ti-prefix}-arrow-ramp-left:before { content: $ti-icon-arrow-ramp-left; } +.#{$ti-prefix}-arrow-ramp-left-2:before { content: $ti-icon-arrow-ramp-left-2; } +.#{$ti-prefix}-arrow-ramp-left-3:before { content: $ti-icon-arrow-ramp-left-3; } +.#{$ti-prefix}-arrow-ramp-right:before { content: $ti-icon-arrow-ramp-right; } +.#{$ti-prefix}-arrow-ramp-right-2:before { content: $ti-icon-arrow-ramp-right-2; } +.#{$ti-prefix}-arrow-ramp-right-3:before { content: $ti-icon-arrow-ramp-right-3; } +.#{$ti-prefix}-arrow-right:before { content: $ti-icon-arrow-right; } +.#{$ti-prefix}-arrow-right-bar:before { content: $ti-icon-arrow-right-bar; } +.#{$ti-prefix}-arrow-right-circle:before { content: $ti-icon-arrow-right-circle; } +.#{$ti-prefix}-arrow-right-rhombus:before { content: $ti-icon-arrow-right-rhombus; } +.#{$ti-prefix}-arrow-right-square:before { content: $ti-icon-arrow-right-square; } +.#{$ti-prefix}-arrow-right-tail:before { content: $ti-icon-arrow-right-tail; } +.#{$ti-prefix}-arrow-rotary-first-left:before { content: $ti-icon-arrow-rotary-first-left; } +.#{$ti-prefix}-arrow-rotary-first-right:before { content: $ti-icon-arrow-rotary-first-right; } +.#{$ti-prefix}-arrow-rotary-last-left:before { content: $ti-icon-arrow-rotary-last-left; } +.#{$ti-prefix}-arrow-rotary-last-right:before { content: $ti-icon-arrow-rotary-last-right; } +.#{$ti-prefix}-arrow-rotary-left:before { content: $ti-icon-arrow-rotary-left; } +.#{$ti-prefix}-arrow-rotary-right:before { content: $ti-icon-arrow-rotary-right; } +.#{$ti-prefix}-arrow-rotary-straight:before { content: $ti-icon-arrow-rotary-straight; } +.#{$ti-prefix}-arrow-roundabout-left:before { content: $ti-icon-arrow-roundabout-left; } +.#{$ti-prefix}-arrow-roundabout-right:before { content: $ti-icon-arrow-roundabout-right; } +.#{$ti-prefix}-arrow-sharp-turn-left:before { content: $ti-icon-arrow-sharp-turn-left; } +.#{$ti-prefix}-arrow-sharp-turn-right:before { content: $ti-icon-arrow-sharp-turn-right; } +.#{$ti-prefix}-arrow-up:before { content: $ti-icon-arrow-up; } +.#{$ti-prefix}-arrow-up-bar:before { content: $ti-icon-arrow-up-bar; } +.#{$ti-prefix}-arrow-up-circle:before { content: $ti-icon-arrow-up-circle; } +.#{$ti-prefix}-arrow-up-left:before { content: $ti-icon-arrow-up-left; } +.#{$ti-prefix}-arrow-up-left-circle:before { content: $ti-icon-arrow-up-left-circle; } +.#{$ti-prefix}-arrow-up-rhombus:before { content: $ti-icon-arrow-up-rhombus; } +.#{$ti-prefix}-arrow-up-right:before { content: $ti-icon-arrow-up-right; } +.#{$ti-prefix}-arrow-up-right-circle:before { content: $ti-icon-arrow-up-right-circle; } +.#{$ti-prefix}-arrow-up-square:before { content: $ti-icon-arrow-up-square; } +.#{$ti-prefix}-arrow-up-tail:before { content: $ti-icon-arrow-up-tail; } +.#{$ti-prefix}-arrow-wave-left-down:before { content: $ti-icon-arrow-wave-left-down; } +.#{$ti-prefix}-arrow-wave-left-up:before { content: $ti-icon-arrow-wave-left-up; } +.#{$ti-prefix}-arrow-wave-right-down:before { content: $ti-icon-arrow-wave-right-down; } +.#{$ti-prefix}-arrow-wave-right-up:before { content: $ti-icon-arrow-wave-right-up; } +.#{$ti-prefix}-arrow-zig-zag:before { content: $ti-icon-arrow-zig-zag; } +.#{$ti-prefix}-arrows-cross:before { content: $ti-icon-arrows-cross; } +.#{$ti-prefix}-arrows-diagonal:before { content: $ti-icon-arrows-diagonal; } +.#{$ti-prefix}-arrows-diagonal-2:before { content: $ti-icon-arrows-diagonal-2; } +.#{$ti-prefix}-arrows-diagonal-minimize:before { content: $ti-icon-arrows-diagonal-minimize; } +.#{$ti-prefix}-arrows-diagonal-minimize-2:before { content: $ti-icon-arrows-diagonal-minimize-2; } +.#{$ti-prefix}-arrows-diff:before { content: $ti-icon-arrows-diff; } +.#{$ti-prefix}-arrows-double-ne-sw:before { content: $ti-icon-arrows-double-ne-sw; } +.#{$ti-prefix}-arrows-double-nw-se:before { content: $ti-icon-arrows-double-nw-se; } +.#{$ti-prefix}-arrows-double-se-nw:before { content: $ti-icon-arrows-double-se-nw; } +.#{$ti-prefix}-arrows-double-sw-ne:before { content: $ti-icon-arrows-double-sw-ne; } +.#{$ti-prefix}-arrows-down:before { content: $ti-icon-arrows-down; } +.#{$ti-prefix}-arrows-down-up:before { content: $ti-icon-arrows-down-up; } +.#{$ti-prefix}-arrows-exchange:before { content: $ti-icon-arrows-exchange; } +.#{$ti-prefix}-arrows-exchange-2:before { content: $ti-icon-arrows-exchange-2; } +.#{$ti-prefix}-arrows-horizontal:before { content: $ti-icon-arrows-horizontal; } +.#{$ti-prefix}-arrows-join:before { content: $ti-icon-arrows-join; } +.#{$ti-prefix}-arrows-join-2:before { content: $ti-icon-arrows-join-2; } +.#{$ti-prefix}-arrows-left:before { content: $ti-icon-arrows-left; } +.#{$ti-prefix}-arrows-left-down:before { content: $ti-icon-arrows-left-down; } +.#{$ti-prefix}-arrows-left-right:before { content: $ti-icon-arrows-left-right; } +.#{$ti-prefix}-arrows-maximize:before { content: $ti-icon-arrows-maximize; } +.#{$ti-prefix}-arrows-minimize:before { content: $ti-icon-arrows-minimize; } +.#{$ti-prefix}-arrows-move:before { content: $ti-icon-arrows-move; } +.#{$ti-prefix}-arrows-move-horizontal:before { content: $ti-icon-arrows-move-horizontal; } +.#{$ti-prefix}-arrows-move-vertical:before { content: $ti-icon-arrows-move-vertical; } +.#{$ti-prefix}-arrows-random:before { content: $ti-icon-arrows-random; } +.#{$ti-prefix}-arrows-right:before { content: $ti-icon-arrows-right; } +.#{$ti-prefix}-arrows-right-down:before { content: $ti-icon-arrows-right-down; } +.#{$ti-prefix}-arrows-right-left:before { content: $ti-icon-arrows-right-left; } +.#{$ti-prefix}-arrows-shuffle:before { content: $ti-icon-arrows-shuffle; } +.#{$ti-prefix}-arrows-shuffle-2:before { content: $ti-icon-arrows-shuffle-2; } +.#{$ti-prefix}-arrows-sort:before { content: $ti-icon-arrows-sort; } +.#{$ti-prefix}-arrows-split:before { content: $ti-icon-arrows-split; } +.#{$ti-prefix}-arrows-split-2:before { content: $ti-icon-arrows-split-2; } +.#{$ti-prefix}-arrows-transfer-down:before { content: $ti-icon-arrows-transfer-down; } +.#{$ti-prefix}-arrows-transfer-up:before { content: $ti-icon-arrows-transfer-up; } +.#{$ti-prefix}-arrows-up:before { content: $ti-icon-arrows-up; } +.#{$ti-prefix}-arrows-up-down:before { content: $ti-icon-arrows-up-down; } +.#{$ti-prefix}-arrows-up-left:before { content: $ti-icon-arrows-up-left; } +.#{$ti-prefix}-arrows-up-right:before { content: $ti-icon-arrows-up-right; } +.#{$ti-prefix}-arrows-vertical:before { content: $ti-icon-arrows-vertical; } +.#{$ti-prefix}-artboard:before { content: $ti-icon-artboard; } +.#{$ti-prefix}-artboard-off:before { content: $ti-icon-artboard-off; } +.#{$ti-prefix}-article:before { content: $ti-icon-article; } +.#{$ti-prefix}-article-filled-filled:before { content: $ti-icon-article-filled-filled; } +.#{$ti-prefix}-article-off:before { content: $ti-icon-article-off; } +.#{$ti-prefix}-aspect-ratio:before { content: $ti-icon-aspect-ratio; } +.#{$ti-prefix}-aspect-ratio-filled:before { content: $ti-icon-aspect-ratio-filled; } +.#{$ti-prefix}-aspect-ratio-off:before { content: $ti-icon-aspect-ratio-off; } +.#{$ti-prefix}-assembly:before { content: $ti-icon-assembly; } +.#{$ti-prefix}-assembly-off:before { content: $ti-icon-assembly-off; } +.#{$ti-prefix}-asset:before { content: $ti-icon-asset; } +.#{$ti-prefix}-asterisk:before { content: $ti-icon-asterisk; } +.#{$ti-prefix}-asterisk-simple:before { content: $ti-icon-asterisk-simple; } +.#{$ti-prefix}-at:before { content: $ti-icon-at; } +.#{$ti-prefix}-at-off:before { content: $ti-icon-at-off; } +.#{$ti-prefix}-atom:before { content: $ti-icon-atom; } +.#{$ti-prefix}-atom-2:before { content: $ti-icon-atom-2; } +.#{$ti-prefix}-atom-2-filled:before { content: $ti-icon-atom-2-filled; } +.#{$ti-prefix}-atom-off:before { content: $ti-icon-atom-off; } +.#{$ti-prefix}-augmented-reality:before { content: $ti-icon-augmented-reality; } +.#{$ti-prefix}-augmented-reality-2:before { content: $ti-icon-augmented-reality-2; } +.#{$ti-prefix}-augmented-reality-off:before { content: $ti-icon-augmented-reality-off; } +.#{$ti-prefix}-award:before { content: $ti-icon-award; } +.#{$ti-prefix}-award-filled:before { content: $ti-icon-award-filled; } +.#{$ti-prefix}-award-off:before { content: $ti-icon-award-off; } +.#{$ti-prefix}-axe:before { content: $ti-icon-axe; } +.#{$ti-prefix}-axis-x:before { content: $ti-icon-axis-x; } +.#{$ti-prefix}-axis-y:before { content: $ti-icon-axis-y; } +.#{$ti-prefix}-baby-bottle:before { content: $ti-icon-baby-bottle; } +.#{$ti-prefix}-baby-carriage:before { content: $ti-icon-baby-carriage; } +.#{$ti-prefix}-backhoe:before { content: $ti-icon-backhoe; } +.#{$ti-prefix}-backpack:before { content: $ti-icon-backpack; } +.#{$ti-prefix}-backpack-off:before { content: $ti-icon-backpack-off; } +.#{$ti-prefix}-backspace:before { content: $ti-icon-backspace; } +.#{$ti-prefix}-backspace-filled:before { content: $ti-icon-backspace-filled; } +.#{$ti-prefix}-badge:before { content: $ti-icon-badge; } +.#{$ti-prefix}-badge-3d:before { content: $ti-icon-badge-3d; } +.#{$ti-prefix}-badge-4k:before { content: $ti-icon-badge-4k; } +.#{$ti-prefix}-badge-8k:before { content: $ti-icon-badge-8k; } +.#{$ti-prefix}-badge-ad:before { content: $ti-icon-badge-ad; } +.#{$ti-prefix}-badge-ar:before { content: $ti-icon-badge-ar; } +.#{$ti-prefix}-badge-cc:before { content: $ti-icon-badge-cc; } +.#{$ti-prefix}-badge-filled:before { content: $ti-icon-badge-filled; } +.#{$ti-prefix}-badge-hd:before { content: $ti-icon-badge-hd; } +.#{$ti-prefix}-badge-off:before { content: $ti-icon-badge-off; } +.#{$ti-prefix}-badge-sd:before { content: $ti-icon-badge-sd; } +.#{$ti-prefix}-badge-tm:before { content: $ti-icon-badge-tm; } +.#{$ti-prefix}-badge-vo:before { content: $ti-icon-badge-vo; } +.#{$ti-prefix}-badge-vr:before { content: $ti-icon-badge-vr; } +.#{$ti-prefix}-badge-wc:before { content: $ti-icon-badge-wc; } +.#{$ti-prefix}-badges:before { content: $ti-icon-badges; } +.#{$ti-prefix}-badges-filled:before { content: $ti-icon-badges-filled; } +.#{$ti-prefix}-badges-off:before { content: $ti-icon-badges-off; } +.#{$ti-prefix}-baguette:before { content: $ti-icon-baguette; } +.#{$ti-prefix}-ball-american-football:before { content: $ti-icon-ball-american-football; } +.#{$ti-prefix}-ball-american-football-off:before { content: $ti-icon-ball-american-football-off; } +.#{$ti-prefix}-ball-baseball:before { content: $ti-icon-ball-baseball; } +.#{$ti-prefix}-ball-basketball:before { content: $ti-icon-ball-basketball; } +.#{$ti-prefix}-ball-bowling:before { content: $ti-icon-ball-bowling; } +.#{$ti-prefix}-ball-football:before { content: $ti-icon-ball-football; } +.#{$ti-prefix}-ball-football-off:before { content: $ti-icon-ball-football-off; } +.#{$ti-prefix}-ball-tennis:before { content: $ti-icon-ball-tennis; } +.#{$ti-prefix}-ball-volleyball:before { content: $ti-icon-ball-volleyball; } +.#{$ti-prefix}-balloon:before { content: $ti-icon-balloon; } +.#{$ti-prefix}-balloon-off:before { content: $ti-icon-balloon-off; } +.#{$ti-prefix}-ballpen:before { content: $ti-icon-ballpen; } +.#{$ti-prefix}-ballpen-off:before { content: $ti-icon-ballpen-off; } +.#{$ti-prefix}-ban:before { content: $ti-icon-ban; } +.#{$ti-prefix}-bandage:before { content: $ti-icon-bandage; } +.#{$ti-prefix}-bandage-filled:before { content: $ti-icon-bandage-filled; } +.#{$ti-prefix}-bandage-off:before { content: $ti-icon-bandage-off; } +.#{$ti-prefix}-barbell:before { content: $ti-icon-barbell; } +.#{$ti-prefix}-barbell-off:before { content: $ti-icon-barbell-off; } +.#{$ti-prefix}-barcode:before { content: $ti-icon-barcode; } +.#{$ti-prefix}-barcode-off:before { content: $ti-icon-barcode-off; } +.#{$ti-prefix}-barrel:before { content: $ti-icon-barrel; } +.#{$ti-prefix}-barrel-off:before { content: $ti-icon-barrel-off; } +.#{$ti-prefix}-barrier-block:before { content: $ti-icon-barrier-block; } +.#{$ti-prefix}-barrier-block-off:before { content: $ti-icon-barrier-block-off; } +.#{$ti-prefix}-baseline:before { content: $ti-icon-baseline; } +.#{$ti-prefix}-baseline-density-large:before { content: $ti-icon-baseline-density-large; } +.#{$ti-prefix}-baseline-density-medium:before { content: $ti-icon-baseline-density-medium; } +.#{$ti-prefix}-baseline-density-small:before { content: $ti-icon-baseline-density-small; } +.#{$ti-prefix}-basket:before { content: $ti-icon-basket; } +.#{$ti-prefix}-basket-filled:before { content: $ti-icon-basket-filled; } +.#{$ti-prefix}-basket-off:before { content: $ti-icon-basket-off; } +.#{$ti-prefix}-bat:before { content: $ti-icon-bat; } +.#{$ti-prefix}-bath:before { content: $ti-icon-bath; } +.#{$ti-prefix}-bath-filled:before { content: $ti-icon-bath-filled; } +.#{$ti-prefix}-bath-off:before { content: $ti-icon-bath-off; } +.#{$ti-prefix}-battery:before { content: $ti-icon-battery; } +.#{$ti-prefix}-battery-1:before { content: $ti-icon-battery-1; } +.#{$ti-prefix}-battery-1-filled:before { content: $ti-icon-battery-1-filled; } +.#{$ti-prefix}-battery-2:before { content: $ti-icon-battery-2; } +.#{$ti-prefix}-battery-2-filled:before { content: $ti-icon-battery-2-filled; } +.#{$ti-prefix}-battery-3:before { content: $ti-icon-battery-3; } +.#{$ti-prefix}-battery-3-filled:before { content: $ti-icon-battery-3-filled; } +.#{$ti-prefix}-battery-4:before { content: $ti-icon-battery-4; } +.#{$ti-prefix}-battery-4-filled:before { content: $ti-icon-battery-4-filled; } +.#{$ti-prefix}-battery-automotive:before { content: $ti-icon-battery-automotive; } +.#{$ti-prefix}-battery-charging:before { content: $ti-icon-battery-charging; } +.#{$ti-prefix}-battery-charging-2:before { content: $ti-icon-battery-charging-2; } +.#{$ti-prefix}-battery-eco:before { content: $ti-icon-battery-eco; } +.#{$ti-prefix}-battery-filled:before { content: $ti-icon-battery-filled; } +.#{$ti-prefix}-battery-off:before { content: $ti-icon-battery-off; } +.#{$ti-prefix}-beach:before { content: $ti-icon-beach; } +.#{$ti-prefix}-beach-off:before { content: $ti-icon-beach-off; } +.#{$ti-prefix}-bed:before { content: $ti-icon-bed; } +.#{$ti-prefix}-bed-filled:before { content: $ti-icon-bed-filled; } +.#{$ti-prefix}-bed-off:before { content: $ti-icon-bed-off; } +.#{$ti-prefix}-beer:before { content: $ti-icon-beer; } +.#{$ti-prefix}-beer-filled:before { content: $ti-icon-beer-filled; } +.#{$ti-prefix}-beer-off:before { content: $ti-icon-beer-off; } +.#{$ti-prefix}-bell:before { content: $ti-icon-bell; } +.#{$ti-prefix}-bell-bolt:before { content: $ti-icon-bell-bolt; } +.#{$ti-prefix}-bell-cancel:before { content: $ti-icon-bell-cancel; } +.#{$ti-prefix}-bell-check:before { content: $ti-icon-bell-check; } +.#{$ti-prefix}-bell-code:before { content: $ti-icon-bell-code; } +.#{$ti-prefix}-bell-cog:before { content: $ti-icon-bell-cog; } +.#{$ti-prefix}-bell-dollar:before { content: $ti-icon-bell-dollar; } +.#{$ti-prefix}-bell-down:before { content: $ti-icon-bell-down; } +.#{$ti-prefix}-bell-exclamation:before { content: $ti-icon-bell-exclamation; } +.#{$ti-prefix}-bell-filled:before { content: $ti-icon-bell-filled; } +.#{$ti-prefix}-bell-heart:before { content: $ti-icon-bell-heart; } +.#{$ti-prefix}-bell-minus:before { content: $ti-icon-bell-minus; } +.#{$ti-prefix}-bell-minus-filled:before { content: $ti-icon-bell-minus-filled; } +.#{$ti-prefix}-bell-off:before { content: $ti-icon-bell-off; } +.#{$ti-prefix}-bell-pause:before { content: $ti-icon-bell-pause; } +.#{$ti-prefix}-bell-pin:before { content: $ti-icon-bell-pin; } +.#{$ti-prefix}-bell-plus:before { content: $ti-icon-bell-plus; } +.#{$ti-prefix}-bell-plus-filled:before { content: $ti-icon-bell-plus-filled; } +.#{$ti-prefix}-bell-question:before { content: $ti-icon-bell-question; } +.#{$ti-prefix}-bell-ringing:before { content: $ti-icon-bell-ringing; } +.#{$ti-prefix}-bell-ringing-2:before { content: $ti-icon-bell-ringing-2; } +.#{$ti-prefix}-bell-ringing-2-filled:before { content: $ti-icon-bell-ringing-2-filled; } +.#{$ti-prefix}-bell-ringing-filled:before { content: $ti-icon-bell-ringing-filled; } +.#{$ti-prefix}-bell-school:before { content: $ti-icon-bell-school; } +.#{$ti-prefix}-bell-search:before { content: $ti-icon-bell-search; } +.#{$ti-prefix}-bell-share:before { content: $ti-icon-bell-share; } +.#{$ti-prefix}-bell-star:before { content: $ti-icon-bell-star; } +.#{$ti-prefix}-bell-up:before { content: $ti-icon-bell-up; } +.#{$ti-prefix}-bell-x:before { content: $ti-icon-bell-x; } +.#{$ti-prefix}-bell-x-filled:before { content: $ti-icon-bell-x-filled; } +.#{$ti-prefix}-bell-z:before { content: $ti-icon-bell-z; } +.#{$ti-prefix}-bell-z-filled:before { content: $ti-icon-bell-z-filled; } +.#{$ti-prefix}-beta:before { content: $ti-icon-beta; } +.#{$ti-prefix}-bible:before { content: $ti-icon-bible; } +.#{$ti-prefix}-bike:before { content: $ti-icon-bike; } +.#{$ti-prefix}-bike-off:before { content: $ti-icon-bike-off; } +.#{$ti-prefix}-binary:before { content: $ti-icon-binary; } +.#{$ti-prefix}-binary-off:before { content: $ti-icon-binary-off; } +.#{$ti-prefix}-binary-tree:before { content: $ti-icon-binary-tree; } +.#{$ti-prefix}-binary-tree-2:before { content: $ti-icon-binary-tree-2; } +.#{$ti-prefix}-biohazard:before { content: $ti-icon-biohazard; } +.#{$ti-prefix}-biohazard-off:before { content: $ti-icon-biohazard-off; } +.#{$ti-prefix}-blade:before { content: $ti-icon-blade; } +.#{$ti-prefix}-blade-filled:before { content: $ti-icon-blade-filled; } +.#{$ti-prefix}-bleach:before { content: $ti-icon-bleach; } +.#{$ti-prefix}-bleach-chlorine:before { content: $ti-icon-bleach-chlorine; } +.#{$ti-prefix}-bleach-no-chlorine:before { content: $ti-icon-bleach-no-chlorine; } +.#{$ti-prefix}-bleach-off:before { content: $ti-icon-bleach-off; } +.#{$ti-prefix}-blockquote:before { content: $ti-icon-blockquote; } +.#{$ti-prefix}-bluetooth:before { content: $ti-icon-bluetooth; } +.#{$ti-prefix}-bluetooth-connected:before { content: $ti-icon-bluetooth-connected; } +.#{$ti-prefix}-bluetooth-off:before { content: $ti-icon-bluetooth-off; } +.#{$ti-prefix}-bluetooth-x:before { content: $ti-icon-bluetooth-x; } +.#{$ti-prefix}-blur:before { content: $ti-icon-blur; } +.#{$ti-prefix}-blur-off:before { content: $ti-icon-blur-off; } +.#{$ti-prefix}-bmp:before { content: $ti-icon-bmp; } +.#{$ti-prefix}-bold:before { content: $ti-icon-bold; } +.#{$ti-prefix}-bold-off:before { content: $ti-icon-bold-off; } +.#{$ti-prefix}-bolt:before { content: $ti-icon-bolt; } +.#{$ti-prefix}-bolt-off:before { content: $ti-icon-bolt-off; } +.#{$ti-prefix}-bomb:before { content: $ti-icon-bomb; } +.#{$ti-prefix}-bone:before { content: $ti-icon-bone; } +.#{$ti-prefix}-bone-off:before { content: $ti-icon-bone-off; } +.#{$ti-prefix}-bong:before { content: $ti-icon-bong; } +.#{$ti-prefix}-bong-off:before { content: $ti-icon-bong-off; } +.#{$ti-prefix}-book:before { content: $ti-icon-book; } +.#{$ti-prefix}-book-2:before { content: $ti-icon-book-2; } +.#{$ti-prefix}-book-download:before { content: $ti-icon-book-download; } +.#{$ti-prefix}-book-off:before { content: $ti-icon-book-off; } +.#{$ti-prefix}-book-upload:before { content: $ti-icon-book-upload; } +.#{$ti-prefix}-bookmark:before { content: $ti-icon-bookmark; } +.#{$ti-prefix}-bookmark-off:before { content: $ti-icon-bookmark-off; } +.#{$ti-prefix}-bookmarks:before { content: $ti-icon-bookmarks; } +.#{$ti-prefix}-bookmarks-off:before { content: $ti-icon-bookmarks-off; } +.#{$ti-prefix}-books:before { content: $ti-icon-books; } +.#{$ti-prefix}-books-off:before { content: $ti-icon-books-off; } +.#{$ti-prefix}-border-all:before { content: $ti-icon-border-all; } +.#{$ti-prefix}-border-bottom:before { content: $ti-icon-border-bottom; } +.#{$ti-prefix}-border-corners:before { content: $ti-icon-border-corners; } +.#{$ti-prefix}-border-horizontal:before { content: $ti-icon-border-horizontal; } +.#{$ti-prefix}-border-inner:before { content: $ti-icon-border-inner; } +.#{$ti-prefix}-border-left:before { content: $ti-icon-border-left; } +.#{$ti-prefix}-border-none:before { content: $ti-icon-border-none; } +.#{$ti-prefix}-border-outer:before { content: $ti-icon-border-outer; } +.#{$ti-prefix}-border-radius:before { content: $ti-icon-border-radius; } +.#{$ti-prefix}-border-right:before { content: $ti-icon-border-right; } +.#{$ti-prefix}-border-sides:before { content: $ti-icon-border-sides; } +.#{$ti-prefix}-border-style:before { content: $ti-icon-border-style; } +.#{$ti-prefix}-border-style-2:before { content: $ti-icon-border-style-2; } +.#{$ti-prefix}-border-top:before { content: $ti-icon-border-top; } +.#{$ti-prefix}-border-vertical:before { content: $ti-icon-border-vertical; } +.#{$ti-prefix}-bottle:before { content: $ti-icon-bottle; } +.#{$ti-prefix}-bottle-off:before { content: $ti-icon-bottle-off; } +.#{$ti-prefix}-bounce-left:before { content: $ti-icon-bounce-left; } +.#{$ti-prefix}-bounce-right:before { content: $ti-icon-bounce-right; } +.#{$ti-prefix}-bow:before { content: $ti-icon-bow; } +.#{$ti-prefix}-bowl:before { content: $ti-icon-bowl; } +.#{$ti-prefix}-box:before { content: $ti-icon-box; } +.#{$ti-prefix}-box-align-bottom:before { content: $ti-icon-box-align-bottom; } +.#{$ti-prefix}-box-align-bottom-left:before { content: $ti-icon-box-align-bottom-left; } +.#{$ti-prefix}-box-align-bottom-right:before { content: $ti-icon-box-align-bottom-right; } +.#{$ti-prefix}-box-align-left:before { content: $ti-icon-box-align-left; } +.#{$ti-prefix}-box-align-right:before { content: $ti-icon-box-align-right; } +.#{$ti-prefix}-box-align-top:before { content: $ti-icon-box-align-top; } +.#{$ti-prefix}-box-align-top-left:before { content: $ti-icon-box-align-top-left; } +.#{$ti-prefix}-box-align-top-right:before { content: $ti-icon-box-align-top-right; } +.#{$ti-prefix}-box-margin:before { content: $ti-icon-box-margin; } +.#{$ti-prefix}-box-model:before { content: $ti-icon-box-model; } +.#{$ti-prefix}-box-model-2:before { content: $ti-icon-box-model-2; } +.#{$ti-prefix}-box-model-2-off:before { content: $ti-icon-box-model-2-off; } +.#{$ti-prefix}-box-model-off:before { content: $ti-icon-box-model-off; } +.#{$ti-prefix}-box-multiple:before { content: $ti-icon-box-multiple; } +.#{$ti-prefix}-box-multiple-0:before { content: $ti-icon-box-multiple-0; } +.#{$ti-prefix}-box-multiple-1:before { content: $ti-icon-box-multiple-1; } +.#{$ti-prefix}-box-multiple-2:before { content: $ti-icon-box-multiple-2; } +.#{$ti-prefix}-box-multiple-3:before { content: $ti-icon-box-multiple-3; } +.#{$ti-prefix}-box-multiple-4:before { content: $ti-icon-box-multiple-4; } +.#{$ti-prefix}-box-multiple-5:before { content: $ti-icon-box-multiple-5; } +.#{$ti-prefix}-box-multiple-6:before { content: $ti-icon-box-multiple-6; } +.#{$ti-prefix}-box-multiple-7:before { content: $ti-icon-box-multiple-7; } +.#{$ti-prefix}-box-multiple-8:before { content: $ti-icon-box-multiple-8; } +.#{$ti-prefix}-box-multiple-9:before { content: $ti-icon-box-multiple-9; } +.#{$ti-prefix}-box-off:before { content: $ti-icon-box-off; } +.#{$ti-prefix}-box-padding:before { content: $ti-icon-box-padding; } +.#{$ti-prefix}-box-seam:before { content: $ti-icon-box-seam; } +.#{$ti-prefix}-braces:before { content: $ti-icon-braces; } +.#{$ti-prefix}-braces-off:before { content: $ti-icon-braces-off; } +.#{$ti-prefix}-brackets:before { content: $ti-icon-brackets; } +.#{$ti-prefix}-brackets-contain:before { content: $ti-icon-brackets-contain; } +.#{$ti-prefix}-brackets-contain-end:before { content: $ti-icon-brackets-contain-end; } +.#{$ti-prefix}-brackets-contain-start:before { content: $ti-icon-brackets-contain-start; } +.#{$ti-prefix}-brackets-off:before { content: $ti-icon-brackets-off; } +.#{$ti-prefix}-braille:before { content: $ti-icon-braille; } +.#{$ti-prefix}-brain:before { content: $ti-icon-brain; } +.#{$ti-prefix}-brand-4chan:before { content: $ti-icon-brand-4chan; } +.#{$ti-prefix}-brand-abstract:before { content: $ti-icon-brand-abstract; } +.#{$ti-prefix}-brand-adobe:before { content: $ti-icon-brand-adobe; } +.#{$ti-prefix}-brand-adonis-js:before { content: $ti-icon-brand-adonis-js; } +.#{$ti-prefix}-brand-airbnb:before { content: $ti-icon-brand-airbnb; } +.#{$ti-prefix}-brand-airtable:before { content: $ti-icon-brand-airtable; } +.#{$ti-prefix}-brand-algolia:before { content: $ti-icon-brand-algolia; } +.#{$ti-prefix}-brand-alipay:before { content: $ti-icon-brand-alipay; } +.#{$ti-prefix}-brand-alpine-js:before { content: $ti-icon-brand-alpine-js; } +.#{$ti-prefix}-brand-amazon:before { content: $ti-icon-brand-amazon; } +.#{$ti-prefix}-brand-amd:before { content: $ti-icon-brand-amd; } +.#{$ti-prefix}-brand-amigo:before { content: $ti-icon-brand-amigo; } +.#{$ti-prefix}-brand-among-us:before { content: $ti-icon-brand-among-us; } +.#{$ti-prefix}-brand-android:before { content: $ti-icon-brand-android; } +.#{$ti-prefix}-brand-angular:before { content: $ti-icon-brand-angular; } +.#{$ti-prefix}-brand-ao3:before { content: $ti-icon-brand-ao3; } +.#{$ti-prefix}-brand-appgallery:before { content: $ti-icon-brand-appgallery; } +.#{$ti-prefix}-brand-apple:before { content: $ti-icon-brand-apple; } +.#{$ti-prefix}-brand-apple-arcade:before { content: $ti-icon-brand-apple-arcade; } +.#{$ti-prefix}-brand-apple-podcast:before { content: $ti-icon-brand-apple-podcast; } +.#{$ti-prefix}-brand-appstore:before { content: $ti-icon-brand-appstore; } +.#{$ti-prefix}-brand-asana:before { content: $ti-icon-brand-asana; } +.#{$ti-prefix}-brand-backbone:before { content: $ti-icon-brand-backbone; } +.#{$ti-prefix}-brand-badoo:before { content: $ti-icon-brand-badoo; } +.#{$ti-prefix}-brand-baidu:before { content: $ti-icon-brand-baidu; } +.#{$ti-prefix}-brand-bandcamp:before { content: $ti-icon-brand-bandcamp; } +.#{$ti-prefix}-brand-bandlab:before { content: $ti-icon-brand-bandlab; } +.#{$ti-prefix}-brand-beats:before { content: $ti-icon-brand-beats; } +.#{$ti-prefix}-brand-behance:before { content: $ti-icon-brand-behance; } +.#{$ti-prefix}-brand-bilibili:before { content: $ti-icon-brand-bilibili; } +.#{$ti-prefix}-brand-binance:before { content: $ti-icon-brand-binance; } +.#{$ti-prefix}-brand-bing:before { content: $ti-icon-brand-bing; } +.#{$ti-prefix}-brand-bitbucket:before { content: $ti-icon-brand-bitbucket; } +.#{$ti-prefix}-brand-blackberry:before { content: $ti-icon-brand-blackberry; } +.#{$ti-prefix}-brand-blender:before { content: $ti-icon-brand-blender; } +.#{$ti-prefix}-brand-blogger:before { content: $ti-icon-brand-blogger; } +.#{$ti-prefix}-brand-booking:before { content: $ti-icon-brand-booking; } +.#{$ti-prefix}-brand-bootstrap:before { content: $ti-icon-brand-bootstrap; } +.#{$ti-prefix}-brand-bulma:before { content: $ti-icon-brand-bulma; } +.#{$ti-prefix}-brand-bumble:before { content: $ti-icon-brand-bumble; } +.#{$ti-prefix}-brand-bunpo:before { content: $ti-icon-brand-bunpo; } +.#{$ti-prefix}-brand-c-sharp:before { content: $ti-icon-brand-c-sharp; } +.#{$ti-prefix}-brand-cake:before { content: $ti-icon-brand-cake; } +.#{$ti-prefix}-brand-cakephp:before { content: $ti-icon-brand-cakephp; } +.#{$ti-prefix}-brand-campaignmonitor:before { content: $ti-icon-brand-campaignmonitor; } +.#{$ti-prefix}-brand-carbon:before { content: $ti-icon-brand-carbon; } +.#{$ti-prefix}-brand-cashapp:before { content: $ti-icon-brand-cashapp; } +.#{$ti-prefix}-brand-chrome:before { content: $ti-icon-brand-chrome; } +.#{$ti-prefix}-brand-citymapper:before { content: $ti-icon-brand-citymapper; } +.#{$ti-prefix}-brand-codecov:before { content: $ti-icon-brand-codecov; } +.#{$ti-prefix}-brand-codepen:before { content: $ti-icon-brand-codepen; } +.#{$ti-prefix}-brand-codesandbox:before { content: $ti-icon-brand-codesandbox; } +.#{$ti-prefix}-brand-cohost:before { content: $ti-icon-brand-cohost; } +.#{$ti-prefix}-brand-coinbase:before { content: $ti-icon-brand-coinbase; } +.#{$ti-prefix}-brand-comedy-central:before { content: $ti-icon-brand-comedy-central; } +.#{$ti-prefix}-brand-coreos:before { content: $ti-icon-brand-coreos; } +.#{$ti-prefix}-brand-couchdb:before { content: $ti-icon-brand-couchdb; } +.#{$ti-prefix}-brand-couchsurfing:before { content: $ti-icon-brand-couchsurfing; } +.#{$ti-prefix}-brand-cpp:before { content: $ti-icon-brand-cpp; } +.#{$ti-prefix}-brand-crunchbase:before { content: $ti-icon-brand-crunchbase; } +.#{$ti-prefix}-brand-css3:before { content: $ti-icon-brand-css3; } +.#{$ti-prefix}-brand-ctemplar:before { content: $ti-icon-brand-ctemplar; } +.#{$ti-prefix}-brand-cucumber:before { content: $ti-icon-brand-cucumber; } +.#{$ti-prefix}-brand-cupra:before { content: $ti-icon-brand-cupra; } +.#{$ti-prefix}-brand-cypress:before { content: $ti-icon-brand-cypress; } +.#{$ti-prefix}-brand-d3:before { content: $ti-icon-brand-d3; } +.#{$ti-prefix}-brand-days-counter:before { content: $ti-icon-brand-days-counter; } +.#{$ti-prefix}-brand-dcos:before { content: $ti-icon-brand-dcos; } +.#{$ti-prefix}-brand-debian:before { content: $ti-icon-brand-debian; } +.#{$ti-prefix}-brand-deezer:before { content: $ti-icon-brand-deezer; } +.#{$ti-prefix}-brand-deliveroo:before { content: $ti-icon-brand-deliveroo; } +.#{$ti-prefix}-brand-deno:before { content: $ti-icon-brand-deno; } +.#{$ti-prefix}-brand-denodo:before { content: $ti-icon-brand-denodo; } +.#{$ti-prefix}-brand-deviantart:before { content: $ti-icon-brand-deviantart; } +.#{$ti-prefix}-brand-dingtalk:before { content: $ti-icon-brand-dingtalk; } +.#{$ti-prefix}-brand-discord:before { content: $ti-icon-brand-discord; } +.#{$ti-prefix}-brand-discord-filled:before { content: $ti-icon-brand-discord-filled; } +.#{$ti-prefix}-brand-disney:before { content: $ti-icon-brand-disney; } +.#{$ti-prefix}-brand-disqus:before { content: $ti-icon-brand-disqus; } +.#{$ti-prefix}-brand-django:before { content: $ti-icon-brand-django; } +.#{$ti-prefix}-brand-docker:before { content: $ti-icon-brand-docker; } +.#{$ti-prefix}-brand-doctrine:before { content: $ti-icon-brand-doctrine; } +.#{$ti-prefix}-brand-dolby-digital:before { content: $ti-icon-brand-dolby-digital; } +.#{$ti-prefix}-brand-douban:before { content: $ti-icon-brand-douban; } +.#{$ti-prefix}-brand-dribbble:before { content: $ti-icon-brand-dribbble; } +.#{$ti-prefix}-brand-dribbble-filled:before { content: $ti-icon-brand-dribbble-filled; } +.#{$ti-prefix}-brand-drops:before { content: $ti-icon-brand-drops; } +.#{$ti-prefix}-brand-drupal:before { content: $ti-icon-brand-drupal; } +.#{$ti-prefix}-brand-edge:before { content: $ti-icon-brand-edge; } +.#{$ti-prefix}-brand-elastic:before { content: $ti-icon-brand-elastic; } +.#{$ti-prefix}-brand-ember:before { content: $ti-icon-brand-ember; } +.#{$ti-prefix}-brand-envato:before { content: $ti-icon-brand-envato; } +.#{$ti-prefix}-brand-etsy:before { content: $ti-icon-brand-etsy; } +.#{$ti-prefix}-brand-evernote:before { content: $ti-icon-brand-evernote; } +.#{$ti-prefix}-brand-facebook:before { content: $ti-icon-brand-facebook; } +.#{$ti-prefix}-brand-facebook-filled:before { content: $ti-icon-brand-facebook-filled; } +.#{$ti-prefix}-brand-figma:before { content: $ti-icon-brand-figma; } +.#{$ti-prefix}-brand-finder:before { content: $ti-icon-brand-finder; } +.#{$ti-prefix}-brand-firebase:before { content: $ti-icon-brand-firebase; } +.#{$ti-prefix}-brand-firefox:before { content: $ti-icon-brand-firefox; } +.#{$ti-prefix}-brand-fiverr:before { content: $ti-icon-brand-fiverr; } +.#{$ti-prefix}-brand-flickr:before { content: $ti-icon-brand-flickr; } +.#{$ti-prefix}-brand-flightradar24:before { content: $ti-icon-brand-flightradar24; } +.#{$ti-prefix}-brand-flipboard:before { content: $ti-icon-brand-flipboard; } +.#{$ti-prefix}-brand-flutter:before { content: $ti-icon-brand-flutter; } +.#{$ti-prefix}-brand-fortnite:before { content: $ti-icon-brand-fortnite; } +.#{$ti-prefix}-brand-foursquare:before { content: $ti-icon-brand-foursquare; } +.#{$ti-prefix}-brand-framer:before { content: $ti-icon-brand-framer; } +.#{$ti-prefix}-brand-framer-motion:before { content: $ti-icon-brand-framer-motion; } +.#{$ti-prefix}-brand-funimation:before { content: $ti-icon-brand-funimation; } +.#{$ti-prefix}-brand-gatsby:before { content: $ti-icon-brand-gatsby; } +.#{$ti-prefix}-brand-git:before { content: $ti-icon-brand-git; } +.#{$ti-prefix}-brand-github:before { content: $ti-icon-brand-github; } +.#{$ti-prefix}-brand-github-copilot:before { content: $ti-icon-brand-github-copilot; } +.#{$ti-prefix}-brand-github-filled:before { content: $ti-icon-brand-github-filled; } +.#{$ti-prefix}-brand-gitlab:before { content: $ti-icon-brand-gitlab; } +.#{$ti-prefix}-brand-gmail:before { content: $ti-icon-brand-gmail; } +.#{$ti-prefix}-brand-golang:before { content: $ti-icon-brand-golang; } +.#{$ti-prefix}-brand-google:before { content: $ti-icon-brand-google; } +.#{$ti-prefix}-brand-google-analytics:before { content: $ti-icon-brand-google-analytics; } +.#{$ti-prefix}-brand-google-big-query:before { content: $ti-icon-brand-google-big-query; } +.#{$ti-prefix}-brand-google-drive:before { content: $ti-icon-brand-google-drive; } +.#{$ti-prefix}-brand-google-fit:before { content: $ti-icon-brand-google-fit; } +.#{$ti-prefix}-brand-google-home:before { content: $ti-icon-brand-google-home; } +.#{$ti-prefix}-brand-google-one:before { content: $ti-icon-brand-google-one; } +.#{$ti-prefix}-brand-google-photos:before { content: $ti-icon-brand-google-photos; } +.#{$ti-prefix}-brand-google-play:before { content: $ti-icon-brand-google-play; } +.#{$ti-prefix}-brand-google-podcasts:before { content: $ti-icon-brand-google-podcasts; } +.#{$ti-prefix}-brand-grammarly:before { content: $ti-icon-brand-grammarly; } +.#{$ti-prefix}-brand-graphql:before { content: $ti-icon-brand-graphql; } +.#{$ti-prefix}-brand-gravatar:before { content: $ti-icon-brand-gravatar; } +.#{$ti-prefix}-brand-grindr:before { content: $ti-icon-brand-grindr; } +.#{$ti-prefix}-brand-guardian:before { content: $ti-icon-brand-guardian; } +.#{$ti-prefix}-brand-gumroad:before { content: $ti-icon-brand-gumroad; } +.#{$ti-prefix}-brand-hbo:before { content: $ti-icon-brand-hbo; } +.#{$ti-prefix}-brand-headlessui:before { content: $ti-icon-brand-headlessui; } +.#{$ti-prefix}-brand-hipchat:before { content: $ti-icon-brand-hipchat; } +.#{$ti-prefix}-brand-html5:before { content: $ti-icon-brand-html5; } +.#{$ti-prefix}-brand-inertia:before { content: $ti-icon-brand-inertia; } +.#{$ti-prefix}-brand-instagram:before { content: $ti-icon-brand-instagram; } +.#{$ti-prefix}-brand-intercom:before { content: $ti-icon-brand-intercom; } +.#{$ti-prefix}-brand-javascript:before { content: $ti-icon-brand-javascript; } +.#{$ti-prefix}-brand-juejin:before { content: $ti-icon-brand-juejin; } +.#{$ti-prefix}-brand-kickstarter:before { content: $ti-icon-brand-kickstarter; } +.#{$ti-prefix}-brand-kotlin:before { content: $ti-icon-brand-kotlin; } +.#{$ti-prefix}-brand-laravel:before { content: $ti-icon-brand-laravel; } +.#{$ti-prefix}-brand-lastfm:before { content: $ti-icon-brand-lastfm; } +.#{$ti-prefix}-brand-line:before { content: $ti-icon-brand-line; } +.#{$ti-prefix}-brand-linkedin:before { content: $ti-icon-brand-linkedin; } +.#{$ti-prefix}-brand-linktree:before { content: $ti-icon-brand-linktree; } +.#{$ti-prefix}-brand-linqpad:before { content: $ti-icon-brand-linqpad; } +.#{$ti-prefix}-brand-loom:before { content: $ti-icon-brand-loom; } +.#{$ti-prefix}-brand-mailgun:before { content: $ti-icon-brand-mailgun; } +.#{$ti-prefix}-brand-mantine:before { content: $ti-icon-brand-mantine; } +.#{$ti-prefix}-brand-mastercard:before { content: $ti-icon-brand-mastercard; } +.#{$ti-prefix}-brand-mastodon:before { content: $ti-icon-brand-mastodon; } +.#{$ti-prefix}-brand-matrix:before { content: $ti-icon-brand-matrix; } +.#{$ti-prefix}-brand-mcdonalds:before { content: $ti-icon-brand-mcdonalds; } +.#{$ti-prefix}-brand-medium:before { content: $ti-icon-brand-medium; } +.#{$ti-prefix}-brand-mercedes:before { content: $ti-icon-brand-mercedes; } +.#{$ti-prefix}-brand-messenger:before { content: $ti-icon-brand-messenger; } +.#{$ti-prefix}-brand-meta:before { content: $ti-icon-brand-meta; } +.#{$ti-prefix}-brand-miniprogram:before { content: $ti-icon-brand-miniprogram; } +.#{$ti-prefix}-brand-mixpanel:before { content: $ti-icon-brand-mixpanel; } +.#{$ti-prefix}-brand-monday:before { content: $ti-icon-brand-monday; } +.#{$ti-prefix}-brand-mongodb:before { content: $ti-icon-brand-mongodb; } +.#{$ti-prefix}-brand-my-oppo:before { content: $ti-icon-brand-my-oppo; } +.#{$ti-prefix}-brand-mysql:before { content: $ti-icon-brand-mysql; } +.#{$ti-prefix}-brand-national-geographic:before { content: $ti-icon-brand-national-geographic; } +.#{$ti-prefix}-brand-nem:before { content: $ti-icon-brand-nem; } +.#{$ti-prefix}-brand-netbeans:before { content: $ti-icon-brand-netbeans; } +.#{$ti-prefix}-brand-netease-music:before { content: $ti-icon-brand-netease-music; } +.#{$ti-prefix}-brand-netflix:before { content: $ti-icon-brand-netflix; } +.#{$ti-prefix}-brand-nexo:before { content: $ti-icon-brand-nexo; } +.#{$ti-prefix}-brand-nextcloud:before { content: $ti-icon-brand-nextcloud; } +.#{$ti-prefix}-brand-nextjs:before { content: $ti-icon-brand-nextjs; } +.#{$ti-prefix}-brand-nord-vpn:before { content: $ti-icon-brand-nord-vpn; } +.#{$ti-prefix}-brand-notion:before { content: $ti-icon-brand-notion; } +.#{$ti-prefix}-brand-npm:before { content: $ti-icon-brand-npm; } +.#{$ti-prefix}-brand-nuxt:before { content: $ti-icon-brand-nuxt; } +.#{$ti-prefix}-brand-nytimes:before { content: $ti-icon-brand-nytimes; } +.#{$ti-prefix}-brand-office:before { content: $ti-icon-brand-office; } +.#{$ti-prefix}-brand-ok-ru:before { content: $ti-icon-brand-ok-ru; } +.#{$ti-prefix}-brand-onedrive:before { content: $ti-icon-brand-onedrive; } +.#{$ti-prefix}-brand-onlyfans:before { content: $ti-icon-brand-onlyfans; } +.#{$ti-prefix}-brand-open-source:before { content: $ti-icon-brand-open-source; } +.#{$ti-prefix}-brand-openai:before { content: $ti-icon-brand-openai; } +.#{$ti-prefix}-brand-openvpn:before { content: $ti-icon-brand-openvpn; } +.#{$ti-prefix}-brand-opera:before { content: $ti-icon-brand-opera; } +.#{$ti-prefix}-brand-pagekit:before { content: $ti-icon-brand-pagekit; } +.#{$ti-prefix}-brand-patreon:before { content: $ti-icon-brand-patreon; } +.#{$ti-prefix}-brand-paypal:before { content: $ti-icon-brand-paypal; } +.#{$ti-prefix}-brand-paypal-filled:before { content: $ti-icon-brand-paypal-filled; } +.#{$ti-prefix}-brand-paypay:before { content: $ti-icon-brand-paypay; } +.#{$ti-prefix}-brand-peanut:before { content: $ti-icon-brand-peanut; } +.#{$ti-prefix}-brand-pepsi:before { content: $ti-icon-brand-pepsi; } +.#{$ti-prefix}-brand-php:before { content: $ti-icon-brand-php; } +.#{$ti-prefix}-brand-picsart:before { content: $ti-icon-brand-picsart; } +.#{$ti-prefix}-brand-pinterest:before { content: $ti-icon-brand-pinterest; } +.#{$ti-prefix}-brand-planetscale:before { content: $ti-icon-brand-planetscale; } +.#{$ti-prefix}-brand-pocket:before { content: $ti-icon-brand-pocket; } +.#{$ti-prefix}-brand-polymer:before { content: $ti-icon-brand-polymer; } +.#{$ti-prefix}-brand-powershell:before { content: $ti-icon-brand-powershell; } +.#{$ti-prefix}-brand-prisma:before { content: $ti-icon-brand-prisma; } +.#{$ti-prefix}-brand-producthunt:before { content: $ti-icon-brand-producthunt; } +.#{$ti-prefix}-brand-pushbullet:before { content: $ti-icon-brand-pushbullet; } +.#{$ti-prefix}-brand-pushover:before { content: $ti-icon-brand-pushover; } +.#{$ti-prefix}-brand-python:before { content: $ti-icon-brand-python; } +.#{$ti-prefix}-brand-qq:before { content: $ti-icon-brand-qq; } +.#{$ti-prefix}-brand-radix-ui:before { content: $ti-icon-brand-radix-ui; } +.#{$ti-prefix}-brand-react:before { content: $ti-icon-brand-react; } +.#{$ti-prefix}-brand-react-native:before { content: $ti-icon-brand-react-native; } +.#{$ti-prefix}-brand-reason:before { content: $ti-icon-brand-reason; } +.#{$ti-prefix}-brand-reddit:before { content: $ti-icon-brand-reddit; } +.#{$ti-prefix}-brand-redhat:before { content: $ti-icon-brand-redhat; } +.#{$ti-prefix}-brand-redux:before { content: $ti-icon-brand-redux; } +.#{$ti-prefix}-brand-revolut:before { content: $ti-icon-brand-revolut; } +.#{$ti-prefix}-brand-safari:before { content: $ti-icon-brand-safari; } +.#{$ti-prefix}-brand-samsungpass:before { content: $ti-icon-brand-samsungpass; } +.#{$ti-prefix}-brand-sass:before { content: $ti-icon-brand-sass; } +.#{$ti-prefix}-brand-sentry:before { content: $ti-icon-brand-sentry; } +.#{$ti-prefix}-brand-sharik:before { content: $ti-icon-brand-sharik; } +.#{$ti-prefix}-brand-shazam:before { content: $ti-icon-brand-shazam; } +.#{$ti-prefix}-brand-shopee:before { content: $ti-icon-brand-shopee; } +.#{$ti-prefix}-brand-sketch:before { content: $ti-icon-brand-sketch; } +.#{$ti-prefix}-brand-skype:before { content: $ti-icon-brand-skype; } +.#{$ti-prefix}-brand-slack:before { content: $ti-icon-brand-slack; } +.#{$ti-prefix}-brand-snapchat:before { content: $ti-icon-brand-snapchat; } +.#{$ti-prefix}-brand-snapseed:before { content: $ti-icon-brand-snapseed; } +.#{$ti-prefix}-brand-snowflake:before { content: $ti-icon-brand-snowflake; } +.#{$ti-prefix}-brand-socket-io:before { content: $ti-icon-brand-socket-io; } +.#{$ti-prefix}-brand-solidjs:before { content: $ti-icon-brand-solidjs; } +.#{$ti-prefix}-brand-soundcloud:before { content: $ti-icon-brand-soundcloud; } +.#{$ti-prefix}-brand-spacehey:before { content: $ti-icon-brand-spacehey; } +.#{$ti-prefix}-brand-spotify:before { content: $ti-icon-brand-spotify; } +.#{$ti-prefix}-brand-stackoverflow:before { content: $ti-icon-brand-stackoverflow; } +.#{$ti-prefix}-brand-stackshare:before { content: $ti-icon-brand-stackshare; } +.#{$ti-prefix}-brand-steam:before { content: $ti-icon-brand-steam; } +.#{$ti-prefix}-brand-storybook:before { content: $ti-icon-brand-storybook; } +.#{$ti-prefix}-brand-storytel:before { content: $ti-icon-brand-storytel; } +.#{$ti-prefix}-brand-strava:before { content: $ti-icon-brand-strava; } +.#{$ti-prefix}-brand-stripe:before { content: $ti-icon-brand-stripe; } +.#{$ti-prefix}-brand-sublime-text:before { content: $ti-icon-brand-sublime-text; } +.#{$ti-prefix}-brand-sugarizer:before { content: $ti-icon-brand-sugarizer; } +.#{$ti-prefix}-brand-supabase:before { content: $ti-icon-brand-supabase; } +.#{$ti-prefix}-brand-superhuman:before { content: $ti-icon-brand-superhuman; } +.#{$ti-prefix}-brand-supernova:before { content: $ti-icon-brand-supernova; } +.#{$ti-prefix}-brand-surfshark:before { content: $ti-icon-brand-surfshark; } +.#{$ti-prefix}-brand-svelte:before { content: $ti-icon-brand-svelte; } +.#{$ti-prefix}-brand-symfony:before { content: $ti-icon-brand-symfony; } +.#{$ti-prefix}-brand-tabler:before { content: $ti-icon-brand-tabler; } +.#{$ti-prefix}-brand-tailwind:before { content: $ti-icon-brand-tailwind; } +.#{$ti-prefix}-brand-taobao:before { content: $ti-icon-brand-taobao; } +.#{$ti-prefix}-brand-ted:before { content: $ti-icon-brand-ted; } +.#{$ti-prefix}-brand-telegram:before { content: $ti-icon-brand-telegram; } +.#{$ti-prefix}-brand-tether:before { content: $ti-icon-brand-tether; } +.#{$ti-prefix}-brand-threejs:before { content: $ti-icon-brand-threejs; } +.#{$ti-prefix}-brand-tidal:before { content: $ti-icon-brand-tidal; } +.#{$ti-prefix}-brand-tikto-filled:before { content: $ti-icon-brand-tikto-filled; } +.#{$ti-prefix}-brand-tiktok:before { content: $ti-icon-brand-tiktok; } +.#{$ti-prefix}-brand-tinder:before { content: $ti-icon-brand-tinder; } +.#{$ti-prefix}-brand-topbuzz:before { content: $ti-icon-brand-topbuzz; } +.#{$ti-prefix}-brand-torchain:before { content: $ti-icon-brand-torchain; } +.#{$ti-prefix}-brand-toyota:before { content: $ti-icon-brand-toyota; } +.#{$ti-prefix}-brand-trello:before { content: $ti-icon-brand-trello; } +.#{$ti-prefix}-brand-tripadvisor:before { content: $ti-icon-brand-tripadvisor; } +.#{$ti-prefix}-brand-tumblr:before { content: $ti-icon-brand-tumblr; } +.#{$ti-prefix}-brand-twilio:before { content: $ti-icon-brand-twilio; } +.#{$ti-prefix}-brand-twitch:before { content: $ti-icon-brand-twitch; } +.#{$ti-prefix}-brand-twitter:before { content: $ti-icon-brand-twitter; } +.#{$ti-prefix}-brand-twitter-filled:before { content: $ti-icon-brand-twitter-filled; } +.#{$ti-prefix}-brand-typescript:before { content: $ti-icon-brand-typescript; } +.#{$ti-prefix}-brand-uber:before { content: $ti-icon-brand-uber; } +.#{$ti-prefix}-brand-ubuntu:before { content: $ti-icon-brand-ubuntu; } +.#{$ti-prefix}-brand-unity:before { content: $ti-icon-brand-unity; } +.#{$ti-prefix}-brand-unsplash:before { content: $ti-icon-brand-unsplash; } +.#{$ti-prefix}-brand-upwork:before { content: $ti-icon-brand-upwork; } +.#{$ti-prefix}-brand-valorant:before { content: $ti-icon-brand-valorant; } +.#{$ti-prefix}-brand-vercel:before { content: $ti-icon-brand-vercel; } +.#{$ti-prefix}-brand-vimeo:before { content: $ti-icon-brand-vimeo; } +.#{$ti-prefix}-brand-vinted:before { content: $ti-icon-brand-vinted; } +.#{$ti-prefix}-brand-visa:before { content: $ti-icon-brand-visa; } +.#{$ti-prefix}-brand-visual-studio:before { content: $ti-icon-brand-visual-studio; } +.#{$ti-prefix}-brand-vite:before { content: $ti-icon-brand-vite; } +.#{$ti-prefix}-brand-vivaldi:before { content: $ti-icon-brand-vivaldi; } +.#{$ti-prefix}-brand-vk:before { content: $ti-icon-brand-vk; } +.#{$ti-prefix}-brand-volkswagen:before { content: $ti-icon-brand-volkswagen; } +.#{$ti-prefix}-brand-vsco:before { content: $ti-icon-brand-vsco; } +.#{$ti-prefix}-brand-vscode:before { content: $ti-icon-brand-vscode; } +.#{$ti-prefix}-brand-vue:before { content: $ti-icon-brand-vue; } +.#{$ti-prefix}-brand-walmart:before { content: $ti-icon-brand-walmart; } +.#{$ti-prefix}-brand-waze:before { content: $ti-icon-brand-waze; } +.#{$ti-prefix}-brand-webflow:before { content: $ti-icon-brand-webflow; } +.#{$ti-prefix}-brand-wechat:before { content: $ti-icon-brand-wechat; } +.#{$ti-prefix}-brand-weibo:before { content: $ti-icon-brand-weibo; } +.#{$ti-prefix}-brand-whatsapp:before { content: $ti-icon-brand-whatsapp; } +.#{$ti-prefix}-brand-windows:before { content: $ti-icon-brand-windows; } +.#{$ti-prefix}-brand-windy:before { content: $ti-icon-brand-windy; } +.#{$ti-prefix}-brand-wish:before { content: $ti-icon-brand-wish; } +.#{$ti-prefix}-brand-wix:before { content: $ti-icon-brand-wix; } +.#{$ti-prefix}-brand-wordpress:before { content: $ti-icon-brand-wordpress; } +.#{$ti-prefix}-brand-xbox:before { content: $ti-icon-brand-xbox; } +.#{$ti-prefix}-brand-xing:before { content: $ti-icon-brand-xing; } +.#{$ti-prefix}-brand-yahoo:before { content: $ti-icon-brand-yahoo; } +.#{$ti-prefix}-brand-yatse:before { content: $ti-icon-brand-yatse; } +.#{$ti-prefix}-brand-ycombinator:before { content: $ti-icon-brand-ycombinator; } +.#{$ti-prefix}-brand-youtube:before { content: $ti-icon-brand-youtube; } +.#{$ti-prefix}-brand-youtube-kids:before { content: $ti-icon-brand-youtube-kids; } +.#{$ti-prefix}-brand-zalando:before { content: $ti-icon-brand-zalando; } +.#{$ti-prefix}-brand-zapier:before { content: $ti-icon-brand-zapier; } +.#{$ti-prefix}-brand-zeit:before { content: $ti-icon-brand-zeit; } +.#{$ti-prefix}-brand-zhihu:before { content: $ti-icon-brand-zhihu; } +.#{$ti-prefix}-brand-zoom:before { content: $ti-icon-brand-zoom; } +.#{$ti-prefix}-brand-zulip:before { content: $ti-icon-brand-zulip; } +.#{$ti-prefix}-brand-zwift:before { content: $ti-icon-brand-zwift; } +.#{$ti-prefix}-bread:before { content: $ti-icon-bread; } +.#{$ti-prefix}-bread-off:before { content: $ti-icon-bread-off; } +.#{$ti-prefix}-briefcase:before { content: $ti-icon-briefcase; } +.#{$ti-prefix}-briefcase-off:before { content: $ti-icon-briefcase-off; } +.#{$ti-prefix}-brightness:before { content: $ti-icon-brightness; } +.#{$ti-prefix}-brightness-2:before { content: $ti-icon-brightness-2; } +.#{$ti-prefix}-brightness-down:before { content: $ti-icon-brightness-down; } +.#{$ti-prefix}-brightness-half:before { content: $ti-icon-brightness-half; } +.#{$ti-prefix}-brightness-off:before { content: $ti-icon-brightness-off; } +.#{$ti-prefix}-brightness-up:before { content: $ti-icon-brightness-up; } +.#{$ti-prefix}-broadcast:before { content: $ti-icon-broadcast; } +.#{$ti-prefix}-broadcast-off:before { content: $ti-icon-broadcast-off; } +.#{$ti-prefix}-browser:before { content: $ti-icon-browser; } +.#{$ti-prefix}-browser-check:before { content: $ti-icon-browser-check; } +.#{$ti-prefix}-browser-off:before { content: $ti-icon-browser-off; } +.#{$ti-prefix}-browser-plus:before { content: $ti-icon-browser-plus; } +.#{$ti-prefix}-browser-x:before { content: $ti-icon-browser-x; } +.#{$ti-prefix}-brush:before { content: $ti-icon-brush; } +.#{$ti-prefix}-brush-off:before { content: $ti-icon-brush-off; } +.#{$ti-prefix}-bucket:before { content: $ti-icon-bucket; } +.#{$ti-prefix}-bucket-droplet:before { content: $ti-icon-bucket-droplet; } +.#{$ti-prefix}-bucket-off:before { content: $ti-icon-bucket-off; } +.#{$ti-prefix}-bug:before { content: $ti-icon-bug; } +.#{$ti-prefix}-bug-off:before { content: $ti-icon-bug-off; } +.#{$ti-prefix}-building:before { content: $ti-icon-building; } +.#{$ti-prefix}-building-arch:before { content: $ti-icon-building-arch; } +.#{$ti-prefix}-building-bank:before { content: $ti-icon-building-bank; } +.#{$ti-prefix}-building-bridge:before { content: $ti-icon-building-bridge; } +.#{$ti-prefix}-building-bridge-2:before { content: $ti-icon-building-bridge-2; } +.#{$ti-prefix}-building-broadcast-tower:before { content: $ti-icon-building-broadcast-tower; } +.#{$ti-prefix}-building-carousel:before { content: $ti-icon-building-carousel; } +.#{$ti-prefix}-building-castle:before { content: $ti-icon-building-castle; } +.#{$ti-prefix}-building-church:before { content: $ti-icon-building-church; } +.#{$ti-prefix}-building-circus:before { content: $ti-icon-building-circus; } +.#{$ti-prefix}-building-community:before { content: $ti-icon-building-community; } +.#{$ti-prefix}-building-cottage:before { content: $ti-icon-building-cottage; } +.#{$ti-prefix}-building-estate:before { content: $ti-icon-building-estate; } +.#{$ti-prefix}-building-factory:before { content: $ti-icon-building-factory; } +.#{$ti-prefix}-building-factory-2:before { content: $ti-icon-building-factory-2; } +.#{$ti-prefix}-building-fortress:before { content: $ti-icon-building-fortress; } +.#{$ti-prefix}-building-hospital:before { content: $ti-icon-building-hospital; } +.#{$ti-prefix}-building-lighthouse:before { content: $ti-icon-building-lighthouse; } +.#{$ti-prefix}-building-monument:before { content: $ti-icon-building-monument; } +.#{$ti-prefix}-building-pavilion:before { content: $ti-icon-building-pavilion; } +.#{$ti-prefix}-building-skyscraper:before { content: $ti-icon-building-skyscraper; } +.#{$ti-prefix}-building-stadium:before { content: $ti-icon-building-stadium; } +.#{$ti-prefix}-building-store:before { content: $ti-icon-building-store; } +.#{$ti-prefix}-building-tunnel:before { content: $ti-icon-building-tunnel; } +.#{$ti-prefix}-building-warehouse:before { content: $ti-icon-building-warehouse; } +.#{$ti-prefix}-building-wind-turbine:before { content: $ti-icon-building-wind-turbine; } +.#{$ti-prefix}-bulb:before { content: $ti-icon-bulb; } +.#{$ti-prefix}-bulb-filled:before { content: $ti-icon-bulb-filled; } +.#{$ti-prefix}-bulb-off:before { content: $ti-icon-bulb-off; } +.#{$ti-prefix}-bulldozer:before { content: $ti-icon-bulldozer; } +.#{$ti-prefix}-bus:before { content: $ti-icon-bus; } +.#{$ti-prefix}-bus-off:before { content: $ti-icon-bus-off; } +.#{$ti-prefix}-bus-stop:before { content: $ti-icon-bus-stop; } +.#{$ti-prefix}-businessplan:before { content: $ti-icon-businessplan; } +.#{$ti-prefix}-butterfly:before { content: $ti-icon-butterfly; } +.#{$ti-prefix}-cactus:before { content: $ti-icon-cactus; } +.#{$ti-prefix}-cactus-off:before { content: $ti-icon-cactus-off; } +.#{$ti-prefix}-cake:before { content: $ti-icon-cake; } +.#{$ti-prefix}-cake-off:before { content: $ti-icon-cake-off; } +.#{$ti-prefix}-calculator:before { content: $ti-icon-calculator; } +.#{$ti-prefix}-calculator-off:before { content: $ti-icon-calculator-off; } +.#{$ti-prefix}-calendar:before { content: $ti-icon-calendar; } +.#{$ti-prefix}-calendar-bolt:before { content: $ti-icon-calendar-bolt; } +.#{$ti-prefix}-calendar-cancel:before { content: $ti-icon-calendar-cancel; } +.#{$ti-prefix}-calendar-check:before { content: $ti-icon-calendar-check; } +.#{$ti-prefix}-calendar-code:before { content: $ti-icon-calendar-code; } +.#{$ti-prefix}-calendar-cog:before { content: $ti-icon-calendar-cog; } +.#{$ti-prefix}-calendar-dollar:before { content: $ti-icon-calendar-dollar; } +.#{$ti-prefix}-calendar-down:before { content: $ti-icon-calendar-down; } +.#{$ti-prefix}-calendar-due:before { content: $ti-icon-calendar-due; } +.#{$ti-prefix}-calendar-event:before { content: $ti-icon-calendar-event; } +.#{$ti-prefix}-calendar-exclamation:before { content: $ti-icon-calendar-exclamation; } +.#{$ti-prefix}-calendar-heart:before { content: $ti-icon-calendar-heart; } +.#{$ti-prefix}-calendar-minus:before { content: $ti-icon-calendar-minus; } +.#{$ti-prefix}-calendar-off:before { content: $ti-icon-calendar-off; } +.#{$ti-prefix}-calendar-pause:before { content: $ti-icon-calendar-pause; } +.#{$ti-prefix}-calendar-pin:before { content: $ti-icon-calendar-pin; } +.#{$ti-prefix}-calendar-plus:before { content: $ti-icon-calendar-plus; } +.#{$ti-prefix}-calendar-question:before { content: $ti-icon-calendar-question; } +.#{$ti-prefix}-calendar-search:before { content: $ti-icon-calendar-search; } +.#{$ti-prefix}-calendar-share:before { content: $ti-icon-calendar-share; } +.#{$ti-prefix}-calendar-star:before { content: $ti-icon-calendar-star; } +.#{$ti-prefix}-calendar-stats:before { content: $ti-icon-calendar-stats; } +.#{$ti-prefix}-calendar-time:before { content: $ti-icon-calendar-time; } +.#{$ti-prefix}-calendar-up:before { content: $ti-icon-calendar-up; } +.#{$ti-prefix}-calendar-x:before { content: $ti-icon-calendar-x; } +.#{$ti-prefix}-camera:before { content: $ti-icon-camera; } +.#{$ti-prefix}-camera-bolt:before { content: $ti-icon-camera-bolt; } +.#{$ti-prefix}-camera-cancel:before { content: $ti-icon-camera-cancel; } +.#{$ti-prefix}-camera-check:before { content: $ti-icon-camera-check; } +.#{$ti-prefix}-camera-code:before { content: $ti-icon-camera-code; } +.#{$ti-prefix}-camera-cog:before { content: $ti-icon-camera-cog; } +.#{$ti-prefix}-camera-dollar:before { content: $ti-icon-camera-dollar; } +.#{$ti-prefix}-camera-down:before { content: $ti-icon-camera-down; } +.#{$ti-prefix}-camera-exclamation:before { content: $ti-icon-camera-exclamation; } +.#{$ti-prefix}-camera-heart:before { content: $ti-icon-camera-heart; } +.#{$ti-prefix}-camera-minus:before { content: $ti-icon-camera-minus; } +.#{$ti-prefix}-camera-off:before { content: $ti-icon-camera-off; } +.#{$ti-prefix}-camera-pause:before { content: $ti-icon-camera-pause; } +.#{$ti-prefix}-camera-pin:before { content: $ti-icon-camera-pin; } +.#{$ti-prefix}-camera-plus:before { content: $ti-icon-camera-plus; } +.#{$ti-prefix}-camera-question:before { content: $ti-icon-camera-question; } +.#{$ti-prefix}-camera-rotate:before { content: $ti-icon-camera-rotate; } +.#{$ti-prefix}-camera-search:before { content: $ti-icon-camera-search; } +.#{$ti-prefix}-camera-selfie:before { content: $ti-icon-camera-selfie; } +.#{$ti-prefix}-camera-share:before { content: $ti-icon-camera-share; } +.#{$ti-prefix}-camera-star:before { content: $ti-icon-camera-star; } +.#{$ti-prefix}-camera-up:before { content: $ti-icon-camera-up; } +.#{$ti-prefix}-camera-x:before { content: $ti-icon-camera-x; } +.#{$ti-prefix}-campfire:before { content: $ti-icon-campfire; } +.#{$ti-prefix}-candle:before { content: $ti-icon-candle; } +.#{$ti-prefix}-candy:before { content: $ti-icon-candy; } +.#{$ti-prefix}-candy-off:before { content: $ti-icon-candy-off; } +.#{$ti-prefix}-cane:before { content: $ti-icon-cane; } +.#{$ti-prefix}-cannabis:before { content: $ti-icon-cannabis; } +.#{$ti-prefix}-capture:before { content: $ti-icon-capture; } +.#{$ti-prefix}-capture-off:before { content: $ti-icon-capture-off; } +.#{$ti-prefix}-car:before { content: $ti-icon-car; } +.#{$ti-prefix}-car-crane:before { content: $ti-icon-car-crane; } +.#{$ti-prefix}-car-crash:before { content: $ti-icon-car-crash; } +.#{$ti-prefix}-car-off:before { content: $ti-icon-car-off; } +.#{$ti-prefix}-car-turbine:before { content: $ti-icon-car-turbine; } +.#{$ti-prefix}-caravan:before { content: $ti-icon-caravan; } +.#{$ti-prefix}-cardboards:before { content: $ti-icon-cardboards; } +.#{$ti-prefix}-cardboards-off:before { content: $ti-icon-cardboards-off; } +.#{$ti-prefix}-cards:before { content: $ti-icon-cards; } +.#{$ti-prefix}-caret-down:before { content: $ti-icon-caret-down; } +.#{$ti-prefix}-caret-left:before { content: $ti-icon-caret-left; } +.#{$ti-prefix}-caret-right:before { content: $ti-icon-caret-right; } +.#{$ti-prefix}-caret-up:before { content: $ti-icon-caret-up; } +.#{$ti-prefix}-carousel-horizontal:before { content: $ti-icon-carousel-horizontal; } +.#{$ti-prefix}-carousel-vertical:before { content: $ti-icon-carousel-vertical; } +.#{$ti-prefix}-carrot:before { content: $ti-icon-carrot; } +.#{$ti-prefix}-carrot-off:before { content: $ti-icon-carrot-off; } +.#{$ti-prefix}-cash:before { content: $ti-icon-cash; } +.#{$ti-prefix}-cash-banknote:before { content: $ti-icon-cash-banknote; } +.#{$ti-prefix}-cash-banknote-off:before { content: $ti-icon-cash-banknote-off; } +.#{$ti-prefix}-cash-off:before { content: $ti-icon-cash-off; } +.#{$ti-prefix}-cast:before { content: $ti-icon-cast; } +.#{$ti-prefix}-cast-off:before { content: $ti-icon-cast-off; } +.#{$ti-prefix}-cat:before { content: $ti-icon-cat; } +.#{$ti-prefix}-category:before { content: $ti-icon-category; } +.#{$ti-prefix}-category-2:before { content: $ti-icon-category-2; } +.#{$ti-prefix}-ce:before { content: $ti-icon-ce; } +.#{$ti-prefix}-ce-off:before { content: $ti-icon-ce-off; } +.#{$ti-prefix}-cell:before { content: $ti-icon-cell; } +.#{$ti-prefix}-cell-signal-1:before { content: $ti-icon-cell-signal-1; } +.#{$ti-prefix}-cell-signal-2:before { content: $ti-icon-cell-signal-2; } +.#{$ti-prefix}-cell-signal-3:before { content: $ti-icon-cell-signal-3; } +.#{$ti-prefix}-cell-signal-4:before { content: $ti-icon-cell-signal-4; } +.#{$ti-prefix}-cell-signal-5:before { content: $ti-icon-cell-signal-5; } +.#{$ti-prefix}-cell-signal-off:before { content: $ti-icon-cell-signal-off; } +.#{$ti-prefix}-certificate:before { content: $ti-icon-certificate; } +.#{$ti-prefix}-certificate-2:before { content: $ti-icon-certificate-2; } +.#{$ti-prefix}-certificate-2-off:before { content: $ti-icon-certificate-2-off; } +.#{$ti-prefix}-certificate-off:before { content: $ti-icon-certificate-off; } +.#{$ti-prefix}-chair-director:before { content: $ti-icon-chair-director; } +.#{$ti-prefix}-chalkboard:before { content: $ti-icon-chalkboard; } +.#{$ti-prefix}-chalkboard-off:before { content: $ti-icon-chalkboard-off; } +.#{$ti-prefix}-charging-pile:before { content: $ti-icon-charging-pile; } +.#{$ti-prefix}-chart-arcs:before { content: $ti-icon-chart-arcs; } +.#{$ti-prefix}-chart-arcs-3:before { content: $ti-icon-chart-arcs-3; } +.#{$ti-prefix}-chart-area:before { content: $ti-icon-chart-area; } +.#{$ti-prefix}-chart-area-filled:before { content: $ti-icon-chart-area-filled; } +.#{$ti-prefix}-chart-area-line:before { content: $ti-icon-chart-area-line; } +.#{$ti-prefix}-chart-area-line-filled:before { content: $ti-icon-chart-area-line-filled; } +.#{$ti-prefix}-chart-arrows:before { content: $ti-icon-chart-arrows; } +.#{$ti-prefix}-chart-arrows-vertical:before { content: $ti-icon-chart-arrows-vertical; } +.#{$ti-prefix}-chart-bar:before { content: $ti-icon-chart-bar; } +.#{$ti-prefix}-chart-bar-off:before { content: $ti-icon-chart-bar-off; } +.#{$ti-prefix}-chart-bubble:before { content: $ti-icon-chart-bubble; } +.#{$ti-prefix}-chart-bubble-filled:before { content: $ti-icon-chart-bubble-filled; } +.#{$ti-prefix}-chart-candle:before { content: $ti-icon-chart-candle; } +.#{$ti-prefix}-chart-candle-filled:before { content: $ti-icon-chart-candle-filled; } +.#{$ti-prefix}-chart-circles:before { content: $ti-icon-chart-circles; } +.#{$ti-prefix}-chart-donut:before { content: $ti-icon-chart-donut; } +.#{$ti-prefix}-chart-donut-2:before { content: $ti-icon-chart-donut-2; } +.#{$ti-prefix}-chart-donut-3:before { content: $ti-icon-chart-donut-3; } +.#{$ti-prefix}-chart-donut-4:before { content: $ti-icon-chart-donut-4; } +.#{$ti-prefix}-chart-donut-filled:before { content: $ti-icon-chart-donut-filled; } +.#{$ti-prefix}-chart-dots:before { content: $ti-icon-chart-dots; } +.#{$ti-prefix}-chart-dots-2:before { content: $ti-icon-chart-dots-2; } +.#{$ti-prefix}-chart-dots-3:before { content: $ti-icon-chart-dots-3; } +.#{$ti-prefix}-chart-grid-dots:before { content: $ti-icon-chart-grid-dots; } +.#{$ti-prefix}-chart-histogram:before { content: $ti-icon-chart-histogram; } +.#{$ti-prefix}-chart-infographic:before { content: $ti-icon-chart-infographic; } +.#{$ti-prefix}-chart-line:before { content: $ti-icon-chart-line; } +.#{$ti-prefix}-chart-pie:before { content: $ti-icon-chart-pie; } +.#{$ti-prefix}-chart-pie-2:before { content: $ti-icon-chart-pie-2; } +.#{$ti-prefix}-chart-pie-3:before { content: $ti-icon-chart-pie-3; } +.#{$ti-prefix}-chart-pie-4:before { content: $ti-icon-chart-pie-4; } +.#{$ti-prefix}-chart-pie-filled:before { content: $ti-icon-chart-pie-filled; } +.#{$ti-prefix}-chart-pie-off:before { content: $ti-icon-chart-pie-off; } +.#{$ti-prefix}-chart-ppf:before { content: $ti-icon-chart-ppf; } +.#{$ti-prefix}-chart-radar:before { content: $ti-icon-chart-radar; } +.#{$ti-prefix}-chart-sankey:before { content: $ti-icon-chart-sankey; } +.#{$ti-prefix}-chart-treemap:before { content: $ti-icon-chart-treemap; } +.#{$ti-prefix}-check:before { content: $ti-icon-check; } +.#{$ti-prefix}-checkbox:before { content: $ti-icon-checkbox; } +.#{$ti-prefix}-checklist:before { content: $ti-icon-checklist; } +.#{$ti-prefix}-checks:before { content: $ti-icon-checks; } +.#{$ti-prefix}-checkup-list:before { content: $ti-icon-checkup-list; } +.#{$ti-prefix}-cheese:before { content: $ti-icon-cheese; } +.#{$ti-prefix}-chef-hat:before { content: $ti-icon-chef-hat; } +.#{$ti-prefix}-chef-hat-off:before { content: $ti-icon-chef-hat-off; } +.#{$ti-prefix}-cherry:before { content: $ti-icon-cherry; } +.#{$ti-prefix}-cherry-filled:before { content: $ti-icon-cherry-filled; } +.#{$ti-prefix}-chess:before { content: $ti-icon-chess; } +.#{$ti-prefix}-chess-bishop:before { content: $ti-icon-chess-bishop; } +.#{$ti-prefix}-chess-bishop-filled:before { content: $ti-icon-chess-bishop-filled; } +.#{$ti-prefix}-chess-filled:before { content: $ti-icon-chess-filled; } +.#{$ti-prefix}-chess-king:before { content: $ti-icon-chess-king; } +.#{$ti-prefix}-chess-king-filled:before { content: $ti-icon-chess-king-filled; } +.#{$ti-prefix}-chess-knight:before { content: $ti-icon-chess-knight; } +.#{$ti-prefix}-chess-knight-filled:before { content: $ti-icon-chess-knight-filled; } +.#{$ti-prefix}-chess-queen:before { content: $ti-icon-chess-queen; } +.#{$ti-prefix}-chess-queen-filled:before { content: $ti-icon-chess-queen-filled; } +.#{$ti-prefix}-chess-rook:before { content: $ti-icon-chess-rook; } +.#{$ti-prefix}-chess-rook-filled:before { content: $ti-icon-chess-rook-filled; } +.#{$ti-prefix}-chevron-down:before { content: $ti-icon-chevron-down; } +.#{$ti-prefix}-chevron-down-left:before { content: $ti-icon-chevron-down-left; } +.#{$ti-prefix}-chevron-down-right:before { content: $ti-icon-chevron-down-right; } +.#{$ti-prefix}-chevron-left:before { content: $ti-icon-chevron-left; } +.#{$ti-prefix}-chevron-right:before { content: $ti-icon-chevron-right; } +.#{$ti-prefix}-chevron-up:before { content: $ti-icon-chevron-up; } +.#{$ti-prefix}-chevron-up-left:before { content: $ti-icon-chevron-up-left; } +.#{$ti-prefix}-chevron-up-right:before { content: $ti-icon-chevron-up-right; } +.#{$ti-prefix}-chevrons-down:before { content: $ti-icon-chevrons-down; } +.#{$ti-prefix}-chevrons-down-left:before { content: $ti-icon-chevrons-down-left; } +.#{$ti-prefix}-chevrons-down-right:before { content: $ti-icon-chevrons-down-right; } +.#{$ti-prefix}-chevrons-left:before { content: $ti-icon-chevrons-left; } +.#{$ti-prefix}-chevrons-right:before { content: $ti-icon-chevrons-right; } +.#{$ti-prefix}-chevrons-up:before { content: $ti-icon-chevrons-up; } +.#{$ti-prefix}-chevrons-up-left:before { content: $ti-icon-chevrons-up-left; } +.#{$ti-prefix}-chevrons-up-right:before { content: $ti-icon-chevrons-up-right; } +.#{$ti-prefix}-chisel:before { content: $ti-icon-chisel; } +.#{$ti-prefix}-christmas-tree:before { content: $ti-icon-christmas-tree; } +.#{$ti-prefix}-christmas-tree-off:before { content: $ti-icon-christmas-tree-off; } +.#{$ti-prefix}-circle:before { content: $ti-icon-circle; } +.#{$ti-prefix}-circle-0-filled:before { content: $ti-icon-circle-0-filled; } +.#{$ti-prefix}-circle-1-filled:before { content: $ti-icon-circle-1-filled; } +.#{$ti-prefix}-circle-2-filled:before { content: $ti-icon-circle-2-filled; } +.#{$ti-prefix}-circle-3-filled:before { content: $ti-icon-circle-3-filled; } +.#{$ti-prefix}-circle-4-filled:before { content: $ti-icon-circle-4-filled; } +.#{$ti-prefix}-circle-5-filled:before { content: $ti-icon-circle-5-filled; } +.#{$ti-prefix}-circle-6-filled:before { content: $ti-icon-circle-6-filled; } +.#{$ti-prefix}-circle-7-filled:before { content: $ti-icon-circle-7-filled; } +.#{$ti-prefix}-circle-8-filled:before { content: $ti-icon-circle-8-filled; } +.#{$ti-prefix}-circle-9-filled:before { content: $ti-icon-circle-9-filled; } +.#{$ti-prefix}-circle-arrow-down:before { content: $ti-icon-circle-arrow-down; } +.#{$ti-prefix}-circle-arrow-down-filled:before { content: $ti-icon-circle-arrow-down-filled; } +.#{$ti-prefix}-circle-arrow-down-left:before { content: $ti-icon-circle-arrow-down-left; } +.#{$ti-prefix}-circle-arrow-down-left-filled:before { content: $ti-icon-circle-arrow-down-left-filled; } +.#{$ti-prefix}-circle-arrow-down-right:before { content: $ti-icon-circle-arrow-down-right; } +.#{$ti-prefix}-circle-arrow-down-right-filled:before { content: $ti-icon-circle-arrow-down-right-filled; } +.#{$ti-prefix}-circle-arrow-left:before { content: $ti-icon-circle-arrow-left; } +.#{$ti-prefix}-circle-arrow-left-filled:before { content: $ti-icon-circle-arrow-left-filled; } +.#{$ti-prefix}-circle-arrow-right:before { content: $ti-icon-circle-arrow-right; } +.#{$ti-prefix}-circle-arrow-right-filled:before { content: $ti-icon-circle-arrow-right-filled; } +.#{$ti-prefix}-circle-arrow-up:before { content: $ti-icon-circle-arrow-up; } +.#{$ti-prefix}-circle-arrow-up-filled:before { content: $ti-icon-circle-arrow-up-filled; } +.#{$ti-prefix}-circle-arrow-up-left:before { content: $ti-icon-circle-arrow-up-left; } +.#{$ti-prefix}-circle-arrow-up-left-filled:before { content: $ti-icon-circle-arrow-up-left-filled; } +.#{$ti-prefix}-circle-arrow-up-right:before { content: $ti-icon-circle-arrow-up-right; } +.#{$ti-prefix}-circle-arrow-up-right-filled:before { content: $ti-icon-circle-arrow-up-right-filled; } +.#{$ti-prefix}-circle-caret-down:before { content: $ti-icon-circle-caret-down; } +.#{$ti-prefix}-circle-caret-left:before { content: $ti-icon-circle-caret-left; } +.#{$ti-prefix}-circle-caret-right:before { content: $ti-icon-circle-caret-right; } +.#{$ti-prefix}-circle-caret-up:before { content: $ti-icon-circle-caret-up; } +.#{$ti-prefix}-circle-check:before { content: $ti-icon-circle-check; } +.#{$ti-prefix}-circle-check-filled:before { content: $ti-icon-circle-check-filled; } +.#{$ti-prefix}-circle-chevron-down:before { content: $ti-icon-circle-chevron-down; } +.#{$ti-prefix}-circle-chevron-left:before { content: $ti-icon-circle-chevron-left; } +.#{$ti-prefix}-circle-chevron-right:before { content: $ti-icon-circle-chevron-right; } +.#{$ti-prefix}-circle-chevron-up:before { content: $ti-icon-circle-chevron-up; } +.#{$ti-prefix}-circle-chevrons-down:before { content: $ti-icon-circle-chevrons-down; } +.#{$ti-prefix}-circle-chevrons-left:before { content: $ti-icon-circle-chevrons-left; } +.#{$ti-prefix}-circle-chevrons-right:before { content: $ti-icon-circle-chevrons-right; } +.#{$ti-prefix}-circle-chevrons-up:before { content: $ti-icon-circle-chevrons-up; } +.#{$ti-prefix}-circle-dashed:before { content: $ti-icon-circle-dashed; } +.#{$ti-prefix}-circle-dot:before { content: $ti-icon-circle-dot; } +.#{$ti-prefix}-circle-dot-filled:before { content: $ti-icon-circle-dot-filled; } +.#{$ti-prefix}-circle-dotted:before { content: $ti-icon-circle-dotted; } +.#{$ti-prefix}-circle-filled:before { content: $ti-icon-circle-filled; } +.#{$ti-prefix}-circle-half:before { content: $ti-icon-circle-half; } +.#{$ti-prefix}-circle-half-2:before { content: $ti-icon-circle-half-2; } +.#{$ti-prefix}-circle-half-vertical:before { content: $ti-icon-circle-half-vertical; } +.#{$ti-prefix}-circle-key:before { content: $ti-icon-circle-key; } +.#{$ti-prefix}-circle-key-filled:before { content: $ti-icon-circle-key-filled; } +.#{$ti-prefix}-circle-letter-a:before { content: $ti-icon-circle-letter-a; } +.#{$ti-prefix}-circle-letter-b:before { content: $ti-icon-circle-letter-b; } +.#{$ti-prefix}-circle-letter-c:before { content: $ti-icon-circle-letter-c; } +.#{$ti-prefix}-circle-letter-d:before { content: $ti-icon-circle-letter-d; } +.#{$ti-prefix}-circle-letter-e:before { content: $ti-icon-circle-letter-e; } +.#{$ti-prefix}-circle-letter-f:before { content: $ti-icon-circle-letter-f; } +.#{$ti-prefix}-circle-letter-g:before { content: $ti-icon-circle-letter-g; } +.#{$ti-prefix}-circle-letter-h:before { content: $ti-icon-circle-letter-h; } +.#{$ti-prefix}-circle-letter-i:before { content: $ti-icon-circle-letter-i; } +.#{$ti-prefix}-circle-letter-j:before { content: $ti-icon-circle-letter-j; } +.#{$ti-prefix}-circle-letter-k:before { content: $ti-icon-circle-letter-k; } +.#{$ti-prefix}-circle-letter-l:before { content: $ti-icon-circle-letter-l; } +.#{$ti-prefix}-circle-letter-m:before { content: $ti-icon-circle-letter-m; } +.#{$ti-prefix}-circle-letter-n:before { content: $ti-icon-circle-letter-n; } +.#{$ti-prefix}-circle-letter-o:before { content: $ti-icon-circle-letter-o; } +.#{$ti-prefix}-circle-letter-p:before { content: $ti-icon-circle-letter-p; } +.#{$ti-prefix}-circle-letter-q:before { content: $ti-icon-circle-letter-q; } +.#{$ti-prefix}-circle-letter-r:before { content: $ti-icon-circle-letter-r; } +.#{$ti-prefix}-circle-letter-s:before { content: $ti-icon-circle-letter-s; } +.#{$ti-prefix}-circle-letter-t:before { content: $ti-icon-circle-letter-t; } +.#{$ti-prefix}-circle-letter-u:before { content: $ti-icon-circle-letter-u; } +.#{$ti-prefix}-circle-letter-v:before { content: $ti-icon-circle-letter-v; } +.#{$ti-prefix}-circle-letter-w:before { content: $ti-icon-circle-letter-w; } +.#{$ti-prefix}-circle-letter-x:before { content: $ti-icon-circle-letter-x; } +.#{$ti-prefix}-circle-letter-y:before { content: $ti-icon-circle-letter-y; } +.#{$ti-prefix}-circle-letter-z:before { content: $ti-icon-circle-letter-z; } +.#{$ti-prefix}-circle-minus:before { content: $ti-icon-circle-minus; } +.#{$ti-prefix}-circle-number-0:before { content: $ti-icon-circle-number-0; } +.#{$ti-prefix}-circle-number-1:before { content: $ti-icon-circle-number-1; } +.#{$ti-prefix}-circle-number-2:before { content: $ti-icon-circle-number-2; } +.#{$ti-prefix}-circle-number-3:before { content: $ti-icon-circle-number-3; } +.#{$ti-prefix}-circle-number-4:before { content: $ti-icon-circle-number-4; } +.#{$ti-prefix}-circle-number-5:before { content: $ti-icon-circle-number-5; } +.#{$ti-prefix}-circle-number-6:before { content: $ti-icon-circle-number-6; } +.#{$ti-prefix}-circle-number-7:before { content: $ti-icon-circle-number-7; } +.#{$ti-prefix}-circle-number-8:before { content: $ti-icon-circle-number-8; } +.#{$ti-prefix}-circle-number-9:before { content: $ti-icon-circle-number-9; } +.#{$ti-prefix}-circle-off:before { content: $ti-icon-circle-off; } +.#{$ti-prefix}-circle-plus:before { content: $ti-icon-circle-plus; } +.#{$ti-prefix}-circle-rectangle:before { content: $ti-icon-circle-rectangle; } +.#{$ti-prefix}-circle-rectangle-off:before { content: $ti-icon-circle-rectangle-off; } +.#{$ti-prefix}-circle-square:before { content: $ti-icon-circle-square; } +.#{$ti-prefix}-circle-triangle:before { content: $ti-icon-circle-triangle; } +.#{$ti-prefix}-circle-x:before { content: $ti-icon-circle-x; } +.#{$ti-prefix}-circle-x-filled:before { content: $ti-icon-circle-x-filled; } +.#{$ti-prefix}-circles:before { content: $ti-icon-circles; } +.#{$ti-prefix}-circles-filled:before { content: $ti-icon-circles-filled; } +.#{$ti-prefix}-circles-relation:before { content: $ti-icon-circles-relation; } +.#{$ti-prefix}-circuit-ammeter:before { content: $ti-icon-circuit-ammeter; } +.#{$ti-prefix}-circuit-battery:before { content: $ti-icon-circuit-battery; } +.#{$ti-prefix}-circuit-bulb:before { content: $ti-icon-circuit-bulb; } +.#{$ti-prefix}-circuit-capacitor:before { content: $ti-icon-circuit-capacitor; } +.#{$ti-prefix}-circuit-capacitor-polarized:before { content: $ti-icon-circuit-capacitor-polarized; } +.#{$ti-prefix}-circuit-cell:before { content: $ti-icon-circuit-cell; } +.#{$ti-prefix}-circuit-cell-plus:before { content: $ti-icon-circuit-cell-plus; } +.#{$ti-prefix}-circuit-changeover:before { content: $ti-icon-circuit-changeover; } +.#{$ti-prefix}-circuit-diode:before { content: $ti-icon-circuit-diode; } +.#{$ti-prefix}-circuit-diode-zener:before { content: $ti-icon-circuit-diode-zener; } +.#{$ti-prefix}-circuit-ground:before { content: $ti-icon-circuit-ground; } +.#{$ti-prefix}-circuit-ground-digital:before { content: $ti-icon-circuit-ground-digital; } +.#{$ti-prefix}-circuit-inductor:before { content: $ti-icon-circuit-inductor; } +.#{$ti-prefix}-circuit-motor:before { content: $ti-icon-circuit-motor; } +.#{$ti-prefix}-circuit-pushbutton:before { content: $ti-icon-circuit-pushbutton; } +.#{$ti-prefix}-circuit-resistor:before { content: $ti-icon-circuit-resistor; } +.#{$ti-prefix}-circuit-switch-closed:before { content: $ti-icon-circuit-switch-closed; } +.#{$ti-prefix}-circuit-switch-open:before { content: $ti-icon-circuit-switch-open; } +.#{$ti-prefix}-circuit-voltmeter:before { content: $ti-icon-circuit-voltmeter; } +.#{$ti-prefix}-clear-all:before { content: $ti-icon-clear-all; } +.#{$ti-prefix}-clear-formatting:before { content: $ti-icon-clear-formatting; } +.#{$ti-prefix}-click:before { content: $ti-icon-click; } +.#{$ti-prefix}-clipboard:before { content: $ti-icon-clipboard; } +.#{$ti-prefix}-clipboard-check:before { content: $ti-icon-clipboard-check; } +.#{$ti-prefix}-clipboard-copy:before { content: $ti-icon-clipboard-copy; } +.#{$ti-prefix}-clipboard-data:before { content: $ti-icon-clipboard-data; } +.#{$ti-prefix}-clipboard-heart:before { content: $ti-icon-clipboard-heart; } +.#{$ti-prefix}-clipboard-list:before { content: $ti-icon-clipboard-list; } +.#{$ti-prefix}-clipboard-off:before { content: $ti-icon-clipboard-off; } +.#{$ti-prefix}-clipboard-plus:before { content: $ti-icon-clipboard-plus; } +.#{$ti-prefix}-clipboard-text:before { content: $ti-icon-clipboard-text; } +.#{$ti-prefix}-clipboard-typography:before { content: $ti-icon-clipboard-typography; } +.#{$ti-prefix}-clipboard-x:before { content: $ti-icon-clipboard-x; } +.#{$ti-prefix}-clock:before { content: $ti-icon-clock; } +.#{$ti-prefix}-clock-2:before { content: $ti-icon-clock-2; } +.#{$ti-prefix}-clock-bolt:before { content: $ti-icon-clock-bolt; } +.#{$ti-prefix}-clock-cancel:before { content: $ti-icon-clock-cancel; } +.#{$ti-prefix}-clock-check:before { content: $ti-icon-clock-check; } +.#{$ti-prefix}-clock-code:before { content: $ti-icon-clock-code; } +.#{$ti-prefix}-clock-cog:before { content: $ti-icon-clock-cog; } +.#{$ti-prefix}-clock-dollar:before { content: $ti-icon-clock-dollar; } +.#{$ti-prefix}-clock-down:before { content: $ti-icon-clock-down; } +.#{$ti-prefix}-clock-edit:before { content: $ti-icon-clock-edit; } +.#{$ti-prefix}-clock-exclamation:before { content: $ti-icon-clock-exclamation; } +.#{$ti-prefix}-clock-filled:before { content: $ti-icon-clock-filled; } +.#{$ti-prefix}-clock-heart:before { content: $ti-icon-clock-heart; } +.#{$ti-prefix}-clock-hour-1:before { content: $ti-icon-clock-hour-1; } +.#{$ti-prefix}-clock-hour-10:before { content: $ti-icon-clock-hour-10; } +.#{$ti-prefix}-clock-hour-11:before { content: $ti-icon-clock-hour-11; } +.#{$ti-prefix}-clock-hour-12:before { content: $ti-icon-clock-hour-12; } +.#{$ti-prefix}-clock-hour-2:before { content: $ti-icon-clock-hour-2; } +.#{$ti-prefix}-clock-hour-3:before { content: $ti-icon-clock-hour-3; } +.#{$ti-prefix}-clock-hour-4:before { content: $ti-icon-clock-hour-4; } +.#{$ti-prefix}-clock-hour-5:before { content: $ti-icon-clock-hour-5; } +.#{$ti-prefix}-clock-hour-6:before { content: $ti-icon-clock-hour-6; } +.#{$ti-prefix}-clock-hour-7:before { content: $ti-icon-clock-hour-7; } +.#{$ti-prefix}-clock-hour-8:before { content: $ti-icon-clock-hour-8; } +.#{$ti-prefix}-clock-hour-9:before { content: $ti-icon-clock-hour-9; } +.#{$ti-prefix}-clock-minus:before { content: $ti-icon-clock-minus; } +.#{$ti-prefix}-clock-off:before { content: $ti-icon-clock-off; } +.#{$ti-prefix}-clock-pause:before { content: $ti-icon-clock-pause; } +.#{$ti-prefix}-clock-pin:before { content: $ti-icon-clock-pin; } +.#{$ti-prefix}-clock-play:before { content: $ti-icon-clock-play; } +.#{$ti-prefix}-clock-plus:before { content: $ti-icon-clock-plus; } +.#{$ti-prefix}-clock-question:before { content: $ti-icon-clock-question; } +.#{$ti-prefix}-clock-record:before { content: $ti-icon-clock-record; } +.#{$ti-prefix}-clock-search:before { content: $ti-icon-clock-search; } +.#{$ti-prefix}-clock-share:before { content: $ti-icon-clock-share; } +.#{$ti-prefix}-clock-shield:before { content: $ti-icon-clock-shield; } +.#{$ti-prefix}-clock-star:before { content: $ti-icon-clock-star; } +.#{$ti-prefix}-clock-stop:before { content: $ti-icon-clock-stop; } +.#{$ti-prefix}-clock-up:before { content: $ti-icon-clock-up; } +.#{$ti-prefix}-clock-x:before { content: $ti-icon-clock-x; } +.#{$ti-prefix}-clothes-rack:before { content: $ti-icon-clothes-rack; } +.#{$ti-prefix}-clothes-rack-off:before { content: $ti-icon-clothes-rack-off; } +.#{$ti-prefix}-cloud:before { content: $ti-icon-cloud; } +.#{$ti-prefix}-cloud-bolt:before { content: $ti-icon-cloud-bolt; } +.#{$ti-prefix}-cloud-cancel:before { content: $ti-icon-cloud-cancel; } +.#{$ti-prefix}-cloud-check:before { content: $ti-icon-cloud-check; } +.#{$ti-prefix}-cloud-code:before { content: $ti-icon-cloud-code; } +.#{$ti-prefix}-cloud-cog:before { content: $ti-icon-cloud-cog; } +.#{$ti-prefix}-cloud-computing:before { content: $ti-icon-cloud-computing; } +.#{$ti-prefix}-cloud-data-connection:before { content: $ti-icon-cloud-data-connection; } +.#{$ti-prefix}-cloud-dollar:before { content: $ti-icon-cloud-dollar; } +.#{$ti-prefix}-cloud-down:before { content: $ti-icon-cloud-down; } +.#{$ti-prefix}-cloud-download:before { content: $ti-icon-cloud-download; } +.#{$ti-prefix}-cloud-exclamation:before { content: $ti-icon-cloud-exclamation; } +.#{$ti-prefix}-cloud-filled:before { content: $ti-icon-cloud-filled; } +.#{$ti-prefix}-cloud-fog:before { content: $ti-icon-cloud-fog; } +.#{$ti-prefix}-cloud-heart:before { content: $ti-icon-cloud-heart; } +.#{$ti-prefix}-cloud-lock:before { content: $ti-icon-cloud-lock; } +.#{$ti-prefix}-cloud-lock-open:before { content: $ti-icon-cloud-lock-open; } +.#{$ti-prefix}-cloud-minus:before { content: $ti-icon-cloud-minus; } +.#{$ti-prefix}-cloud-off:before { content: $ti-icon-cloud-off; } +.#{$ti-prefix}-cloud-pause:before { content: $ti-icon-cloud-pause; } +.#{$ti-prefix}-cloud-pin:before { content: $ti-icon-cloud-pin; } +.#{$ti-prefix}-cloud-plus:before { content: $ti-icon-cloud-plus; } +.#{$ti-prefix}-cloud-question:before { content: $ti-icon-cloud-question; } +.#{$ti-prefix}-cloud-rain:before { content: $ti-icon-cloud-rain; } +.#{$ti-prefix}-cloud-search:before { content: $ti-icon-cloud-search; } +.#{$ti-prefix}-cloud-share:before { content: $ti-icon-cloud-share; } +.#{$ti-prefix}-cloud-snow:before { content: $ti-icon-cloud-snow; } +.#{$ti-prefix}-cloud-star:before { content: $ti-icon-cloud-star; } +.#{$ti-prefix}-cloud-storm:before { content: $ti-icon-cloud-storm; } +.#{$ti-prefix}-cloud-up:before { content: $ti-icon-cloud-up; } +.#{$ti-prefix}-cloud-upload:before { content: $ti-icon-cloud-upload; } +.#{$ti-prefix}-cloud-x:before { content: $ti-icon-cloud-x; } +.#{$ti-prefix}-clover:before { content: $ti-icon-clover; } +.#{$ti-prefix}-clover-2:before { content: $ti-icon-clover-2; } +.#{$ti-prefix}-clubs:before { content: $ti-icon-clubs; } +.#{$ti-prefix}-clubs-filled:before { content: $ti-icon-clubs-filled; } +.#{$ti-prefix}-code:before { content: $ti-icon-code; } +.#{$ti-prefix}-code-asterix:before { content: $ti-icon-code-asterix; } +.#{$ti-prefix}-code-circle:before { content: $ti-icon-code-circle; } +.#{$ti-prefix}-code-circle-2:before { content: $ti-icon-code-circle-2; } +.#{$ti-prefix}-code-dots:before { content: $ti-icon-code-dots; } +.#{$ti-prefix}-code-minus:before { content: $ti-icon-code-minus; } +.#{$ti-prefix}-code-off:before { content: $ti-icon-code-off; } +.#{$ti-prefix}-code-plus:before { content: $ti-icon-code-plus; } +.#{$ti-prefix}-coffee:before { content: $ti-icon-coffee; } +.#{$ti-prefix}-coffee-off:before { content: $ti-icon-coffee-off; } +.#{$ti-prefix}-coffin:before { content: $ti-icon-coffin; } +.#{$ti-prefix}-coin:before { content: $ti-icon-coin; } +.#{$ti-prefix}-coin-bitcoin:before { content: $ti-icon-coin-bitcoin; } +.#{$ti-prefix}-coin-euro:before { content: $ti-icon-coin-euro; } +.#{$ti-prefix}-coin-monero:before { content: $ti-icon-coin-monero; } +.#{$ti-prefix}-coin-off:before { content: $ti-icon-coin-off; } +.#{$ti-prefix}-coin-pound:before { content: $ti-icon-coin-pound; } +.#{$ti-prefix}-coin-rupee:before { content: $ti-icon-coin-rupee; } +.#{$ti-prefix}-coin-yen:before { content: $ti-icon-coin-yen; } +.#{$ti-prefix}-coin-yuan:before { content: $ti-icon-coin-yuan; } +.#{$ti-prefix}-coins:before { content: $ti-icon-coins; } +.#{$ti-prefix}-color-filter:before { content: $ti-icon-color-filter; } +.#{$ti-prefix}-color-picker:before { content: $ti-icon-color-picker; } +.#{$ti-prefix}-color-picker-off:before { content: $ti-icon-color-picker-off; } +.#{$ti-prefix}-color-swatch:before { content: $ti-icon-color-swatch; } +.#{$ti-prefix}-color-swatch-off:before { content: $ti-icon-color-swatch-off; } +.#{$ti-prefix}-column-insert-left:before { content: $ti-icon-column-insert-left; } +.#{$ti-prefix}-column-insert-right:before { content: $ti-icon-column-insert-right; } +.#{$ti-prefix}-columns:before { content: $ti-icon-columns; } +.#{$ti-prefix}-columns-1:before { content: $ti-icon-columns-1; } +.#{$ti-prefix}-columns-2:before { content: $ti-icon-columns-2; } +.#{$ti-prefix}-columns-3:before { content: $ti-icon-columns-3; } +.#{$ti-prefix}-columns-off:before { content: $ti-icon-columns-off; } +.#{$ti-prefix}-comet:before { content: $ti-icon-comet; } +.#{$ti-prefix}-command:before { content: $ti-icon-command; } +.#{$ti-prefix}-command-off:before { content: $ti-icon-command-off; } +.#{$ti-prefix}-compass:before { content: $ti-icon-compass; } +.#{$ti-prefix}-compass-off:before { content: $ti-icon-compass-off; } +.#{$ti-prefix}-components:before { content: $ti-icon-components; } +.#{$ti-prefix}-components-off:before { content: $ti-icon-components-off; } +.#{$ti-prefix}-cone:before { content: $ti-icon-cone; } +.#{$ti-prefix}-cone-2:before { content: $ti-icon-cone-2; } +.#{$ti-prefix}-cone-off:before { content: $ti-icon-cone-off; } +.#{$ti-prefix}-confetti:before { content: $ti-icon-confetti; } +.#{$ti-prefix}-confetti-off:before { content: $ti-icon-confetti-off; } +.#{$ti-prefix}-confucius:before { content: $ti-icon-confucius; } +.#{$ti-prefix}-container:before { content: $ti-icon-container; } +.#{$ti-prefix}-container-off:before { content: $ti-icon-container-off; } +.#{$ti-prefix}-contrast:before { content: $ti-icon-contrast; } +.#{$ti-prefix}-contrast-2:before { content: $ti-icon-contrast-2; } +.#{$ti-prefix}-contrast-2-off:before { content: $ti-icon-contrast-2-off; } +.#{$ti-prefix}-contrast-off:before { content: $ti-icon-contrast-off; } +.#{$ti-prefix}-cooker:before { content: $ti-icon-cooker; } +.#{$ti-prefix}-cookie:before { content: $ti-icon-cookie; } +.#{$ti-prefix}-cookie-man:before { content: $ti-icon-cookie-man; } +.#{$ti-prefix}-cookie-off:before { content: $ti-icon-cookie-off; } +.#{$ti-prefix}-copy:before { content: $ti-icon-copy; } +.#{$ti-prefix}-copy-off:before { content: $ti-icon-copy-off; } +.#{$ti-prefix}-copyleft:before { content: $ti-icon-copyleft; } +.#{$ti-prefix}-copyleft-filled:before { content: $ti-icon-copyleft-filled; } +.#{$ti-prefix}-copyleft-off:before { content: $ti-icon-copyleft-off; } +.#{$ti-prefix}-copyright:before { content: $ti-icon-copyright; } +.#{$ti-prefix}-copyright-filled:before { content: $ti-icon-copyright-filled; } +.#{$ti-prefix}-copyright-off:before { content: $ti-icon-copyright-off; } +.#{$ti-prefix}-corner-down-left:before { content: $ti-icon-corner-down-left; } +.#{$ti-prefix}-corner-down-left-double:before { content: $ti-icon-corner-down-left-double; } +.#{$ti-prefix}-corner-down-right:before { content: $ti-icon-corner-down-right; } +.#{$ti-prefix}-corner-down-right-double:before { content: $ti-icon-corner-down-right-double; } +.#{$ti-prefix}-corner-left-down:before { content: $ti-icon-corner-left-down; } +.#{$ti-prefix}-corner-left-down-double:before { content: $ti-icon-corner-left-down-double; } +.#{$ti-prefix}-corner-left-up:before { content: $ti-icon-corner-left-up; } +.#{$ti-prefix}-corner-left-up-double:before { content: $ti-icon-corner-left-up-double; } +.#{$ti-prefix}-corner-right-down:before { content: $ti-icon-corner-right-down; } +.#{$ti-prefix}-corner-right-down-double:before { content: $ti-icon-corner-right-down-double; } +.#{$ti-prefix}-corner-right-up:before { content: $ti-icon-corner-right-up; } +.#{$ti-prefix}-corner-right-up-double:before { content: $ti-icon-corner-right-up-double; } +.#{$ti-prefix}-corner-up-left:before { content: $ti-icon-corner-up-left; } +.#{$ti-prefix}-corner-up-left-double:before { content: $ti-icon-corner-up-left-double; } +.#{$ti-prefix}-corner-up-right:before { content: $ti-icon-corner-up-right; } +.#{$ti-prefix}-corner-up-right-double:before { content: $ti-icon-corner-up-right-double; } +.#{$ti-prefix}-cpu:before { content: $ti-icon-cpu; } +.#{$ti-prefix}-cpu-2:before { content: $ti-icon-cpu-2; } +.#{$ti-prefix}-cpu-off:before { content: $ti-icon-cpu-off; } +.#{$ti-prefix}-crane:before { content: $ti-icon-crane; } +.#{$ti-prefix}-crane-off:before { content: $ti-icon-crane-off; } +.#{$ti-prefix}-creative-commons:before { content: $ti-icon-creative-commons; } +.#{$ti-prefix}-creative-commons-by:before { content: $ti-icon-creative-commons-by; } +.#{$ti-prefix}-creative-commons-nc:before { content: $ti-icon-creative-commons-nc; } +.#{$ti-prefix}-creative-commons-nd:before { content: $ti-icon-creative-commons-nd; } +.#{$ti-prefix}-creative-commons-off:before { content: $ti-icon-creative-commons-off; } +.#{$ti-prefix}-creative-commons-sa:before { content: $ti-icon-creative-commons-sa; } +.#{$ti-prefix}-creative-commons-zero:before { content: $ti-icon-creative-commons-zero; } +.#{$ti-prefix}-credit-card:before { content: $ti-icon-credit-card; } +.#{$ti-prefix}-credit-card-off:before { content: $ti-icon-credit-card-off; } +.#{$ti-prefix}-cricket:before { content: $ti-icon-cricket; } +.#{$ti-prefix}-crop:before { content: $ti-icon-crop; } +.#{$ti-prefix}-cross:before { content: $ti-icon-cross; } +.#{$ti-prefix}-cross-filled:before { content: $ti-icon-cross-filled; } +.#{$ti-prefix}-cross-off:before { content: $ti-icon-cross-off; } +.#{$ti-prefix}-crosshair:before { content: $ti-icon-crosshair; } +.#{$ti-prefix}-crown:before { content: $ti-icon-crown; } +.#{$ti-prefix}-crown-off:before { content: $ti-icon-crown-off; } +.#{$ti-prefix}-crutches:before { content: $ti-icon-crutches; } +.#{$ti-prefix}-crutches-off:before { content: $ti-icon-crutches-off; } +.#{$ti-prefix}-crystal-ball:before { content: $ti-icon-crystal-ball; } +.#{$ti-prefix}-csv:before { content: $ti-icon-csv; } +.#{$ti-prefix}-cube-send:before { content: $ti-icon-cube-send; } +.#{$ti-prefix}-cube-unfolded:before { content: $ti-icon-cube-unfolded; } +.#{$ti-prefix}-cup:before { content: $ti-icon-cup; } +.#{$ti-prefix}-cup-off:before { content: $ti-icon-cup-off; } +.#{$ti-prefix}-curling:before { content: $ti-icon-curling; } +.#{$ti-prefix}-curly-loop:before { content: $ti-icon-curly-loop; } +.#{$ti-prefix}-currency:before { content: $ti-icon-currency; } +.#{$ti-prefix}-currency-afghani:before { content: $ti-icon-currency-afghani; } +.#{$ti-prefix}-currency-bahraini:before { content: $ti-icon-currency-bahraini; } +.#{$ti-prefix}-currency-baht:before { content: $ti-icon-currency-baht; } +.#{$ti-prefix}-currency-bitcoin:before { content: $ti-icon-currency-bitcoin; } +.#{$ti-prefix}-currency-cent:before { content: $ti-icon-currency-cent; } +.#{$ti-prefix}-currency-dinar:before { content: $ti-icon-currency-dinar; } +.#{$ti-prefix}-currency-dirham:before { content: $ti-icon-currency-dirham; } +.#{$ti-prefix}-currency-dogecoin:before { content: $ti-icon-currency-dogecoin; } +.#{$ti-prefix}-currency-dollar:before { content: $ti-icon-currency-dollar; } +.#{$ti-prefix}-currency-dollar-australian:before { content: $ti-icon-currency-dollar-australian; } +.#{$ti-prefix}-currency-dollar-brunei:before { content: $ti-icon-currency-dollar-brunei; } +.#{$ti-prefix}-currency-dollar-canadian:before { content: $ti-icon-currency-dollar-canadian; } +.#{$ti-prefix}-currency-dollar-guyanese:before { content: $ti-icon-currency-dollar-guyanese; } +.#{$ti-prefix}-currency-dollar-off:before { content: $ti-icon-currency-dollar-off; } +.#{$ti-prefix}-currency-dollar-singapore:before { content: $ti-icon-currency-dollar-singapore; } +.#{$ti-prefix}-currency-dollar-zimbabwean:before { content: $ti-icon-currency-dollar-zimbabwean; } +.#{$ti-prefix}-currency-dong:before { content: $ti-icon-currency-dong; } +.#{$ti-prefix}-currency-dram:before { content: $ti-icon-currency-dram; } +.#{$ti-prefix}-currency-ethereum:before { content: $ti-icon-currency-ethereum; } +.#{$ti-prefix}-currency-euro:before { content: $ti-icon-currency-euro; } +.#{$ti-prefix}-currency-euro-off:before { content: $ti-icon-currency-euro-off; } +.#{$ti-prefix}-currency-forint:before { content: $ti-icon-currency-forint; } +.#{$ti-prefix}-currency-frank:before { content: $ti-icon-currency-frank; } +.#{$ti-prefix}-currency-guarani:before { content: $ti-icon-currency-guarani; } +.#{$ti-prefix}-currency-hryvnia:before { content: $ti-icon-currency-hryvnia; } +.#{$ti-prefix}-currency-kip:before { content: $ti-icon-currency-kip; } +.#{$ti-prefix}-currency-krone-czech:before { content: $ti-icon-currency-krone-czech; } +.#{$ti-prefix}-currency-krone-danish:before { content: $ti-icon-currency-krone-danish; } +.#{$ti-prefix}-currency-krone-swedish:before { content: $ti-icon-currency-krone-swedish; } +.#{$ti-prefix}-currency-lari:before { content: $ti-icon-currency-lari; } +.#{$ti-prefix}-currency-leu:before { content: $ti-icon-currency-leu; } +.#{$ti-prefix}-currency-lira:before { content: $ti-icon-currency-lira; } +.#{$ti-prefix}-currency-litecoin:before { content: $ti-icon-currency-litecoin; } +.#{$ti-prefix}-currency-lyd:before { content: $ti-icon-currency-lyd; } +.#{$ti-prefix}-currency-manat:before { content: $ti-icon-currency-manat; } +.#{$ti-prefix}-currency-monero:before { content: $ti-icon-currency-monero; } +.#{$ti-prefix}-currency-naira:before { content: $ti-icon-currency-naira; } +.#{$ti-prefix}-currency-nano:before { content: $ti-icon-currency-nano; } +.#{$ti-prefix}-currency-off:before { content: $ti-icon-currency-off; } +.#{$ti-prefix}-currency-paanga:before { content: $ti-icon-currency-paanga; } +.#{$ti-prefix}-currency-peso:before { content: $ti-icon-currency-peso; } +.#{$ti-prefix}-currency-pound:before { content: $ti-icon-currency-pound; } +.#{$ti-prefix}-currency-pound-off:before { content: $ti-icon-currency-pound-off; } +.#{$ti-prefix}-currency-quetzal:before { content: $ti-icon-currency-quetzal; } +.#{$ti-prefix}-currency-real:before { content: $ti-icon-currency-real; } +.#{$ti-prefix}-currency-renminbi:before { content: $ti-icon-currency-renminbi; } +.#{$ti-prefix}-currency-ripple:before { content: $ti-icon-currency-ripple; } +.#{$ti-prefix}-currency-riyal:before { content: $ti-icon-currency-riyal; } +.#{$ti-prefix}-currency-rubel:before { content: $ti-icon-currency-rubel; } +.#{$ti-prefix}-currency-rufiyaa:before { content: $ti-icon-currency-rufiyaa; } +.#{$ti-prefix}-currency-rupee:before { content: $ti-icon-currency-rupee; } +.#{$ti-prefix}-currency-rupee-nepalese:before { content: $ti-icon-currency-rupee-nepalese; } +.#{$ti-prefix}-currency-shekel:before { content: $ti-icon-currency-shekel; } +.#{$ti-prefix}-currency-solana:before { content: $ti-icon-currency-solana; } +.#{$ti-prefix}-currency-som:before { content: $ti-icon-currency-som; } +.#{$ti-prefix}-currency-taka:before { content: $ti-icon-currency-taka; } +.#{$ti-prefix}-currency-tenge:before { content: $ti-icon-currency-tenge; } +.#{$ti-prefix}-currency-tugrik:before { content: $ti-icon-currency-tugrik; } +.#{$ti-prefix}-currency-won:before { content: $ti-icon-currency-won; } +.#{$ti-prefix}-currency-yen:before { content: $ti-icon-currency-yen; } +.#{$ti-prefix}-currency-yen-off:before { content: $ti-icon-currency-yen-off; } +.#{$ti-prefix}-currency-yuan:before { content: $ti-icon-currency-yuan; } +.#{$ti-prefix}-currency-zloty:before { content: $ti-icon-currency-zloty; } +.#{$ti-prefix}-current-location:before { content: $ti-icon-current-location; } +.#{$ti-prefix}-current-location-off:before { content: $ti-icon-current-location-off; } +.#{$ti-prefix}-cursor-off:before { content: $ti-icon-cursor-off; } +.#{$ti-prefix}-cursor-text:before { content: $ti-icon-cursor-text; } +.#{$ti-prefix}-cut:before { content: $ti-icon-cut; } +.#{$ti-prefix}-cylinder:before { content: $ti-icon-cylinder; } +.#{$ti-prefix}-dashboard:before { content: $ti-icon-dashboard; } +.#{$ti-prefix}-dashboard-off:before { content: $ti-icon-dashboard-off; } +.#{$ti-prefix}-database:before { content: $ti-icon-database; } +.#{$ti-prefix}-database-export:before { content: $ti-icon-database-export; } +.#{$ti-prefix}-database-import:before { content: $ti-icon-database-import; } +.#{$ti-prefix}-database-off:before { content: $ti-icon-database-off; } +.#{$ti-prefix}-deer:before { content: $ti-icon-deer; } +.#{$ti-prefix}-delta:before { content: $ti-icon-delta; } +.#{$ti-prefix}-dental:before { content: $ti-icon-dental; } +.#{$ti-prefix}-dental-broken:before { content: $ti-icon-dental-broken; } +.#{$ti-prefix}-dental-off:before { content: $ti-icon-dental-off; } +.#{$ti-prefix}-deselect:before { content: $ti-icon-deselect; } +.#{$ti-prefix}-details:before { content: $ti-icon-details; } +.#{$ti-prefix}-details-off:before { content: $ti-icon-details-off; } +.#{$ti-prefix}-device-airpods:before { content: $ti-icon-device-airpods; } +.#{$ti-prefix}-device-airpods-case:before { content: $ti-icon-device-airpods-case; } +.#{$ti-prefix}-device-analytics:before { content: $ti-icon-device-analytics; } +.#{$ti-prefix}-device-audio-tape:before { content: $ti-icon-device-audio-tape; } +.#{$ti-prefix}-device-camera-phone:before { content: $ti-icon-device-camera-phone; } +.#{$ti-prefix}-device-cctv:before { content: $ti-icon-device-cctv; } +.#{$ti-prefix}-device-cctv-off:before { content: $ti-icon-device-cctv-off; } +.#{$ti-prefix}-device-computer-camera:before { content: $ti-icon-device-computer-camera; } +.#{$ti-prefix}-device-computer-camera-off:before { content: $ti-icon-device-computer-camera-off; } +.#{$ti-prefix}-device-desktop:before { content: $ti-icon-device-desktop; } +.#{$ti-prefix}-device-desktop-analytics:before { content: $ti-icon-device-desktop-analytics; } +.#{$ti-prefix}-device-desktop-bolt:before { content: $ti-icon-device-desktop-bolt; } +.#{$ti-prefix}-device-desktop-cancel:before { content: $ti-icon-device-desktop-cancel; } +.#{$ti-prefix}-device-desktop-check:before { content: $ti-icon-device-desktop-check; } +.#{$ti-prefix}-device-desktop-code:before { content: $ti-icon-device-desktop-code; } +.#{$ti-prefix}-device-desktop-cog:before { content: $ti-icon-device-desktop-cog; } +.#{$ti-prefix}-device-desktop-dollar:before { content: $ti-icon-device-desktop-dollar; } +.#{$ti-prefix}-device-desktop-down:before { content: $ti-icon-device-desktop-down; } +.#{$ti-prefix}-device-desktop-exclamation:before { content: $ti-icon-device-desktop-exclamation; } +.#{$ti-prefix}-device-desktop-heart:before { content: $ti-icon-device-desktop-heart; } +.#{$ti-prefix}-device-desktop-minus:before { content: $ti-icon-device-desktop-minus; } +.#{$ti-prefix}-device-desktop-off:before { content: $ti-icon-device-desktop-off; } +.#{$ti-prefix}-device-desktop-pause:before { content: $ti-icon-device-desktop-pause; } +.#{$ti-prefix}-device-desktop-pin:before { content: $ti-icon-device-desktop-pin; } +.#{$ti-prefix}-device-desktop-plus:before { content: $ti-icon-device-desktop-plus; } +.#{$ti-prefix}-device-desktop-question:before { content: $ti-icon-device-desktop-question; } +.#{$ti-prefix}-device-desktop-search:before { content: $ti-icon-device-desktop-search; } +.#{$ti-prefix}-device-desktop-share:before { content: $ti-icon-device-desktop-share; } +.#{$ti-prefix}-device-desktop-star:before { content: $ti-icon-device-desktop-star; } +.#{$ti-prefix}-device-desktop-up:before { content: $ti-icon-device-desktop-up; } +.#{$ti-prefix}-device-desktop-x:before { content: $ti-icon-device-desktop-x; } +.#{$ti-prefix}-device-floppy:before { content: $ti-icon-device-floppy; } +.#{$ti-prefix}-device-gamepad:before { content: $ti-icon-device-gamepad; } +.#{$ti-prefix}-device-gamepad-2:before { content: $ti-icon-device-gamepad-2; } +.#{$ti-prefix}-device-heart-monitor:before { content: $ti-icon-device-heart-monitor; } +.#{$ti-prefix}-device-imac:before { content: $ti-icon-device-imac; } +.#{$ti-prefix}-device-imac-bolt:before { content: $ti-icon-device-imac-bolt; } +.#{$ti-prefix}-device-imac-cancel:before { content: $ti-icon-device-imac-cancel; } +.#{$ti-prefix}-device-imac-check:before { content: $ti-icon-device-imac-check; } +.#{$ti-prefix}-device-imac-code:before { content: $ti-icon-device-imac-code; } +.#{$ti-prefix}-device-imac-cog:before { content: $ti-icon-device-imac-cog; } +.#{$ti-prefix}-device-imac-dollar:before { content: $ti-icon-device-imac-dollar; } +.#{$ti-prefix}-device-imac-down:before { content: $ti-icon-device-imac-down; } +.#{$ti-prefix}-device-imac-exclamation:before { content: $ti-icon-device-imac-exclamation; } +.#{$ti-prefix}-device-imac-heart:before { content: $ti-icon-device-imac-heart; } +.#{$ti-prefix}-device-imac-minus:before { content: $ti-icon-device-imac-minus; } +.#{$ti-prefix}-device-imac-off:before { content: $ti-icon-device-imac-off; } +.#{$ti-prefix}-device-imac-pause:before { content: $ti-icon-device-imac-pause; } +.#{$ti-prefix}-device-imac-pin:before { content: $ti-icon-device-imac-pin; } +.#{$ti-prefix}-device-imac-plus:before { content: $ti-icon-device-imac-plus; } +.#{$ti-prefix}-device-imac-question:before { content: $ti-icon-device-imac-question; } +.#{$ti-prefix}-device-imac-search:before { content: $ti-icon-device-imac-search; } +.#{$ti-prefix}-device-imac-share:before { content: $ti-icon-device-imac-share; } +.#{$ti-prefix}-device-imac-star:before { content: $ti-icon-device-imac-star; } +.#{$ti-prefix}-device-imac-up:before { content: $ti-icon-device-imac-up; } +.#{$ti-prefix}-device-imac-x:before { content: $ti-icon-device-imac-x; } +.#{$ti-prefix}-device-ipad:before { content: $ti-icon-device-ipad; } +.#{$ti-prefix}-device-ipad-bolt:before { content: $ti-icon-device-ipad-bolt; } +.#{$ti-prefix}-device-ipad-cancel:before { content: $ti-icon-device-ipad-cancel; } +.#{$ti-prefix}-device-ipad-check:before { content: $ti-icon-device-ipad-check; } +.#{$ti-prefix}-device-ipad-code:before { content: $ti-icon-device-ipad-code; } +.#{$ti-prefix}-device-ipad-cog:before { content: $ti-icon-device-ipad-cog; } +.#{$ti-prefix}-device-ipad-dollar:before { content: $ti-icon-device-ipad-dollar; } +.#{$ti-prefix}-device-ipad-down:before { content: $ti-icon-device-ipad-down; } +.#{$ti-prefix}-device-ipad-exclamation:before { content: $ti-icon-device-ipad-exclamation; } +.#{$ti-prefix}-device-ipad-heart:before { content: $ti-icon-device-ipad-heart; } +.#{$ti-prefix}-device-ipad-horizontal:before { content: $ti-icon-device-ipad-horizontal; } +.#{$ti-prefix}-device-ipad-horizontal-bolt:before { content: $ti-icon-device-ipad-horizontal-bolt; } +.#{$ti-prefix}-device-ipad-horizontal-cancel:before { content: $ti-icon-device-ipad-horizontal-cancel; } +.#{$ti-prefix}-device-ipad-horizontal-check:before { content: $ti-icon-device-ipad-horizontal-check; } +.#{$ti-prefix}-device-ipad-horizontal-code:before { content: $ti-icon-device-ipad-horizontal-code; } +.#{$ti-prefix}-device-ipad-horizontal-cog:before { content: $ti-icon-device-ipad-horizontal-cog; } +.#{$ti-prefix}-device-ipad-horizontal-dollar:before { content: $ti-icon-device-ipad-horizontal-dollar; } +.#{$ti-prefix}-device-ipad-horizontal-down:before { content: $ti-icon-device-ipad-horizontal-down; } +.#{$ti-prefix}-device-ipad-horizontal-exclamation:before { content: $ti-icon-device-ipad-horizontal-exclamation; } +.#{$ti-prefix}-device-ipad-horizontal-heart:before { content: $ti-icon-device-ipad-horizontal-heart; } +.#{$ti-prefix}-device-ipad-horizontal-minus:before { content: $ti-icon-device-ipad-horizontal-minus; } +.#{$ti-prefix}-device-ipad-horizontal-off:before { content: $ti-icon-device-ipad-horizontal-off; } +.#{$ti-prefix}-device-ipad-horizontal-pause:before { content: $ti-icon-device-ipad-horizontal-pause; } +.#{$ti-prefix}-device-ipad-horizontal-pin:before { content: $ti-icon-device-ipad-horizontal-pin; } +.#{$ti-prefix}-device-ipad-horizontal-plus:before { content: $ti-icon-device-ipad-horizontal-plus; } +.#{$ti-prefix}-device-ipad-horizontal-question:before { content: $ti-icon-device-ipad-horizontal-question; } +.#{$ti-prefix}-device-ipad-horizontal-search:before { content: $ti-icon-device-ipad-horizontal-search; } +.#{$ti-prefix}-device-ipad-horizontal-share:before { content: $ti-icon-device-ipad-horizontal-share; } +.#{$ti-prefix}-device-ipad-horizontal-star:before { content: $ti-icon-device-ipad-horizontal-star; } +.#{$ti-prefix}-device-ipad-horizontal-up:before { content: $ti-icon-device-ipad-horizontal-up; } +.#{$ti-prefix}-device-ipad-horizontal-x:before { content: $ti-icon-device-ipad-horizontal-x; } +.#{$ti-prefix}-device-ipad-minus:before { content: $ti-icon-device-ipad-minus; } +.#{$ti-prefix}-device-ipad-off:before { content: $ti-icon-device-ipad-off; } +.#{$ti-prefix}-device-ipad-pause:before { content: $ti-icon-device-ipad-pause; } +.#{$ti-prefix}-device-ipad-pin:before { content: $ti-icon-device-ipad-pin; } +.#{$ti-prefix}-device-ipad-plus:before { content: $ti-icon-device-ipad-plus; } +.#{$ti-prefix}-device-ipad-question:before { content: $ti-icon-device-ipad-question; } +.#{$ti-prefix}-device-ipad-search:before { content: $ti-icon-device-ipad-search; } +.#{$ti-prefix}-device-ipad-share:before { content: $ti-icon-device-ipad-share; } +.#{$ti-prefix}-device-ipad-star:before { content: $ti-icon-device-ipad-star; } +.#{$ti-prefix}-device-ipad-up:before { content: $ti-icon-device-ipad-up; } +.#{$ti-prefix}-device-ipad-x:before { content: $ti-icon-device-ipad-x; } +.#{$ti-prefix}-device-landline-phone:before { content: $ti-icon-device-landline-phone; } +.#{$ti-prefix}-device-laptop:before { content: $ti-icon-device-laptop; } +.#{$ti-prefix}-device-laptop-off:before { content: $ti-icon-device-laptop-off; } +.#{$ti-prefix}-device-mobile:before { content: $ti-icon-device-mobile; } +.#{$ti-prefix}-device-mobile-bolt:before { content: $ti-icon-device-mobile-bolt; } +.#{$ti-prefix}-device-mobile-cancel:before { content: $ti-icon-device-mobile-cancel; } +.#{$ti-prefix}-device-mobile-charging:before { content: $ti-icon-device-mobile-charging; } +.#{$ti-prefix}-device-mobile-check:before { content: $ti-icon-device-mobile-check; } +.#{$ti-prefix}-device-mobile-code:before { content: $ti-icon-device-mobile-code; } +.#{$ti-prefix}-device-mobile-cog:before { content: $ti-icon-device-mobile-cog; } +.#{$ti-prefix}-device-mobile-dollar:before { content: $ti-icon-device-mobile-dollar; } +.#{$ti-prefix}-device-mobile-down:before { content: $ti-icon-device-mobile-down; } +.#{$ti-prefix}-device-mobile-exclamation:before { content: $ti-icon-device-mobile-exclamation; } +.#{$ti-prefix}-device-mobile-heart:before { content: $ti-icon-device-mobile-heart; } +.#{$ti-prefix}-device-mobile-message:before { content: $ti-icon-device-mobile-message; } +.#{$ti-prefix}-device-mobile-minus:before { content: $ti-icon-device-mobile-minus; } +.#{$ti-prefix}-device-mobile-off:before { content: $ti-icon-device-mobile-off; } +.#{$ti-prefix}-device-mobile-pause:before { content: $ti-icon-device-mobile-pause; } +.#{$ti-prefix}-device-mobile-pin:before { content: $ti-icon-device-mobile-pin; } +.#{$ti-prefix}-device-mobile-plus:before { content: $ti-icon-device-mobile-plus; } +.#{$ti-prefix}-device-mobile-question:before { content: $ti-icon-device-mobile-question; } +.#{$ti-prefix}-device-mobile-rotated:before { content: $ti-icon-device-mobile-rotated; } +.#{$ti-prefix}-device-mobile-search:before { content: $ti-icon-device-mobile-search; } +.#{$ti-prefix}-device-mobile-share:before { content: $ti-icon-device-mobile-share; } +.#{$ti-prefix}-device-mobile-star:before { content: $ti-icon-device-mobile-star; } +.#{$ti-prefix}-device-mobile-up:before { content: $ti-icon-device-mobile-up; } +.#{$ti-prefix}-device-mobile-vibration:before { content: $ti-icon-device-mobile-vibration; } +.#{$ti-prefix}-device-mobile-x:before { content: $ti-icon-device-mobile-x; } +.#{$ti-prefix}-device-nintendo:before { content: $ti-icon-device-nintendo; } +.#{$ti-prefix}-device-nintendo-off:before { content: $ti-icon-device-nintendo-off; } +.#{$ti-prefix}-device-remote:before { content: $ti-icon-device-remote; } +.#{$ti-prefix}-device-sd-card:before { content: $ti-icon-device-sd-card; } +.#{$ti-prefix}-device-sim:before { content: $ti-icon-device-sim; } +.#{$ti-prefix}-device-sim-1:before { content: $ti-icon-device-sim-1; } +.#{$ti-prefix}-device-sim-2:before { content: $ti-icon-device-sim-2; } +.#{$ti-prefix}-device-sim-3:before { content: $ti-icon-device-sim-3; } +.#{$ti-prefix}-device-speaker:before { content: $ti-icon-device-speaker; } +.#{$ti-prefix}-device-speaker-off:before { content: $ti-icon-device-speaker-off; } +.#{$ti-prefix}-device-tablet:before { content: $ti-icon-device-tablet; } +.#{$ti-prefix}-device-tablet-bolt:before { content: $ti-icon-device-tablet-bolt; } +.#{$ti-prefix}-device-tablet-cancel:before { content: $ti-icon-device-tablet-cancel; } +.#{$ti-prefix}-device-tablet-check:before { content: $ti-icon-device-tablet-check; } +.#{$ti-prefix}-device-tablet-code:before { content: $ti-icon-device-tablet-code; } +.#{$ti-prefix}-device-tablet-cog:before { content: $ti-icon-device-tablet-cog; } +.#{$ti-prefix}-device-tablet-dollar:before { content: $ti-icon-device-tablet-dollar; } +.#{$ti-prefix}-device-tablet-down:before { content: $ti-icon-device-tablet-down; } +.#{$ti-prefix}-device-tablet-exclamation:before { content: $ti-icon-device-tablet-exclamation; } +.#{$ti-prefix}-device-tablet-heart:before { content: $ti-icon-device-tablet-heart; } +.#{$ti-prefix}-device-tablet-minus:before { content: $ti-icon-device-tablet-minus; } +.#{$ti-prefix}-device-tablet-off:before { content: $ti-icon-device-tablet-off; } +.#{$ti-prefix}-device-tablet-pause:before { content: $ti-icon-device-tablet-pause; } +.#{$ti-prefix}-device-tablet-pin:before { content: $ti-icon-device-tablet-pin; } +.#{$ti-prefix}-device-tablet-plus:before { content: $ti-icon-device-tablet-plus; } +.#{$ti-prefix}-device-tablet-question:before { content: $ti-icon-device-tablet-question; } +.#{$ti-prefix}-device-tablet-search:before { content: $ti-icon-device-tablet-search; } +.#{$ti-prefix}-device-tablet-share:before { content: $ti-icon-device-tablet-share; } +.#{$ti-prefix}-device-tablet-star:before { content: $ti-icon-device-tablet-star; } +.#{$ti-prefix}-device-tablet-up:before { content: $ti-icon-device-tablet-up; } +.#{$ti-prefix}-device-tablet-x:before { content: $ti-icon-device-tablet-x; } +.#{$ti-prefix}-device-tv:before { content: $ti-icon-device-tv; } +.#{$ti-prefix}-device-tv-off:before { content: $ti-icon-device-tv-off; } +.#{$ti-prefix}-device-tv-old:before { content: $ti-icon-device-tv-old; } +.#{$ti-prefix}-device-watch:before { content: $ti-icon-device-watch; } +.#{$ti-prefix}-device-watch-bolt:before { content: $ti-icon-device-watch-bolt; } +.#{$ti-prefix}-device-watch-cancel:before { content: $ti-icon-device-watch-cancel; } +.#{$ti-prefix}-device-watch-check:before { content: $ti-icon-device-watch-check; } +.#{$ti-prefix}-device-watch-code:before { content: $ti-icon-device-watch-code; } +.#{$ti-prefix}-device-watch-cog:before { content: $ti-icon-device-watch-cog; } +.#{$ti-prefix}-device-watch-dollar:before { content: $ti-icon-device-watch-dollar; } +.#{$ti-prefix}-device-watch-down:before { content: $ti-icon-device-watch-down; } +.#{$ti-prefix}-device-watch-exclamation:before { content: $ti-icon-device-watch-exclamation; } +.#{$ti-prefix}-device-watch-heart:before { content: $ti-icon-device-watch-heart; } +.#{$ti-prefix}-device-watch-minus:before { content: $ti-icon-device-watch-minus; } +.#{$ti-prefix}-device-watch-off:before { content: $ti-icon-device-watch-off; } +.#{$ti-prefix}-device-watch-pause:before { content: $ti-icon-device-watch-pause; } +.#{$ti-prefix}-device-watch-pin:before { content: $ti-icon-device-watch-pin; } +.#{$ti-prefix}-device-watch-plus:before { content: $ti-icon-device-watch-plus; } +.#{$ti-prefix}-device-watch-question:before { content: $ti-icon-device-watch-question; } +.#{$ti-prefix}-device-watch-search:before { content: $ti-icon-device-watch-search; } +.#{$ti-prefix}-device-watch-share:before { content: $ti-icon-device-watch-share; } +.#{$ti-prefix}-device-watch-star:before { content: $ti-icon-device-watch-star; } +.#{$ti-prefix}-device-watch-stats:before { content: $ti-icon-device-watch-stats; } +.#{$ti-prefix}-device-watch-stats-2:before { content: $ti-icon-device-watch-stats-2; } +.#{$ti-prefix}-device-watch-up:before { content: $ti-icon-device-watch-up; } +.#{$ti-prefix}-device-watch-x:before { content: $ti-icon-device-watch-x; } +.#{$ti-prefix}-devices:before { content: $ti-icon-devices; } +.#{$ti-prefix}-devices-2:before { content: $ti-icon-devices-2; } +.#{$ti-prefix}-devices-bolt:before { content: $ti-icon-devices-bolt; } +.#{$ti-prefix}-devices-cancel:before { content: $ti-icon-devices-cancel; } +.#{$ti-prefix}-devices-check:before { content: $ti-icon-devices-check; } +.#{$ti-prefix}-devices-code:before { content: $ti-icon-devices-code; } +.#{$ti-prefix}-devices-cog:before { content: $ti-icon-devices-cog; } +.#{$ti-prefix}-devices-dollar:before { content: $ti-icon-devices-dollar; } +.#{$ti-prefix}-devices-down:before { content: $ti-icon-devices-down; } +.#{$ti-prefix}-devices-exclamation:before { content: $ti-icon-devices-exclamation; } +.#{$ti-prefix}-devices-heart:before { content: $ti-icon-devices-heart; } +.#{$ti-prefix}-devices-minus:before { content: $ti-icon-devices-minus; } +.#{$ti-prefix}-devices-off:before { content: $ti-icon-devices-off; } +.#{$ti-prefix}-devices-pause:before { content: $ti-icon-devices-pause; } +.#{$ti-prefix}-devices-pc:before { content: $ti-icon-devices-pc; } +.#{$ti-prefix}-devices-pc-off:before { content: $ti-icon-devices-pc-off; } +.#{$ti-prefix}-devices-pin:before { content: $ti-icon-devices-pin; } +.#{$ti-prefix}-devices-plus:before { content: $ti-icon-devices-plus; } +.#{$ti-prefix}-devices-question:before { content: $ti-icon-devices-question; } +.#{$ti-prefix}-devices-search:before { content: $ti-icon-devices-search; } +.#{$ti-prefix}-devices-share:before { content: $ti-icon-devices-share; } +.#{$ti-prefix}-devices-star:before { content: $ti-icon-devices-star; } +.#{$ti-prefix}-devices-up:before { content: $ti-icon-devices-up; } +.#{$ti-prefix}-devices-x:before { content: $ti-icon-devices-x; } +.#{$ti-prefix}-dialpad:before { content: $ti-icon-dialpad; } +.#{$ti-prefix}-dialpad-off:before { content: $ti-icon-dialpad-off; } +.#{$ti-prefix}-diamond:before { content: $ti-icon-diamond; } +.#{$ti-prefix}-diamond-filled:before { content: $ti-icon-diamond-filled; } +.#{$ti-prefix}-diamond-off:before { content: $ti-icon-diamond-off; } +.#{$ti-prefix}-diamonds:before { content: $ti-icon-diamonds; } +.#{$ti-prefix}-diamonds-filled:before { content: $ti-icon-diamonds-filled; } +.#{$ti-prefix}-dice:before { content: $ti-icon-dice; } +.#{$ti-prefix}-dice-1:before { content: $ti-icon-dice-1; } +.#{$ti-prefix}-dice-1-filled:before { content: $ti-icon-dice-1-filled; } +.#{$ti-prefix}-dice-2:before { content: $ti-icon-dice-2; } +.#{$ti-prefix}-dice-2-filled:before { content: $ti-icon-dice-2-filled; } +.#{$ti-prefix}-dice-3:before { content: $ti-icon-dice-3; } +.#{$ti-prefix}-dice-3-filled:before { content: $ti-icon-dice-3-filled; } +.#{$ti-prefix}-dice-4:before { content: $ti-icon-dice-4; } +.#{$ti-prefix}-dice-4-filled:before { content: $ti-icon-dice-4-filled; } +.#{$ti-prefix}-dice-5:before { content: $ti-icon-dice-5; } +.#{$ti-prefix}-dice-5-filled:before { content: $ti-icon-dice-5-filled; } +.#{$ti-prefix}-dice-6:before { content: $ti-icon-dice-6; } +.#{$ti-prefix}-dice-6-filled:before { content: $ti-icon-dice-6-filled; } +.#{$ti-prefix}-dice-filled:before { content: $ti-icon-dice-filled; } +.#{$ti-prefix}-dimensions:before { content: $ti-icon-dimensions; } +.#{$ti-prefix}-direction:before { content: $ti-icon-direction; } +.#{$ti-prefix}-direction-horizontal:before { content: $ti-icon-direction-horizontal; } +.#{$ti-prefix}-direction-sign:before { content: $ti-icon-direction-sign; } +.#{$ti-prefix}-direction-sign-filled:before { content: $ti-icon-direction-sign-filled; } +.#{$ti-prefix}-direction-sign-off:before { content: $ti-icon-direction-sign-off; } +.#{$ti-prefix}-directions:before { content: $ti-icon-directions; } +.#{$ti-prefix}-directions-off:before { content: $ti-icon-directions-off; } +.#{$ti-prefix}-disabled:before { content: $ti-icon-disabled; } +.#{$ti-prefix}-disabled-2:before { content: $ti-icon-disabled-2; } +.#{$ti-prefix}-disabled-off:before { content: $ti-icon-disabled-off; } +.#{$ti-prefix}-disc:before { content: $ti-icon-disc; } +.#{$ti-prefix}-disc-golf:before { content: $ti-icon-disc-golf; } +.#{$ti-prefix}-disc-off:before { content: $ti-icon-disc-off; } +.#{$ti-prefix}-discount:before { content: $ti-icon-discount; } +.#{$ti-prefix}-discount-2:before { content: $ti-icon-discount-2; } +.#{$ti-prefix}-discount-2-off:before { content: $ti-icon-discount-2-off; } +.#{$ti-prefix}-discount-check:before { content: $ti-icon-discount-check; } +.#{$ti-prefix}-discount-check-filled:before { content: $ti-icon-discount-check-filled; } +.#{$ti-prefix}-discount-off:before { content: $ti-icon-discount-off; } +.#{$ti-prefix}-divide:before { content: $ti-icon-divide; } +.#{$ti-prefix}-dna:before { content: $ti-icon-dna; } +.#{$ti-prefix}-dna-2:before { content: $ti-icon-dna-2; } +.#{$ti-prefix}-dna-2-off:before { content: $ti-icon-dna-2-off; } +.#{$ti-prefix}-dna-off:before { content: $ti-icon-dna-off; } +.#{$ti-prefix}-dog:before { content: $ti-icon-dog; } +.#{$ti-prefix}-dog-bowl:before { content: $ti-icon-dog-bowl; } +.#{$ti-prefix}-door:before { content: $ti-icon-door; } +.#{$ti-prefix}-door-enter:before { content: $ti-icon-door-enter; } +.#{$ti-prefix}-door-exit:before { content: $ti-icon-door-exit; } +.#{$ti-prefix}-door-off:before { content: $ti-icon-door-off; } +.#{$ti-prefix}-dots:before { content: $ti-icon-dots; } +.#{$ti-prefix}-dots-circle-horizontal:before { content: $ti-icon-dots-circle-horizontal; } +.#{$ti-prefix}-dots-diagonal:before { content: $ti-icon-dots-diagonal; } +.#{$ti-prefix}-dots-diagonal-2:before { content: $ti-icon-dots-diagonal-2; } +.#{$ti-prefix}-dots-vertical:before { content: $ti-icon-dots-vertical; } +.#{$ti-prefix}-download:before { content: $ti-icon-download; } +.#{$ti-prefix}-download-off:before { content: $ti-icon-download-off; } +.#{$ti-prefix}-drag-drop:before { content: $ti-icon-drag-drop; } +.#{$ti-prefix}-drag-drop-2:before { content: $ti-icon-drag-drop-2; } +.#{$ti-prefix}-drone:before { content: $ti-icon-drone; } +.#{$ti-prefix}-drone-off:before { content: $ti-icon-drone-off; } +.#{$ti-prefix}-drop-circle:before { content: $ti-icon-drop-circle; } +.#{$ti-prefix}-droplet:before { content: $ti-icon-droplet; } +.#{$ti-prefix}-droplet-bolt:before { content: $ti-icon-droplet-bolt; } +.#{$ti-prefix}-droplet-cancel:before { content: $ti-icon-droplet-cancel; } +.#{$ti-prefix}-droplet-check:before { content: $ti-icon-droplet-check; } +.#{$ti-prefix}-droplet-code:before { content: $ti-icon-droplet-code; } +.#{$ti-prefix}-droplet-cog:before { content: $ti-icon-droplet-cog; } +.#{$ti-prefix}-droplet-dollar:before { content: $ti-icon-droplet-dollar; } +.#{$ti-prefix}-droplet-down:before { content: $ti-icon-droplet-down; } +.#{$ti-prefix}-droplet-exclamation:before { content: $ti-icon-droplet-exclamation; } +.#{$ti-prefix}-droplet-filled:before { content: $ti-icon-droplet-filled; } +.#{$ti-prefix}-droplet-filled-2:before { content: $ti-icon-droplet-filled-2; } +.#{$ti-prefix}-droplet-half:before { content: $ti-icon-droplet-half; } +.#{$ti-prefix}-droplet-half-2:before { content: $ti-icon-droplet-half-2; } +.#{$ti-prefix}-droplet-half-filled:before { content: $ti-icon-droplet-half-filled; } +.#{$ti-prefix}-droplet-heart:before { content: $ti-icon-droplet-heart; } +.#{$ti-prefix}-droplet-minus:before { content: $ti-icon-droplet-minus; } +.#{$ti-prefix}-droplet-off:before { content: $ti-icon-droplet-off; } +.#{$ti-prefix}-droplet-pause:before { content: $ti-icon-droplet-pause; } +.#{$ti-prefix}-droplet-pin:before { content: $ti-icon-droplet-pin; } +.#{$ti-prefix}-droplet-plus:before { content: $ti-icon-droplet-plus; } +.#{$ti-prefix}-droplet-question:before { content: $ti-icon-droplet-question; } +.#{$ti-prefix}-droplet-search:before { content: $ti-icon-droplet-search; } +.#{$ti-prefix}-droplet-share:before { content: $ti-icon-droplet-share; } +.#{$ti-prefix}-droplet-star:before { content: $ti-icon-droplet-star; } +.#{$ti-prefix}-droplet-up:before { content: $ti-icon-droplet-up; } +.#{$ti-prefix}-droplet-x:before { content: $ti-icon-droplet-x; } +.#{$ti-prefix}-e-passport:before { content: $ti-icon-e-passport; } +.#{$ti-prefix}-ear:before { content: $ti-icon-ear; } +.#{$ti-prefix}-ear-off:before { content: $ti-icon-ear-off; } +.#{$ti-prefix}-ease-in:before { content: $ti-icon-ease-in; } +.#{$ti-prefix}-ease-in-control-point:before { content: $ti-icon-ease-in-control-point; } +.#{$ti-prefix}-ease-in-out:before { content: $ti-icon-ease-in-out; } +.#{$ti-prefix}-ease-in-out-control-points:before { content: $ti-icon-ease-in-out-control-points; } +.#{$ti-prefix}-ease-out:before { content: $ti-icon-ease-out; } +.#{$ti-prefix}-ease-out-control-point:before { content: $ti-icon-ease-out-control-point; } +.#{$ti-prefix}-edit:before { content: $ti-icon-edit; } +.#{$ti-prefix}-edit-circle:before { content: $ti-icon-edit-circle; } +.#{$ti-prefix}-edit-circle-off:before { content: $ti-icon-edit-circle-off; } +.#{$ti-prefix}-edit-off:before { content: $ti-icon-edit-off; } +.#{$ti-prefix}-egg:before { content: $ti-icon-egg; } +.#{$ti-prefix}-egg-cracked:before { content: $ti-icon-egg-cracked; } +.#{$ti-prefix}-egg-filled:before { content: $ti-icon-egg-filled; } +.#{$ti-prefix}-egg-fried:before { content: $ti-icon-egg-fried; } +.#{$ti-prefix}-egg-off:before { content: $ti-icon-egg-off; } +.#{$ti-prefix}-eggs:before { content: $ti-icon-eggs; } +.#{$ti-prefix}-elevator:before { content: $ti-icon-elevator; } +.#{$ti-prefix}-elevator-off:before { content: $ti-icon-elevator-off; } +.#{$ti-prefix}-emergency-bed:before { content: $ti-icon-emergency-bed; } +.#{$ti-prefix}-empathize:before { content: $ti-icon-empathize; } +.#{$ti-prefix}-empathize-off:before { content: $ti-icon-empathize-off; } +.#{$ti-prefix}-emphasis:before { content: $ti-icon-emphasis; } +.#{$ti-prefix}-engine:before { content: $ti-icon-engine; } +.#{$ti-prefix}-engine-off:before { content: $ti-icon-engine-off; } +.#{$ti-prefix}-equal:before { content: $ti-icon-equal; } +.#{$ti-prefix}-equal-double:before { content: $ti-icon-equal-double; } +.#{$ti-prefix}-equal-not:before { content: $ti-icon-equal-not; } +.#{$ti-prefix}-eraser:before { content: $ti-icon-eraser; } +.#{$ti-prefix}-eraser-off:before { content: $ti-icon-eraser-off; } +.#{$ti-prefix}-error-404:before { content: $ti-icon-error-404; } +.#{$ti-prefix}-error-404-off:before { content: $ti-icon-error-404-off; } +.#{$ti-prefix}-exchange:before { content: $ti-icon-exchange; } +.#{$ti-prefix}-exchange-off:before { content: $ti-icon-exchange-off; } +.#{$ti-prefix}-exclamation-circle:before { content: $ti-icon-exclamation-circle; } +.#{$ti-prefix}-exclamation-mark:before { content: $ti-icon-exclamation-mark; } +.#{$ti-prefix}-exclamation-mark-off:before { content: $ti-icon-exclamation-mark-off; } +.#{$ti-prefix}-explicit:before { content: $ti-icon-explicit; } +.#{$ti-prefix}-explicit-off:before { content: $ti-icon-explicit-off; } +.#{$ti-prefix}-exposure:before { content: $ti-icon-exposure; } +.#{$ti-prefix}-exposure-0:before { content: $ti-icon-exposure-0; } +.#{$ti-prefix}-exposure-minus-1:before { content: $ti-icon-exposure-minus-1; } +.#{$ti-prefix}-exposure-minus-2:before { content: $ti-icon-exposure-minus-2; } +.#{$ti-prefix}-exposure-off:before { content: $ti-icon-exposure-off; } +.#{$ti-prefix}-exposure-plus-1:before { content: $ti-icon-exposure-plus-1; } +.#{$ti-prefix}-exposure-plus-2:before { content: $ti-icon-exposure-plus-2; } +.#{$ti-prefix}-external-link:before { content: $ti-icon-external-link; } +.#{$ti-prefix}-external-link-off:before { content: $ti-icon-external-link-off; } +.#{$ti-prefix}-eye:before { content: $ti-icon-eye; } +.#{$ti-prefix}-eye-check:before { content: $ti-icon-eye-check; } +.#{$ti-prefix}-eye-closed:before { content: $ti-icon-eye-closed; } +.#{$ti-prefix}-eye-cog:before { content: $ti-icon-eye-cog; } +.#{$ti-prefix}-eye-edit:before { content: $ti-icon-eye-edit; } +.#{$ti-prefix}-eye-exclamation:before { content: $ti-icon-eye-exclamation; } +.#{$ti-prefix}-eye-filled:before { content: $ti-icon-eye-filled; } +.#{$ti-prefix}-eye-heart:before { content: $ti-icon-eye-heart; } +.#{$ti-prefix}-eye-off:before { content: $ti-icon-eye-off; } +.#{$ti-prefix}-eye-table:before { content: $ti-icon-eye-table; } +.#{$ti-prefix}-eye-x:before { content: $ti-icon-eye-x; } +.#{$ti-prefix}-eyeglass:before { content: $ti-icon-eyeglass; } +.#{$ti-prefix}-eyeglass-2:before { content: $ti-icon-eyeglass-2; } +.#{$ti-prefix}-eyeglass-off:before { content: $ti-icon-eyeglass-off; } +.#{$ti-prefix}-face-id:before { content: $ti-icon-face-id; } +.#{$ti-prefix}-face-id-error:before { content: $ti-icon-face-id-error; } +.#{$ti-prefix}-face-mask:before { content: $ti-icon-face-mask; } +.#{$ti-prefix}-face-mask-off:before { content: $ti-icon-face-mask-off; } +.#{$ti-prefix}-fall:before { content: $ti-icon-fall; } +.#{$ti-prefix}-feather:before { content: $ti-icon-feather; } +.#{$ti-prefix}-feather-off:before { content: $ti-icon-feather-off; } +.#{$ti-prefix}-fence:before { content: $ti-icon-fence; } +.#{$ti-prefix}-fence-off:before { content: $ti-icon-fence-off; } +.#{$ti-prefix}-fidget-spinner:before { content: $ti-icon-fidget-spinner; } +.#{$ti-prefix}-file:before { content: $ti-icon-file; } +.#{$ti-prefix}-file-3d:before { content: $ti-icon-file-3d; } +.#{$ti-prefix}-file-alert:before { content: $ti-icon-file-alert; } +.#{$ti-prefix}-file-analytics:before { content: $ti-icon-file-analytics; } +.#{$ti-prefix}-file-arrow-left:before { content: $ti-icon-file-arrow-left; } +.#{$ti-prefix}-file-arrow-right:before { content: $ti-icon-file-arrow-right; } +.#{$ti-prefix}-file-barcode:before { content: $ti-icon-file-barcode; } +.#{$ti-prefix}-file-broken:before { content: $ti-icon-file-broken; } +.#{$ti-prefix}-file-certificate:before { content: $ti-icon-file-certificate; } +.#{$ti-prefix}-file-chart:before { content: $ti-icon-file-chart; } +.#{$ti-prefix}-file-check:before { content: $ti-icon-file-check; } +.#{$ti-prefix}-file-code:before { content: $ti-icon-file-code; } +.#{$ti-prefix}-file-code-2:before { content: $ti-icon-file-code-2; } +.#{$ti-prefix}-file-database:before { content: $ti-icon-file-database; } +.#{$ti-prefix}-file-delta:before { content: $ti-icon-file-delta; } +.#{$ti-prefix}-file-description:before { content: $ti-icon-file-description; } +.#{$ti-prefix}-file-diff:before { content: $ti-icon-file-diff; } +.#{$ti-prefix}-file-digit:before { content: $ti-icon-file-digit; } +.#{$ti-prefix}-file-dislike:before { content: $ti-icon-file-dislike; } +.#{$ti-prefix}-file-dollar:before { content: $ti-icon-file-dollar; } +.#{$ti-prefix}-file-dots:before { content: $ti-icon-file-dots; } +.#{$ti-prefix}-file-download:before { content: $ti-icon-file-download; } +.#{$ti-prefix}-file-euro:before { content: $ti-icon-file-euro; } +.#{$ti-prefix}-file-export:before { content: $ti-icon-file-export; } +.#{$ti-prefix}-file-filled:before { content: $ti-icon-file-filled; } +.#{$ti-prefix}-file-function:before { content: $ti-icon-file-function; } +.#{$ti-prefix}-file-horizontal:before { content: $ti-icon-file-horizontal; } +.#{$ti-prefix}-file-import:before { content: $ti-icon-file-import; } +.#{$ti-prefix}-file-infinity:before { content: $ti-icon-file-infinity; } +.#{$ti-prefix}-file-info:before { content: $ti-icon-file-info; } +.#{$ti-prefix}-file-invoice:before { content: $ti-icon-file-invoice; } +.#{$ti-prefix}-file-lambda:before { content: $ti-icon-file-lambda; } +.#{$ti-prefix}-file-like:before { content: $ti-icon-file-like; } +.#{$ti-prefix}-file-minus:before { content: $ti-icon-file-minus; } +.#{$ti-prefix}-file-music:before { content: $ti-icon-file-music; } +.#{$ti-prefix}-file-off:before { content: $ti-icon-file-off; } +.#{$ti-prefix}-file-orientation:before { content: $ti-icon-file-orientation; } +.#{$ti-prefix}-file-pencil:before { content: $ti-icon-file-pencil; } +.#{$ti-prefix}-file-percent:before { content: $ti-icon-file-percent; } +.#{$ti-prefix}-file-phone:before { content: $ti-icon-file-phone; } +.#{$ti-prefix}-file-plus:before { content: $ti-icon-file-plus; } +.#{$ti-prefix}-file-power:before { content: $ti-icon-file-power; } +.#{$ti-prefix}-file-report:before { content: $ti-icon-file-report; } +.#{$ti-prefix}-file-rss:before { content: $ti-icon-file-rss; } +.#{$ti-prefix}-file-scissors:before { content: $ti-icon-file-scissors; } +.#{$ti-prefix}-file-search:before { content: $ti-icon-file-search; } +.#{$ti-prefix}-file-settings:before { content: $ti-icon-file-settings; } +.#{$ti-prefix}-file-shredder:before { content: $ti-icon-file-shredder; } +.#{$ti-prefix}-file-signal:before { content: $ti-icon-file-signal; } +.#{$ti-prefix}-file-spreadsheet:before { content: $ti-icon-file-spreadsheet; } +.#{$ti-prefix}-file-stack:before { content: $ti-icon-file-stack; } +.#{$ti-prefix}-file-star:before { content: $ti-icon-file-star; } +.#{$ti-prefix}-file-symlink:before { content: $ti-icon-file-symlink; } +.#{$ti-prefix}-file-text:before { content: $ti-icon-file-text; } +.#{$ti-prefix}-file-time:before { content: $ti-icon-file-time; } +.#{$ti-prefix}-file-typography:before { content: $ti-icon-file-typography; } +.#{$ti-prefix}-file-unknown:before { content: $ti-icon-file-unknown; } +.#{$ti-prefix}-file-upload:before { content: $ti-icon-file-upload; } +.#{$ti-prefix}-file-vector:before { content: $ti-icon-file-vector; } +.#{$ti-prefix}-file-x:before { content: $ti-icon-file-x; } +.#{$ti-prefix}-file-x-filled:before { content: $ti-icon-file-x-filled; } +.#{$ti-prefix}-file-zip:before { content: $ti-icon-file-zip; } +.#{$ti-prefix}-files:before { content: $ti-icon-files; } +.#{$ti-prefix}-files-off:before { content: $ti-icon-files-off; } +.#{$ti-prefix}-filter:before { content: $ti-icon-filter; } +.#{$ti-prefix}-filter-off:before { content: $ti-icon-filter-off; } +.#{$ti-prefix}-filters:before { content: $ti-icon-filters; } +.#{$ti-prefix}-fingerprint:before { content: $ti-icon-fingerprint; } +.#{$ti-prefix}-fingerprint-off:before { content: $ti-icon-fingerprint-off; } +.#{$ti-prefix}-fire-hydrant:before { content: $ti-icon-fire-hydrant; } +.#{$ti-prefix}-fire-hydrant-off:before { content: $ti-icon-fire-hydrant-off; } +.#{$ti-prefix}-firetruck:before { content: $ti-icon-firetruck; } +.#{$ti-prefix}-first-aid-kit:before { content: $ti-icon-first-aid-kit; } +.#{$ti-prefix}-first-aid-kit-off:before { content: $ti-icon-first-aid-kit-off; } +.#{$ti-prefix}-fish:before { content: $ti-icon-fish; } +.#{$ti-prefix}-fish-bone:before { content: $ti-icon-fish-bone; } +.#{$ti-prefix}-fish-christianity:before { content: $ti-icon-fish-christianity; } +.#{$ti-prefix}-fish-hook:before { content: $ti-icon-fish-hook; } +.#{$ti-prefix}-fish-hook-off:before { content: $ti-icon-fish-hook-off; } +.#{$ti-prefix}-fish-off:before { content: $ti-icon-fish-off; } +.#{$ti-prefix}-flag:before { content: $ti-icon-flag; } +.#{$ti-prefix}-flag-2:before { content: $ti-icon-flag-2; } +.#{$ti-prefix}-flag-2-filled:before { content: $ti-icon-flag-2-filled; } +.#{$ti-prefix}-flag-2-off:before { content: $ti-icon-flag-2-off; } +.#{$ti-prefix}-flag-3:before { content: $ti-icon-flag-3; } +.#{$ti-prefix}-flag-3-filled:before { content: $ti-icon-flag-3-filled; } +.#{$ti-prefix}-flag-filled:before { content: $ti-icon-flag-filled; } +.#{$ti-prefix}-flag-off:before { content: $ti-icon-flag-off; } +.#{$ti-prefix}-flame:before { content: $ti-icon-flame; } +.#{$ti-prefix}-flame-off:before { content: $ti-icon-flame-off; } +.#{$ti-prefix}-flare:before { content: $ti-icon-flare; } +.#{$ti-prefix}-flask:before { content: $ti-icon-flask; } +.#{$ti-prefix}-flask-2:before { content: $ti-icon-flask-2; } +.#{$ti-prefix}-flask-2-off:before { content: $ti-icon-flask-2-off; } +.#{$ti-prefix}-flask-off:before { content: $ti-icon-flask-off; } +.#{$ti-prefix}-flip-flops:before { content: $ti-icon-flip-flops; } +.#{$ti-prefix}-flip-horizontal:before { content: $ti-icon-flip-horizontal; } +.#{$ti-prefix}-flip-vertical:before { content: $ti-icon-flip-vertical; } +.#{$ti-prefix}-float-center:before { content: $ti-icon-float-center; } +.#{$ti-prefix}-float-left:before { content: $ti-icon-float-left; } +.#{$ti-prefix}-float-none:before { content: $ti-icon-float-none; } +.#{$ti-prefix}-float-right:before { content: $ti-icon-float-right; } +.#{$ti-prefix}-flower:before { content: $ti-icon-flower; } +.#{$ti-prefix}-flower-off:before { content: $ti-icon-flower-off; } +.#{$ti-prefix}-focus:before { content: $ti-icon-focus; } +.#{$ti-prefix}-focus-2:before { content: $ti-icon-focus-2; } +.#{$ti-prefix}-focus-centered:before { content: $ti-icon-focus-centered; } +.#{$ti-prefix}-fold:before { content: $ti-icon-fold; } +.#{$ti-prefix}-fold-down:before { content: $ti-icon-fold-down; } +.#{$ti-prefix}-fold-up:before { content: $ti-icon-fold-up; } +.#{$ti-prefix}-folder:before { content: $ti-icon-folder; } +.#{$ti-prefix}-folder-bolt:before { content: $ti-icon-folder-bolt; } +.#{$ti-prefix}-folder-cancel:before { content: $ti-icon-folder-cancel; } +.#{$ti-prefix}-folder-check:before { content: $ti-icon-folder-check; } +.#{$ti-prefix}-folder-code:before { content: $ti-icon-folder-code; } +.#{$ti-prefix}-folder-cog:before { content: $ti-icon-folder-cog; } +.#{$ti-prefix}-folder-dollar:before { content: $ti-icon-folder-dollar; } +.#{$ti-prefix}-folder-down:before { content: $ti-icon-folder-down; } +.#{$ti-prefix}-folder-exclamation:before { content: $ti-icon-folder-exclamation; } +.#{$ti-prefix}-folder-filled:before { content: $ti-icon-folder-filled; } +.#{$ti-prefix}-folder-heart:before { content: $ti-icon-folder-heart; } +.#{$ti-prefix}-folder-minus:before { content: $ti-icon-folder-minus; } +.#{$ti-prefix}-folder-off:before { content: $ti-icon-folder-off; } +.#{$ti-prefix}-folder-pause:before { content: $ti-icon-folder-pause; } +.#{$ti-prefix}-folder-pin:before { content: $ti-icon-folder-pin; } +.#{$ti-prefix}-folder-plus:before { content: $ti-icon-folder-plus; } +.#{$ti-prefix}-folder-question:before { content: $ti-icon-folder-question; } +.#{$ti-prefix}-folder-search:before { content: $ti-icon-folder-search; } +.#{$ti-prefix}-folder-share:before { content: $ti-icon-folder-share; } +.#{$ti-prefix}-folder-star:before { content: $ti-icon-folder-star; } +.#{$ti-prefix}-folder-symlink:before { content: $ti-icon-folder-symlink; } +.#{$ti-prefix}-folder-up:before { content: $ti-icon-folder-up; } +.#{$ti-prefix}-folder-x:before { content: $ti-icon-folder-x; } +.#{$ti-prefix}-folders:before { content: $ti-icon-folders; } +.#{$ti-prefix}-folders-off:before { content: $ti-icon-folders-off; } +.#{$ti-prefix}-forbid:before { content: $ti-icon-forbid; } +.#{$ti-prefix}-forbid-2:before { content: $ti-icon-forbid-2; } +.#{$ti-prefix}-forklift:before { content: $ti-icon-forklift; } +.#{$ti-prefix}-forms:before { content: $ti-icon-forms; } +.#{$ti-prefix}-fountain:before { content: $ti-icon-fountain; } +.#{$ti-prefix}-fountain-off:before { content: $ti-icon-fountain-off; } +.#{$ti-prefix}-frame:before { content: $ti-icon-frame; } +.#{$ti-prefix}-frame-off:before { content: $ti-icon-frame-off; } +.#{$ti-prefix}-free-rights:before { content: $ti-icon-free-rights; } +.#{$ti-prefix}-fridge:before { content: $ti-icon-fridge; } +.#{$ti-prefix}-fridge-off:before { content: $ti-icon-fridge-off; } +.#{$ti-prefix}-friends:before { content: $ti-icon-friends; } +.#{$ti-prefix}-friends-off:before { content: $ti-icon-friends-off; } +.#{$ti-prefix}-function:before { content: $ti-icon-function; } +.#{$ti-prefix}-function-off:before { content: $ti-icon-function-off; } +.#{$ti-prefix}-garden-cart:before { content: $ti-icon-garden-cart; } +.#{$ti-prefix}-garden-cart-off:before { content: $ti-icon-garden-cart-off; } +.#{$ti-prefix}-gas-station:before { content: $ti-icon-gas-station; } +.#{$ti-prefix}-gas-station-off:before { content: $ti-icon-gas-station-off; } +.#{$ti-prefix}-gauge:before { content: $ti-icon-gauge; } +.#{$ti-prefix}-gauge-off:before { content: $ti-icon-gauge-off; } +.#{$ti-prefix}-gavel:before { content: $ti-icon-gavel; } +.#{$ti-prefix}-gender-agender:before { content: $ti-icon-gender-agender; } +.#{$ti-prefix}-gender-androgyne:before { content: $ti-icon-gender-androgyne; } +.#{$ti-prefix}-gender-bigender:before { content: $ti-icon-gender-bigender; } +.#{$ti-prefix}-gender-demiboy:before { content: $ti-icon-gender-demiboy; } +.#{$ti-prefix}-gender-demigirl:before { content: $ti-icon-gender-demigirl; } +.#{$ti-prefix}-gender-epicene:before { content: $ti-icon-gender-epicene; } +.#{$ti-prefix}-gender-female:before { content: $ti-icon-gender-female; } +.#{$ti-prefix}-gender-femme:before { content: $ti-icon-gender-femme; } +.#{$ti-prefix}-gender-genderfluid:before { content: $ti-icon-gender-genderfluid; } +.#{$ti-prefix}-gender-genderless:before { content: $ti-icon-gender-genderless; } +.#{$ti-prefix}-gender-genderqueer:before { content: $ti-icon-gender-genderqueer; } +.#{$ti-prefix}-gender-hermaphrodite:before { content: $ti-icon-gender-hermaphrodite; } +.#{$ti-prefix}-gender-intergender:before { content: $ti-icon-gender-intergender; } +.#{$ti-prefix}-gender-male:before { content: $ti-icon-gender-male; } +.#{$ti-prefix}-gender-neutrois:before { content: $ti-icon-gender-neutrois; } +.#{$ti-prefix}-gender-third:before { content: $ti-icon-gender-third; } +.#{$ti-prefix}-gender-transgender:before { content: $ti-icon-gender-transgender; } +.#{$ti-prefix}-gender-trasvesti:before { content: $ti-icon-gender-trasvesti; } +.#{$ti-prefix}-geometry:before { content: $ti-icon-geometry; } +.#{$ti-prefix}-ghost:before { content: $ti-icon-ghost; } +.#{$ti-prefix}-ghost-2:before { content: $ti-icon-ghost-2; } +.#{$ti-prefix}-ghost-2-filled:before { content: $ti-icon-ghost-2-filled; } +.#{$ti-prefix}-ghost-filled:before { content: $ti-icon-ghost-filled; } +.#{$ti-prefix}-ghost-off:before { content: $ti-icon-ghost-off; } +.#{$ti-prefix}-gif:before { content: $ti-icon-gif; } +.#{$ti-prefix}-gift:before { content: $ti-icon-gift; } +.#{$ti-prefix}-gift-card:before { content: $ti-icon-gift-card; } +.#{$ti-prefix}-gift-off:before { content: $ti-icon-gift-off; } +.#{$ti-prefix}-git-branch:before { content: $ti-icon-git-branch; } +.#{$ti-prefix}-git-branch-deleted:before { content: $ti-icon-git-branch-deleted; } +.#{$ti-prefix}-git-cherry-pick:before { content: $ti-icon-git-cherry-pick; } +.#{$ti-prefix}-git-commit:before { content: $ti-icon-git-commit; } +.#{$ti-prefix}-git-compare:before { content: $ti-icon-git-compare; } +.#{$ti-prefix}-git-fork:before { content: $ti-icon-git-fork; } +.#{$ti-prefix}-git-merge:before { content: $ti-icon-git-merge; } +.#{$ti-prefix}-git-pull-request:before { content: $ti-icon-git-pull-request; } +.#{$ti-prefix}-git-pull-request-closed:before { content: $ti-icon-git-pull-request-closed; } +.#{$ti-prefix}-git-pull-request-draft:before { content: $ti-icon-git-pull-request-draft; } +.#{$ti-prefix}-gizmo:before { content: $ti-icon-gizmo; } +.#{$ti-prefix}-glass:before { content: $ti-icon-glass; } +.#{$ti-prefix}-glass-full:before { content: $ti-icon-glass-full; } +.#{$ti-prefix}-glass-off:before { content: $ti-icon-glass-off; } +.#{$ti-prefix}-globe:before { content: $ti-icon-globe; } +.#{$ti-prefix}-globe-off:before { content: $ti-icon-globe-off; } +.#{$ti-prefix}-go-game:before { content: $ti-icon-go-game; } +.#{$ti-prefix}-golf:before { content: $ti-icon-golf; } +.#{$ti-prefix}-golf-off:before { content: $ti-icon-golf-off; } +.#{$ti-prefix}-gps:before { content: $ti-icon-gps; } +.#{$ti-prefix}-gradienter:before { content: $ti-icon-gradienter; } +.#{$ti-prefix}-grain:before { content: $ti-icon-grain; } +.#{$ti-prefix}-graph:before { content: $ti-icon-graph; } +.#{$ti-prefix}-graph-off:before { content: $ti-icon-graph-off; } +.#{$ti-prefix}-grave:before { content: $ti-icon-grave; } +.#{$ti-prefix}-grave-2:before { content: $ti-icon-grave-2; } +.#{$ti-prefix}-grid-dots:before { content: $ti-icon-grid-dots; } +.#{$ti-prefix}-grid-pattern:before { content: $ti-icon-grid-pattern; } +.#{$ti-prefix}-grill:before { content: $ti-icon-grill; } +.#{$ti-prefix}-grill-fork:before { content: $ti-icon-grill-fork; } +.#{$ti-prefix}-grill-off:before { content: $ti-icon-grill-off; } +.#{$ti-prefix}-grill-spatula:before { content: $ti-icon-grill-spatula; } +.#{$ti-prefix}-grip-horizontal:before { content: $ti-icon-grip-horizontal; } +.#{$ti-prefix}-grip-vertical:before { content: $ti-icon-grip-vertical; } +.#{$ti-prefix}-growth:before { content: $ti-icon-growth; } +.#{$ti-prefix}-guitar-pick:before { content: $ti-icon-guitar-pick; } +.#{$ti-prefix}-guitar-pick-filled:before { content: $ti-icon-guitar-pick-filled; } +.#{$ti-prefix}-h-1:before { content: $ti-icon-h-1; } +.#{$ti-prefix}-h-2:before { content: $ti-icon-h-2; } +.#{$ti-prefix}-h-3:before { content: $ti-icon-h-3; } +.#{$ti-prefix}-h-4:before { content: $ti-icon-h-4; } +.#{$ti-prefix}-h-5:before { content: $ti-icon-h-5; } +.#{$ti-prefix}-h-6:before { content: $ti-icon-h-6; } +.#{$ti-prefix}-hammer:before { content: $ti-icon-hammer; } +.#{$ti-prefix}-hammer-off:before { content: $ti-icon-hammer-off; } +.#{$ti-prefix}-hand-click:before { content: $ti-icon-hand-click; } +.#{$ti-prefix}-hand-finger:before { content: $ti-icon-hand-finger; } +.#{$ti-prefix}-hand-finger-off:before { content: $ti-icon-hand-finger-off; } +.#{$ti-prefix}-hand-grab:before { content: $ti-icon-hand-grab; } +.#{$ti-prefix}-hand-little-finger:before { content: $ti-icon-hand-little-finger; } +.#{$ti-prefix}-hand-middle-finger:before { content: $ti-icon-hand-middle-finger; } +.#{$ti-prefix}-hand-move:before { content: $ti-icon-hand-move; } +.#{$ti-prefix}-hand-off:before { content: $ti-icon-hand-off; } +.#{$ti-prefix}-hand-ring-finger:before { content: $ti-icon-hand-ring-finger; } +.#{$ti-prefix}-hand-rock:before { content: $ti-icon-hand-rock; } +.#{$ti-prefix}-hand-sanitizer:before { content: $ti-icon-hand-sanitizer; } +.#{$ti-prefix}-hand-stop:before { content: $ti-icon-hand-stop; } +.#{$ti-prefix}-hand-three-fingers:before { content: $ti-icon-hand-three-fingers; } +.#{$ti-prefix}-hand-two-fingers:before { content: $ti-icon-hand-two-fingers; } +.#{$ti-prefix}-hanger:before { content: $ti-icon-hanger; } +.#{$ti-prefix}-hanger-2:before { content: $ti-icon-hanger-2; } +.#{$ti-prefix}-hanger-off:before { content: $ti-icon-hanger-off; } +.#{$ti-prefix}-hash:before { content: $ti-icon-hash; } +.#{$ti-prefix}-haze:before { content: $ti-icon-haze; } +.#{$ti-prefix}-heading:before { content: $ti-icon-heading; } +.#{$ti-prefix}-heading-off:before { content: $ti-icon-heading-off; } +.#{$ti-prefix}-headphones:before { content: $ti-icon-headphones; } +.#{$ti-prefix}-headphones-off:before { content: $ti-icon-headphones-off; } +.#{$ti-prefix}-headset:before { content: $ti-icon-headset; } +.#{$ti-prefix}-headset-off:before { content: $ti-icon-headset-off; } +.#{$ti-prefix}-health-recognition:before { content: $ti-icon-health-recognition; } +.#{$ti-prefix}-heart:before { content: $ti-icon-heart; } +.#{$ti-prefix}-heart-broken:before { content: $ti-icon-heart-broken; } +.#{$ti-prefix}-heart-filled:before { content: $ti-icon-heart-filled; } +.#{$ti-prefix}-heart-handshake:before { content: $ti-icon-heart-handshake; } +.#{$ti-prefix}-heart-minus:before { content: $ti-icon-heart-minus; } +.#{$ti-prefix}-heart-off:before { content: $ti-icon-heart-off; } +.#{$ti-prefix}-heart-plus:before { content: $ti-icon-heart-plus; } +.#{$ti-prefix}-heart-rate-monitor:before { content: $ti-icon-heart-rate-monitor; } +.#{$ti-prefix}-heartbeat:before { content: $ti-icon-heartbeat; } +.#{$ti-prefix}-hearts:before { content: $ti-icon-hearts; } +.#{$ti-prefix}-hearts-off:before { content: $ti-icon-hearts-off; } +.#{$ti-prefix}-helicopter:before { content: $ti-icon-helicopter; } +.#{$ti-prefix}-helicopter-landing:before { content: $ti-icon-helicopter-landing; } +.#{$ti-prefix}-helmet:before { content: $ti-icon-helmet; } +.#{$ti-prefix}-helmet-off:before { content: $ti-icon-helmet-off; } +.#{$ti-prefix}-help:before { content: $ti-icon-help; } +.#{$ti-prefix}-help-circle:before { content: $ti-icon-help-circle; } +.#{$ti-prefix}-help-hexagon:before { content: $ti-icon-help-hexagon; } +.#{$ti-prefix}-help-octagon:before { content: $ti-icon-help-octagon; } +.#{$ti-prefix}-help-off:before { content: $ti-icon-help-off; } +.#{$ti-prefix}-help-small:before { content: $ti-icon-help-small; } +.#{$ti-prefix}-help-square:before { content: $ti-icon-help-square; } +.#{$ti-prefix}-help-square-rounded:before { content: $ti-icon-help-square-rounded; } +.#{$ti-prefix}-help-triangle:before { content: $ti-icon-help-triangle; } +.#{$ti-prefix}-hexagon:before { content: $ti-icon-hexagon; } +.#{$ti-prefix}-hexagon-0-filled:before { content: $ti-icon-hexagon-0-filled; } +.#{$ti-prefix}-hexagon-1-filled:before { content: $ti-icon-hexagon-1-filled; } +.#{$ti-prefix}-hexagon-2-filled:before { content: $ti-icon-hexagon-2-filled; } +.#{$ti-prefix}-hexagon-3-filled:before { content: $ti-icon-hexagon-3-filled; } +.#{$ti-prefix}-hexagon-3d:before { content: $ti-icon-hexagon-3d; } +.#{$ti-prefix}-hexagon-4-filled:before { content: $ti-icon-hexagon-4-filled; } +.#{$ti-prefix}-hexagon-5-filled:before { content: $ti-icon-hexagon-5-filled; } +.#{$ti-prefix}-hexagon-6-filled:before { content: $ti-icon-hexagon-6-filled; } +.#{$ti-prefix}-hexagon-7-filled:before { content: $ti-icon-hexagon-7-filled; } +.#{$ti-prefix}-hexagon-8-filled:before { content: $ti-icon-hexagon-8-filled; } +.#{$ti-prefix}-hexagon-9-filled:before { content: $ti-icon-hexagon-9-filled; } +.#{$ti-prefix}-hexagon-filled:before { content: $ti-icon-hexagon-filled; } +.#{$ti-prefix}-hexagon-letter-a:before { content: $ti-icon-hexagon-letter-a; } +.#{$ti-prefix}-hexagon-letter-b:before { content: $ti-icon-hexagon-letter-b; } +.#{$ti-prefix}-hexagon-letter-c:before { content: $ti-icon-hexagon-letter-c; } +.#{$ti-prefix}-hexagon-letter-d:before { content: $ti-icon-hexagon-letter-d; } +.#{$ti-prefix}-hexagon-letter-e:before { content: $ti-icon-hexagon-letter-e; } +.#{$ti-prefix}-hexagon-letter-f:before { content: $ti-icon-hexagon-letter-f; } +.#{$ti-prefix}-hexagon-letter-g:before { content: $ti-icon-hexagon-letter-g; } +.#{$ti-prefix}-hexagon-letter-h:before { content: $ti-icon-hexagon-letter-h; } +.#{$ti-prefix}-hexagon-letter-i:before { content: $ti-icon-hexagon-letter-i; } +.#{$ti-prefix}-hexagon-letter-j:before { content: $ti-icon-hexagon-letter-j; } +.#{$ti-prefix}-hexagon-letter-k:before { content: $ti-icon-hexagon-letter-k; } +.#{$ti-prefix}-hexagon-letter-l:before { content: $ti-icon-hexagon-letter-l; } +.#{$ti-prefix}-hexagon-letter-m:before { content: $ti-icon-hexagon-letter-m; } +.#{$ti-prefix}-hexagon-letter-n:before { content: $ti-icon-hexagon-letter-n; } +.#{$ti-prefix}-hexagon-letter-o:before { content: $ti-icon-hexagon-letter-o; } +.#{$ti-prefix}-hexagon-letter-p:before { content: $ti-icon-hexagon-letter-p; } +.#{$ti-prefix}-hexagon-letter-q:before { content: $ti-icon-hexagon-letter-q; } +.#{$ti-prefix}-hexagon-letter-r:before { content: $ti-icon-hexagon-letter-r; } +.#{$ti-prefix}-hexagon-letter-s:before { content: $ti-icon-hexagon-letter-s; } +.#{$ti-prefix}-hexagon-letter-t:before { content: $ti-icon-hexagon-letter-t; } +.#{$ti-prefix}-hexagon-letter-u:before { content: $ti-icon-hexagon-letter-u; } +.#{$ti-prefix}-hexagon-letter-v:before { content: $ti-icon-hexagon-letter-v; } +.#{$ti-prefix}-hexagon-letter-w:before { content: $ti-icon-hexagon-letter-w; } +.#{$ti-prefix}-hexagon-letter-x:before { content: $ti-icon-hexagon-letter-x; } +.#{$ti-prefix}-hexagon-letter-y:before { content: $ti-icon-hexagon-letter-y; } +.#{$ti-prefix}-hexagon-letter-z:before { content: $ti-icon-hexagon-letter-z; } +.#{$ti-prefix}-hexagon-number-0:before { content: $ti-icon-hexagon-number-0; } +.#{$ti-prefix}-hexagon-number-1:before { content: $ti-icon-hexagon-number-1; } +.#{$ti-prefix}-hexagon-number-2:before { content: $ti-icon-hexagon-number-2; } +.#{$ti-prefix}-hexagon-number-3:before { content: $ti-icon-hexagon-number-3; } +.#{$ti-prefix}-hexagon-number-4:before { content: $ti-icon-hexagon-number-4; } +.#{$ti-prefix}-hexagon-number-5:before { content: $ti-icon-hexagon-number-5; } +.#{$ti-prefix}-hexagon-number-6:before { content: $ti-icon-hexagon-number-6; } +.#{$ti-prefix}-hexagon-number-7:before { content: $ti-icon-hexagon-number-7; } +.#{$ti-prefix}-hexagon-number-8:before { content: $ti-icon-hexagon-number-8; } +.#{$ti-prefix}-hexagon-number-9:before { content: $ti-icon-hexagon-number-9; } +.#{$ti-prefix}-hexagon-off:before { content: $ti-icon-hexagon-off; } +.#{$ti-prefix}-hexagons:before { content: $ti-icon-hexagons; } +.#{$ti-prefix}-hexagons-off:before { content: $ti-icon-hexagons-off; } +.#{$ti-prefix}-hierarchy:before { content: $ti-icon-hierarchy; } +.#{$ti-prefix}-hierarchy-2:before { content: $ti-icon-hierarchy-2; } +.#{$ti-prefix}-hierarchy-3:before { content: $ti-icon-hierarchy-3; } +.#{$ti-prefix}-hierarchy-off:before { content: $ti-icon-hierarchy-off; } +.#{$ti-prefix}-highlight:before { content: $ti-icon-highlight; } +.#{$ti-prefix}-highlight-off:before { content: $ti-icon-highlight-off; } +.#{$ti-prefix}-history:before { content: $ti-icon-history; } +.#{$ti-prefix}-history-off:before { content: $ti-icon-history-off; } +.#{$ti-prefix}-history-toggle:before { content: $ti-icon-history-toggle; } +.#{$ti-prefix}-home:before { content: $ti-icon-home; } +.#{$ti-prefix}-home-2:before { content: $ti-icon-home-2; } +.#{$ti-prefix}-home-bolt:before { content: $ti-icon-home-bolt; } +.#{$ti-prefix}-home-cancel:before { content: $ti-icon-home-cancel; } +.#{$ti-prefix}-home-check:before { content: $ti-icon-home-check; } +.#{$ti-prefix}-home-cog:before { content: $ti-icon-home-cog; } +.#{$ti-prefix}-home-dollar:before { content: $ti-icon-home-dollar; } +.#{$ti-prefix}-home-dot:before { content: $ti-icon-home-dot; } +.#{$ti-prefix}-home-down:before { content: $ti-icon-home-down; } +.#{$ti-prefix}-home-eco:before { content: $ti-icon-home-eco; } +.#{$ti-prefix}-home-edit:before { content: $ti-icon-home-edit; } +.#{$ti-prefix}-home-exclamation:before { content: $ti-icon-home-exclamation; } +.#{$ti-prefix}-home-hand:before { content: $ti-icon-home-hand; } +.#{$ti-prefix}-home-heart:before { content: $ti-icon-home-heart; } +.#{$ti-prefix}-home-infinity:before { content: $ti-icon-home-infinity; } +.#{$ti-prefix}-home-link:before { content: $ti-icon-home-link; } +.#{$ti-prefix}-home-minus:before { content: $ti-icon-home-minus; } +.#{$ti-prefix}-home-move:before { content: $ti-icon-home-move; } +.#{$ti-prefix}-home-off:before { content: $ti-icon-home-off; } +.#{$ti-prefix}-home-plus:before { content: $ti-icon-home-plus; } +.#{$ti-prefix}-home-question:before { content: $ti-icon-home-question; } +.#{$ti-prefix}-home-ribbon:before { content: $ti-icon-home-ribbon; } +.#{$ti-prefix}-home-search:before { content: $ti-icon-home-search; } +.#{$ti-prefix}-home-share:before { content: $ti-icon-home-share; } +.#{$ti-prefix}-home-shield:before { content: $ti-icon-home-shield; } +.#{$ti-prefix}-home-signal:before { content: $ti-icon-home-signal; } +.#{$ti-prefix}-home-star:before { content: $ti-icon-home-star; } +.#{$ti-prefix}-home-stats:before { content: $ti-icon-home-stats; } +.#{$ti-prefix}-home-up:before { content: $ti-icon-home-up; } +.#{$ti-prefix}-home-x:before { content: $ti-icon-home-x; } +.#{$ti-prefix}-horse-toy:before { content: $ti-icon-horse-toy; } +.#{$ti-prefix}-hotel-service:before { content: $ti-icon-hotel-service; } +.#{$ti-prefix}-hourglass:before { content: $ti-icon-hourglass; } +.#{$ti-prefix}-hourglass-empty:before { content: $ti-icon-hourglass-empty; } +.#{$ti-prefix}-hourglass-filled:before { content: $ti-icon-hourglass-filled; } +.#{$ti-prefix}-hourglass-high:before { content: $ti-icon-hourglass-high; } +.#{$ti-prefix}-hourglass-low:before { content: $ti-icon-hourglass-low; } +.#{$ti-prefix}-hourglass-off:before { content: $ti-icon-hourglass-off; } +.#{$ti-prefix}-html:before { content: $ti-icon-html; } +.#{$ti-prefix}-ice-cream:before { content: $ti-icon-ice-cream; } +.#{$ti-prefix}-ice-cream-2:before { content: $ti-icon-ice-cream-2; } +.#{$ti-prefix}-ice-cream-off:before { content: $ti-icon-ice-cream-off; } +.#{$ti-prefix}-ice-skating:before { content: $ti-icon-ice-skating; } +.#{$ti-prefix}-icons:before { content: $ti-icon-icons; } +.#{$ti-prefix}-icons-off:before { content: $ti-icon-icons-off; } +.#{$ti-prefix}-id:before { content: $ti-icon-id; } +.#{$ti-prefix}-id-badge:before { content: $ti-icon-id-badge; } +.#{$ti-prefix}-id-badge-2:before { content: $ti-icon-id-badge-2; } +.#{$ti-prefix}-id-badge-off:before { content: $ti-icon-id-badge-off; } +.#{$ti-prefix}-id-off:before { content: $ti-icon-id-off; } +.#{$ti-prefix}-inbox:before { content: $ti-icon-inbox; } +.#{$ti-prefix}-inbox-off:before { content: $ti-icon-inbox-off; } +.#{$ti-prefix}-indent-decrease:before { content: $ti-icon-indent-decrease; } +.#{$ti-prefix}-indent-increase:before { content: $ti-icon-indent-increase; } +.#{$ti-prefix}-infinity:before { content: $ti-icon-infinity; } +.#{$ti-prefix}-infinity-off:before { content: $ti-icon-infinity-off; } +.#{$ti-prefix}-info-circle:before { content: $ti-icon-info-circle; } +.#{$ti-prefix}-info-circle-filled:before { content: $ti-icon-info-circle-filled; } +.#{$ti-prefix}-info-hexagon:before { content: $ti-icon-info-hexagon; } +.#{$ti-prefix}-info-octagon:before { content: $ti-icon-info-octagon; } +.#{$ti-prefix}-info-small:before { content: $ti-icon-info-small; } +.#{$ti-prefix}-info-square:before { content: $ti-icon-info-square; } +.#{$ti-prefix}-info-square-rounded:before { content: $ti-icon-info-square-rounded; } +.#{$ti-prefix}-info-square-rounded-filled:before { content: $ti-icon-info-square-rounded-filled; } +.#{$ti-prefix}-info-triangle:before { content: $ti-icon-info-triangle; } +.#{$ti-prefix}-inner-shadow-bottom:before { content: $ti-icon-inner-shadow-bottom; } +.#{$ti-prefix}-inner-shadow-bottom-filled:before { content: $ti-icon-inner-shadow-bottom-filled; } +.#{$ti-prefix}-inner-shadow-bottom-left:before { content: $ti-icon-inner-shadow-bottom-left; } +.#{$ti-prefix}-inner-shadow-bottom-left-filled:before { content: $ti-icon-inner-shadow-bottom-left-filled; } +.#{$ti-prefix}-inner-shadow-bottom-right:before { content: $ti-icon-inner-shadow-bottom-right; } +.#{$ti-prefix}-inner-shadow-bottom-right-filled:before { content: $ti-icon-inner-shadow-bottom-right-filled; } +.#{$ti-prefix}-inner-shadow-left:before { content: $ti-icon-inner-shadow-left; } +.#{$ti-prefix}-inner-shadow-left-filled:before { content: $ti-icon-inner-shadow-left-filled; } +.#{$ti-prefix}-inner-shadow-right:before { content: $ti-icon-inner-shadow-right; } +.#{$ti-prefix}-inner-shadow-right-filled:before { content: $ti-icon-inner-shadow-right-filled; } +.#{$ti-prefix}-inner-shadow-top:before { content: $ti-icon-inner-shadow-top; } +.#{$ti-prefix}-inner-shadow-top-filled:before { content: $ti-icon-inner-shadow-top-filled; } +.#{$ti-prefix}-inner-shadow-top-left:before { content: $ti-icon-inner-shadow-top-left; } +.#{$ti-prefix}-inner-shadow-top-left-filled:before { content: $ti-icon-inner-shadow-top-left-filled; } +.#{$ti-prefix}-inner-shadow-top-right:before { content: $ti-icon-inner-shadow-top-right; } +.#{$ti-prefix}-inner-shadow-top-right-filled:before { content: $ti-icon-inner-shadow-top-right-filled; } +.#{$ti-prefix}-input-search:before { content: $ti-icon-input-search; } +.#{$ti-prefix}-ironing-1:before { content: $ti-icon-ironing-1; } +.#{$ti-prefix}-ironing-2:before { content: $ti-icon-ironing-2; } +.#{$ti-prefix}-ironing-3:before { content: $ti-icon-ironing-3; } +.#{$ti-prefix}-ironing-off:before { content: $ti-icon-ironing-off; } +.#{$ti-prefix}-ironing-steam:before { content: $ti-icon-ironing-steam; } +.#{$ti-prefix}-ironing-steam-off:before { content: $ti-icon-ironing-steam-off; } +.#{$ti-prefix}-italic:before { content: $ti-icon-italic; } +.#{$ti-prefix}-jacket:before { content: $ti-icon-jacket; } +.#{$ti-prefix}-jetpack:before { content: $ti-icon-jetpack; } +.#{$ti-prefix}-jewish-star:before { content: $ti-icon-jewish-star; } +.#{$ti-prefix}-jewish-star-filled:before { content: $ti-icon-jewish-star-filled; } +.#{$ti-prefix}-jpg:before { content: $ti-icon-jpg; } +.#{$ti-prefix}-json:before { content: $ti-icon-json; } +.#{$ti-prefix}-jump-rope:before { content: $ti-icon-jump-rope; } +.#{$ti-prefix}-karate:before { content: $ti-icon-karate; } +.#{$ti-prefix}-kayak:before { content: $ti-icon-kayak; } +.#{$ti-prefix}-kering:before { content: $ti-icon-kering; } +.#{$ti-prefix}-key:before { content: $ti-icon-key; } +.#{$ti-prefix}-key-off:before { content: $ti-icon-key-off; } +.#{$ti-prefix}-keyboard:before { content: $ti-icon-keyboard; } +.#{$ti-prefix}-keyboard-hide:before { content: $ti-icon-keyboard-hide; } +.#{$ti-prefix}-keyboard-off:before { content: $ti-icon-keyboard-off; } +.#{$ti-prefix}-keyboard-show:before { content: $ti-icon-keyboard-show; } +.#{$ti-prefix}-keyframe:before { content: $ti-icon-keyframe; } +.#{$ti-prefix}-keyframe-align-center:before { content: $ti-icon-keyframe-align-center; } +.#{$ti-prefix}-keyframe-align-horizontal:before { content: $ti-icon-keyframe-align-horizontal; } +.#{$ti-prefix}-keyframe-align-vertical:before { content: $ti-icon-keyframe-align-vertical; } +.#{$ti-prefix}-keyframes:before { content: $ti-icon-keyframes; } +.#{$ti-prefix}-ladder:before { content: $ti-icon-ladder; } +.#{$ti-prefix}-ladder-off:before { content: $ti-icon-ladder-off; } +.#{$ti-prefix}-lambda:before { content: $ti-icon-lambda; } +.#{$ti-prefix}-lamp:before { content: $ti-icon-lamp; } +.#{$ti-prefix}-lamp-2:before { content: $ti-icon-lamp-2; } +.#{$ti-prefix}-lamp-off:before { content: $ti-icon-lamp-off; } +.#{$ti-prefix}-language:before { content: $ti-icon-language; } +.#{$ti-prefix}-language-hiragana:before { content: $ti-icon-language-hiragana; } +.#{$ti-prefix}-language-katakana:before { content: $ti-icon-language-katakana; } +.#{$ti-prefix}-language-off:before { content: $ti-icon-language-off; } +.#{$ti-prefix}-lasso:before { content: $ti-icon-lasso; } +.#{$ti-prefix}-lasso-off:before { content: $ti-icon-lasso-off; } +.#{$ti-prefix}-lasso-polygon:before { content: $ti-icon-lasso-polygon; } +.#{$ti-prefix}-layers-difference:before { content: $ti-icon-layers-difference; } +.#{$ti-prefix}-layers-intersect:before { content: $ti-icon-layers-intersect; } +.#{$ti-prefix}-layers-intersect-2:before { content: $ti-icon-layers-intersect-2; } +.#{$ti-prefix}-layers-linked:before { content: $ti-icon-layers-linked; } +.#{$ti-prefix}-layers-off:before { content: $ti-icon-layers-off; } +.#{$ti-prefix}-layers-subtract:before { content: $ti-icon-layers-subtract; } +.#{$ti-prefix}-layers-union:before { content: $ti-icon-layers-union; } +.#{$ti-prefix}-layout:before { content: $ti-icon-layout; } +.#{$ti-prefix}-layout-2:before { content: $ti-icon-layout-2; } +.#{$ti-prefix}-layout-align-bottom:before { content: $ti-icon-layout-align-bottom; } +.#{$ti-prefix}-layout-align-center:before { content: $ti-icon-layout-align-center; } +.#{$ti-prefix}-layout-align-left:before { content: $ti-icon-layout-align-left; } +.#{$ti-prefix}-layout-align-middle:before { content: $ti-icon-layout-align-middle; } +.#{$ti-prefix}-layout-align-right:before { content: $ti-icon-layout-align-right; } +.#{$ti-prefix}-layout-align-top:before { content: $ti-icon-layout-align-top; } +.#{$ti-prefix}-layout-board:before { content: $ti-icon-layout-board; } +.#{$ti-prefix}-layout-board-split:before { content: $ti-icon-layout-board-split; } +.#{$ti-prefix}-layout-bottombar:before { content: $ti-icon-layout-bottombar; } +.#{$ti-prefix}-layout-bottombar-collapse:before { content: $ti-icon-layout-bottombar-collapse; } +.#{$ti-prefix}-layout-bottombar-expand:before { content: $ti-icon-layout-bottombar-expand; } +.#{$ti-prefix}-layout-cards:before { content: $ti-icon-layout-cards; } +.#{$ti-prefix}-layout-collage:before { content: $ti-icon-layout-collage; } +.#{$ti-prefix}-layout-columns:before { content: $ti-icon-layout-columns; } +.#{$ti-prefix}-layout-dashboard:before { content: $ti-icon-layout-dashboard; } +.#{$ti-prefix}-layout-distribute-horizontal:before { content: $ti-icon-layout-distribute-horizontal; } +.#{$ti-prefix}-layout-distribute-vertical:before { content: $ti-icon-layout-distribute-vertical; } +.#{$ti-prefix}-layout-grid:before { content: $ti-icon-layout-grid; } +.#{$ti-prefix}-layout-grid-add:before { content: $ti-icon-layout-grid-add; } +.#{$ti-prefix}-layout-kanban:before { content: $ti-icon-layout-kanban; } +.#{$ti-prefix}-layout-list:before { content: $ti-icon-layout-list; } +.#{$ti-prefix}-layout-navbar:before { content: $ti-icon-layout-navbar; } +.#{$ti-prefix}-layout-navbar-collapse:before { content: $ti-icon-layout-navbar-collapse; } +.#{$ti-prefix}-layout-navbar-expand:before { content: $ti-icon-layout-navbar-expand; } +.#{$ti-prefix}-layout-off:before { content: $ti-icon-layout-off; } +.#{$ti-prefix}-layout-rows:before { content: $ti-icon-layout-rows; } +.#{$ti-prefix}-layout-sidebar:before { content: $ti-icon-layout-sidebar; } +.#{$ti-prefix}-layout-sidebar-left-collapse:before { content: $ti-icon-layout-sidebar-left-collapse; } +.#{$ti-prefix}-layout-sidebar-left-expand:before { content: $ti-icon-layout-sidebar-left-expand; } +.#{$ti-prefix}-layout-sidebar-right:before { content: $ti-icon-layout-sidebar-right; } +.#{$ti-prefix}-layout-sidebar-right-collapse:before { content: $ti-icon-layout-sidebar-right-collapse; } +.#{$ti-prefix}-layout-sidebar-right-expand:before { content: $ti-icon-layout-sidebar-right-expand; } +.#{$ti-prefix}-leaf:before { content: $ti-icon-leaf; } +.#{$ti-prefix}-leaf-off:before { content: $ti-icon-leaf-off; } +.#{$ti-prefix}-lego:before { content: $ti-icon-lego; } +.#{$ti-prefix}-lego-off:before { content: $ti-icon-lego-off; } +.#{$ti-prefix}-lemon:before { content: $ti-icon-lemon; } +.#{$ti-prefix}-lemon-2:before { content: $ti-icon-lemon-2; } +.#{$ti-prefix}-letter-a:before { content: $ti-icon-letter-a; } +.#{$ti-prefix}-letter-b:before { content: $ti-icon-letter-b; } +.#{$ti-prefix}-letter-c:before { content: $ti-icon-letter-c; } +.#{$ti-prefix}-letter-case:before { content: $ti-icon-letter-case; } +.#{$ti-prefix}-letter-case-lower:before { content: $ti-icon-letter-case-lower; } +.#{$ti-prefix}-letter-case-toggle:before { content: $ti-icon-letter-case-toggle; } +.#{$ti-prefix}-letter-case-upper:before { content: $ti-icon-letter-case-upper; } +.#{$ti-prefix}-letter-d:before { content: $ti-icon-letter-d; } +.#{$ti-prefix}-letter-e:before { content: $ti-icon-letter-e; } +.#{$ti-prefix}-letter-f:before { content: $ti-icon-letter-f; } +.#{$ti-prefix}-letter-g:before { content: $ti-icon-letter-g; } +.#{$ti-prefix}-letter-h:before { content: $ti-icon-letter-h; } +.#{$ti-prefix}-letter-i:before { content: $ti-icon-letter-i; } +.#{$ti-prefix}-letter-j:before { content: $ti-icon-letter-j; } +.#{$ti-prefix}-letter-k:before { content: $ti-icon-letter-k; } +.#{$ti-prefix}-letter-l:before { content: $ti-icon-letter-l; } +.#{$ti-prefix}-letter-m:before { content: $ti-icon-letter-m; } +.#{$ti-prefix}-letter-n:before { content: $ti-icon-letter-n; } +.#{$ti-prefix}-letter-o:before { content: $ti-icon-letter-o; } +.#{$ti-prefix}-letter-p:before { content: $ti-icon-letter-p; } +.#{$ti-prefix}-letter-q:before { content: $ti-icon-letter-q; } +.#{$ti-prefix}-letter-r:before { content: $ti-icon-letter-r; } +.#{$ti-prefix}-letter-s:before { content: $ti-icon-letter-s; } +.#{$ti-prefix}-letter-spacing:before { content: $ti-icon-letter-spacing; } +.#{$ti-prefix}-letter-t:before { content: $ti-icon-letter-t; } +.#{$ti-prefix}-letter-u:before { content: $ti-icon-letter-u; } +.#{$ti-prefix}-letter-v:before { content: $ti-icon-letter-v; } +.#{$ti-prefix}-letter-w:before { content: $ti-icon-letter-w; } +.#{$ti-prefix}-letter-x:before { content: $ti-icon-letter-x; } +.#{$ti-prefix}-letter-y:before { content: $ti-icon-letter-y; } +.#{$ti-prefix}-letter-z:before { content: $ti-icon-letter-z; } +.#{$ti-prefix}-license:before { content: $ti-icon-license; } +.#{$ti-prefix}-license-off:before { content: $ti-icon-license-off; } +.#{$ti-prefix}-lifebuoy:before { content: $ti-icon-lifebuoy; } +.#{$ti-prefix}-lifebuoy-off:before { content: $ti-icon-lifebuoy-off; } +.#{$ti-prefix}-lighter:before { content: $ti-icon-lighter; } +.#{$ti-prefix}-line:before { content: $ti-icon-line; } +.#{$ti-prefix}-line-dashed:before { content: $ti-icon-line-dashed; } +.#{$ti-prefix}-line-dotted:before { content: $ti-icon-line-dotted; } +.#{$ti-prefix}-line-height:before { content: $ti-icon-line-height; } +.#{$ti-prefix}-link:before { content: $ti-icon-link; } +.#{$ti-prefix}-link-off:before { content: $ti-icon-link-off; } +.#{$ti-prefix}-list:before { content: $ti-icon-list; } +.#{$ti-prefix}-list-check:before { content: $ti-icon-list-check; } +.#{$ti-prefix}-list-details:before { content: $ti-icon-list-details; } +.#{$ti-prefix}-list-numbers:before { content: $ti-icon-list-numbers; } +.#{$ti-prefix}-list-search:before { content: $ti-icon-list-search; } +.#{$ti-prefix}-live-photo:before { content: $ti-icon-live-photo; } +.#{$ti-prefix}-live-photo-off:before { content: $ti-icon-live-photo-off; } +.#{$ti-prefix}-live-view:before { content: $ti-icon-live-view; } +.#{$ti-prefix}-loader:before { content: $ti-icon-loader; } +.#{$ti-prefix}-loader-2:before { content: $ti-icon-loader-2; } +.#{$ti-prefix}-loader-3:before { content: $ti-icon-loader-3; } +.#{$ti-prefix}-loader-quarter:before { content: $ti-icon-loader-quarter; } +.#{$ti-prefix}-location:before { content: $ti-icon-location; } +.#{$ti-prefix}-location-broken:before { content: $ti-icon-location-broken; } +.#{$ti-prefix}-location-filled:before { content: $ti-icon-location-filled; } +.#{$ti-prefix}-location-off:before { content: $ti-icon-location-off; } +.#{$ti-prefix}-lock:before { content: $ti-icon-lock; } +.#{$ti-prefix}-lock-access:before { content: $ti-icon-lock-access; } +.#{$ti-prefix}-lock-access-off:before { content: $ti-icon-lock-access-off; } +.#{$ti-prefix}-lock-bolt:before { content: $ti-icon-lock-bolt; } +.#{$ti-prefix}-lock-cancel:before { content: $ti-icon-lock-cancel; } +.#{$ti-prefix}-lock-check:before { content: $ti-icon-lock-check; } +.#{$ti-prefix}-lock-code:before { content: $ti-icon-lock-code; } +.#{$ti-prefix}-lock-cog:before { content: $ti-icon-lock-cog; } +.#{$ti-prefix}-lock-dollar:before { content: $ti-icon-lock-dollar; } +.#{$ti-prefix}-lock-down:before { content: $ti-icon-lock-down; } +.#{$ti-prefix}-lock-exclamation:before { content: $ti-icon-lock-exclamation; } +.#{$ti-prefix}-lock-heart:before { content: $ti-icon-lock-heart; } +.#{$ti-prefix}-lock-minus:before { content: $ti-icon-lock-minus; } +.#{$ti-prefix}-lock-off:before { content: $ti-icon-lock-off; } +.#{$ti-prefix}-lock-open:before { content: $ti-icon-lock-open; } +.#{$ti-prefix}-lock-open-off:before { content: $ti-icon-lock-open-off; } +.#{$ti-prefix}-lock-pause:before { content: $ti-icon-lock-pause; } +.#{$ti-prefix}-lock-pin:before { content: $ti-icon-lock-pin; } +.#{$ti-prefix}-lock-plus:before { content: $ti-icon-lock-plus; } +.#{$ti-prefix}-lock-question:before { content: $ti-icon-lock-question; } +.#{$ti-prefix}-lock-search:before { content: $ti-icon-lock-search; } +.#{$ti-prefix}-lock-share:before { content: $ti-icon-lock-share; } +.#{$ti-prefix}-lock-square:before { content: $ti-icon-lock-square; } +.#{$ti-prefix}-lock-square-rounded:before { content: $ti-icon-lock-square-rounded; } +.#{$ti-prefix}-lock-square-rounded-filled:before { content: $ti-icon-lock-square-rounded-filled; } +.#{$ti-prefix}-lock-star:before { content: $ti-icon-lock-star; } +.#{$ti-prefix}-lock-up:before { content: $ti-icon-lock-up; } +.#{$ti-prefix}-lock-x:before { content: $ti-icon-lock-x; } +.#{$ti-prefix}-logic-and:before { content: $ti-icon-logic-and; } +.#{$ti-prefix}-logic-buffer:before { content: $ti-icon-logic-buffer; } +.#{$ti-prefix}-logic-nand:before { content: $ti-icon-logic-nand; } +.#{$ti-prefix}-logic-nor:before { content: $ti-icon-logic-nor; } +.#{$ti-prefix}-logic-not:before { content: $ti-icon-logic-not; } +.#{$ti-prefix}-logic-or:before { content: $ti-icon-logic-or; } +.#{$ti-prefix}-logic-xnor:before { content: $ti-icon-logic-xnor; } +.#{$ti-prefix}-logic-xor:before { content: $ti-icon-logic-xor; } +.#{$ti-prefix}-login:before { content: $ti-icon-login; } +.#{$ti-prefix}-logout:before { content: $ti-icon-logout; } +.#{$ti-prefix}-lollipop:before { content: $ti-icon-lollipop; } +.#{$ti-prefix}-lollipop-off:before { content: $ti-icon-lollipop-off; } +.#{$ti-prefix}-luggage:before { content: $ti-icon-luggage; } +.#{$ti-prefix}-luggage-off:before { content: $ti-icon-luggage-off; } +.#{$ti-prefix}-lungs:before { content: $ti-icon-lungs; } +.#{$ti-prefix}-lungs-off:before { content: $ti-icon-lungs-off; } +.#{$ti-prefix}-macro:before { content: $ti-icon-macro; } +.#{$ti-prefix}-macro-off:before { content: $ti-icon-macro-off; } +.#{$ti-prefix}-magnet:before { content: $ti-icon-magnet; } +.#{$ti-prefix}-magnet-off:before { content: $ti-icon-magnet-off; } +.#{$ti-prefix}-mail:before { content: $ti-icon-mail; } +.#{$ti-prefix}-mail-bolt:before { content: $ti-icon-mail-bolt; } +.#{$ti-prefix}-mail-cancel:before { content: $ti-icon-mail-cancel; } +.#{$ti-prefix}-mail-check:before { content: $ti-icon-mail-check; } +.#{$ti-prefix}-mail-code:before { content: $ti-icon-mail-code; } +.#{$ti-prefix}-mail-cog:before { content: $ti-icon-mail-cog; } +.#{$ti-prefix}-mail-dollar:before { content: $ti-icon-mail-dollar; } +.#{$ti-prefix}-mail-down:before { content: $ti-icon-mail-down; } +.#{$ti-prefix}-mail-exclamation:before { content: $ti-icon-mail-exclamation; } +.#{$ti-prefix}-mail-fast:before { content: $ti-icon-mail-fast; } +.#{$ti-prefix}-mail-forward:before { content: $ti-icon-mail-forward; } +.#{$ti-prefix}-mail-heart:before { content: $ti-icon-mail-heart; } +.#{$ti-prefix}-mail-minus:before { content: $ti-icon-mail-minus; } +.#{$ti-prefix}-mail-off:before { content: $ti-icon-mail-off; } +.#{$ti-prefix}-mail-opened:before { content: $ti-icon-mail-opened; } +.#{$ti-prefix}-mail-pause:before { content: $ti-icon-mail-pause; } +.#{$ti-prefix}-mail-pin:before { content: $ti-icon-mail-pin; } +.#{$ti-prefix}-mail-plus:before { content: $ti-icon-mail-plus; } +.#{$ti-prefix}-mail-question:before { content: $ti-icon-mail-question; } +.#{$ti-prefix}-mail-search:before { content: $ti-icon-mail-search; } +.#{$ti-prefix}-mail-share:before { content: $ti-icon-mail-share; } +.#{$ti-prefix}-mail-star:before { content: $ti-icon-mail-star; } +.#{$ti-prefix}-mail-up:before { content: $ti-icon-mail-up; } +.#{$ti-prefix}-mail-x:before { content: $ti-icon-mail-x; } +.#{$ti-prefix}-mailbox:before { content: $ti-icon-mailbox; } +.#{$ti-prefix}-mailbox-off:before { content: $ti-icon-mailbox-off; } +.#{$ti-prefix}-man:before { content: $ti-icon-man; } +.#{$ti-prefix}-manual-gearbox:before { content: $ti-icon-manual-gearbox; } +.#{$ti-prefix}-map:before { content: $ti-icon-map; } +.#{$ti-prefix}-map-2:before { content: $ti-icon-map-2; } +.#{$ti-prefix}-map-off:before { content: $ti-icon-map-off; } +.#{$ti-prefix}-map-pin:before { content: $ti-icon-map-pin; } +.#{$ti-prefix}-map-pin-bolt:before { content: $ti-icon-map-pin-bolt; } +.#{$ti-prefix}-map-pin-cancel:before { content: $ti-icon-map-pin-cancel; } +.#{$ti-prefix}-map-pin-check:before { content: $ti-icon-map-pin-check; } +.#{$ti-prefix}-map-pin-code:before { content: $ti-icon-map-pin-code; } +.#{$ti-prefix}-map-pin-cog:before { content: $ti-icon-map-pin-cog; } +.#{$ti-prefix}-map-pin-dollar:before { content: $ti-icon-map-pin-dollar; } +.#{$ti-prefix}-map-pin-down:before { content: $ti-icon-map-pin-down; } +.#{$ti-prefix}-map-pin-exclamation:before { content: $ti-icon-map-pin-exclamation; } +.#{$ti-prefix}-map-pin-filled:before { content: $ti-icon-map-pin-filled; } +.#{$ti-prefix}-map-pin-heart:before { content: $ti-icon-map-pin-heart; } +.#{$ti-prefix}-map-pin-minus:before { content: $ti-icon-map-pin-minus; } +.#{$ti-prefix}-map-pin-off:before { content: $ti-icon-map-pin-off; } +.#{$ti-prefix}-map-pin-pause:before { content: $ti-icon-map-pin-pause; } +.#{$ti-prefix}-map-pin-pin:before { content: $ti-icon-map-pin-pin; } +.#{$ti-prefix}-map-pin-plus:before { content: $ti-icon-map-pin-plus; } +.#{$ti-prefix}-map-pin-question:before { content: $ti-icon-map-pin-question; } +.#{$ti-prefix}-map-pin-search:before { content: $ti-icon-map-pin-search; } +.#{$ti-prefix}-map-pin-share:before { content: $ti-icon-map-pin-share; } +.#{$ti-prefix}-map-pin-star:before { content: $ti-icon-map-pin-star; } +.#{$ti-prefix}-map-pin-up:before { content: $ti-icon-map-pin-up; } +.#{$ti-prefix}-map-pin-x:before { content: $ti-icon-map-pin-x; } +.#{$ti-prefix}-map-pins:before { content: $ti-icon-map-pins; } +.#{$ti-prefix}-map-search:before { content: $ti-icon-map-search; } +.#{$ti-prefix}-markdown:before { content: $ti-icon-markdown; } +.#{$ti-prefix}-markdown-off:before { content: $ti-icon-markdown-off; } +.#{$ti-prefix}-marquee:before { content: $ti-icon-marquee; } +.#{$ti-prefix}-marquee-2:before { content: $ti-icon-marquee-2; } +.#{$ti-prefix}-marquee-off:before { content: $ti-icon-marquee-off; } +.#{$ti-prefix}-mars:before { content: $ti-icon-mars; } +.#{$ti-prefix}-mask:before { content: $ti-icon-mask; } +.#{$ti-prefix}-mask-off:before { content: $ti-icon-mask-off; } +.#{$ti-prefix}-masks-theater:before { content: $ti-icon-masks-theater; } +.#{$ti-prefix}-masks-theater-off:before { content: $ti-icon-masks-theater-off; } +.#{$ti-prefix}-massage:before { content: $ti-icon-massage; } +.#{$ti-prefix}-matchstick:before { content: $ti-icon-matchstick; } +.#{$ti-prefix}-math:before { content: $ti-icon-math; } +.#{$ti-prefix}-math-1-divide-2:before { content: $ti-icon-math-1-divide-2; } +.#{$ti-prefix}-math-1-divide-3:before { content: $ti-icon-math-1-divide-3; } +.#{$ti-prefix}-math-avg:before { content: $ti-icon-math-avg; } +.#{$ti-prefix}-math-equal-greater:before { content: $ti-icon-math-equal-greater; } +.#{$ti-prefix}-math-equal-lower:before { content: $ti-icon-math-equal-lower; } +.#{$ti-prefix}-math-function:before { content: $ti-icon-math-function; } +.#{$ti-prefix}-math-function-off:before { content: $ti-icon-math-function-off; } +.#{$ti-prefix}-math-function-y:before { content: $ti-icon-math-function-y; } +.#{$ti-prefix}-math-greater:before { content: $ti-icon-math-greater; } +.#{$ti-prefix}-math-integral:before { content: $ti-icon-math-integral; } +.#{$ti-prefix}-math-integral-x:before { content: $ti-icon-math-integral-x; } +.#{$ti-prefix}-math-integrals:before { content: $ti-icon-math-integrals; } +.#{$ti-prefix}-math-lower:before { content: $ti-icon-math-lower; } +.#{$ti-prefix}-math-max:before { content: $ti-icon-math-max; } +.#{$ti-prefix}-math-min:before { content: $ti-icon-math-min; } +.#{$ti-prefix}-math-not:before { content: $ti-icon-math-not; } +.#{$ti-prefix}-math-off:before { content: $ti-icon-math-off; } +.#{$ti-prefix}-math-pi:before { content: $ti-icon-math-pi; } +.#{$ti-prefix}-math-pi-divide-2:before { content: $ti-icon-math-pi-divide-2; } +.#{$ti-prefix}-math-symbols:before { content: $ti-icon-math-symbols; } +.#{$ti-prefix}-math-x-divide-2:before { content: $ti-icon-math-x-divide-2; } +.#{$ti-prefix}-math-x-divide-y:before { content: $ti-icon-math-x-divide-y; } +.#{$ti-prefix}-math-x-divide-y-2:before { content: $ti-icon-math-x-divide-y-2; } +.#{$ti-prefix}-math-x-minus-x:before { content: $ti-icon-math-x-minus-x; } +.#{$ti-prefix}-math-x-minus-y:before { content: $ti-icon-math-x-minus-y; } +.#{$ti-prefix}-math-x-plus-x:before { content: $ti-icon-math-x-plus-x; } +.#{$ti-prefix}-math-x-plus-y:before { content: $ti-icon-math-x-plus-y; } +.#{$ti-prefix}-math-xy:before { content: $ti-icon-math-xy; } +.#{$ti-prefix}-math-y-minus-y:before { content: $ti-icon-math-y-minus-y; } +.#{$ti-prefix}-math-y-plus-y:before { content: $ti-icon-math-y-plus-y; } +.#{$ti-prefix}-maximize:before { content: $ti-icon-maximize; } +.#{$ti-prefix}-maximize-off:before { content: $ti-icon-maximize-off; } +.#{$ti-prefix}-meat:before { content: $ti-icon-meat; } +.#{$ti-prefix}-meat-off:before { content: $ti-icon-meat-off; } +.#{$ti-prefix}-medal:before { content: $ti-icon-medal; } +.#{$ti-prefix}-medal-2:before { content: $ti-icon-medal-2; } +.#{$ti-prefix}-medical-cross:before { content: $ti-icon-medical-cross; } +.#{$ti-prefix}-medical-cross-filled:before { content: $ti-icon-medical-cross-filled; } +.#{$ti-prefix}-medical-cross-off:before { content: $ti-icon-medical-cross-off; } +.#{$ti-prefix}-medicine-syrup:before { content: $ti-icon-medicine-syrup; } +.#{$ti-prefix}-meeple:before { content: $ti-icon-meeple; } +.#{$ti-prefix}-menorah:before { content: $ti-icon-menorah; } +.#{$ti-prefix}-menu:before { content: $ti-icon-menu; } +.#{$ti-prefix}-menu-2:before { content: $ti-icon-menu-2; } +.#{$ti-prefix}-menu-order:before { content: $ti-icon-menu-order; } +.#{$ti-prefix}-message:before { content: $ti-icon-message; } +.#{$ti-prefix}-message-2:before { content: $ti-icon-message-2; } +.#{$ti-prefix}-message-2-bolt:before { content: $ti-icon-message-2-bolt; } +.#{$ti-prefix}-message-2-cancel:before { content: $ti-icon-message-2-cancel; } +.#{$ti-prefix}-message-2-check:before { content: $ti-icon-message-2-check; } +.#{$ti-prefix}-message-2-code:before { content: $ti-icon-message-2-code; } +.#{$ti-prefix}-message-2-cog:before { content: $ti-icon-message-2-cog; } +.#{$ti-prefix}-message-2-dollar:before { content: $ti-icon-message-2-dollar; } +.#{$ti-prefix}-message-2-down:before { content: $ti-icon-message-2-down; } +.#{$ti-prefix}-message-2-exclamation:before { content: $ti-icon-message-2-exclamation; } +.#{$ti-prefix}-message-2-heart:before { content: $ti-icon-message-2-heart; } +.#{$ti-prefix}-message-2-minus:before { content: $ti-icon-message-2-minus; } +.#{$ti-prefix}-message-2-off:before { content: $ti-icon-message-2-off; } +.#{$ti-prefix}-message-2-pause:before { content: $ti-icon-message-2-pause; } +.#{$ti-prefix}-message-2-pin:before { content: $ti-icon-message-2-pin; } +.#{$ti-prefix}-message-2-plus:before { content: $ti-icon-message-2-plus; } +.#{$ti-prefix}-message-2-question:before { content: $ti-icon-message-2-question; } +.#{$ti-prefix}-message-2-search:before { content: $ti-icon-message-2-search; } +.#{$ti-prefix}-message-2-share:before { content: $ti-icon-message-2-share; } +.#{$ti-prefix}-message-2-star:before { content: $ti-icon-message-2-star; } +.#{$ti-prefix}-message-2-up:before { content: $ti-icon-message-2-up; } +.#{$ti-prefix}-message-2-x:before { content: $ti-icon-message-2-x; } +.#{$ti-prefix}-message-bolt:before { content: $ti-icon-message-bolt; } +.#{$ti-prefix}-message-cancel:before { content: $ti-icon-message-cancel; } +.#{$ti-prefix}-message-chatbot:before { content: $ti-icon-message-chatbot; } +.#{$ti-prefix}-message-check:before { content: $ti-icon-message-check; } +.#{$ti-prefix}-message-circle:before { content: $ti-icon-message-circle; } +.#{$ti-prefix}-message-circle-2:before { content: $ti-icon-message-circle-2; } +.#{$ti-prefix}-message-circle-2-filled:before { content: $ti-icon-message-circle-2-filled; } +.#{$ti-prefix}-message-circle-bolt:before { content: $ti-icon-message-circle-bolt; } +.#{$ti-prefix}-message-circle-cancel:before { content: $ti-icon-message-circle-cancel; } +.#{$ti-prefix}-message-circle-check:before { content: $ti-icon-message-circle-check; } +.#{$ti-prefix}-message-circle-code:before { content: $ti-icon-message-circle-code; } +.#{$ti-prefix}-message-circle-cog:before { content: $ti-icon-message-circle-cog; } +.#{$ti-prefix}-message-circle-dollar:before { content: $ti-icon-message-circle-dollar; } +.#{$ti-prefix}-message-circle-down:before { content: $ti-icon-message-circle-down; } +.#{$ti-prefix}-message-circle-exclamation:before { content: $ti-icon-message-circle-exclamation; } +.#{$ti-prefix}-message-circle-heart:before { content: $ti-icon-message-circle-heart; } +.#{$ti-prefix}-message-circle-minus:before { content: $ti-icon-message-circle-minus; } +.#{$ti-prefix}-message-circle-off:before { content: $ti-icon-message-circle-off; } +.#{$ti-prefix}-message-circle-pause:before { content: $ti-icon-message-circle-pause; } +.#{$ti-prefix}-message-circle-pin:before { content: $ti-icon-message-circle-pin; } +.#{$ti-prefix}-message-circle-plus:before { content: $ti-icon-message-circle-plus; } +.#{$ti-prefix}-message-circle-question:before { content: $ti-icon-message-circle-question; } +.#{$ti-prefix}-message-circle-search:before { content: $ti-icon-message-circle-search; } +.#{$ti-prefix}-message-circle-share:before { content: $ti-icon-message-circle-share; } +.#{$ti-prefix}-message-circle-star:before { content: $ti-icon-message-circle-star; } +.#{$ti-prefix}-message-circle-up:before { content: $ti-icon-message-circle-up; } +.#{$ti-prefix}-message-circle-x:before { content: $ti-icon-message-circle-x; } +.#{$ti-prefix}-message-code:before { content: $ti-icon-message-code; } +.#{$ti-prefix}-message-cog:before { content: $ti-icon-message-cog; } +.#{$ti-prefix}-message-dollar:before { content: $ti-icon-message-dollar; } +.#{$ti-prefix}-message-dots:before { content: $ti-icon-message-dots; } +.#{$ti-prefix}-message-down:before { content: $ti-icon-message-down; } +.#{$ti-prefix}-message-exclamation:before { content: $ti-icon-message-exclamation; } +.#{$ti-prefix}-message-forward:before { content: $ti-icon-message-forward; } +.#{$ti-prefix}-message-heart:before { content: $ti-icon-message-heart; } +.#{$ti-prefix}-message-language:before { content: $ti-icon-message-language; } +.#{$ti-prefix}-message-minus:before { content: $ti-icon-message-minus; } +.#{$ti-prefix}-message-off:before { content: $ti-icon-message-off; } +.#{$ti-prefix}-message-pause:before { content: $ti-icon-message-pause; } +.#{$ti-prefix}-message-pin:before { content: $ti-icon-message-pin; } +.#{$ti-prefix}-message-plus:before { content: $ti-icon-message-plus; } +.#{$ti-prefix}-message-question:before { content: $ti-icon-message-question; } +.#{$ti-prefix}-message-report:before { content: $ti-icon-message-report; } +.#{$ti-prefix}-message-search:before { content: $ti-icon-message-search; } +.#{$ti-prefix}-message-share:before { content: $ti-icon-message-share; } +.#{$ti-prefix}-message-star:before { content: $ti-icon-message-star; } +.#{$ti-prefix}-message-up:before { content: $ti-icon-message-up; } +.#{$ti-prefix}-message-x:before { content: $ti-icon-message-x; } +.#{$ti-prefix}-messages:before { content: $ti-icon-messages; } +.#{$ti-prefix}-messages-off:before { content: $ti-icon-messages-off; } +.#{$ti-prefix}-meteor:before { content: $ti-icon-meteor; } +.#{$ti-prefix}-meteor-off:before { content: $ti-icon-meteor-off; } +.#{$ti-prefix}-mickey:before { content: $ti-icon-mickey; } +.#{$ti-prefix}-mickey-filled:before { content: $ti-icon-mickey-filled; } +.#{$ti-prefix}-microphone:before { content: $ti-icon-microphone; } +.#{$ti-prefix}-microphone-2:before { content: $ti-icon-microphone-2; } +.#{$ti-prefix}-microphone-2-off:before { content: $ti-icon-microphone-2-off; } +.#{$ti-prefix}-microphone-off:before { content: $ti-icon-microphone-off; } +.#{$ti-prefix}-microscope:before { content: $ti-icon-microscope; } +.#{$ti-prefix}-microscope-off:before { content: $ti-icon-microscope-off; } +.#{$ti-prefix}-microwave:before { content: $ti-icon-microwave; } +.#{$ti-prefix}-microwave-off:before { content: $ti-icon-microwave-off; } +.#{$ti-prefix}-military-award:before { content: $ti-icon-military-award; } +.#{$ti-prefix}-military-rank:before { content: $ti-icon-military-rank; } +.#{$ti-prefix}-milk:before { content: $ti-icon-milk; } +.#{$ti-prefix}-milk-off:before { content: $ti-icon-milk-off; } +.#{$ti-prefix}-milkshake:before { content: $ti-icon-milkshake; } +.#{$ti-prefix}-minimize:before { content: $ti-icon-minimize; } +.#{$ti-prefix}-minus:before { content: $ti-icon-minus; } +.#{$ti-prefix}-minus-vertical:before { content: $ti-icon-minus-vertical; } +.#{$ti-prefix}-mist:before { content: $ti-icon-mist; } +.#{$ti-prefix}-mist-off:before { content: $ti-icon-mist-off; } +.#{$ti-prefix}-mobiledata:before { content: $ti-icon-mobiledata; } +.#{$ti-prefix}-mobiledata-off:before { content: $ti-icon-mobiledata-off; } +.#{$ti-prefix}-moneybag:before { content: $ti-icon-moneybag; } +.#{$ti-prefix}-mood-angry:before { content: $ti-icon-mood-angry; } +.#{$ti-prefix}-mood-annoyed:before { content: $ti-icon-mood-annoyed; } +.#{$ti-prefix}-mood-annoyed-2:before { content: $ti-icon-mood-annoyed-2; } +.#{$ti-prefix}-mood-boy:before { content: $ti-icon-mood-boy; } +.#{$ti-prefix}-mood-check:before { content: $ti-icon-mood-check; } +.#{$ti-prefix}-mood-cog:before { content: $ti-icon-mood-cog; } +.#{$ti-prefix}-mood-confuzed:before { content: $ti-icon-mood-confuzed; } +.#{$ti-prefix}-mood-confuzed-filled:before { content: $ti-icon-mood-confuzed-filled; } +.#{$ti-prefix}-mood-crazy-happy:before { content: $ti-icon-mood-crazy-happy; } +.#{$ti-prefix}-mood-cry:before { content: $ti-icon-mood-cry; } +.#{$ti-prefix}-mood-dollar:before { content: $ti-icon-mood-dollar; } +.#{$ti-prefix}-mood-empty:before { content: $ti-icon-mood-empty; } +.#{$ti-prefix}-mood-empty-filled:before { content: $ti-icon-mood-empty-filled; } +.#{$ti-prefix}-mood-happy:before { content: $ti-icon-mood-happy; } +.#{$ti-prefix}-mood-happy-filled:before { content: $ti-icon-mood-happy-filled; } +.#{$ti-prefix}-mood-heart:before { content: $ti-icon-mood-heart; } +.#{$ti-prefix}-mood-kid:before { content: $ti-icon-mood-kid; } +.#{$ti-prefix}-mood-kid-filled:before { content: $ti-icon-mood-kid-filled; } +.#{$ti-prefix}-mood-look-left:before { content: $ti-icon-mood-look-left; } +.#{$ti-prefix}-mood-look-right:before { content: $ti-icon-mood-look-right; } +.#{$ti-prefix}-mood-minus:before { content: $ti-icon-mood-minus; } +.#{$ti-prefix}-mood-nerd:before { content: $ti-icon-mood-nerd; } +.#{$ti-prefix}-mood-nervous:before { content: $ti-icon-mood-nervous; } +.#{$ti-prefix}-mood-neutral:before { content: $ti-icon-mood-neutral; } +.#{$ti-prefix}-mood-neutral-filled:before { content: $ti-icon-mood-neutral-filled; } +.#{$ti-prefix}-mood-off:before { content: $ti-icon-mood-off; } +.#{$ti-prefix}-mood-pin:before { content: $ti-icon-mood-pin; } +.#{$ti-prefix}-mood-plus:before { content: $ti-icon-mood-plus; } +.#{$ti-prefix}-mood-sad:before { content: $ti-icon-mood-sad; } +.#{$ti-prefix}-mood-sad-2:before { content: $ti-icon-mood-sad-2; } +.#{$ti-prefix}-mood-sad-dizzy:before { content: $ti-icon-mood-sad-dizzy; } +.#{$ti-prefix}-mood-sad-filled:before { content: $ti-icon-mood-sad-filled; } +.#{$ti-prefix}-mood-sad-squint:before { content: $ti-icon-mood-sad-squint; } +.#{$ti-prefix}-mood-search:before { content: $ti-icon-mood-search; } +.#{$ti-prefix}-mood-sick:before { content: $ti-icon-mood-sick; } +.#{$ti-prefix}-mood-silence:before { content: $ti-icon-mood-silence; } +.#{$ti-prefix}-mood-sing:before { content: $ti-icon-mood-sing; } +.#{$ti-prefix}-mood-smile:before { content: $ti-icon-mood-smile; } +.#{$ti-prefix}-mood-smile-beam:before { content: $ti-icon-mood-smile-beam; } +.#{$ti-prefix}-mood-smile-dizzy:before { content: $ti-icon-mood-smile-dizzy; } +.#{$ti-prefix}-mood-smile-filled:before { content: $ti-icon-mood-smile-filled; } +.#{$ti-prefix}-mood-suprised:before { content: $ti-icon-mood-suprised; } +.#{$ti-prefix}-mood-tongue:before { content: $ti-icon-mood-tongue; } +.#{$ti-prefix}-mood-tongue-wink:before { content: $ti-icon-mood-tongue-wink; } +.#{$ti-prefix}-mood-tongue-wink-2:before { content: $ti-icon-mood-tongue-wink-2; } +.#{$ti-prefix}-mood-unamused:before { content: $ti-icon-mood-unamused; } +.#{$ti-prefix}-mood-up:before { content: $ti-icon-mood-up; } +.#{$ti-prefix}-mood-wink:before { content: $ti-icon-mood-wink; } +.#{$ti-prefix}-mood-wink-2:before { content: $ti-icon-mood-wink-2; } +.#{$ti-prefix}-mood-wrrr:before { content: $ti-icon-mood-wrrr; } +.#{$ti-prefix}-mood-x:before { content: $ti-icon-mood-x; } +.#{$ti-prefix}-mood-xd:before { content: $ti-icon-mood-xd; } +.#{$ti-prefix}-moon:before { content: $ti-icon-moon; } +.#{$ti-prefix}-moon-2:before { content: $ti-icon-moon-2; } +.#{$ti-prefix}-moon-filled:before { content: $ti-icon-moon-filled; } +.#{$ti-prefix}-moon-off:before { content: $ti-icon-moon-off; } +.#{$ti-prefix}-moon-stars:before { content: $ti-icon-moon-stars; } +.#{$ti-prefix}-moped:before { content: $ti-icon-moped; } +.#{$ti-prefix}-motorbike:before { content: $ti-icon-motorbike; } +.#{$ti-prefix}-mountain:before { content: $ti-icon-mountain; } +.#{$ti-prefix}-mountain-off:before { content: $ti-icon-mountain-off; } +.#{$ti-prefix}-mouse:before { content: $ti-icon-mouse; } +.#{$ti-prefix}-mouse-2:before { content: $ti-icon-mouse-2; } +.#{$ti-prefix}-mouse-off:before { content: $ti-icon-mouse-off; } +.#{$ti-prefix}-moustache:before { content: $ti-icon-moustache; } +.#{$ti-prefix}-movie:before { content: $ti-icon-movie; } +.#{$ti-prefix}-movie-off:before { content: $ti-icon-movie-off; } +.#{$ti-prefix}-mug:before { content: $ti-icon-mug; } +.#{$ti-prefix}-mug-off:before { content: $ti-icon-mug-off; } +.#{$ti-prefix}-multiplier-0-5x:before { content: $ti-icon-multiplier-0-5x; } +.#{$ti-prefix}-multiplier-1-5x:before { content: $ti-icon-multiplier-1-5x; } +.#{$ti-prefix}-multiplier-1x:before { content: $ti-icon-multiplier-1x; } +.#{$ti-prefix}-multiplier-2x:before { content: $ti-icon-multiplier-2x; } +.#{$ti-prefix}-mushroom:before { content: $ti-icon-mushroom; } +.#{$ti-prefix}-mushroom-filled:before { content: $ti-icon-mushroom-filled; } +.#{$ti-prefix}-mushroom-off:before { content: $ti-icon-mushroom-off; } +.#{$ti-prefix}-music:before { content: $ti-icon-music; } +.#{$ti-prefix}-music-off:before { content: $ti-icon-music-off; } +.#{$ti-prefix}-navigation:before { content: $ti-icon-navigation; } +.#{$ti-prefix}-navigation-filled:before { content: $ti-icon-navigation-filled; } +.#{$ti-prefix}-navigation-off:before { content: $ti-icon-navigation-off; } +.#{$ti-prefix}-needle:before { content: $ti-icon-needle; } +.#{$ti-prefix}-needle-thread:before { content: $ti-icon-needle-thread; } +.#{$ti-prefix}-network:before { content: $ti-icon-network; } +.#{$ti-prefix}-network-off:before { content: $ti-icon-network-off; } +.#{$ti-prefix}-new-section:before { content: $ti-icon-new-section; } +.#{$ti-prefix}-news:before { content: $ti-icon-news; } +.#{$ti-prefix}-news-off:before { content: $ti-icon-news-off; } +.#{$ti-prefix}-nfc:before { content: $ti-icon-nfc; } +.#{$ti-prefix}-nfc-off:before { content: $ti-icon-nfc-off; } +.#{$ti-prefix}-no-copyright:before { content: $ti-icon-no-copyright; } +.#{$ti-prefix}-no-creative-commons:before { content: $ti-icon-no-creative-commons; } +.#{$ti-prefix}-no-derivatives:before { content: $ti-icon-no-derivatives; } +.#{$ti-prefix}-north-star:before { content: $ti-icon-north-star; } +.#{$ti-prefix}-note:before { content: $ti-icon-note; } +.#{$ti-prefix}-note-off:before { content: $ti-icon-note-off; } +.#{$ti-prefix}-notebook:before { content: $ti-icon-notebook; } +.#{$ti-prefix}-notebook-off:before { content: $ti-icon-notebook-off; } +.#{$ti-prefix}-notes:before { content: $ti-icon-notes; } +.#{$ti-prefix}-notes-off:before { content: $ti-icon-notes-off; } +.#{$ti-prefix}-notification:before { content: $ti-icon-notification; } +.#{$ti-prefix}-notification-off:before { content: $ti-icon-notification-off; } +.#{$ti-prefix}-number:before { content: $ti-icon-number; } +.#{$ti-prefix}-number-0:before { content: $ti-icon-number-0; } +.#{$ti-prefix}-number-1:before { content: $ti-icon-number-1; } +.#{$ti-prefix}-number-2:before { content: $ti-icon-number-2; } +.#{$ti-prefix}-number-3:before { content: $ti-icon-number-3; } +.#{$ti-prefix}-number-4:before { content: $ti-icon-number-4; } +.#{$ti-prefix}-number-5:before { content: $ti-icon-number-5; } +.#{$ti-prefix}-number-6:before { content: $ti-icon-number-6; } +.#{$ti-prefix}-number-7:before { content: $ti-icon-number-7; } +.#{$ti-prefix}-number-8:before { content: $ti-icon-number-8; } +.#{$ti-prefix}-number-9:before { content: $ti-icon-number-9; } +.#{$ti-prefix}-numbers:before { content: $ti-icon-numbers; } +.#{$ti-prefix}-nurse:before { content: $ti-icon-nurse; } +.#{$ti-prefix}-octagon:before { content: $ti-icon-octagon; } +.#{$ti-prefix}-octagon-filled:before { content: $ti-icon-octagon-filled; } +.#{$ti-prefix}-octagon-off:before { content: $ti-icon-octagon-off; } +.#{$ti-prefix}-old:before { content: $ti-icon-old; } +.#{$ti-prefix}-olympics:before { content: $ti-icon-olympics; } +.#{$ti-prefix}-olympics-off:before { content: $ti-icon-olympics-off; } +.#{$ti-prefix}-om:before { content: $ti-icon-om; } +.#{$ti-prefix}-omega:before { content: $ti-icon-omega; } +.#{$ti-prefix}-outbound:before { content: $ti-icon-outbound; } +.#{$ti-prefix}-outlet:before { content: $ti-icon-outlet; } +.#{$ti-prefix}-oval:before { content: $ti-icon-oval; } +.#{$ti-prefix}-oval-filled:before { content: $ti-icon-oval-filled; } +.#{$ti-prefix}-oval-vertical:before { content: $ti-icon-oval-vertical; } +.#{$ti-prefix}-oval-vertical-filled:before { content: $ti-icon-oval-vertical-filled; } +.#{$ti-prefix}-overline:before { content: $ti-icon-overline; } +.#{$ti-prefix}-package:before { content: $ti-icon-package; } +.#{$ti-prefix}-package-export:before { content: $ti-icon-package-export; } +.#{$ti-prefix}-package-import:before { content: $ti-icon-package-import; } +.#{$ti-prefix}-package-off:before { content: $ti-icon-package-off; } +.#{$ti-prefix}-packages:before { content: $ti-icon-packages; } +.#{$ti-prefix}-pacman:before { content: $ti-icon-pacman; } +.#{$ti-prefix}-page-break:before { content: $ti-icon-page-break; } +.#{$ti-prefix}-paint:before { content: $ti-icon-paint; } +.#{$ti-prefix}-paint-filled:before { content: $ti-icon-paint-filled; } +.#{$ti-prefix}-paint-off:before { content: $ti-icon-paint-off; } +.#{$ti-prefix}-palette:before { content: $ti-icon-palette; } +.#{$ti-prefix}-palette-off:before { content: $ti-icon-palette-off; } +.#{$ti-prefix}-panorama-horizontal:before { content: $ti-icon-panorama-horizontal; } +.#{$ti-prefix}-panorama-horizontal-off:before { content: $ti-icon-panorama-horizontal-off; } +.#{$ti-prefix}-panorama-vertical:before { content: $ti-icon-panorama-vertical; } +.#{$ti-prefix}-panorama-vertical-off:before { content: $ti-icon-panorama-vertical-off; } +.#{$ti-prefix}-paper-bag:before { content: $ti-icon-paper-bag; } +.#{$ti-prefix}-paper-bag-off:before { content: $ti-icon-paper-bag-off; } +.#{$ti-prefix}-paperclip:before { content: $ti-icon-paperclip; } +.#{$ti-prefix}-parachute:before { content: $ti-icon-parachute; } +.#{$ti-prefix}-parachute-off:before { content: $ti-icon-parachute-off; } +.#{$ti-prefix}-parentheses:before { content: $ti-icon-parentheses; } +.#{$ti-prefix}-parentheses-off:before { content: $ti-icon-parentheses-off; } +.#{$ti-prefix}-parking:before { content: $ti-icon-parking; } +.#{$ti-prefix}-parking-off:before { content: $ti-icon-parking-off; } +.#{$ti-prefix}-password:before { content: $ti-icon-password; } +.#{$ti-prefix}-paw:before { content: $ti-icon-paw; } +.#{$ti-prefix}-paw-filled:before { content: $ti-icon-paw-filled; } +.#{$ti-prefix}-paw-off:before { content: $ti-icon-paw-off; } +.#{$ti-prefix}-pdf:before { content: $ti-icon-pdf; } +.#{$ti-prefix}-peace:before { content: $ti-icon-peace; } +.#{$ti-prefix}-pencil:before { content: $ti-icon-pencil; } +.#{$ti-prefix}-pencil-minus:before { content: $ti-icon-pencil-minus; } +.#{$ti-prefix}-pencil-off:before { content: $ti-icon-pencil-off; } +.#{$ti-prefix}-pencil-plus:before { content: $ti-icon-pencil-plus; } +.#{$ti-prefix}-pennant:before { content: $ti-icon-pennant; } +.#{$ti-prefix}-pennant-2:before { content: $ti-icon-pennant-2; } +.#{$ti-prefix}-pennant-2-filled:before { content: $ti-icon-pennant-2-filled; } +.#{$ti-prefix}-pennant-filled:before { content: $ti-icon-pennant-filled; } +.#{$ti-prefix}-pennant-off:before { content: $ti-icon-pennant-off; } +.#{$ti-prefix}-pentagon:before { content: $ti-icon-pentagon; } +.#{$ti-prefix}-pentagon-filled:before { content: $ti-icon-pentagon-filled; } +.#{$ti-prefix}-pentagon-off:before { content: $ti-icon-pentagon-off; } +.#{$ti-prefix}-pentagram:before { content: $ti-icon-pentagram; } +.#{$ti-prefix}-pepper:before { content: $ti-icon-pepper; } +.#{$ti-prefix}-pepper-off:before { content: $ti-icon-pepper-off; } +.#{$ti-prefix}-percentage:before { content: $ti-icon-percentage; } +.#{$ti-prefix}-perfume:before { content: $ti-icon-perfume; } +.#{$ti-prefix}-perspective:before { content: $ti-icon-perspective; } +.#{$ti-prefix}-perspective-off:before { content: $ti-icon-perspective-off; } +.#{$ti-prefix}-phone:before { content: $ti-icon-phone; } +.#{$ti-prefix}-phone-call:before { content: $ti-icon-phone-call; } +.#{$ti-prefix}-phone-calling:before { content: $ti-icon-phone-calling; } +.#{$ti-prefix}-phone-check:before { content: $ti-icon-phone-check; } +.#{$ti-prefix}-phone-incoming:before { content: $ti-icon-phone-incoming; } +.#{$ti-prefix}-phone-off:before { content: $ti-icon-phone-off; } +.#{$ti-prefix}-phone-outgoing:before { content: $ti-icon-phone-outgoing; } +.#{$ti-prefix}-phone-pause:before { content: $ti-icon-phone-pause; } +.#{$ti-prefix}-phone-plus:before { content: $ti-icon-phone-plus; } +.#{$ti-prefix}-phone-x:before { content: $ti-icon-phone-x; } +.#{$ti-prefix}-photo:before { content: $ti-icon-photo; } +.#{$ti-prefix}-photo-bolt:before { content: $ti-icon-photo-bolt; } +.#{$ti-prefix}-photo-cancel:before { content: $ti-icon-photo-cancel; } +.#{$ti-prefix}-photo-check:before { content: $ti-icon-photo-check; } +.#{$ti-prefix}-photo-code:before { content: $ti-icon-photo-code; } +.#{$ti-prefix}-photo-cog:before { content: $ti-icon-photo-cog; } +.#{$ti-prefix}-photo-dollar:before { content: $ti-icon-photo-dollar; } +.#{$ti-prefix}-photo-down:before { content: $ti-icon-photo-down; } +.#{$ti-prefix}-photo-edit:before { content: $ti-icon-photo-edit; } +.#{$ti-prefix}-photo-exclamation:before { content: $ti-icon-photo-exclamation; } +.#{$ti-prefix}-photo-heart:before { content: $ti-icon-photo-heart; } +.#{$ti-prefix}-photo-minus:before { content: $ti-icon-photo-minus; } +.#{$ti-prefix}-photo-off:before { content: $ti-icon-photo-off; } +.#{$ti-prefix}-photo-pause:before { content: $ti-icon-photo-pause; } +.#{$ti-prefix}-photo-pin:before { content: $ti-icon-photo-pin; } +.#{$ti-prefix}-photo-plus:before { content: $ti-icon-photo-plus; } +.#{$ti-prefix}-photo-question:before { content: $ti-icon-photo-question; } +.#{$ti-prefix}-photo-search:before { content: $ti-icon-photo-search; } +.#{$ti-prefix}-photo-sensor:before { content: $ti-icon-photo-sensor; } +.#{$ti-prefix}-photo-sensor-2:before { content: $ti-icon-photo-sensor-2; } +.#{$ti-prefix}-photo-sensor-3:before { content: $ti-icon-photo-sensor-3; } +.#{$ti-prefix}-photo-share:before { content: $ti-icon-photo-share; } +.#{$ti-prefix}-photo-shield:before { content: $ti-icon-photo-shield; } +.#{$ti-prefix}-photo-star:before { content: $ti-icon-photo-star; } +.#{$ti-prefix}-photo-up:before { content: $ti-icon-photo-up; } +.#{$ti-prefix}-photo-x:before { content: $ti-icon-photo-x; } +.#{$ti-prefix}-physotherapist:before { content: $ti-icon-physotherapist; } +.#{$ti-prefix}-picture-in-picture:before { content: $ti-icon-picture-in-picture; } +.#{$ti-prefix}-picture-in-picture-off:before { content: $ti-icon-picture-in-picture-off; } +.#{$ti-prefix}-picture-in-picture-on:before { content: $ti-icon-picture-in-picture-on; } +.#{$ti-prefix}-picture-in-picture-top:before { content: $ti-icon-picture-in-picture-top; } +.#{$ti-prefix}-pig:before { content: $ti-icon-pig; } +.#{$ti-prefix}-pig-money:before { content: $ti-icon-pig-money; } +.#{$ti-prefix}-pig-off:before { content: $ti-icon-pig-off; } +.#{$ti-prefix}-pilcrow:before { content: $ti-icon-pilcrow; } +.#{$ti-prefix}-pill:before { content: $ti-icon-pill; } +.#{$ti-prefix}-pill-off:before { content: $ti-icon-pill-off; } +.#{$ti-prefix}-pills:before { content: $ti-icon-pills; } +.#{$ti-prefix}-pin:before { content: $ti-icon-pin; } +.#{$ti-prefix}-pin-filled:before { content: $ti-icon-pin-filled; } +.#{$ti-prefix}-ping-pong:before { content: $ti-icon-ping-pong; } +.#{$ti-prefix}-pinned:before { content: $ti-icon-pinned; } +.#{$ti-prefix}-pinned-filled:before { content: $ti-icon-pinned-filled; } +.#{$ti-prefix}-pinned-off:before { content: $ti-icon-pinned-off; } +.#{$ti-prefix}-pizza:before { content: $ti-icon-pizza; } +.#{$ti-prefix}-pizza-off:before { content: $ti-icon-pizza-off; } +.#{$ti-prefix}-placeholder:before { content: $ti-icon-placeholder; } +.#{$ti-prefix}-plane:before { content: $ti-icon-plane; } +.#{$ti-prefix}-plane-arrival:before { content: $ti-icon-plane-arrival; } +.#{$ti-prefix}-plane-departure:before { content: $ti-icon-plane-departure; } +.#{$ti-prefix}-plane-inflight:before { content: $ti-icon-plane-inflight; } +.#{$ti-prefix}-plane-off:before { content: $ti-icon-plane-off; } +.#{$ti-prefix}-plane-tilt:before { content: $ti-icon-plane-tilt; } +.#{$ti-prefix}-planet:before { content: $ti-icon-planet; } +.#{$ti-prefix}-planet-off:before { content: $ti-icon-planet-off; } +.#{$ti-prefix}-plant:before { content: $ti-icon-plant; } +.#{$ti-prefix}-plant-2:before { content: $ti-icon-plant-2; } +.#{$ti-prefix}-plant-2-off:before { content: $ti-icon-plant-2-off; } +.#{$ti-prefix}-plant-off:before { content: $ti-icon-plant-off; } +.#{$ti-prefix}-play-card:before { content: $ti-icon-play-card; } +.#{$ti-prefix}-play-card-off:before { content: $ti-icon-play-card-off; } +.#{$ti-prefix}-player-eject:before { content: $ti-icon-player-eject; } +.#{$ti-prefix}-player-eject-filled:before { content: $ti-icon-player-eject-filled; } +.#{$ti-prefix}-player-pause:before { content: $ti-icon-player-pause; } +.#{$ti-prefix}-player-pause-filled:before { content: $ti-icon-player-pause-filled; } +.#{$ti-prefix}-player-play:before { content: $ti-icon-player-play; } +.#{$ti-prefix}-player-play-filled:before { content: $ti-icon-player-play-filled; } +.#{$ti-prefix}-player-record:before { content: $ti-icon-player-record; } +.#{$ti-prefix}-player-record-filled:before { content: $ti-icon-player-record-filled; } +.#{$ti-prefix}-player-skip-back:before { content: $ti-icon-player-skip-back; } +.#{$ti-prefix}-player-skip-back-filled:before { content: $ti-icon-player-skip-back-filled; } +.#{$ti-prefix}-player-skip-forward:before { content: $ti-icon-player-skip-forward; } +.#{$ti-prefix}-player-skip-forward-filled:before { content: $ti-icon-player-skip-forward-filled; } +.#{$ti-prefix}-player-stop:before { content: $ti-icon-player-stop; } +.#{$ti-prefix}-player-stop-filled:before { content: $ti-icon-player-stop-filled; } +.#{$ti-prefix}-player-track-next:before { content: $ti-icon-player-track-next; } +.#{$ti-prefix}-player-track-next-filled:before { content: $ti-icon-player-track-next-filled; } +.#{$ti-prefix}-player-track-prev:before { content: $ti-icon-player-track-prev; } +.#{$ti-prefix}-player-track-prev-filled:before { content: $ti-icon-player-track-prev-filled; } +.#{$ti-prefix}-playlist:before { content: $ti-icon-playlist; } +.#{$ti-prefix}-playlist-add:before { content: $ti-icon-playlist-add; } +.#{$ti-prefix}-playlist-off:before { content: $ti-icon-playlist-off; } +.#{$ti-prefix}-playlist-x:before { content: $ti-icon-playlist-x; } +.#{$ti-prefix}-playstation-circle:before { content: $ti-icon-playstation-circle; } +.#{$ti-prefix}-playstation-square:before { content: $ti-icon-playstation-square; } +.#{$ti-prefix}-playstation-triangle:before { content: $ti-icon-playstation-triangle; } +.#{$ti-prefix}-playstation-x:before { content: $ti-icon-playstation-x; } +.#{$ti-prefix}-plug:before { content: $ti-icon-plug; } +.#{$ti-prefix}-plug-connected:before { content: $ti-icon-plug-connected; } +.#{$ti-prefix}-plug-connected-x:before { content: $ti-icon-plug-connected-x; } +.#{$ti-prefix}-plug-off:before { content: $ti-icon-plug-off; } +.#{$ti-prefix}-plug-x:before { content: $ti-icon-plug-x; } +.#{$ti-prefix}-plus:before { content: $ti-icon-plus; } +.#{$ti-prefix}-plus-equal:before { content: $ti-icon-plus-equal; } +.#{$ti-prefix}-plus-minus:before { content: $ti-icon-plus-minus; } +.#{$ti-prefix}-png:before { content: $ti-icon-png; } +.#{$ti-prefix}-podium:before { content: $ti-icon-podium; } +.#{$ti-prefix}-podium-off:before { content: $ti-icon-podium-off; } +.#{$ti-prefix}-point:before { content: $ti-icon-point; } +.#{$ti-prefix}-point-filled:before { content: $ti-icon-point-filled; } +.#{$ti-prefix}-point-off:before { content: $ti-icon-point-off; } +.#{$ti-prefix}-pointer:before { content: $ti-icon-pointer; } +.#{$ti-prefix}-pointer-bolt:before { content: $ti-icon-pointer-bolt; } +.#{$ti-prefix}-pointer-cancel:before { content: $ti-icon-pointer-cancel; } +.#{$ti-prefix}-pointer-check:before { content: $ti-icon-pointer-check; } +.#{$ti-prefix}-pointer-code:before { content: $ti-icon-pointer-code; } +.#{$ti-prefix}-pointer-cog:before { content: $ti-icon-pointer-cog; } +.#{$ti-prefix}-pointer-dollar:before { content: $ti-icon-pointer-dollar; } +.#{$ti-prefix}-pointer-down:before { content: $ti-icon-pointer-down; } +.#{$ti-prefix}-pointer-exclamation:before { content: $ti-icon-pointer-exclamation; } +.#{$ti-prefix}-pointer-heart:before { content: $ti-icon-pointer-heart; } +.#{$ti-prefix}-pointer-minus:before { content: $ti-icon-pointer-minus; } +.#{$ti-prefix}-pointer-off:before { content: $ti-icon-pointer-off; } +.#{$ti-prefix}-pointer-pause:before { content: $ti-icon-pointer-pause; } +.#{$ti-prefix}-pointer-pin:before { content: $ti-icon-pointer-pin; } +.#{$ti-prefix}-pointer-plus:before { content: $ti-icon-pointer-plus; } +.#{$ti-prefix}-pointer-question:before { content: $ti-icon-pointer-question; } +.#{$ti-prefix}-pointer-search:before { content: $ti-icon-pointer-search; } +.#{$ti-prefix}-pointer-share:before { content: $ti-icon-pointer-share; } +.#{$ti-prefix}-pointer-star:before { content: $ti-icon-pointer-star; } +.#{$ti-prefix}-pointer-up:before { content: $ti-icon-pointer-up; } +.#{$ti-prefix}-pointer-x:before { content: $ti-icon-pointer-x; } +.#{$ti-prefix}-pokeball:before { content: $ti-icon-pokeball; } +.#{$ti-prefix}-pokeball-off:before { content: $ti-icon-pokeball-off; } +.#{$ti-prefix}-poker-chip:before { content: $ti-icon-poker-chip; } +.#{$ti-prefix}-polaroid:before { content: $ti-icon-polaroid; } +.#{$ti-prefix}-polygon:before { content: $ti-icon-polygon; } +.#{$ti-prefix}-polygon-off:before { content: $ti-icon-polygon-off; } +.#{$ti-prefix}-poo:before { content: $ti-icon-poo; } +.#{$ti-prefix}-pool:before { content: $ti-icon-pool; } +.#{$ti-prefix}-pool-off:before { content: $ti-icon-pool-off; } +.#{$ti-prefix}-power:before { content: $ti-icon-power; } +.#{$ti-prefix}-pray:before { content: $ti-icon-pray; } +.#{$ti-prefix}-premium-rights:before { content: $ti-icon-premium-rights; } +.#{$ti-prefix}-prescription:before { content: $ti-icon-prescription; } +.#{$ti-prefix}-presentation:before { content: $ti-icon-presentation; } +.#{$ti-prefix}-presentation-analytics:before { content: $ti-icon-presentation-analytics; } +.#{$ti-prefix}-presentation-off:before { content: $ti-icon-presentation-off; } +.#{$ti-prefix}-printer:before { content: $ti-icon-printer; } +.#{$ti-prefix}-printer-off:before { content: $ti-icon-printer-off; } +.#{$ti-prefix}-prison:before { content: $ti-icon-prison; } +.#{$ti-prefix}-prompt:before { content: $ti-icon-prompt; } +.#{$ti-prefix}-propeller:before { content: $ti-icon-propeller; } +.#{$ti-prefix}-propeller-off:before { content: $ti-icon-propeller-off; } +.#{$ti-prefix}-pumpkin-scary:before { content: $ti-icon-pumpkin-scary; } +.#{$ti-prefix}-puzzle:before { content: $ti-icon-puzzle; } +.#{$ti-prefix}-puzzle-2:before { content: $ti-icon-puzzle-2; } +.#{$ti-prefix}-puzzle-filled:before { content: $ti-icon-puzzle-filled; } +.#{$ti-prefix}-puzzle-off:before { content: $ti-icon-puzzle-off; } +.#{$ti-prefix}-pyramid:before { content: $ti-icon-pyramid; } +.#{$ti-prefix}-pyramid-off:before { content: $ti-icon-pyramid-off; } +.#{$ti-prefix}-qrcode:before { content: $ti-icon-qrcode; } +.#{$ti-prefix}-qrcode-off:before { content: $ti-icon-qrcode-off; } +.#{$ti-prefix}-question-mark:before { content: $ti-icon-question-mark; } +.#{$ti-prefix}-quote:before { content: $ti-icon-quote; } +.#{$ti-prefix}-quote-off:before { content: $ti-icon-quote-off; } +.#{$ti-prefix}-radar:before { content: $ti-icon-radar; } +.#{$ti-prefix}-radar-2:before { content: $ti-icon-radar-2; } +.#{$ti-prefix}-radar-off:before { content: $ti-icon-radar-off; } +.#{$ti-prefix}-radio:before { content: $ti-icon-radio; } +.#{$ti-prefix}-radio-off:before { content: $ti-icon-radio-off; } +.#{$ti-prefix}-radioactive:before { content: $ti-icon-radioactive; } +.#{$ti-prefix}-radioactive-filled:before { content: $ti-icon-radioactive-filled; } +.#{$ti-prefix}-radioactive-off:before { content: $ti-icon-radioactive-off; } +.#{$ti-prefix}-radius-bottom-left:before { content: $ti-icon-radius-bottom-left; } +.#{$ti-prefix}-radius-bottom-right:before { content: $ti-icon-radius-bottom-right; } +.#{$ti-prefix}-radius-top-left:before { content: $ti-icon-radius-top-left; } +.#{$ti-prefix}-radius-top-right:before { content: $ti-icon-radius-top-right; } +.#{$ti-prefix}-rainbow:before { content: $ti-icon-rainbow; } +.#{$ti-prefix}-rainbow-off:before { content: $ti-icon-rainbow-off; } +.#{$ti-prefix}-rating-12-plus:before { content: $ti-icon-rating-12-plus; } +.#{$ti-prefix}-rating-14-plus:before { content: $ti-icon-rating-14-plus; } +.#{$ti-prefix}-rating-16-plus:before { content: $ti-icon-rating-16-plus; } +.#{$ti-prefix}-rating-18-plus:before { content: $ti-icon-rating-18-plus; } +.#{$ti-prefix}-rating-21-plus:before { content: $ti-icon-rating-21-plus; } +.#{$ti-prefix}-razor:before { content: $ti-icon-razor; } +.#{$ti-prefix}-razor-electric:before { content: $ti-icon-razor-electric; } +.#{$ti-prefix}-receipt:before { content: $ti-icon-receipt; } +.#{$ti-prefix}-receipt-2:before { content: $ti-icon-receipt-2; } +.#{$ti-prefix}-receipt-off:before { content: $ti-icon-receipt-off; } +.#{$ti-prefix}-receipt-refund:before { content: $ti-icon-receipt-refund; } +.#{$ti-prefix}-receipt-tax:before { content: $ti-icon-receipt-tax; } +.#{$ti-prefix}-recharging:before { content: $ti-icon-recharging; } +.#{$ti-prefix}-record-mail:before { content: $ti-icon-record-mail; } +.#{$ti-prefix}-record-mail-off:before { content: $ti-icon-record-mail-off; } +.#{$ti-prefix}-rectangle:before { content: $ti-icon-rectangle; } +.#{$ti-prefix}-rectangle-filled:before { content: $ti-icon-rectangle-filled; } +.#{$ti-prefix}-rectangle-vertical:before { content: $ti-icon-rectangle-vertical; } +.#{$ti-prefix}-rectangle-vertical-filled:before { content: $ti-icon-rectangle-vertical-filled; } +.#{$ti-prefix}-recycle:before { content: $ti-icon-recycle; } +.#{$ti-prefix}-recycle-off:before { content: $ti-icon-recycle-off; } +.#{$ti-prefix}-refresh:before { content: $ti-icon-refresh; } +.#{$ti-prefix}-refresh-alert:before { content: $ti-icon-refresh-alert; } +.#{$ti-prefix}-refresh-dot:before { content: $ti-icon-refresh-dot; } +.#{$ti-prefix}-refresh-off:before { content: $ti-icon-refresh-off; } +.#{$ti-prefix}-regex:before { content: $ti-icon-regex; } +.#{$ti-prefix}-regex-off:before { content: $ti-icon-regex-off; } +.#{$ti-prefix}-registered:before { content: $ti-icon-registered; } +.#{$ti-prefix}-relation-many-to-many:before { content: $ti-icon-relation-many-to-many; } +.#{$ti-prefix}-relation-one-to-many:before { content: $ti-icon-relation-one-to-many; } +.#{$ti-prefix}-relation-one-to-one:before { content: $ti-icon-relation-one-to-one; } +.#{$ti-prefix}-reload:before { content: $ti-icon-reload; } +.#{$ti-prefix}-repeat:before { content: $ti-icon-repeat; } +.#{$ti-prefix}-repeat-off:before { content: $ti-icon-repeat-off; } +.#{$ti-prefix}-repeat-once:before { content: $ti-icon-repeat-once; } +.#{$ti-prefix}-replace:before { content: $ti-icon-replace; } +.#{$ti-prefix}-replace-filled:before { content: $ti-icon-replace-filled; } +.#{$ti-prefix}-replace-off:before { content: $ti-icon-replace-off; } +.#{$ti-prefix}-report:before { content: $ti-icon-report; } +.#{$ti-prefix}-report-analytics:before { content: $ti-icon-report-analytics; } +.#{$ti-prefix}-report-medical:before { content: $ti-icon-report-medical; } +.#{$ti-prefix}-report-money:before { content: $ti-icon-report-money; } +.#{$ti-prefix}-report-off:before { content: $ti-icon-report-off; } +.#{$ti-prefix}-report-search:before { content: $ti-icon-report-search; } +.#{$ti-prefix}-reserved-line:before { content: $ti-icon-reserved-line; } +.#{$ti-prefix}-resize:before { content: $ti-icon-resize; } +.#{$ti-prefix}-ribbon-health:before { content: $ti-icon-ribbon-health; } +.#{$ti-prefix}-ripple:before { content: $ti-icon-ripple; } +.#{$ti-prefix}-ripple-off:before { content: $ti-icon-ripple-off; } +.#{$ti-prefix}-road:before { content: $ti-icon-road; } +.#{$ti-prefix}-road-off:before { content: $ti-icon-road-off; } +.#{$ti-prefix}-road-sign:before { content: $ti-icon-road-sign; } +.#{$ti-prefix}-robot:before { content: $ti-icon-robot; } +.#{$ti-prefix}-robot-off:before { content: $ti-icon-robot-off; } +.#{$ti-prefix}-rocket:before { content: $ti-icon-rocket; } +.#{$ti-prefix}-rocket-off:before { content: $ti-icon-rocket-off; } +.#{$ti-prefix}-roller-skating:before { content: $ti-icon-roller-skating; } +.#{$ti-prefix}-rollercoaster:before { content: $ti-icon-rollercoaster; } +.#{$ti-prefix}-rollercoaster-off:before { content: $ti-icon-rollercoaster-off; } +.#{$ti-prefix}-rosette:before { content: $ti-icon-rosette; } +.#{$ti-prefix}-rosette-filled:before { content: $ti-icon-rosette-filled; } +.#{$ti-prefix}-rosette-number-0:before { content: $ti-icon-rosette-number-0; } +.#{$ti-prefix}-rosette-number-1:before { content: $ti-icon-rosette-number-1; } +.#{$ti-prefix}-rosette-number-2:before { content: $ti-icon-rosette-number-2; } +.#{$ti-prefix}-rosette-number-3:before { content: $ti-icon-rosette-number-3; } +.#{$ti-prefix}-rosette-number-4:before { content: $ti-icon-rosette-number-4; } +.#{$ti-prefix}-rosette-number-5:before { content: $ti-icon-rosette-number-5; } +.#{$ti-prefix}-rosette-number-6:before { content: $ti-icon-rosette-number-6; } +.#{$ti-prefix}-rosette-number-7:before { content: $ti-icon-rosette-number-7; } +.#{$ti-prefix}-rosette-number-8:before { content: $ti-icon-rosette-number-8; } +.#{$ti-prefix}-rosette-number-9:before { content: $ti-icon-rosette-number-9; } +.#{$ti-prefix}-rotate:before { content: $ti-icon-rotate; } +.#{$ti-prefix}-rotate-2:before { content: $ti-icon-rotate-2; } +.#{$ti-prefix}-rotate-360:before { content: $ti-icon-rotate-360; } +.#{$ti-prefix}-rotate-clockwise:before { content: $ti-icon-rotate-clockwise; } +.#{$ti-prefix}-rotate-clockwise-2:before { content: $ti-icon-rotate-clockwise-2; } +.#{$ti-prefix}-rotate-dot:before { content: $ti-icon-rotate-dot; } +.#{$ti-prefix}-rotate-rectangle:before { content: $ti-icon-rotate-rectangle; } +.#{$ti-prefix}-route:before { content: $ti-icon-route; } +.#{$ti-prefix}-route-2:before { content: $ti-icon-route-2; } +.#{$ti-prefix}-route-off:before { content: $ti-icon-route-off; } +.#{$ti-prefix}-router:before { content: $ti-icon-router; } +.#{$ti-prefix}-router-off:before { content: $ti-icon-router-off; } +.#{$ti-prefix}-row-insert-bottom:before { content: $ti-icon-row-insert-bottom; } +.#{$ti-prefix}-row-insert-top:before { content: $ti-icon-row-insert-top; } +.#{$ti-prefix}-rss:before { content: $ti-icon-rss; } +.#{$ti-prefix}-rubber-stamp:before { content: $ti-icon-rubber-stamp; } +.#{$ti-prefix}-rubber-stamp-off:before { content: $ti-icon-rubber-stamp-off; } +.#{$ti-prefix}-ruler:before { content: $ti-icon-ruler; } +.#{$ti-prefix}-ruler-2:before { content: $ti-icon-ruler-2; } +.#{$ti-prefix}-ruler-2-off:before { content: $ti-icon-ruler-2-off; } +.#{$ti-prefix}-ruler-3:before { content: $ti-icon-ruler-3; } +.#{$ti-prefix}-ruler-measure:before { content: $ti-icon-ruler-measure; } +.#{$ti-prefix}-ruler-off:before { content: $ti-icon-ruler-off; } +.#{$ti-prefix}-run:before { content: $ti-icon-run; } +.#{$ti-prefix}-s-turn-down:before { content: $ti-icon-s-turn-down; } +.#{$ti-prefix}-s-turn-left:before { content: $ti-icon-s-turn-left; } +.#{$ti-prefix}-s-turn-right:before { content: $ti-icon-s-turn-right; } +.#{$ti-prefix}-s-turn-up:before { content: $ti-icon-s-turn-up; } +.#{$ti-prefix}-sailboat:before { content: $ti-icon-sailboat; } +.#{$ti-prefix}-sailboat-2:before { content: $ti-icon-sailboat-2; } +.#{$ti-prefix}-sailboat-off:before { content: $ti-icon-sailboat-off; } +.#{$ti-prefix}-salad:before { content: $ti-icon-salad; } +.#{$ti-prefix}-salt:before { content: $ti-icon-salt; } +.#{$ti-prefix}-satellite:before { content: $ti-icon-satellite; } +.#{$ti-prefix}-satellite-off:before { content: $ti-icon-satellite-off; } +.#{$ti-prefix}-sausage:before { content: $ti-icon-sausage; } +.#{$ti-prefix}-scale:before { content: $ti-icon-scale; } +.#{$ti-prefix}-scale-off:before { content: $ti-icon-scale-off; } +.#{$ti-prefix}-scale-outline:before { content: $ti-icon-scale-outline; } +.#{$ti-prefix}-scale-outline-off:before { content: $ti-icon-scale-outline-off; } +.#{$ti-prefix}-scan:before { content: $ti-icon-scan; } +.#{$ti-prefix}-scan-eye:before { content: $ti-icon-scan-eye; } +.#{$ti-prefix}-schema:before { content: $ti-icon-schema; } +.#{$ti-prefix}-schema-off:before { content: $ti-icon-schema-off; } +.#{$ti-prefix}-school:before { content: $ti-icon-school; } +.#{$ti-prefix}-school-bell:before { content: $ti-icon-school-bell; } +.#{$ti-prefix}-school-off:before { content: $ti-icon-school-off; } +.#{$ti-prefix}-scissors:before { content: $ti-icon-scissors; } +.#{$ti-prefix}-scissors-off:before { content: $ti-icon-scissors-off; } +.#{$ti-prefix}-scooter:before { content: $ti-icon-scooter; } +.#{$ti-prefix}-scooter-electric:before { content: $ti-icon-scooter-electric; } +.#{$ti-prefix}-screen-share:before { content: $ti-icon-screen-share; } +.#{$ti-prefix}-screen-share-off:before { content: $ti-icon-screen-share-off; } +.#{$ti-prefix}-screenshot:before { content: $ti-icon-screenshot; } +.#{$ti-prefix}-scribble:before { content: $ti-icon-scribble; } +.#{$ti-prefix}-scribble-off:before { content: $ti-icon-scribble-off; } +.#{$ti-prefix}-script:before { content: $ti-icon-script; } +.#{$ti-prefix}-script-minus:before { content: $ti-icon-script-minus; } +.#{$ti-prefix}-script-plus:before { content: $ti-icon-script-plus; } +.#{$ti-prefix}-script-x:before { content: $ti-icon-script-x; } +.#{$ti-prefix}-scuba-mask:before { content: $ti-icon-scuba-mask; } +.#{$ti-prefix}-scuba-mask-off:before { content: $ti-icon-scuba-mask-off; } +.#{$ti-prefix}-sdk:before { content: $ti-icon-sdk; } +.#{$ti-prefix}-search:before { content: $ti-icon-search; } +.#{$ti-prefix}-search-off:before { content: $ti-icon-search-off; } +.#{$ti-prefix}-section:before { content: $ti-icon-section; } +.#{$ti-prefix}-section-sign:before { content: $ti-icon-section-sign; } +.#{$ti-prefix}-seeding:before { content: $ti-icon-seeding; } +.#{$ti-prefix}-seeding-off:before { content: $ti-icon-seeding-off; } +.#{$ti-prefix}-select:before { content: $ti-icon-select; } +.#{$ti-prefix}-select-all:before { content: $ti-icon-select-all; } +.#{$ti-prefix}-selector:before { content: $ti-icon-selector; } +.#{$ti-prefix}-send:before { content: $ti-icon-send; } +.#{$ti-prefix}-send-off:before { content: $ti-icon-send-off; } +.#{$ti-prefix}-seo:before { content: $ti-icon-seo; } +.#{$ti-prefix}-separator:before { content: $ti-icon-separator; } +.#{$ti-prefix}-separator-horizontal:before { content: $ti-icon-separator-horizontal; } +.#{$ti-prefix}-separator-vertical:before { content: $ti-icon-separator-vertical; } +.#{$ti-prefix}-server:before { content: $ti-icon-server; } +.#{$ti-prefix}-server-2:before { content: $ti-icon-server-2; } +.#{$ti-prefix}-server-bolt:before { content: $ti-icon-server-bolt; } +.#{$ti-prefix}-server-cog:before { content: $ti-icon-server-cog; } +.#{$ti-prefix}-server-off:before { content: $ti-icon-server-off; } +.#{$ti-prefix}-servicemark:before { content: $ti-icon-servicemark; } +.#{$ti-prefix}-settings:before { content: $ti-icon-settings; } +.#{$ti-prefix}-settings-2:before { content: $ti-icon-settings-2; } +.#{$ti-prefix}-settings-automation:before { content: $ti-icon-settings-automation; } +.#{$ti-prefix}-settings-bolt:before { content: $ti-icon-settings-bolt; } +.#{$ti-prefix}-settings-cancel:before { content: $ti-icon-settings-cancel; } +.#{$ti-prefix}-settings-check:before { content: $ti-icon-settings-check; } +.#{$ti-prefix}-settings-code:before { content: $ti-icon-settings-code; } +.#{$ti-prefix}-settings-cog:before { content: $ti-icon-settings-cog; } +.#{$ti-prefix}-settings-dollar:before { content: $ti-icon-settings-dollar; } +.#{$ti-prefix}-settings-down:before { content: $ti-icon-settings-down; } +.#{$ti-prefix}-settings-exclamation:before { content: $ti-icon-settings-exclamation; } +.#{$ti-prefix}-settings-filled:before { content: $ti-icon-settings-filled; } +.#{$ti-prefix}-settings-heart:before { content: $ti-icon-settings-heart; } +.#{$ti-prefix}-settings-minus:before { content: $ti-icon-settings-minus; } +.#{$ti-prefix}-settings-off:before { content: $ti-icon-settings-off; } +.#{$ti-prefix}-settings-pause:before { content: $ti-icon-settings-pause; } +.#{$ti-prefix}-settings-pin:before { content: $ti-icon-settings-pin; } +.#{$ti-prefix}-settings-plus:before { content: $ti-icon-settings-plus; } +.#{$ti-prefix}-settings-question:before { content: $ti-icon-settings-question; } +.#{$ti-prefix}-settings-search:before { content: $ti-icon-settings-search; } +.#{$ti-prefix}-settings-share:before { content: $ti-icon-settings-share; } +.#{$ti-prefix}-settings-star:before { content: $ti-icon-settings-star; } +.#{$ti-prefix}-settings-up:before { content: $ti-icon-settings-up; } +.#{$ti-prefix}-settings-x:before { content: $ti-icon-settings-x; } +.#{$ti-prefix}-shadow:before { content: $ti-icon-shadow; } +.#{$ti-prefix}-shadow-off:before { content: $ti-icon-shadow-off; } +.#{$ti-prefix}-shape:before { content: $ti-icon-shape; } +.#{$ti-prefix}-shape-2:before { content: $ti-icon-shape-2; } +.#{$ti-prefix}-shape-3:before { content: $ti-icon-shape-3; } +.#{$ti-prefix}-shape-off:before { content: $ti-icon-shape-off; } +.#{$ti-prefix}-share:before { content: $ti-icon-share; } +.#{$ti-prefix}-share-2:before { content: $ti-icon-share-2; } +.#{$ti-prefix}-share-3:before { content: $ti-icon-share-3; } +.#{$ti-prefix}-share-off:before { content: $ti-icon-share-off; } +.#{$ti-prefix}-shield:before { content: $ti-icon-shield; } +.#{$ti-prefix}-shield-bolt:before { content: $ti-icon-shield-bolt; } +.#{$ti-prefix}-shield-cancel:before { content: $ti-icon-shield-cancel; } +.#{$ti-prefix}-shield-check:before { content: $ti-icon-shield-check; } +.#{$ti-prefix}-shield-check-filled:before { content: $ti-icon-shield-check-filled; } +.#{$ti-prefix}-shield-checkered:before { content: $ti-icon-shield-checkered; } +.#{$ti-prefix}-shield-checkered-filled:before { content: $ti-icon-shield-checkered-filled; } +.#{$ti-prefix}-shield-chevron:before { content: $ti-icon-shield-chevron; } +.#{$ti-prefix}-shield-code:before { content: $ti-icon-shield-code; } +.#{$ti-prefix}-shield-cog:before { content: $ti-icon-shield-cog; } +.#{$ti-prefix}-shield-dollar:before { content: $ti-icon-shield-dollar; } +.#{$ti-prefix}-shield-down:before { content: $ti-icon-shield-down; } +.#{$ti-prefix}-shield-exclamation:before { content: $ti-icon-shield-exclamation; } +.#{$ti-prefix}-shield-filled:before { content: $ti-icon-shield-filled; } +.#{$ti-prefix}-shield-half:before { content: $ti-icon-shield-half; } +.#{$ti-prefix}-shield-half-filled:before { content: $ti-icon-shield-half-filled; } +.#{$ti-prefix}-shield-heart:before { content: $ti-icon-shield-heart; } +.#{$ti-prefix}-shield-lock:before { content: $ti-icon-shield-lock; } +.#{$ti-prefix}-shield-lock-filled:before { content: $ti-icon-shield-lock-filled; } +.#{$ti-prefix}-shield-minus:before { content: $ti-icon-shield-minus; } +.#{$ti-prefix}-shield-off:before { content: $ti-icon-shield-off; } +.#{$ti-prefix}-shield-pause:before { content: $ti-icon-shield-pause; } +.#{$ti-prefix}-shield-pin:before { content: $ti-icon-shield-pin; } +.#{$ti-prefix}-shield-plus:before { content: $ti-icon-shield-plus; } +.#{$ti-prefix}-shield-question:before { content: $ti-icon-shield-question; } +.#{$ti-prefix}-shield-search:before { content: $ti-icon-shield-search; } +.#{$ti-prefix}-shield-share:before { content: $ti-icon-shield-share; } +.#{$ti-prefix}-shield-star:before { content: $ti-icon-shield-star; } +.#{$ti-prefix}-shield-up:before { content: $ti-icon-shield-up; } +.#{$ti-prefix}-shield-x:before { content: $ti-icon-shield-x; } +.#{$ti-prefix}-ship:before { content: $ti-icon-ship; } +.#{$ti-prefix}-ship-off:before { content: $ti-icon-ship-off; } +.#{$ti-prefix}-shirt:before { content: $ti-icon-shirt; } +.#{$ti-prefix}-shirt-filled:before { content: $ti-icon-shirt-filled; } +.#{$ti-prefix}-shirt-off:before { content: $ti-icon-shirt-off; } +.#{$ti-prefix}-shirt-sport:before { content: $ti-icon-shirt-sport; } +.#{$ti-prefix}-shoe:before { content: $ti-icon-shoe; } +.#{$ti-prefix}-shoe-off:before { content: $ti-icon-shoe-off; } +.#{$ti-prefix}-shopping-bag:before { content: $ti-icon-shopping-bag; } +.#{$ti-prefix}-shopping-cart:before { content: $ti-icon-shopping-cart; } +.#{$ti-prefix}-shopping-cart-discount:before { content: $ti-icon-shopping-cart-discount; } +.#{$ti-prefix}-shopping-cart-off:before { content: $ti-icon-shopping-cart-off; } +.#{$ti-prefix}-shopping-cart-plus:before { content: $ti-icon-shopping-cart-plus; } +.#{$ti-prefix}-shopping-cart-x:before { content: $ti-icon-shopping-cart-x; } +.#{$ti-prefix}-shovel:before { content: $ti-icon-shovel; } +.#{$ti-prefix}-shredder:before { content: $ti-icon-shredder; } +.#{$ti-prefix}-sign-left:before { content: $ti-icon-sign-left; } +.#{$ti-prefix}-sign-left-filled:before { content: $ti-icon-sign-left-filled; } +.#{$ti-prefix}-sign-right:before { content: $ti-icon-sign-right; } +.#{$ti-prefix}-sign-right-filled:before { content: $ti-icon-sign-right-filled; } +.#{$ti-prefix}-signal-2g:before { content: $ti-icon-signal-2g; } +.#{$ti-prefix}-signal-3g:before { content: $ti-icon-signal-3g; } +.#{$ti-prefix}-signal-4g:before { content: $ti-icon-signal-4g; } +.#{$ti-prefix}-signal-4g-plus:before { content: $ti-icon-signal-4g-plus; } +.#{$ti-prefix}-signal-5g:before { content: $ti-icon-signal-5g; } +.#{$ti-prefix}-signal-6g:before { content: $ti-icon-signal-6g; } +.#{$ti-prefix}-signal-e:before { content: $ti-icon-signal-e; } +.#{$ti-prefix}-signal-g:before { content: $ti-icon-signal-g; } +.#{$ti-prefix}-signal-h:before { content: $ti-icon-signal-h; } +.#{$ti-prefix}-signal-h-plus:before { content: $ti-icon-signal-h-plus; } +.#{$ti-prefix}-signal-lte:before { content: $ti-icon-signal-lte; } +.#{$ti-prefix}-signature:before { content: $ti-icon-signature; } +.#{$ti-prefix}-signature-off:before { content: $ti-icon-signature-off; } +.#{$ti-prefix}-sitemap:before { content: $ti-icon-sitemap; } +.#{$ti-prefix}-sitemap-off:before { content: $ti-icon-sitemap-off; } +.#{$ti-prefix}-skateboard:before { content: $ti-icon-skateboard; } +.#{$ti-prefix}-skateboard-off:before { content: $ti-icon-skateboard-off; } +.#{$ti-prefix}-skull:before { content: $ti-icon-skull; } +.#{$ti-prefix}-slash:before { content: $ti-icon-slash; } +.#{$ti-prefix}-slashes:before { content: $ti-icon-slashes; } +.#{$ti-prefix}-sleigh:before { content: $ti-icon-sleigh; } +.#{$ti-prefix}-slice:before { content: $ti-icon-slice; } +.#{$ti-prefix}-slideshow:before { content: $ti-icon-slideshow; } +.#{$ti-prefix}-smart-home:before { content: $ti-icon-smart-home; } +.#{$ti-prefix}-smart-home-off:before { content: $ti-icon-smart-home-off; } +.#{$ti-prefix}-smoking:before { content: $ti-icon-smoking; } +.#{$ti-prefix}-smoking-no:before { content: $ti-icon-smoking-no; } +.#{$ti-prefix}-snowflake:before { content: $ti-icon-snowflake; } +.#{$ti-prefix}-snowflake-off:before { content: $ti-icon-snowflake-off; } +.#{$ti-prefix}-snowman:before { content: $ti-icon-snowman; } +.#{$ti-prefix}-soccer-field:before { content: $ti-icon-soccer-field; } +.#{$ti-prefix}-social:before { content: $ti-icon-social; } +.#{$ti-prefix}-social-off:before { content: $ti-icon-social-off; } +.#{$ti-prefix}-sock:before { content: $ti-icon-sock; } +.#{$ti-prefix}-sofa:before { content: $ti-icon-sofa; } +.#{$ti-prefix}-sofa-off:before { content: $ti-icon-sofa-off; } +.#{$ti-prefix}-solar-panel:before { content: $ti-icon-solar-panel; } +.#{$ti-prefix}-solar-panel-2:before { content: $ti-icon-solar-panel-2; } +.#{$ti-prefix}-sort-0-9:before { content: $ti-icon-sort-0-9; } +.#{$ti-prefix}-sort-9-0:before { content: $ti-icon-sort-9-0; } +.#{$ti-prefix}-sort-a-z:before { content: $ti-icon-sort-a-z; } +.#{$ti-prefix}-sort-ascending:before { content: $ti-icon-sort-ascending; } +.#{$ti-prefix}-sort-ascending-2:before { content: $ti-icon-sort-ascending-2; } +.#{$ti-prefix}-sort-ascending-letters:before { content: $ti-icon-sort-ascending-letters; } +.#{$ti-prefix}-sort-ascending-numbers:before { content: $ti-icon-sort-ascending-numbers; } +.#{$ti-prefix}-sort-descending:before { content: $ti-icon-sort-descending; } +.#{$ti-prefix}-sort-descending-2:before { content: $ti-icon-sort-descending-2; } +.#{$ti-prefix}-sort-descending-letters:before { content: $ti-icon-sort-descending-letters; } +.#{$ti-prefix}-sort-descending-numbers:before { content: $ti-icon-sort-descending-numbers; } +.#{$ti-prefix}-sort-z-a:before { content: $ti-icon-sort-z-a; } +.#{$ti-prefix}-sos:before { content: $ti-icon-sos; } +.#{$ti-prefix}-soup:before { content: $ti-icon-soup; } +.#{$ti-prefix}-soup-off:before { content: $ti-icon-soup-off; } +.#{$ti-prefix}-source-code:before { content: $ti-icon-source-code; } +.#{$ti-prefix}-space:before { content: $ti-icon-space; } +.#{$ti-prefix}-space-off:before { content: $ti-icon-space-off; } +.#{$ti-prefix}-spacing-horizontal:before { content: $ti-icon-spacing-horizontal; } +.#{$ti-prefix}-spacing-vertical:before { content: $ti-icon-spacing-vertical; } +.#{$ti-prefix}-spade:before { content: $ti-icon-spade; } +.#{$ti-prefix}-spade-filled:before { content: $ti-icon-spade-filled; } +.#{$ti-prefix}-sparkles:before { content: $ti-icon-sparkles; } +.#{$ti-prefix}-speakerphone:before { content: $ti-icon-speakerphone; } +.#{$ti-prefix}-speedboat:before { content: $ti-icon-speedboat; } +.#{$ti-prefix}-spider:before { content: $ti-icon-spider; } +.#{$ti-prefix}-spiral:before { content: $ti-icon-spiral; } +.#{$ti-prefix}-spiral-off:before { content: $ti-icon-spiral-off; } +.#{$ti-prefix}-sport-billard:before { content: $ti-icon-sport-billard; } +.#{$ti-prefix}-spray:before { content: $ti-icon-spray; } +.#{$ti-prefix}-spy:before { content: $ti-icon-spy; } +.#{$ti-prefix}-spy-off:before { content: $ti-icon-spy-off; } +.#{$ti-prefix}-sql:before { content: $ti-icon-sql; } +.#{$ti-prefix}-square:before { content: $ti-icon-square; } +.#{$ti-prefix}-square-0-filled:before { content: $ti-icon-square-0-filled; } +.#{$ti-prefix}-square-1-filled:before { content: $ti-icon-square-1-filled; } +.#{$ti-prefix}-square-2-filled:before { content: $ti-icon-square-2-filled; } +.#{$ti-prefix}-square-3-filled:before { content: $ti-icon-square-3-filled; } +.#{$ti-prefix}-square-4-filled:before { content: $ti-icon-square-4-filled; } +.#{$ti-prefix}-square-5-filled:before { content: $ti-icon-square-5-filled; } +.#{$ti-prefix}-square-6-filled:before { content: $ti-icon-square-6-filled; } +.#{$ti-prefix}-square-7-filled:before { content: $ti-icon-square-7-filled; } +.#{$ti-prefix}-square-8-filled:before { content: $ti-icon-square-8-filled; } +.#{$ti-prefix}-square-9-filled:before { content: $ti-icon-square-9-filled; } +.#{$ti-prefix}-square-arrow-down:before { content: $ti-icon-square-arrow-down; } +.#{$ti-prefix}-square-arrow-left:before { content: $ti-icon-square-arrow-left; } +.#{$ti-prefix}-square-arrow-right:before { content: $ti-icon-square-arrow-right; } +.#{$ti-prefix}-square-arrow-up:before { content: $ti-icon-square-arrow-up; } +.#{$ti-prefix}-square-asterisk:before { content: $ti-icon-square-asterisk; } +.#{$ti-prefix}-square-check:before { content: $ti-icon-square-check; } +.#{$ti-prefix}-square-check-filled:before { content: $ti-icon-square-check-filled; } +.#{$ti-prefix}-square-chevron-down:before { content: $ti-icon-square-chevron-down; } +.#{$ti-prefix}-square-chevron-left:before { content: $ti-icon-square-chevron-left; } +.#{$ti-prefix}-square-chevron-right:before { content: $ti-icon-square-chevron-right; } +.#{$ti-prefix}-square-chevron-up:before { content: $ti-icon-square-chevron-up; } +.#{$ti-prefix}-square-chevrons-down:before { content: $ti-icon-square-chevrons-down; } +.#{$ti-prefix}-square-chevrons-left:before { content: $ti-icon-square-chevrons-left; } +.#{$ti-prefix}-square-chevrons-right:before { content: $ti-icon-square-chevrons-right; } +.#{$ti-prefix}-square-chevrons-up:before { content: $ti-icon-square-chevrons-up; } +.#{$ti-prefix}-square-dot:before { content: $ti-icon-square-dot; } +.#{$ti-prefix}-square-f0:before { content: $ti-icon-square-f0; } +.#{$ti-prefix}-square-f0-filled:before { content: $ti-icon-square-f0-filled; } +.#{$ti-prefix}-square-f1:before { content: $ti-icon-square-f1; } +.#{$ti-prefix}-square-f1-filled:before { content: $ti-icon-square-f1-filled; } +.#{$ti-prefix}-square-f2:before { content: $ti-icon-square-f2; } +.#{$ti-prefix}-square-f2-filled:before { content: $ti-icon-square-f2-filled; } +.#{$ti-prefix}-square-f3:before { content: $ti-icon-square-f3; } +.#{$ti-prefix}-square-f3-filled:before { content: $ti-icon-square-f3-filled; } +.#{$ti-prefix}-square-f4:before { content: $ti-icon-square-f4; } +.#{$ti-prefix}-square-f4-filled:before { content: $ti-icon-square-f4-filled; } +.#{$ti-prefix}-square-f5:before { content: $ti-icon-square-f5; } +.#{$ti-prefix}-square-f5-filled:before { content: $ti-icon-square-f5-filled; } +.#{$ti-prefix}-square-f6:before { content: $ti-icon-square-f6; } +.#{$ti-prefix}-square-f6-filled:before { content: $ti-icon-square-f6-filled; } +.#{$ti-prefix}-square-f7:before { content: $ti-icon-square-f7; } +.#{$ti-prefix}-square-f7-filled:before { content: $ti-icon-square-f7-filled; } +.#{$ti-prefix}-square-f8:before { content: $ti-icon-square-f8; } +.#{$ti-prefix}-square-f8-filled:before { content: $ti-icon-square-f8-filled; } +.#{$ti-prefix}-square-f9:before { content: $ti-icon-square-f9; } +.#{$ti-prefix}-square-f9-filled:before { content: $ti-icon-square-f9-filled; } +.#{$ti-prefix}-square-forbid:before { content: $ti-icon-square-forbid; } +.#{$ti-prefix}-square-forbid-2:before { content: $ti-icon-square-forbid-2; } +.#{$ti-prefix}-square-half:before { content: $ti-icon-square-half; } +.#{$ti-prefix}-square-key:before { content: $ti-icon-square-key; } +.#{$ti-prefix}-square-letter-a:before { content: $ti-icon-square-letter-a; } +.#{$ti-prefix}-square-letter-b:before { content: $ti-icon-square-letter-b; } +.#{$ti-prefix}-square-letter-c:before { content: $ti-icon-square-letter-c; } +.#{$ti-prefix}-square-letter-d:before { content: $ti-icon-square-letter-d; } +.#{$ti-prefix}-square-letter-e:before { content: $ti-icon-square-letter-e; } +.#{$ti-prefix}-square-letter-f:before { content: $ti-icon-square-letter-f; } +.#{$ti-prefix}-square-letter-g:before { content: $ti-icon-square-letter-g; } +.#{$ti-prefix}-square-letter-h:before { content: $ti-icon-square-letter-h; } +.#{$ti-prefix}-square-letter-i:before { content: $ti-icon-square-letter-i; } +.#{$ti-prefix}-square-letter-j:before { content: $ti-icon-square-letter-j; } +.#{$ti-prefix}-square-letter-k:before { content: $ti-icon-square-letter-k; } +.#{$ti-prefix}-square-letter-l:before { content: $ti-icon-square-letter-l; } +.#{$ti-prefix}-square-letter-m:before { content: $ti-icon-square-letter-m; } +.#{$ti-prefix}-square-letter-n:before { content: $ti-icon-square-letter-n; } +.#{$ti-prefix}-square-letter-o:before { content: $ti-icon-square-letter-o; } +.#{$ti-prefix}-square-letter-p:before { content: $ti-icon-square-letter-p; } +.#{$ti-prefix}-square-letter-q:before { content: $ti-icon-square-letter-q; } +.#{$ti-prefix}-square-letter-r:before { content: $ti-icon-square-letter-r; } +.#{$ti-prefix}-square-letter-s:before { content: $ti-icon-square-letter-s; } +.#{$ti-prefix}-square-letter-t:before { content: $ti-icon-square-letter-t; } +.#{$ti-prefix}-square-letter-u:before { content: $ti-icon-square-letter-u; } +.#{$ti-prefix}-square-letter-v:before { content: $ti-icon-square-letter-v; } +.#{$ti-prefix}-square-letter-w:before { content: $ti-icon-square-letter-w; } +.#{$ti-prefix}-square-letter-x:before { content: $ti-icon-square-letter-x; } +.#{$ti-prefix}-square-letter-y:before { content: $ti-icon-square-letter-y; } +.#{$ti-prefix}-square-letter-z:before { content: $ti-icon-square-letter-z; } +.#{$ti-prefix}-square-minus:before { content: $ti-icon-square-minus; } +.#{$ti-prefix}-square-number-0:before { content: $ti-icon-square-number-0; } +.#{$ti-prefix}-square-number-1:before { content: $ti-icon-square-number-1; } +.#{$ti-prefix}-square-number-2:before { content: $ti-icon-square-number-2; } +.#{$ti-prefix}-square-number-3:before { content: $ti-icon-square-number-3; } +.#{$ti-prefix}-square-number-4:before { content: $ti-icon-square-number-4; } +.#{$ti-prefix}-square-number-5:before { content: $ti-icon-square-number-5; } +.#{$ti-prefix}-square-number-6:before { content: $ti-icon-square-number-6; } +.#{$ti-prefix}-square-number-7:before { content: $ti-icon-square-number-7; } +.#{$ti-prefix}-square-number-8:before { content: $ti-icon-square-number-8; } +.#{$ti-prefix}-square-number-9:before { content: $ti-icon-square-number-9; } +.#{$ti-prefix}-square-off:before { content: $ti-icon-square-off; } +.#{$ti-prefix}-square-plus:before { content: $ti-icon-square-plus; } +.#{$ti-prefix}-square-root:before { content: $ti-icon-square-root; } +.#{$ti-prefix}-square-root-2:before { content: $ti-icon-square-root-2; } +.#{$ti-prefix}-square-rotated:before { content: $ti-icon-square-rotated; } +.#{$ti-prefix}-square-rotated-filled:before { content: $ti-icon-square-rotated-filled; } +.#{$ti-prefix}-square-rotated-forbid:before { content: $ti-icon-square-rotated-forbid; } +.#{$ti-prefix}-square-rotated-forbid-2:before { content: $ti-icon-square-rotated-forbid-2; } +.#{$ti-prefix}-square-rotated-off:before { content: $ti-icon-square-rotated-off; } +.#{$ti-prefix}-square-rounded:before { content: $ti-icon-square-rounded; } +.#{$ti-prefix}-square-rounded-arrow-down:before { content: $ti-icon-square-rounded-arrow-down; } +.#{$ti-prefix}-square-rounded-arrow-down-filled:before { content: $ti-icon-square-rounded-arrow-down-filled; } +.#{$ti-prefix}-square-rounded-arrow-left:before { content: $ti-icon-square-rounded-arrow-left; } +.#{$ti-prefix}-square-rounded-arrow-left-filled:before { content: $ti-icon-square-rounded-arrow-left-filled; } +.#{$ti-prefix}-square-rounded-arrow-right:before { content: $ti-icon-square-rounded-arrow-right; } +.#{$ti-prefix}-square-rounded-arrow-right-filled:before { content: $ti-icon-square-rounded-arrow-right-filled; } +.#{$ti-prefix}-square-rounded-arrow-up:before { content: $ti-icon-square-rounded-arrow-up; } +.#{$ti-prefix}-square-rounded-arrow-up-filled:before { content: $ti-icon-square-rounded-arrow-up-filled; } +.#{$ti-prefix}-square-rounded-check:before { content: $ti-icon-square-rounded-check; } +.#{$ti-prefix}-square-rounded-check-filled:before { content: $ti-icon-square-rounded-check-filled; } +.#{$ti-prefix}-square-rounded-chevron-down:before { content: $ti-icon-square-rounded-chevron-down; } +.#{$ti-prefix}-square-rounded-chevron-down-filled:before { content: $ti-icon-square-rounded-chevron-down-filled; } +.#{$ti-prefix}-square-rounded-chevron-left:before { content: $ti-icon-square-rounded-chevron-left; } +.#{$ti-prefix}-square-rounded-chevron-left-filled:before { content: $ti-icon-square-rounded-chevron-left-filled; } +.#{$ti-prefix}-square-rounded-chevron-right:before { content: $ti-icon-square-rounded-chevron-right; } +.#{$ti-prefix}-square-rounded-chevron-right-filled:before { content: $ti-icon-square-rounded-chevron-right-filled; } +.#{$ti-prefix}-square-rounded-chevron-up:before { content: $ti-icon-square-rounded-chevron-up; } +.#{$ti-prefix}-square-rounded-chevron-up-filled:before { content: $ti-icon-square-rounded-chevron-up-filled; } +.#{$ti-prefix}-square-rounded-chevrons-down:before { content: $ti-icon-square-rounded-chevrons-down; } +.#{$ti-prefix}-square-rounded-chevrons-down-filled:before { content: $ti-icon-square-rounded-chevrons-down-filled; } +.#{$ti-prefix}-square-rounded-chevrons-left:before { content: $ti-icon-square-rounded-chevrons-left; } +.#{$ti-prefix}-square-rounded-chevrons-left-filled:before { content: $ti-icon-square-rounded-chevrons-left-filled; } +.#{$ti-prefix}-square-rounded-chevrons-right:before { content: $ti-icon-square-rounded-chevrons-right; } +.#{$ti-prefix}-square-rounded-chevrons-right-filled:before { content: $ti-icon-square-rounded-chevrons-right-filled; } +.#{$ti-prefix}-square-rounded-chevrons-up:before { content: $ti-icon-square-rounded-chevrons-up; } +.#{$ti-prefix}-square-rounded-chevrons-up-filled:before { content: $ti-icon-square-rounded-chevrons-up-filled; } +.#{$ti-prefix}-square-rounded-filled:before { content: $ti-icon-square-rounded-filled; } +.#{$ti-prefix}-square-rounded-letter-a:before { content: $ti-icon-square-rounded-letter-a; } +.#{$ti-prefix}-square-rounded-letter-b:before { content: $ti-icon-square-rounded-letter-b; } +.#{$ti-prefix}-square-rounded-letter-c:before { content: $ti-icon-square-rounded-letter-c; } +.#{$ti-prefix}-square-rounded-letter-d:before { content: $ti-icon-square-rounded-letter-d; } +.#{$ti-prefix}-square-rounded-letter-e:before { content: $ti-icon-square-rounded-letter-e; } +.#{$ti-prefix}-square-rounded-letter-f:before { content: $ti-icon-square-rounded-letter-f; } +.#{$ti-prefix}-square-rounded-letter-g:before { content: $ti-icon-square-rounded-letter-g; } +.#{$ti-prefix}-square-rounded-letter-h:before { content: $ti-icon-square-rounded-letter-h; } +.#{$ti-prefix}-square-rounded-letter-i:before { content: $ti-icon-square-rounded-letter-i; } +.#{$ti-prefix}-square-rounded-letter-j:before { content: $ti-icon-square-rounded-letter-j; } +.#{$ti-prefix}-square-rounded-letter-k:before { content: $ti-icon-square-rounded-letter-k; } +.#{$ti-prefix}-square-rounded-letter-l:before { content: $ti-icon-square-rounded-letter-l; } +.#{$ti-prefix}-square-rounded-letter-m:before { content: $ti-icon-square-rounded-letter-m; } +.#{$ti-prefix}-square-rounded-letter-n:before { content: $ti-icon-square-rounded-letter-n; } +.#{$ti-prefix}-square-rounded-letter-o:before { content: $ti-icon-square-rounded-letter-o; } +.#{$ti-prefix}-square-rounded-letter-p:before { content: $ti-icon-square-rounded-letter-p; } +.#{$ti-prefix}-square-rounded-letter-q:before { content: $ti-icon-square-rounded-letter-q; } +.#{$ti-prefix}-square-rounded-letter-r:before { content: $ti-icon-square-rounded-letter-r; } +.#{$ti-prefix}-square-rounded-letter-s:before { content: $ti-icon-square-rounded-letter-s; } +.#{$ti-prefix}-square-rounded-letter-t:before { content: $ti-icon-square-rounded-letter-t; } +.#{$ti-prefix}-square-rounded-letter-u:before { content: $ti-icon-square-rounded-letter-u; } +.#{$ti-prefix}-square-rounded-letter-v:before { content: $ti-icon-square-rounded-letter-v; } +.#{$ti-prefix}-square-rounded-letter-w:before { content: $ti-icon-square-rounded-letter-w; } +.#{$ti-prefix}-square-rounded-letter-x:before { content: $ti-icon-square-rounded-letter-x; } +.#{$ti-prefix}-square-rounded-letter-y:before { content: $ti-icon-square-rounded-letter-y; } +.#{$ti-prefix}-square-rounded-letter-z:before { content: $ti-icon-square-rounded-letter-z; } +.#{$ti-prefix}-square-rounded-minus:before { content: $ti-icon-square-rounded-minus; } +.#{$ti-prefix}-square-rounded-number-0:before { content: $ti-icon-square-rounded-number-0; } +.#{$ti-prefix}-square-rounded-number-0-filled:before { content: $ti-icon-square-rounded-number-0-filled; } +.#{$ti-prefix}-square-rounded-number-1:before { content: $ti-icon-square-rounded-number-1; } +.#{$ti-prefix}-square-rounded-number-1-filled:before { content: $ti-icon-square-rounded-number-1-filled; } +.#{$ti-prefix}-square-rounded-number-2:before { content: $ti-icon-square-rounded-number-2; } +.#{$ti-prefix}-square-rounded-number-2-filled:before { content: $ti-icon-square-rounded-number-2-filled; } +.#{$ti-prefix}-square-rounded-number-3:before { content: $ti-icon-square-rounded-number-3; } +.#{$ti-prefix}-square-rounded-number-3-filled:before { content: $ti-icon-square-rounded-number-3-filled; } +.#{$ti-prefix}-square-rounded-number-4:before { content: $ti-icon-square-rounded-number-4; } +.#{$ti-prefix}-square-rounded-number-4-filled:before { content: $ti-icon-square-rounded-number-4-filled; } +.#{$ti-prefix}-square-rounded-number-5:before { content: $ti-icon-square-rounded-number-5; } +.#{$ti-prefix}-square-rounded-number-5-filled:before { content: $ti-icon-square-rounded-number-5-filled; } +.#{$ti-prefix}-square-rounded-number-6:before { content: $ti-icon-square-rounded-number-6; } +.#{$ti-prefix}-square-rounded-number-6-filled:before { content: $ti-icon-square-rounded-number-6-filled; } +.#{$ti-prefix}-square-rounded-number-7:before { content: $ti-icon-square-rounded-number-7; } +.#{$ti-prefix}-square-rounded-number-7-filled:before { content: $ti-icon-square-rounded-number-7-filled; } +.#{$ti-prefix}-square-rounded-number-8:before { content: $ti-icon-square-rounded-number-8; } +.#{$ti-prefix}-square-rounded-number-8-filled:before { content: $ti-icon-square-rounded-number-8-filled; } +.#{$ti-prefix}-square-rounded-number-9:before { content: $ti-icon-square-rounded-number-9; } +.#{$ti-prefix}-square-rounded-number-9-filled:before { content: $ti-icon-square-rounded-number-9-filled; } +.#{$ti-prefix}-square-rounded-plus:before { content: $ti-icon-square-rounded-plus; } +.#{$ti-prefix}-square-rounded-plus-filled:before { content: $ti-icon-square-rounded-plus-filled; } +.#{$ti-prefix}-square-rounded-x:before { content: $ti-icon-square-rounded-x; } +.#{$ti-prefix}-square-rounded-x-filled:before { content: $ti-icon-square-rounded-x-filled; } +.#{$ti-prefix}-square-toggle:before { content: $ti-icon-square-toggle; } +.#{$ti-prefix}-square-toggle-horizontal:before { content: $ti-icon-square-toggle-horizontal; } +.#{$ti-prefix}-square-x:before { content: $ti-icon-square-x; } +.#{$ti-prefix}-squares-diagonal:before { content: $ti-icon-squares-diagonal; } +.#{$ti-prefix}-squares-filled:before { content: $ti-icon-squares-filled; } +.#{$ti-prefix}-stack:before { content: $ti-icon-stack; } +.#{$ti-prefix}-stack-2:before { content: $ti-icon-stack-2; } +.#{$ti-prefix}-stack-3:before { content: $ti-icon-stack-3; } +.#{$ti-prefix}-stack-pop:before { content: $ti-icon-stack-pop; } +.#{$ti-prefix}-stack-push:before { content: $ti-icon-stack-push; } +.#{$ti-prefix}-stairs:before { content: $ti-icon-stairs; } +.#{$ti-prefix}-stairs-down:before { content: $ti-icon-stairs-down; } +.#{$ti-prefix}-stairs-up:before { content: $ti-icon-stairs-up; } +.#{$ti-prefix}-star:before { content: $ti-icon-star; } +.#{$ti-prefix}-star-filled:before { content: $ti-icon-star-filled; } +.#{$ti-prefix}-star-half:before { content: $ti-icon-star-half; } +.#{$ti-prefix}-star-half-filled:before { content: $ti-icon-star-half-filled; } +.#{$ti-prefix}-star-off:before { content: $ti-icon-star-off; } +.#{$ti-prefix}-stars:before { content: $ti-icon-stars; } +.#{$ti-prefix}-stars-filled:before { content: $ti-icon-stars-filled; } +.#{$ti-prefix}-stars-off:before { content: $ti-icon-stars-off; } +.#{$ti-prefix}-status-change:before { content: $ti-icon-status-change; } +.#{$ti-prefix}-steam:before { content: $ti-icon-steam; } +.#{$ti-prefix}-steering-wheel:before { content: $ti-icon-steering-wheel; } +.#{$ti-prefix}-steering-wheel-off:before { content: $ti-icon-steering-wheel-off; } +.#{$ti-prefix}-step-into:before { content: $ti-icon-step-into; } +.#{$ti-prefix}-step-out:before { content: $ti-icon-step-out; } +.#{$ti-prefix}-stereo-glasses:before { content: $ti-icon-stereo-glasses; } +.#{$ti-prefix}-stethoscope:before { content: $ti-icon-stethoscope; } +.#{$ti-prefix}-stethoscope-off:before { content: $ti-icon-stethoscope-off; } +.#{$ti-prefix}-sticker:before { content: $ti-icon-sticker; } +.#{$ti-prefix}-storm:before { content: $ti-icon-storm; } +.#{$ti-prefix}-storm-off:before { content: $ti-icon-storm-off; } +.#{$ti-prefix}-stretching:before { content: $ti-icon-stretching; } +.#{$ti-prefix}-strikethrough:before { content: $ti-icon-strikethrough; } +.#{$ti-prefix}-submarine:before { content: $ti-icon-submarine; } +.#{$ti-prefix}-subscript:before { content: $ti-icon-subscript; } +.#{$ti-prefix}-subtask:before { content: $ti-icon-subtask; } +.#{$ti-prefix}-sum:before { content: $ti-icon-sum; } +.#{$ti-prefix}-sum-off:before { content: $ti-icon-sum-off; } +.#{$ti-prefix}-sun:before { content: $ti-icon-sun; } +.#{$ti-prefix}-sun-filled:before { content: $ti-icon-sun-filled; } +.#{$ti-prefix}-sun-high:before { content: $ti-icon-sun-high; } +.#{$ti-prefix}-sun-low:before { content: $ti-icon-sun-low; } +.#{$ti-prefix}-sun-moon:before { content: $ti-icon-sun-moon; } +.#{$ti-prefix}-sun-off:before { content: $ti-icon-sun-off; } +.#{$ti-prefix}-sun-wind:before { content: $ti-icon-sun-wind; } +.#{$ti-prefix}-sunglasses:before { content: $ti-icon-sunglasses; } +.#{$ti-prefix}-sunrise:before { content: $ti-icon-sunrise; } +.#{$ti-prefix}-sunset:before { content: $ti-icon-sunset; } +.#{$ti-prefix}-sunset-2:before { content: $ti-icon-sunset-2; } +.#{$ti-prefix}-superscript:before { content: $ti-icon-superscript; } +.#{$ti-prefix}-svg:before { content: $ti-icon-svg; } +.#{$ti-prefix}-swimming:before { content: $ti-icon-swimming; } +.#{$ti-prefix}-swipe:before { content: $ti-icon-swipe; } +.#{$ti-prefix}-switch:before { content: $ti-icon-switch; } +.#{$ti-prefix}-switch-2:before { content: $ti-icon-switch-2; } +.#{$ti-prefix}-switch-3:before { content: $ti-icon-switch-3; } +.#{$ti-prefix}-switch-horizontal:before { content: $ti-icon-switch-horizontal; } +.#{$ti-prefix}-switch-vertical:before { content: $ti-icon-switch-vertical; } +.#{$ti-prefix}-sword:before { content: $ti-icon-sword; } +.#{$ti-prefix}-sword-off:before { content: $ti-icon-sword-off; } +.#{$ti-prefix}-swords:before { content: $ti-icon-swords; } +.#{$ti-prefix}-table:before { content: $ti-icon-table; } +.#{$ti-prefix}-table-alias:before { content: $ti-icon-table-alias; } +.#{$ti-prefix}-table-export:before { content: $ti-icon-table-export; } +.#{$ti-prefix}-table-filled:before { content: $ti-icon-table-filled; } +.#{$ti-prefix}-table-import:before { content: $ti-icon-table-import; } +.#{$ti-prefix}-table-off:before { content: $ti-icon-table-off; } +.#{$ti-prefix}-table-options:before { content: $ti-icon-table-options; } +.#{$ti-prefix}-table-shortcut:before { content: $ti-icon-table-shortcut; } +.#{$ti-prefix}-tag:before { content: $ti-icon-tag; } +.#{$ti-prefix}-tag-off:before { content: $ti-icon-tag-off; } +.#{$ti-prefix}-tags:before { content: $ti-icon-tags; } +.#{$ti-prefix}-tags-off:before { content: $ti-icon-tags-off; } +.#{$ti-prefix}-tallymark-1:before { content: $ti-icon-tallymark-1; } +.#{$ti-prefix}-tallymark-2:before { content: $ti-icon-tallymark-2; } +.#{$ti-prefix}-tallymark-3:before { content: $ti-icon-tallymark-3; } +.#{$ti-prefix}-tallymark-4:before { content: $ti-icon-tallymark-4; } +.#{$ti-prefix}-tallymarks:before { content: $ti-icon-tallymarks; } +.#{$ti-prefix}-tank:before { content: $ti-icon-tank; } +.#{$ti-prefix}-target:before { content: $ti-icon-target; } +.#{$ti-prefix}-target-arrow:before { content: $ti-icon-target-arrow; } +.#{$ti-prefix}-target-off:before { content: $ti-icon-target-off; } +.#{$ti-prefix}-teapot:before { content: $ti-icon-teapot; } +.#{$ti-prefix}-telescope:before { content: $ti-icon-telescope; } +.#{$ti-prefix}-telescope-off:before { content: $ti-icon-telescope-off; } +.#{$ti-prefix}-temperature:before { content: $ti-icon-temperature; } +.#{$ti-prefix}-temperature-celsius:before { content: $ti-icon-temperature-celsius; } +.#{$ti-prefix}-temperature-fahrenheit:before { content: $ti-icon-temperature-fahrenheit; } +.#{$ti-prefix}-temperature-minus:before { content: $ti-icon-temperature-minus; } +.#{$ti-prefix}-temperature-off:before { content: $ti-icon-temperature-off; } +.#{$ti-prefix}-temperature-plus:before { content: $ti-icon-temperature-plus; } +.#{$ti-prefix}-template:before { content: $ti-icon-template; } +.#{$ti-prefix}-template-off:before { content: $ti-icon-template-off; } +.#{$ti-prefix}-tent:before { content: $ti-icon-tent; } +.#{$ti-prefix}-tent-off:before { content: $ti-icon-tent-off; } +.#{$ti-prefix}-terminal:before { content: $ti-icon-terminal; } +.#{$ti-prefix}-terminal-2:before { content: $ti-icon-terminal-2; } +.#{$ti-prefix}-test-pipe:before { content: $ti-icon-test-pipe; } +.#{$ti-prefix}-test-pipe-2:before { content: $ti-icon-test-pipe-2; } +.#{$ti-prefix}-test-pipe-off:before { content: $ti-icon-test-pipe-off; } +.#{$ti-prefix}-tex:before { content: $ti-icon-tex; } +.#{$ti-prefix}-text-caption:before { content: $ti-icon-text-caption; } +.#{$ti-prefix}-text-color:before { content: $ti-icon-text-color; } +.#{$ti-prefix}-text-decrease:before { content: $ti-icon-text-decrease; } +.#{$ti-prefix}-text-direction-ltr:before { content: $ti-icon-text-direction-ltr; } +.#{$ti-prefix}-text-direction-rtl:before { content: $ti-icon-text-direction-rtl; } +.#{$ti-prefix}-text-increase:before { content: $ti-icon-text-increase; } +.#{$ti-prefix}-text-orientation:before { content: $ti-icon-text-orientation; } +.#{$ti-prefix}-text-plus:before { content: $ti-icon-text-plus; } +.#{$ti-prefix}-text-recognition:before { content: $ti-icon-text-recognition; } +.#{$ti-prefix}-text-resize:before { content: $ti-icon-text-resize; } +.#{$ti-prefix}-text-size:before { content: $ti-icon-text-size; } +.#{$ti-prefix}-text-spellcheck:before { content: $ti-icon-text-spellcheck; } +.#{$ti-prefix}-text-wrap:before { content: $ti-icon-text-wrap; } +.#{$ti-prefix}-text-wrap-disabled:before { content: $ti-icon-text-wrap-disabled; } +.#{$ti-prefix}-texture:before { content: $ti-icon-texture; } +.#{$ti-prefix}-theater:before { content: $ti-icon-theater; } +.#{$ti-prefix}-thermometer:before { content: $ti-icon-thermometer; } +.#{$ti-prefix}-thumb-down:before { content: $ti-icon-thumb-down; } +.#{$ti-prefix}-thumb-down-filled:before { content: $ti-icon-thumb-down-filled; } +.#{$ti-prefix}-thumb-down-off:before { content: $ti-icon-thumb-down-off; } +.#{$ti-prefix}-thumb-up:before { content: $ti-icon-thumb-up; } +.#{$ti-prefix}-thumb-up-filled:before { content: $ti-icon-thumb-up-filled; } +.#{$ti-prefix}-thumb-up-off:before { content: $ti-icon-thumb-up-off; } +.#{$ti-prefix}-tic-tac:before { content: $ti-icon-tic-tac; } +.#{$ti-prefix}-ticket:before { content: $ti-icon-ticket; } +.#{$ti-prefix}-ticket-off:before { content: $ti-icon-ticket-off; } +.#{$ti-prefix}-tie:before { content: $ti-icon-tie; } +.#{$ti-prefix}-tilde:before { content: $ti-icon-tilde; } +.#{$ti-prefix}-tilt-shift:before { content: $ti-icon-tilt-shift; } +.#{$ti-prefix}-tilt-shift-off:before { content: $ti-icon-tilt-shift-off; } +.#{$ti-prefix}-timeline:before { content: $ti-icon-timeline; } +.#{$ti-prefix}-timeline-event:before { content: $ti-icon-timeline-event; } +.#{$ti-prefix}-timeline-event-exclamation:before { content: $ti-icon-timeline-event-exclamation; } +.#{$ti-prefix}-timeline-event-minus:before { content: $ti-icon-timeline-event-minus; } +.#{$ti-prefix}-timeline-event-plus:before { content: $ti-icon-timeline-event-plus; } +.#{$ti-prefix}-timeline-event-text:before { content: $ti-icon-timeline-event-text; } +.#{$ti-prefix}-timeline-event-x:before { content: $ti-icon-timeline-event-x; } +.#{$ti-prefix}-tir:before { content: $ti-icon-tir; } +.#{$ti-prefix}-toggle-left:before { content: $ti-icon-toggle-left; } +.#{$ti-prefix}-toggle-right:before { content: $ti-icon-toggle-right; } +.#{$ti-prefix}-toilet-paper:before { content: $ti-icon-toilet-paper; } +.#{$ti-prefix}-toilet-paper-off:before { content: $ti-icon-toilet-paper-off; } +.#{$ti-prefix}-tool:before { content: $ti-icon-tool; } +.#{$ti-prefix}-tools:before { content: $ti-icon-tools; } +.#{$ti-prefix}-tools-kitchen:before { content: $ti-icon-tools-kitchen; } +.#{$ti-prefix}-tools-kitchen-2:before { content: $ti-icon-tools-kitchen-2; } +.#{$ti-prefix}-tools-kitchen-2-off:before { content: $ti-icon-tools-kitchen-2-off; } +.#{$ti-prefix}-tools-kitchen-off:before { content: $ti-icon-tools-kitchen-off; } +.#{$ti-prefix}-tools-off:before { content: $ti-icon-tools-off; } +.#{$ti-prefix}-tooltip:before { content: $ti-icon-tooltip; } +.#{$ti-prefix}-topology-bus:before { content: $ti-icon-topology-bus; } +.#{$ti-prefix}-topology-complex:before { content: $ti-icon-topology-complex; } +.#{$ti-prefix}-topology-full:before { content: $ti-icon-topology-full; } +.#{$ti-prefix}-topology-full-hierarchy:before { content: $ti-icon-topology-full-hierarchy; } +.#{$ti-prefix}-topology-ring:before { content: $ti-icon-topology-ring; } +.#{$ti-prefix}-topology-ring-2:before { content: $ti-icon-topology-ring-2; } +.#{$ti-prefix}-topology-ring-3:before { content: $ti-icon-topology-ring-3; } +.#{$ti-prefix}-topology-star:before { content: $ti-icon-topology-star; } +.#{$ti-prefix}-topology-star-2:before { content: $ti-icon-topology-star-2; } +.#{$ti-prefix}-topology-star-3:before { content: $ti-icon-topology-star-3; } +.#{$ti-prefix}-topology-star-ring:before { content: $ti-icon-topology-star-ring; } +.#{$ti-prefix}-topology-star-ring-2:before { content: $ti-icon-topology-star-ring-2; } +.#{$ti-prefix}-topology-star-ring-3:before { content: $ti-icon-topology-star-ring-3; } +.#{$ti-prefix}-torii:before { content: $ti-icon-torii; } +.#{$ti-prefix}-tornado:before { content: $ti-icon-tornado; } +.#{$ti-prefix}-tournament:before { content: $ti-icon-tournament; } +.#{$ti-prefix}-tower:before { content: $ti-icon-tower; } +.#{$ti-prefix}-tower-off:before { content: $ti-icon-tower-off; } +.#{$ti-prefix}-track:before { content: $ti-icon-track; } +.#{$ti-prefix}-tractor:before { content: $ti-icon-tractor; } +.#{$ti-prefix}-trademark:before { content: $ti-icon-trademark; } +.#{$ti-prefix}-traffic-cone:before { content: $ti-icon-traffic-cone; } +.#{$ti-prefix}-traffic-cone-off:before { content: $ti-icon-traffic-cone-off; } +.#{$ti-prefix}-traffic-lights:before { content: $ti-icon-traffic-lights; } +.#{$ti-prefix}-traffic-lights-off:before { content: $ti-icon-traffic-lights-off; } +.#{$ti-prefix}-train:before { content: $ti-icon-train; } +.#{$ti-prefix}-transfer-in:before { content: $ti-icon-transfer-in; } +.#{$ti-prefix}-transfer-out:before { content: $ti-icon-transfer-out; } +.#{$ti-prefix}-transform:before { content: $ti-icon-transform; } +.#{$ti-prefix}-transform-filled:before { content: $ti-icon-transform-filled; } +.#{$ti-prefix}-transition-bottom:before { content: $ti-icon-transition-bottom; } +.#{$ti-prefix}-transition-left:before { content: $ti-icon-transition-left; } +.#{$ti-prefix}-transition-right:before { content: $ti-icon-transition-right; } +.#{$ti-prefix}-transition-top:before { content: $ti-icon-transition-top; } +.#{$ti-prefix}-trash:before { content: $ti-icon-trash; } +.#{$ti-prefix}-trash-filled:before { content: $ti-icon-trash-filled; } +.#{$ti-prefix}-trash-off:before { content: $ti-icon-trash-off; } +.#{$ti-prefix}-trash-x:before { content: $ti-icon-trash-x; } +.#{$ti-prefix}-trash-x-filled:before { content: $ti-icon-trash-x-filled; } +.#{$ti-prefix}-tree:before { content: $ti-icon-tree; } +.#{$ti-prefix}-trees:before { content: $ti-icon-trees; } +.#{$ti-prefix}-trekking:before { content: $ti-icon-trekking; } +.#{$ti-prefix}-trending-down:before { content: $ti-icon-trending-down; } +.#{$ti-prefix}-trending-down-2:before { content: $ti-icon-trending-down-2; } +.#{$ti-prefix}-trending-down-3:before { content: $ti-icon-trending-down-3; } +.#{$ti-prefix}-trending-up:before { content: $ti-icon-trending-up; } +.#{$ti-prefix}-trending-up-2:before { content: $ti-icon-trending-up-2; } +.#{$ti-prefix}-trending-up-3:before { content: $ti-icon-trending-up-3; } +.#{$ti-prefix}-triangle:before { content: $ti-icon-triangle; } +.#{$ti-prefix}-triangle-filled:before { content: $ti-icon-triangle-filled; } +.#{$ti-prefix}-triangle-inverted:before { content: $ti-icon-triangle-inverted; } +.#{$ti-prefix}-triangle-inverted-filled:before { content: $ti-icon-triangle-inverted-filled; } +.#{$ti-prefix}-triangle-off:before { content: $ti-icon-triangle-off; } +.#{$ti-prefix}-triangle-square-circle:before { content: $ti-icon-triangle-square-circle; } +.#{$ti-prefix}-triangles:before { content: $ti-icon-triangles; } +.#{$ti-prefix}-trident:before { content: $ti-icon-trident; } +.#{$ti-prefix}-trolley:before { content: $ti-icon-trolley; } +.#{$ti-prefix}-trophy:before { content: $ti-icon-trophy; } +.#{$ti-prefix}-trophy-filled:before { content: $ti-icon-trophy-filled; } +.#{$ti-prefix}-trophy-off:before { content: $ti-icon-trophy-off; } +.#{$ti-prefix}-trowel:before { content: $ti-icon-trowel; } +.#{$ti-prefix}-truck:before { content: $ti-icon-truck; } +.#{$ti-prefix}-truck-delivery:before { content: $ti-icon-truck-delivery; } +.#{$ti-prefix}-truck-loading:before { content: $ti-icon-truck-loading; } +.#{$ti-prefix}-truck-off:before { content: $ti-icon-truck-off; } +.#{$ti-prefix}-truck-return:before { content: $ti-icon-truck-return; } +.#{$ti-prefix}-txt:before { content: $ti-icon-txt; } +.#{$ti-prefix}-typography:before { content: $ti-icon-typography; } +.#{$ti-prefix}-typography-off:before { content: $ti-icon-typography-off; } +.#{$ti-prefix}-ufo:before { content: $ti-icon-ufo; } +.#{$ti-prefix}-ufo-off:before { content: $ti-icon-ufo-off; } +.#{$ti-prefix}-umbrella:before { content: $ti-icon-umbrella; } +.#{$ti-prefix}-umbrella-filled:before { content: $ti-icon-umbrella-filled; } +.#{$ti-prefix}-umbrella-off:before { content: $ti-icon-umbrella-off; } +.#{$ti-prefix}-underline:before { content: $ti-icon-underline; } +.#{$ti-prefix}-unlink:before { content: $ti-icon-unlink; } +.#{$ti-prefix}-upload:before { content: $ti-icon-upload; } +.#{$ti-prefix}-urgent:before { content: $ti-icon-urgent; } +.#{$ti-prefix}-usb:before { content: $ti-icon-usb; } +.#{$ti-prefix}-user:before { content: $ti-icon-user; } +.#{$ti-prefix}-user-bolt:before { content: $ti-icon-user-bolt; } +.#{$ti-prefix}-user-cancel:before { content: $ti-icon-user-cancel; } +.#{$ti-prefix}-user-check:before { content: $ti-icon-user-check; } +.#{$ti-prefix}-user-circle:before { content: $ti-icon-user-circle; } +.#{$ti-prefix}-user-code:before { content: $ti-icon-user-code; } +.#{$ti-prefix}-user-cog:before { content: $ti-icon-user-cog; } +.#{$ti-prefix}-user-dollar:before { content: $ti-icon-user-dollar; } +.#{$ti-prefix}-user-down:before { content: $ti-icon-user-down; } +.#{$ti-prefix}-user-edit:before { content: $ti-icon-user-edit; } +.#{$ti-prefix}-user-exclamation:before { content: $ti-icon-user-exclamation; } +.#{$ti-prefix}-user-heart:before { content: $ti-icon-user-heart; } +.#{$ti-prefix}-user-minus:before { content: $ti-icon-user-minus; } +.#{$ti-prefix}-user-off:before { content: $ti-icon-user-off; } +.#{$ti-prefix}-user-pause:before { content: $ti-icon-user-pause; } +.#{$ti-prefix}-user-pin:before { content: $ti-icon-user-pin; } +.#{$ti-prefix}-user-plus:before { content: $ti-icon-user-plus; } +.#{$ti-prefix}-user-question:before { content: $ti-icon-user-question; } +.#{$ti-prefix}-user-search:before { content: $ti-icon-user-search; } +.#{$ti-prefix}-user-share:before { content: $ti-icon-user-share; } +.#{$ti-prefix}-user-shield:before { content: $ti-icon-user-shield; } +.#{$ti-prefix}-user-star:before { content: $ti-icon-user-star; } +.#{$ti-prefix}-user-up:before { content: $ti-icon-user-up; } +.#{$ti-prefix}-user-x:before { content: $ti-icon-user-x; } +.#{$ti-prefix}-users:before { content: $ti-icon-users; } +.#{$ti-prefix}-uv-index:before { content: $ti-icon-uv-index; } +.#{$ti-prefix}-ux-circle:before { content: $ti-icon-ux-circle; } +.#{$ti-prefix}-vaccine:before { content: $ti-icon-vaccine; } +.#{$ti-prefix}-vaccine-bottle:before { content: $ti-icon-vaccine-bottle; } +.#{$ti-prefix}-vaccine-bottle-off:before { content: $ti-icon-vaccine-bottle-off; } +.#{$ti-prefix}-vaccine-off:before { content: $ti-icon-vaccine-off; } +.#{$ti-prefix}-vacuum-cleaner:before { content: $ti-icon-vacuum-cleaner; } +.#{$ti-prefix}-variable:before { content: $ti-icon-variable; } +.#{$ti-prefix}-variable-minus:before { content: $ti-icon-variable-minus; } +.#{$ti-prefix}-variable-off:before { content: $ti-icon-variable-off; } +.#{$ti-prefix}-variable-plus:before { content: $ti-icon-variable-plus; } +.#{$ti-prefix}-vector:before { content: $ti-icon-vector; } +.#{$ti-prefix}-vector-bezier:before { content: $ti-icon-vector-bezier; } +.#{$ti-prefix}-vector-bezier-2:before { content: $ti-icon-vector-bezier-2; } +.#{$ti-prefix}-vector-bezier-arc:before { content: $ti-icon-vector-bezier-arc; } +.#{$ti-prefix}-vector-bezier-circle:before { content: $ti-icon-vector-bezier-circle; } +.#{$ti-prefix}-vector-off:before { content: $ti-icon-vector-off; } +.#{$ti-prefix}-vector-spline:before { content: $ti-icon-vector-spline; } +.#{$ti-prefix}-vector-triangle:before { content: $ti-icon-vector-triangle; } +.#{$ti-prefix}-vector-triangle-off:before { content: $ti-icon-vector-triangle-off; } +.#{$ti-prefix}-venus:before { content: $ti-icon-venus; } +.#{$ti-prefix}-versions:before { content: $ti-icon-versions; } +.#{$ti-prefix}-versions-filled:before { content: $ti-icon-versions-filled; } +.#{$ti-prefix}-versions-off:before { content: $ti-icon-versions-off; } +.#{$ti-prefix}-video:before { content: $ti-icon-video; } +.#{$ti-prefix}-video-minus:before { content: $ti-icon-video-minus; } +.#{$ti-prefix}-video-off:before { content: $ti-icon-video-off; } +.#{$ti-prefix}-video-plus:before { content: $ti-icon-video-plus; } +.#{$ti-prefix}-view-360:before { content: $ti-icon-view-360; } +.#{$ti-prefix}-view-360-off:before { content: $ti-icon-view-360-off; } +.#{$ti-prefix}-viewfinder:before { content: $ti-icon-viewfinder; } +.#{$ti-prefix}-viewfinder-off:before { content: $ti-icon-viewfinder-off; } +.#{$ti-prefix}-viewport-narrow:before { content: $ti-icon-viewport-narrow; } +.#{$ti-prefix}-viewport-wide:before { content: $ti-icon-viewport-wide; } +.#{$ti-prefix}-vinyl:before { content: $ti-icon-vinyl; } +.#{$ti-prefix}-vip:before { content: $ti-icon-vip; } +.#{$ti-prefix}-vip-off:before { content: $ti-icon-vip-off; } +.#{$ti-prefix}-virus:before { content: $ti-icon-virus; } +.#{$ti-prefix}-virus-off:before { content: $ti-icon-virus-off; } +.#{$ti-prefix}-virus-search:before { content: $ti-icon-virus-search; } +.#{$ti-prefix}-vocabulary:before { content: $ti-icon-vocabulary; } +.#{$ti-prefix}-vocabulary-off:before { content: $ti-icon-vocabulary-off; } +.#{$ti-prefix}-volcano:before { content: $ti-icon-volcano; } +.#{$ti-prefix}-volume:before { content: $ti-icon-volume; } +.#{$ti-prefix}-volume-2:before { content: $ti-icon-volume-2; } +.#{$ti-prefix}-volume-3:before { content: $ti-icon-volume-3; } +.#{$ti-prefix}-volume-off:before { content: $ti-icon-volume-off; } +.#{$ti-prefix}-walk:before { content: $ti-icon-walk; } +.#{$ti-prefix}-wall:before { content: $ti-icon-wall; } +.#{$ti-prefix}-wall-off:before { content: $ti-icon-wall-off; } +.#{$ti-prefix}-wallet:before { content: $ti-icon-wallet; } +.#{$ti-prefix}-wallet-off:before { content: $ti-icon-wallet-off; } +.#{$ti-prefix}-wallpaper:before { content: $ti-icon-wallpaper; } +.#{$ti-prefix}-wallpaper-off:before { content: $ti-icon-wallpaper-off; } +.#{$ti-prefix}-wand:before { content: $ti-icon-wand; } +.#{$ti-prefix}-wand-off:before { content: $ti-icon-wand-off; } +.#{$ti-prefix}-wash:before { content: $ti-icon-wash; } +.#{$ti-prefix}-wash-dry:before { content: $ti-icon-wash-dry; } +.#{$ti-prefix}-wash-dry-1:before { content: $ti-icon-wash-dry-1; } +.#{$ti-prefix}-wash-dry-2:before { content: $ti-icon-wash-dry-2; } +.#{$ti-prefix}-wash-dry-3:before { content: $ti-icon-wash-dry-3; } +.#{$ti-prefix}-wash-dry-a:before { content: $ti-icon-wash-dry-a; } +.#{$ti-prefix}-wash-dry-dip:before { content: $ti-icon-wash-dry-dip; } +.#{$ti-prefix}-wash-dry-f:before { content: $ti-icon-wash-dry-f; } +.#{$ti-prefix}-wash-dry-hang:before { content: $ti-icon-wash-dry-hang; } +.#{$ti-prefix}-wash-dry-off:before { content: $ti-icon-wash-dry-off; } +.#{$ti-prefix}-wash-dry-p:before { content: $ti-icon-wash-dry-p; } +.#{$ti-prefix}-wash-dry-shade:before { content: $ti-icon-wash-dry-shade; } +.#{$ti-prefix}-wash-dry-w:before { content: $ti-icon-wash-dry-w; } +.#{$ti-prefix}-wash-dryclean:before { content: $ti-icon-wash-dryclean; } +.#{$ti-prefix}-wash-dryclean-off:before { content: $ti-icon-wash-dryclean-off; } +.#{$ti-prefix}-wash-gentle:before { content: $ti-icon-wash-gentle; } +.#{$ti-prefix}-wash-machine:before { content: $ti-icon-wash-machine; } +.#{$ti-prefix}-wash-off:before { content: $ti-icon-wash-off; } +.#{$ti-prefix}-wash-press:before { content: $ti-icon-wash-press; } +.#{$ti-prefix}-wash-temperature-1:before { content: $ti-icon-wash-temperature-1; } +.#{$ti-prefix}-wash-temperature-2:before { content: $ti-icon-wash-temperature-2; } +.#{$ti-prefix}-wash-temperature-3:before { content: $ti-icon-wash-temperature-3; } +.#{$ti-prefix}-wash-temperature-4:before { content: $ti-icon-wash-temperature-4; } +.#{$ti-prefix}-wash-temperature-5:before { content: $ti-icon-wash-temperature-5; } +.#{$ti-prefix}-wash-temperature-6:before { content: $ti-icon-wash-temperature-6; } +.#{$ti-prefix}-wash-tumble-dry:before { content: $ti-icon-wash-tumble-dry; } +.#{$ti-prefix}-wash-tumble-off:before { content: $ti-icon-wash-tumble-off; } +.#{$ti-prefix}-wave-saw-tool:before { content: $ti-icon-wave-saw-tool; } +.#{$ti-prefix}-wave-sine:before { content: $ti-icon-wave-sine; } +.#{$ti-prefix}-wave-square:before { content: $ti-icon-wave-square; } +.#{$ti-prefix}-webhook:before { content: $ti-icon-webhook; } +.#{$ti-prefix}-webhook-off:before { content: $ti-icon-webhook-off; } +.#{$ti-prefix}-weight:before { content: $ti-icon-weight; } +.#{$ti-prefix}-wheelchair:before { content: $ti-icon-wheelchair; } +.#{$ti-prefix}-wheelchair-off:before { content: $ti-icon-wheelchair-off; } +.#{$ti-prefix}-whirl:before { content: $ti-icon-whirl; } +.#{$ti-prefix}-wifi:before { content: $ti-icon-wifi; } +.#{$ti-prefix}-wifi-0:before { content: $ti-icon-wifi-0; } +.#{$ti-prefix}-wifi-1:before { content: $ti-icon-wifi-1; } +.#{$ti-prefix}-wifi-2:before { content: $ti-icon-wifi-2; } +.#{$ti-prefix}-wifi-off:before { content: $ti-icon-wifi-off; } +.#{$ti-prefix}-wind:before { content: $ti-icon-wind; } +.#{$ti-prefix}-wind-off:before { content: $ti-icon-wind-off; } +.#{$ti-prefix}-windmill:before { content: $ti-icon-windmill; } +.#{$ti-prefix}-windmill-filled:before { content: $ti-icon-windmill-filled; } +.#{$ti-prefix}-windmill-off:before { content: $ti-icon-windmill-off; } +.#{$ti-prefix}-window:before { content: $ti-icon-window; } +.#{$ti-prefix}-window-maximize:before { content: $ti-icon-window-maximize; } +.#{$ti-prefix}-window-minimize:before { content: $ti-icon-window-minimize; } +.#{$ti-prefix}-window-off:before { content: $ti-icon-window-off; } +.#{$ti-prefix}-windsock:before { content: $ti-icon-windsock; } +.#{$ti-prefix}-wiper:before { content: $ti-icon-wiper; } +.#{$ti-prefix}-wiper-wash:before { content: $ti-icon-wiper-wash; } +.#{$ti-prefix}-woman:before { content: $ti-icon-woman; } +.#{$ti-prefix}-wood:before { content: $ti-icon-wood; } +.#{$ti-prefix}-world:before { content: $ti-icon-world; } +.#{$ti-prefix}-world-bolt:before { content: $ti-icon-world-bolt; } +.#{$ti-prefix}-world-cancel:before { content: $ti-icon-world-cancel; } +.#{$ti-prefix}-world-check:before { content: $ti-icon-world-check; } +.#{$ti-prefix}-world-code:before { content: $ti-icon-world-code; } +.#{$ti-prefix}-world-cog:before { content: $ti-icon-world-cog; } +.#{$ti-prefix}-world-dollar:before { content: $ti-icon-world-dollar; } +.#{$ti-prefix}-world-down:before { content: $ti-icon-world-down; } +.#{$ti-prefix}-world-download:before { content: $ti-icon-world-download; } +.#{$ti-prefix}-world-exclamation:before { content: $ti-icon-world-exclamation; } +.#{$ti-prefix}-world-heart:before { content: $ti-icon-world-heart; } +.#{$ti-prefix}-world-latitude:before { content: $ti-icon-world-latitude; } +.#{$ti-prefix}-world-longitude:before { content: $ti-icon-world-longitude; } +.#{$ti-prefix}-world-minus:before { content: $ti-icon-world-minus; } +.#{$ti-prefix}-world-off:before { content: $ti-icon-world-off; } +.#{$ti-prefix}-world-pause:before { content: $ti-icon-world-pause; } +.#{$ti-prefix}-world-pin:before { content: $ti-icon-world-pin; } +.#{$ti-prefix}-world-plus:before { content: $ti-icon-world-plus; } +.#{$ti-prefix}-world-question:before { content: $ti-icon-world-question; } +.#{$ti-prefix}-world-search:before { content: $ti-icon-world-search; } +.#{$ti-prefix}-world-share:before { content: $ti-icon-world-share; } +.#{$ti-prefix}-world-star:before { content: $ti-icon-world-star; } +.#{$ti-prefix}-world-up:before { content: $ti-icon-world-up; } +.#{$ti-prefix}-world-upload:before { content: $ti-icon-world-upload; } +.#{$ti-prefix}-world-www:before { content: $ti-icon-world-www; } +.#{$ti-prefix}-world-x:before { content: $ti-icon-world-x; } +.#{$ti-prefix}-wrecking-ball:before { content: $ti-icon-wrecking-ball; } +.#{$ti-prefix}-writing:before { content: $ti-icon-writing; } +.#{$ti-prefix}-writing-off:before { content: $ti-icon-writing-off; } +.#{$ti-prefix}-writing-sign:before { content: $ti-icon-writing-sign; } +.#{$ti-prefix}-writing-sign-off:before { content: $ti-icon-writing-sign-off; } +.#{$ti-prefix}-x:before { content: $ti-icon-x; } +.#{$ti-prefix}-xbox-a:before { content: $ti-icon-xbox-a; } +.#{$ti-prefix}-xbox-b:before { content: $ti-icon-xbox-b; } +.#{$ti-prefix}-xbox-x:before { content: $ti-icon-xbox-x; } +.#{$ti-prefix}-xbox-y:before { content: $ti-icon-xbox-y; } +.#{$ti-prefix}-yin-yang:before { content: $ti-icon-yin-yang; } +.#{$ti-prefix}-yin-yang-filled:before { content: $ti-icon-yin-yang-filled; } +.#{$ti-prefix}-yoga:before { content: $ti-icon-yoga; } +.#{$ti-prefix}-zeppelin:before { content: $ti-icon-zeppelin; } +.#{$ti-prefix}-zeppelin-off:before { content: $ti-icon-zeppelin-off; } +.#{$ti-prefix}-zip:before { content: $ti-icon-zip; } +.#{$ti-prefix}-zodiac-aquarius:before { content: $ti-icon-zodiac-aquarius; } +.#{$ti-prefix}-zodiac-aries:before { content: $ti-icon-zodiac-aries; } +.#{$ti-prefix}-zodiac-cancer:before { content: $ti-icon-zodiac-cancer; } +.#{$ti-prefix}-zodiac-capricorn:before { content: $ti-icon-zodiac-capricorn; } +.#{$ti-prefix}-zodiac-gemini:before { content: $ti-icon-zodiac-gemini; } +.#{$ti-prefix}-zodiac-leo:before { content: $ti-icon-zodiac-leo; } +.#{$ti-prefix}-zodiac-libra:before { content: $ti-icon-zodiac-libra; } +.#{$ti-prefix}-zodiac-pisces:before { content: $ti-icon-zodiac-pisces; } +.#{$ti-prefix}-zodiac-sagittarius:before { content: $ti-icon-zodiac-sagittarius; } +.#{$ti-prefix}-zodiac-scorpio:before { content: $ti-icon-zodiac-scorpio; } +.#{$ti-prefix}-zodiac-taurus:before { content: $ti-icon-zodiac-taurus; } +.#{$ti-prefix}-zodiac-virgo:before { content: $ti-icon-zodiac-virgo; } +.#{$ti-prefix}-zoom-cancel:before { content: $ti-icon-zoom-cancel; } +.#{$ti-prefix}-zoom-check:before { content: $ti-icon-zoom-check; } +.#{$ti-prefix}-zoom-check-filled:before { content: $ti-icon-zoom-check-filled; } +.#{$ti-prefix}-zoom-code:before { content: $ti-icon-zoom-code; } +.#{$ti-prefix}-zoom-exclamation:before { content: $ti-icon-zoom-exclamation; } +.#{$ti-prefix}-zoom-filled:before { content: $ti-icon-zoom-filled; } +.#{$ti-prefix}-zoom-in:before { content: $ti-icon-zoom-in; } +.#{$ti-prefix}-zoom-in-area:before { content: $ti-icon-zoom-in-area; } +.#{$ti-prefix}-zoom-in-area-filled:before { content: $ti-icon-zoom-in-area-filled; } +.#{$ti-prefix}-zoom-in-filled:before { content: $ti-icon-zoom-in-filled; } +.#{$ti-prefix}-zoom-money:before { content: $ti-icon-zoom-money; } +.#{$ti-prefix}-zoom-out:before { content: $ti-icon-zoom-out; } +.#{$ti-prefix}-zoom-out-area:before { content: $ti-icon-zoom-out-area; } +.#{$ti-prefix}-zoom-out-filled:before { content: $ti-icon-zoom-out-filled; } +.#{$ti-prefix}-zoom-pan:before { content: $ti-icon-zoom-pan; } +.#{$ti-prefix}-zoom-question:before { content: $ti-icon-zoom-question; } +.#{$ti-prefix}-zoom-replace:before { content: $ti-icon-zoom-replace; } +.#{$ti-prefix}-zoom-reset:before { content: $ti-icon-zoom-reset; } +.#{$ti-prefix}-zzz:before { content: $ti-icon-zzz; } +.#{$ti-prefix}-zzz-off:before { content: $ti-icon-zzz-off; } diff --git a/playground/index.html b/playground/index.html new file mode 100644 index 00000000000000..caf52018180e43 --- /dev/null +++ b/playground/index.html @@ -0,0 +1,202 @@ + + + + three.js - playground + + + + + + + + + + + + + + + + diff --git a/examples/jsm/libs/flow.module.js b/playground/libs/flow.module.js similarity index 67% rename from examples/jsm/libs/flow.module.js rename to playground/libs/flow.module.js index 0fc27a54c02295..da2b64a5bc932d 100644 --- a/examples/jsm/libs/flow.module.js +++ b/playground/libs/flow.module.js @@ -16,16 +16,9 @@ function __flow__addCSS( css ) { } -__flow__addCSS( '@keyframes f-animation-open { 0% { transform: scale(.5); opacity: 0; } 100% { transform: scale(1); opacity: 1; }}f-canvas,f-canvas canvas.background,f-canvas canvas.frontground { position: absolute; top: 0; left: 0; margin: 0; padding: 0; width: 100%; height: 100%; -webkit-touch-callout: none; transition: opacity .17s;}f-canvas { cursor: grab;}f-canvas canvas.frontground { z-index: 10;}body.dragging *:not(.drag) { pointer-events: none !important;}f-canvas.grabbing * { cursor: grabbing; user-select: none;}f-canvas canvas.background,f-canvas canvas.frontground { position: fixed; overflow: hidden;}f-canvas canvas.frontground { pointer-events: none;}f-canvas::-webkit-scrollbar { width: 8px; height: 8px;}f-canvas::-webkit-scrollbar-thumb:hover{ background: #014fc5;}f-canvas::-webkit-scrollbar-track { background: #363636;}f-canvas::-webkit-scrollbar-thumb { background-color: #666666; border-radius: 10px; border: 0;}f-canvas f-content { left: 0; top: 0;}f-canvas f-content,f-canvas f-area { position: absolute; display: block;}f-canvas canvas.map { position: absolute; top: 10px; right: 10px; z-index: 50; backdrop-filter: blur( 10px ); background-color: rgba( 45, 45, 48, .8 );}f-node { position: absolute; margin: 0; padding: 0; user-select: none; width: 320px; z-index: 1; cursor: auto; filter: drop-shadow(0 0 10px #00000061); backdrop-filter: blur(4px);}f-node.selected { z-index: 2;}f-canvas.focusing canvas.background,f-canvas.focusing f-node:not(.selected),f-canvas.focusing f-element f-disconnect:not(.selected) { opacity: 0; pointer-events: none;}.dragging f-canvas f-element f-disconnect { opacity: 0;}.dragging.node f-canvas.focusing canvas.background,.dragging.node f-canvas.focusing f-node:not(.selected) { opacity: .5;}f-node.selected,f-canvas.dragging-rio f-node:hover,f-canvas.dragging-lio f-node:hover { filter: drop-shadow(0 0 10px #00000061) drop-shadow(0 0 8px #4444dd);}f-node.closed f-element:not(:first-child) { display: none;}f-node.center { top: 50%; left: 50%; transform: translate( -50%, -50% );}f-node.top-right { top: 0; right: 0;}f-node.top-center { top: 0; left: 50%; transform: translateX( -50% );}f-node.top-left { top: 0; left: 0;}f-node { transition: filter 0.2s ease, opacity 0.12s ease;}f-node { animation: .2s f-animation-open 1 alternate ease-out;}f-tips,f-drop,f-menu,f-menu input,f-menu button,f-element,f-element input,f-element select,f-element button,f-element textarea { font-family: \'Open Sans\', sans-serif; font-size: 13px; text-transform: capitalize; color: #eeeeee; outline: solid 0px #000; margin: 0; padding: 0; border: 0; user-select: none; -webkit-tap-highlight-color: transparent; transition: background 0.2s ease, filter 0.2s ease;}f-element input:read-only { color: #666;}f-element input,f-element textarea { text-transform: initial;}f-element input { transition: background 0.1s ease;}f-element input,f-element select,f-element button,f-element textarea { background-color: #232324d1;}f-element { position: relative; width: calc( 100% - 14px ); background: rgba(45, 45, 48, 0.95); pointer-events: auto; border-bottom: 2px solid #232323; display: flex; padding-left: 7px; padding-right: 7px; padding-top: 2px; padding-bottom: 2px;}f-element:after,f-element:before { transition: opacity .17s; opacity: 0; content: \'\';}f-element[tooltip]:hover:after,f-element[tooltip]:focus-within:after { font-size: 14px !important; display: flex; justify-content: center; position: fixed; margin-left: -7px; width: calc( 100% ); background: #1d1d1de8; border: 1px solid #444444a1; border-radius: 6px; color: #dadada; content: attr( tooltip ); margin-top: -41px; font-size: 16px; padding-top: 3px; padding-bottom: 3px; z-index: 10; opacity: 1; backdrop-filter: blur(4px); white-space: nowrap; overflow: hidden; text-shadow: 1px 1px 0px #0007;}f-element[tooltip]:hover:before,f-element[tooltip]:focus-within:before { border: solid; border-color: #1d1d1de8 transparent; border-width: 12px 6px 0 6px; left: calc( 50% - 6px ); bottom: 30px; position: absolute; opacity: 1; z-index: 11;}f-element[error] { background-color: #ff0000;}f-element[error]:hover:after,f-element[error]:focus-within:after { border: none; background-color: #ff0000bb; filter: drop-shadow( 2px 2px 5px #000 ); color: #fff;}f-element[error]:hover:before,f-element[error]:focus-within:before { border-color: #ff0000bb transparent;}f-element { height: 24px;}f-element input { margin-top: 2px; margin-bottom: 2px; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%); margin-left: 2px; margin-right: 2px; width: 100%; padding-left: 4px; padding-right: 4px;}f-element input.number { cursor: col-resize;}f-element input:focus[type=\'text\'], f-element input:focus[type=\'range\'], f-element input:focus[type=\'color\'] { background: rgba( 0, 0, 0, 0.6 ); outline: solid 1px rgba( 0, 80, 200, 0.98 );}f-element input[type=\'color\'] { appearance: none; padding: 0; margin-left: 2px; margin-right: 2px; height: calc( 100% - 4px ); margin-top: 2px; border: none;}f-element input[type=\'color\']::-webkit-color-swatch-wrapper { padding: 2px;}f-element input[type=\'color\']::-webkit-color-swatch { border: none; cursor: alias;}f-element input[type=\'range\'] { appearance: none; width: 100%; overflow: hidden; padding: 0; cursor: ew-resize;}f-element input[type=\'range\']::-webkit-slider-runnable-track { appearance: none; height: 10px; color: #13bba4; margin: 0;}f-element input[type=\'range\']::-webkit-slider-thumb { appearance: none; width: 0; background: #434343; box-shadow: -500px 0 0 500px rgba( 0, 120, 255, 0.98 ); border-radius: 50%; border: 0 !important;}f-element input[type=\'range\']::-webkit-slider-runnable-track { margin-left: -4px; margin-right: -5px;}f-element input[type=\'checkbox\'] { appearance: none; cursor: pointer;}f-element input[type=\'checkbox\'].toggle { height: 20px; width: 45px; border-radius: 16px; display: inline-block; position: relative; margin: 0; margin-top: 2px; background: linear-gradient( 0deg, #292929 0%, #0a0a0ac2 100% ); transition: all 0.2s ease;}f-element input[type=\'checkbox\'].toggle:after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: white; box-shadow: 0 1px 2px rgba(44, 44, 44, 0.2); transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);}f-element input[type=\'checkbox\'].toggle:checked { background: linear-gradient( 0deg, #0177fb 0%, #0177fb 100% );}f-element input[type=\'checkbox\'].toggle:checked:after { transform: translatex(25px);}f-element.auto-height { display: table;}f-element textarea { width: calc( 100% - 18px ); padding-top: 1px; padding-bottom: 3px; padding-left: 3px; padding-right: 8px; margin-top: 2px; margin-left: 2px; height: calc( 100% - 8px ); max-height: 300px; border-radius: 2px; resize: none; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%);}f-element.auto-height textarea { resize: auto;}f-element select { width: 100%; margin-top: 2px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; cursor: pointer; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%);}f-element f-toolbar { position: absolute; display: flex; top: 0; width: 100%; height: 100%; align-content: space-around;}f-element.input-right f-toolbar { right: 7px; float: right; justify-content: end;}f-element f-toolbar { margin-top: auto; margin-bottom: auto; margin-left: 3px; margin-right: 3px; font-size: 18px; line-height: 18px;}f-element f-toolbar button { opacity: .7; cursor: pointer; font-size: 14px; width: unset; height: unset; border-radius: unset; border: unset; outline: 0; background-color: unset; box-shadow: unset;}f-element f-toolbar button:hover,f-element f-toolbar button:active { opacity: 1; border: 0; background-color: unset;}f-element input.range-value { width: 60px; text-align: center;}f-menu.context button,f-element button { width: 100%; height: calc( 100% - 4px ); margin-left: 2px; margin-right: 2px; margin-top: 2px; border-radius: 3px; cursor: pointer;}f-element button { box-shadow: inset 1px 1px 1px 0 rgb(255 255 255 / 17%), inset -2px -2px 2px 0 rgb(0 0 0 / 26%);}f-element button:hover { color: #fff; background-color: #2a2a2a;}f-element button:active { border: 1px solid rgba( 0, 120, 255, 0.98 );}f-element f-inputs,f-element f-subinputs { display: flex; justify-content: flex-end; width: 100%;}f-element f-inputs { left: 100px; top: 50%; transform: translateY( -50% ); position: absolute; width: calc( 100% - 106px ); height: calc( 100% - 4px ); z-index: 1;}f-element.inputs-disable f-inputs { filter: grayscale(100%); opacity: .5;}f-element.inputs-disable f-inputs input { pointer-events: none;}f-element f-label,f-element span { margin: auto; text-shadow: 1px 1px 0px #0007;}f-element f-label { padding-left: 4px; white-space: nowrap; position: absolute; top: 50%; transform: translateY( -50% ); width: calc( 100% - 20px );}f-element.right f-label { text-align: right;}f-element.center f-label { text-align: center;}f-element f-label i { font-size: 18px; margin-right: 6px; vertical-align: sub;}f-element f-label.center { width: 100%; text-align: center; display: block;}f-element.title { height: 29px; background-color: #3a3a3ab0; background-color: #3b3b43ed; cursor: all-scroll; border-top-left-radius: 6px; border-top-right-radius: 6px;}f-element.blue { background-color: #014fc5;}f-element.red { background-color: #bd0b0b;}f-element.green { background-color: #148d05;}f-element.yellow { background-color: #d6b100;}f-element.title.left { text-align: left; display: inline-grid; justify-content: start;}f-element.title f-title { text-align: center; font-size: 15px; padding-top: 2px; position: absolute; top: 50%; transform: translateY( -50% ); width: 100%;}f-element.title i { font-size: 18px; position: absolute; right: 10px; top: 50%; transform: translateY( -50% ); opacity: .5;}f-element.title f-toolbar i { font-size: 20px; right: unset; left: 0px;}f-element.input-right.title i { left: 10px; right: unset;}f-element.title.left span { text-align: left;}f-element f-io { border: 2px solid #dadada; width: 7px; height: 7px; position: absolute; background: #242427; border-radius: 8px; float: left; left: -7px; top: calc( 50% - 5px ); cursor: alias; box-shadow: 0 0 3px 2px #0000005e; z-index: 1;}f-element f-io.connect,f-canvas.dragging-rio f-element:hover f-io.lio,f-canvas.dragging-lio f-element:hover f-io.rio { zoom: 1.4;}f-node.io-connect f-io:not(.connect) { border: 2px solid #dadada !important; zoom: 1 !important;}f-element f-io.rio { float: right; right: -7px; left: unset;}f-element f-disconnect { position: absolute; left: -35px; top: 50%; font-size: 22px; transform: translateY( -50% ); filter: drop-shadow(0 0 5px #000); text-shadow: 0px 0px 5px black; cursor: pointer; transition: all .2s;}f-element.input-right f-disconnect { right: -35px; left: unset;}f-element f-disconnect:hover { color: #ff3300;}f-element textarea::-webkit-scrollbar { width: 6px;}f-element textarea::-webkit-scrollbar-track { background: #111; } f-element textarea::-webkit-scrollbar-thumb { background: #0177fb; }f-element textarea::-webkit-scrollbar-thumb:hover { background: #1187ff; }f-element.small { height: 18px;}f-element.large { height: 36px;}f-canvas.dragging-lio f-node:not(.io-connect) f-element.rio:hover,f-canvas.dragging-rio f-node:not(.io-connect) f-element.lio:hover,f-element.select { background-color: rgba(61, 70, 82, 0.98);}f-element.invalid > f-io { zoom: 1 !important;}f-element.invalid::after { font-size: 14px !important; display: flex; justify-content: center; align-items:center; margin: auto; position: absolute; width: 100%; height: 100%; background: #bd0b0b77; vertical-align: middle; color: #fff; content: \'Not Compatible\'; opacity: .95; backdrop-filter: grayscale(100%); white-space: nowrap; overflow: hidden; left: 0; top: 0; text-transform: initial;}f-drop { width: 100%; height: 100%; position: sticky; left: 0; top: 0; background: #02358417; text-align: center; justify-content: center; align-items: center; display: flex; box-shadow: inset 0 0 20px 10px #464ace17; pointer-events: none; transition: all .07s; opacity: 0; visibility: hidden;}f-drop.visible { visibility: unset; opacity: unset; transition: all .23s;}f-drop span { opacity: .5; font-size: 40px; text-shadow: 0px 0px 5px #000; font-weight: bold;}f-tooltip { pointer-events: none;}f-tooltip { position: absolute; left: 0; top: 0; background: rgba(0,0,0,.8); backdrop-filter: blur(4px); font-size: 14px; padding: 7px; left: 50%; border-radius: 10px; transform: translateX(-50%); visibility: hidden; pointer-events: none; opacity: 0; transition: all 0.3s ease; z-index: 150; white-space: nowrap;}f-menu.context,f-menu.search { position: absolute;}f-menu.context { width: 170px; z-index: 110;}f-menu.search { bottom: 85px; left: 50%; transform: translateX(-50%); z-index: 10; width: 300px;}f-menu.context f-list { display: block; margin: 0; background: #171717e6; font-size: 12px; border-radius: 6px; backdrop-filter: blur(6px); border: 1px solid #7e7e7e45; box-shadow: 3px 3px 6px rgba(0,0,0,.2); transition: opacity 0.2s ease, transform 0.1s ease;}f-menu.search f-list { margin: 0 6px 0 6px; display: flex; flex-direction: column-reverse; margin-bottom: 5px;}f-menu.context.hidden { visibility: hidden; opacity: 0;}f-menu.context f-item,f-menu.search f-item { display: block; position: relative; margin: 0; padding: 0; white-space: nowrap;}f-menu.search f-item { opacity: 0;}f-menu.context f-item.submenu::after { content: ""; position: absolute; right: 6px; top: 50%; -webkit-transform: translateY( -50% ); transform: translateY( -50% ); border: 5px solid transparent; border-left-color: #808080;}f-menu.context f-item:hover > f-menu,f-menu.context f-item.active > f-menu { visibility: unset; transform: unset; opacity: unset;}f-menu.context f-menu { top: 0px; left: calc( 100% - 4px );}f-menu.context f-item button,f-menu.search f-item button { overflow: visible; display: block; width: calc( 100% - 6px ); text-align: left; cursor: pointer; white-space: nowrap; padding: 6px 8px; border-radius: 3px; background: rgba(45, 45, 48, 0.95); border: 0; color: #ddd; margin: 3px; text-shadow: 1px 1px 0px #0007;}f-menu.context f-item button i,f-menu.search f-item button i { float: left; font-size: 16px;}f-menu.context f-item button span,f-menu.search f-item button span { margin-left: 6px;}f-menu.context f-item:hover > button,f-menu.search f-item:hover > button,f-menu.search f-item.active > button { color: #fff; background-color: rgba(61, 70, 82, 0.98);}f-menu.search f-item:hover,f-menu.search f-item.active { opacity: 1 !important;}f-menu.context f-item button:active { outline: solid 1px rgba( 0, 80, 200, 0.98 );}f-menu.context f-item f-tooltip { margin-left: 85px; top: -50px;}f-menu.search f-item { display: none;}f-menu.search f-item:nth-child(1) { opacity: 1; display: unset;}f-menu.search f-item:nth-child(2) { opacity: .8; display: unset;}f-menu.search f-item:nth-child(3) { opacity: .6; display: unset;}f-menu.search f-item:nth-child(4) { opacity: .4; display: unset;}f-menu.search f-item button { border-radius: 14px;}f-tips { right: 10px; top: 10px; position: absolute; z-index: 100; pointer-events: none; display: flex; flex-direction: column;}f-tips f-tip { width: 450px; font-size: 13px; border-radius: 6px; text-align: center; display: block; height: auto; color: #ffffffe0; margin: 4px; padding: 4px; background: #17171794; border: 1px solid #7e7e7e38; line-height: 100%; backdrop-filter: blur(6px); transition: all 0.2s ease; text-transform: initial; opacity: 0;}f-tips f-tip:nth-child(1) { opacity: 1;}f-tips f-tip:nth-child(2) { opacity: .75;}f-tips f-tip:nth-child(3) { opacity: .25;}f-tips f-tip:nth-child(4) { opacity: .1;}f-tips f-tip.error { background: #b900005e;}f-menu.search input { width: calc( 100% - 28px ); height: 41px; position: absolute; z-index: 10; border-radius: 20px; padding-left: 14px; padding-right: 14px; font-size: 15px; background-color: #17171794; border: 1px solid #7e7e7e45; backdrop-filter: blur(6px); box-shadow: 3px 3px 6px rgb(0 0 0 / 20%); text-transform: initial;}f-menu.circle { position: absolute; z-index: 100;}f-menu.circle.top { top: 40px;}f-menu.circle.left { left: 40px;}f-menu.circle.bottom { bottom: 40px;}f-menu.circle.right { right: 40px;}f-menu.circle f-item { align-content: space-around; margin-right: 20px;}f-menu.circle f-item button { width: 47px; height: 47px; font-size: 22px; background: #17171794; border-radius: 50%; backdrop-filter: blur(6px); border: 1px solid #7e7e7e45; line-height: 100%; cursor: pointer; box-shadow: 3px 3px 6px rgba(0,0,0,.2);}f-menu.circle f-item f-tooltip { margin-top: -60px;}f-menu.circle.top f-item f-tooltip { margin-top: 50px;}.f-rounded f-node f-element,.f-rounded f-node f-element.title.left { border-radius: 10px 5px 10px 5px;}.f-rounded f-node f-element input, .f-rounded f-node f-element select,.f-rounded f-node f-element button,.f-rounded f-node f-element textarea,.f-rounded f-node f-element input[type=\'checkbox\'].toggle,.f-rounded f-node f-element input[type=\'checkbox\'].toggle:after { border-radius: 20px 10px;}.f-rounded f-node f-element input { padding-left: 7px; padding-right: 7px;}.f-rounded f-menu.context,.f-rounded f-menu.context f-item button { border-radius: 20px 10px;}@media (hover: hover) and (pointer: fine) { f-node:not(.selected):hover { filter: drop-shadow(0 0 6px #66666630); } f-element f-toolbar { visibility: hidden; opacity: 0; transition: opacity 0.2s ease; } body:not(.connecting) f-node:hover > f-element f-toolbar { visibility: visible; opacity: 1; } f-element f-io:hover { zoom: 1.4; } f-menu.circle f-item button:hover { background-color: #2a2a2a; } f-menu.search input:hover, f-menu.search input:focus { background-color: #1a1a1a; filter: drop-shadow(0 0 6px #66666630); } f-menu.search input:focus { filter: drop-shadow(0 0 8px #4444dd); } f-menu.circle f-item button:hover > f-tooltip, f-menu.context f-item button:hover > f-tooltip { visibility: visible; opacity: 1; } f-menu.circle f-item button:hover > f-tooltip { margin-top: -50px; } f-menu.circle.top f-item button:hover > f-tooltip { margin-top: 60px; } f-menu.context f-item button:hover > f-tooltip { top: -30px; } f-menu.circle f-item button:focus > f-tooltip, f-menu.context f-item button:focus > f-tooltip { visibility: hidden; opacity: 0; }}@media (hover: none) and (pointer: coarse) { body.dragging f-canvas, body.connecting f-canvas { overflow: hidden !important; }}f-element.invalid > f-inputs,f-element.invalid > f-label,f-element.invalid > f-title,f-element.invalid > f-toolbar,f-element.invalid > input,f-element.invalid > select { opacity: .1 !important;}f-canvas { will-change: top, left;}f-node { will-change: transform !important;}' ); +__flow__addCSS( `f-element .ti { vertical-align: middle; font-size: 17px; display: inline-block; margin-right: 5px;}f-element f-disconnect .ti { font-size: 20px; margin-top: -6px; margin-left: 2px;}@keyframes f-animation-open { 0% { transform: scale(.5); opacity: 0; } 100% { transform: scale(1); opacity: 1; }}f-canvas,f-canvas canvas.background,f-canvas canvas.frontground { position: absolute; top: 0; left: 0; margin: 0; padding: 0; width: 100%; height: 100%; -webkit-touch-callout: none; transition: opacity .17s;}f-canvas { cursor: grab;}f-canvas canvas.frontground { z-index: 10;}body.dragging *:not(.drag) { pointer-events: none !important;}f-canvas.grabbing * { cursor: grabbing; user-select: none;}f-canvas canvas.background,f-canvas canvas.frontground { position: fixed; overflow: hidden;}f-canvas canvas.frontground { pointer-events: none;}::-webkit-scrollbar { width: 6px; height: 6px;}::-webkit-scrollbar-thumb:hover{ background: #014fc5;}::-webkit-scrollbar-track { background: #363636;}::-webkit-scrollbar-thumb { background-color: #666666; border-radius: 8px; border: 0;}f-canvas f-content { left: 0; top: 0;}f-canvas f-content,f-canvas f-area { position: absolute; display: block;}f-canvas canvas.map { position: absolute; top: 10px; right: 10px; z-index: 50; backdrop-filter: blur( 10px ); background-color: rgba( 45, 45, 48, .8 );}f-node { position: absolute; margin: 0; padding: 0; user-select: none; width: 320px; z-index: 1; cursor: auto; filter: drop-shadow(0 0 10px #00000061); backdrop-filter: blur(4px);}f-node.selected { z-index: 2;}f-canvas.focusing canvas.background,f-canvas.focusing f-node:not(.selected),f-canvas.focusing f-element f-disconnect:not(.selected) { opacity: 0; pointer-events: none;}.dragging f-canvas f-element f-disconnect { opacity: 0;}.dragging.node f-canvas.focusing canvas.background,.dragging.node f-canvas.focusing f-node:not(.selected) { opacity: .5;}f-node.selected,f-canvas.dragging-rio f-node:hover,f-canvas.dragging-lio f-node:hover { filter: drop-shadow(0 0 10px #00000061) drop-shadow(0 0 8px #4444dd);}f-node.closed f-element:not(:first-child) { display: none;}f-node.center { top: 50%; left: 50%; transform: translate( -50%, -50% );}f-node.top-right { top: 0; right: 0;}f-node.top-center { top: 0; left: 50%; transform: translateX( -50% );}f-node.top-left { top: 0; left: 0;}f-node { transition: filter 0.2s ease, opacity 0.12s ease;}f-node { animation: .2s f-animation-open 1 alternate ease-out;}f-tips,f-drop,f-menu,f-menu input,f-menu button,f-element,f-element input,f-element select,f-element button,f-element textarea { font-family: 'Open Sans', sans-serif; font-size: 12px; text-transform: initial; line-height: normal; color: #eeeeee; outline: solid 0px #000; margin: 0; padding: 0; border: 0; user-select: none; -webkit-tap-highlight-color: transparent; transition: background 0.2s ease, filter 0.2s ease;}f-node.resizable { display: grid; width: auto !important;}f-node.resizable f-element:last-child { resize: both; overflow: auto; min-width: 100px;}f-element input:read-only { color: #666;}f-element input,f-element textarea { text-transform: initial;}f-element input { transition: background 0.1s ease;}f-element input,f-element select,f-element button,f-element textarea { background-color: #232324d1;}f-element { position: relative; width: calc( 100% - 14px ); background: rgba(45, 45, 48, 0.95); pointer-events: auto; border-bottom: 2px solid #232323; display: flex; padding-left: 7px; padding-right: 7px; padding-top: 2px; padding-bottom: 2px;}f-element:after,f-element:before { transition: opacity .17s; opacity: 0; content: '';}f-element[tooltip]:hover:after,f-element[tooltip]:focus-within:after { font-size: 14px !important; display: flex; justify-content: center; position: fixed; margin-left: -7px; width: calc( 100% ); background: #1d1d1de8; border: 1px solid #444444a1; border-radius: 6px; color: #dadada; content: attr( tooltip ); margin-top: -41px; font-size: 16px; padding-top: 3px; padding-bottom: 3px; z-index: 10; opacity: 1; backdrop-filter: blur(4px); white-space: nowrap; overflow: hidden; text-shadow: 1px 1px 0px #0007;}f-element[tooltip]:hover:before,f-element[tooltip]:focus-within:before { border: solid; border-color: #1d1d1de8 transparent; border-width: 12px 6px 0 6px; left: calc( 50% - 6px ); bottom: 30px; position: absolute; opacity: 1; z-index: 11;}f-element[error] { background-color: #ff0000;}f-element[error]:hover:after,f-element[error]:focus-within:after { border: none; background-color: #ff0000bb; filter: drop-shadow( 2px 2px 5px #000 ); color: #fff;}f-element[error]:hover:before,f-element[error]:focus-within:before { border-color: #ff0000bb transparent;}f-element { height: 24px;}f-element input { margin-top: 2px; margin-bottom: 2px; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%); margin-left: 2px; margin-right: 2px; width: 100%; padding-left: 4px; padding-right: 4px; line-height: 100%;}f-element f-string:has( i[type=icon] ) input { padding-right: 23px;}f-element input.number { cursor: col-resize;}f-element input:focus[type='text'], f-element input:focus[type='range'], f-element input:focus[type='color'] { background: rgba( 0, 0, 0, 0.6 ); outline: solid 1px rgba( 0, 80, 200, 0.98 );}f-element input[type='color'] { appearance: none; padding: 0; margin-left: 2px; margin-right: 2px; height: calc( 100% - 4px ); margin-top: 2px; border: none;}f-element input[type='color']::-webkit-color-swatch-wrapper { padding: 2px;}f-element input[type='color']::-webkit-color-swatch { border: none; cursor: alias;}f-element input[type='range'] { appearance: none; width: 100%; overflow: hidden; padding: 0; cursor: ew-resize;}f-element input[type='range']::-webkit-slider-runnable-track { appearance: none; height: 10px; color: #13bba4; margin: 0;}f-element input[type='range']::-webkit-slider-thumb { appearance: none; width: 0; background: #434343; box-shadow: -500px 0 0 500px rgba( 0, 120, 255, 0.98 ); border-radius: 50%; border: 0 !important;}f-element input[type='range']::-webkit-slider-runnable-track { margin-left: -4px; margin-right: -5px;}f-element input[type='checkbox'] { appearance: none; cursor: pointer;}f-element input[type='checkbox'].toggle { height: 20px; width: 45px; border-radius: 16px; display: inline-block; position: relative; margin: 0; margin-top: 2px; background: linear-gradient( 0deg, #292929 0%, #0a0a0ac2 100% ); transition: all 0.2s ease;}f-element input[type='checkbox'].toggle:after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: white; box-shadow: 0 1px 2px rgba(44, 44, 44, 0.2); transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);}f-element input[type='checkbox'].toggle:checked { background: linear-gradient( 0deg, #0177fb 0%, #0177fb 100% );}f-element input[type='checkbox'].toggle:checked:after { transform: translatex(25px);}f-element.auto-height { display: table;}f-element textarea { width: calc( 100% - 18px ); padding-top: 1px; padding-bottom: 3px; padding-left: 4px; padding-right: 8px; margin-top: 2px; margin-left: 2px; height: calc( 100% - 8px ); max-height: 300px; border-radius: 2px; resize: none; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%);}f-element.auto-height textarea { resize: auto;}f-element select { width: 100%; margin-top: 2px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; cursor: pointer; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%);}f-element f-toolbar { position: absolute; top: 0; height: 100%; align-content: space-around; margin-top: auto; margin-bottom: auto; margin-left: 6px; margin-right: 6px; font-size: 18px; line-height: 18px; display: inline-flex; justify-content: flex-end; left: 2px;}f-element f-toolbar button { opacity: .7; cursor: pointer; font-size: 14px; width: unset; height: unset; border-radius: unset; border: unset; outline: 0; background-color: unset; box-shadow: unset; padding-right: 0; padding-left: 0; margin-left: 0; margin-right: 0;}f-element f-toolbar button span { padding-right: 5px;}f-element f-toolbar button:hover,f-element f-toolbar button:active { opacity: 1; border: 0; background-color: unset;}f-element input.range-value { width: 60px; text-align: center;}f-menu.context button,f-element button { width: 100%; height: calc( 100% - 4px ); margin-left: 2px; margin-right: 2px; margin-top: 3px; border-radius: 3px; cursor: pointer;}f-element button { box-shadow: inset 1px 1px 1px 0 rgb(255 255 255 / 17%), inset -2px -2px 2px 0 rgb(0 0 0 / 26%);}f-element button:hover { color: #fff; background-color: #2a2a2a;}f-element button:active { border: 1px solid rgba( 0, 120, 255, 0.98 );}f-element f-inputs,f-element f-subinputs { display: flex; justify-content: flex-end; width: 100%;}f-element f-inputs { left: 100px; top: 50%; transform: translateY( -50% ); position: absolute; width: calc( 100% - 106px ); height: calc( 100% - 4px );}f-element.inputs-disable f-inputs { filter: grayscale(100%); opacity: .5;}f-element.inputs-disable f-inputs input { pointer-events: none;}f-element f-label,f-element span { margin: auto; text-shadow: 1px 1px 0px #0007;}f-element f-label { padding-left: 4px; white-space: nowrap; position: absolute; top: 50%; transform: translateY( -50% ); width: calc( 100% - 20px );}f-element.right f-label { text-align: right;}f-element.center f-label { text-align: center;}f-element f-label i { font-size: 18px; margin-right: 4px; vertical-align: sub; margin-right: 0;}f-element f-label.center { width: 100%; text-align: center; display: block;}f-element.title { height: 29px; background-color: #3a3a3ab0; background-color: #3b3b43ed; cursor: all-scroll; border-top-left-radius: 6px; border-top-right-radius: 6px;}f-element:last-child { border-bottom-left-radius: 6px; border-bottom-right-radius: 6px;}f-element.blue { background-color: #014fc5;}f-element.red { background-color: #bd0b0b;}f-element.green { background-color: #148d05;}f-element.yellow { background-color: #d6b100;}f-element.title.left { text-align: left; display: inline-grid; justify-content: start;}f-element.title f-title { text-align: center; font-size: 15px; position: absolute; top: 50%; transform: translateY( -50% ); width: calc( 100% - 14px );}f-element.title > i { font-size: 21px; position: absolute; right: 8px; top: 50%; transform: translateY( -50% ); opacity: .7;}f-element.title f-toolbar i { font-size: 22px; display: contents; right: unset; left: unset;}f-element.title.left span { text-align: left;}f-element f-io { border: 2px solid #dadada; width: 7px; height: 7px; position: absolute; background: #242427; border-radius: 8px; float: left; left: -7px; top: calc( 50% - 5px ); cursor: alias; box-shadow: 0 0 3px 2px #0000005e; z-index: 1;}f-element f-io.connect,f-canvas.dragging-rio f-element:hover f-io.lio,f-canvas.dragging-lio f-element:hover f-io.rio { zoom: 1.4;}f-node.io-connect f-io:not(.connect) { border: 2px solid #dadada !important; zoom: 1 !important;}f-element f-io.rio { float: right; right: -7px; left: unset;}f-element f-disconnect { position: absolute; left: -35px; top: 50%; font-size: 22px; transform: translateY( -50% ); filter: drop-shadow(0 0 5px #000); text-shadow: 0px 0px 5px black; cursor: pointer; transition: all .2s;}f-element.input-right f-disconnect { right: -35px; left: unset;}f-element f-disconnect:hover { color: #ff3300;}f-element textarea::-webkit-scrollbar { width: 6px;}f-element textarea::-webkit-scrollbar-track { background: #111; } f-element textarea::-webkit-scrollbar-thumb { background: #0177fb; }f-element textarea::-webkit-scrollbar-thumb:hover { background: #1187ff; }f-element.small { height: 18px;}f-element.large { height: 36px;}f-canvas.dragging-lio f-node:not(.io-connect) f-element.rio:hover,f-canvas.dragging-rio f-node:not(.io-connect) f-element.lio:hover,f-element.select { background-color: rgba(61, 70, 82, 0.98);}f-element.invalid > f-io { zoom: 1 !important;}f-element.invalid::after,.zoom f-element.no-zoom::after { font-size: 14px !important; display: flex; justify-content: center; align-items:center; margin: auto; position: absolute; width: 100%; height: 100%; background: #bd0b0b77; vertical-align: middle; color: #fff; content: 'Incompatible!'; opacity: .95; backdrop-filter: grayscale(100%); white-space: nowrap; overflow: hidden; left: 0; top: 0; text-transform: initial;}.zoom f-element.no-zoom::after { background: #0b3fbd77; content: 'Incompatible with zoom!';}f-treeview { width: 100%; background-color: #232324d1; border-radius: 2px; overflow-y: auto; overflow-x: hidden; margin-top: 2px; margin-left: 2px; height: calc( 100% - 6px ); box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%);}f-treeview f-treeview-node { position: relative; margin-top: 1px; min-height: 24px;}f-treeview f-treeview-node f-treeview-children { position: relative; display: none; padding-left: 16px;}f-treeview f-treeview-node input[type='checkbox'] { position: absolute; width: 100%; height: 24px; margin-top: 0px; background: none; box-shadow: none; cursor: default; width: calc( 100% + 100px ); padding-top: 3px; margin-left: -100px;}f-treeview f-treeview-node input[type='checkbox']:checked ~ f-treeview-children { display: block;}f-treeview f-arrow { border: solid #999; border-width: 0 2px 2px 0; display: inline-block; padding: 3px; position: absolute; right: 10px; margin-top: 8px; transform: rotate( -45deg ); transition: all 0.1s ease; pointer-events: none;}f-treeview f-treeview-node input[type='checkbox']:checked ~ f-arrow { margin-top: 7px; transform: rotate( 45deg );}f-treeview f-treeview-label { display: flex; align-content: center; width: 100%; height: 22px; background: none; box-shadow: none; cursor: default; width: calc( 100% + 100px ); padding-top: 3px; margin-left: -100px; padding-left: 105px; border-bottom: 1px solid #333; pointer-events: none; z-index: 1;}f-treeview f-treeview-node input[type='checkbox']:hover { background: #2c2c2f;}f-treeview f-treeview-node:has( f-arrow ) > input[type='checkbox'] { background: #2c2c2f;}f-treeview f-treeview-node:has( f-arrow ) > input[type='checkbox']:hover { background: #333339;}f-treeview f-treeview-label { color: #aaa;}f-treeview f-treeview-label spam { margin-top: 1px;}f-treeview f-treeview-label i { color: #ccc; transition: color 0.1s ease; margin-top: 1px;}f-treeview f-treeview-node { position: relative; display: flex; flex-direction: column;}f-treeview f-treeview-node input[type='checkbox']:hover ~ f-treeview-label { color: #eee;}f-treeview f-treeview-node input[type='checkbox']:hover ~ f-treeview-label i { color: #fff;}f-menu.context f-item f-node { position: relative; display: block; width: calc( 100% - 6px ) !important; margin: 3px; animation: unset;}f-treeview f-treeview-node.selected > input[type='checkbox'] { background-color: #014fc5;}f-treeview f-treeview-node.selected > f-treeview-label,f-treeview f-treeview-node.selected > f-treeview-label i { color: #fff;}f-treeview f-treeview-node.selected > input[type='checkbox']:hover { background-color: #06f;}f-string { display: contents;}f-string f-buttons { position: absolute; top: 50%; right: 1px; transform: translateY( -50% );}f-string f-buttons i { color: #999; padding-left: 4px; padding-right: 4px; padding-bottom: 1px; margin-right: 1px; cursor: pointer; background: #252526eb; height: 100%; padding-top: 1px; margin-right: 1px !important;}f-string i[type=icon] { color: #999; position: absolute; right: 8px; top: calc( 50% - 8px ); margin-right: 5px;}f-inputs f-string i[type=icon] { right: 0;}f-string f-buttons i:hover { color: #eeeeee;}f-string input:focus ~ f-string { opacity: .9;}f-string:hover input::placeholder { color: #999;}f-string f-treeview { position: absolute; max-height: 200px; height: 200px; background-color: #000; z-index: 10;}f-drop { width: 100%; height: 100%; position: sticky; left: 0; top: 0; background: #02358417; text-align: center; justify-content: center; align-items: center; display: flex; box-shadow: inset 0 0 20px 10px #464ace17; pointer-events: none; transition: all .07s; opacity: 0; visibility: hidden;}f-drop.visible { visibility: unset; opacity: unset; transition: all .23s;}f-drop span { opacity: .5; font-size: 40px; text-shadow: 0px 0px 5px #000; font-weight: bold;}f-tooltip { pointer-events: none;}f-tooltip { position: absolute; left: 0; top: 0; background: rgba(0,0,0,.8); backdrop-filter: blur(4px); font-size: 14px; padding: 7px; left: 50%; border-radius: 10px; transform: translateX(-50%); visibility: hidden; pointer-events: none; opacity: 0; transition: all 0.3s ease; z-index: 150; white-space: nowrap;}f-menu.context,f-menu.search { position: absolute;}f-menu.context { width: 170px; z-index: 110;}f-menu.search { bottom: 85px; left: 50%; transform: translateX(-50%); z-index: 10; width: 300px;}f-menu.context f-list { display: block; margin: 0; background: #171717e6; font-size: 12px; border-radius: 6px; backdrop-filter: blur(6px); border: 1px solid #7e7e7e45; box-shadow: 3px 3px 6px rgba(0,0,0,.2); transition: opacity 0.2s ease, transform 0.1s ease;}f-menu.search f-list { margin: 0 6px 0 6px; display: flex; flex-direction: column-reverse; margin-bottom: 5px;}f-menu.context.hidden { visibility: hidden; opacity: 0;}f-menu.context f-item,f-menu.search f-item { display: block; position: relative; margin: 0; padding: 0; white-space: nowrap;}f-menu.search f-item { opacity: 0;}f-menu.context f-item.submenu::after { content: ""; position: absolute; right: 6px; top: 50%; -webkit-transform: translateY( -50% ); transform: translateY( -50% ); border: 5px solid transparent; border-left-color: #808080;}f-menu.context f-item:hover > f-menu,f-menu.context f-item.active > f-menu { visibility: unset; transform: unset; opacity: unset;}f-menu.context f-menu { top: 0px; left: calc( 100% - 4px );}f-menu.context f-item button,f-menu.search f-item button { overflow: visible; display: block; width: calc( 100% - 6px ); text-align: left; cursor: pointer; white-space: nowrap; padding: 6px 8px; border-radius: 3px; background: rgba(45, 45, 48, 0.95); border: 0; color: #ddd; margin: 3px; text-shadow: 1px 1px 0px #0007;}f-menu.context f-item button i,f-menu.search f-item button i { float: left; font-size: 20px; margin-top: -1px; margin-right: 3px;}f-menu.context f-item button i { height: 18px; margin-top: -2px;}f-menu.context f-item button span,f-menu.search f-item button span { margin-left: 4px;}f-menu.context f-item:hover > button,f-menu.search f-item:hover > button,f-menu.search f-item.active > button { color: #fff; background-color: rgba(61, 70, 82, 0.98);}f-menu.search f-item:hover,f-menu.search f-item.active { opacity: 1 !important;}f-menu.context f-item button:active { outline: solid 1px rgba( 0, 80, 200, 0.98 );}f-menu.context f-item f-tooltip { margin-left: 85px; top: -50px;}f-menu.search f-item { display: none;}f-menu.search f-item:nth-child(1) { opacity: 1; display: unset;}f-menu.search f-item:nth-child(2) { opacity: .8; display: unset;}f-menu.search f-item:nth-child(3) { opacity: .6; display: unset;}f-menu.search f-item:nth-child(4) { opacity: .4; display: unset;}f-menu.search f-item button { border-radius: 14px;}f-tips { right: 10px; top: 10px; position: absolute; z-index: 100; pointer-events: none; display: flex; flex-direction: column;}f-tips f-tip { width: 450px; font-size: 13px; border-radius: 6px; text-align: center; display: block; height: auto; color: #ffffffe0; margin: 4px; padding: 4px; background: #17171794; border: 1px solid #7e7e7e38; line-height: 100%; backdrop-filter: blur(6px); transition: all 0.2s ease; text-transform: initial; opacity: 0;}f-tips f-tip:nth-child(1) { opacity: 1;}f-tips f-tip:nth-child(2) { opacity: .75;}f-tips f-tip:nth-child(3) { opacity: .25;}f-tips f-tip:nth-child(4) { opacity: .1;}f-tips f-tip.error { background: #b900005e;}f-menu.search input { width: calc( 100% - 28px ); height: 41px; position: absolute; z-index: 10; border-radius: 20px; padding-left: 14px; padding-right: 14px; font-size: 15px; background-color: #17171794; border: 1px solid #7e7e7e45; backdrop-filter: blur(6px); box-shadow: 3px 3px 6px rgb(0 0 0 / 20%); text-transform: initial;}f-menu.circle { position: absolute; z-index: 100;}f-menu.circle.top { top: 40px;}f-menu.circle.left { left: 40px;}f-menu.circle.bottom { bottom: 40px;}f-menu.circle.right { right: 40px;}f-menu.circle f-item { align-content: space-around; margin-right: 20px;}f-menu.circle f-item button { width: 46px; height: 46px; font-size: 22px; background: #17171794; border-radius: 50%; backdrop-filter: blur(6px); border: 1px solid #7e7e7e45; line-height: 100%; cursor: pointer; box-shadow: 3px 3px 6px rgba(0,0,0,.2); margin-bottom: 20px;}f-menu.circle f-item f-tooltip { margin-top: -60px;}f-menu.circle.top f-item f-tooltip { margin-top: 50px;}.f-rounded f-node f-element,.f-rounded f-node f-element.title.left { border-radius: 10px 5px 10px 5px;}.f-rounded f-node f-element input, .f-rounded f-node f-element select,.f-rounded f-node f-element button,.f-rounded f-node f-element textarea,.f-rounded f-node f-element input[type='checkbox'].toggle,.f-rounded f-node f-element input[type='checkbox'].toggle:after { border-radius: 20px 10px;}.f-rounded f-node f-element input { padding-left: 7px; padding-right: 7px;}.f-rounded f-menu.context,.f-rounded f-menu.context f-item button { border-radius: 20px 10px;}@media (hover: hover) and (pointer: fine) { f-node:not(.selected):hover { filter: drop-shadow(0 0 6px #66666630); } f-element f-toolbar { visibility: hidden; opacity: 0; transition: opacity 0.2s ease; } body:not(.connecting) f-node:hover > f-element f-toolbar, f-node.selected f-element f-toolbar { visibility: visible; opacity: 1; } f-element f-io:hover { zoom: 1.4; } f-menu.circle f-item button:hover { background-color: #2a2a2a; } f-menu.search input:hover, f-menu.search input:focus { background-color: #1a1a1a; filter: drop-shadow(0 0 6px #66666630); } f-menu.search input:focus { filter: drop-shadow(0 0 8px #4444dd); } f-menu.circle f-item button:hover > f-tooltip, f-menu.context f-item button:hover > f-tooltip { visibility: visible; opacity: 1; } f-menu.circle f-item button:hover > f-tooltip { margin-top: -50px; } f-menu.circle.top f-item button:hover > f-tooltip { margin-top: 60px; } f-menu.context f-item button:hover > f-tooltip { top: -30px; } f-menu.circle f-item button:focus > f-tooltip, f-menu.context f-item button:focus > f-tooltip { visibility: hidden; opacity: 0; }}@media (hover: none) and (pointer: coarse) { body.dragging f-canvas, body.connecting f-canvas { overflow: hidden !important; }}f-element.invalid > f-inputs,f-element.invalid > f-label,f-element.invalid > f-title,f-element.invalid > f-toolbar,f-element.invalid > input,f-element.invalid > select { opacity: .1 !important;}f-canvas { will-change: top, left;}f-node { will-change: transform !important;}` ); -const REVISION = '1'; - -const Styles = { - icons: { - close: '', - unlink: '' - } -}; +const REVISION = '3'; let _id = 0; @@ -73,6 +66,18 @@ class Serializer extends EventTarget { } + deserializeLib( /*data, lib*/ ) { + + // Abstract function. + + } + + get className() { + + return this.constructor.name; + + } + toJSON( data = null ) { let object = null; @@ -106,7 +111,7 @@ class Serializer extends EventTarget { } object.id = id; - object.type = this.constructor.name; + object.type = this.className; return object; @@ -116,12 +121,11 @@ class Serializer extends EventTarget { class PointerMonitor { - started = false; - constructor() { this.x = 0; this.y = 0; + this.started = false; this._onMoveEvent = ( e ) => { @@ -384,7 +388,7 @@ const addDOMClass = ( dom, classList ) => { }; -var Utils = /*#__PURE__*/Object.freeze( { +var Utils = /*#__PURE__*/Object.freeze({ __proto__: null, pointer: pointer, draggableDOM: draggableDOM, @@ -394,7 +398,7 @@ var Utils = /*#__PURE__*/Object.freeze( { rgbaToArray: rgbaToArray, removeDOMClass: removeDOMClass, addDOMClass: addDOMClass -} ); +}); class Link { @@ -446,6 +450,8 @@ class Element extends Serializer { super(); + this.isElement = true; + const dom = document.createElement( 'f-element' ); dom.element = this; @@ -853,7 +859,7 @@ class Element extends Serializer { getHeight() { - return this.dom.style.height; + return parseInt( this.dom.style.height ); } @@ -884,7 +890,7 @@ class Element extends Serializer { if ( this.disconnectDOM === null ) { this.disconnectDOM = document.createElement( 'f-disconnect' ); - this.disconnectDOM.innerHTML = Styles.icons.unlink ? `` : '✖'; + this.disconnectDOM.innerHTML = Element.icons.unlink ? `` : '✖'; this.dom.append( this.disconnectDOM ); @@ -953,16 +959,38 @@ class Element extends Serializer { } - serialize( data ) { + getInputByProperty( property ) { + + for ( const input of this.inputs ) { - const height = this.getHeight(); + if ( input.getProperty() === property ) { + + return input; + + } + + } + + } + + serialize( data ) { const inputs = []; + const properties = []; const links = []; for ( const input of this.inputs ) { - inputs.push( input.toJSON( data ).id ); + const id = input.toJSON( data ).id; + const property = input.getProperty(); + + inputs.push( id ); + + if ( property !== null ) { + + properties.push( { property, id } ); + + } } @@ -980,6 +1008,7 @@ class Element extends Serializer { if ( this.outputLength > 0 ) data.outputLength = this.outputLength; if ( inputs.length > 0 ) data.inputs = inputs; + if ( properties.length > 0 ) data.properties = properties; if ( links.length > 0 ) data.links = links; if ( this.style !== '' ) { @@ -988,11 +1017,7 @@ class Element extends Serializer { } - if ( height !== '' ) { - - data.height = height; - - } + data.height = this.getHeight(); } @@ -1001,7 +1026,15 @@ class Element extends Serializer { if ( data.inputLength !== undefined ) this.setInput( data.inputLength ); if ( data.outputLength !== undefined ) this.setOutput( data.outputLength ); - if ( data.inputs !== undefined ) { + if ( data.properties !== undefined ) { + + for ( const { id, property } of data.properties ) { + + data.objects[ id ] = this.getInputByProperty( property ); + + } + + } else if ( data.inputs !== undefined ) { const inputs = this.inputs; @@ -1193,7 +1226,7 @@ class Element extends Serializer { } -Element.prototype.isElement = true; +Element.icons = { unlink: '' }; class Input extends Serializer { @@ -1209,6 +1242,8 @@ class Input extends Serializer { this.tagColor = null; + this.property = null; + this.events = { 'change': [], 'click': [] @@ -1242,6 +1277,20 @@ class Input extends Serializer { } + setProperty( name ) { + + this.property = name; + + return this; + + } + + getProperty() { + + return this.property; + + } + setTagColor( color ) { this.tagColor = color; @@ -1287,7 +1336,7 @@ class Input extends Serializer { setReadOnly( value ) { - this.dom.readOnly = value; + this.getInput().readOnly = value; return this; @@ -1295,13 +1344,13 @@ class Input extends Serializer { getReadOnly() { - return this.dom.readOnly; + return this.getInput().readOnly; } setValue( value, dispatch = true ) { - this.dom.value = value; + this.getInput().value = value; if ( dispatch ) this.dispatchEvent( new Event( 'change' ) ); @@ -1311,7 +1360,13 @@ class Input extends Serializer { getValue() { - return this.dom.value; + return this.getInput().value; + + } + + getInput() { + + return this.dom; } @@ -1391,6 +1446,8 @@ class Node extends Serializer { this.style = ''; this.canvas = null; + this.resizable = false; + this.serializePriority = 0; this.elements = []; @@ -1409,6 +1466,53 @@ class Node extends Serializer { } + setAlign( align ) { + + const dom = this.dom; + const style = dom.style; + + style.left = ''; + style.top = ''; + style.animation = 'none'; + + if ( typeof align === 'string' ) { + + dom.classList.add( align ); + + } else if ( align ) { + + for ( const name in align ) { + + style[ name ] = align[ name ]; + + } + + } + + return this; + + } + + setResizable( val ) { + + this.resizable = val === true; + + if ( this.resizable ) { + + this.dom.classList.add( 'resizable' ); + + } else { + + this.dom.classList.remove( 'resizable' ); + + } + + this.updateSize(); + + return this; + + } + onFocus( callback ) { this.events.focus.push( callback ); @@ -1465,6 +1569,8 @@ class Node extends Serializer { this.dom.style.width = numberToPX( val ); + this.updateSize(); + return this; } @@ -1484,8 +1590,7 @@ class Node extends Serializer { getBound() { const { x, y } = this.getPosition(); - const width = this.getWidth(); - const height = this.getHeight(); + const { width, height } = this.dom.getBoundingClientRect(); return { x, y, width, height }; @@ -1501,6 +1606,8 @@ class Node extends Serializer { this.dom.append( element.dom ); + this.updateSize(); + return this; } @@ -1515,6 +1622,8 @@ class Node extends Serializer { this.dom.removeChild( element.dom ); + this.updateSize(); + return this; } @@ -1571,7 +1680,29 @@ class Node extends Serializer { getColor() { - return ( this.elements[ 0 ] ) ? this.elements[ 0 ].getColor() : undefined; + return this.elements.length > 0 ? this.elements[ 0 ].getColor() : null; + + } + + updateSize() { + + for ( const element of this.elements ) { + + element.dom.style.width = ''; + + } + + if ( this.resizable === true ) { + + const element = this.elements[ this.elements.length - 1 ]; + + if ( element !== undefined ) { + + element.dom.style.width = this.dom.style.width; + + } + + } } @@ -1591,6 +1722,7 @@ class Node extends Serializer { data.y = y; data.width = this.getWidth(); data.elements = elements; + data.autoResize = this.resizable; if ( this.style !== '' ) { @@ -1604,6 +1736,7 @@ class Node extends Serializer { this.setPosition( data.x, data.y ); this.setWidth( data.width ); + this.setResizable( data.autoResize ); if ( data.style !== undefined ) { @@ -1676,7 +1809,7 @@ class TitleElement extends DraggableElement { const { dom } = this; - dom.className = 'title'; + dom.classList.add( 'title' ); const dbClick = () => { @@ -1912,8 +2045,26 @@ class Canvas extends Serializer { }; + const classInElements = ( element, className ) => { + + do { + + if ( element.classList ? element.classList.contains( className ) : false ) { + + return true; + + } + + } while ( ( element = element.parentElement ) && element !== dom ); + + return false; + + }; + const onMouseZoom = ( e ) => { + if ( classInElements( e.srcElement, 'f-scroll' ) ) return; + e.preventDefault(); e.stopImmediatePropagation(); @@ -2209,6 +2360,10 @@ class Canvas extends Serializer { this._zoom = val; this.contentDOM.style.zoom = val; + val === 1 ? this.dom.classList.remove( 'zoom' ) : this.dom.classList.add( 'zoom' ); + + this.updateMozTransform(); + } set scrollLeft( val ) { @@ -2216,6 +2371,8 @@ class Canvas extends Serializer { this._scrollLeft = val; this.contentDOM.style.left = numberToPX( val ); + this.updateMozTransform(); + } get scrollLeft() { @@ -2229,6 +2386,8 @@ class Canvas extends Serializer { this._scrollTop = val; this.contentDOM.style.top = numberToPX( val ); + this.updateMozTransform(); + } get scrollTop() { @@ -2263,6 +2422,21 @@ class Canvas extends Serializer { } + get useTransform() { + + return navigator.userAgent.match( /firefox/i ) !== null; + + } + + updateMozTransform() { + + if ( this.useTransform === false ) return; + + this.contentDOM.style[ '-moz-transform' ] = 'scale(' + this.zoom + ')'; + this.contentDOM.style[ '-moz-transform-origin' ] = '-' + this.contentDOM.style.left + ' -' + this.contentDOM.style.top; + + } + onDrop( callback ) { this.events.drop.push( callback ); @@ -2539,7 +2713,7 @@ class Canvas extends Serializer { updateLines() { - const { dom, zoom, canvas, frontCanvas, frontContext, context, _width, _height } = this; + const { dom, zoom, canvas, frontCanvas, frontContext, context, _width, _height, useTransform } = this; const domRect = this.rect; @@ -2586,6 +2760,13 @@ class Canvas extends Serializer { aPos.x = rect.x + rect.width; aPos.y = rect.y + ( rect.height / 2 ); + if ( useTransform ) { + + aPos.x /= zoom; + aPos.y /= zoom; + + } + } else { aPos.x = this.clientX; @@ -2604,6 +2785,13 @@ class Canvas extends Serializer { bPos.x = rect.x; bPos.y = rect.y + ( rect.height / 2 ); + if ( useTransform ) { + + bPos.x /= zoom; + bPos.y /= zoom; + + } + } else { bPos.x = this.clientX; @@ -2705,7 +2893,6 @@ class Canvas extends Serializer { } - update() { if ( this.updating === false ) return; @@ -2720,8 +2907,9 @@ class Canvas extends Serializer { serialize( data ) { const nodes = []; + const serializeNodes = this.nodes.sort( ( a, b ) => a.serializePriority > b.serializePriority ? - 1 : 1 ); - for ( const node of this.nodes ) { + for ( const node of serializeNodes ) { nodes.push( node.toJSON( data ).id ); @@ -2743,580 +2931,711 @@ class Canvas extends Serializer { } -class ButtonInput extends Input { - - constructor( innterText = '' ) { - - const dom = document.createElement( 'button' ); - - const spanDOM = document.createElement( 'span' ); - dom.append( spanDOM ); - - const iconDOM = document.createElement( 'i' ); - dom.append( iconDOM ); +class Menu extends EventTarget { - super( dom ); + constructor( className ) { - this.spanDOM = spanDOM; - this.iconDOM = iconDOM; + super(); - spanDOM.innerText = innterText; + const dom = document.createElement( 'f-menu' ); + dom.className = className + ' bottom left hidden'; - dom.onmouseover = () => { + const listDOM = document.createElement( 'f-list' ); - this.dispatchEvent( new Event( 'mouseover' ) ); + dom.append( listDOM ); - }; + this.dom = dom; + this.listDOM = listDOM; - dom.onclick = dom.ontouchstart = ( e ) => { + this.visible = false; - e.preventDefault(); + this.align = 'bottom left'; - e.stopPropagation(); + this.subMenus = new WeakMap(); + this.domButtons = new WeakMap(); - this.dispatchEvent( new Event( 'click' ) ); + this.buttons = []; - }; + this.events = {}; } - setIcon( className ) { + onContext( callback ) { - this.iconDOM.className = className; + this.events.context.push( callback ); return this; } - setValue( val ) { + setAlign( align ) { - this.spanDOM.innerText = val; + const dom = this.dom; + + removeDOMClass( dom, this.align ); + addDOMClass( dom, align ); + + this.align = align; return this; } - getValue() { + getAlign() { - return this.spanDOM.innerText; + return this.align; } -} + show() { -class ObjectNode extends Node { + this.dom.classList.remove( 'hidden' ); - constructor( name, inputLength, callback = null, width = 300 ) { + this.visible = true; - super(); + this.dispatchEvent( new Event( 'show' ) ); - this.setWidth( width ); + return this; - const title = new TitleElement( name ) - .setObjectCallback( callback ) - .setSerializable( false ) - .setOutput( inputLength ); + } - const closeButton = new ButtonInput( Styles.icons.close || '✕' ).onClick( () => { + hide() { - this.dispose(); + this.dom.classList.add( 'hidden' ); - } ).setIcon( Styles.icons.close ); + this.dispatchEvent( new Event( 'hide' ) ); - title.addButton( closeButton ); + this.visible = false; - this.add( title ); + } - this.title = title; - this.closeButton = closeButton; + add( button, submenu = null ) { - } + const liDOM = document.createElement( 'f-item' ); - setName( value ) { + if ( submenu !== null ) { - this.title.setTitle( value ); + liDOM.classList.add( 'submenu' ); - return this; + liDOM.append( submenu.dom ); - } + this.subMenus.set( button, submenu ); - getName() { + button.dom.addEventListener( 'mouseover', () => submenu.show() ); + button.dom.addEventListener( 'mouseout', () => submenu.hide() ); - return this.title.getTitle(); + } - } + liDOM.append( button.dom ); - setObjectCallback( callback ) { + this.buttons.push( button ); + + this.listDOM.append( liDOM ); - this.title.setObjectCallback( callback ); + this.domButtons.set( button, liDOM ); return this; } - getObject( callback ) { + clear() { - return this.title.getObject( callback ); + this.buttons = []; - } + this.subMenus = new WeakMap(); + this.domButtons = new WeakMap(); - setColor( color ) { + while ( this.listDOM.firstChild ) { - return this.title.setColor( color ); + this.listDOM.firstChild.remove(); + + } } - setOutputColor( color ) { +} - return this.title.setOutputColor( color ); +let lastContext = null; - } +const onCloseLastContext = ( e ) => { - invalidate() { + if ( lastContext && lastContext.visible === true && e.target.closest( 'f-menu.context' ) === null ) { - this.title.dispatchEvent( new Event( 'connect' ) ); + lastContext.hide(); } -} +}; -const ENTER_KEY$2 = 13; +document.body.addEventListener( 'mousedown', onCloseLastContext, true ); +document.body.addEventListener( 'touchstart', onCloseLastContext, true ); -class StringInput extends Input { +class ContextMenu extends Menu { - constructor( value = '' ) { + constructor( target = null ) { - const dom = document.createElement( 'input' ); - super( dom ); + super( 'context' ); - dom.type = 'text'; - dom.value = value; - dom.spellcheck = false; - dom.autocomplete = 'off'; + this.events.context = []; - dom.onblur = () => { + this._lastButtonClick = null; - this.dispatchEvent( new Event( 'blur' ) ); + this._onButtonClick = ( e = null ) => { - }; + const button = e ? e.target : null; - dom.onchange = () => { + if ( this._lastButtonClick ) { - this.dispatchEvent( new Event( 'change' ) ); + this._lastButtonClick.dom.parentElement.classList.remove( 'active' ); - }; + } - dom.onkeyup = ( e ) => { + this._lastButtonClick = button; - if ( e.keyCode === ENTER_KEY$2 ) { + if ( button ) { - e.target.blur(); + if ( this.subMenus.has( button ) ) { + + this.subMenus.get( button )._onButtonClick(); + + } + + button.dom.parentElement.classList.add( 'active' ); } - e.stopPropagation(); + }; - this.dispatchEvent( new Event( 'change' ) ); + this._onButtonMouseOver = ( e ) => { + + const button = e.target; + + if ( this.subMenus.has( button ) && this._lastButtonClick !== button ) { + + this._onButtonClick(); + + } }; + this.addEventListener( 'context', ( ) => { + + dispatchEventList( this.events.context, this ); + + } ); + + this.setTarget( target ); + } -} + openFrom( dom ) { -const ENTER_KEY$1 = 13; + const rect = dom.getBoundingClientRect(); -class NumberInput extends Input { + return this.open( rect.x + ( rect.width / 2 ), rect.y + ( rect.height / 2 ) ); - constructor( value = 0, min = - Infinity, max = Infinity, step = .01 ) { + } - const dom = document.createElement( 'input' ); - super( dom ); + open( x = pointer.x, y = pointer.y ) { - this.min = min; - this.max = max; - this.step = step; + if ( lastContext !== null ) { - this.integer = false; + lastContext.hide(); - dom.type = 'text'; - dom.className = 'number'; - dom.value = this._getString( value ); - dom.spellcheck = false; - dom.autocomplete = 'off'; + } - dom.ondragstart = dom.oncontextmenu = ( e ) => { + lastContext = this; - e.preventDefault(); + this.setPosition( x, y ); - e.stopPropagation(); + document.body.append( this.dom ); - }; + return this.show(); - dom.onfocus = dom.onclick = () => { + } - dom.select(); + setWidth( width ) { - }; + this.dom.style.width = numberToPX( width ); - dom.onblur = () => { + return this; - this.dom.value = this._getString( this.dom.value ); + } - this.dispatchEvent( new Event( 'blur' ) ); + setPosition( x, y ) { - }; + const dom = this.dom; - dom.onchange = () => { + dom.style.left = numberToPX( x ); + dom.style.top = numberToPX( y ); - this.dispatchEvent( new Event( 'change' ) ); + return this; - }; + } - dom.onkeydown = ( e ) => { + setTarget( target = null ) { - if ( e.key.length === 1 && /\d|\./.test( e.key ) !== true ) { + if ( target !== null ) { - return false; + const onContextMenu = ( e ) => { - } + e.preventDefault(); - if ( e.keyCode === ENTER_KEY$1 ) { + if ( e.pointerType !== 'mouse' || ( e.pageX === 0 && e.pageY === 0 ) ) return; - e.target.blur(); + this.dispatchEvent( new Event( 'context' ) ); - } + this.open(); - e.stopPropagation(); + }; - }; + this.target = target; - draggableDOM( dom, ( data ) => { + target.addEventListener( 'contextmenu', onContextMenu, false ); - const { delta } = data; + } - if ( dom.readOnly === true ) return; + return this; - if ( data.value === undefined ) { + } - data.value = this.getValue(); + show() { - } + if ( ! this.opened ) { - const diff = delta.x - delta.y; + this.dom.style.left = ''; + this.dom.style.transform = ''; - const value = data.value + ( diff * this.step ); + } - dom.value = this._getString( value.toFixed( this.precision ) ); + const domRect = this.dom.getBoundingClientRect(); - this.dispatchEvent( new Event( 'change' ) ); + let offsetX = Math.min( window.innerWidth - ( domRect.x + domRect.width + 10 ), 0 ); + let offsetY = Math.min( window.innerHeight - ( domRect.y + domRect.height + 10 ), 0 ); - } ); + if ( this.opened ) { - } + if ( offsetX < 0 ) offsetX = - domRect.width; + if ( offsetY < 0 ) offsetY = - domRect.height; - setStep( step ) { + this.setPosition( domRect.x + offsetX, domRect.y + offsetY ); - this.step = step; + } else { - return this; + // flip submenus + + if ( offsetX < 0 ) this.dom.style.left = '-100%'; + if ( offsetY < 0 ) this.dom.style.transform = 'translateY( calc( 32px - 100% ) )'; + + } + + return super.show(); } - setRange( min, max, step ) { + hide() { - this.min = min; - this.max = max; - this.step = step; + if ( this.opened ) { - this.dispatchEvent( new Event( 'range' ) ); + lastContext = null; - return this.setValue( this.getValue() ); + } - } + return super.hide(); - get precision() { + } - if ( this.integer === true ) return 0; + add( button, submenu = null ) { - const fract = this.step % 1; + button.addEventListener( 'click', this._onButtonClick ); + button.addEventListener( 'mouseover', this._onButtonMouseOver ); - return fract !== 0 ? fract.toString().split( '.' )[ 1 ].length : 1; + return super.add( button, submenu ); } - setValue( val, dispatch = true ) { + get opened() { - return super.setValue( this._getString( val ), dispatch ); + return lastContext === this; } - getValue() { +} - return Number( this.dom.value ); +class CircleMenu extends Menu { + + constructor() { + + super( 'circle' ); } - serialize( data ) { +} - const { min, max } = this; +class Tips extends EventTarget { - if ( min !== - Infinity && max !== Infinity ) { + constructor() { - data.min = this.min; - data.max = this.max; - data.step = this.step; + super(); - } + const dom = document.createElement( 'f-tips' ); - super.serialize( data ); + this.dom = dom; - } + this.time = 0; + this.duration = 3000; - deserialize( data ) { + } - if ( data.min !== undefined ) { + message( str ) { - const { min, max, step } = this; + return this.tip( str ); - this.setRange( min, max, step ); + } - } + error( str ) { - super.deserialize( data ); + return this.tip( str, 'error' ); } - _getString( value ) { + tip( html, className = '' ) { - const num = Math.min( Math.max( Number( value ), this.min ), this.max ); + const dom = document.createElement( 'f-tip' ); + dom.className = className; + dom.innerHTML = html; - if ( this.integer === true ) { + this.dom.prepend( dom ); - return Math.floor( num ); + //requestAnimationFrame( () => dom.style.opacity = 1 ); - } else { + this.time = Math.min( this.time + this.duration, this.duration ); - return num + ( num % 1 ? '' : '.0' ); + setTimeout( () => { - } + this.time = Math.max( this.time - this.duration, 0 ); + + dom.style.opacity = 0; + + setTimeout( () => dom.remove(), 250 ); + + }, this.time ); + + return this; } } -const getStep = ( min, max ) => { - - const sensibility = .001; +const filterString = ( str ) => { - return ( max - min ) * sensibility; + return str.trim().toLowerCase().replace( /\s\s+/g, ' ' ); }; -class SliderInput extends Input { +class Search extends Menu { - constructor( value = 0, min = 0, max = 100 ) { + constructor() { - const dom = document.createElement( 'f-subinputs' ); - super( dom ); + super( 'search' ); - value = Math.min( Math.max( value, min ), max ); + this.events.submit = []; + this.events.filter = []; - const step = getStep( min, max ); + this.tags = new WeakMap(); - const rangeDOM = document.createElement( 'input' ); - rangeDOM.type = 'range'; - rangeDOM.min = min; - rangeDOM.max = max; - rangeDOM.step = step; - rangeDOM.value = value; + const inputDOM = document.createElement( 'input' ); + inputDOM.placeholder = 'Type here'; - const field = new NumberInput( value, min, max, step ); - field.dom.className = 'range-value'; - field.onChange( () => { + let filter = true; + let filterNeedUpdate = true; - rangeDOM.value = field.getValue(); + inputDOM.addEventListener( 'focusout', () => { - this.dispatchEvent( new Event( 'change' ) ); + filterNeedUpdate = true; + + this.setValue( '' ); } ); - field.addEventListener( 'range', () => { + inputDOM.onkeydown = ( e ) => { - rangeDOM.min = field.min; - rangeDOM.max = field.max; - rangeDOM.step = field.step; - rangeDOM.value = field.getValue(); + const key = e.key; + + if ( key === 'ArrowUp' ) { + + const index = this.filteredIndex; + + if ( this.forceAutoComplete ) { + + this.filteredIndex = index !== null ? ( index + 1 ) % ( this.filtered.length || 1 ) : 0; + + } else { + + this.filteredIndex = index !== null ? Math.min( index + 1, this.filtered.length - 1 ) : 0; + + } + + e.preventDefault(); + + filter = false; + + } else if ( key === 'ArrowDown' ) { + + const index = this.filteredIndex; + + if ( this.forceAutoComplete ) { + + this.filteredIndex = index - 1; + + if ( this.filteredIndex === null ) this.filteredIndex = this.filtered.length - 1; + + } else { + + this.filteredIndex = index !== null ? index - 1 : null; + + } + + e.preventDefault(); + + filter = false; + + } else if ( key === 'Enter' ) { + + this.value = this.currentFiltered ? this.currentFiltered.button.getValue() : inputDOM.value; + + this.submit(); + + e.preventDefault(); + + filter = false; + + } else { + + filter = true; + + } + + }; + + inputDOM.onkeyup = () => { + + if ( filter ) { + + if ( filterNeedUpdate ) { + + this.dispatchEvent( new Event( 'filter' ) ); + + filterNeedUpdate = false; + + } + + this.filter( inputDOM.value ); + + } + + }; + + this.filtered = []; + this.currentFiltered = null; + + this.value = ''; + + this.forceAutoComplete = false; + + this.dom.append( inputDOM ); + + this.inputDOM = inputDOM; + + this.addEventListener( 'filter', ( ) => { + + dispatchEventList( this.events.filter, this ); } ); - dom.append( rangeDOM ); - dom.append( field.dom ); + this.addEventListener( 'submit', ( ) => { - this.rangeDOM = rangeDOM; - this.field = field; + dispatchEventList( this.events.submit, this ); - const updateRangeValue = () => { + } ); - let value = Number( rangeDOM.value ); + } - if ( value !== this.max && value + this.step >= this.max ) { + submit() { - // fix not end range fraction + this.dispatchEvent( new Event( 'submit' ) ); - rangeDOM.value = value = this.max; + return this.setValue( '' ); + + } - } + setValue( value ) { - this.field.setValue( value ); + this.inputDOM.value = value; - }; + this.filter( value ); - draggableDOM( rangeDOM, () => { + return this; - updateRangeValue(); + } - this.dispatchEvent( new Event( 'change' ) ); + getValue() { - }, { className: '' } ); + return this.value; } - get min() { + onFilter( callback ) { - return this.field.min; + this.events.filter.push( callback ); + + return this; } - get max() { + onSubmit( callback ) { - return this.field.max; + this.events.submit.push( callback ); + + return this; } - get step() { + getFilterByButton( button ) { - return this.field.step; + for ( const filter of this.filtered ) { - } + if ( filter.button === button ) { - setRange( min, max ) { + return filter; - this.field.setRange( min, max, getStep( min, max ) ); + } - this.dispatchEvent( new Event( 'range' ) ); - this.dispatchEvent( new Event( 'change' ) ); + } - return this; + return null; } - setValue( val, dispatch = true ) { - - this.field.setValue( val ); - this.rangeDOM.value = val; + add( button ) { - if ( dispatch ) this.dispatchEvent( new Event( 'change' ) ); + super.add( button ); - return this; + const onDown = () => { - } + const filter = this.getFilterByButton( button ); - getValue() { + this.filteredIndex = this.filtered.indexOf( filter ); + this.value = button.getValue(); - return this.field.getValue(); + this.submit(); - } + }; - serialize( data ) { + button.dom.addEventListener( 'mousedown', onDown ); + button.dom.addEventListener( 'touchstart', onDown ); - data.min = this.min; - data.max = this.max; + this.domButtons.get( button ).remove(); - super.serialize( data ); + return this; } - deserialize( data ) { + set filteredIndex( index ) { - const { min, max } = data; + if ( this.currentFiltered ) { - this.setRange( min, max ); + const buttonDOM = this.domButtons.get( this.currentFiltered.button ); - super.deserialize( data ); + buttonDOM.classList.remove( 'active' ); - } + this.currentFiltered = null; -} + } -class ColorInput extends Input { + const filteredItem = this.filtered[ index ]; - constructor( value = 0x0099ff ) { + if ( filteredItem ) { - const dom = document.createElement( 'input' ); - super( dom ); + const buttonDOM = this.domButtons.get( filteredItem.button ); - dom.type = 'color'; - dom.value = numberToHex( value ); + buttonDOM.classList.add( 'active' ); - dom.oninput = () => { + this.currentFiltered = filteredItem; - this.dispatchEvent( new Event( 'change' ) ); + } - }; + this.updateFilter(); } - setValue( value, dispatch = true ) { + get filteredIndex() { - return super.setValue( numberToHex( value ), dispatch ); + return this.currentFiltered ? this.filtered.indexOf( this.currentFiltered ) : null; } - getValue() { + setTag( button, tags ) { - return parseInt( super.getValue().substr( 1 ), 16 ); + this.tags.set( button, tags ); } -} + filter( text ) { -const ENTER_KEY = 13; + text = filterString( text ); -class TextInput extends Input { + const tags = this.tags; + const filtered = []; - constructor( innerText = '' ) { + for ( const button of this.buttons ) { - const dom = document.createElement( 'textarea' ); - super( dom ); + const buttonDOM = this.domButtons.get( button ); - dom.innerText = innerText; + buttonDOM.remove(); - dom.onblur = () => { + const buttonTags = tags.has( button ) ? ' ' + tags.get( button ) : ''; - this.dispatchEvent( new Event( 'blur' ) ); + const label = filterString( button.getValue() + buttonTags ); - }; + if ( text && label.includes( text ) === true ) { - dom.onchange = () => { + const score = text.length / label.length; - this.dispatchEvent( new Event( 'change' ) ); + filtered.push( { + button, + score + } ); - }; + } - dom.onkeyup = ( e ) => { + } - if ( e.keyCode === ENTER_KEY ) { + filtered.sort( ( a, b ) => b.score - a.score ); - e.target.blur(); + this.filtered = filtered; + this.filteredIndex = this.forceAutoComplete ? 0 : null; - } + } - e.stopPropagation(); + updateFilter() { - this.dispatchEvent( new Event( 'change' ) ); + const filteredIndex = Math.min( this.filteredIndex, this.filteredIndex - 3 ); - }; + for ( let i = 0; i < this.filtered.length; i ++ ) { + + const button = this.filtered[ i ].button; + const buttonDOM = this.domButtons.get( button ); + + buttonDOM.remove(); + + if ( i >= filteredIndex ) { + + this.listDOM.append( buttonDOM ); + + } + + } } @@ -3362,7 +3681,7 @@ class LabelElement extends Element { getIcon() { - return this.iconDOM ? this.iconDOM.className : undefined; + return this.iconDOM ? this.iconDOM.className : null; } @@ -3425,966 +3744,966 @@ class LabelElement extends Element { } -class PanelNode extends Node { - - constructor( title = 'Panel', align = 'top-right' ) { - - super(); - - const titleElement = new TitleElement( title ); - this.add( titleElement ); - - const collapseButton = new ButtonInput( '🗕' ); - collapseButton.onClick( () => { - - this.setCollapse( ! this.collapsed ); - - } ); - - titleElement.addButton( collapseButton ); - - this.collapseButton = collapseButton; - this.titleElement = titleElement; - this.align = align; - this.collapsed = false; - - this.setAlign( align ); - this.setStyle( 'rouded' ); - - } - - setCollapse( value ) { - - const cssClass = 'closed'; - - this.dom.classList.remove( cssClass ); - - this.collapsed = value; - - this.collapseButton.value = value ? '🗖' : '🗕'; - - if ( value === true ) { - - this.dom.classList.add( cssClass ); - - } - - return this; - - } - - setAlign( align ) { - - if ( this.align ) this.dom.classList.remove( this.align ); - this.dom.classList.add( align ); - - this.align = align; - - return this; - - } - - addInput( inputClass, object, property, ...params ) { - - const value = object[ property ]; - - const input = new inputClass( value, ...params ); - input.onChange( () => { - - object[ property ] = input.value; - - } ); - - this.add( new LabelElement( property ).add( input ) ); - - return input; - - } - - addSlider( object, property, min, max ) { - - return this.addInput( SliderInput, object, property, min, max ); - - } - - addNumber( object, property ) { - - return this.addInput( NumberInput, object, property ); - - } - - addColor( object, property ) { - - return this.addInput( ColorInput, object, property ); - - } - - addString( object, property ) { - - return this.addInput( StringInput, object, property ); - - } - - addText( object, property ) { - - const input = this.addInput( TextInput, object, property ); - input.element.setHeight( 70 ); - - return input; - - } - - addButton( name ) { - - const input = new ButtonInput( name ); - - this.add( new Element().setHeight( 34 ).add( input ) ); +class ButtonInput extends Input { - return input; + constructor( innterText = '' ) { - } + const dom = document.createElement( 'button' ); -} + const spanDOM = document.createElement( 'span' ); + dom.append( spanDOM ); -class Menu extends EventTarget { + const iconDOM = document.createElement( 'i' ); + dom.append( iconDOM ); - constructor( className ) { + super( dom ); - super(); + this.spanDOM = spanDOM; + this.iconDOM = iconDOM; - const dom = document.createElement( 'f-menu' ); - dom.className = className + ' bottom left hidden'; + spanDOM.innerText = innterText; - const listDOM = document.createElement( 'f-list' ); + dom.onmouseover = () => { - dom.append( listDOM ); + this.dispatchEvent( new Event( 'mouseover' ) ); - this.dom = dom; - this.listDOM = listDOM; + }; - this.visible = false; + dom.onclick = dom.ontouchstart = + iconDOM.onclick = iconDOM.ontouchstart = ( e ) => { - this.align = 'bottom left'; + e.preventDefault(); - this.subMenus = new WeakMap(); - this.domButtons = new WeakMap(); + e.stopPropagation(); - this.buttons = []; + this.dispatchEvent( new Event( 'click' ) ); - this.events = {}; + }; } - onContext( callback ) { + setIcon( className ) { - this.events.context.push( callback ); + this.iconDOM.className = className; return this; } - setAlign( align ) { + getIcon() { - const dom = this.dom; + return this.iconDOM.className; - removeDOMClass( dom, this.align ); - addDOMClass( dom, align ); + } - this.align = align; + setValue( val ) { + + this.spanDOM.innerText = val; return this; } - getAlign() { + getValue() { - return this.align; + return this.spanDOM.innerText; } - show() { +} - this.dom.classList.remove( 'hidden' ); +class ColorInput extends Input { - this.visible = true; + constructor( value = 0x0099ff ) { - this.dispatchEvent( new Event( 'show' ) ); + const dom = document.createElement( 'input' ); + super( dom ); - return this; + dom.type = 'color'; + dom.value = numberToHex( value ); - } + dom.oninput = () => { - hide() { + this.dispatchEvent( new Event( 'change' ) ); - this.dom.classList.add( 'hidden' ); + }; - this.dispatchEvent( new Event( 'hide' ) ); + } - this.visible = false; + setValue( value, dispatch = true ) { + + return super.setValue( numberToHex( value ), dispatch ); } - add( button, submenu = null ) { + getValue() { - const liDOM = document.createElement( 'f-item' ); + return parseInt( super.getValue().substr( 1 ), 16 ); - if ( submenu !== null ) { + } - liDOM.classList.add( 'submenu' ); +} - liDOM.append( submenu.dom ); +class NumberInput extends Input { - this.subMenus.set( button, submenu ); + constructor( value = 0, min = - Infinity, max = Infinity, step = .01 ) { - button.dom.addEventListener( 'mouseover', () => submenu.show() ); - button.dom.addEventListener( 'mouseout', () => submenu.hide() ); + const dom = document.createElement( 'input' ); + super( dom ); - } + this.min = min; + this.max = max; + this.step = step; - liDOM.append( button.dom ); + this.integer = false; - this.buttons.push( button ); + dom.type = 'text'; + dom.className = 'number'; + dom.value = this._getString( value ); + dom.spellcheck = false; + dom.autocomplete = 'off'; - this.listDOM.append( liDOM ); + dom.ondragstart = dom.oncontextmenu = ( e ) => { - this.domButtons.set( button, liDOM ); + e.preventDefault(); - return this; + e.stopPropagation(); - } + }; - clear() { + dom.onfocus = dom.onclick = () => { - this.buttons = []; + dom.select(); - this.subMenus = new WeakMap(); - this.domButtons = new WeakMap(); + }; - while ( this.listDOM.firstChild ) { + dom.onblur = () => { - this.listDOM.firstChild.remove(); + this.dom.value = this._getString( this.dom.value ); - } + this.dispatchEvent( new Event( 'blur' ) ); - } + }; -} + dom.onchange = () => { -let lastContext = null; + this.dispatchEvent( new Event( 'change' ) ); -const onCloseLastContext = ( e ) => { + }; - if ( lastContext && lastContext.visible === true && e.target.closest( 'f-menu.context' ) === null ) { + dom.onkeydown = ( e ) => { - lastContext.hide(); + if ( e.key.length === 1 && /\d|\.|\-/.test( e.key ) !== true ) { - } + return false; -}; + } -document.body.addEventListener( 'mousedown', onCloseLastContext, true ); -document.body.addEventListener( 'touchstart', onCloseLastContext, true ); + if ( e.key === 'Enter' ) { -class ContextMenu extends Menu { + e.target.blur(); - constructor( target = null ) { + } - super( 'context', target ); + e.stopPropagation(); - this.events.context = []; + }; - this._lastButtonClick = null; + draggableDOM( dom, ( data ) => { - this._onButtonClick = ( e = null ) => { + const { delta } = data; - const button = e ? e.target : null; + if ( dom.readOnly === true ) return; - if ( this._lastButtonClick ) { + if ( data.value === undefined ) { - this._lastButtonClick.dom.parentElement.classList.remove( 'active' ); + data.value = this.getValue(); } - this._lastButtonClick = button; + const diff = delta.x - delta.y; - if ( button ) { + const value = data.value + ( diff * this.step ); - if ( this.subMenus.has( button ) ) { + dom.value = this._getString( value.toFixed( this.precision ) ); - this.subMenus.get( button )._onButtonClick(); + this.dispatchEvent( new Event( 'change' ) ); - } + } ); - button.dom.parentElement.classList.add( 'active' ); + } - } + setStep( step ) { - }; + this.step = step; - this._onButtonMouseOver = ( e ) => { + return this; - const button = e.target; + } - if ( this.subMenus.has( button ) && this._lastButtonClick !== button ) { + setRange( min, max, step ) { - this._onButtonClick(); + this.min = min; + this.max = max; + this.step = step; - } + this.dispatchEvent( new Event( 'range' ) ); - }; + return this.setValue( this.getValue() ); - this.addEventListener( 'context', ( ) => { + } - dispatchEventList( this.events.context, this ); + get precision() { - } ); + if ( this.integer === true ) return 0; - this.setTarget( target ); + const fract = this.step % 1; + + return fract !== 0 ? fract.toString().split( '.' )[ 1 ].length : 1; } - openFrom( dom ) { + setValue( val, dispatch = true ) { - const rect = dom.getBoundingClientRect(); + return super.setValue( this._getString( val ), dispatch ); - return this.open( rect.x + ( rect.width / 2 ), rect.y + ( rect.height / 2 ) ); + } + + getValue() { + + return Number( this.dom.value ); } - open( x = pointer.x, y = pointer.y ) { + serialize( data ) { - if ( lastContext !== null ) { + const { min, max } = this; - lastContext.hide(); + if ( min !== - Infinity && max !== Infinity ) { + + data.min = this.min; + data.max = this.max; + data.step = this.step; } - lastContext = this; + super.serialize( data ); - this.setPosition( x, y ); + } - document.body.append( this.dom ); + deserialize( data ) { - return this.show(); + if ( data.min !== undefined ) { + + const { min, max, step } = this; + + this.setRange( min, max, step ); + + } + + super.deserialize( data ); } - setPosition( x, y ) { + _getString( value ) { - const dom = this.dom; + const num = Math.min( Math.max( Number( value ), this.min ), this.max ); - dom.style.left = numberToPX( x ); - dom.style.top = numberToPX( y ); + if ( this.integer === true ) { - return this; + return Math.floor( num ); - } + } else { - setTarget( target = null ) { + return num + ( num % 1 ? '' : '.0' ); - if ( target !== null ) { + } - const onContextMenu = ( e ) => { + } - e.preventDefault(); +} - if ( e.pointerType !== 'mouse' || ( e.pageX === 0 && e.pageY === 0 ) ) return; +class SelectInput extends Input { - this.dispatchEvent( new Event( 'context' ) ); + constructor( options = [], value = null ) { - this.open(); + const dom = document.createElement( 'select' ); + super( dom ); - }; + dom.onchange = () => { - this.target = target; + this.dispatchEvent( new Event( 'change' ) ); - target.addEventListener( 'contextmenu', onContextMenu, false ); + }; - } + dom.onmousedown = dom.ontouchstart = () => { - return this; + this.dispatchEvent( new Event( 'click' ) ); + + }; + + this.setOptions( options, value ); } - show() { + setOptions( options, value = null ) { + + const dom = this.dom; + const defaultValue = dom.value; + + let containsDefaultValue = false; - if ( ! this.opened ) { + this.options = options; + dom.innerHTML = ''; - this.dom.style.left = ''; - this.dom.style.transform = ''; + for ( let index = 0; index < options.length; index ++ ) { - } + let opt = options[ index ]; - const domRect = this.dom.getBoundingClientRect(); + if ( typeof opt === 'string' ) { - let offsetX = Math.min( window.innerWidth - ( domRect.x + domRect.width + 10 ), 0 ); - let offsetY = Math.min( window.innerHeight - ( domRect.y + domRect.height + 10 ), 0 ); + opt = { name: opt, value: index }; - if ( this.opened ) { + } - if ( offsetX < 0 ) offsetX = - domRect.width; - if ( offsetY < 0 ) offsetY = - domRect.height; + const option = document.createElement( 'option' ); + option.innerText = opt.name; + option.value = opt.value; - this.setPosition( domRect.x + offsetX, domRect.y + offsetY ); + if ( containsDefaultValue === false && defaultValue === opt.value ) { - } else { + containsDefaultValue = true; - // flip submenus + } - if ( offsetX < 0 ) this.dom.style.left = '-100%'; - if ( offsetY < 0 ) this.dom.style.transform = 'translateY( calc( 32px - 100% ) )'; + dom.append( option ); } - return super.show(); + dom.value = value !== null ? value : containsDefaultValue ? defaultValue : ''; + + return this; } - hide() { + getOptions() { - if ( this.opened ) { + return this._options; - lastContext = null; + } - } + serialize( data ) { - return super.hide(); + data.options = [ ...this.options ]; + + super.serialize( data ); } - add( button, submenu = null ) { + deserialize( data ) { - button.addEventListener( 'click', this._onButtonClick ); - button.addEventListener( 'mouseover', this._onButtonMouseOver ); + const currentOptions = this.options; - return super.add( button, submenu ); + if ( currentOptions.length === 0 ) { - } + this.setOptions( data.options ); - get opened() { + } - return lastContext === this; + super.deserialize( data ); } } -class CircleMenu extends Menu { +const getStep = ( min, max ) => { - constructor( target = null ) { + const sensibility = .001; - super( 'circle', target ); + return ( max - min ) * sensibility; - } +}; -} +class SliderInput extends Input { -class Tips extends EventTarget { + constructor( value = 0, min = 0, max = 100 ) { - constructor() { + const dom = document.createElement( 'f-subinputs' ); + super( dom ); - super(); + value = Math.min( Math.max( value, min ), max ); - const dom = document.createElement( 'f-tips' ); + const step = getStep( min, max ); - this.dom = dom; + const rangeDOM = document.createElement( 'input' ); + rangeDOM.type = 'range'; + rangeDOM.min = min; + rangeDOM.max = max; + rangeDOM.step = step; + rangeDOM.value = value; - this.time = 0; - this.duration = 3000; + const field = new NumberInput( value, min, max, step ); + field.dom.className = 'range-value'; + field.onChange( () => { - } + rangeDOM.value = field.getValue(); - message( str ) { + this.dispatchEvent( new Event( 'change' ) ); - return this.tip( str ); + } ); - } + field.addEventListener( 'range', () => { - error( str ) { + rangeDOM.min = field.min; + rangeDOM.max = field.max; + rangeDOM.step = field.step; + rangeDOM.value = field.getValue(); - return this.tip( str, 'error' ); + } ); - } + dom.append( rangeDOM ); + dom.append( field.dom ); - tip( html, className = '' ) { + this.rangeDOM = rangeDOM; + this.field = field; - const dom = document.createElement( 'f-tip' ); - dom.className = className; - dom.innerHTML = html; + const updateRangeValue = () => { - this.dom.prepend( dom ); + let value = Number( rangeDOM.value ); - //requestAnimationFrame( () => dom.style.opacity = 1 ); + if ( value !== this.max && value + this.step >= this.max ) { - this.time = Math.min( this.time + this.duration, this.duration ); + // fix not end range fraction - setTimeout( () => { + rangeDOM.value = value = this.max; - this.time = Math.max( this.time - this.duration, 0 ); + } - dom.style.opacity = 0; + this.field.setValue( value ); - setTimeout( () => dom.remove(), 250 ); + }; - }, this.time ); + draggableDOM( rangeDOM, () => { - return this; + updateRangeValue(); + + this.dispatchEvent( new Event( 'change' ) ); + + }, { className: '' } ); } -} + get min() { -const filterString = ( str ) => { + return this.field.min; - return str.trim().toLowerCase().replace( /\s\s+/g, ' ' ); + } -}; + get max() { -class Search extends Menu { + return this.field.max; - constructor() { + } - super( 'search' ); + get step() { - this.events.submit = []; - this.events.filter = []; + return this.field.step; - this.tags = new WeakMap(); + } - const inputDOM = document.createElement( 'input' ); - inputDOM.placeholder = 'Type here'; + setRange( min, max ) { - let filter = true; - let filterNeedUpdate = true; + this.field.setRange( min, max, getStep( min, max ) ); - inputDOM.addEventListener( 'focusout', () => { + this.dispatchEvent( new Event( 'range' ) ); + this.dispatchEvent( new Event( 'change' ) ); - filterNeedUpdate = true; + return this; - this.setValue( '' ); + } - } ); + setValue( val, dispatch = true ) { - inputDOM.onkeydown = ( e ) => { + this.field.setValue( val ); + this.rangeDOM.value = val; - const keyCode = e.keyCode; + if ( dispatch ) this.dispatchEvent( new Event( 'change' ) ); - if ( keyCode === 38 ) { + return this; - const index = this.filteredIndex; + } - if ( this.forceAutoComplete ) { + getValue() { - this.filteredIndex = index !== null ? ( index + 1 ) % ( this.filtered.length || 1 ) : 0; + return this.field.getValue(); - } else { + } - this.filteredIndex = index !== null ? Math.min( index + 1, this.filtered.length - 1 ) : 0; + serialize( data ) { - } + data.min = this.min; + data.max = this.max; - e.preventDefault(); + super.serialize( data ); - filter = false; + } - } else if ( keyCode === 40 ) { + deserialize( data ) { - const index = this.filteredIndex; + const { min, max } = data; - if ( this.forceAutoComplete ) { + this.setRange( min, max ); - this.filteredIndex = index - 1; + super.deserialize( data ); - if ( this.filteredIndex === null ) this.filteredIndex = this.filtered.length - 1; + } - } else { +} - this.filteredIndex = index !== null ? index - 1 : null; +class StringInput extends Input { - } + constructor( value = '' ) { - e.preventDefault(); + const dom = document.createElement( 'f-string' ); + super( dom ); - filter = false; + const inputDOM = document.createElement( 'input' ); - } else if ( keyCode === 13 ) { + dom.append( inputDOM ); - this.value = this.currentFiltered ? this.currentFiltered.button.getValue() : inputDOM.value; + inputDOM.type = 'text'; + inputDOM.value = value; + inputDOM.spellcheck = false; + inputDOM.autocomplete = 'off'; - this.submit(); + this._buttonsDOM = null; + this._datalistDOM = null; - e.preventDefault(); + this.iconDOM = null; + this.inputDOM = inputDOM; - filter = false; + this.buttons = []; - } else { + inputDOM.onblur = () => { - filter = true; + this.dispatchEvent( new Event( 'blur' ) ); - } + }; + + inputDOM.onchange = () => { + + this.dispatchEvent( new Event( 'change' ) ); }; - inputDOM.onkeyup = () => { + let keyDownStr = ''; - if ( filter ) { + inputDOM.onkeydown = () => keyDownStr = inputDOM.value; - if ( filterNeedUpdate ) { + inputDOM.onkeyup = ( e ) => { - this.dispatchEvent( new Event( 'filter' ) ); + if ( e.key === 'Enter' ) { - filterNeedUpdate = false; + e.target.blur(); - } + } - this.filter( inputDOM.value ); + e.stopPropagation(); + + if ( keyDownStr !== inputDOM.value ) { + + this.dispatchEvent( new Event( 'change' ) ); } }; - this.filtered = []; - this.currentFiltered = null; + } - this.value = ''; + setPlaceHolder( text ) { - this.forceAutoComplete = false; + this.inputDOM.placeholder = text; - this.dom.append( inputDOM ); + return this; - this.inputDOM = inputDOM; + } - this.addEventListener( 'filter', ( ) => { + setIcon( value ) { - dispatchEventList( this.events.filter, this ); + this.iconDOM = this.iconDOM || document.createElement( 'i' ); + this.iconDOM.setAttribute( 'type', 'icon' ); + this.iconDOM.className = value; - } ); + if ( value ) this.dom.prepend( this.iconDOM ); + else this.iconDOM.remove(); + + return this; - this.addEventListener( 'submit', ( ) => { + } - dispatchEventList( this.events.submit, this ); + getIcon() { - } ); + return this.iconInput ? this.iconInput.getIcon() : ''; } - submit() { + addButton( button ) { - this.dispatchEvent( new Event( 'submit' ) ); + this.buttonsDOM.prepend( button.iconDOM ); - return this.setValue( '' ); + this.buttons.push( button ); + + return this; } - setValue( value ) { + addOption( value ) { - this.inputDOM.value = value; + const option = document.createElement( 'option' ); + option.value = value; - this.filter( value ); + this.datalistDOM.append( option ); return this; } - getValue() { + clearOptions() { - return this.value; + this.datalistDOM.remove(); } - onFilter( callback ) { + get datalistDOM() { - this.events.filter.push( callback ); + let dom = this._datalistDOM; - return this; + if ( dom === null ) { - } + const datalistId = 'input-dt-' + this.id; - onSubmit( callback ) { + dom = document.createElement( 'datalist' ); + dom.id = datalistId; - this.events.submit.push( callback ); + this._datalistDOM = dom; - return this; + this.inputDOM.autocomplete = 'on'; + this.inputDOM.setAttribute( 'list', datalistId ); + + this.dom.prepend( dom ); + + } + + return dom; } - getFilterByButton( button ) { + get buttonsDOM() { - for ( const filter of this.filtered ) { + let dom = this._buttonsDOM; - if ( filter.button === button ) { + if ( dom === null ) { - return filter; + dom = document.createElement( 'f-buttons' ); - } + this._buttonsDOM = dom; + + this.dom.prepend( dom ); } - return null; + return dom; } - add( button ) { + getInput() { - super.add( button ); + return this.inputDOM; - const onDown = () => { + } - const filter = this.getFilterByButton( button ); +} - this.filteredIndex = this.filtered.indexOf( filter ); - this.value = button.getValue(); +class TextInput extends Input { - this.submit(); + constructor( innerText = '' ) { - }; + const dom = document.createElement( 'textarea' ); + super( dom ); - button.dom.addEventListener( 'mousedown', onDown ); - button.dom.addEventListener( 'touchstart', onDown ); + dom.innerText = innerText; - this.domButtons.get( button ).remove(); + dom.classList.add( 'f-scroll' ); - return this; + dom.onblur = () => { - } + this.dispatchEvent( new Event( 'blur' ) ); - set filteredIndex( index ) { + }; - if ( this.currentFiltered ) { + dom.onchange = () => { - const buttonDOM = this.domButtons.get( this.currentFiltered.button ); + this.dispatchEvent( new Event( 'change' ) ); - buttonDOM.classList.remove( 'active' ); + }; - this.currentFiltered = null; + dom.onkeyup = ( e ) => { - } + if ( e.key === 'Enter' ) { - const filteredItem = this.filtered[ index ]; + e.target.blur(); - if ( filteredItem ) { + } - const buttonDOM = this.domButtons.get( filteredItem.button ); + e.stopPropagation(); - buttonDOM.classList.add( 'active' ); + this.dispatchEvent( new Event( 'change' ) ); - this.currentFiltered = filteredItem; + }; - } + } - this.updateFilter(); +} - } +class ToggleInput extends Input { - get filteredIndex() { + constructor( value = false ) { - return this.currentFiltered ? this.filtered.indexOf( this.currentFiltered ) : null; + const dom = document.createElement( 'input' ); + super( dom ); + + dom.type = 'checkbox'; + dom.className = 'toggle'; + dom.checked = value; + + dom.onclick = () => this.dispatchEvent( new Event( 'click' ) ); + dom.onchange = () => this.dispatchEvent( new Event( 'change' ) ); } - setTag( button, tags ) { + setValue( val ) { - this.tags.set( button, tags ); + this.dom.checked = val; + + this.dispatchEvent( new Event( 'change' ) ); + + return this; } - filter( text ) { + getValue() { - text = filterString( text ); + return this.dom.checked; - const tags = this.tags; - const filtered = []; + } - for ( const button of this.buttons ) { +} - const buttonDOM = this.domButtons.get( button ); +class TreeViewNode { - buttonDOM.remove(); + constructor( name = '' ) { - const buttonTags = tags.has( button ) ? ' ' + tags.get( button ) : ''; + const dom = document.createElement( 'f-treeview-node' ); + const labelDOM = document.createElement( 'f-treeview-label' ); + const inputDOM = document.createElement( 'input' ); - const label = filterString( button.getValue() + buttonTags ); + const labelSpam = document.createElement( 'spam' ); + labelDOM.append( labelSpam ); - if ( text && label.includes( text ) === true ) { + labelSpam.innerText = name; - const score = text.length / label.length; + inputDOM.type = 'checkbox'; - filtered.push( { - button, - score - } ); + dom.append( inputDOM ); + dom.append( labelDOM ); - } + this.dom = dom; + this.childrenDOM = null; + this.labelSpam = labelSpam; + this.labelDOM = labelDOM; + this.inputDOM = inputDOM; + this.iconDOM = null; - } + this.parent = null; + this.children = []; - filtered.sort( ( a, b ) => b.score - a.score ); + this.selected = false; - this.filtered = filtered; - this.filteredIndex = this.forceAutoComplete ? 0 : null; + this.events = { + 'change': [], + 'click': [] + }; - } + dom.addEventListener( 'click', ( ) => { - updateFilter() { + dispatchEventList( this.events.click, this ); - const filteredIndex = Math.min( this.filteredIndex, this.filteredIndex - 3 ); + } ); - for ( let i = 0; i < this.filtered.length; i ++ ) { + } - const button = this.filtered[ i ].button; - const buttonDOM = this.domButtons.get( button ); + setLabel( value ) { - buttonDOM.remove(); + this.labelSpam.innerText = value; - if ( i >= filteredIndex ) { + return this; - this.listDOM.append( buttonDOM ); + } - } + getLabel() { - } + return this.labelSpam.innerText; } -} + add( node ) { -class SelectInput extends Input { + let childrenDOM = this.childrenDOM; - constructor( options = [], value = null ) { + if ( this.childrenDOM === null ) { - const dom = document.createElement( 'select' ); - super( dom ); + const dom = this.dom; - dom.onchange = () => { + const arrowDOM = document.createElement( 'f-arrow' ); + childrenDOM = document.createElement( 'f-treeview-children' ); - this.dispatchEvent( new Event( 'change' ) ); + dom.append( arrowDOM ); + dom.append( childrenDOM ); - }; + this.childrenDOM = childrenDOM; - dom.onmousedown = dom.ontouchstart = () => { + } - this.dispatchEvent( new Event( 'click' ) ); + this.children.push( node ); + childrenDOM.append( node.dom ); - }; + node.parent = this; - this.setOptions( options, value ); + return this; } - setOptions( options, value = null ) { + setOpened( value ) { - const dom = this.dom; - const defaultValue = dom.value; + this.inputDOM.checked = value; - let containsDefaultValue = false; + return this; - this.options = options; - dom.innerHTML = ''; + } - for ( let index = 0; index < options.length; index ++ ) { + getOpened() { - let opt = options[ index ]; + return this.inputDOM.checkbox; - if ( typeof opt === 'string' ) { + } - opt = { name: opt, value: index }; + setIcon( value ) { - } + this.iconDOM = this.iconDOM || document.createElement( 'i' ); + this.iconDOM.className = value; - const option = document.createElement( 'option' ); - option.innerText = opt.name; - option.value = opt.value; + if ( value ) this.labelDOM.prepend( this.iconDOM ); + else this.iconDOM.remove(); - if ( containsDefaultValue === false && defaultValue === opt.value ) { + return this; - containsDefaultValue = true; + } - } + getIcon() { - dom.append( option ); + return this.iconDOM ? this.iconDOM.className : null; - } + } - dom.value = value !== null ? value : containsDefaultValue ? defaultValue : ''; + setVisible( value ) { + + this.dom.style.display = value ? '' : 'none'; return this; } - getOptions() { + setSelected( value ) { - return this._options; + if ( this.selected === value ) return this; + + if ( value ) this.dom.classList.add( 'selected' ); + else this.dom.classList.remove( 'selected' ); + + this.selected = value; + + return this; } - serialize( data ) { + onClick( callback ) { - data.options = [ ...this.options ]; + this.events.click.push( callback ); - super.serialize( data ); + return this; } - deserialize( data ) { +} - const currentOptions = this.options; +class TreeViewInput extends Input { - if ( currentOptions.length === 0 ) { + constructor( options = [] ) { - this.setOptions( data.options ); + const dom = document.createElement( 'f-treeview' ); + super( dom ); - } + const childrenDOM = document.createElement( 'f-treeview-children' ); + dom.append( childrenDOM ); - super.deserialize( data ); + dom.setAttribute( 'type', 'tree' ); + + this.childrenDOM = childrenDOM; + + this.children = []; } -} + add( node ) { -class ToggleInput extends Input { + this.children.push( node ); + this.childrenDOM.append( node.dom ); - constructor( value = false ) { + return this; - const dom = document.createElement( 'input' ); - super( dom ); + } - dom.type = 'checkbox'; - dom.className = 'toggle'; - dom.checked = value; + serialize( data ) { - dom.onclick = () => this.dispatchEvent( new Event( 'click' ) ); - dom.onchange = () => this.dispatchEvent( new Event( 'change' ) ); + //data.options = [ ...this.options ]; - } + super.serialize( data ); - setValue( val ) { + } - this.dom.checked = val; + deserialize( data ) { - this.dispatchEvent( new Event( 'change' ) ); + /*const currentOptions = this.options; - return this; + if ( currentOptions.length === 0 ) { - } + this.setOptions( data.options ); - getValue() { + }*/ - return this.dom.checked; + super.deserialize( data ); } } -var Flow = /*#__PURE__*/Object.freeze( { +var Flow = /*#__PURE__*/Object.freeze({ __proto__: null, Element: Element, Input: Input, Node: Node, Canvas: Canvas, Serializer: Serializer, - Styles: Styles, - ObjectNode: ObjectNode, - PanelNode: PanelNode, Menu: Menu, ContextMenu: ContextMenu, CircleMenu: CircleMenu, @@ -4400,8 +4719,12 @@ var Flow = /*#__PURE__*/Object.freeze( { SliderInput: SliderInput, StringInput: StringInput, TextInput: TextInput, - ToggleInput: ToggleInput -} ); + ToggleInput: ToggleInput, + TreeViewInput: TreeViewInput, + TreeViewNode: TreeViewNode +}); + +const LoaderLib = {}; class Loader extends EventTarget { @@ -4439,7 +4762,7 @@ class Loader extends EventTarget { } - async load( url, lib = null ) { + async load( url, lib = {} ) { return await fetch( url ) .then( response => response.json() ) @@ -4460,7 +4783,7 @@ class Loader extends EventTarget { } - parse( json, lib = null ) { + parse( json, lib = {} ) { json = this._parseObjects( json, lib ); @@ -4468,7 +4791,10 @@ class Loader extends EventTarget { if ( parseType === Loader.DEFAULT ) { - const flowObj = new Flow[ json.type ](); + const type = json.type; + + const flowClass = lib[ type ] ? lib[ type ] : ( LoaderLib[ type ] || Flow[ type ] ); + const flowObj = new flowClass(); if ( flowObj.getSerializable() ) { @@ -4486,7 +4812,7 @@ class Loader extends EventTarget { } - _parseObjects( json, lib = null ) { + _parseObjects( json, lib = {} ) { json = { ...json }; @@ -4497,19 +4823,21 @@ class Loader extends EventTarget { const obj = json.objects[ id ]; obj.objects = objects; - const Class = lib && lib[ obj.type ] ? lib[ obj.type ] : Flow[ obj.type ]; + const type = obj.type; + const flowClass = lib[ type ] ? lib[ type ] : ( LoaderLib[ type ] || Flow[ type ] ); - if ( ! Class ) { + if ( ! flowClass ) { - console.error( `Class "${ obj.type }" not found!` ); + console.error( `Class "${ type }" not found!` ); } - objects[ id ] = new Class(); + objects[ id ] = new flowClass(); + objects[ id ].deserializeLib( json.objects[ id ], lib ); } - const ref = new WeakMap(); + const ref = new Map(); const deserializePass = ( prop = null ) => { @@ -4549,4 +4877,4 @@ class Loader extends EventTarget { Loader.DEFAULT = 'default'; Loader.OBJECTS = 'objects'; -export { ButtonInput, Canvas, CircleMenu, ColorInput, ContextMenu, DraggableElement, Element, Input, LabelElement, Loader, Menu, Node, NumberInput, ObjectNode, PanelNode, REVISION, Search, SelectInput, Serializer, SliderInput, StringInput, Styles, TextInput, Tips, TitleElement, ToggleInput, Utils }; +export { ButtonInput, Canvas, CircleMenu, ColorInput, ContextMenu, DraggableElement, Element, Input, LabelElement, Loader, LoaderLib, Menu, Node, NumberInput, REVISION, Search, SelectInput, Serializer, SliderInput, StringInput, TextInput, Tips, TitleElement, ToggleInput, TreeViewInput, TreeViewNode, Utils }; diff --git a/src/Three.Legacy.js b/src/Three.Legacy.js index e0f5b2a2834dd4..890b540855776d 100644 --- a/src/Three.Legacy.js +++ b/src/Three.Legacy.js @@ -18,9 +18,7 @@ import { TorusGeometry } from './geometries/TorusGeometry.js'; import { TorusKnotGeometry } from './geometries/TorusKnotGeometry.js'; import { TubeGeometry } from './geometries/TubeGeometry.js'; -// r144 - -export class BoxBufferGeometry extends BoxGeometry { +export class BoxBufferGeometry extends BoxGeometry { // @deprecated, r144 constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) { @@ -32,9 +30,7 @@ export class BoxBufferGeometry extends BoxGeometry { } -// r144 - -export class CapsuleBufferGeometry extends CapsuleGeometry { +export class CapsuleBufferGeometry extends CapsuleGeometry { // @deprecated, r144 constructor( radius, length, capSegments, radialSegments ) { @@ -45,9 +41,7 @@ export class CapsuleBufferGeometry extends CapsuleGeometry { } -// r144 - -export class CircleBufferGeometry extends CircleGeometry { +export class CircleBufferGeometry extends CircleGeometry { // @deprecated, r144 constructor( radius, segments, thetaStart, thetaLength ) { @@ -58,9 +52,7 @@ export class CircleBufferGeometry extends CircleGeometry { } -// r144 - -export class ConeBufferGeometry extends ConeGeometry { +export class ConeBufferGeometry extends ConeGeometry { // @deprecated, r144 constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -71,9 +63,7 @@ export class ConeBufferGeometry extends ConeGeometry { } -// r144 - -export class CylinderBufferGeometry extends CylinderGeometry { +export class CylinderBufferGeometry extends CylinderGeometry { // @deprecated, r144 constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { @@ -84,9 +74,7 @@ export class CylinderBufferGeometry extends CylinderGeometry { } -// r144 - -export class DodecahedronBufferGeometry extends DodecahedronGeometry { +export class DodecahedronBufferGeometry extends DodecahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -97,9 +85,7 @@ export class DodecahedronBufferGeometry extends DodecahedronGeometry { } -// r144 - -export class ExtrudeBufferGeometry extends ExtrudeGeometry { +export class ExtrudeBufferGeometry extends ExtrudeGeometry { // @deprecated, r144 constructor( shapes, options ) { @@ -110,9 +96,7 @@ export class ExtrudeBufferGeometry extends ExtrudeGeometry { } -// r144 - -export class IcosahedronBufferGeometry extends IcosahedronGeometry { +export class IcosahedronBufferGeometry extends IcosahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -123,9 +107,7 @@ export class IcosahedronBufferGeometry extends IcosahedronGeometry { } -// r144 - -export class LatheBufferGeometry extends LatheGeometry { +export class LatheBufferGeometry extends LatheGeometry { // @deprecated, r144 constructor( points, segments, phiStart, phiLength ) { @@ -136,9 +118,7 @@ export class LatheBufferGeometry extends LatheGeometry { } -// r144 - -export class OctahedronBufferGeometry extends OctahedronGeometry { +export class OctahedronBufferGeometry extends OctahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -149,9 +129,7 @@ export class OctahedronBufferGeometry extends OctahedronGeometry { } -// r144 - -export class PlaneBufferGeometry extends PlaneGeometry { +export class PlaneBufferGeometry extends PlaneGeometry { // @deprecated, r144 constructor( width, height, widthSegments, heightSegments ) { @@ -162,9 +140,7 @@ export class PlaneBufferGeometry extends PlaneGeometry { } -// r144 - -export class PolyhedronBufferGeometry extends PolyhedronGeometry { +export class PolyhedronBufferGeometry extends PolyhedronGeometry { // @deprecated, r144 constructor( vertices, indices, radius, detail ) { @@ -175,9 +151,7 @@ export class PolyhedronBufferGeometry extends PolyhedronGeometry { } -// r144 - -export class RingBufferGeometry extends RingGeometry { +export class RingBufferGeometry extends RingGeometry { // @deprecated, r144 constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { @@ -188,9 +162,7 @@ export class RingBufferGeometry extends RingGeometry { } -// r144 - -export class ShapeBufferGeometry extends ShapeGeometry { +export class ShapeBufferGeometry extends ShapeGeometry { // @deprecated, r144 constructor( shapes, curveSegments ) { @@ -201,9 +173,7 @@ export class ShapeBufferGeometry extends ShapeGeometry { } -// r144 - -export class SphereBufferGeometry extends SphereGeometry { +export class SphereBufferGeometry extends SphereGeometry { // @deprecated, r144 constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { @@ -214,9 +184,7 @@ export class SphereBufferGeometry extends SphereGeometry { } -// r144 - -export class TetrahedronBufferGeometry extends TetrahedronGeometry { +export class TetrahedronBufferGeometry extends TetrahedronGeometry { // @deprecated, r144 constructor( radius, detail ) { @@ -227,9 +195,7 @@ export class TetrahedronBufferGeometry extends TetrahedronGeometry { } -// r144 - -export class TorusBufferGeometry extends TorusGeometry { +export class TorusBufferGeometry extends TorusGeometry { // @deprecated, r144 constructor( radius, tube, radialSegments, tubularSegments, arc ) { @@ -240,9 +206,7 @@ export class TorusBufferGeometry extends TorusGeometry { } -// r144 - -export class TorusKnotBufferGeometry extends TorusKnotGeometry { +export class TorusKnotBufferGeometry extends TorusKnotGeometry { // @deprecated, r144 constructor( radius, tube, tubularSegments, radialSegments, p, q ) { @@ -253,9 +217,7 @@ export class TorusKnotBufferGeometry extends TorusKnotGeometry { } -// r144 - -export class TubeBufferGeometry extends TubeGeometry { +export class TubeBufferGeometry extends TubeGeometry { // @deprecated, r144 constructor( path, tubularSegments, radius, radialSegments, closed ) { @@ -265,5 +227,3 @@ export class TubeBufferGeometry extends TubeGeometry { } } - - diff --git a/src/Three.js b/src/Three.js index 8254f9a36f7038..0773a037ca7b1f 100644 --- a/src/Three.js +++ b/src/Three.js @@ -86,10 +86,11 @@ export { BooleanKeyframeTrack } from './animation/tracks/BooleanKeyframeTrack.js export { PropertyMixer } from './animation/PropertyMixer.js'; export { PropertyBinding } from './animation/PropertyBinding.js'; export { KeyframeTrack } from './animation/KeyframeTrack.js'; -export * as AnimationUtils from './animation/AnimationUtils.js'; +export { AnimationUtils } from './animation/AnimationUtils.js'; export { AnimationObjectGroup } from './animation/AnimationObjectGroup.js'; export { AnimationMixer } from './animation/AnimationMixer.js'; export { AnimationClip } from './animation/AnimationClip.js'; +export { AnimationAction } from './animation/AnimationAction.js'; export { Uniform } from './core/Uniform.js'; export { UniformsGroup } from './core/UniformsGroup.js'; export { InstancedBufferGeometry } from './core/InstancedBufferGeometry.js'; @@ -111,7 +112,7 @@ export { DiscreteInterpolant } from './math/interpolants/DiscreteInterpolant.js' export { CubicInterpolant } from './math/interpolants/CubicInterpolant.js'; export { Interpolant } from './math/Interpolant.js'; export { Triangle } from './math/Triangle.js'; -export * as MathUtils from './math/MathUtils.js'; +export { MathUtils } from './math/MathUtils.js'; export { Spherical } from './math/Spherical.js'; export { Cylindrical } from './math/Cylindrical.js'; export { Plane } from './math/Plane.js'; @@ -150,7 +151,7 @@ export { Path } from './extras/core/Path.js'; export { ShapePath } from './extras/core/ShapePath.js'; export { CurvePath } from './extras/core/CurvePath.js'; export { Curve } from './extras/core/Curve.js'; -export * as DataUtils from './extras/DataUtils.js'; +export { DataUtils } from './extras/DataUtils.js'; export { ImageUtils } from './extras/ImageUtils.js'; export { ShapeUtils } from './extras/ShapeUtils.js'; export { PMREMGenerator } from './extras/PMREMGenerator.js'; diff --git a/src/animation/AnimationUtils.js b/src/animation/AnimationUtils.js index 0ac0626810d4ea..6cd6f5ba1ccb64 100644 --- a/src/animation/AnimationUtils.js +++ b/src/animation/AnimationUtils.js @@ -349,6 +349,17 @@ function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targe } +const AnimationUtils = { + arraySlice: arraySlice, + convertArray: convertArray, + isTypedArray: isTypedArray, + getKeyframeOrder: getKeyframeOrder, + sortedArray: sortedArray, + flattenJSON: flattenJSON, + subclip: subclip, + makeClipAdditive: makeClipAdditive +}; + export { arraySlice, convertArray, @@ -357,5 +368,6 @@ export { sortedArray, flattenJSON, subclip, - makeClipAdditive + makeClipAdditive, + AnimationUtils }; diff --git a/src/audio/PositionalAudio.js b/src/audio/PositionalAudio.js index 9c2a7a213c1abe..f60bcb383e4e6f 100644 --- a/src/audio/PositionalAudio.js +++ b/src/audio/PositionalAudio.js @@ -19,6 +19,14 @@ class PositionalAudio extends Audio { } + connect() { + + super.connect(); + + this.panner.connect( this.gain ); + + } + disconnect() { super.disconnect(); diff --git a/src/constants.js b/src/constants.js index c9f91cba51e23d..2dfdf4f55d6586 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,4 +1,5 @@ -export const REVISION = '150dev'; +export const REVISION = '153dev'; + export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; export const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; export const CullFaceNone = 0; @@ -139,7 +140,9 @@ export const AdditiveAnimationBlendMode = 2501; export const TrianglesDrawMode = 0; export const TriangleStripDrawMode = 1; export const TriangleFanDrawMode = 2; +/** @deprecated Use LinearSRGBColorSpace or NoColorSpace in three.js r152+. */ export const LinearEncoding = 3000; +/** @deprecated Use SRGBColorSpace in three.js r152+. */ export const sRGBEncoding = 3001; export const BasicDepthPacking = 3200; export const RGBADepthPacking = 3201; @@ -150,6 +153,7 @@ export const ObjectSpaceNormalMap = 1; export const NoColorSpace = ''; export const SRGBColorSpace = 'srgb'; export const LinearSRGBColorSpace = 'srgb-linear'; +export const DisplayP3ColorSpace = 'display-p3'; export const ZeroStencilOp = 0; export const KeepStencilOp = 7680; @@ -169,6 +173,15 @@ export const NotEqualStencilFunc = 517; export const GreaterEqualStencilFunc = 518; export const AlwaysStencilFunc = 519; +export const NeverCompare = 512; +export const LessCompare = 513; +export const EqualCompare = 514; +export const LessEqualCompare = 515; +export const GreaterCompare = 516; +export const NotEqualCompare = 517; +export const GreaterEqualCompare = 518; +export const AlwaysCompare = 519; + export const StaticDrawUsage = 35044; export const DynamicDrawUsage = 35048; export const StreamDrawUsage = 35040; diff --git a/src/core/BufferAttribute.js b/src/core/BufferAttribute.js index b146f3479176fb..f0f167ab3ae1d9 100644 --- a/src/core/BufferAttribute.js +++ b/src/core/BufferAttribute.js @@ -1,7 +1,8 @@ import { Vector3 } from '../math/Vector3.js'; import { Vector2 } from '../math/Vector2.js'; import { denormalize, normalize } from '../math/MathUtils.js'; -import { StaticDrawUsage } from '../constants.js'; +import { StaticDrawUsage, FloatType } from '../constants.js'; +import { fromHalfFloat, toHalfFloat } from '../extras/DataUtils.js'; const _vector = /*@__PURE__*/ new Vector3(); const _vector2 = /*@__PURE__*/ new Vector2(); @@ -27,6 +28,7 @@ class BufferAttribute { this.usage = StaticDrawUsage; this.updateRange = { offset: 0, count: - 1 }; + this.gpuType = FloatType; this.version = 0; @@ -57,6 +59,7 @@ class BufferAttribute { this.normalized = source.normalized; this.usage = source.usage; + this.gpuType = source.gpuType; return this; @@ -343,27 +346,25 @@ class BufferAttribute { } - // @deprecated - - copyColorsArray() { + copyColorsArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyColorsArray() was removed in r144.' ); } - copyVector2sArray() { + copyVector2sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector2sArray() was removed in r144.' ); } - copyVector3sArray() { + copyVector3sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector3sArray() was removed in r144.' ); } - copyVector4sArray() { + copyVector4sArray() { // @deprecated, r144 console.error( 'THREE.BufferAttribute: copyVector4sArray() was removed in r144.' ); @@ -453,6 +454,146 @@ class Float16BufferAttribute extends BufferAttribute { } + getX( index ) { + + let x = fromHalfFloat( this.array[ index * this.itemSize ] ); + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; + + } + + setX( index, x ) { + + if ( this.normalized ) x = normalize( x, this.array ); + + this.array[ index * this.itemSize ] = toHalfFloat( x ); + + return this; + + } + + getY( index ) { + + let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; + + } + + setY( index, y ) { + + if ( this.normalized ) y = normalize( y, this.array ); + + this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); + + return this; + + } + + getZ( index ) { + + let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; + + } + + setZ( index, z ) { + + if ( this.normalized ) z = normalize( z, this.array ); + + this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); + + return this; + + } + + getW( index ) { + + let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; + + } + + setW( index, w ) { + + if ( this.normalized ) w = normalize( w, this.array ); + + this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); + + return this; + + } + + setXY( index, x, y ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + + return this; + + } + + setXYZ( index, x, y, z ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + + return this; + + } + + setXYZW( index, x, y, z, w ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize( x, this.array ); + y = normalize( y, this.array ); + z = normalize( z, this.array ); + w = normalize( w, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + this.array[ index + 3 ] = toHalfFloat( w ); + + return this; + + } + } diff --git a/src/core/BufferGeometry.js b/src/core/BufferGeometry.js index c0fff3779622f5..b2dc14bea2768f 100644 --- a/src/core/BufferGeometry.js +++ b/src/core/BufferGeometry.js @@ -726,11 +726,9 @@ class BufferGeometry extends EventDispatcher { } - // @deprecated since r144 + merge() { // @deprecated, r144 - merge() { - - console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeBufferGeometries() instead.' ); + console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeGeometries() instead.' ); return this; } @@ -857,7 +855,7 @@ class BufferGeometry extends EventDispatcher { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'BufferGeometry', generator: 'BufferGeometry.toJSON' } @@ -1073,10 +1071,6 @@ class BufferGeometry extends EventDispatcher { this.userData = source.userData; - // geometry generator parameters - - if ( source.parameters !== undefined ) this.parameters = Object.assign( {}, source.parameters ); - return this; } diff --git a/src/core/Object3D.js b/src/core/Object3D.js index 37c0cc2d9e9be8..63497bd1d4cbac 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -693,7 +693,7 @@ class Object3D extends EventDispatcher { }; output.metadata = { - version: 4.5, + version: 4.6, type: 'Object', generator: 'Object3D.toJSON' }; @@ -717,6 +717,7 @@ class Object3D extends EventDispatcher { object.layers = this.layers.mask; object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; @@ -944,6 +945,8 @@ class Object3D extends EventDispatcher { this.frustumCulled = source.frustumCulled; this.renderOrder = source.renderOrder; + this.animations = source.animations; + this.userData = JSON.parse( JSON.stringify( source.userData ) ); if ( recursive === true ) { diff --git a/src/extras/DataUtils.js b/src/extras/DataUtils.js index ec3910b5231a1b..3234f34c0106a6 100644 --- a/src/extras/DataUtils.js +++ b/src/extras/DataUtils.js @@ -164,7 +164,13 @@ function fromHalfFloat( val ) { } +const DataUtils = { + toHalfFloat: toHalfFloat, + fromHalfFloat: fromHalfFloat, +}; + export { toHalfFloat, - fromHalfFloat + fromHalfFloat, + DataUtils }; diff --git a/src/extras/ImageUtils.js b/src/extras/ImageUtils.js index e7fcfef9b51fa0..ceddc4d9ddd1d2 100644 --- a/src/extras/ImageUtils.js +++ b/src/extras/ImageUtils.js @@ -1,5 +1,5 @@ import { createElementNS } from '../utils.js'; -import { SRGBToLinear } from '../math/Color.js'; +import { SRGBToLinear } from '../math/ColorManagement.js'; let _canvas; @@ -13,7 +13,7 @@ class ImageUtils { } - if ( typeof HTMLCanvasElement == 'undefined' ) { + if ( typeof HTMLCanvasElement === 'undefined' ) { return image.src; diff --git a/src/extras/PMREMGenerator.js b/src/extras/PMREMGenerator.js index 75c4dfbff15dc3..73d52bee27339f 100644 --- a/src/extras/PMREMGenerator.js +++ b/src/extras/PMREMGenerator.js @@ -2,12 +2,13 @@ import { CubeReflectionMapping, CubeRefractionMapping, CubeUVReflectionMapping, - LinearEncoding, LinearFilter, NoToneMapping, NoBlending, RGBAFormat, - HalfFloatType + HalfFloatType, + BackSide, + LinearSRGBColorSpace } from '../constants.js'; import { BufferAttribute } from '../core/BufferAttribute.js'; @@ -21,7 +22,6 @@ import { Color } from '../math/Color.js'; import { WebGLRenderTarget } from '../renderers/WebGLRenderTarget.js'; import { MeshBasicMaterial } from '../materials/MeshBasicMaterial.js'; import { BoxGeometry } from '../geometries/BoxGeometry.js'; -import { BackSide } from '../constants.js'; const LOD_MIN = 4; @@ -100,23 +100,13 @@ class PMREMGenerator { * and far planes ensure the scene is rendered in its entirety (the cubeCamera * is placed at the origin). */ - fromScene( scene, sigma = 0, near = 0.1, far = 100, cubeUVRenderTarget = null, pingPongRenderTarget = null ) { + fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { _oldTarget = this._renderer.getRenderTarget(); - if ( ! cubeUVRenderTarget ) { - - cubeUVRenderTarget = this._allocateTargets(); - - } - - if ( pingPongRenderTarget ) { - - this._pingPongRenderTarget = pingPongRenderTarget; - - } this._setSize( 256 ); + const cubeUVRenderTarget = this._allocateTargets(); cubeUVRenderTarget.depthBuffer = true; this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); @@ -134,42 +124,6 @@ class PMREMGenerator { } - prepareForRenderTarget ( cubeUVRenderTarget, pingPongRenderTarget = null, cubeSize = 256 ) { - this._setSize( cubeSize ); - const { _lodMax } = this; - ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); - const width = 3 * Math.max( this._cubeSize, 16 * 7 ); - const height = 4 * this._cubeSize; - this._blurMaterial = _getBlurShader( _lodMax, width, height ); - cubeUVRenderTarget.setSize( width, height ); - if (pingPongRenderTarget) { - pingPongRenderTarget.setSize( width, height); - } - } - - fromSceneToRenderTarget( scene, cubeUVRenderTarget, pingPongRenderTarget, sigma = 0, near = 0.1, far = 100 ) { - - _oldTarget = this._renderer.getRenderTarget(); - - this._pingPongRenderTarget = pingPongRenderTarget; - - this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); - if ( sigma > 0 ) { - - this._blur( cubeUVRenderTarget, 0, 0, sigma ); - - } - - this._applyPMREM( cubeUVRenderTarget ); - - this._renderer.setRenderTarget( _oldTarget ); - cubeUVRenderTarget.scissorTest = false; - _setViewport( cubeUVRenderTarget, 0, 0, cubeUVRenderTarget.width, cubeUVRenderTarget.height ); - - return cubeUVRenderTarget; - - } - /** * Generates a PMREM from an equirectangular texture, which can be either LDR * or HDR. The ideal input image size is 1k (1024 x 512), @@ -301,7 +255,7 @@ class PMREMGenerator { generateMipmaps: false, type: HalfFloatType, format: RGBAFormat, - encoding: LinearEncoding, + colorSpace: LinearSRGBColorSpace, depthBuffer: false }; @@ -893,16 +847,6 @@ function _getCommonVertexShader() { varying vec3 vOutputDirection; - mat3 getRotationMatrix(vec3 axis, float angle) { - axis = normalize(axis); - float s = sin(angle); - float c = cos(angle); - float oc = 1.0 - c; - - return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, - oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, - oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); - } // RH coordinate system; PMREM face-indexing convention vec3 getDirection( vec2 uv, float face ) { @@ -938,8 +882,7 @@ function _getCommonVertexShader() { direction.z *= -1.0; // ( u, v, -1 ) neg z } - mat3 rotationMatrix = getRotationMatrix(vec3(1.0, 0.0, 0.0), 1.57); - direction = rotationMatrix * direction; + return direction; } diff --git a/src/extras/core/Curve.js b/src/extras/core/Curve.js index 5ef49ab89994a6..b1b1f46fb83e64 100644 --- a/src/extras/core/Curve.js +++ b/src/extras/core/Curve.js @@ -389,7 +389,7 @@ class Curve { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Curve', generator: 'Curve.toJSON' } diff --git a/src/extras/curves/LineCurve.js b/src/extras/curves/LineCurve.js index 4b14d5edb6aad8..0a636898ce30cb 100644 --- a/src/extras/curves/LineCurve.js +++ b/src/extras/curves/LineCurve.js @@ -42,13 +42,15 @@ class LineCurve extends Curve { } - getTangent( t, optionalTarget ) { + getTangent( t, optionalTarget = new Vector2() ) { - const tangent = optionalTarget || new Vector2(); + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); - tangent.copy( this.v2 ).sub( this.v1 ).normalize(); + } + + getTangentAt( u, optionalTarget ) { - return tangent; + return this.getTangent( u, optionalTarget ); } diff --git a/src/extras/curves/LineCurve3.js b/src/extras/curves/LineCurve3.js index c315c3869f3024..f83a63914fed22 100644 --- a/src/extras/curves/LineCurve3.js +++ b/src/extras/curves/LineCurve3.js @@ -39,6 +39,19 @@ class LineCurve3 extends Curve { return this.getPoint( u, optionalTarget ); } + + getTangent( t, optionalTarget = new Vector3() ) { + + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); + + } + + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); + + } + copy( source ) { super.copy( source ); diff --git a/src/geometries/BoxGeometry.js b/src/geometries/BoxGeometry.js index 5f3aa4c8590451..486a3cd9d67539 100644 --- a/src/geometries/BoxGeometry.js +++ b/src/geometries/BoxGeometry.js @@ -159,6 +159,16 @@ class BoxGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); diff --git a/src/geometries/CircleGeometry.js b/src/geometries/CircleGeometry.js index 528f94c47d0774..63e912126e69f9 100644 --- a/src/geometries/CircleGeometry.js +++ b/src/geometries/CircleGeometry.js @@ -79,6 +79,16 @@ class CircleGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); diff --git a/src/geometries/CylinderGeometry.js b/src/geometries/CylinderGeometry.js index 8e3c2cbc11f388..f27e14e7b6a761 100644 --- a/src/geometries/CylinderGeometry.js +++ b/src/geometries/CylinderGeometry.js @@ -264,6 +264,16 @@ class CylinderGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); diff --git a/src/geometries/EdgesGeometry.js b/src/geometries/EdgesGeometry.js index 73af2d96973eac..795a7c1cc5b798 100644 --- a/src/geometries/EdgesGeometry.js +++ b/src/geometries/EdgesGeometry.js @@ -137,6 +137,16 @@ class EdgesGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } export { EdgesGeometry }; diff --git a/src/geometries/ExtrudeGeometry.js b/src/geometries/ExtrudeGeometry.js index a726b11360d4df..a27b67da818c2f 100644 --- a/src/geometries/ExtrudeGeometry.js +++ b/src/geometries/ExtrudeGeometry.js @@ -170,7 +170,7 @@ class ExtrudeGeometry extends BufferGeometry { if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); - return vec.clone().multiplyScalar( size ).add( pt ); + return pt.clone().addScaledVector( vec, size ); } @@ -677,6 +677,16 @@ class ExtrudeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); diff --git a/src/geometries/LatheGeometry.js b/src/geometries/LatheGeometry.js index 8e509912221990..50a1d09dd1814a 100644 --- a/src/geometries/LatheGeometry.js +++ b/src/geometries/LatheGeometry.js @@ -167,6 +167,16 @@ class LatheGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); diff --git a/src/geometries/PlaneGeometry.js b/src/geometries/PlaneGeometry.js index d093f041d71a0a..53f98f7a37a255 100644 --- a/src/geometries/PlaneGeometry.js +++ b/src/geometries/PlaneGeometry.js @@ -77,6 +77,16 @@ class PlaneGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); diff --git a/src/geometries/PolyhedronGeometry.js b/src/geometries/PolyhedronGeometry.js index 99478e618f8f5d..114cfeece111b6 100644 --- a/src/geometries/PolyhedronGeometry.js +++ b/src/geometries/PolyhedronGeometry.js @@ -298,6 +298,16 @@ class PolyhedronGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); diff --git a/src/geometries/RingGeometry.js b/src/geometries/RingGeometry.js index 75ed9559d7450a..9a8cbbc5871162 100644 --- a/src/geometries/RingGeometry.js +++ b/src/geometries/RingGeometry.js @@ -106,6 +106,16 @@ class RingGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); diff --git a/src/geometries/ShapeGeometry.js b/src/geometries/ShapeGeometry.js index 098c82e656fc9a..5b97d771af1448 100644 --- a/src/geometries/ShapeGeometry.js +++ b/src/geometries/ShapeGeometry.js @@ -130,6 +130,16 @@ class ShapeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); diff --git a/src/geometries/SphereGeometry.js b/src/geometries/SphereGeometry.js index 8551e9b228c865..56cd3805b4dc7a 100644 --- a/src/geometries/SphereGeometry.js +++ b/src/geometries/SphereGeometry.js @@ -50,11 +50,11 @@ class SphereGeometry extends BufferGeometry { let uOffset = 0; - if ( iy == 0 && thetaStart == 0 ) { + if ( iy === 0 && thetaStart === 0 ) { uOffset = 0.5 / widthSegments; - } else if ( iy == heightSegments && thetaEnd == Math.PI ) { + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { uOffset = - 0.5 / widthSegments; @@ -116,6 +116,16 @@ class SphereGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); diff --git a/src/geometries/TorusGeometry.js b/src/geometries/TorusGeometry.js index 6da3b4a11e319a..9061e6d0315008 100644 --- a/src/geometries/TorusGeometry.js +++ b/src/geometries/TorusGeometry.js @@ -99,6 +99,16 @@ class TorusGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); diff --git a/src/geometries/TorusKnotGeometry.js b/src/geometries/TorusKnotGeometry.js index 66fcdf022b188a..a8b82da0a8f0fc 100644 --- a/src/geometries/TorusKnotGeometry.js +++ b/src/geometries/TorusKnotGeometry.js @@ -146,6 +146,16 @@ class TorusKnotGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + static fromJSON( data ) { return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); diff --git a/src/geometries/TubeGeometry.js b/src/geometries/TubeGeometry.js index e02eb923da75c2..95247a0ce51197 100644 --- a/src/geometries/TubeGeometry.js +++ b/src/geometries/TubeGeometry.js @@ -163,6 +163,16 @@ class TubeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + toJSON() { const data = super.toJSON(); diff --git a/src/geometries/WireframeGeometry.js b/src/geometries/WireframeGeometry.js index 743787609c7b23..353018bfe64952 100644 --- a/src/geometries/WireframeGeometry.js +++ b/src/geometries/WireframeGeometry.js @@ -112,6 +112,16 @@ class WireframeGeometry extends BufferGeometry { } + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + } function isUniqueEdge( start, end, edges ) { diff --git a/src/helpers/Box3Helper.js b/src/helpers/Box3Helper.js index 93ef5930f50e9f..385ea8096d2f92 100644 --- a/src/helpers/Box3Helper.js +++ b/src/helpers/Box3Helper.js @@ -1,7 +1,6 @@ import { LineSegments } from '../objects/LineSegments.js'; import { LineBasicMaterial } from '../materials/LineBasicMaterial.js'; -import { BufferAttribute } from '../core/BufferAttribute.js'; -import { Float32BufferAttribute } from '../core/BufferAttribute.js'; +import { BufferAttribute, Float32BufferAttribute } from '../core/BufferAttribute.js'; import { BufferGeometry } from '../core/BufferGeometry.js'; class Box3Helper extends LineSegments { diff --git a/src/loaders/AudioLoader.js b/src/loaders/AudioLoader.js index 857394e4812f71..c62c7ed5def66a 100644 --- a/src/loaders/AudioLoader.js +++ b/src/loaders/AudioLoader.js @@ -32,25 +32,31 @@ class AudioLoader extends Loader { onLoad( audioBuffer ); - } ); + }, handleError ); } catch ( e ) { - if ( onError ) { + handleError( e ); - onError( e ); + } + + }, onProgress, onError ); - } else { + function handleError( e ) { - console.error( e ); + if ( onError ) { - } + onError( e ); - scope.manager.itemError( url ); + } else { + + console.error( e ); } - }, onProgress, onError ); + scope.manager.itemError( url ); + + } } diff --git a/src/loaders/DataTextureLoader.js b/src/loaders/DataTextureLoader.js index e584dbb9412ac8..a0cd411d65f59b 100644 --- a/src/loaders/DataTextureLoader.js +++ b/src/loaders/DataTextureLoader.js @@ -54,7 +54,11 @@ class DataTextureLoader extends Loader { texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - if ( texData.encoding !== undefined ) { + if ( texData.colorSpace !== undefined ) { + + texture.colorSpace = texData.colorSpace; + + } else if ( texData.encoding !== undefined ) { // @deprecated, r152 texture.encoding = texData.encoding; diff --git a/src/loaders/MaterialLoader.js b/src/loaders/MaterialLoader.js index 2fb13925fc1d20..3d701158841ad5 100644 --- a/src/loaders/MaterialLoader.js +++ b/src/loaders/MaterialLoader.js @@ -110,6 +110,8 @@ class MaterialLoader extends Loader { if ( json.thickness !== undefined ) material.thickness = json.thickness; if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); + if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; + if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; if ( json.fog !== undefined ) material.fog = json.fog; if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; if ( json.blending !== undefined ) material.blending = json.blending; @@ -238,6 +240,9 @@ class MaterialLoader extends Loader { } + if ( json.lights !== undefined ) material.lights = json.lights; + if ( json.clipping !== undefined ) material.clipping = json.clipping; + // for PointsMaterial if ( json.size !== undefined ) material.size = json.size; @@ -310,6 +315,8 @@ class MaterialLoader extends Loader { if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); + if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); + if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index 73fb64331134a0..33e8febe383d9f 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -296,7 +296,7 @@ class ObjectLoader extends Loader { geometry.uuid = data.uuid; if ( data.name !== undefined ) geometry.name = data.name; - if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData; + if ( data.userData !== undefined ) geometry.userData = data.userData; geometries[ data.uuid ] = geometry; @@ -638,6 +638,7 @@ class ObjectLoader extends Loader { if ( data.name !== undefined ) texture.name = data.name; if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); + if ( data.channel !== undefined ) texture.channel = data.channel; if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); @@ -652,8 +653,10 @@ class ObjectLoader extends Loader { } if ( data.format !== undefined ) texture.format = data.format; + if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; if ( data.type !== undefined ) texture.type = data.type; - if ( data.encoding !== undefined ) texture.encoding = data.encoding; + if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; + if ( data.encoding !== undefined ) texture.encoding = data.encoding; // @deprecated, r152 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); @@ -664,6 +667,7 @@ class ObjectLoader extends Loader { if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; + if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; if ( data.userData !== undefined ) texture.userData = data.userData; @@ -962,6 +966,8 @@ class ObjectLoader extends Loader { } + if ( data.up !== undefined ) object.up.fromArray( data.up ); + if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; diff --git a/src/materials/LineBasicMaterial.js b/src/materials/LineBasicMaterial.js index fe876f47979e12..b6cc7be93afff5 100644 --- a/src/materials/LineBasicMaterial.js +++ b/src/materials/LineBasicMaterial.js @@ -13,6 +13,8 @@ class LineBasicMaterial extends Material { this.color = new Color( 0xffffff ); + this.map = null; + this.linewidth = 1; this.linecap = 'round'; this.linejoin = 'round'; @@ -30,6 +32,8 @@ class LineBasicMaterial extends Material { this.color.copy( source.color ); + this.map = source.map; + this.linewidth = source.linewidth; this.linecap = source.linecap; this.linejoin = source.linejoin; diff --git a/src/materials/Material.js b/src/materials/Material.js index c3a9a82bec1717..169257d48fbb86 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -118,7 +118,7 @@ class Material extends EventDispatcher { if ( newValue === undefined ) { - console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' ); + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); continue; } @@ -127,7 +127,7 @@ class Material extends EventDispatcher { if ( currentValue === undefined ) { - console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' ); + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); continue; } @@ -165,7 +165,7 @@ class Material extends EventDispatcher { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Material', generator: 'Material.toJSON' } @@ -230,6 +230,15 @@ class Material extends EventDispatcher { } + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; + + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { + + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; + + } + if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; diff --git a/src/materials/MeshDistanceMaterial.js b/src/materials/MeshDistanceMaterial.js index 3b54005235ed3c..a12add1551f8cf 100644 --- a/src/materials/MeshDistanceMaterial.js +++ b/src/materials/MeshDistanceMaterial.js @@ -1,5 +1,4 @@ import { Material } from './Material.js'; -import { Vector3 } from '../math/Vector3.js'; class MeshDistanceMaterial extends Material { @@ -11,10 +10,6 @@ class MeshDistanceMaterial extends Material { this.type = 'MeshDistanceMaterial'; - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; - this.map = null; this.alphaMap = null; @@ -31,10 +26,6 @@ class MeshDistanceMaterial extends Material { super.copy( source ); - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; - this.map = source.map; this.alphaMap = source.alphaMap; diff --git a/src/materials/MeshPhysicalMaterial.js b/src/materials/MeshPhysicalMaterial.js index b3fb4c5d910e20..b165a493934ea9 100644 --- a/src/materials/MeshPhysicalMaterial.js +++ b/src/materials/MeshPhysicalMaterial.js @@ -20,6 +20,9 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { this.type = 'MeshPhysicalMaterial'; + this.anisotropyRotation = 0; + this.anisotropyMap = null; + this.clearcoatMap = null; this.clearcoatRoughness = 0.0; this.clearcoatRoughnessMap = null; @@ -63,30 +66,31 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { this.specularColor = new Color( 1, 1, 1 ); this.specularColorMap = null; - this._sheen = 0.0; + this._anisotropy = 0; this._clearcoat = 0; this._iridescence = 0; + this._sheen = 0.0; this._transmission = 0; this.setValues( parameters ); } - get sheen() { + get anisotropy() { - return this._sheen; + return this._anisotropy; } - set sheen( value ) { + set anisotropy( value ) { - if ( this._sheen > 0 !== value > 0 ) { + if ( this._anisotropy > 0 !== value > 0 ) { this.version ++; } - this._sheen = value; + this._anisotropy = value; } @@ -126,6 +130,24 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { } + get sheen() { + + return this._sheen; + + } + + set sheen( value ) { + + if ( this._sheen > 0 !== value > 0 ) { + + this.version ++; + + } + + this._sheen = value; + + } + get transmission() { return this._transmission; @@ -155,6 +177,10 @@ class MeshPhysicalMaterial extends MeshStandardMaterial { }; + this.anisotropy = source.anisotropy; + this.anisotropyRotation = source.anisotropyRotation; + this.anisotropyMap = source.anisotropyMap; + this.clearcoat = source.clearcoat; this.clearcoatMap = source.clearcoatMap; this.clearcoatRoughness = source.clearcoatRoughness; diff --git a/src/materials/ShaderMaterial.js b/src/materials/ShaderMaterial.js index 1a856e6a609a2d..11cafe04f44db7 100644 --- a/src/materials/ShaderMaterial.js +++ b/src/materials/ShaderMaterial.js @@ -30,6 +30,8 @@ class ShaderMaterial extends Material { this.lights = false; // set to use scene lights this.clipping = false; // set to use user-defined clipping planes + this.forceSinglePass = true; + this.extensions = { derivatives: false, // set to use derivatives fragDepth: false, // set to use fragment depth values @@ -42,7 +44,7 @@ class ShaderMaterial extends Material { this.defaultAttributeValues = { 'color': [ 1, 1, 1 ], 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] + 'uv1': [ 0, 0 ] }; this.index0AttributeName = undefined; @@ -163,6 +165,9 @@ class ShaderMaterial extends Material { data.vertexShader = this.vertexShader; data.fragmentShader = this.fragmentShader; + data.lights = this.lights; + data.clipping = this.clipping; + const extensions = {}; for ( const key in this.extensions ) { diff --git a/src/math/Box2.js b/src/math/Box2.js index 7f47e104bf1671..3a81d26521b6e6 100644 --- a/src/math/Box2.js +++ b/src/math/Box2.js @@ -160,8 +160,7 @@ class Box2 { distanceToPoint( point ) { - const clampedPoint = _vector.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector ).distanceTo( point ); } @@ -170,6 +169,8 @@ class Box2 { this.min.max( box.min ); this.max.min( box.max ); + if ( this.isEmpty() ) this.makeEmpty(); + return this; } diff --git a/src/math/Box3.js b/src/math/Box3.js index 1110d1c219102e..44863617391d43 100644 --- a/src/math/Box3.js +++ b/src/math/Box3.js @@ -22,66 +22,28 @@ class Box3 { setFromArray( array ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = array.length; i < l; i += 3 ) { - - const x = array[ i ]; - const y = array[ i + 1 ]; - const z = array[ i + 2 ]; + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = array.length; i < il; i += 3 ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector.fromArray( array, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } setFromBufferAttribute( attribute ) { - let minX = + Infinity; - let minY = + Infinity; - let minZ = + Infinity; - - let maxX = - Infinity; - let maxY = - Infinity; - let maxZ = - Infinity; - - for ( let i = 0, l = attribute.count; i < l; i ++ ) { - - const x = attribute.getX( i ); - const y = attribute.getY( i ); - const z = attribute.getZ( i ); + this.makeEmpty(); - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; + for ( let i = 0, il = attribute.count; i < il; i ++ ) { - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; + this.expandByPoint( _vector.fromBufferAttribute( attribute, i ) ); } - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - return this; } @@ -197,32 +159,49 @@ class Box3 { object.updateWorldMatrix( false, false ); - const geometry = object.geometry; + if ( object.boundingBox !== undefined ) { - if ( geometry !== undefined ) { + if ( object.boundingBox === null ) { - if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) { + object.computeBoundingBox(); - const position = geometry.attributes.position; - for ( let i = 0, l = position.count; i < l; i ++ ) { + } - _vector.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); - this.expandByPoint( _vector ); + _box.copy( object.boundingBox ); + _box.applyMatrix4( object.matrixWorld ); - } + this.union( _box ); - } else { + } else { - if ( geometry.boundingBox === null ) { + const geometry = object.geometry; - geometry.computeBoundingBox(); + if ( geometry !== undefined ) { - } + if ( precise && geometry.attributes !== undefined && geometry.attributes.position !== undefined ) { + + const position = geometry.attributes.position; + for ( let i = 0, l = position.count; i < l; i ++ ) { + + _vector.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector ); - _box.copy( geometry.boundingBox ); - _box.applyMatrix4( object.matrixWorld ); + } - this.union( _box ); + } else { + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + _box.copy( geometry.boundingBox ); + _box.applyMatrix4( object.matrixWorld ); + + this.union( _box ); + + } } @@ -396,17 +375,23 @@ class Box3 { distanceToPoint( point ) { - const clampedPoint = _vector.copy( point ).clamp( this.min, this.max ); - - return clampedPoint.sub( point ).length(); + return this.clampPoint( point, _vector ).distanceTo( point ); } getBoundingSphere( target ) { - this.getCenter( target.center ); + if ( this.isEmpty() ) { + + target.makeEmpty(); + + } else { - target.radius = this.getSize( _vector ).length() * 0.5; + this.getCenter( target.center ); + + target.radius = this.getSize( _vector ).length() * 0.5; + + } return target; diff --git a/src/math/Color.js b/src/math/Color.js index 80f8140ebd9763..1056069d575cd9 100644 --- a/src/math/Color.js +++ b/src/math/Color.js @@ -27,7 +27,6 @@ const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua' 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; -const _rgb = { r: 0, g: 0, b: 0 }; const _hslA = { h: 0, s: 0, l: 0 }; const _hslB = { h: 0, s: 0, l: 0 }; @@ -42,16 +41,6 @@ function hue2rgb( p, q, t ) { } -function toComponents( source, target ) { - - target.r = source.r; - target.g = source.g; - target.b = source.b; - - return target; - -} - class Color { constructor( r, g, b ) { @@ -62,30 +51,35 @@ class Color { this.g = 1; this.b = 1; + return this.set( r, g, b ); + + } + + set( r, g, b ) { + if ( g === undefined && b === undefined ) { // r is THREE.Color, hex or string - return this.set( r ); - } + const value = r; - return this.setRGB( r, g, b ); + if ( value && value.isColor ) { - } + this.copy( value ); - set( value ) { + } else if ( typeof value === 'number' ) { - if ( value && value.isColor ) { + this.setHex( value ); - this.copy( value ); + } else if ( typeof value === 'string' ) { - } else if ( typeof value === 'number' ) { + this.setStyle( value ); - this.setHex( value ); + } - } else if ( typeof value === 'string' ) { + } else { - this.setStyle( value ); + this.setRGB( r, g, b ); } @@ -174,7 +168,7 @@ class Color { let m; - if ( m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec( style ) ) { + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { // rgb / hsl @@ -190,30 +184,30 @@ class Color { if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; - - ColorManagement.toWorkingColorSpace( this, colorSpace ); handleAlpha( color[ 4 ] ); - return this; + return this.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); } if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; - - ColorManagement.toWorkingColorSpace( this, colorSpace ); handleAlpha( color[ 4 ] ); - return this; + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); } @@ -225,18 +219,24 @@ class Color { if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - const h = parseFloat( color[ 1 ] ) / 360; - const s = parseFloat( color[ 2 ] ) / 100; - const l = parseFloat( color[ 3 ] ) / 100; handleAlpha( color[ 4 ] ); - return this.setHSL( h, s, l, colorSpace ); + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); } break; + default: + + console.warn( 'THREE.Color: Unknown color model ' + style ); + } } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { @@ -249,30 +249,25 @@ class Color { if ( size === 3 ) { // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; - - ColorManagement.toWorkingColorSpace( this, colorSpace ); - - return this; + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); } else if ( size === 6 ) { // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; + return this.setHex( parseInt( hex, 16 ), colorSpace ); - ColorManagement.toWorkingColorSpace( this, colorSpace ); + } else { - return this; + console.warn( 'THREE.Color: Invalid hex color ' + style ); } - } - - if ( style && style.length > 0 ) { + } else if ( style && style.length > 0 ) { return this.setColorName( style, colorSpace ); @@ -357,9 +352,9 @@ class Color { getHex( colorSpace = SRGBColorSpace ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb ), colorSpace ); + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - return clamp( _rgb.r * 255, 0, 255 ) << 16 ^ clamp( _rgb.g * 255, 0, 255 ) << 8 ^ clamp( _rgb.b * 255, 0, 255 ) << 0; + return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color.b * 255, 0, 255 ) ); } @@ -373,9 +368,9 @@ class Color { // h,s,l ranges are in 0.0 - 1.0 - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb ), colorSpace ); + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - const r = _rgb.r, g = _rgb.g, b = _rgb.b; + const r = _color.r, g = _color.g, b = _color.b; const max = Math.max( r, g, b ); const min = Math.min( r, g, b ); @@ -416,11 +411,11 @@ class Color { getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb ), colorSpace ); + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); - target.r = _rgb.r; - target.g = _rgb.g; - target.b = _rgb.b; + target.r = _color.r; + target.g = _color.g; + target.b = _color.b; return target; @@ -428,16 +423,18 @@ class Color { getStyle( colorSpace = SRGBColorSpace ) { - ColorManagement.fromWorkingColorSpace( toComponents( this, _rgb ), colorSpace ); + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); + + const r = _color.r, g = _color.g, b = _color.b; if ( colorSpace !== SRGBColorSpace ) { // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). - return `color(${ colorSpace } ${ _rgb.r } ${ _rgb.g } ${ _rgb.b })`; + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; } - return `rgb(${( _rgb.r * 255 ) | 0},${( _rgb.g * 255 ) | 0},${( _rgb.b * 255 ) | 0})`; + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; } @@ -548,6 +545,29 @@ class Color { } + setFromVector3( v ) { + + this.r = v.x; + this.g = v.y; + this.b = v.z; + + return this; + + } + + applyMatrix3( m ) { + + const r = this.r, g = this.g, b = this.b; + const e = m.elements; + + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; + + return this; + + } + equals( c ) { return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); @@ -600,6 +620,8 @@ class Color { } +const _color = /*@__PURE__*/ new Color(); + Color.NAMES = _colorKeywords; -export { Color, SRGBToLinear }; +export { Color }; diff --git a/src/math/ColorManagement.js b/src/math/ColorManagement.js index e0b3f68da5a2d1..d15d3d3539c98e 100644 --- a/src/math/ColorManagement.js +++ b/src/math/ColorManagement.js @@ -1,4 +1,5 @@ -import { SRGBColorSpace, LinearSRGBColorSpace } from '../constants.js'; +import { SRGBColorSpace, LinearSRGBColorSpace, DisplayP3ColorSpace, } from '../constants.js'; +import { Matrix3 } from './Matrix3.js'; export function SRGBToLinear( c ) { @@ -12,16 +13,77 @@ export function LinearToSRGB( c ) { } -// JavaScript RGB-to-RGB transforms, defined as -// FN[InputColorSpace][OutputColorSpace] callback functions. -const FN = { - [ SRGBColorSpace ]: { [ LinearSRGBColorSpace ]: SRGBToLinear }, - [ LinearSRGBColorSpace ]: { [ SRGBColorSpace ]: LinearToSRGB }, +/** + * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + +const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().fromArray( [ + 0.8224621, 0.0331941, 0.0170827, + 0.1775380, 0.9668058, 0.0723974, + - 0.0000001, 0.0000001, 0.9105199 +] ); + +const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().fromArray( [ + 1.2249401, - 0.0420569, - 0.0196376, + - 0.2249404, 1.0420571, - 0.0786361, + 0.0000001, 0.0000000, 1.0982735 +] ); + +function DisplayP3ToLinearSRGB( color ) { + + // Display P3 uses the sRGB transfer functions + return color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ); + +} + +function LinearSRGBToDisplayP3( color ) { + + // Display P3 uses the sRGB transfer functions + return color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(); + +} + +// Conversions from to Linear-sRGB reference space. +const TO_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertSRGBToLinear(), + [ DisplayP3ColorSpace ]: DisplayP3ToLinearSRGB, +}; + +// Conversions to from Linear-sRGB reference space. +const FROM_LINEAR = { + [ LinearSRGBColorSpace ]: ( color ) => color, + [ SRGBColorSpace ]: ( color ) => color.convertLinearToSRGB(), + [ DisplayP3ColorSpace ]: LinearSRGBToDisplayP3, }; export const ColorManagement = { - legacyMode: true, + enabled: true, + + get legacyMode() { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + return ! this.enabled; + + }, + + set legacyMode( legacyMode ) { + + console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); + + this.enabled = ! legacyMode; + + }, get workingColorSpace() { @@ -37,25 +99,22 @@ export const ColorManagement = { convert: function ( color, sourceColorSpace, targetColorSpace ) { - if ( this.legacyMode || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { return color; } - if ( FN[ sourceColorSpace ] && FN[ sourceColorSpace ][ targetColorSpace ] !== undefined ) { + const sourceToLinear = TO_LINEAR[ sourceColorSpace ]; + const targetFromLinear = FROM_LINEAR[ targetColorSpace ]; - const fn = FN[ sourceColorSpace ][ targetColorSpace ]; + if ( sourceToLinear === undefined || targetFromLinear === undefined ) { - color.r = fn( color.r ); - color.g = fn( color.g ); - color.b = fn( color.b ); - - return color; + throw new Error( `Unsupported color space conversion, "${ sourceColorSpace }" to "${ targetColorSpace }".` ); } - throw new Error( 'Unsupported color space conversion.' ); + return targetFromLinear( sourceToLinear( color ) ); }, diff --git a/src/math/Frustum.js b/src/math/Frustum.js index fc6b928a31ff5b..03ab34a309f7f4 100644 --- a/src/math/Frustum.js +++ b/src/math/Frustum.js @@ -64,11 +64,21 @@ class Frustum { intersectsObject( object ) { - const geometry = object.geometry; + if ( object.boundingSphere !== undefined ) { - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + if ( object.boundingSphere === null ) object.computeBoundingSphere(); - _sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + _sphere.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } else { + + const geometry = object.geometry; + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } return this.intersectsSphere( _sphere ); diff --git a/src/math/MathUtils.js b/src/math/MathUtils.js index f64985edf8d892..e4d4448b8e7ee8 100644 --- a/src/math/MathUtils.js +++ b/src/math/MathUtils.js @@ -235,6 +235,10 @@ function denormalize( value, array ) { return value; + case Uint32Array: + + return value / 4294967295.0; + case Uint16Array: return value / 65535.0; @@ -243,6 +247,10 @@ function denormalize( value, array ) { return value / 255.0; + case Int32Array: + + return Math.max( value / 2147483647.0, - 1.0 ); + case Int16Array: return Math.max( value / 32767.0, - 1.0 ); @@ -267,6 +275,10 @@ function normalize( value, array ) { return value; + case Uint32Array: + + return Math.round( value * 4294967295.0 ); + case Uint16Array: return Math.round( value * 65535.0 ); @@ -275,6 +287,10 @@ function normalize( value, array ) { return Math.round( value * 255.0 ); + case Int32Array: + + return Math.round( value * 2147483647.0 ); + case Int16Array: return Math.round( value * 32767.0 ); @@ -291,7 +307,32 @@ function normalize( value, array ) { } - +const MathUtils = { + DEG2RAD: DEG2RAD, + RAD2DEG: RAD2DEG, + generateUUID: generateUUID, + clamp: clamp, + euclideanModulo: euclideanModulo, + mapLinear: mapLinear, + inverseLerp: inverseLerp, + lerp: lerp, + damp: damp, + pingpong: pingpong, + smoothstep: smoothstep, + smootherstep: smootherstep, + randInt: randInt, + randFloat: randFloat, + randFloatSpread: randFloatSpread, + seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, + setQuaternionFromProperEuler: setQuaternionFromProperEuler, + normalize: normalize, + denormalize: denormalize +}; export { DEG2RAD, @@ -318,4 +359,5 @@ export { setQuaternionFromProperEuler, normalize, denormalize, + MathUtils }; diff --git a/src/math/Matrix3.js b/src/math/Matrix3.js index 134b59efe9ac26..6bfb050d7f0945 100644 --- a/src/math/Matrix3.js +++ b/src/math/Matrix3.js @@ -1,6 +1,6 @@ class Matrix3 { - constructor() { + constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { Matrix3.prototype.isMatrix3 = true; @@ -12,6 +12,12 @@ class Matrix3 { ]; + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); + + } + } set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { @@ -261,13 +267,27 @@ class Matrix3 { makeTranslation( x, y ) { - this.set( + if ( x.isVector2 ) { - 1, 0, x, - 0, 1, y, - 0, 0, 1 + this.set( - ); + 1, 0, x.x, + 0, 1, x.y, + 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, x, + 0, 1, y, + 0, 0, 1 + + ); + + } return this; diff --git a/src/math/Matrix4.js b/src/math/Matrix4.js index 9b12867ca990fc..bec64aa872a1b4 100644 --- a/src/math/Matrix4.js +++ b/src/math/Matrix4.js @@ -2,7 +2,7 @@ import { Vector3 } from './Vector3.js'; class Matrix4 { - constructor() { + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { Matrix4.prototype.isMatrix4 = true; @@ -15,6 +15,12 @@ class Matrix4 { ]; + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); + + } + } set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { @@ -554,14 +560,29 @@ class Matrix4 { makeTranslation( x, y, z ) { - this.set( + if ( x.isVector3 ) { - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 + this.set( - ); + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 + + ); + + } return this; diff --git a/src/math/Plane.js b/src/math/Plane.js index 795f9173f81cb3..d8f2fd43e36232 100644 --- a/src/math/Plane.js +++ b/src/math/Plane.js @@ -101,7 +101,7 @@ class Plane { projectPoint( point, target ) { - return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); } @@ -133,7 +133,7 @@ class Plane { } - return target.copy( direction ).multiplyScalar( t ).add( line.start ); + return target.copy( line.start ).addScaledVector( direction, t ); } diff --git a/src/math/Quaternion.js b/src/math/Quaternion.js index 3d67435c32721b..77c20bf5eba1b0 100644 --- a/src/math/Quaternion.js +++ b/src/math/Quaternion.js @@ -654,6 +654,12 @@ class Quaternion { } + toJSON() { + + return this.toArray(); + + } + _onChange( callback ) { this._onChangeCallback = callback; diff --git a/src/math/Ray.js b/src/math/Ray.js index 4544c904ca6862..ed3d12059aebb4 100644 --- a/src/math/Ray.js +++ b/src/math/Ray.js @@ -38,7 +38,7 @@ class Ray { at( t, target ) { - return target.copy( this.direction ).multiplyScalar( t ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, t ); } @@ -70,7 +70,7 @@ class Ray { } - return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); } @@ -92,7 +92,7 @@ class Ray { } - _vector.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); + _vector.copy( this.origin ).addScaledVector( this.direction, directionDistance ); return _vector.distanceToSquared( point ); @@ -203,13 +203,13 @@ class Ray { if ( optionalPointOnRay ) { - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); } if ( optionalPointOnSegment ) { - optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter ); + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); } @@ -234,8 +234,8 @@ class Ray { // t1 = second intersect point - exit point on back of sphere const t1 = tca + thc; - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; // test to see if t0 is behind the ray: // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, diff --git a/src/math/Triangle.js b/src/math/Triangle.js index 617ca629d438a3..b78602571919e3 100644 --- a/src/math/Triangle.js +++ b/src/math/Triangle.js @@ -12,6 +12,8 @@ const _vap = /*@__PURE__*/ new Vector3(); const _vbp = /*@__PURE__*/ new Vector3(); const _vcp = /*@__PURE__*/ new Vector3(); +let warnedGetUV = false; + class Triangle { constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { @@ -81,14 +83,28 @@ class Triangle { } - static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { + static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { // @deprecated, r151 + + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return this.getInterpolation( point, p1, p2, p3, uv1, uv2, uv3, target ); + + } + + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { this.getBarycoord( point, p1, p2, p3, _v3 ); - target.set( 0, 0 ); - target.addScaledVector( uv1, _v3.x ); - target.addScaledVector( uv2, _v3.y ); - target.addScaledVector( uv3, _v3.z ); + target.setScalar( 0 ); + target.addScaledVector( v1, _v3.x ); + target.addScaledVector( v2, _v3.y ); + target.addScaledVector( v3, _v3.z ); return target; @@ -183,9 +199,23 @@ class Triangle { } - getUV( point, uv1, uv2, uv3, target ) { + getUV( point, uv1, uv2, uv3, target ) { // @deprecated, r151 + + if ( warnedGetUV === false ) { + + console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); + + warnedGetUV = true; + + } + + return Triangle.getInterpolation( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + + } + + getInterpolation( point, v1, v2, v3, target ) { - return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); } diff --git a/src/math/Vector2.js b/src/math/Vector2.js index d05fbe541e3c61..21c890f2e4f7aa 100644 --- a/src/math/Vector2.js +++ b/src/math/Vector2.js @@ -1,3 +1,5 @@ +import * as MathUtils from './MathUtils.js'; + class Vector2 { constructor( x = 0, y = 0 ) { @@ -353,6 +355,20 @@ class Vector2 { } + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; + + const theta = this.dot( v ) / denominator; + + // clamp, to handle numerical problems + + return Math.acos( MathUtils.clamp( theta, - 1, 1 ) ); + + } + distanceTo( v ) { return Math.sqrt( this.distanceToSquared( v ) ); diff --git a/src/math/Vector3.js b/src/math/Vector3.js index 7b18ab34046a9e..354e5b926b55e9 100644 --- a/src/math/Vector3.js +++ b/src/math/Vector3.js @@ -637,6 +637,16 @@ class Vector3 { } + setFromColor( c ) { + + this.x = c.r; + this.y = c.g; + this.z = c.b; + + return this; + + } + equals( v ) { return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); diff --git a/src/math/interpolants/CubicInterpolant.js b/src/math/interpolants/CubicInterpolant.js index 3484dbfa7c3d3f..14c9b58f0bdde6 100644 --- a/src/math/interpolants/CubicInterpolant.js +++ b/src/math/interpolants/CubicInterpolant.js @@ -1,6 +1,5 @@ -import { ZeroCurvatureEnding } from '../../constants.js'; +import { ZeroCurvatureEnding, WrapAroundEnding, ZeroSlopeEnding } from '../../constants.js'; import { Interpolant } from '../Interpolant.js'; -import { WrapAroundEnding, ZeroSlopeEnding } from '../../constants.js'; /** * Fast and simple cubic spline interpolant. diff --git a/src/objects/InstancedMesh.js b/src/objects/InstancedMesh.js index e1c842bc633b0c..c8ce16f3697f49 100644 --- a/src/objects/InstancedMesh.js +++ b/src/objects/InstancedMesh.js @@ -1,14 +1,18 @@ import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js'; import { Mesh } from './Mesh.js'; +import { Box3 } from '../math/Box3.js'; import { Matrix4 } from '../math/Matrix4.js'; +import { Sphere } from '../math/Sphere.js'; const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); const _instanceIntersects = []; +const _box3 = /*@__PURE__*/ new Box3(); const _identity = /*@__PURE__*/ new Matrix4(); const _mesh = /*@__PURE__*/ new Mesh(); +const _sphere = /*@__PURE__*/ new Sphere(); class InstancedMesh extends Mesh { @@ -23,7 +27,8 @@ class InstancedMesh extends Mesh { this.count = count; - this.frustumCulled = false; + this.boundingBox = null; + this.boundingSphere = null; for ( let i = 0; i < count; i ++ ) { @@ -33,6 +38,68 @@ class InstancedMesh extends Mesh { } + computeBoundingBox() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + this.boundingBox.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingBox.union( _box3 ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + if ( geometry.boundingSphere === null ) { + + geometry.computeBoundingSphere(); + + } + + this.boundingSphere.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _sphere.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingSphere.union( _sphere ); + + } + + } + copy( source, recursive ) { super.copy( source, recursive ); @@ -43,6 +110,9 @@ class InstancedMesh extends Mesh { this.count = source.count; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } @@ -69,6 +139,17 @@ class InstancedMesh extends Mesh { if ( _mesh.material === undefined ) return; + // test with bounding sphere first + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere.copy( this.boundingSphere ); + _sphere.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; + + // now test each instance + for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { // calculate the world matrix for each instance diff --git a/src/objects/Mesh.js b/src/objects/Mesh.js index 23d386e767d6c6..03f52902430df3 100644 --- a/src/objects/Mesh.js +++ b/src/objects/Mesh.js @@ -12,6 +12,7 @@ import { BufferGeometry } from '../core/BufferGeometry.js'; const _inverseMatrix = /*@__PURE__*/ new Matrix4(); const _ray = /*@__PURE__*/ new Ray(); const _sphere = /*@__PURE__*/ new Sphere(); +const _sphereHitAt = /*@__PURE__*/ new Vector3(); const _vA = /*@__PURE__*/ new Vector3(); const _vB = /*@__PURE__*/ new Vector3(); @@ -24,6 +25,10 @@ const _uvA = /*@__PURE__*/ new Vector2(); const _uvB = /*@__PURE__*/ new Vector2(); const _uvC = /*@__PURE__*/ new Vector2(); +const _normalA = /*@__PURE__*/ new Vector3(); +const _normalB = /*@__PURE__*/ new Vector3(); +const _normalC = /*@__PURE__*/ new Vector3(); + const _intersectionPoint = /*@__PURE__*/ new Vector3(); const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); @@ -138,12 +143,6 @@ class Mesh extends Object3D { } - if ( this.isSkinnedMesh ) { - - this.boneTransform( index, target ); - - } - return target; } @@ -156,21 +155,31 @@ class Mesh extends Object3D { if ( material === undefined ) return; - // Checking boundingSphere distance to ray + // test with bounding sphere in world space if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); _sphere.copy( geometry.boundingSphere ); _sphere.applyMatrix4( matrixWorld ); - if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; + // check distance from ray origin to bounding sphere + + _ray.copy( raycaster.ray ).recast( raycaster.near ); + + if ( _sphere.containsPoint( _ray.origin ) === false ) { - // + if ( _ray.intersectSphere( _sphere, _sphereHitAt ) === null ) return; + + if ( _ray.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; + + } + + // convert ray to local space of mesh _inverseMatrix.copy( matrixWorld ).invert(); _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); - // Check boundingBox before continuing + // test with bounding box in local space if ( geometry.boundingBox !== null ) { @@ -178,12 +187,24 @@ class Mesh extends Object3D { } + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray ); + + } + + _computeIntersections( raycaster, intersects, rayLocalSpace ) { + let intersection; + const geometry = this.geometry; + const material = this.material; + const index = geometry.index; const position = geometry.attributes.position; const uv = geometry.attributes.uv; - const uv2 = geometry.attributes.uv2; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; const groups = geometry.groups; const drawRange = geometry.drawRange; @@ -207,7 +228,7 @@ class Mesh extends Object3D { const b = index.getX( j + 1 ); const c = index.getX( j + 2 ); - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -232,7 +253,7 @@ class Mesh extends Object3D { const b = index.getX( i + 1 ); const c = index.getX( i + 2 ); - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -265,7 +286,7 @@ class Mesh extends Object3D { const b = j + 1; const c = j + 2; - intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -290,7 +311,7 @@ class Mesh extends Object3D { const b = i + 1; const c = i + 2; - intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, uv, uv2, a, b, c ); + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); if ( intersection ) { @@ -340,7 +361,7 @@ function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point } -function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, uv2, a, b, c ) { +function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { object.getVertexPosition( a, _vA ); object.getVertexPosition( b, _vB ); @@ -356,17 +377,34 @@ function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, _uvB.fromBufferAttribute( uv, b ); _uvC.fromBufferAttribute( uv, c ); - intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ); + intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ); + + } + + if ( uv1 ) { + + _uvA.fromBufferAttribute( uv1, a ); + _uvB.fromBufferAttribute( uv1, b ); + _uvC.fromBufferAttribute( uv1, c ); + + intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ); + intersection.uv2 = intersection.uv1; // @deprecated, r152 } - if ( uv2 ) { + if ( normal ) { + + _normalA.fromBufferAttribute( normal, a ); + _normalB.fromBufferAttribute( normal, b ); + _normalC.fromBufferAttribute( normal, c ); - _uvA.fromBufferAttribute( uv2, a ); - _uvB.fromBufferAttribute( uv2, b ); - _uvC.fromBufferAttribute( uv2, c ); + intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA, _vB, _vC, _normalA, _normalB, _normalC, new Vector3() ); - intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ); + if ( intersection.normal.dot( ray.direction ) > 0 ) { + + intersection.normal.multiplyScalar( - 1 ); + + } } diff --git a/src/objects/Skeleton.js b/src/objects/Skeleton.js index fd98477844d253..ee52afd2fb35a7 100644 --- a/src/objects/Skeleton.js +++ b/src/objects/Skeleton.js @@ -249,7 +249,7 @@ class Skeleton { const data = { metadata: { - version: 4.5, + version: 4.6, type: 'Skeleton', generator: 'Skeleton.toJSON' }, diff --git a/src/objects/SkinnedMesh.js b/src/objects/SkinnedMesh.js index f0a5b7b9b49812..0f86494527f0c1 100644 --- a/src/objects/SkinnedMesh.js +++ b/src/objects/SkinnedMesh.js @@ -1,15 +1,23 @@ import { Mesh } from './Mesh.js'; +import { Box3 } from '../math/Box3.js'; import { Matrix4 } from '../math/Matrix4.js'; +import { Sphere } from '../math/Sphere.js'; import { Vector3 } from '../math/Vector3.js'; import { Vector4 } from '../math/Vector4.js'; +import { Ray } from '../math/Ray.js'; const _basePosition = /*@__PURE__*/ new Vector3(); const _skinIndex = /*@__PURE__*/ new Vector4(); const _skinWeight = /*@__PURE__*/ new Vector4(); -const _vector = /*@__PURE__*/ new Vector3(); -const _matrix = /*@__PURE__*/ new Matrix4(); +const _vector3 = /*@__PURE__*/ new Vector3(); +const _matrix4 = /*@__PURE__*/ new Matrix4(); +const _vertex = /*@__PURE__*/ new Vector3(); + +const _sphere = /*@__PURE__*/ new Sphere(); +const _inverseMatrix = /*@__PURE__*/ new Matrix4(); +const _ray = /*@__PURE__*/ new Ray(); class SkinnedMesh extends Mesh { @@ -25,6 +33,57 @@ class SkinnedMesh extends Mesh { this.bindMatrix = new Matrix4(); this.bindMatrixInverse = new Matrix4(); + this.boundingBox = null; + this.boundingSphere = null; + + } + + computeBoundingBox() { + + const geometry = this.geometry; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + this.boundingBox.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + this.boundingSphere.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + _vertex.fromBufferAttribute( positionAttribute, i ); + this.applyBoneTransform( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); + + } + } copy( source, recursive ) { @@ -37,10 +96,58 @@ class SkinnedMesh extends Mesh { this.skeleton = source.skeleton; + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + return this; } + raycast( raycaster, intersects ) { + + const material = this.material; + const matrixWorld = this.matrixWorld; + + if ( material === undefined ) return; + + // test with bounding sphere in world space + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere.copy( this.boundingSphere ); + _sphere.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; + + // convert ray to local space of skinned mesh + + _inverseMatrix.copy( matrixWorld ).invert(); + _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); + + // test with bounding box in local space + + if ( this.boundingBox !== null ) { + + if ( _ray.intersectsBox( this.boundingBox ) === false ) return; + + } + + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray ); + + } + + getVertexPosition( index, target ) { + + super.getVertexPosition( index, target ); + + this.applyBoneTransform( index, target ); + + return target; + + } + bind( skeleton, bindMatrix ) { this.skeleton = skeleton; @@ -114,7 +221,7 @@ class SkinnedMesh extends Mesh { } - boneTransform( index, target ) { + applyBoneTransform( index, vector ) { const skeleton = this.skeleton; const geometry = this.geometry; @@ -122,9 +229,9 @@ class SkinnedMesh extends Mesh { _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); - _basePosition.copy( target ).applyMatrix4( this.bindMatrix ); + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); - target.set( 0, 0, 0 ); + vector.set( 0, 0, 0 ); for ( let i = 0; i < 4; i ++ ) { @@ -134,18 +241,26 @@ class SkinnedMesh extends Mesh { const boneIndex = _skinIndex.getComponent( i ); - _matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - target.addScaledVector( _vector.copy( _basePosition ).applyMatrix4( _matrix ), weight ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); } } - return target.applyMatrix4( this.bindMatrixInverse ); + return vector.applyMatrix4( this.bindMatrixInverse ); } + boneTransform( index, vector ) { // @deprecated, r151 + + console.warn( 'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' ); + return this.applyBoneTransform( index, vector ); + + } + + } export { SkinnedMesh }; diff --git a/src/objects/Sprite.js b/src/objects/Sprite.js index 8444de9712de1d..31e797811f8998 100644 --- a/src/objects/Sprite.js +++ b/src/objects/Sprite.js @@ -129,7 +129,7 @@ class Sprite extends Object3D { distance: distance, point: _intersectPoint.clone(), - uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), + uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), face: null, object: this diff --git a/src/renderers/WebGLCubeRenderTarget.js b/src/renderers/WebGLCubeRenderTarget.js index 3f22ea365f7cda..a3271ed0d76f87 100644 --- a/src/renderers/WebGLCubeRenderTarget.js +++ b/src/renderers/WebGLCubeRenderTarget.js @@ -1,4 +1,4 @@ -import { BackSide, LinearFilter, LinearMipmapLinearFilter, NoBlending } from '../constants.js'; +import { BackSide, LinearFilter, LinearMipmapLinearFilter, NoBlending, NoColorSpace, SRGBColorSpace, sRGBEncoding } from '../constants.js'; import { Mesh } from '../objects/Mesh.js'; import { BoxGeometry } from '../geometries/BoxGeometry.js'; import { ShaderMaterial } from '../materials/ShaderMaterial.js'; @@ -6,6 +6,7 @@ import { cloneUniforms } from './shaders/UniformsUtils.js'; import { WebGLRenderTarget } from './WebGLRenderTarget.js'; import { CubeCamera } from '../cameras/CubeCamera.js'; import { CubeTexture } from '../textures/CubeTexture.js'; +import { warnOnce } from '../utils.js'; class WebGLCubeRenderTarget extends WebGLRenderTarget { @@ -18,7 +19,15 @@ class WebGLCubeRenderTarget extends WebGLRenderTarget { const image = { width: size, height: size, depth: 1 }; const images = [ image, image, image, image, image, image ]; - this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( options.encoding !== undefined ) { + + // @deprecated, r152 + warnOnce( 'THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; + + } + + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, @@ -38,7 +47,7 @@ class WebGLCubeRenderTarget extends WebGLRenderTarget { fromEquirectangularTexture( renderer, texture ) { this.texture.type = texture.type; - this.texture.encoding = texture.encoding; + this.texture.colorSpace = texture.colorSpace; this.texture.generateMipmaps = texture.generateMipmaps; this.texture.minFilter = texture.minFilter; diff --git a/src/renderers/WebGLMultipleRenderTargets.js b/src/renderers/WebGLMultipleRenderTargets.js index 9d453a3337ab29..c2f289054fd301 100644 --- a/src/renderers/WebGLMultipleRenderTargets.js +++ b/src/renderers/WebGLMultipleRenderTargets.js @@ -56,8 +56,10 @@ class WebGLMultipleRenderTargets extends WebGLRenderTarget { this.height = source.height; this.depth = source.depth; - this.viewport.set( 0, 0, this.width, this.height ); - this.scissor.set( 0, 0, this.width, this.height ); + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; + + this.viewport.copy( source.viewport ); this.depthBuffer = source.depthBuffer; this.stencilBuffer = source.stencilBuffer; diff --git a/src/renderers/WebGLRenderTarget.js b/src/renderers/WebGLRenderTarget.js index a6df80e99620b1..b458a2b8f1566a 100644 --- a/src/renderers/WebGLRenderTarget.js +++ b/src/renderers/WebGLRenderTarget.js @@ -1,8 +1,9 @@ import { EventDispatcher } from '../core/EventDispatcher.js'; import { Texture } from '../textures/Texture.js'; -import { LinearFilter } from '../constants.js'; +import { LinearFilter, NoColorSpace, SRGBColorSpace, sRGBEncoding } from '../constants.js'; import { Vector4 } from '../math/Vector4.js'; import { Source } from '../textures/Source.js'; +import { warnOnce } from '../utils.js'; /* In options, we can specify: @@ -28,7 +29,15 @@ class WebGLRenderTarget extends EventDispatcher { const image = { width: width, height: height, depth: 1 }; - this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); + if ( options.encoding !== undefined ) { + + // @deprecated, r152 + warnOnce( 'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' ); + options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; + + } + + this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); this.texture.isRenderTargetTexture = true; this.texture.flipY = false; @@ -78,6 +87,9 @@ class WebGLRenderTarget extends EventDispatcher { this.height = source.height; this.depth = source.depth; + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; + this.viewport.copy( source.viewport ); this.texture = source.texture.clone(); diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 925992c40fd837..d494700cd0171c 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -7,16 +7,28 @@ import { HalfFloatType, FloatType, UnsignedByteType, - LinearEncoding, NoToneMapping, - LinearMipmapLinearFilter + LinearMipmapLinearFilter, + SRGBColorSpace, + LinearSRGBColorSpace, + sRGBEncoding, + LinearEncoding, + RGBAIntegerFormat, + RGIntegerFormat, + RedIntegerFormat, + UnsignedIntType, + UnsignedShortType, + UnsignedInt248Type, + UnsignedShort4444Type, + UnsignedShort5551Type } from '../constants.js'; -import { floorPowerOfTwo } from '../math/MathUtils.js'; +import { Color } from '../math/Color.js'; import { Frustum } from '../math/Frustum.js'; import { Matrix4 } from '../math/Matrix4.js'; import { Vector2 } from '../math/Vector2.js'; import { Vector3 } from '../math/Vector3.js'; import { Vector4 } from '../math/Vector4.js'; +import { floorPowerOfTwo } from '../math/MathUtils.js'; import { WebGLAnimation } from './webgl/WebGLAnimation.js'; import { WebGLAttributes } from './webgl/WebGLAttributes.js'; import { WebGLBackground } from './webgl/WebGLBackground.js'; @@ -55,1135 +67,1229 @@ function createCanvasElement() { } -function WebGLRenderer( parameters = {} ) { +class WebGLRenderer { - this.isWebGLRenderer = true; + constructor( parameters = {} ) { - const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(), - _context = parameters.context !== undefined ? parameters.context : null, + const { + canvas = createCanvasElement(), + context = null, + depth = true, + stencil = true, + alpha = false, + antialias = false, + premultipliedAlpha = true, + preserveDrawingBuffer = false, + powerPreference = 'default', + failIfMajorPerformanceCaveat = false, + } = parameters; - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, - _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', - _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; + this.isWebGLRenderer = true; - let _alpha; + let _alpha; - if ( _context !== null ) { + if ( context !== null ) { - _alpha = _context.getContextAttributes().alpha; + _alpha = context.getContextAttributes().alpha; - } else { + } else { - _alpha = parameters.alpha !== undefined ? parameters.alpha : false; + _alpha = alpha; - } + } - let currentRenderList = null; - let currentRenderState = null; + const uintClearColor = new Uint32Array( 4 ); + const intClearColor = new Int32Array( 4 ); - // render() can be called from within a callback triggered by another render. - // We track this so that the nested render call gets its list and state isolated from the parent render call. + let currentRenderList = null; + let currentRenderState = null; - const renderListStack = []; - const renderStateStack = []; + // render() can be called from within a callback triggered by another render. + // We track this so that the nested render call gets its list and state isolated from the parent render call. - // public properties + const renderListStack = []; + const renderStateStack = []; - this.domElement = _canvas; + // public properties - // Debug configuration container - this.debug = { + this.domElement = canvas; - /** - * Enables error checking and reporting when shader programs are being compiled - * @type {boolean} - */ - checkShaderErrors: true - }; + // Debug configuration container + this.debug = { - // clearing + /** + * Enables error checking and reporting when shader programs are being compiled + * @type {boolean} + */ + checkShaderErrors: true, + /** + * Callback for custom error reporting. + * @type {?Function} + */ + onShaderError: null + }; - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; + // clearing - // scene graph + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; - this.sortObjects = true; + // scene graph - // user-defined clipping + this.sortObjects = true; - this.clippingPlanes = []; - this.localClippingEnabled = false; + // user-defined clipping - // physically based shading + this.clippingPlanes = []; + this.localClippingEnabled = false; - this.outputEncoding = LinearEncoding; + // physically based shading - // physical lights + this.outputColorSpace = SRGBColorSpace; - this.physicallyCorrectLights = false; + // physical lights - // tone mapping + this.useLegacyLights = true; - this.toneMapping = NoToneMapping; - this.toneMappingExposure = 1.0; + // tone mapping - // internal properties + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; - const _this = this; + // internal properties - let _isContextLost = false; + const _this = this; - // internal state cache + let _isContextLost = false; - let _currentActiveCubeFace = 0; - let _currentActiveMipmapLevel = 0; - let _currentRenderTarget = null; - let _currentMaterialId = - 1; + // internal state cache - let _currentCamera = null; + let _currentActiveCubeFace = 0; + let _currentActiveMipmapLevel = 0; + let _currentRenderTarget = null; + let _currentMaterialId = - 1; - const _currentViewport = new Vector4(); - const _currentScissor = new Vector4(); - let _currentScissorTest = null; + let _currentCamera = null; - // + const _currentViewport = new Vector4(); + const _currentScissor = new Vector4(); + let _currentScissorTest = null; - let _width = _canvas.width; - let _height = _canvas.height; + const _currentClearColor = new Color( 0x000000 ); + let _currentClearAlpha = 0; - let _pixelRatio = 1; - let _opaqueSort = null; - let _transparentSort = null; + // - const _viewport = new Vector4( 0, 0, _width, _height ); - const _scissor = new Vector4( 0, 0, _width, _height ); - let _scissorTest = false; + let _width = canvas.width; + let _height = canvas.height; - // frustum + let _pixelRatio = 1; + let _opaqueSort = null; + let _transparentSort = null; - const _frustum = new Frustum(); + const _viewport = new Vector4( 0, 0, _width, _height ); + const _scissor = new Vector4( 0, 0, _width, _height ); + let _scissorTest = false; - // clipping + // frustum - let _clippingEnabled = false; - let _localClippingEnabled = false; + const _frustum = new Frustum(); - // transmission + // clipping - let _transmissionRenderTarget = null; + let _clippingEnabled = false; + let _localClippingEnabled = false; - // camera matrices cache + // transmission - const _projScreenMatrix = new Matrix4(); + let _transmissionRenderTarget = null; - const _vector2 = new Vector2(); - const _vector3 = new Vector3(); + // camera matrices cache - const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; + const _projScreenMatrix = new Matrix4(); - function getTargetPixelRatio() { + const _vector2 = new Vector2(); + const _vector3 = new Vector3(); - return _currentRenderTarget === null ? _pixelRatio : 1; + const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; - } + function getTargetPixelRatio() { - // initialize + return _currentRenderTarget === null ? _pixelRatio : 1; - let _gl = _context; + } - function getContext( contextNames, contextAttributes ) { + // initialize - for ( let i = 0; i < contextNames.length; i ++ ) { + let _gl = context; - const contextName = contextNames[ i ]; - const context = _canvas.getContext( contextName, contextAttributes ); - if ( context !== null ) return context; + function getContext( contextNames, contextAttributes ) { - } + for ( let i = 0; i < contextNames.length; i ++ ) { - return null; + const contextName = contextNames[ i ]; + const context = canvas.getContext( contextName, contextAttributes ); + if ( context !== null ) return context; - } + } - try { - - const contextAttributes = { - alpha: true, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer, - powerPreference: _powerPreference, - failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat - }; + return null; - // OffscreenCanvas does not have setAttribute, see #22811 - if ( 'setAttribute' in _canvas ) _canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); + } - // event listeners must be registered before WebGL context is created, see #12753 - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + try { + + const contextAttributes = { + alpha: true, + depth, + stencil, + antialias, + premultipliedAlpha, + preserveDrawingBuffer, + powerPreference, + failIfMajorPerformanceCaveat, + }; - if ( _gl === null ) { + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); - const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; + // event listeners must be registered before WebGL context is created, see #12753 + canvas.addEventListener( 'webglcontextlost', onContextLost, false ); + canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - if ( _this.isWebGL1Renderer === true ) { + if ( _gl === null ) { - contextNames.shift(); + const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; - } + if ( _this.isWebGL1Renderer === true ) { - _gl = getContext( contextNames, contextAttributes ); + contextNames.shift(); - if ( _gl === null ) { + } - if ( getContext( contextNames ) ) { + _gl = getContext( contextNames, contextAttributes ); - throw new Error( 'Error creating WebGL context with your selected attributes.' ); + if ( _gl === null ) { - } else { + if ( getContext( contextNames ) ) { + + throw new Error( 'Error creating WebGL context with your selected attributes.' ); - throw new Error( 'Error creating WebGL context.' ); + } else { + + throw new Error( 'Error creating WebGL context.' ); + + } } } - } + if ( _gl instanceof WebGLRenderingContext ) { // @deprecated, r153 + + console.warn( 'THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.' ); - // Some experimental-webgl implementations do not have getShaderPrecisionFormat + } - if ( _gl.getShaderPrecisionFormat === undefined ) { + // Some experimental-webgl implementations do not have getShaderPrecisionFormat - _gl.getShaderPrecisionFormat = function () { + if ( _gl.getShaderPrecisionFormat === undefined ) { - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + _gl.getShaderPrecisionFormat = function () { - }; + return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; + + }; + + } + + } catch ( error ) { + + console.error( 'THREE.WebGLRenderer: ' + error.message ); + throw error; } - } catch ( error ) { + let extensions, capabilities, state, info; + let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; + let programCache, materials, renderLists, renderStates, clipping, shadowMap; - console.error( 'THREE.WebGLRenderer: ' + error.message ); - throw error; + let background, morphtargets, bufferRenderer, indexedBufferRenderer; - } + let utils, bindingStates, uniformsGroups; - let extensions, capabilities, state, info; - let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; - let programCache, materials, renderLists, renderStates, clipping, shadowMap; + function initGLContext() { - let background, morphtargets, bufferRenderer, indexedBufferRenderer; + extensions = new WebGLExtensions( _gl ); - let utils, bindingStates, uniformsGroups; + capabilities = new WebGLCapabilities( _gl, extensions, parameters ); - function initGLContext() { + extensions.init( capabilities ); - extensions = new WebGLExtensions( _gl ); + utils = new WebGLUtils( _gl, extensions, capabilities ); - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); + state = new WebGLState( _gl, extensions, capabilities ); - extensions.init( capabilities ); + info = new WebGLInfo( _gl ); + properties = new WebGLProperties(); + textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); + cubemaps = new WebGLCubeMaps( _this ); + cubeuvmaps = new WebGLCubeUVMaps( _this ); + attributes = new WebGLAttributes( _gl, capabilities ); + bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); + geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); + objects = new WebGLObjects( _gl, geometries, attributes, info ); + morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); + clipping = new WebGLClipping( properties ); + programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); + materials = new WebGLMaterials( _this, properties ); + renderLists = new WebGLRenderLists(); + renderStates = new WebGLRenderStates( extensions, capabilities ); + background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); + shadowMap = new WebGLShadowMap( _this, objects, capabilities ); + uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); - utils = new WebGLUtils( _gl, extensions, capabilities ); + bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); + indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); - state = new WebGLState( _gl, extensions, capabilities ); + info.programs = programCache.programs; - info = new WebGLInfo( _gl ); - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); - cubemaps = new WebGLCubeMaps( _this ); - cubeuvmaps = new WebGLCubeUVMaps( _this ); - attributes = new WebGLAttributes( _gl, capabilities ); - bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); - geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); - objects = new WebGLObjects( _gl, geometries, attributes, info ); - morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); - clipping = new WebGLClipping( properties ); - programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); - materials = new WebGLMaterials( _this, properties ); - renderLists = new WebGLRenderLists(); - renderStates = new WebGLRenderStates( extensions, capabilities ); - background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, _premultipliedAlpha ); - shadowMap = new WebGLShadowMap( _this, objects, capabilities ); - uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); + _this.capabilities = capabilities; + _this.extensions = extensions; + _this.properties = properties; + _this.renderLists = renderLists; + _this.shadowMap = shadowMap; + _this.state = state; + _this.info = info; - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); + } - info.programs = programCache.programs; + initGLContext(); - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.shadowMap = shadowMap; - _this.state = state; - _this.info = info; + // xr - } + const xr = new WebXRManager( _this, _gl ); + + this.xr = xr; + + // API + + this.getContext = function () { - initGLContext(); + return _gl; - // xr + }; - const xr = new WebXRManager( _this, _gl ); + this.getContextAttributes = function () { - this.xr = xr; + return _gl.getContextAttributes(); - // API + }; - this.getContext = function () { + this.forceContextLoss = function () { - return _gl; + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.loseContext(); - }; + }; - this.getContextAttributes = function () { + this.forceContextRestore = function () { - return _gl.getContextAttributes(); + const extension = extensions.get( 'WEBGL_lose_context' ); + if ( extension ) extension.restoreContext(); - }; + }; - this.forceContextLoss = function () { + this.getPixelRatio = function () { - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.loseContext(); + return _pixelRatio; - }; + }; - this.forceContextRestore = function () { + this.setPixelRatio = function ( value ) { - const extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.restoreContext(); + if ( value === undefined ) return; - }; + _pixelRatio = value; - this.getPixelRatio = function () { + this.setSize( _width, _height, false ); - return _pixelRatio; + }; - }; + this.getSize = function ( target ) { - this.setPixelRatio = function ( value ) { + return target.set( _width, _height ); - if ( value === undefined ) return; + }; - _pixelRatio = value; + this.setSize = function ( width, height, updateStyle = true ) { - this.setSize( _width, _height, false ); + if ( xr.isPresenting ) { - }; + console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); + return; - this.getSize = function ( target ) { + } - return target.set( _width, _height ); + _width = width; + _height = height; - }; + canvas.width = Math.floor( width * _pixelRatio ); + canvas.height = Math.floor( height * _pixelRatio ); - this.setSize = function ( width, height, updateStyle ) { + if ( updateStyle === true ) { - if ( xr.isPresenting ) { + canvas.style.width = width + 'px'; + canvas.style.height = height + 'px'; - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; + } - } + this.setViewport( 0, 0, width, height ); - _width = width; - _height = height; + }; - _canvas.width = Math.floor( width * _pixelRatio ); - _canvas.height = Math.floor( height * _pixelRatio ); + this.getDrawingBufferSize = function ( target ) { - if ( updateStyle !== false ) { + return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; + }; - } + this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - this.setViewport( 0, 0, width, height ); + _width = width; + _height = height; - }; + _pixelRatio = pixelRatio; - this.getDrawingBufferSize = function ( target ) { + canvas.width = Math.floor( width * pixelRatio ); + canvas.height = Math.floor( height * pixelRatio ); - return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); + this.setViewport( 0, 0, width, height ); - }; + }; - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { + this.getCurrentViewport = function ( target ) { - _width = width; - _height = height; + return target.copy( _currentViewport ); - _pixelRatio = pixelRatio; + }; - _canvas.width = Math.floor( width * pixelRatio ); - _canvas.height = Math.floor( height * pixelRatio ); + this.getViewport = function ( target ) { - this.setViewport( 0, 0, width, height ); + return target.copy( _viewport ); - }; + }; - this.getCurrentViewport = function ( target ) { + this.setViewport = function ( x, y, width, height ) { - return target.copy( _currentViewport ); + if ( x.isVector4 ) { - }; + _viewport.set( x.x, x.y, x.z, x.w ); - this.getViewport = function ( target ) { + } else { - return target.copy( _viewport ); + _viewport.set( x, y, width, height ); - }; + } - this.setViewport = function ( x, y, width, height ) { + state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); - if ( x.isVector4 ) { + }; - _viewport.set( x.x, x.y, x.z, x.w ); + this.getScissor = function ( target ) { - } else { + return target.copy( _scissor ); - _viewport.set( x, y, width, height ); + }; - } + this.setScissor = function ( x, y, width, height ) { - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); + if ( x.isVector4 ) { - }; + _scissor.set( x.x, x.y, x.z, x.w ); - this.getScissor = function ( target ) { + } else { - return target.copy( _scissor ); + _scissor.set( x, y, width, height ); - }; + } - this.setScissor = function ( x, y, width, height ) { + state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); - if ( x.isVector4 ) { + }; - _scissor.set( x.x, x.y, x.z, x.w ); + this.getScissorTest = function () { - } else { + return _scissorTest; - _scissor.set( x, y, width, height ); + }; - } + this.setScissorTest = function ( boolean ) { - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); + state.setScissorTest( _scissorTest = boolean ); - }; + }; - this.getScissorTest = function () { + this.setOpaqueSort = function ( method ) { - return _scissorTest; + _opaqueSort = method; - }; + }; - this.setScissorTest = function ( boolean ) { + this.setTransparentSort = function ( method ) { - state.setScissorTest( _scissorTest = boolean ); + _transparentSort = method; - }; + }; - this.setOpaqueSort = function ( method ) { + // Clearing - _opaqueSort = method; + this.getClearColor = function ( target ) { - }; + return target.copy( background.getClearColor() ); - this.setTransparentSort = function ( method ) { + }; - _transparentSort = method; + this.setClearColor = function () { - }; + background.setClearColor.apply( background, arguments ); - // Clearing + }; - this.getClearColor = function ( target ) { + this.getClearAlpha = function () { - return target.copy( background.getClearColor() ); + return background.getClearAlpha(); - }; + }; - this.setClearColor = function () { + this.setClearAlpha = function () { - background.setClearColor.apply( background, arguments ); + background.setClearAlpha.apply( background, arguments ); - }; + }; - this.getClearAlpha = function () { + this.clear = function ( color = true, depth = true, stencil = true ) { - return background.getClearAlpha(); + let bits = 0; - }; + if ( color ) { - this.setClearAlpha = function () { + // check if we're trying to clear an integer target + let isIntegerFormat = false; + if ( _currentRenderTarget !== null ) { - background.setClearAlpha.apply( background, arguments ); + const targetFormat = _currentRenderTarget.texture.format; + isIntegerFormat = targetFormat === RGBAIntegerFormat || + targetFormat === RGIntegerFormat || + targetFormat === RedIntegerFormat; - }; + } - this.clear = function ( color = true, depth = true, stencil = true ) { + // use the appropriate clear functions to clear the target if it's a signed + // or unsigned integer target + if ( isIntegerFormat ) { - let bits = 0; + const targetType = _currentRenderTarget.texture.type; + const isUnsignedType = targetType === UnsignedByteType || + targetType === UnsignedIntType || + targetType === UnsignedShortType || + targetType === UnsignedInt248Type || + targetType === UnsignedShort4444Type || + targetType === UnsignedShort5551Type; - if ( color ) bits |= _gl.COLOR_BUFFER_BIT; - if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; - if ( stencil ) bits |= _gl.STENCIL_BUFFER_BIT; + const clearColor = background.getClearColor(); + const a = background.getClearAlpha(); + const r = clearColor.r; + const g = clearColor.g; + const b = clearColor.b; - _gl.clear( bits ); + const __webglFramebuffer = properties.get( _currentRenderTarget ).__webglFramebuffer; - }; + if ( isUnsignedType ) { - this.clearColor = function () { + uintClearColor[ 0 ] = r; + uintClearColor[ 1 ] = g; + uintClearColor[ 2 ] = b; + uintClearColor[ 3 ] = a; + _gl.clearBufferuiv( _gl.COLOR, __webglFramebuffer, uintClearColor ); - this.clear( true, false, false ); + } else { - }; + intClearColor[ 0 ] = r; + intClearColor[ 1 ] = g; + intClearColor[ 2 ] = b; + intClearColor[ 3 ] = a; + _gl.clearBufferiv( _gl.COLOR, __webglFramebuffer, intClearColor ); - this.clearDepth = function () { + } - this.clear( false, true, false ); + } else { - }; + bits |= _gl.COLOR_BUFFER_BIT; - this.clearStencil = function () { + } - this.clear( false, false, true ); + } - }; + if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( stencil ) bits |= _gl.STENCIL_BUFFER_BIT; - // + _gl.clear( bits ); - this.dispose = function () { + }; - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); - _canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); + this.clearColor = function () { - renderLists.dispose(); - renderStates.dispose(); - properties.dispose(); - cubemaps.dispose(); - cubeuvmaps.dispose(); - objects.dispose(); - bindingStates.dispose(); - uniformsGroups.dispose(); - programCache.dispose(); + this.clear( true, false, false ); - xr.dispose(); + }; - xr.removeEventListener( 'sessionstart', onXRSessionStart ); - xr.removeEventListener( 'sessionend', onXRSessionEnd ); + this.clearDepth = function () { - if ( _transmissionRenderTarget ) { + this.clear( false, true, false ); - _transmissionRenderTarget.dispose(); - _transmissionRenderTarget = null; + }; - } + this.clearStencil = function () { - animation.stop(); + this.clear( false, false, true ); - }; + }; - // Events + // - function onContextLost( event ) { + this.dispose = function () { - event.preventDefault(); + canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); + canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); - console.log( 'THREE.WebGLRenderer: Context Lost.' ); + renderLists.dispose(); + renderStates.dispose(); + properties.dispose(); + cubemaps.dispose(); + cubeuvmaps.dispose(); + objects.dispose(); + bindingStates.dispose(); + uniformsGroups.dispose(); + programCache.dispose(); - _isContextLost = true; + xr.dispose(); - } + xr.removeEventListener( 'sessionstart', onXRSessionStart ); + xr.removeEventListener( 'sessionend', onXRSessionEnd ); - function onContextRestore( /* event */ ) { + if ( _transmissionRenderTarget ) { - console.log( 'THREE.WebGLRenderer: Context Restored.' ); + _transmissionRenderTarget.dispose(); + _transmissionRenderTarget = null; - _isContextLost = false; + } - const infoAutoReset = info.autoReset; - const shadowMapEnabled = shadowMap.enabled; - const shadowMapAutoUpdate = shadowMap.autoUpdate; - const shadowMapNeedsUpdate = shadowMap.needsUpdate; - const shadowMapType = shadowMap.type; + animation.stop(); - initGLContext(); + }; - info.autoReset = infoAutoReset; - shadowMap.enabled = shadowMapEnabled; - shadowMap.autoUpdate = shadowMapAutoUpdate; - shadowMap.needsUpdate = shadowMapNeedsUpdate; - shadowMap.type = shadowMapType; + // Events - } + function onContextLost( event ) { - function onContextCreationError( event ) { + event.preventDefault(); - console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); + console.log( 'THREE.WebGLRenderer: Context Lost.' ); - } + _isContextLost = true; - function onMaterialDispose( event ) { + } - const material = event.target; + function onContextRestore( /* event */ ) { - material.removeEventListener( 'dispose', onMaterialDispose ); + console.log( 'THREE.WebGLRenderer: Context Restored.' ); - deallocateMaterial( material ); + _isContextLost = false; - } + const infoAutoReset = info.autoReset; + const shadowMapEnabled = shadowMap.enabled; + const shadowMapAutoUpdate = shadowMap.autoUpdate; + const shadowMapNeedsUpdate = shadowMap.needsUpdate; + const shadowMapType = shadowMap.type; - // Buffer deallocation + initGLContext(); - function deallocateMaterial( material ) { + info.autoReset = infoAutoReset; + shadowMap.enabled = shadowMapEnabled; + shadowMap.autoUpdate = shadowMapAutoUpdate; + shadowMap.needsUpdate = shadowMapNeedsUpdate; + shadowMap.type = shadowMapType; - releaseMaterialProgramReferences( material ); + } - properties.remove( material ); + function onContextCreationError( event ) { - } + console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); + } - function releaseMaterialProgramReferences( material ) { + function onMaterialDispose( event ) { - const programs = properties.get( material ).programs; + const material = event.target; - if ( programs !== undefined ) { + material.removeEventListener( 'dispose', onMaterialDispose ); - programs.forEach( function ( program ) { + deallocateMaterial( material ); - programCache.releaseProgram( program ); + } - } ); + // Buffer deallocation - if ( material.isShaderMaterial ) { + function deallocateMaterial( material ) { - programCache.releaseShaderCache( material ); + releaseMaterialProgramReferences( material ); - } + properties.remove( material ); } - } - // Buffer rendering + function releaseMaterialProgramReferences( material ) { - this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { + const programs = properties.get( material ).programs; - if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) + if ( programs !== undefined ) { - const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + programs.forEach( function ( program ) { - const program = setProgram( camera, scene, geometry, material, object ); + programCache.releaseProgram( program ); - state.setMaterial( material, frontFaceCW ); + } ); - // + if ( material.isShaderMaterial ) { - let index = geometry.index; - let rangeFactor = 1; + programCache.releaseShaderCache( material ); - if ( material.wireframe === true ) { + } - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; + } } - // + // Buffer rendering - const drawRange = geometry.drawRange; - const position = geometry.attributes.position; + this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { - let drawStart = drawRange.start * rangeFactor; - let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; + if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) - if ( group !== null ) { + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); - drawStart = Math.max( drawStart, group.start * rangeFactor ); - drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); + const program = setProgram( camera, scene, geometry, material, object ); - } + state.setMaterial( material, frontFaceCW ); - if ( index !== null ) { + // - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, index.count ); + let index = geometry.index; + let rangeFactor = 1; - } else if ( position !== undefined && position !== null ) { + if ( material.wireframe === true ) { - drawStart = Math.max( drawStart, 0 ); - drawEnd = Math.min( drawEnd, position.count ); + index = geometries.getWireframeAttribute( geometry ); + rangeFactor = 2; - } + } - const drawCount = drawEnd - drawStart; + // - if ( drawCount < 0 || drawCount === Infinity ) return; + const drawRange = geometry.drawRange; + const position = geometry.attributes.position; - // + let drawStart = drawRange.start * rangeFactor; + let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; - bindingStates.setup( object, material, program, geometry, index ); + if ( group !== null ) { - let attribute; - let renderer = bufferRenderer; + drawStart = Math.max( drawStart, group.start * rangeFactor ); + drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); - if ( index !== null ) { + } - attribute = attributes.get( index ); + if ( index !== null ) { - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, index.count ); - } + } else if ( position !== undefined && position !== null ) { - // + drawStart = Math.max( drawStart, 0 ); + drawEnd = Math.min( drawEnd, position.count ); - if ( object.isMesh ) { + } - if ( material.wireframe === true ) { + const drawCount = drawEnd - drawStart; - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( _gl.LINES ); + if ( drawCount < 0 || drawCount === Infinity ) return; - } else { + // - renderer.setMode( _gl.TRIANGLES ); + bindingStates.setup( object, material, program, geometry, index ); - } + let attribute; + let renderer = bufferRenderer; - } else if ( object.isLine ) { + if ( index !== null ) { - let lineWidth = material.linewidth; + attribute = attributes.get( index ); - if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material + renderer = indexedBufferRenderer; + renderer.setIndex( attribute ); - state.setLineWidth( lineWidth * getTargetPixelRatio() ); + } - if ( object.isLineSegments ) { + // - renderer.setMode( _gl.LINES ); + if ( object.isMesh ) { - } else if ( object.isLineLoop ) { + if ( material.wireframe === true ) { - renderer.setMode( _gl.LINE_LOOP ); + state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); + renderer.setMode( _gl.LINES ); - } else { + } else { - renderer.setMode( _gl.LINE_STRIP ); + renderer.setMode( _gl.TRIANGLES ); - } + } - } else if ( object.isPoints ) { + } else if ( object.isLine ) { - renderer.setMode( _gl.POINTS ); + let lineWidth = material.linewidth; - } else if ( object.isSprite ) { + if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - renderer.setMode( _gl.TRIANGLES ); + state.setLineWidth( lineWidth * getTargetPixelRatio() ); - } + if ( object.isLineSegments ) { - if ( object.isInstancedMesh ) { + renderer.setMode( _gl.LINES ); - renderer.renderInstances( drawStart, drawCount, object.count ); + } else if ( object.isLineLoop ) { - } else if ( geometry.isInstancedBufferGeometry ) { + renderer.setMode( _gl.LINE_LOOP ); - const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; - const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); + } else { - renderer.renderInstances( drawStart, drawCount, instanceCount ); + renderer.setMode( _gl.LINE_STRIP ); - } else { + } - renderer.render( drawStart, drawCount ); + } else if ( object.isPoints ) { - } + renderer.setMode( _gl.POINTS ); - }; + } else if ( object.isSprite ) { - // Compile + renderer.setMode( _gl.TRIANGLES ); - this.compile = function ( scene, camera ) { + } - function prepare( material, scene, object ) { + if ( object.isInstancedMesh ) { - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + renderer.renderInstances( drawStart, drawCount, object.count ); - material.side = BackSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + } else if ( geometry.isInstancedBufferGeometry ) { - material.side = FrontSide; - material.needsUpdate = true; - getProgram( material, scene, object ); + const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; + const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); - material.side = DoubleSide; + renderer.renderInstances( drawStart, drawCount, instanceCount ); } else { - getProgram( material, scene, object ); + renderer.render( drawStart, drawCount ); } - } + }; + + // Compile - currentRenderState = renderStates.get( scene ); - currentRenderState.init(); + this.compile = function ( scene, camera ) { - renderStateStack.push( currentRenderState ); + function prepare( material, scene, object ) { - scene.traverseVisible( function ( object ) { + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - if ( object.isLight && object.layers.test( camera.layers ) ) { + material.side = BackSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - currentRenderState.pushLight( object ); + material.side = FrontSide; + material.needsUpdate = true; + getProgram( material, scene, object ); - if ( object.castShadow ) { + material.side = DoubleSide; + + } else { - currentRenderState.pushShadow( object ); + getProgram( material, scene, object ); } } - } ); + currentRenderState = renderStates.get( scene ); + currentRenderState.init(); - currentRenderState.setupLights( _this.physicallyCorrectLights ); + renderStateStack.push( currentRenderState ); - scene.traverse( function ( object ) { + scene.traverseVisible( function ( object ) { - const material = object.material; + if ( object.isLight && object.layers.test( camera.layers ) ) { - if ( material ) { + currentRenderState.pushLight( object ); - if ( Array.isArray( material ) ) { + if ( object.castShadow ) { - for ( let i = 0; i < material.length; i ++ ) { + currentRenderState.pushShadow( object ); - const material2 = material[ i ]; + } - prepare( material2, scene, object ); + } - } + } ); - } else { + currentRenderState.setupLights( _this.useLegacyLights ); - prepare( material, scene, object ); + scene.traverse( function ( object ) { - } + const material = object.material; - } + if ( material ) { - } ); + if ( Array.isArray( material ) ) { - renderStateStack.pop(); - currentRenderState = null; + for ( let i = 0; i < material.length; i ++ ) { - }; + const material2 = material[ i ]; - // Animation Loop + prepare( material2, scene, object ); - let onAnimationFrameCallback = null; + } - function onAnimationFrame( time ) { + } else { - if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); + prepare( material, scene, object ); - } + } - function onXRSessionStart() { + } - animation.stop(); + } ); - } + renderStateStack.pop(); + currentRenderState = null; - function onXRSessionEnd() { + }; - animation.start(); + // Animation Loop - } + let onAnimationFrameCallback = null; - const animation = new WebGLAnimation(); - animation.setAnimationLoop( onAnimationFrame ); + function onAnimationFrame( time ) { - if ( typeof self !== 'undefined' ) animation.setContext( self ); + if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); - this.setAnimationLoop = function ( callback ) { + } - onAnimationFrameCallback = callback; - xr.setAnimationLoop( callback ); + function onXRSessionStart() { - ( callback === null ) ? animation.stop() : animation.start(); + animation.stop(); - }; + } - xr.addEventListener( 'sessionstart', onXRSessionStart ); - xr.addEventListener( 'sessionend', onXRSessionEnd ); + function onXRSessionEnd() { - // Rendering + animation.start(); - this.render = function ( scene, camera ) { + } - if ( camera !== undefined && camera.isCamera !== true ) { + const animation = new WebGLAnimation(); + animation.setAnimationLoop( onAnimationFrame ); - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; + if ( typeof self !== 'undefined' ) animation.setContext( self ); - } + this.setAnimationLoop = function ( callback ) { - if ( _isContextLost === true ) return; + onAnimationFrameCallback = callback; + xr.setAnimationLoop( callback ); - // update scene graph + ( callback === null ) ? animation.stop() : animation.start(); - if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); + }; - // update camera matrices and frustum + xr.addEventListener( 'sessionstart', onXRSessionStart ); + xr.addEventListener( 'sessionend', onXRSessionEnd ); - if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); + // Rendering - if ( xr.enabled === true && xr.isPresenting === true ) { + this.render = function ( scene, camera ) { - if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); + if ( camera !== undefined && camera.isCamera !== true ) { - camera = xr.getCamera(); // use XR camera for rendering + console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); + return; - } + } - // - if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); + if ( _isContextLost === true ) return; - currentRenderState = renderStates.get( scene, renderStateStack.length ); - currentRenderState.init(); + // update scene graph - renderStateStack.push( currentRenderState ); + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromProjectionMatrix( _projScreenMatrix ); + // update camera matrices and frustum - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - currentRenderList = renderLists.get( scene, renderListStack.length ); - currentRenderList.init(); + if ( xr.enabled === true && xr.isPresenting === true ) { - renderListStack.push( currentRenderList ); + camera = xr.updateCameraXR( camera ); // use XR camera for rendering - projectObject( scene, camera, 0, _this.sortObjects ); + } - currentRenderList.finish(); + // + if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); - if ( _this.sortObjects === true ) { + currentRenderState = renderStates.get( scene, renderStateStack.length ); + currentRenderState.init(); - currentRenderList.sort( _opaqueSort, _transparentSort ); + renderStateStack.push( currentRenderState ); - } + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix ); - // + _localClippingEnabled = this.localClippingEnabled; + _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); - if ( _clippingEnabled === true ) clipping.beginShadows(); + currentRenderList = renderLists.get( scene, renderListStack.length ); + currentRenderList.init(); - const shadowsArray = currentRenderState.state.shadowsArray; + renderListStack.push( currentRenderList ); - shadowMap.render( shadowsArray, scene, camera ); + projectObject( scene, camera, 0, _this.sortObjects ); - if ( _clippingEnabled === true ) clipping.endShadows(); + currentRenderList.finish(); - // + if ( _this.sortObjects === true ) { - if ( this.info.autoReset === true ) this.info.reset(); + currentRenderList.sort( _opaqueSort, _transparentSort ); - // + } - background.render( currentRenderList, scene ); + // - // render scene + if ( _clippingEnabled === true ) clipping.beginShadows(); - currentRenderState.setupLights( _this.physicallyCorrectLights ); + const shadowsArray = currentRenderState.state.shadowsArray; - if ( camera.isArrayCamera ) { + shadowMap.render( shadowsArray, scene, camera ); - const cameras = camera.cameras; + if ( _clippingEnabled === true ) clipping.endShadows(); - for ( let i = 0, l = cameras.length; i < l; i ++ ) { + // - const camera2 = cameras[ i ]; + if ( this.info.autoReset === true ) this.info.reset(); - renderScene( currentRenderList, scene, camera2, camera2.viewport ); + this.info.render.frame ++; - } + // - } else { + background.render( currentRenderList, scene ); - renderScene( currentRenderList, scene, camera ); + // render scene - } + currentRenderState.setupLights( _this.useLegacyLights ); - // + if ( camera.isArrayCamera ) { - if ( _currentRenderTarget !== null ) { + const cameras = camera.cameras; - // resolve multisample renderbuffers to a single-sample texture if necessary + for ( let i = 0, l = cameras.length; i < l; i ++ ) { - textures.updateMultisampleRenderTarget( _currentRenderTarget ); + const camera2 = cameras[ i ]; - // Generate mipmap if we're using any kind of mipmap filtering + renderScene( currentRenderList, scene, camera2, camera2.viewport ); - textures.updateRenderTargetMipmap( _currentRenderTarget ); + } - } + } else { - // + renderScene( currentRenderList, scene, camera ); - if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); + } - // _gl.finish(); + // - bindingStates.resetDefaultState(); - _currentMaterialId = - 1; - _currentCamera = null; + if ( _currentRenderTarget !== null ) { - renderStateStack.pop(); + // resolve multisample renderbuffers to a single-sample texture if necessary - if ( renderStateStack.length > 0 ) { + textures.updateMultisampleRenderTarget( _currentRenderTarget ); - currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; + // Generate mipmap if we're using any kind of mipmap filtering - } else { + textures.updateRenderTargetMipmap( _currentRenderTarget ); - currentRenderState = null; + } - } + // - renderListStack.pop(); + if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); - if ( renderListStack.length > 0 ) { + // _gl.finish(); - currentRenderList = renderListStack[ renderListStack.length - 1 ]; + bindingStates.resetDefaultState(); + _currentMaterialId = - 1; + _currentCamera = null; - } else { + renderStateStack.pop(); - currentRenderList = null; + if ( renderStateStack.length > 0 ) { - } + currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; - }; + } else { - function projectObject( object, camera, groupOrder, sortObjects ) { + currentRenderState = null; - if ( object.visible === false ) return; + } - const visible = object.layers.test( camera.layers ); + renderListStack.pop(); - if ( visible ) { + if ( renderListStack.length > 0 ) { - if ( object.isGroup ) { + currentRenderList = renderListStack[ renderListStack.length - 1 ]; - groupOrder = object.renderOrder; + } else { - } else if ( object.isLOD ) { + currentRenderList = null; - if ( object.autoUpdate === true ) object.update( camera ); + } - } else if ( object.isLight ) { + }; - currentRenderState.pushLight( object ); + function projectObject( object, camera, groupOrder, sortObjects ) { - if ( object.castShadow ) { + if ( object.visible === false ) return; - currentRenderState.pushShadow( object ); + const visible = object.layers.test( camera.layers ); - } + if ( visible ) { - } else if ( object.isSprite ) { + if ( object.isGroup ) { - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + groupOrder = object.renderOrder; - if ( sortObjects ) { + } else if ( object.isLOD ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + if ( object.autoUpdate === true ) object.update( camera ); - } + } else if ( object.isLight ) { - const geometry = objects.update( object ); - const material = object.material; + currentRenderState.pushLight( object ); - if ( material.visible ) { + if ( object.castShadow ) { - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + currentRenderState.pushShadow( object ); } - } + } else if ( object.isSprite ) { + + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - } else if ( object.isMesh || object.isLine || object.isPoints ) { + if ( sortObjects ) { + + _vector3.setFromMatrixPosition( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); + + } - if ( object.isSkinnedMesh ) { + const geometry = objects.update( object ); + const material = object.material; - // update skeleton only once in a frame + if ( material.visible ) { - if ( object.skeleton.frame !== info.render.frame ) { + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); - object.skeleton.update(); - object.skeleton.frame = info.render.frame; + } } - } + } else if ( object.isMesh || object.isLine || object.isPoints ) { - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - if ( sortObjects ) { + if ( object.isSkinnedMesh ) { - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); + // update skeleton only once in a frame - } + if ( object.skeleton.frame !== info.render.frame ) { - const geometry = objects.update( object ); - const material = object.material; + object.skeleton.update(); + object.skeleton.frame = info.render.frame; - if ( Array.isArray( material ) ) { + } + + } - const groups = geometry.groups; + const geometry = objects.update( object ); + const material = object.material; - for ( let i = 0, l = groups.length; i < l; i ++ ) { + if ( sortObjects ) { - const group = groups[ i ]; - const groupMaterial = material[ group.materialIndex ]; + if ( object.boundingSphere !== undefined ) { - if ( groupMaterial && groupMaterial.visible ) { + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + _vector3.copy( object.boundingSphere.center ); - currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); + } else { + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + _vector3.copy( geometry.boundingSphere.center ); } + _vector3 + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); + } - } else if ( material.visible ) { + if ( Array.isArray( material ) ) { + + const groups = geometry.groups; + + for ( let i = 0, l = groups.length; i < l; i ++ ) { + + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; + + if ( groupMaterial && groupMaterial.visible ) { + + currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); - currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + } + + } + + } else if ( material.visible ) { + + currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + + } } @@ -1191,1073 +1297,1148 @@ function WebGLRenderer( parameters = {} ) { } - } + const children = object.children; - const children = object.children; + for ( let i = 0, l = children.length; i < l; i ++ ) { - for ( let i = 0, l = children.length; i < l; i ++ ) { + projectObject( children[ i ], camera, groupOrder, sortObjects ); - projectObject( children[ i ], camera, groupOrder, sortObjects ); + } } - } + function renderScene( currentRenderList, scene, camera, viewport ) { - function renderScene( currentRenderList, scene, camera, viewport ) { + const opaqueObjects = currentRenderList.opaque; + const transmissiveObjects = currentRenderList.transmissive; + const transparentObjects = currentRenderList.transparent; - const opaqueObjects = currentRenderList.opaque; - const transmissiveObjects = currentRenderList.transmissive; - const transparentObjects = currentRenderList.transparent; + currentRenderState.setupLightsView( camera ); - currentRenderState.setupLightsView( camera ); + if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); - if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); + if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); - if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, scene, camera ); + if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); - if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); + if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); + if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); + if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); - if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); - if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); - if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); + // Ensure depth buffer writing is enabled so it can be cleared on next render - // Ensure depth buffer writing is enabled so it can be cleared on next render + state.buffers.depth.setTest( true ); + state.buffers.depth.setMask( true ); + state.buffers.color.setMask( true ); - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); + state.setPolygonOffset( false ); - state.setPolygonOffset( false ); + } - } + function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { - function renderTransmissionPass( opaqueObjects, scene, camera ) { + const isWebGL2 = capabilities.isWebGL2; - const isWebGL2 = capabilities.isWebGL2; + if ( _transmissionRenderTarget === null ) { - if ( _transmissionRenderTarget === null ) { + _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { + generateMipmaps: true, + type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, + minFilter: LinearMipmapLinearFilter, + samples: ( isWebGL2 && antialias === true ) ? 4 : 0 + } ); - _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { - generateMipmaps: true, - type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, - minFilter: LinearMipmapLinearFilter, - samples: ( isWebGL2 && _antialias === true ) ? 4 : 0 - } ); + // debug - } + /* + const geometry = new PlaneGeometry(); + const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); - _this.getDrawingBufferSize( _vector2 ); + const mesh = new Mesh( geometry, material ); + scene.add( mesh ); + */ - if ( isWebGL2 ) { + } - _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); + _this.getDrawingBufferSize( _vector2 ); - } else { + if ( isWebGL2 ) { - _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); + _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); - } + } else { - // + _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); - const currentRenderTarget = _this.getRenderTarget(); - _this.setRenderTarget( _transmissionRenderTarget ); - _this.clear(); + } - // Turn off the features which can affect the frag color for opaque objects pass. - // Otherwise they are applied twice in opaque objects pass and transmission objects pass. - const currentToneMapping = _this.toneMapping; - _this.toneMapping = NoToneMapping; + // - renderObjects( opaqueObjects, scene, camera ); + const currentRenderTarget = _this.getRenderTarget(); + _this.setRenderTarget( _transmissionRenderTarget ); - _this.toneMapping = currentToneMapping; + _this.getClearColor( _currentClearColor ); + _currentClearAlpha = _this.getClearAlpha(); + if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); - textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); - textures.updateRenderTargetMipmap( _transmissionRenderTarget ); + _this.clear(); - _this.setRenderTarget( currentRenderTarget ); + // Turn off the features which can affect the frag color for opaque objects pass. + // Otherwise they are applied twice in opaque objects pass and transmission objects pass. + const currentToneMapping = _this.toneMapping; + _this.toneMapping = NoToneMapping; - } + renderObjects( opaqueObjects, scene, camera ); - function renderObjects( renderList, scene, camera ) { + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; + let renderTargetNeedsUpdate = false; - for ( let i = 0, l = renderList.length; i < l; i ++ ) { + for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { - const renderItem = renderList[ i ]; + const renderItem = transmissiveObjects[ i ]; - const object = renderItem.object; - const geometry = renderItem.geometry; - const material = overrideMaterial === null ? renderItem.material : overrideMaterial; - const group = renderItem.group; + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = renderItem.material; + const group = renderItem.group; - if ( object.layers.test( camera.layers ) ) { + if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { - renderObject( object, scene, camera, geometry, material, group ); + const currentSide = material.side; + + material.side = BackSide; + material.needsUpdate = true; + + renderObject( object, scene, camera, geometry, material, group ); + + material.side = currentSide; + material.needsUpdate = true; + + renderTargetNeedsUpdate = true; + + } } - } + if ( renderTargetNeedsUpdate === true ) { - } + textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); + textures.updateRenderTargetMipmap( _transmissionRenderTarget ); - function renderObject( object, scene, camera, geometry, material, group ) { + } - object.onBeforeRender( _this, scene, camera, geometry, material, group ); + _this.setRenderTarget( currentRenderTarget ); - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + _this.setClearColor( _currentClearColor, _currentClearAlpha ); - material.onBeforeRender( _this, scene, camera, geometry, object, group ); + _this.toneMapping = currentToneMapping; - if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + } - material.side = BackSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + function renderObjects( renderList, scene, camera ) { - material.side = FrontSide; - material.needsUpdate = true; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; - material.side = DoubleSide; + for ( let i = 0, l = renderList.length; i < l; i ++ ) { - } else { + const renderItem = renderList[ i ]; - _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + const object = renderItem.object; + const geometry = renderItem.geometry; + const material = overrideMaterial === null ? renderItem.material : overrideMaterial; + const group = renderItem.group; - } + if ( object.layers.test( camera.layers ) ) { - object.onAfterRender( _this, scene, camera, geometry, material, group ); + renderObject( object, scene, camera, geometry, material, group ); - } + } - function getProgram( material, scene, object ) { + } - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + } - const materialProperties = properties.get( material ); + function renderObject( object, scene, camera, geometry, material, group ) { - const lights = currentRenderState.state.lights; - const shadowsArray = currentRenderState.state.shadowsArray; + object.onBeforeRender( _this, scene, camera, geometry, material, group ); - const lightsStateVersion = lights.state.version; + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); - const programCacheKey = programCache.getProgramCacheKey( parameters ); + material.onBeforeRender( _this, scene, camera, geometry, object, group ); - let programs = materialProperties.programs; + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { - // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change + material.side = BackSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); + + material.side = FrontSide; + material.needsUpdate = true; + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; - materialProperties.fog = scene.fog; - materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + material.side = DoubleSide; - if ( programs === undefined ) { + } else { - // new material + _this.renderBufferDirect( camera, scene, geometry, material, object, group ); - material.addEventListener( 'dispose', onMaterialDispose ); + } - programs = new Map(); - materialProperties.programs = programs; + object.onAfterRender( _this, scene, camera, geometry, material, group ); } - let program = programs.get( programCacheKey ); + function getProgram( material, scene, object ) { + + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + + const materialProperties = properties.get( material ); + + const lights = currentRenderState.state.lights; + const shadowsArray = currentRenderState.state.shadowsArray; - if ( program !== undefined ) { + const lightsStateVersion = lights.state.version; - // early out if program and light state is identical + const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); + const programCacheKey = programCache.getProgramCacheKey( parameters ); - if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { + let programs = materialProperties.programs; - updateCommonMaterialProperties( material, parameters ); + // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change - return program; + materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; + materialProperties.fog = scene.fog; + materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); + + if ( programs === undefined ) { + + // new material + + material.addEventListener( 'dispose', onMaterialDispose ); + + programs = new Map(); + materialProperties.programs = programs; } - } else { + let program = programs.get( programCacheKey ); - parameters.uniforms = programCache.getUniforms( material ); + if ( program !== undefined ) { - material.onBuild( object, parameters, _this ); + // early out if program and light state is identical - material.onBeforeCompile( parameters, _this ); + if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { - program = programCache.acquireProgram( parameters, programCacheKey ); - programs.set( programCacheKey, program ); + updateCommonMaterialProperties( material, parameters ); - materialProperties.uniforms = parameters.uniforms; + return program; - } + } - const uniforms = materialProperties.uniforms; + } else { - if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { + parameters.uniforms = programCache.getUniforms( material ); - uniforms.clippingPlanes = clipping.uniform; + material.onBuild( object, parameters, _this ); - } + material.onBeforeCompile( parameters, _this ); - updateCommonMaterialProperties( material, parameters ); + program = programCache.acquireProgram( parameters, programCacheKey ); + programs.set( programCacheKey, program ); - // store the light setup it was created for + materialProperties.uniforms = parameters.uniforms; - materialProperties.needsLights = materialNeedsLights( material ); - materialProperties.lightsStateVersion = lightsStateVersion; + } - if ( materialProperties.needsLights ) { + const uniforms = materialProperties.uniforms; - // wire up the material to this renderer's lighting state + if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.lightProbe.value = lights.state.probe; - uniforms.directionalLights.value = lights.state.directional; - uniforms.directionalLightShadows.value = lights.state.directionalShadow; - uniforms.spotLights.value = lights.state.spot; - uniforms.spotLightShadows.value = lights.state.spotShadow; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.ltc_1.value = lights.state.rectAreaLTC1; - uniforms.ltc_2.value = lights.state.rectAreaLTC2; - uniforms.pointLights.value = lights.state.point; - uniforms.pointLightShadows.value = lights.state.pointShadow; - uniforms.hemisphereLights.value = lights.state.hemi; + uniforms.clippingPlanes = clipping.uniform; - uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; - uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; - uniforms.spotShadowMap.value = lights.state.spotShadowMap; - uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; - uniforms.spotLightMap.value = lights.state.spotLightMap; - uniforms.pointShadowMap.value = lights.state.pointShadowMap; - uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; - // TODO (abelnation): add area lights shadow info to uniforms + } - } + updateCommonMaterialProperties( material, parameters ); - const progUniforms = program.getUniforms(); - const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); + // store the light setup it was created for - materialProperties.currentProgram = program; - materialProperties.uniformsList = uniformsList; + materialProperties.needsLights = materialNeedsLights( material ); + materialProperties.lightsStateVersion = lightsStateVersion; - return program; + if ( materialProperties.needsLights ) { - } + // wire up the material to this renderer's lighting state + + uniforms.ambientLightColor.value = lights.state.ambient; + uniforms.lightProbe.value = lights.state.probe; + uniforms.directionalLights.value = lights.state.directional; + uniforms.directionalLightShadows.value = lights.state.directionalShadow; + uniforms.spotLights.value = lights.state.spot; + uniforms.spotLightShadows.value = lights.state.spotShadow; + uniforms.rectAreaLights.value = lights.state.rectArea; + uniforms.ltc_1.value = lights.state.rectAreaLTC1; + uniforms.ltc_2.value = lights.state.rectAreaLTC2; + uniforms.pointLights.value = lights.state.point; + uniforms.pointLightShadows.value = lights.state.pointShadow; + uniforms.hemisphereLights.value = lights.state.hemi; + + uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; + uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; + uniforms.spotShadowMap.value = lights.state.spotShadowMap; + uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; + uniforms.spotLightMap.value = lights.state.spotLightMap; + uniforms.pointShadowMap.value = lights.state.pointShadowMap; + uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; + // TODO (abelnation): add area lights shadow info to uniforms - function updateCommonMaterialProperties( material, parameters ) { + } - const materialProperties = properties.get( material ); + const progUniforms = program.getUniforms(); + const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); - materialProperties.outputEncoding = parameters.outputEncoding; - materialProperties.instancing = parameters.instancing; - materialProperties.skinning = parameters.skinning; - materialProperties.morphTargets = parameters.morphTargets; - materialProperties.morphNormals = parameters.morphNormals; - materialProperties.morphColors = parameters.morphColors; - materialProperties.morphTargetsCount = parameters.morphTargetsCount; - materialProperties.numClippingPlanes = parameters.numClippingPlanes; - materialProperties.numIntersection = parameters.numClipIntersection; - materialProperties.vertexAlphas = parameters.vertexAlphas; - materialProperties.vertexTangents = parameters.vertexTangents; - materialProperties.toneMapping = parameters.toneMapping; - materialProperties.extraProgramCacheKey = parameters.extraProgramCacheKey; + materialProperties.currentProgram = program; + materialProperties.uniformsList = uniformsList; - } + return program; + + } + + function updateCommonMaterialProperties( material, parameters ) { + + const materialProperties = properties.get( material ); + + materialProperties.outputColorSpace = parameters.outputColorSpace; + materialProperties.instancing = parameters.instancing; + materialProperties.skinning = parameters.skinning; + materialProperties.morphTargets = parameters.morphTargets; + materialProperties.morphNormals = parameters.morphNormals; + materialProperties.morphColors = parameters.morphColors; + materialProperties.morphTargetsCount = parameters.morphTargetsCount; + materialProperties.numClippingPlanes = parameters.numClippingPlanes; + materialProperties.numIntersection = parameters.numClipIntersection; + materialProperties.vertexAlphas = parameters.vertexAlphas; + materialProperties.vertexTangents = parameters.vertexTangents; + materialProperties.toneMapping = parameters.toneMapping; - function setProgram( camera, scene, geometry, material, object ) { + } + + function setProgram( camera, scene, geometry, material, object ) { - if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... + if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... - textures.resetTextureUnits(); + textures.resetTextureUnits(); - const fog = scene.fog; - const environment = material.isMeshStandardMaterial ? scene.environment : null; - const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding ); - const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); - const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; - const vertexTangents = !! material.normalMap && !! geometry.attributes.tangent; - const morphTargets = !! geometry.morphAttributes.position; - const morphNormals = !! geometry.morphAttributes.normal; - const morphColors = !! geometry.morphAttributes.color; - const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; + const fog = scene.fog; + const environment = material.isMeshStandardMaterial ? scene.environment : null; + const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); + const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); + const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; + const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); + const morphTargets = !! geometry.morphAttributes.position; + const morphNormals = !! geometry.morphAttributes.normal; + const morphColors = !! geometry.morphAttributes.color; + const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - const materialProperties = properties.get( material ); - const lights = currentRenderState.state.lights; + const materialProperties = properties.get( material ); + const lights = currentRenderState.state.lights; - const extraProgramCacheKey = _this.extraProgramCacheKey; + if ( _clippingEnabled === true ) { - if ( _clippingEnabled === true ) { + if ( _localClippingEnabled === true || camera !== _currentCamera ) { - if ( _localClippingEnabled === true || camera !== _currentCamera ) { + const useCache = + camera === _currentCamera && + material.id === _currentMaterialId; - const useCache = - camera === _currentCamera && - material.id === _currentMaterialId; + // we might want to call this function with some ClippingGroup + // object instead of the material, once it becomes feasible + // (#8465, #8379) + clipping.setState( material, camera, useCache ); - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - clipping.setState( material, camera, useCache ); + } } - } + // - // + let needsProgramChange = false; - let needsProgramChange = false; + if ( material.version === materialProperties.__version ) { - if ( material.version === materialProperties.__version ) { + if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { - if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.outputColorSpace !== colorSpace ) { - } else if ( materialProperties.outputEncoding !== encoding ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { - } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { - } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { - } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { - } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.envMap !== envMap ) { - } else if ( materialProperties.envMap !== envMap ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( material.fog === true && materialProperties.fog !== fog ) { - } else if ( material.fog === true && materialProperties.fog !== fog ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.numClippingPlanes !== undefined && + ( materialProperties.numClippingPlanes !== clipping.numPlanes || + materialProperties.numIntersection !== clipping.numIntersection ) ) { - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== clipping.numPlanes || - materialProperties.numIntersection !== clipping.numIntersection ) ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { - } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.vertexTangents !== vertexTangents ) { - } else if ( materialProperties.vertexTangents !== vertexTangents ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.morphTargets !== morphTargets ) { - } else if ( materialProperties.morphTargets !== morphTargets ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.morphNormals !== morphNormals ) { - } else if ( materialProperties.morphNormals !== morphNormals ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.morphColors !== morphColors ) { - } else if ( materialProperties.morphColors !== morphColors ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( materialProperties.toneMapping !== toneMapping ) { - } else if ( materialProperties.toneMapping !== toneMapping ) { + needsProgramChange = true; - needsProgramChange = true; + } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { - } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { + needsProgramChange = true; - needsProgramChange = true; + } - } else if ( extraProgramCacheKey !== materialProperties.extraProgramCacheKey ) { + } else { needsProgramChange = true; + materialProperties.__version = material.version; } - } else { - - needsProgramChange = true; - materialProperties.__version = material.version; + // - } - - // + let program = materialProperties.currentProgram; - let program = materialProperties.currentProgram; + if ( needsProgramChange === true ) { - if ( needsProgramChange === true ) { + program = getProgram( material, scene, object ); - program = getProgram( material, scene, object ); + } - } + let refreshProgram = false; + let refreshMaterial = false; + let refreshLights = false; - let refreshProgram = false; - let refreshMaterial = false; - let refreshLights = false; + const p_uniforms = program.getUniforms(), + m_uniforms = materialProperties.uniforms; - const p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.uniforms; + if ( state.useProgram( program.program ) ) { - if ( state.useProgram( program.program ) ) { + refreshProgram = true; + refreshMaterial = true; + refreshLights = true; - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; + } - } + if ( material.id !== _currentMaterialId ) { - if ( material.id !== _currentMaterialId ) { + _currentMaterialId = material.id; - _currentMaterialId = material.id; + refreshMaterial = true; - refreshMaterial = true; + } - } + if ( refreshProgram || _currentCamera !== camera ) { - if ( refreshProgram || _currentCamera !== camera ) { + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + if ( capabilities.logarithmicDepthBuffer ) { - if ( capabilities.logarithmicDepthBuffer ) { + p_uniforms.setValue( _gl, 'logDepthBufFC', + 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); + } - } + if ( _currentCamera !== camera ) { - if ( _currentCamera !== camera ) { + _currentCamera = camera; - _currentCamera = camera; + // lighting uniforms depend on the camera so enforce an update + // now, in case this material supports lights - or later, when + // the next material that does gets activated: - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: + refreshMaterial = true; // set to true on material change + refreshLights = true; // remains set until update done - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done + } - } + // load material specific uniforms + // (shader material also gets them for the sake of genericity) - // load material specific uniforms - // (shader material also gets them for the sake of genericity) + if ( material.isShaderMaterial || + material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshStandardMaterial || + material.envMap ) { - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshStandardMaterial || - material.envMap ) { + const uCamPos = p_uniforms.map.cameraPosition; - const uCamPos = p_uniforms.map.cameraPosition; + if ( uCamPos !== undefined ) { - if ( uCamPos !== undefined ) { + uCamPos.setValue( _gl, + _vector3.setFromMatrixPosition( camera.matrixWorld ) ); - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); + } } - } + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial ) { - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial ) { + p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); - p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); + } - } + if ( material.isMeshPhongMaterial || + material.isMeshToonMaterial || + material.isMeshLambertMaterial || + material.isMeshBasicMaterial || + material.isMeshStandardMaterial || + material.isShaderMaterial || + material.isShadowMaterial || + object.isSkinnedMesh ) { - if ( material.isMeshPhongMaterial || - material.isMeshToonMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.isShadowMaterial || - object.isSkinnedMesh ) { + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); + } } - } + // skinning and morph target uniforms must be set even if material didn't change + // auto-setting of texture unit for bone and morph texture must go before other textures + // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures - // skinning and morph target uniforms must be set even if material didn't change - // auto-setting of texture unit for bone and morph texture must go before other textures - // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures + if ( object.isSkinnedMesh ) { - if ( object.isSkinnedMesh ) { + p_uniforms.setOptional( _gl, object, 'bindMatrix' ); + p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); + const skeleton = object.skeleton; - const skeleton = object.skeleton; + if ( skeleton ) { - if ( skeleton ) { + if ( capabilities.floatVertexTextures ) { - if ( capabilities.floatVertexTextures ) { + if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); - if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); + p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); + p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); + } else { - } else { + console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); - console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); + } } } - } + const morphAttributes = geometry.morphAttributes; - const morphAttributes = geometry.morphAttributes; + if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { - if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { + morphtargets.update( object, geometry, program ); - morphtargets.update( object, geometry, material, program ); + } - } + if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { - if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { + materialProperties.receiveShadow = object.receiveShadow; + p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); - materialProperties.receiveShadow = object.receiveShadow; - p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); + } - } + // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 - // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 + if ( material.isMeshGouraudMaterial && material.envMap !== null ) { - if ( material.isMeshGouraudMaterial && material.envMap !== null ) { + m_uniforms.envMap.value = envMap; - m_uniforms.envMap.value = envMap; + m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; - m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; + } - } + if ( refreshMaterial ) { - if ( refreshMaterial ) { + p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); + if ( materialProperties.needsLights ) { - if ( materialProperties.needsLights ) { + // the current material requires lighting info - // the current material requires lighting info + // note: all lighting uniforms are always set correctly + // they simply reference the renderer's state for their + // values + // + // use the current material's .needsUpdate flags to set + // the GL state when required - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required + markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); + } - } + // refresh uniforms common to several materials - // refresh uniforms common to several materials + if ( fog && material.fog === true ) { - if ( fog && material.fog === true ) { + materials.refreshFogUniforms( m_uniforms, fog ); - materials.refreshFogUniforms( m_uniforms, fog ); + } - } + materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); - materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + } - } + if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { - if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { + WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); + material.uniformsNeedUpdate = false; - WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); - material.uniformsNeedUpdate = false; + } - } + if ( material.isSpriteMaterial ) { - if ( material.isSpriteMaterial ) { + p_uniforms.setValue( _gl, 'center', object.center ); - p_uniforms.setValue( _gl, 'center', object.center ); + } - } + // common matrices - // common matrices + p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); + p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); + p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); + // UBOs - // UBOs + if ( material.isShaderMaterial || material.isRawShaderMaterial ) { - if ( material.isShaderMaterial || material.isRawShaderMaterial ) { + const groups = material.uniformsGroups; - const groups = material.uniformsGroups; + for ( let i = 0, l = groups.length; i < l; i ++ ) { - for ( let i = 0, l = groups.length; i < l; i ++ ) { + if ( capabilities.isWebGL2 ) { - if ( capabilities.isWebGL2 ) { + const group = groups[ i ]; - const group = groups[ i ]; + uniformsGroups.update( group, program ); + uniformsGroups.bind( group, program ); - uniformsGroups.update( group, program ); - uniformsGroups.bind( group, program ); + } else { - } else { + console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); - console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); + } } } - } + return program; - return program; + } - } + // If uniforms are marked as clean, they don't need to be loaded to the GPU. - // If uniforms are marked as clean, they don't need to be loaded to the GPU. + function markUniformsLightsNeedsUpdate( uniforms, value ) { - function markUniformsLightsNeedsUpdate( uniforms, value ) { + uniforms.ambientLightColor.needsUpdate = value; + uniforms.lightProbe.needsUpdate = value; - uniforms.ambientLightColor.needsUpdate = value; - uniforms.lightProbe.needsUpdate = value; + uniforms.directionalLights.needsUpdate = value; + uniforms.directionalLightShadows.needsUpdate = value; + uniforms.pointLights.needsUpdate = value; + uniforms.pointLightShadows.needsUpdate = value; + uniforms.spotLights.needsUpdate = value; + uniforms.spotLightShadows.needsUpdate = value; + uniforms.rectAreaLights.needsUpdate = value; + uniforms.hemisphereLights.needsUpdate = value; - uniforms.directionalLights.needsUpdate = value; - uniforms.directionalLightShadows.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.pointLightShadows.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.spotLightShadows.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; + } - } + function materialNeedsLights( material ) { - function materialNeedsLights( material ) { + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + material.isMeshStandardMaterial || material.isShadowMaterial || + ( material.isShaderMaterial && material.lights === true ); - return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || - material.isMeshStandardMaterial || material.isShadowMaterial || - ( material.isShaderMaterial && material.lights === true ); + } - } + this.getActiveCubeFace = function () { - this.getActiveCubeFace = function () { + return _currentActiveCubeFace; - return _currentActiveCubeFace; + }; - }; + this.getActiveMipmapLevel = function () { - this.getActiveMipmapLevel = function () { + return _currentActiveMipmapLevel; - return _currentActiveMipmapLevel; + }; - }; + this.getRenderTarget = function () { - this.getRenderTarget = function () { + return _currentRenderTarget; - return _currentRenderTarget; + }; - }; + this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { - this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { + properties.get( renderTarget.texture ).__webglTexture = colorTexture; + properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; - properties.get( renderTarget.texture ).__webglTexture = colorTexture; - properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__hasExternalTextures = true; - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__hasExternalTextures = true; + if ( renderTargetProperties.__hasExternalTextures ) { - if ( renderTargetProperties.__hasExternalTextures ) { + renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; - renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; + if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { - if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { + // The multisample_render_to_texture extension doesn't work properly if there + // are midframe flushes and an external depth buffer. Disable use of the extension. + if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { - // The multisample_render_to_texture extension doesn't work properly if there - // are midframe flushes and an external depth buffer. Disable use of the extension. - if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { + console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); + renderTargetProperties.__useRenderToTexture = false; - console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); - renderTargetProperties.__useRenderToTexture = false; + } } } - } + }; - }; + this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { - this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { + const renderTargetProperties = properties.get( renderTarget ); + renderTargetProperties.__webglFramebuffer = defaultFramebuffer; + renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; - const renderTargetProperties = properties.get( renderTarget ); - renderTargetProperties.__webglFramebuffer = defaultFramebuffer; - renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; + }; - }; + this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { - this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { + _currentRenderTarget = renderTarget; + _currentActiveCubeFace = activeCubeFace; + _currentActiveMipmapLevel = activeMipmapLevel; - _currentRenderTarget = renderTarget; - _currentActiveCubeFace = activeCubeFace; - _currentActiveMipmapLevel = activeMipmapLevel; + let useDefaultFramebuffer = true; + let framebuffer = null; + let isCube = false; + let isRenderTarget3D = false; - let useDefaultFramebuffer = true; - let framebuffer = null; - let isCube = false; - let isRenderTarget3D = false; + if ( renderTarget ) { - if ( renderTarget ) { + const renderTargetProperties = properties.get( renderTarget ); - const renderTargetProperties = properties.get( renderTarget ); + if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { + + // We need to make sure to rebind the framebuffer. + state.bindFramebuffer( _gl.FRAMEBUFFER, null ); + useDefaultFramebuffer = false; - if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { + } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { - // We need to make sure to rebind the framebuffer. - state.bindFramebuffer( _gl.FRAMEBUFFER, null ); - useDefaultFramebuffer = false; + textures.setupRenderTarget( renderTarget ); - } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { + } else if ( renderTargetProperties.__hasExternalTextures ) { - textures.setupRenderTarget( renderTarget ); + // Color and depth texture must be rebound in order for the swapchain to update. + textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); - } else if ( renderTargetProperties.__hasExternalTextures ) { + } - // Color and depth texture must be rebound in order for the swapchain to update. - textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); + const texture = renderTarget.texture; - } + if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - const texture = renderTarget.texture; + isRenderTarget3D = true; - if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + } - isRenderTarget3D = true; + const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - } + if ( renderTarget.isWebGLCubeRenderTarget ) { + + framebuffer = __webglFramebuffer[ activeCubeFace ]; + isCube = true; + + } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { - const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; + framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; - if ( renderTarget.isWebGLCubeRenderTarget ) { + } else { - framebuffer = __webglFramebuffer[ activeCubeFace ]; - isCube = true; + framebuffer = __webglFramebuffer; - } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { + } - framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; + _currentViewport.copy( renderTarget.viewport ); + _currentScissor.copy( renderTarget.scissor ); + _currentScissorTest = renderTarget.scissorTest; } else { - framebuffer = __webglFramebuffer; + _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); + _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); + _currentScissorTest = _scissorTest; } - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - } else { + if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); - _currentScissorTest = _scissorTest; + state.drawBuffers( renderTarget, framebuffer ); - } + } - const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + state.viewport( _currentViewport ); + state.scissor( _currentScissor ); + state.setScissorTest( _currentScissorTest ); - if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { + if ( isCube ) { - state.drawBuffers( renderTarget, framebuffer ); + const textureProperties = properties.get( renderTarget.texture ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); - } + } else if ( isRenderTarget3D ) { - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); + const textureProperties = properties.get( renderTarget.texture ); + const layer = activeCubeFace || 0; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); - if ( isCube ) { + } - const textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); + _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings - } else if ( isRenderTarget3D ) { + }; - const textureProperties = properties.get( renderTarget.texture ); - const layer = activeCubeFace || 0; - _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); + this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { - } + if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); + return; - }; + } - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { + let framebuffer = properties.get( renderTarget ).__webglFramebuffer; - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { + if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; + framebuffer = framebuffer[ activeCubeFaceIndex ]; - } + } - let framebuffer = properties.get( renderTarget ).__webglFramebuffer; + if ( framebuffer ) { - if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - framebuffer = framebuffer[ activeCubeFaceIndex ]; + try { - } + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - if ( framebuffer ) { + if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); + return; - try { + } - const texture = renderTarget.texture; - const textureFormat = texture.format; - const textureType = texture.type; + const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { + if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) + ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox + ! halfFloatSupportedByExt ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; + console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); + return; - } + } - const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! halfFloatSupportedByExt ) { + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - } + } - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + } finally { - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + // restore framebuffer of current render target if necessary - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); + const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); } - } finally { + } + + }; - // restore framebuffer of current render target if necessary + this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { - const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + const levelScale = Math.pow( 2, - level ); + const width = Math.floor( texture.image.width * levelScale ); + const height = Math.floor( texture.image.height * levelScale ); - } + textures.setTexture2D( texture, 0 ); - } + _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); + + state.unbindTexture(); - }; + }; - this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { + this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { - const levelScale = Math.pow( 2, - level ); - const width = Math.floor( texture.image.width * levelScale ); - const height = Math.floor( texture.image.height * levelScale ); + const width = srcTexture.image.width; + const height = srcTexture.image.height; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); - textures.setTexture2D( texture, 0 ); + textures.setTexture2D( dstTexture, 0 ); - _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - state.unbindTexture(); + if ( srcTexture.isDataTexture ) { - }; + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); - this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { + } else { - const width = srcTexture.image.width; - const height = srcTexture.image.height; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); + if ( srcTexture.isCompressedTexture ) { - textures.setTexture2D( dstTexture, 0 ); + _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); - // As another texture upload may have changed pixelStorei - // parameters, make sure they are correct for the dstTexture - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + } else { - if ( srcTexture.isDataTexture ) { + _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); - _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); + } - } else { + } - if ( srcTexture.isCompressedTexture ) { + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); - _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); + state.unbindTexture(); - } else { + }; + + this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { - _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); + if ( _this.isWebGL1Renderer ) { + + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); + return; } - } + const width = sourceBox.max.x - sourceBox.min.x + 1; + const height = sourceBox.max.y - sourceBox.min.y + 1; + const depth = sourceBox.max.z - sourceBox.min.z + 1; + const glFormat = utils.convert( dstTexture.format ); + const glType = utils.convert( dstTexture.type ); + let glTarget; - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); + if ( dstTexture.isData3DTexture ) { - state.unbindTexture(); + textures.setTexture3D( dstTexture, 0 ); + glTarget = _gl.TEXTURE_3D; - }; + } else if ( dstTexture.isDataArrayTexture ) { - this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { + textures.setTexture2DArray( dstTexture, 0 ); + glTarget = _gl.TEXTURE_2D_ARRAY; - if ( _this.isWebGL1Renderer ) { + } else { - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); - return; + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); + return; - } + } - const width = sourceBox.max.x - sourceBox.min.x + 1; - const height = sourceBox.max.y - sourceBox.min.y + 1; - const depth = sourceBox.max.z - sourceBox.min.z + 1; - const glFormat = utils.convert( dstTexture.format ); - const glType = utils.convert( dstTexture.type ); - let glTarget; + _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); - if ( dstTexture.isData3DTexture ) { + const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); + const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); + const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); + const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); + const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); - textures.setTexture3D( dstTexture, 0 ); - glTarget = _gl.TEXTURE_3D; + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; - } else if ( dstTexture.isDataArrayTexture ) { + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); - textures.setTexture2DArray( dstTexture, 0 ); - glTarget = _gl.TEXTURE_2D_ARRAY; + if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { - } else { + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); - return; + } else { - } + if ( srcTexture.isCompressedArrayTexture ) { - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); + _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); - const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); - const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); - const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); - const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); - const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); + } else { - const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; + _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); + } - if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { + } - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); + _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); + _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); + _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); + _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); + _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); - } else { + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); - if ( srcTexture.isCompressedArrayTexture ) { + state.unbindTexture(); - console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); - _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); + }; - } else { + this.initTexture = function ( texture ) { - _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); + if ( texture.isCubeTexture ) { - } + textures.setTextureCube( texture, 0 ); - } + } else if ( texture.isData3DTexture ) { - _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); - _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); - _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); - _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); - _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); + textures.setTexture3D( texture, 0 ); - // Generate mipmaps only when copying level 0 - if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { - state.unbindTexture(); + textures.setTexture2DArray( texture, 0 ); - }; + } else { - this.initTexture = function ( texture ) { + textures.setTexture2D( texture, 0 ); - if ( texture.isCubeTexture ) { + } - textures.setTextureCube( texture, 0 ); + state.unbindTexture(); - } else if ( texture.isData3DTexture ) { + }; - textures.setTexture3D( texture, 0 ); + this.resetState = function () { - } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + _currentActiveCubeFace = 0; + _currentActiveMipmapLevel = 0; + _currentRenderTarget = null; - textures.setTexture2DArray( texture, 0 ); + state.reset(); + bindingStates.reset(); - } else { + }; - textures.setTexture2D( texture, 0 ); + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); } - state.unbindTexture(); + } - }; + get physicallyCorrectLights() { // @deprecated, r150 - this.resetState = function () { + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + return ! this.useLegacyLights; - _currentActiveCubeFace = 0; - _currentActiveMipmapLevel = 0; - _currentRenderTarget = null; + } - state.reset(); - bindingStates.reset(); + set physicallyCorrectLights( value ) { // @deprecated, r150 - }; + console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); + this.useLegacyLights = ! value; - if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + } - __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); + get outputEncoding() { // @deprecated, r152 + + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + return this.outputColorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; + + } + + set outputEncoding( encoding ) { // @deprecated, r152 + + console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); + this.outputColorSpace = encoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; } } + export { WebGLRenderer }; diff --git a/src/renderers/shaders/ShaderChunk.js b/src/renderers/shaders/ShaderChunk.js index e8435e4359944a..dcf52b1893dc68 100644 --- a/src/renderers/shaders/ShaderChunk.js +++ b/src/renderers/shaders/ShaderChunk.js @@ -100,9 +100,6 @@ import transmission_pars_fragment from './ShaderChunk/transmission_pars_fragment import uv_pars_fragment from './ShaderChunk/uv_pars_fragment.glsl.js'; import uv_pars_vertex from './ShaderChunk/uv_pars_vertex.glsl.js'; import uv_vertex from './ShaderChunk/uv_vertex.glsl.js'; -import uv2_pars_fragment from './ShaderChunk/uv2_pars_fragment.glsl.js'; -import uv2_pars_vertex from './ShaderChunk/uv2_pars_vertex.glsl.js'; -import uv2_vertex from './ShaderChunk/uv2_vertex.glsl.js'; import worldpos_vertex from './ShaderChunk/worldpos_vertex.glsl.js'; import * as background from './ShaderLib/background.glsl.js'; @@ -226,9 +223,6 @@ export const ShaderChunk = { uv_pars_fragment: uv_pars_fragment, uv_pars_vertex: uv_pars_vertex, uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, worldpos_vertex: worldpos_vertex, background_vert: background.vertex, diff --git a/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js index 81c5796588a2e2..98296ae1fc0dce 100644 --- a/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js @@ -1,7 +1,7 @@ export default /* glsl */` #ifdef USE_ALPHAMAP - diffuseColor.a *= texture2D( alphaMap, vUv ).g; + diffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g; #endif `; diff --git a/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js index cd387f215d8d44..8fdac363da1196 100644 --- a/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js @@ -2,7 +2,7 @@ export default /* glsl */` #ifdef USE_AOMAP // reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture - float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0; + float ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0; reflectedLight.indirectDiffuse *= ambientOcclusion; diff --git a/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js b/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js index 86001f31e4dda9..72b3c7ef45f517 100644 --- a/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js +++ b/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js @@ -1,236 +1,5 @@ export default /* glsl */` -vec3 BRDF_Lambert( const in vec3 diffuseColor ) { - - return RECIPROCAL_PI * diffuseColor; - -} // validated - -vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { - - // Original approximation by Christophe Schlick '94 - // float fresnel = pow( 1.0 - dotVH, 5.0 ); - - // Optimized variant (presented by Epic at SIGGRAPH '13) - // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf - float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); - - return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); - -} // validated - -float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { - - // Original approximation by Christophe Schlick '94 - // float fresnel = pow( 1.0 - dotVH, 5.0 ); - - // Optimized variant (presented by Epic at SIGGRAPH '13) - // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf - float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); - - return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); - -} // validated - -vec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) { - float x = clamp( 1.0 - dotVH, 0.0, 1.0 ); - float x2 = x * x; - float x5 = clamp( x * x2 * x2, 0.0, 0.9999 ); - - return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 ); -} - -// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2 -// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf -float V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) { - - float a2 = pow2( alpha ); - - float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) ); - float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) ); - - return 0.5 / max( gv + gl, EPSILON ); - -} - -// Microfacet Models for Refraction through Rough Surfaces - equation (33) -// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html -// alpha is "roughness squared" in Disney’s reparameterization -float D_GGX( const in float alpha, const in float dotNH ) { - - float a2 = pow2( alpha ); - - float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1 - - return RECIPROCAL_PI * a2 / pow2( denom ); - -} - -// GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility -vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) { - - float alpha = pow2( roughness ); // UE4's roughness - - vec3 halfDir = normalize( lightDir + viewDir ); - - float dotNL = saturate( dot( normal, lightDir ) ); - float dotNV = saturate( dot( normal, viewDir ) ); - float dotNH = saturate( dot( normal, halfDir ) ); - float dotVH = saturate( dot( viewDir, halfDir ) ); - - vec3 F = F_Schlick( f0, f90, dotVH ); - - float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); - - float D = D_GGX( alpha, dotNH ); - - return F * ( V * D ); - -} - -#ifdef USE_IRIDESCENCE - - vec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) { - - float alpha = pow2( roughness ); // UE4's roughness - - vec3 halfDir = normalize( lightDir + viewDir ); - - float dotNL = saturate( dot( normal, lightDir ) ); - float dotNV = saturate( dot( normal, viewDir ) ); - float dotNH = saturate( dot( normal, halfDir ) ); - float dotVH = saturate( dot( viewDir, halfDir ) ); - - vec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence ); - - float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); - - float D = D_GGX( alpha, dotNH ); - - return F * ( V * D ); - - } - -#endif - -// Rect Area Light - -// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines -// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt -// code: https://github.com/selfshadow/ltc_code/ - -vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) { - - const float LUT_SIZE = 64.0; - const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; - const float LUT_BIAS = 0.5 / LUT_SIZE; - - float dotNV = saturate( dot( N, V ) ); - - // texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) ) - vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) ); - - uv = uv * LUT_SCALE + LUT_BIAS; - - return uv; - -} - -float LTC_ClippedSphereFormFactor( const in vec3 f ) { - - // Real-Time Area Lighting: a Journey from Research to Production (p.102) - // An approximation of the form factor of a horizon-clipped rectangle. - - float l = length( f ); - - return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 ); - -} - -vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) { - - float x = dot( v1, v2 ); - - float y = abs( x ); - - // rational polynomial approximation to theta / sin( theta ) / 2PI - float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y; - float b = 3.4175940 + ( 4.1616724 + y ) * y; - float v = a / b; - - float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v; - - return cross( v1, v2 ) * theta_sintheta; - -} - -vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) { - - // bail if point is on back side of plane of light - // assumes ccw winding order of light vertices - vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ]; - vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ]; - vec3 lightNormal = cross( v1, v2 ); - - if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 ); - - // construct orthonormal basis around N - vec3 T1, T2; - T1 = normalize( V - N * dot( V, N ) ); - T2 = - cross( N, T1 ); // negated from paper; possibly due to a different handedness of world coordinate system - - // compute transform - mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) ); - - // transform rect - vec3 coords[ 4 ]; - coords[ 0 ] = mat * ( rectCoords[ 0 ] - P ); - coords[ 1 ] = mat * ( rectCoords[ 1 ] - P ); - coords[ 2 ] = mat * ( rectCoords[ 2 ] - P ); - coords[ 3 ] = mat * ( rectCoords[ 3 ] - P ); - - // project rect onto sphere - coords[ 0 ] = normalize( coords[ 0 ] ); - coords[ 1 ] = normalize( coords[ 1 ] ); - coords[ 2 ] = normalize( coords[ 2 ] ); - coords[ 3 ] = normalize( coords[ 3 ] ); - - // calculate vector form factor - vec3 vectorFormFactor = vec3( 0.0 ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] ); - - // adjust for horizon clipping - float result = LTC_ClippedSphereFormFactor( vectorFormFactor ); - -/* - // alternate method of adjusting for horizon clipping (see referece) - // refactoring required - float len = length( vectorFormFactor ); - float z = vectorFormFactor.z / len; - - const float LUT_SIZE = 64.0; - const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; - const float LUT_BIAS = 0.5 / LUT_SIZE; - - // tabulated horizon-clipped sphere, apparently... - vec2 uv = vec2( z * 0.5 + 0.5, len ); - uv = uv * LUT_SCALE + LUT_BIAS; - - float scale = texture2D( ltc_2, uv ).w; - - float result = len * scale; -*/ - - return vec3( result ); - -} - -// End Rect Area Light - - float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) { // geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v) @@ -261,44 +30,4 @@ vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in ve } // validated -#if defined( USE_SHEEN ) - -// https://github.com/google/filament/blob/master/shaders/src/brdf.fs -float D_Charlie( float roughness, float dotNH ) { - - float alpha = pow2( roughness ); - - // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" - float invAlpha = 1.0 / alpha; - float cos2h = dotNH * dotNH; - float sin2h = max( 1.0 - cos2h, 0.0078125 ); // 2^(-14/2), so sin2h^2 > 0 in fp16 - - return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI ); - -} - -// https://github.com/google/filament/blob/master/shaders/src/brdf.fs -float V_Neubelt( float dotNV, float dotNL ) { - - // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" - return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ); - -} - -vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) { - - vec3 halfDir = normalize( lightDir + viewDir ); - - float dotNL = saturate( dot( normal, lightDir ) ); - float dotNV = saturate( dot( normal, viewDir ) ); - float dotNH = saturate( dot( normal, halfDir ) ); - - float D = D_Charlie( sheenRoughness, dotNH ); - float V = V_Neubelt( dotNV, dotNL ); - - return sheenColor * ( D * V ); - -} - -#endif `; diff --git a/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js index 2dd93eb94cad19..7ac75145c4a319 100644 --- a/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js @@ -11,12 +11,12 @@ export default /* glsl */` vec2 dHdxy_fwd() { - vec2 dSTdx = dFdx( vUv ); - vec2 dSTdy = dFdy( vUv ); + vec2 dSTdx = dFdx( vBumpMapUv ); + vec2 dSTdy = dFdy( vBumpMapUv ); - float Hll = bumpScale * texture2D( bumpMap, vUv ).x; - float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll; - float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll; + float Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x; + float dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll; + float dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll; return vec2( dBx, dBy ); diff --git a/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js b/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js index 9a35bdbee1afa9..b09a2dfc7b1e9e 100644 --- a/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js +++ b/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js @@ -1,18 +1,10 @@ export default /* glsl */` #ifdef USE_CLEARCOAT_NORMALMAP - vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0; + vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0; clearcoatMapN.xy *= clearcoatNormalScale; - #ifdef USE_TANGENT - - clearcoatNormal = normalize( vTBN * clearcoatMapN ); - - #else - - clearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection ); - - #endif + clearcoatNormal = normalize( tbn2 * clearcoatMapN ); #endif `; diff --git a/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js index 44f2157d388c39..0f848851c15db1 100644 --- a/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js @@ -6,16 +6,16 @@ export default /* glsl */` #endif -#ifdef USE_CLEARCOAT_ROUGHNESSMAP +#ifdef USE_CLEARCOAT_NORMALMAP - uniform sampler2D clearcoatRoughnessMap; + uniform sampler2D clearcoatNormalMap; + uniform vec2 clearcoatNormalScale; #endif -#ifdef USE_CLEARCOAT_NORMALMAP +#ifdef USE_CLEARCOAT_ROUGHNESSMAP - uniform sampler2D clearcoatNormalMap; - uniform vec2 clearcoatNormalScale; + uniform sampler2D clearcoatRoughnessMap; #endif `; diff --git a/src/renderers/shaders/ShaderChunk/common.glsl.js b/src/renderers/shaders/ShaderChunk/common.glsl.js index b9f49739624495..fbdfcee34237b1 100644 --- a/src/renderers/shaders/ShaderChunk/common.glsl.js +++ b/src/renderers/shaders/ShaderChunk/common.glsl.js @@ -115,4 +115,36 @@ vec2 equirectUv( in vec3 dir ) { return vec2( u, v ); } + +vec3 BRDF_Lambert( const in vec3 diffuseColor ) { + + return RECIPROCAL_PI * diffuseColor; + +} // validated + +vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { + + // Original approximation by Christophe Schlick '94 + // float fresnel = pow( 1.0 - dotVH, 5.0 ); + + // Optimized variant (presented by Epic at SIGGRAPH '13) + // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); + +} // validated + +float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { + + // Original approximation by Christophe Schlick '94 + // float fresnel = pow( 1.0 - dotVH, 5.0 ); + + // Optimized variant (presented by Epic at SIGGRAPH '13) + // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); + +} // validated `; diff --git a/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js index 8cd104e4b05bbb..84ada47906b3b2 100644 --- a/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js @@ -1,7 +1,7 @@ export default /* glsl */` #ifdef USE_DISPLACEMENTMAP - transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias ); + transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias ); #endif `; diff --git a/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js index 68c4a3c7df38aa..517d32ec6daa5c 100644 --- a/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js @@ -1,7 +1,7 @@ export default /* glsl */` #ifdef USE_EMISSIVEMAP - vec4 emissiveColor = texture2D( emissiveMap, vUv ); + vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv ); totalEmissiveRadiance *= emissiveColor.rgb; diff --git a/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js index c5eb54058ba594..914e4fee916e1b 100644 --- a/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js @@ -1,22 +1,13 @@ export default /* glsl */` -#if defined( USE_ENVMAP ) +#ifdef USE_ENVMAP vec3 getIBLIrradiance( const in vec3 normal ) { - #if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE ) + #ifdef ENVMAP_TYPE_CUBE_UV vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); - #if defined( ENVMAP_TYPE_CUBE_UV ) - - vec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz ); - vec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 ); - - #else - - vec4 envMapColor = textureCube( envMap, worldNormal ); - - #endif + vec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 ); return PI * envMapColor.rgb * envMapIntensity; @@ -30,7 +21,7 @@ export default /* glsl */` vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) { - #if defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE ) + #ifdef ENVMAP_TYPE_CUBE_UV vec3 reflectVec = reflect( - viewDir, normal ); @@ -39,16 +30,7 @@ export default /* glsl */` reflectVec = inverseTransformDirection( reflectVec, viewMatrix ); - #if defined( ENVMAP_TYPE_CUBE_UV ) - - vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness ); - - #else - - vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz ); - vec4 envMapColor = textureCube( envMap, queryReflectVec ); - - #endif + vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness ); return envMapColor.rgb * envMapIntensity; @@ -60,5 +42,28 @@ export default /* glsl */` } + #ifdef USE_ANISOTROPY + + vec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) { + + #ifdef ENVMAP_TYPE_CUBE_UV + + // https://google.github.io/filament/Filament.md.html#lighting/imagebasedlights/anisotropy + vec3 bentNormal = cross( bitangent, viewDir ); + bentNormal = normalize( cross( bentNormal, bitangent ) ); + bentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) ); + + return getIBLRadiance( viewDir, bentNormal, roughness ); + + #else + + return vec3( 0.0 ); + + #endif + + } + + #endif + #endif `; diff --git a/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js index 28a7c98787d300..804c348629d747 100644 --- a/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js @@ -1,7 +1,7 @@ export default /* glsl */` #ifdef USE_LIGHTMAP - vec4 lightMapTexel = texture2D( lightMap, vUv2 ); + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; reflectedLight.indirectDiffuse += lightMapIrradiance; diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js index b279e2b9590245..714c7e7a817ae1 100644 --- a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js @@ -3,14 +3,14 @@ export default /* glsl */` #ifdef USE_LIGHTMAP - vec4 lightMapTexel = texture2D( lightMap, vUv2 ); + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; irradiance += lightMapIrradiance; #endif - #if defined( USE_ENVMAP ) && defined( STANDARD ) && ( defined( ENVMAP_TYPE_CUBE_UV ) || defined( ENVMAP_TYPE_CUBE ) ) + #if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV ) iblIrradiance += getIBLIrradiance( geometry.normal ); @@ -20,7 +20,15 @@ export default /* glsl */` #if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular ) - radiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness ); + #ifdef USE_ANISOTROPY + + radiance += getIBLAnisotropyRadiance( geometry.viewDir, geometry.normal, material.roughness, material.anisotropyB, material.anisotropy ); + + #else + + radiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness ); + + #endif #ifdef USE_CLEARCOAT diff --git a/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js b/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js index 5b7979d361c195..36624fe26ac927 100644 --- a/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js @@ -50,7 +50,17 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) { float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) { - #if defined ( PHYSICALLY_CORRECT_LIGHTS ) + #if defined ( LEGACY_LIGHTS ) + + if ( cutoffDistance > 0.0 && decayExponent > 0.0 ) { + + return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent ); + + } + + return 1.0; + + #else // based upon Frostbite 3 Moving to Physically-based Rendering // page 32, equation 26: E[window1] @@ -65,16 +75,6 @@ float getDistanceAttenuation( const in float lightDistance, const in float cutof return distanceFalloff; - #else - - if ( cutoffDistance > 0.0 && decayExponent > 0.0 ) { - - return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent ); - - } - - return 1.0; - #endif } diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js index 33ffd3724bc4ff..c0c1a5a56f441d 100644 --- a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js @@ -13,20 +13,20 @@ material.roughness = min( material.roughness, 1.0 ); material.ior = ior; - #ifdef SPECULAR + #ifdef USE_SPECULAR float specularIntensityFactor = specularIntensity; vec3 specularColorFactor = specularColor; - #ifdef USE_SPECULARINTENSITYMAP + #ifdef USE_SPECULAR_COLORMAP - specularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a; + specularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb; #endif - #ifdef USE_SPECULARCOLORMAP + #ifdef USE_SPECULAR_INTENSITYMAP - specularColorFactor *= texture2D( specularColorMap, vUv ).rgb; + specularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a; #endif @@ -58,13 +58,13 @@ material.roughness = min( material.roughness, 1.0 ); #ifdef USE_CLEARCOATMAP - material.clearcoat *= texture2D( clearcoatMap, vUv ).x; + material.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x; #endif #ifdef USE_CLEARCOAT_ROUGHNESSMAP - material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y; + material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y; #endif @@ -82,13 +82,13 @@ material.roughness = min( material.roughness, 1.0 ); #ifdef USE_IRIDESCENCEMAP - material.iridescence *= texture2D( iridescenceMap, vUv ).r; + material.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r; #endif #ifdef USE_IRIDESCENCE_THICKNESSMAP - material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum; + material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum; #else @@ -102,19 +102,45 @@ material.roughness = min( material.roughness, 1.0 ); material.sheenColor = sheenColor; - #ifdef USE_SHEENCOLORMAP + #ifdef USE_SHEEN_COLORMAP - material.sheenColor *= texture2D( sheenColorMap, vUv ).rgb; + material.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb; #endif material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 ); - #ifdef USE_SHEENROUGHNESSMAP + #ifdef USE_SHEEN_ROUGHNESSMAP - material.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a; + material.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a; #endif +#endif + +#ifdef USE_ANISOTROPY + + #ifdef USE_ANISOTROPYMAP + + mat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x ); + vec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb; + vec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b; + + #else + + vec2 anisotropyV = anisotropyVector; + + #endif + + material.anisotropy = length( anisotropyV ); + anisotropyV /= material.anisotropy; + material.anisotropy = saturate( material.anisotropy ); + + // Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy. + material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) ); + + material.anisotropyT = tbn[ 0 ] * anisotropyV.x - tbn[ 1 ] * anisotropyV.y; + material.anisotropyB = tbn[ 1 ] * anisotropyV.x + tbn[ 0 ] * anisotropyV.y; + #endif `; diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js index 0af32ea590ed4a..2a7bf454cd55c2 100644 --- a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js @@ -1,4 +1,5 @@ export default /* glsl */` + struct PhysicalMaterial { vec3 diffuseColor; @@ -38,12 +39,315 @@ struct PhysicalMaterial { vec3 attenuationColor; #endif + #ifdef USE_ANISOTROPY + float anisotropy; + float alphaT; + vec3 anisotropyT; + vec3 anisotropyB; + #endif + }; // temporary vec3 clearcoatSpecular = vec3( 0.0 ); vec3 sheenSpecular = vec3( 0.0 ); +vec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) { + float x = clamp( 1.0 - dotVH, 0.0, 1.0 ); + float x2 = x * x; + float x5 = clamp( x * x2 * x2, 0.0, 0.9999 ); + + return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 ); +} + +// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2 +// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf +float V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) { + + float a2 = pow2( alpha ); + + float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) ); + float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) ); + + return 0.5 / max( gv + gl, EPSILON ); + +} + +// Microfacet Models for Refraction through Rough Surfaces - equation (33) +// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html +// alpha is "roughness squared" in Disney’s reparameterization +float D_GGX( const in float alpha, const in float dotNH ) { + + float a2 = pow2( alpha ); + + float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1 + + return RECIPROCAL_PI * a2 / pow2( denom ); + +} + +// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf +#ifdef USE_ANISOTROPY + + float V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) { + + float gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) ); + float gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) ); + float v = 0.5 / ( gv + gl ); + + return saturate(v); + + } + + float D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) { + + float a2 = alphaT * alphaB; + highp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH ); + highp float v2 = dot( v, v ); + float w2 = a2 / v2; + + return RECIPROCAL_PI * a2 * pow2 ( w2 ); + + } + +#endif + +#ifdef USE_CLEARCOAT + + // GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility + vec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) { + + vec3 f0 = material.clearcoatF0; + float f90 = material.clearcoatF90; + float roughness = material.clearcoatRoughness; + + float alpha = pow2( roughness ); // UE4's roughness + + vec3 halfDir = normalize( lightDir + viewDir ); + + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + + vec3 F = F_Schlick( f0, f90, dotVH ); + + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + + float D = D_GGX( alpha, dotNH ); + + return F * ( V * D ); + + } + +#endif + +vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) { + + vec3 f0 = material.specularColor; + float f90 = material.specularF90; + float roughness = material.roughness; + + float alpha = pow2( roughness ); // UE4's roughness + + vec3 halfDir = normalize( lightDir + viewDir ); + + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + + vec3 F = F_Schlick( f0, f90, dotVH ); + + #ifdef USE_IRIDESCENCE + + F = mix( F, material.iridescenceFresnel, material.iridescence ); + + #endif + + #ifdef USE_ANISOTROPY + + float dotTL = dot( material.anisotropyT, lightDir ); + float dotTV = dot( material.anisotropyT, viewDir ); + float dotTH = dot( material.anisotropyT, halfDir ); + float dotBL = dot( material.anisotropyB, lightDir ); + float dotBV = dot( material.anisotropyB, viewDir ); + float dotBH = dot( material.anisotropyB, halfDir ); + + float V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL ); + + float D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH ); + + #else + + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + + float D = D_GGX( alpha, dotNH ); + + #endif + + return F * ( V * D ); + +} + +// Rect Area Light + +// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines +// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt +// code: https://github.com/selfshadow/ltc_code/ + +vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) { + + const float LUT_SIZE = 64.0; + const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; + const float LUT_BIAS = 0.5 / LUT_SIZE; + + float dotNV = saturate( dot( N, V ) ); + + // texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) ) + vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) ); + + uv = uv * LUT_SCALE + LUT_BIAS; + + return uv; + +} + +float LTC_ClippedSphereFormFactor( const in vec3 f ) { + + // Real-Time Area Lighting: a Journey from Research to Production (p.102) + // An approximation of the form factor of a horizon-clipped rectangle. + + float l = length( f ); + + return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 ); + +} + +vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) { + + float x = dot( v1, v2 ); + + float y = abs( x ); + + // rational polynomial approximation to theta / sin( theta ) / 2PI + float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y; + float b = 3.4175940 + ( 4.1616724 + y ) * y; + float v = a / b; + + float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v; + + return cross( v1, v2 ) * theta_sintheta; + +} + +vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) { + + // bail if point is on back side of plane of light + // assumes ccw winding order of light vertices + vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ]; + vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ]; + vec3 lightNormal = cross( v1, v2 ); + + if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 ); + + // construct orthonormal basis around N + vec3 T1, T2; + T1 = normalize( V - N * dot( V, N ) ); + T2 = - cross( N, T1 ); // negated from paper; possibly due to a different handedness of world coordinate system + + // compute transform + mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) ); + + // transform rect + vec3 coords[ 4 ]; + coords[ 0 ] = mat * ( rectCoords[ 0 ] - P ); + coords[ 1 ] = mat * ( rectCoords[ 1 ] - P ); + coords[ 2 ] = mat * ( rectCoords[ 2 ] - P ); + coords[ 3 ] = mat * ( rectCoords[ 3 ] - P ); + + // project rect onto sphere + coords[ 0 ] = normalize( coords[ 0 ] ); + coords[ 1 ] = normalize( coords[ 1 ] ); + coords[ 2 ] = normalize( coords[ 2 ] ); + coords[ 3 ] = normalize( coords[ 3 ] ); + + // calculate vector form factor + vec3 vectorFormFactor = vec3( 0.0 ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] ); + + // adjust for horizon clipping + float result = LTC_ClippedSphereFormFactor( vectorFormFactor ); + +/* + // alternate method of adjusting for horizon clipping (see referece) + // refactoring required + float len = length( vectorFormFactor ); + float z = vectorFormFactor.z / len; + + const float LUT_SIZE = 64.0; + const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; + const float LUT_BIAS = 0.5 / LUT_SIZE; + + // tabulated horizon-clipped sphere, apparently... + vec2 uv = vec2( z * 0.5 + 0.5, len ); + uv = uv * LUT_SCALE + LUT_BIAS; + + float scale = texture2D( ltc_2, uv ).w; + + float result = len * scale; +*/ + + return vec3( result ); + +} + +// End Rect Area Light + +#if defined( USE_SHEEN ) + +// https://github.com/google/filament/blob/master/shaders/src/brdf.fs +float D_Charlie( float roughness, float dotNH ) { + + float alpha = pow2( roughness ); + + // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" + float invAlpha = 1.0 / alpha; + float cos2h = dotNH * dotNH; + float sin2h = max( 1.0 - cos2h, 0.0078125 ); // 2^(-14/2), so sin2h^2 > 0 in fp16 + + return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI ); + +} + +// https://github.com/google/filament/blob/master/shaders/src/brdf.fs +float V_Neubelt( float dotNV, float dotNL ) { + + // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" + return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ); + +} + +vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) { + + vec3 halfDir = normalize( lightDir + viewDir ); + + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + + float D = D_Charlie( sheenRoughness, dotNH ); + float V = V_Neubelt( dotNV, dotNL ); + + return sheenColor * ( D * V ); + +} + +#endif + // This is a curve-fit approxmation to the "Charlie sheen" BRDF integrated over the hemisphere from // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found // in the Sheen section of https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing @@ -181,7 +485,7 @@ void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricC vec3 ccIrradiance = dotNLcc * directLight.color; - clearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness ); + clearcoatSpecular += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material ); #endif @@ -191,15 +495,7 @@ void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricC #endif - #ifdef USE_IRIDESCENCE - - reflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness ); - - #else - - reflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness ); - - #endif + reflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material ); reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); } diff --git a/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js index 89ebc6f8b34ec0..50998dba988e1d 100644 --- a/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js @@ -1,17 +1,7 @@ export default /* glsl */` #ifdef USE_MAP - vec4 sampledDiffuseColor = texture2D( map, vUv ); - - #ifdef DECODE_VIDEO_TEXTURE - - // inline sRGB decode (TODO: Remove this code when https://crbug.com/1256340 is solved) - - sampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w ); - - #endif - - diffuseColor *= sampledDiffuseColor; + diffuseColor *= texture2D( map, vMapUv ); #endif `; diff --git a/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js index e1c7259cc1952d..739bf5a99c5b0b 100644 --- a/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js @@ -1,7 +1,15 @@ export default /* glsl */` #if defined( USE_MAP ) || defined( USE_ALPHAMAP ) - vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy; + #if defined( USE_POINTS_UV ) + + vec2 uv = vUv; + + #else + + vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy; + + #endif #endif diff --git a/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js index b974ece2b809e8..bf688193eace7d 100644 --- a/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js @@ -1,7 +1,15 @@ export default /* glsl */` -#if defined( USE_MAP ) || defined( USE_ALPHAMAP ) +#if defined( USE_POINTS_UV ) - uniform mat3 uvTransform; + varying vec2 vUv; + +#else + + #if defined( USE_MAP ) || defined( USE_ALPHAMAP ) + + uniform mat3 uvTransform; + + #endif #endif diff --git a/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js index 0cac7d113cffad..5e8b5c45027d15 100644 --- a/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js @@ -3,7 +3,7 @@ float metalnessFactor = metalness; #ifdef USE_METALNESSMAP - vec4 texelMetalness = texture2D( metalnessMap, vUv ); + vec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv ); // reads channel B, compatible with a combined OcclusionRoughnessMetallic (RGB) texture metalnessFactor *= texelMetalness.b; diff --git a/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js b/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js index fc90fbb58d5fde..736fb4f4ae036e 100644 --- a/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +++ b/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js @@ -13,27 +13,49 @@ float faceDirection = gl_FrontFacing ? 1.0 : - 1.0; #ifdef DOUBLE_SIDED - normal = normal * faceDirection; + normal *= faceDirection; #endif +#endif + +#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) + #ifdef USE_TANGENT - vec3 tangent = normalize( vTangent ); - vec3 bitangent = normalize( vBitangent ); + mat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); - #ifdef DOUBLE_SIDED + #else - tangent = tangent * faceDirection; - bitangent = bitangent * faceDirection; + mat3 tbn = getTangentFrame( - vViewPosition, normal, vNormalMapUv ); + + #endif - #endif + #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) - #if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP ) + tbn[0] *= faceDirection; + tbn[1] *= faceDirection; + + #endif + +#endif + +#ifdef USE_CLEARCOAT_NORMALMAP + + #ifdef USE_TANGENT + + mat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); + + #else + + mat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv ); + + #endif - mat3 vTBN = mat3( tangent, bitangent, normal ); + #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) - #endif + tbn2[0] *= faceDirection; + tbn2[1] *= faceDirection; #endif diff --git a/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js b/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js index df19bdbbe5118f..0a743db303583f 100644 --- a/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +++ b/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js @@ -1,8 +1,8 @@ export default /* glsl */` -#ifdef OBJECTSPACE_NORMALMAP +#ifdef USE_NORMALMAP_OBJECTSPACE - normal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals + normal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals #ifdef FLIP_SIDED @@ -18,20 +18,12 @@ export default /* glsl */` normal = normalize( normalMatrix * normal ); -#elif defined( TANGENTSPACE_NORMALMAP ) +#elif defined( USE_NORMALMAP_TANGENTSPACE ) - vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; + vec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; mapN.xy *= normalScale; - #ifdef USE_TANGENT - - normal = normalize( vTBN * mapN ); - - #else - - normal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection ); - - #endif + normal = normalize( tbn * mapN ); #elif defined( USE_BUMPMAP ) diff --git a/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js index 6d80da660777cf..9f91adb355aed5 100644 --- a/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js @@ -6,23 +6,23 @@ export default /* glsl */` #endif -#ifdef OBJECTSPACE_NORMALMAP +#ifdef USE_NORMALMAP_OBJECTSPACE uniform mat3 normalMatrix; #endif -#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) ) +#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) ) // Normal Mapping Without Precomputed Tangents // http://www.thetenthplanet.de/archives/1180 - vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) { + mat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) { vec3 q0 = dFdx( eye_pos.xyz ); vec3 q1 = dFdy( eye_pos.xyz ); - vec2 st0 = dFdx( vUv.st ); - vec2 st1 = dFdy( vUv.st ); + vec2 st0 = dFdx( uv.st ); + vec2 st1 = dFdy( uv.st ); vec3 N = surf_norm; // normalized @@ -33,9 +33,9 @@ export default /* glsl */` vec3 B = q1perp * st0.y + q0perp * st1.y; float det = max( dot( T, T ), dot( B, B ) ); - float scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det ); + float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det ); - return normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z ); + return mat3( T * scale, B * scale, N ); } diff --git a/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js index 3377354bc8f15d..07fb7207a8665b 100644 --- a/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js @@ -3,9 +3,8 @@ export default /* glsl */` diffuseColor.a = 1.0; #endif -// https://github.com/mrdoob/three.js/pull/22425 #ifdef USE_TRANSMISSION -diffuseColor.a *= material.transmissionAlpha + 0.1; +diffuseColor.a *= material.transmissionAlpha; #endif gl_FragColor = vec4( outgoingLight, diffuseColor.a ); diff --git a/src/renderers/shaders/ShaderChunk/packing.glsl.js b/src/renderers/shaders/ShaderChunk/packing.glsl.js index 8bae84e1df6306..4ee19b70b729d2 100644 --- a/src/renderers/shaders/ShaderChunk/packing.glsl.js +++ b/src/renderers/shaders/ShaderChunk/packing.glsl.js @@ -42,21 +42,27 @@ vec2 unpackRGBATo2Half( vec4 v ) { return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) ); } -// NOTE: viewZ/eyeZ is < 0 when in front of the camera per OpenGL conventions +// NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) { + // -near maps to 0; -far maps to 1 return ( viewZ + near ) / ( near - far ); } -float orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) { - return linearClipZ * ( near - far ) - near; + +float orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) { + // maps orthographic depth in [ 0, 1 ] to viewZ + return depth * ( near - far ) - near; } // NOTE: https://twitter.com/gonnavis/status/1377183786949959682 float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) { + // -near maps to 0; -far maps to 1 return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ ); } -float perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) { - return ( near * far ) / ( ( far - near ) * invClipZ - far ); + +float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) { + // maps perspective depth in [ 0, 1 ] to viewZ + return ( near * far ) / ( ( far - near ) * depth - far ); } `; diff --git a/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js index db5b69872b35de..a9c8833dceb0ab 100644 --- a/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js @@ -3,7 +3,7 @@ float roughnessFactor = roughness; #ifdef USE_ROUGHNESSMAP - vec4 texelRoughness = texture2D( roughnessMap, vUv ); + vec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv ); // reads channel G, compatible with a combined OcclusionRoughnessMetallic (RGB) texture roughnessFactor *= texelRoughness.g; diff --git a/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js index 8e0a4ea5613be2..9b2d1e8674491d 100644 --- a/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js @@ -1,13 +1,13 @@ export default /* glsl */` #if NUM_SPOT_LIGHT_COORDS > 0 - varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; #endif #if NUM_SPOT_LIGHT_MAPS > 0 - uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ]; + uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ]; #endif diff --git a/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js index 76f8995090e690..6f2b23e8e93996 100644 --- a/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js @@ -2,8 +2,8 @@ export default /* glsl */` #if NUM_SPOT_LIGHT_COORDS > 0 - uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ]; - varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; + uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ]; + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; #endif diff --git a/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js index 9f7cf8383b10b6..a57f36b0fac9ab 100644 --- a/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js @@ -3,7 +3,7 @@ float specularStrength; #ifdef USE_SPECULARMAP - vec4 texelSpecular = texture2D( specularMap, vUv ); + vec4 texelSpecular = texture2D( specularMap, vSpecularMapUv ); specularStrength = texelSpecular.r; #else diff --git a/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js index 5087a8313493aa..777da0761e198c 100644 --- a/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js @@ -9,7 +9,7 @@ uniform float toneMappingExposure; // exposure only vec3 LinearToneMapping( vec3 color ) { - return toneMappingExposure * color; + return saturate( toneMappingExposure * color ); } diff --git a/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js index b5a601233a1da9..876a3c6f7aff84 100644 --- a/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js @@ -9,13 +9,13 @@ export default /* glsl */` #ifdef USE_TRANSMISSIONMAP - material.transmission *= texture2D( transmissionMap, vUv ).r; + material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r; #endif #ifdef USE_THICKNESSMAP - material.thickness *= texture2D( thicknessMap, vUv ).g; + material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g; #endif @@ -23,14 +23,14 @@ export default /* glsl */` vec3 v = normalize( cameraPosition - pos ); vec3 n = inverseTransformDirection( normal, viewMatrix ); - vec4 transmission = getIBLVolumeRefraction( + vec4 transmitted = getIBLVolumeRefraction( n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness, material.attenuationColor, material.attenuationDistance ); - material.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission ); + material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); - totalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission ); + totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission ); #endif `; diff --git a/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js index b96e6d3a3b36c1..69e7587695a742 100644 --- a/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js @@ -29,6 +29,95 @@ export default /* glsl */` varying vec3 vWorldPosition; + // Mipped Bicubic Texture Filtering by N8 + // https://www.shadertoy.com/view/Dl2SDW + + float w0( float a ) { + + return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ); + + } + + float w1( float a ) { + + return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ); + + } + + float w2( float a ){ + + return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ); + + } + + float w3( float a ) { + + return ( 1.0 / 6.0 ) * ( a * a * a ); + + } + + // g0 and g1 are the two amplitude functions + float g0( float a ) { + + return w0( a ) + w1( a ); + + } + + float g1( float a ) { + + return w2( a ) + w3( a ); + + } + + // h0 and h1 are the two offset functions + float h0( float a ) { + + return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) ); + + } + + float h1( float a ) { + + return 1.0 + w3( a ) / ( w2( a ) + w3( a ) ); + + } + + vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) { + + uv = uv * texelSize.zw + 0.5; + + vec2 iuv = floor( uv ); + vec2 fuv = fract( uv ); + + float g0x = g0( fuv.x ); + float g1x = g1( fuv.x ); + float h0x = h0( fuv.x ); + float h1x = h1( fuv.x ); + float h0y = h0( fuv.y ); + float h1y = h1( fuv.y ); + + vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + + return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) + + g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) ); + + } + + vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) { + + vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) ); + vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) ); + vec2 fLodSizeInv = 1.0 / fLodSize; + vec2 cLodSizeInv = 1.0 / cLodSize; + vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) ); + vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) ); + return mix( fSample, cSample, fract( lod ) ); + + } + vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { // Direction of refracted light. @@ -55,33 +144,24 @@ export default /* glsl */` vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { - float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); - - #ifdef texture2DLodEXT - - return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod ); - - #else - - return texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod ); - - #endif + float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); + return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod ); } - vec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { + vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { if ( isinf( attenuationDistance ) ) { // Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all. - return radiance; + return vec3( 1.0 ); } else { // Compute light attenuation using Beer's law. vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); // Beer's law - return transmittance * radiance; + return transmittance; } @@ -104,12 +184,17 @@ export default /* glsl */` // Sample framebuffer to get pixel the refracted ray hits. vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); - vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance ); + vec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); + vec3 attenuatedColor = transmittance * transmittedLight.rgb; // Get the specular component. vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); - return vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a ); + // As less light is transmitted, the opacity should be increased. This simple approximation does a decent job + // of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color. + float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; + + return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); } #endif diff --git a/src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl.js deleted file mode 100644 index c9e03d04381403..00000000000000 --- a/src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl.js +++ /dev/null @@ -1,7 +0,0 @@ -export default /* glsl */` -#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP ) - - varying vec2 vUv2; - -#endif -`; diff --git a/src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl.js deleted file mode 100644 index ac764e0cd7f672..00000000000000 --- a/src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl.js +++ /dev/null @@ -1,10 +0,0 @@ -export default /* glsl */` -#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP ) - - attribute vec2 uv2; - varying vec2 vUv2; - - uniform mat3 uv2Transform; - -#endif -`; diff --git a/src/renderers/shaders/ShaderChunk/uv2_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/uv2_vertex.glsl.js deleted file mode 100644 index d3e56312987c7f..00000000000000 --- a/src/renderers/shaders/ShaderChunk/uv2_vertex.glsl.js +++ /dev/null @@ -1,7 +0,0 @@ -export default /* glsl */` -#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP ) - - vUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy; - -#endif -`; diff --git a/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js index 19c95b24c1166d..c50c10e119060e 100644 --- a/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js @@ -1,7 +1,119 @@ export default /* glsl */` -#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) ) +#ifdef USE_UV varying vec2 vUv; +#endif +#ifdef USE_MAP + + varying vec2 vMapUv; + +#endif +#ifdef USE_ALPHAMAP + + varying vec2 vAlphaMapUv; + +#endif +#ifdef USE_LIGHTMAP + + varying vec2 vLightMapUv; + +#endif +#ifdef USE_AOMAP + + varying vec2 vAoMapUv; + +#endif +#ifdef USE_BUMPMAP + + varying vec2 vBumpMapUv; + +#endif +#ifdef USE_NORMALMAP + + varying vec2 vNormalMapUv; + +#endif +#ifdef USE_EMISSIVEMAP + + varying vec2 vEmissiveMapUv; + +#endif +#ifdef USE_METALNESSMAP + + varying vec2 vMetalnessMapUv; + +#endif +#ifdef USE_ROUGHNESSMAP + + varying vec2 vRoughnessMapUv; + +#endif +#ifdef USE_ANISOTROPYMAP + + varying vec2 vAnisotropyMapUv; + +#endif +#ifdef USE_CLEARCOATMAP + + varying vec2 vClearcoatMapUv; + +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + + varying vec2 vClearcoatNormalMapUv; + +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + + varying vec2 vClearcoatRoughnessMapUv; + +#endif +#ifdef USE_IRIDESCENCEMAP + + varying vec2 vIridescenceMapUv; + +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + + varying vec2 vIridescenceThicknessMapUv; + +#endif +#ifdef USE_SHEEN_COLORMAP + + varying vec2 vSheenColorMapUv; + +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + + varying vec2 vSheenRoughnessMapUv; + +#endif +#ifdef USE_SPECULARMAP + + varying vec2 vSpecularMapUv; + +#endif +#ifdef USE_SPECULAR_COLORMAP + + varying vec2 vSpecularColorMapUv; + +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + + varying vec2 vSpecularIntensityMapUv; + +#endif +#ifdef USE_TRANSMISSIONMAP + + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; + +#endif +#ifdef USE_THICKNESSMAP + + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; + #endif `; diff --git a/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js index 0e6a84c9fc3cb7..acbfc6e048d30f 100644 --- a/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js @@ -1,17 +1,145 @@ export default /* glsl */` #ifdef USE_UV - #ifdef UVS_VERTEX_ONLY + varying vec2 vUv; - vec2 vUv; +#endif +#ifdef USE_MAP + + uniform mat3 mapTransform; + varying vec2 vMapUv; + +#endif +#ifdef USE_ALPHAMAP + + uniform mat3 alphaMapTransform; + varying vec2 vAlphaMapUv; + +#endif +#ifdef USE_LIGHTMAP + + uniform mat3 lightMapTransform; + varying vec2 vLightMapUv; + +#endif +#ifdef USE_AOMAP + + uniform mat3 aoMapTransform; + varying vec2 vAoMapUv; + +#endif +#ifdef USE_BUMPMAP + + uniform mat3 bumpMapTransform; + varying vec2 vBumpMapUv; + +#endif +#ifdef USE_NORMALMAP + + uniform mat3 normalMapTransform; + varying vec2 vNormalMapUv; + +#endif +#ifdef USE_DISPLACEMENTMAP + + uniform mat3 displacementMapTransform; + varying vec2 vDisplacementMapUv; + +#endif +#ifdef USE_EMISSIVEMAP + + uniform mat3 emissiveMapTransform; + varying vec2 vEmissiveMapUv; + +#endif +#ifdef USE_METALNESSMAP + + uniform mat3 metalnessMapTransform; + varying vec2 vMetalnessMapUv; + +#endif +#ifdef USE_ROUGHNESSMAP + + uniform mat3 roughnessMapTransform; + varying vec2 vRoughnessMapUv; + +#endif +#ifdef USE_ANISOTROPYMAP + + uniform mat3 anisotropyMapTransform; + varying vec2 vAnisotropyMapUv; - #else +#endif +#ifdef USE_CLEARCOATMAP + + uniform mat3 clearcoatMapTransform; + varying vec2 vClearcoatMapUv; + +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + + uniform mat3 clearcoatNormalMapTransform; + varying vec2 vClearcoatNormalMapUv; + +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + + uniform mat3 clearcoatRoughnessMapTransform; + varying vec2 vClearcoatRoughnessMapUv; + +#endif +#ifdef USE_SHEEN_COLORMAP + + uniform mat3 sheenColorMapTransform; + varying vec2 vSheenColorMapUv; + +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + + uniform mat3 sheenRoughnessMapTransform; + varying vec2 vSheenRoughnessMapUv; + +#endif +#ifdef USE_IRIDESCENCEMAP - varying vec2 vUv; + uniform mat3 iridescenceMapTransform; + varying vec2 vIridescenceMapUv; - #endif +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + + uniform mat3 iridescenceThicknessMapTransform; + varying vec2 vIridescenceThicknessMapUv; + +#endif +#ifdef USE_SPECULARMAP + + uniform mat3 specularMapTransform; + varying vec2 vSpecularMapUv; + +#endif +#ifdef USE_SPECULAR_COLORMAP + + uniform mat3 specularColorMapTransform; + varying vec2 vSpecularColorMapUv; + +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + + uniform mat3 specularIntensityMapTransform; + varying vec2 vSpecularIntensityMapUv; + +#endif +#ifdef USE_TRANSMISSIONMAP + + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; + +#endif +#ifdef USE_THICKNESSMAP - uniform mat3 uvTransform; + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; #endif `; diff --git a/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js index ca031fe1af537b..b865b6b384303f 100644 --- a/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js @@ -1,7 +1,122 @@ export default /* glsl */` #ifdef USE_UV - vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + vUv = vec3( uv, 1 ).xy; + +#endif +#ifdef USE_MAP + + vMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_ALPHAMAP + + vAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_LIGHTMAP + + vLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_AOMAP + + vAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_BUMPMAP + + vBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_NORMALMAP + + vNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_DISPLACEMENTMAP + + vDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_EMISSIVEMAP + + vEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_METALNESSMAP + + vMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_ROUGHNESSMAP + + vRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_ANISOTROPYMAP + + vAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_CLEARCOATMAP + + vClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + + vClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + + vClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_IRIDESCENCEMAP + + vIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + + vIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_SHEEN_COLORMAP + + vSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + + vSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_SPECULARMAP + + vSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_SPECULAR_COLORMAP + + vSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + + vSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_TRANSMISSIONMAP + + vTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy; + +#endif +#ifdef USE_THICKNESSMAP + + vThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy; #endif `; diff --git a/src/renderers/shaders/ShaderLib.js b/src/renderers/shaders/ShaderLib.js index 3e628c0843d36a..0ed7018ee9577c 100644 --- a/src/renderers/shaders/ShaderLib.js +++ b/src/renderers/shaders/ShaderLib.js @@ -306,33 +306,47 @@ ShaderLib.physical = { { clearcoat: { value: 0 }, clearcoatMap: { value: null }, + clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalMap: { value: null }, + clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, clearcoatRoughness: { value: 0 }, clearcoatRoughnessMap: { value: null }, - clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, - clearcoatNormalMap: { value: null }, + clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescence: { value: 0 }, iridescenceMap: { value: null }, + iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, iridescenceIOR: { value: 1.3 }, iridescenceThicknessMinimum: { value: 100 }, iridescenceThicknessMaximum: { value: 400 }, iridescenceThicknessMap: { value: null }, + iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheen: { value: 0 }, sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, sheenColorMap: { value: null }, + sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, sheenRoughness: { value: 1 }, sheenRoughnessMap: { value: null }, + sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmission: { value: 0 }, transmissionMap: { value: null }, + transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, transmissionSamplerMap: { value: null }, thickness: { value: 0 }, thicknessMap: { value: null }, + thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, attenuationDistance: { value: 0 }, attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, - specularIntensity: { value: 1 }, - specularIntensityMap: { value: null }, specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, specularColorMap: { value: null }, + specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + specularIntensity: { value: 1 }, + specularIntensityMap: { value: null }, + specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, + anisotropyMap: { value: null }, + anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, } ] ), diff --git a/src/renderers/shaders/ShaderLib/background.glsl.js b/src/renderers/shaders/ShaderLib/background.glsl.js index ec8e8ee34f10ef..2d2f2aea8b16b7 100644 --- a/src/renderers/shaders/ShaderLib/background.glsl.js +++ b/src/renderers/shaders/ShaderLib/background.glsl.js @@ -21,14 +21,6 @@ void main() { vec4 texColor = texture2D( t2D, vUv ); - #ifdef DECODE_VIDEO_TEXTURE - - // inline sRGB decode (TODO: Remove this code when https://crbug.com/1256340 is solved) - - texColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w ); - - #endif - texColor.rgb *= backgroundIntensity; gl_FragColor = texColor; diff --git a/src/renderers/shaders/ShaderLib/linedashed.glsl.js b/src/renderers/shaders/ShaderLib/linedashed.glsl.js index b561afd6d2a394..db53c7ded67adb 100644 --- a/src/renderers/shaders/ShaderLib/linedashed.glsl.js +++ b/src/renderers/shaders/ShaderLib/linedashed.glsl.js @@ -5,6 +5,7 @@ attribute float lineDistance; varying float vLineDistance; #include +#include #include #include #include @@ -15,6 +16,7 @@ void main() { vLineDistance = scale * lineDistance; + #include #include #include #include @@ -38,6 +40,8 @@ varying float vLineDistance; #include #include +#include +#include #include #include #include @@ -56,6 +60,7 @@ void main() { vec4 diffuseColor = vec4( diffuse, opacity ); #include + #include #include outgoingLight = diffuseColor.rgb; // simple shader diff --git a/src/renderers/shaders/ShaderLib/meshbasic.glsl.js b/src/renderers/shaders/ShaderLib/meshbasic.glsl.js index d5b0199e674c93..8128bda7e82997 100644 --- a/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshbasic.glsl.js @@ -1,7 +1,6 @@ export const vertex = /* glsl */` #include #include -#include #include #include #include @@ -13,7 +12,6 @@ export const vertex = /* glsl */` void main() { #include - #include #include #include @@ -55,7 +53,6 @@ uniform float opacity; #include #include #include -#include #include #include #include @@ -86,7 +83,7 @@ void main() { // accumulation (baked indirect lighting only) #ifdef USE_LIGHTMAP - vec4 lightMapTexel = texture2D( lightMap, vUv2 ); + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI; #else diff --git a/src/renderers/shaders/ShaderLib/meshlambert.glsl.js b/src/renderers/shaders/ShaderLib/meshlambert.glsl.js index 4592a156e1ae63..47a23479dc3054 100644 --- a/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshlambert.glsl.js @@ -5,7 +5,6 @@ varying vec3 vViewPosition; #include #include -#include #include #include #include @@ -20,7 +19,6 @@ varying vec3 vViewPosition; void main() { #include - #include #include #include @@ -61,7 +59,6 @@ uniform float opacity; #include #include #include -#include #include #include #include diff --git a/src/renderers/shaders/ShaderLib/meshnormal.glsl.js b/src/renderers/shaders/ShaderLib/meshnormal.glsl.js index 1628dad57ac7e6..769e54fefc68a9 100644 --- a/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshnormal.glsl.js @@ -1,7 +1,7 @@ export const vertex = /* glsl */` #define NORMAL -#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP ) +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) varying vec3 vViewPosition; @@ -35,7 +35,7 @@ void main() { #include #include -#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP ) +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) vViewPosition = - mvPosition.xyz; @@ -49,7 +49,7 @@ export const fragment = /* glsl */` uniform float opacity; -#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP ) +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) varying vec3 vViewPosition; diff --git a/src/renderers/shaders/ShaderLib/meshphong.glsl.js b/src/renderers/shaders/ShaderLib/meshphong.glsl.js index 54a7b5f80248c4..2beb1ef2c6b67a 100644 --- a/src/renderers/shaders/ShaderLib/meshphong.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshphong.glsl.js @@ -5,7 +5,6 @@ varying vec3 vViewPosition; #include #include -#include #include #include #include @@ -20,7 +19,6 @@ varying vec3 vViewPosition; void main() { #include - #include #include #include @@ -63,7 +61,6 @@ uniform float opacity; #include #include #include -#include #include #include #include diff --git a/src/renderers/shaders/ShaderLib/meshphysical.glsl.js b/src/renderers/shaders/ShaderLib/meshphysical.glsl.js index 4691faa3dd943b..be2c8e5cd59d41 100644 --- a/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshphysical.glsl.js @@ -11,7 +11,6 @@ varying vec3 vViewPosition; #include #include -#include #include #include #include @@ -25,7 +24,6 @@ varying vec3 vViewPosition; void main() { #include - #include #include #include @@ -63,7 +61,7 @@ export const fragment = /* glsl */` #ifdef PHYSICAL #define IOR - #define SPECULAR + #define USE_SPECULAR #endif uniform vec3 diffuse; @@ -76,16 +74,16 @@ uniform float opacity; uniform float ior; #endif -#ifdef SPECULAR +#ifdef USE_SPECULAR uniform float specularIntensity; uniform vec3 specularColor; - #ifdef USE_SPECULARINTENSITYMAP - uniform sampler2D specularIntensityMap; + #ifdef USE_SPECULAR_COLORMAP + uniform sampler2D specularColorMap; #endif - #ifdef USE_SPECULARCOLORMAP - uniform sampler2D specularColorMap; + #ifdef USE_SPECULAR_INTENSITYMAP + uniform sampler2D specularIntensityMap; #endif #endif @@ -105,15 +103,23 @@ uniform float opacity; uniform vec3 sheenColor; uniform float sheenRoughness; - #ifdef USE_SHEENCOLORMAP + #ifdef USE_SHEEN_COLORMAP uniform sampler2D sheenColorMap; #endif - #ifdef USE_SHEENROUGHNESSMAP + #ifdef USE_SHEEN_ROUGHNESSMAP uniform sampler2D sheenRoughnessMap; #endif #endif +#ifdef USE_ANISOTROPY + uniform vec2 anisotropyVector; + + #ifdef USE_ANISOTROPYMAP + uniform sampler2D anisotropyMap; + #endif +#endif + varying vec3 vViewPosition; #include @@ -121,14 +127,12 @@ varying vec3 vViewPosition; #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include @@ -163,7 +167,6 @@ void main() { #include #include #include - #include #include #include #include diff --git a/src/renderers/shaders/ShaderLib/meshtoon.glsl.js b/src/renderers/shaders/ShaderLib/meshtoon.glsl.js index 957dd8c93229da..d0edada0d6ae67 100644 --- a/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshtoon.glsl.js @@ -5,7 +5,6 @@ varying vec3 vViewPosition; #include #include -#include #include #include #include @@ -19,7 +18,6 @@ varying vec3 vViewPosition; void main() { #include - #include #include #include @@ -59,7 +57,6 @@ uniform float opacity; #include #include #include -#include #include #include #include diff --git a/src/renderers/shaders/ShaderLib/points.glsl.js b/src/renderers/shaders/ShaderLib/points.glsl.js index 8af0bf446fc88a..847273fdfa379d 100644 --- a/src/renderers/shaders/ShaderLib/points.glsl.js +++ b/src/renderers/shaders/ShaderLib/points.glsl.js @@ -9,8 +9,21 @@ uniform float scale; #include #include +#ifdef USE_POINTS_UV + + varying vec2 vUv; + uniform mat3 uvTransform; + +#endif + void main() { + #ifdef USE_POINTS_UV + + vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + + #endif + #include #include #include diff --git a/src/renderers/shaders/ShaderLib/shadow.glsl.js b/src/renderers/shaders/ShaderLib/shadow.glsl.js index 5a0b89e19809a9..69fc2113220ffb 100644 --- a/src/renderers/shaders/ShaderLib/shadow.glsl.js +++ b/src/renderers/shaders/ShaderLib/shadow.glsl.js @@ -3,6 +3,7 @@ export const vertex = /* glsl */` #include #include #include +#include #include void main() { @@ -17,6 +18,7 @@ void main() { #include #include #include + #include #include #include @@ -34,11 +36,14 @@ uniform float opacity; #include #include #include +#include #include #include void main() { + #include + gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) ); #include diff --git a/src/renderers/shaders/UniformsLib.js b/src/renderers/shaders/UniformsLib.js index 6f6864709b8c9a..9b23c3f73d884c 100644 --- a/src/renderers/shaders/UniformsLib.js +++ b/src/renderers/shaders/UniformsLib.js @@ -14,10 +14,11 @@ const UniformsLib = { opacity: { value: 1.0 }, map: { value: null }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() }, - uv2Transform: { value: /*@__PURE__*/ new Matrix3() }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } }, @@ -25,6 +26,7 @@ const UniformsLib = { specularmap: { specularMap: { value: null }, + specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -41,26 +43,23 @@ const UniformsLib = { aomap: { aoMap: { value: null }, - aoMapIntensity: { value: 1 } + aoMapIntensity: { value: 1 }, + aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, lightmap: { lightMap: { value: null }, - lightMapIntensity: { value: 1 } - - }, - - emissivemap: { - - emissiveMap: { value: null } + lightMapIntensity: { value: 1 }, + lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, bumpmap: { bumpMap: { value: null }, + bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, bumpScale: { value: 1 } }, @@ -68,6 +67,7 @@ const UniformsLib = { normalmap: { normalMap: { value: null }, + normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } }, @@ -75,20 +75,30 @@ const UniformsLib = { displacementmap: { displacementMap: { value: null }, + displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, displacementScale: { value: 1 }, displacementBias: { value: 0 } }, - roughnessmap: { + emissivemap: { - roughnessMap: { value: null } + emissiveMap: { value: null }, + emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, metalnessmap: { - metalnessMap: { value: null } + metalnessMap: { value: null }, + metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } + + }, + + roughnessmap: { + + roughnessMap: { value: null }, + roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } }, @@ -195,6 +205,7 @@ const UniformsLib = { scale: { value: 1.0 }, map: { value: null }, alphaMap: { value: null }, + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaTest: { value: 0 }, uvTransform: { value: /*@__PURE__*/ new Matrix3() } @@ -207,9 +218,10 @@ const UniformsLib = { center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, rotation: { value: 0.0 }, map: { value: null }, + mapTransform: { value: /*@__PURE__*/ new Matrix3() }, alphaMap: { value: null }, - alphaTest: { value: 0 }, - uvTransform: { value: /*@__PURE__*/ new Matrix3() } + alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, + alphaTest: { value: 0 } } diff --git a/src/renderers/shaders/UniformsUtils.js b/src/renderers/shaders/UniformsUtils.js index b20b4abd60aa32..b8628bbee035c1 100644 --- a/src/renderers/shaders/UniformsUtils.js +++ b/src/renderers/shaders/UniformsUtils.js @@ -1,4 +1,4 @@ -import { sRGBEncoding, LinearSRGBColorSpace, SRGBColorSpace } from '../../constants.js'; +import { LinearSRGBColorSpace } from '../../constants.js'; /** * Uniform Utilities @@ -21,7 +21,16 @@ export function cloneUniforms( src ) { property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion ) ) { - dst[ u ][ p ] = property.clone(); + if ( property.isRenderTargetTexture ) { + + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; + + } else { + + dst[ u ][ p ] = property.clone(); + + } } else if ( Array.isArray( property ) ) { @@ -80,7 +89,7 @@ export function getUnlitUniformColorSpace( renderer ) { if ( renderer.getRenderTarget() === null ) { // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 - return renderer.outputEncoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; + return renderer.outputColorSpace; } diff --git a/src/renderers/webgl/WebGLBackground.js b/src/renderers/webgl/WebGLBackground.js index 9bb13f1eb41945..a82640f1508799 100644 --- a/src/renderers/webgl/WebGLBackground.js +++ b/src/renderers/webgl/WebGLBackground.js @@ -1,4 +1,4 @@ -import { BackSide, FrontSide, CubeUVReflectionMapping, sRGBEncoding } from '../../constants.js'; +import { BackSide, FrontSide, CubeUVReflectionMapping, SRGBColorSpace } from '../../constants.js'; import { BoxGeometry } from '../../geometries/BoxGeometry.js'; import { PlaneGeometry } from '../../geometries/PlaneGeometry.js'; import { ShaderMaterial } from '../../materials/ShaderMaterial.js'; @@ -33,26 +33,35 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, } - // Ignore background in AR - // TODO: Reconsider this. + if ( background === null ) { - const xr = renderer.xr; - const session = xr.getSession && xr.getSession(); + setClear( clearColor, clearAlpha ); - if ( session && session.environmentBlendMode === 'additive' ) { + } else if ( background && background.isColor ) { - background = null; + setClear( background, 1 ); + forceClear = true; } - if ( background === null ) { + const xr = renderer.xr; + const environmentBlendMode = xr.getEnvironmentBlendMode(); - setClear( clearColor, clearAlpha ); + switch ( environmentBlendMode ) { - } else if ( background && background.isColor ) { + case 'opaque': + forceClear = true; + break; - setClear( background, 1 ); - forceClear = true; + case 'additive': + state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); + forceClear = true; + break; + + case 'alpha-blend': + state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); + forceClear = true; + break; } @@ -108,7 +117,7 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - boxMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + boxMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( currentBackground !== background || currentBackgroundVersion !== background.version || @@ -164,7 +173,7 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, planeMesh.material.uniforms.t2D.value = background; planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; - planeMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; + planeMesh.material.toneMapped = ( background.colorSpace === SRGBColorSpace ) ? false : true; if ( background.matrixAutoUpdate === true ) { diff --git a/src/renderers/webgl/WebGLBindingStates.js b/src/renderers/webgl/WebGLBindingStates.js index cf60caa8f54ad5..0d0571561070c0 100644 --- a/src/renderers/webgl/WebGLBindingStates.js +++ b/src/renderers/webgl/WebGLBindingStates.js @@ -1,4 +1,6 @@ -function WebGLBindingStates( gl, extensions, attributes, capabilities ) { +import { IntType } from '../../constants.js'; + +function WebGLBindingStates( gl, extensions, attributes, capabilities ) { const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); @@ -315,9 +317,9 @@ } - function vertexAttribPointer( index, size, type, normalized, stride, offset ) { + function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { - if ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT ) ) { + if ( integer === true ) { gl.vertexAttribIPointer( index, size, type, stride, offset ); @@ -375,6 +377,10 @@ const type = attribute.type; const bytesPerElement = attribute.bytesPerElement; + // check for integer attributes (WebGL 2 only) + + const integer = ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ) ); + if ( geometryAttribute.isInterleavedBufferAttribute ) { const data = geometryAttribute.data; @@ -415,7 +421,8 @@ type, normalized, stride * bytesPerElement, - ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement + ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, + integer ); } @@ -456,7 +463,8 @@ type, normalized, size * bytesPerElement, - ( size / programAttribute.locationSize ) * i * bytesPerElement + ( size / programAttribute.locationSize ) * i * bytesPerElement, + integer ); } diff --git a/src/renderers/webgl/WebGLCapabilities.js b/src/renderers/webgl/WebGLCapabilities.js index 2ff5123fc45792..ca4c2dd5aa8edd 100644 --- a/src/renderers/webgl/WebGLCapabilities.js +++ b/src/renderers/webgl/WebGLCapabilities.js @@ -52,7 +52,7 @@ function WebGLCapabilities( gl, extensions, parameters ) { } - const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; + const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl.constructor.name === 'WebGL2RenderingContext'; let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; const maxPrecision = getMaxPrecision( precision ); diff --git a/src/renderers/webgl/WebGLGeometries.js b/src/renderers/webgl/WebGLGeometries.js index 51781472d0d779..7321ef1fd2a38c 100644 --- a/src/renderers/webgl/WebGLGeometries.js +++ b/src/renderers/webgl/WebGLGeometries.js @@ -22,6 +22,18 @@ function WebGLGeometries( gl, attributes, info, bindingStates ) { } + for ( const name in geometry.morphAttributes ) { + + const array = geometry.morphAttributes[ name ]; + + for ( let i = 0, l = array.length; i < l; i ++ ) { + + attributes.remove( array[ i ] ); + + } + + } + geometry.removeEventListener( 'dispose', onGeometryDispose ); delete geometries[ geometry.id ]; diff --git a/src/renderers/webgl/WebGLInfo.js b/src/renderers/webgl/WebGLInfo.js index 6cbfe413409525..30364091d21510 100644 --- a/src/renderers/webgl/WebGLInfo.js +++ b/src/renderers/webgl/WebGLInfo.js @@ -49,7 +49,6 @@ function WebGLInfo( gl ) { function reset() { - render.frame ++; render.calls = 0; render.triangles = 0; render.points = 0; diff --git a/src/renderers/webgl/WebGLLights.js b/src/renderers/webgl/WebGLLights.js index 2f0df97ae7381c..de48b309fee46e 100644 --- a/src/renderers/webgl/WebGLLights.js +++ b/src/renderers/webgl/WebGLLights.js @@ -202,7 +202,7 @@ function WebGLLights( extensions, capabilities ) { const matrix4 = new Matrix4(); const matrix42 = new Matrix4(); - function setup( lights, physicallyCorrectLights ) { + function setup( lights, useLegacyLights ) { let r = 0, g = 0, b = 0; @@ -224,7 +224,7 @@ function WebGLLights( extensions, capabilities ) { lights.sort( shadowCastingAndTexturingLightsFirst ); // artist-friendly light intensity scaling factor - const scaleFactor = ( physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1; for ( let i = 0, l = lights.length; i < l; i ++ ) { diff --git a/src/renderers/webgl/WebGLMaterials.js b/src/renderers/webgl/WebGLMaterials.js index 2f249bb1d0afeb..207460de8e32e8 100644 --- a/src/renderers/webgl/WebGLMaterials.js +++ b/src/renderers/webgl/WebGLMaterials.js @@ -3,6 +3,18 @@ import { getUnlitUniformColorSpace } from '../shaders/UniformsUtils.js'; function WebGLMaterials( renderer, properties ) { + function refreshTransformUniform( map, uniform ) { + + if ( map.matrixAutoUpdate === true ) { + + map.updateMatrix(); + + } + + uniform.value.copy( map.matrix ); + + } + function refreshFogUniforms( uniforms, fog ) { fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); @@ -120,25 +132,56 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.bumpMap ) { uniforms.bumpMap.value = material.bumpMap; + + refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); + uniforms.bumpScale.value = material.bumpScale; - if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; + + if ( material.side === BackSide ) { + + uniforms.bumpScale.value *= - 1; + + } + + } + + if ( material.normalMap ) { + + uniforms.normalMap.value = material.normalMap; + + refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); + + uniforms.normalScale.value.copy( material.normalScale ); + + if ( material.side === BackSide ) { + + uniforms.normalScale.value.negate(); + + } } if ( material.displacementMap ) { uniforms.displacementMap.value = material.displacementMap; + + refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); + uniforms.displacementScale.value = material.displacementScale; uniforms.displacementBias.value = material.displacementBias; @@ -148,13 +191,7 @@ function WebGLMaterials( renderer, properties ) { uniforms.emissiveMap.value = material.emissiveMap; - } - - if ( material.normalMap ) { - - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); - if ( material.side === BackSide ) uniforms.normalScale.value.negate(); + refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); } @@ -162,6 +199,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.specularMap.value = material.specularMap; + refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -189,10 +228,12 @@ function WebGLMaterials( renderer, properties ) { uniforms.lightMap.value = material.lightMap; // artist-friendly light intensity scaling factor - const scaleFactor = ( renderer.physicallyCorrectLights !== true ) ? Math.PI : 1; + const scaleFactor = ( renderer.useLegacyLights === true ) ? Math.PI : 1; uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; + refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); + } if ( material.aoMap ) { @@ -200,175 +241,27 @@ function WebGLMaterials( renderer, properties ) { uniforms.aoMap.value = material.aoMap; uniforms.aoMapIntensity.value = material.aoMapIntensity; - } - - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. displacementMap map - // 4. normal map - // 5. bump map - // 6. roughnessMap map - // 7. metalnessMap map - // 8. alphaMap map - // 9. emissiveMap map - // 10. clearcoat map - // 11. clearcoat normal map - // 12. clearcoat roughnessMap map - // 13. iridescence map - // 14. iridescence thickness map - // 15. specular intensity map - // 16. specular tint map - // 17. transmission map - // 18. thickness map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.specularMap ) { - - uvScaleMap = material.specularMap; - - } else if ( material.displacementMap ) { - - uvScaleMap = material.displacementMap; - - } else if ( material.normalMap ) { - - uvScaleMap = material.normalMap; - - } else if ( material.bumpMap ) { - - uvScaleMap = material.bumpMap; - - } else if ( material.roughnessMap ) { - - uvScaleMap = material.roughnessMap; - - } else if ( material.metalnessMap ) { - - uvScaleMap = material.metalnessMap; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } else if ( material.emissiveMap ) { - - uvScaleMap = material.emissiveMap; - - } else if ( material.clearcoatMap ) { - - uvScaleMap = material.clearcoatMap; - - } else if ( material.clearcoatNormalMap ) { - - uvScaleMap = material.clearcoatNormalMap; - - } else if ( material.clearcoatRoughnessMap ) { - - uvScaleMap = material.clearcoatRoughnessMap; - - } else if ( material.iridescenceMap ) { - - uvScaleMap = material.iridescenceMap; - - } else if ( material.iridescenceThicknessMap ) { - - uvScaleMap = material.iridescenceThicknessMap; - - } else if ( material.specularIntensityMap ) { - - uvScaleMap = material.specularIntensityMap; - - } else if ( material.specularColorMap ) { - - uvScaleMap = material.specularColorMap; - - } else if ( material.transmissionMap ) { - - uvScaleMap = material.transmissionMap; - - } else if ( material.thicknessMap ) { - - uvScaleMap = material.thicknessMap; - - } else if ( material.sheenColorMap ) { - - uvScaleMap = material.sheenColorMap; - - } else if ( material.sheenRoughnessMap ) { - - uvScaleMap = material.sheenRoughnessMap; + refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); } - if ( uvScaleMap !== undefined ) { - - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { - - uvScaleMap = uvScaleMap.texture; - - } - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - - // uv repeat and offset setting priorities for uv2 - // 1. ao map - // 2. light map - - let uv2ScaleMap; - - if ( material.aoMap ) { - - uv2ScaleMap = material.aoMap; - - } else if ( material.lightMap ) { - - uv2ScaleMap = material.lightMap; - - } - - if ( uv2ScaleMap !== undefined ) { - - // backwards compatibility - if ( uv2ScaleMap.isWebGLRenderTarget ) { - - uv2ScaleMap = uv2ScaleMap.texture; + } - } + function refreshUniformsLine( uniforms, material ) { - if ( uv2ScaleMap.matrixAutoUpdate === true ) { + uniforms.diffuse.value.copy( material.color ); + uniforms.opacity.value = material.opacity; - uv2ScaleMap.updateMatrix(); + if ( material.map ) { - } + uniforms.map.value = material.map; - uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix ); + refreshTransformUniform( material.map, uniforms.mapTransform ); } } - function refreshUniformsLine( uniforms, material ) { - - uniforms.diffuse.value.copy( material.color ); - uniforms.opacity.value = material.opacity; - - } - function refreshUniformsDash( uniforms, material ) { uniforms.dashSize.value = material.dashSize; @@ -388,12 +281,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.uvTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -402,34 +299,6 @@ function WebGLMaterials( renderer, properties ) { } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsSprites( uniforms, material ) { @@ -442,12 +311,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.map.value = material.map; + refreshTransformUniform( material.map, uniforms.mapTransform ); + } if ( material.alphaMap ) { uniforms.alphaMap.value = material.alphaMap; + refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); + } if ( material.alphaTest > 0 ) { @@ -456,34 +329,6 @@ function WebGLMaterials( renderer, properties ) { } - // uv repeat and offset setting priorities - // 1. color map - // 2. alpha map - - let uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } - - if ( uvScaleMap !== undefined ) { - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - uvScaleMap.updateMatrix(); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - } function refreshUniformsPhong( uniforms, material ) { @@ -505,18 +350,23 @@ function WebGLMaterials( renderer, properties ) { function refreshUniformsStandard( uniforms, material ) { - uniforms.roughness.value = material.roughness; uniforms.metalness.value = material.metalness; - if ( material.roughnessMap ) { + if ( material.metalnessMap ) { - uniforms.roughnessMap.value = material.roughnessMap; + uniforms.metalnessMap.value = material.metalnessMap; + + refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); } - if ( material.metalnessMap ) { + uniforms.roughness.value = material.roughness; - uniforms.metalnessMap.value = material.metalnessMap; + if ( material.roughnessMap ) { + + uniforms.roughnessMap.value = material.roughnessMap; + + refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); } @@ -545,12 +395,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.sheenColorMap.value = material.sheenColorMap; + refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); + } if ( material.sheenRoughnessMap ) { uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; + refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); + } } @@ -564,19 +418,26 @@ function WebGLMaterials( renderer, properties ) { uniforms.clearcoatMap.value = material.clearcoatMap; + refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); + } if ( material.clearcoatRoughnessMap ) { uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; + refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); + } if ( material.clearcoatNormalMap ) { - uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; + refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); + + uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); + if ( material.side === BackSide ) { uniforms.clearcoatNormalScale.value.negate(); @@ -598,12 +459,16 @@ function WebGLMaterials( renderer, properties ) { uniforms.iridescenceMap.value = material.iridescenceMap; + refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); + } if ( material.iridescenceThicknessMap ) { uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; + refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); + } } @@ -618,6 +483,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.transmissionMap.value = material.transmissionMap; + refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); + } uniforms.thickness.value = material.thickness; @@ -626,6 +493,8 @@ function WebGLMaterials( renderer, properties ) { uniforms.thicknessMap.value = material.thicknessMap; + refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); + } uniforms.attenuationDistance.value = material.attenuationDistance; @@ -633,19 +502,37 @@ function WebGLMaterials( renderer, properties ) { } - uniforms.specularIntensity.value = material.specularIntensity; - uniforms.specularColor.value.copy( material.specularColor ); + if ( material.anisotropy > 0 ) { - if ( material.specularIntensityMap ) { + uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - uniforms.specularIntensityMap.value = material.specularIntensityMap; + if ( material.anisotropyMap ) { + + uniforms.anisotropyMap.value = material.anisotropyMap; + + refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); + + } } + uniforms.specularIntensity.value = material.specularIntensity; + uniforms.specularColor.value.copy( material.specularColor ); + if ( material.specularColorMap ) { uniforms.specularColorMap.value = material.specularColorMap; + refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); + + } + + if ( material.specularIntensityMap ) { + + uniforms.specularIntensityMap.value = material.specularIntensityMap; + + refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); + } } @@ -662,9 +549,11 @@ function WebGLMaterials( renderer, properties ) { function refreshUniformsDistance( uniforms, material ) { - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; + const light = properties.get( material ).light; + + uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); + uniforms.nearDistance.value = light.shadow.camera.near; + uniforms.farDistance.value = light.shadow.camera.far; } diff --git a/src/renderers/webgl/WebGLMorphtargets.js b/src/renderers/webgl/WebGLMorphtargets.js index 4fb585a138b98f..5ea7fdd961a095 100644 --- a/src/renderers/webgl/WebGLMorphtargets.js +++ b/src/renderers/webgl/WebGLMorphtargets.js @@ -30,7 +30,7 @@ function WebGLMorphtargets( gl, capabilities, textures ) { } - function update( object, geometry, material, program ) { + function update( object, geometry, program ) { const objectInfluences = object.morphTargetInfluences; diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 56b261d49b27aa..c90064186f0a75 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -1,7 +1,7 @@ import { WebGLUniforms } from './WebGLUniforms.js'; import { WebGLShader } from './WebGLShader.js'; import { ShaderChunk } from '../shaders/ShaderChunk.js'; -import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, CubeRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, CustomToneMapping, ReinhardToneMapping, LinearToneMapping, sRGBEncoding, LinearEncoding, GLSL3 } from '../../constants.js'; +import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, CubeRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, CustomToneMapping, ReinhardToneMapping, LinearToneMapping, GLSL3, LinearSRGBColorSpace, SRGBColorSpace } from '../../constants.js'; let programIdCount = 0; @@ -24,16 +24,16 @@ function handleSource( string, errorLine ) { } -function getEncodingComponents( encoding ) { +function getEncodingComponents( colorSpace ) { - switch ( encoding ) { + switch ( colorSpace ) { - case LinearEncoding: + case LinearSRGBColorSpace: return [ 'Linear', '( value )' ]; - case sRGBEncoding: + case SRGBColorSpace: return [ 'sRGB', '( value )' ]; default: - console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding ); + console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); return [ 'Linear', '( value )' ]; } @@ -64,9 +64,9 @@ function getShaderErrors( gl, shader, type ) { } -function getTexelEncodingFunction( functionName, encoding ) { +function getTexelEncodingFunction( functionName, colorSpace ) { - const components = getEncodingComponents( encoding ); + const components = getEncodingComponents( colorSpace ); return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; } @@ -110,7 +110,7 @@ function getToneMappingFunction( functionName, toneMapping ) { function generateExtensions( parameters ) { const chunks = [ - ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', + ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.normalMapTangentSpace || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '', ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '', ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : '' @@ -418,6 +418,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { prefixVertex = [ + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -431,6 +434,10 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { prefixFragment = [ customExtensions, + + '#define SHADER_TYPE ' + parameters.shaderType, + '#define SHADER_NAME ' + parameters.shaderName, + customDefines ].filter( filterEmptyLine ).join( '\n' ); @@ -447,6 +454,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, @@ -454,21 +462,22 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.instancing ? '#define USE_INSTANCING' : '', parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', - - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', @@ -477,11 +486,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', - parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -491,14 +498,52 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', + + // + + parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', + parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', + parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', + parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', + parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', + parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', + parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', + parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', + + parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', + parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', + + parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', + + parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', + parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', + parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', + + parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', + parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', + + parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', + parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', + + parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', + parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', + parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', + + parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', + parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', + + // parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', @@ -518,6 +563,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', + parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -545,6 +592,24 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { 'attribute vec3 normal;', 'attribute vec2 uv;', + '#ifdef USE_UV1', + + ' attribute vec2 uv1;', + + '#endif', + + '#ifdef USE_UV2', + + ' attribute vec2 uv2;', + + '#endif', + + '#ifdef USE_UV3', + + ' attribute vec2 uv3;', + + '#endif', + '#ifdef USE_TANGENT', ' attribute vec4 tangent;', @@ -596,18 +661,20 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { '\n' ].filter( filterEmptyLine ).join( '\n' ); + prefixFragment = [ customExtensions, generatePrecision( parameters ), + '#define SHADER_TYPE ' + parameters.shaderType, '#define SHADER_NAME ' + parameters.shaderName, customDefines, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', + parameters.useFog && parameters.fog ? '#define USE_FOG' : '', + parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.matcap ? '#define USE_MATCAP' : '', @@ -620,11 +687,14 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', - ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', - ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', + parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', + parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', + parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', + + parameters.anisotropy ? '#define USE_ANISOTROPY' : '', + parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', parameters.clearcoat ? '#define USE_CLEARCOAT' : '', parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', @@ -636,8 +706,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', - parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', + parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', + parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', + parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', @@ -645,20 +716,21 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.alphaTest ? '#define USE_ALPHATEST' : '', parameters.sheen ? '#define USE_SHEEN' : '', - parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', - parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', + parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', + parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', parameters.transmission ? '#define USE_TRANSMISSION' : '', parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', - parameters.vertexTangents ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', - parameters.vertexUvs ? '#define USE_UV' : '', - parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', + parameters.vertexUv1s ? '#define USE_UV1' : '', + parameters.vertexUv2s ? '#define USE_UV2' : '', + parameters.vertexUv3s ? '#define USE_UV3' : '', + + parameters.pointsUvs ? '#define USE_POINTS_UV' : '', parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', @@ -672,7 +744,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', - parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', + parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', @@ -689,7 +761,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.opaque ? '#define OPAQUE' : '', ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below - getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ), + getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', @@ -699,14 +771,6 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { } - if ( renderer.onShaderBeforeResolve ) { - - const ret = renderer.onShaderBeforeResolve( vertexShader, fragmentShader, parameters ); - vertexShader = ret.vertexShader; - fragmentShader = ret.fragmentShader; - - } - vertexShader = resolveIncludes( vertexShader ); vertexShader = replaceLightNums( vertexShader, parameters ); vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); @@ -749,16 +813,9 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { } - let vertexGlsl = versionString + prefixVertex + vertexShader; - let fragmentGlsl = versionString + prefixFragment + fragmentShader; - - if ( renderer.onShaderBeforeCompile ) { - - const ret = renderer.onShaderBeforeCompile( vertexGlsl, fragmentGlsl, parameters ); - vertexGlsl = ret.vertexShader; - fragmentGlsl = ret.fragmentShader; + const vertexGlsl = versionString + prefixVertex + vertexShader; + const fragmentGlsl = versionString + prefixFragment + fragmentShader; - } // console.log( '*VERTEX*', vertexGlsl ); // console.log( '*FRAGMENT*', fragmentGlsl ); @@ -797,16 +854,26 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { runnable = false; - const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); - const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + if ( typeof renderer.debug.onShaderError === 'function' ) { + + renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); + + } else { + + // default error reporting + + const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); + + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); - console.error( - 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + - 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + - 'Program Info Log: ' + programLog + '\n' + - vertexErrors + '\n' + - fragmentErrors - ); + } } else if ( programLog !== '' ) { @@ -900,6 +967,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { // + this.type = parameters.shaderType; this.name = parameters.shaderName; this.id = programIdCount ++; this.cacheKey = cacheKey; diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index e1140b871764b2..cf07ee3fc94656 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -1,4 +1,4 @@ -import { BackSide, DoubleSide, CubeUVReflectionMapping, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, LinearEncoding, sRGBEncoding, NormalBlending } from '../../constants.js'; +import { BackSide, DoubleSide, CubeUVReflectionMapping, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, NormalBlending, LinearSRGBColorSpace } from '../../constants.js'; import { Layers } from '../../core/Layers.js'; import { WebGLProgram } from './WebGLProgram.js'; import { WebGLShaderCache } from './WebGLShaderCache.js'; @@ -11,9 +11,10 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const _customShaders = new WebGLShaderCache(); const programs = []; - const isWebGL2 = capabilities.isWebGL2; + const IS_WEBGL2 = capabilities.isWebGL2; const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; - const vertexTextures = capabilities.vertexTextures; + const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; + let precision = capabilities.precision; const shaderIDs = { @@ -34,6 +35,14 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities SpriteMaterial: 'sprite' }; + function getChannel( value ) { + + if ( value === 0 ) return 'uv'; + + return `uv${ value }`; + + } + function getParameters( material, lights, shadows, scene, object ) { const fog = scene.fog; @@ -97,16 +106,65 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const currentRenderTarget = renderer.getRenderTarget(); - const useAlphaTest = material.alphaTest > 0; - const useClearcoat = material.clearcoat > 0; - const useIridescence = material.iridescence > 0; + const IS_INSTANCEDMESH = object.isInstancedMesh === true; + + const HAS_MAP = !! material.map; + const HAS_MATCAP = !! material.matcap; + const HAS_ENVMAP = !! envMap; + const HAS_AOMAP = !! material.aoMap; + const HAS_LIGHTMAP = !! material.lightMap; + const HAS_BUMPMAP = !! material.bumpMap; + const HAS_NORMALMAP = !! material.normalMap; + const HAS_DISPLACEMENTMAP = !! material.displacementMap; + const HAS_EMISSIVEMAP = !! material.emissiveMap; + + const HAS_METALNESSMAP = !! material.metalnessMap; + const HAS_ROUGHNESSMAP = !! material.roughnessMap; + + const HAS_ANISOTROPY = material.anisotropy > 0; + const HAS_CLEARCOAT = material.clearcoat > 0; + const HAS_IRIDESCENCE = material.iridescence > 0; + const HAS_SHEEN = material.sheen > 0; + const HAS_TRANSMISSION = material.transmission > 0; + + const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; + + const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; + const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; + const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; + + const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; + const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; + + const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; + const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; + + const HAS_SPECULARMAP = !! material.specularMap; + const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; + const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; + + const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; + const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; + + const HAS_GRADIENTMAP = !! material.gradientMap; + + const HAS_ALPHAMAP = !! material.alphaMap; + + const HAS_ALPHATEST = material.alphaTest > 0; + + const HAS_EXTENSIONS = !! material.extensions; + + const HAS_ATTRIBUTE_UV1 = !! geometry.attributes.uv1; + const HAS_ATTRIBUTE_UV2 = !! geometry.attributes.uv2; + const HAS_ATTRIBUTE_UV3 = !! geometry.attributes.uv3; const parameters = { - isWebGL2: isWebGL2, + isWebGL2: IS_WEBGL2, shaderID: shaderID, - shaderName: material.type, + shaderType: material.type, + shaderName: material.name, vertexShader: vertexShader, fragmentShader: fragmentShader, @@ -120,72 +178,115 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities precision: precision, - instancing: object.isInstancedMesh === true, - instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, + instancing: IS_INSTANCEDMESH, + instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, + + supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, + outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), - supportsVertexTextures: vertexTextures, - outputEncoding: ( currentRenderTarget === null ) ? renderer.outputEncoding : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding ), - map: !! material.map, - matcap: !! material.matcap, - envMap: !! envMap, - envMapMode: envMap && envMap.mapping, + map: HAS_MAP, + matcap: HAS_MATCAP, + envMap: HAS_ENVMAP, + envMapMode: HAS_ENVMAP && envMap.mapping, envMapCubeUVHeight: envMapCubeUVHeight, - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, - tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, - - decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ), - - clearcoat: useClearcoat, - clearcoatMap: useClearcoat && !! material.clearcoatMap, - clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap, - clearcoatNormalMap: useClearcoat && !! material.clearcoatNormalMap, - - iridescence: useIridescence, - iridescenceMap: useIridescence && !! material.iridescenceMap, - iridescenceThicknessMap: useIridescence && !! material.iridescenceThicknessMap, - - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - specularIntensityMap: !! material.specularIntensityMap, - specularColorMap: !! material.specularColorMap, + aoMap: HAS_AOMAP, + lightMap: HAS_LIGHTMAP, + bumpMap: HAS_BUMPMAP, + normalMap: HAS_NORMALMAP, + displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, + emissiveMap: HAS_EMISSIVEMAP, - opaque: material.transparent === false && material.blending === NormalBlending, + normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, + normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, + + metalnessMap: HAS_METALNESSMAP, + roughnessMap: HAS_ROUGHNESSMAP, - alphaMap: !! material.alphaMap, - alphaTest: useAlphaTest, + anisotropy: HAS_ANISOTROPY, + anisotropyMap: HAS_ANISOTROPYMAP, - gradientMap: !! material.gradientMap, + clearcoat: HAS_CLEARCOAT, + clearcoatMap: HAS_CLEARCOATMAP, + clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, + clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, - sheen: material.sheen > 0, - sheenColorMap: !! material.sheenColorMap, - sheenRoughnessMap: !! material.sheenRoughnessMap, + iridescence: HAS_IRIDESCENCE, + iridescenceMap: HAS_IRIDESCENCEMAP, + iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, - transmission: material.transmission > 0, - transmissionMap: !! material.transmissionMap, - thicknessMap: !! material.thicknessMap, + sheen: HAS_SHEEN, + sheenColorMap: HAS_SHEEN_COLORMAP, + sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, + + specularMap: HAS_SPECULARMAP, + specularColorMap: HAS_SPECULAR_COLORMAP, + specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, + + transmission: HAS_TRANSMISSION, + transmissionMap: HAS_TRANSMISSIONMAP, + thicknessMap: HAS_THICKNESSMAP, + + gradientMap: HAS_GRADIENTMAP, + + opaque: material.transparent === false && material.blending === NormalBlending, + + alphaMap: HAS_ALPHAMAP, + alphaTest: HAS_ALPHATEST, combine: material.combine, - vertexTangents: ( !! material.normalMap && !! geometry.attributes.tangent ), + // + + mapUv: HAS_MAP && getChannel( material.map.channel ), + aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), + lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), + bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), + normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), + displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), + emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), + + metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), + roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), + + anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), + + clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), + clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), + clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), + + iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), + iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), + + sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), + sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), + + specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), + specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), + specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), + + transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), + thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), + + alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), + + // + + vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), vertexColors: material.vertexColors, vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, - vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || !! material.displacementMap || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheenColorMap || !! material.sheenRoughnessMap, - uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || material.transmission > 0 || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || material.sheen > 0 || !! material.sheenColorMap || !! material.sheenRoughnessMap ) && !! material.displacementMap, + vertexUv1s: HAS_ATTRIBUTE_UV1, + vertexUv2s: HAS_ATTRIBUTE_UV2, + vertexUv3s: HAS_ATTRIBUTE_UV3, + + pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), fog: !! fog, useFog: material.fog === true, fogExp2: ( fog && fog.isFogExp2 ), - flatShading: !! material.flatShading, + flatShading: material.flatShading === true, - sizeAttenuation: material.sizeAttenuation, + sizeAttenuation: material.sizeAttenuation === true, logarithmicDepthBuffer: logarithmicDepthBuffer, skinning: object.isSkinnedMesh === true, @@ -217,30 +318,28 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities shadowMapType: renderer.shadowMap.type, toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, + useLegacyLights: renderer.useLegacyLights, premultipliedAlpha: material.premultipliedAlpha, doubleSided: material.side === DoubleSide, flipSided: material.side === BackSide, - useDepthPacking: !! material.depthPacking, + useDepthPacking: material.depthPacking >= 0, depthPacking: material.depthPacking || 0, index0AttributeName: material.index0AttributeName, - extensionDerivatives: material.extensions && material.extensions.derivatives, - extensionFragDepth: material.extensions && material.extensions.fragDepth, - extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, - extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, - - rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ), - rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ), - rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ), + extensionDerivatives: HAS_EXTENSIONS && material.extensions.derivatives === true, + extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true, + extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true, + extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true, - customProgramCacheKey: material.customProgramCacheKey(), + rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ), + rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ), + rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ), - extraProgramCacheKey: renderer.extraProgramCacheKey + customProgramCacheKey: material.customProgramCacheKey() }; @@ -278,18 +377,12 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities getProgramCacheKeyParameters( array, parameters ); getProgramCacheKeyBooleans( array, parameters ); - array.push( renderer.outputEncoding ); + array.push( renderer.outputColorSpace ); } array.push( parameters.customProgramCacheKey ); - if ( renderer.extraProgramCacheKey ) { - - array.push( renderer.extraProgramCacheKey ); - - } - return array.join(); } @@ -297,11 +390,33 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities function getProgramCacheKeyParameters( array, parameters ) { array.push( parameters.precision ); - array.push( parameters.outputEncoding ); + array.push( parameters.outputColorSpace ); array.push( parameters.envMapMode ); array.push( parameters.envMapCubeUVHeight ); + array.push( parameters.mapUv ); + array.push( parameters.alphaMapUv ); + array.push( parameters.lightMapUv ); + array.push( parameters.aoMapUv ); + array.push( parameters.bumpMapUv ); + array.push( parameters.normalMapUv ); + array.push( parameters.displacementMapUv ); + array.push( parameters.emissiveMapUv ); + array.push( parameters.metalnessMapUv ); + array.push( parameters.roughnessMapUv ); + array.push( parameters.anisotropyMapUv ); + array.push( parameters.clearcoatMapUv ); + array.push( parameters.clearcoatNormalMapUv ); + array.push( parameters.clearcoatRoughnessMapUv ); + array.push( parameters.iridescenceMapUv ); + array.push( parameters.iridescenceThicknessMapUv ); + array.push( parameters.sheenColorMapUv ); + array.push( parameters.sheenRoughnessMapUv ); + array.push( parameters.specularMapUv ); + array.push( parameters.specularColorMapUv ); + array.push( parameters.specularIntensityMapUv ); + array.push( parameters.transmissionMapUv ); + array.push( parameters.thicknessMapUv ); array.push( parameters.combine ); - array.push( parameters.vertexUvs ); array.push( parameters.fogExp2 ); array.push( parameters.sizeAttenuation ); array.push( parameters.morphTargetsCount ); @@ -336,64 +451,34 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 2 ); if ( parameters.instancingColor ) _programLayers.enable( 3 ); - if ( parameters.map ) - _programLayers.enable( 4 ); if ( parameters.matcap ) - _programLayers.enable( 5 ); + _programLayers.enable( 4 ); if ( parameters.envMap ) + _programLayers.enable( 5 ); + if ( parameters.normalMapObjectSpace ) _programLayers.enable( 6 ); - if ( parameters.lightMap ) + if ( parameters.normalMapTangentSpace ) _programLayers.enable( 7 ); - if ( parameters.aoMap ) + if ( parameters.clearcoat ) _programLayers.enable( 8 ); - if ( parameters.emissiveMap ) + if ( parameters.iridescence ) _programLayers.enable( 9 ); - if ( parameters.bumpMap ) + if ( parameters.alphaTest ) _programLayers.enable( 10 ); - if ( parameters.normalMap ) + if ( parameters.vertexColors ) _programLayers.enable( 11 ); - if ( parameters.objectSpaceNormalMap ) + if ( parameters.vertexAlphas ) _programLayers.enable( 12 ); - if ( parameters.tangentSpaceNormalMap ) + if ( parameters.vertexUv1s ) _programLayers.enable( 13 ); - if ( parameters.clearcoat ) + if ( parameters.vertexUv2s ) _programLayers.enable( 14 ); - if ( parameters.clearcoatMap ) + if ( parameters.vertexUv3s ) _programLayers.enable( 15 ); - if ( parameters.clearcoatRoughnessMap ) + if ( parameters.vertexTangents ) _programLayers.enable( 16 ); - if ( parameters.clearcoatNormalMap ) + if ( parameters.anisotropy ) _programLayers.enable( 17 ); - if ( parameters.iridescence ) - _programLayers.enable( 18 ); - if ( parameters.iridescenceMap ) - _programLayers.enable( 19 ); - if ( parameters.iridescenceThicknessMap ) - _programLayers.enable( 20 ); - if ( parameters.displacementMap ) - _programLayers.enable( 21 ); - if ( parameters.specularMap ) - _programLayers.enable( 22 ); - if ( parameters.roughnessMap ) - _programLayers.enable( 23 ); - if ( parameters.metalnessMap ) - _programLayers.enable( 24 ); - if ( parameters.gradientMap ) - _programLayers.enable( 25 ); - if ( parameters.alphaMap ) - _programLayers.enable( 26 ); - if ( parameters.alphaTest ) - _programLayers.enable( 27 ); - if ( parameters.vertexColors ) - _programLayers.enable( 28 ); - if ( parameters.vertexAlphas ) - _programLayers.enable( 29 ); - if ( parameters.vertexUvs ) - _programLayers.enable( 30 ); - if ( parameters.vertexTangents ) - _programLayers.enable( 31 ); - if ( parameters.uvsVertexOnly ) - _programLayers.enable( 32 ); array.push( _programLayers.mask ); _programLayers.disableAll(); @@ -418,7 +503,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 8 ); if ( parameters.shadowMapEnabled ) _programLayers.enable( 9 ); - if ( parameters.physicallyCorrectLights ) + if ( parameters.useLegacyLights ) _programLayers.enable( 10 ); if ( parameters.doubleSided ) _programLayers.enable( 11 ); @@ -428,26 +513,14 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 13 ); if ( parameters.dithering ) _programLayers.enable( 14 ); - if ( parameters.specularIntensityMap ) + if ( parameters.transmission ) _programLayers.enable( 15 ); - if ( parameters.specularColorMap ) + if ( parameters.sheen ) _programLayers.enable( 16 ); - if ( parameters.transmission ) + if ( parameters.opaque ) _programLayers.enable( 17 ); - if ( parameters.transmissionMap ) + if ( parameters.pointsUvs ) _programLayers.enable( 18 ); - if ( parameters.thicknessMap ) - _programLayers.enable( 19 ); - if ( parameters.sheen ) - _programLayers.enable( 20 ); - if ( parameters.sheenColorMap ) - _programLayers.enable( 21 ); - if ( parameters.sheenRoughnessMap ) - _programLayers.enable( 22 ); - if ( parameters.decodeVideoTexture ) - _programLayers.enable( 23 ); - if ( parameters.opaque ) - _programLayers.enable( 24 ); array.push( _programLayers.mask ); @@ -546,5 +619,4 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } - export { WebGLPrograms }; diff --git a/src/renderers/webgl/WebGLRenderStates.js b/src/renderers/webgl/WebGLRenderStates.js index a04199744aabfc..dec59885fa115e 100644 --- a/src/renderers/webgl/WebGLRenderStates.js +++ b/src/renderers/webgl/WebGLRenderStates.js @@ -26,9 +26,9 @@ function WebGLRenderState( extensions, capabilities ) { } - function setupLights( physicallyCorrectLights ) { + function setupLights( useLegacyLights ) { - lights.setup( lightsArray, physicallyCorrectLights ); + lights.setup( lightsArray, useLegacyLights ); } diff --git a/src/renderers/webgl/WebGLShadowMap.js b/src/renderers/webgl/WebGLShadowMap.js index 93fd4fe9f671c4..f1171f2ca251e5 100644 --- a/src/renderers/webgl/WebGLShadowMap.js +++ b/src/renderers/webgl/WebGLShadowMap.js @@ -67,6 +67,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { this.needsUpdate = false; this.type = PCFShadowMap; + let _previousType = this.type; this.render = function ( lights, scene, camera ) { @@ -87,6 +88,11 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { _state.buffers.depth.setTest( true ); _state.setScissorTest( false ); + // check for shadow map type changes + + const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); + const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); + // render depth map for ( let i = 0, il = lights.length; i < il; i ++ ) { @@ -131,10 +137,16 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } - if ( shadow.map === null ) { + if ( shadow.map === null || toVSM === true || fromVSM === true ) { const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; + if ( shadow.map !== null ) { + + shadow.map.dispose(); + + } + shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); shadow.map.texture.name = light.name + '.shadowMap'; @@ -180,6 +192,8 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } + _previousType = this.type; + scope.needsUpdate = false; _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); @@ -226,7 +240,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } - function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) { + function getDepthMaterial( object, material, light, type ) { let result = null; @@ -304,9 +318,8 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { - result.referencePosition.setFromMatrixPosition( light.matrixWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; + const materialProperties = _renderer.properties.get( result ); + materialProperties.light = light; } @@ -340,7 +353,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { if ( groupMaterial && groupMaterial.visible ) { - const depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); @@ -350,7 +363,7 @@ function WebGLShadowMap( _renderer, _objects, _capabilities ) { } else if ( material.visible ) { - const depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type ); + const depthMaterial = getDepthMaterial( object, material, light, type ); _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); diff --git a/src/renderers/webgl/WebGLState.js b/src/renderers/webgl/WebGLState.js index e5d08fa542e1c9..486ecd695e00c0 100644 --- a/src/renderers/webgl/WebGLState.js +++ b/src/renderers/webgl/WebGLState.js @@ -362,7 +362,7 @@ function WebGLState( gl, extensions, capabilities ) { const currentScissor = new Vector4().fromArray( scissorParam ); const currentViewport = new Vector4().fromArray( viewportParam ); - function createTexture( type, target, count ) { + function createTexture( type, target, count, dimensions ) { const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. const texture = gl.createTexture(); @@ -373,7 +373,15 @@ function WebGLState( gl, extensions, capabilities ) { for ( let i = 0; i < count; i ++ ) { - gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + if ( isWebGL2 && ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) ) { + + gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } else { + + gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + } } @@ -385,6 +393,13 @@ function WebGLState( gl, extensions, capabilities ) { emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); + if ( isWebGL2 ) { + + emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); + emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); + + } + // init colorBuffer.setClear( 0, 0, 0, 1 ); diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index a66b99febb252d..11ba4c408631d0 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -1,4 +1,4 @@ -import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, sRGBEncoding, LinearEncoding, UnsignedByteType, _SRGBAFormat } from '../../constants.js'; +import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, UnsignedByteType, _SRGBAFormat, NoColorSpace, LinearSRGBColorSpace, SRGBColorSpace, NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare } from '../../constants.js'; import * as MathUtils from '../../math/MathUtils.js'; import { ImageUtils } from '../../extras/ImageUtils.js'; import { createElementNS } from '../../utils.js'; @@ -135,7 +135,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, encoding, forceLinearEncoding = false ) { + function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { if ( isWebGL2 === false ) return glFormat; @@ -169,7 +169,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; - if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( encoding === sRGBEncoding && forceLinearEncoding === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( colorSpace === SRGBColorSpace && forceLinearTransfer === false ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; @@ -426,7 +426,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, array.push( texture.premultiplyAlpha ); array.push( texture.flipY ); array.push( texture.unpackAlignment ); - array.push( texture.encoding ); + array.push( texture.colorSpace ); return array.join(); @@ -526,6 +526,17 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR }; + const compareToGL = { + [ NeverCompare ]: _gl.NEVER, + [ AlwaysCompare ]: _gl.ALWAYS, + [ LessCompare ]: _gl.LESS, + [ LessEqualCompare ]: _gl.LEQUAL, + [ EqualCompare ]: _gl.EQUAL, + [ GreaterEqualCompare ]: _gl.GEQUAL, + [ GreaterCompare ]: _gl.GREATER, + [ NotEqualCompare ]: _gl.NOTEQUAL + }; + function setTextureParameters( textureType, texture, supportsMips ) { if ( supportsMips ) { @@ -570,6 +581,13 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + if ( texture.compareFunction ) { + + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); + _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); + + } + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); @@ -698,10 +716,10 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, image = verifyColorSpace( texture, image ); const supportsMips = isPowerOfTwo( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ); + glFormat = utils.convert( texture.format, texture.colorSpace ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); setTextureParameters( textureType, texture, supportsMips ); @@ -1130,9 +1148,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const image = cubeImage[ 0 ], supportsMips = isPowerOfTwo( image ) || isWebGL2, - glFormat = utils.convert( texture.format, texture.encoding ), + glFormat = utils.convert( texture.format, texture.colorSpace ), glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); @@ -1299,9 +1317,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, // Setup storage for target texture and bind it to correct framebuffer function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) { - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const renderTargetProperties = properties.get( renderTarget ); if ( ! renderTargetProperties.__hasExternalTextures ) { @@ -1411,9 +1429,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const texture = textures[ i ]; - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); const samples = getRenderTargetSamples( renderTarget ); if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { @@ -1646,9 +1664,9 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); - const glFormat = utils.convert( texture.format, texture.encoding ); + const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, renderTarget.isXRRenderTarget === true ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); const samples = getRenderTargetSamples( renderTarget ); _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); @@ -1920,17 +1938,17 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, function verifyColorSpace( texture, image ) { - const encoding = texture.encoding; + const colorSpace = texture.colorSpace; const format = texture.format; const type = texture.type; - if ( texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat ) return image; + if ( texture.isCompressedTexture === true || texture.format === _SRGBAFormat ) return image; - if ( encoding !== LinearEncoding ) { + if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { // sRGB - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { if ( isWebGL2 === false ) { @@ -1967,7 +1985,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } else { - console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding ); + console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); } diff --git a/src/renderers/webgl/WebGLTransformFeedback.js b/src/renderers/webgl/WebGLTransformFeedback.js deleted file mode 100644 index 176776ae0318ca..00000000000000 --- a/src/renderers/webgl/WebGLTransformFeedback.js +++ /dev/null @@ -1,27 +0,0 @@ -function WebGLTransformFeedback( mesh, material ) { - - this.material = material; - this.mesh = mesh; - - this.source = this.mesh.geometry; - this.target = this.source.clone(); - -} - -// WebGLTransformFeedback.prototype = { - -// tick: function () { - -// this.renderer.processTransformFeedback( this.source, this.target, this.material ); - -// this.mesh.geometry = this.target; - -// // Ping pong buffers -// this.target = this.source; -// this.source = this.mesh.geometry; - -// } - -// }; - -export { WebGLTransformFeedback }; \ No newline at end of file diff --git a/src/renderers/webgl/WebGLUtils.js b/src/renderers/webgl/WebGLUtils.js index 5ed1789e2bdc4e..1157c1e0169d59 100644 --- a/src/renderers/webgl/WebGLUtils.js +++ b/src/renderers/webgl/WebGLUtils.js @@ -1,10 +1,10 @@ -import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBAFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, RGBA_BPTC_Format, sRGBEncoding, _SRGBAFormat, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format } from '../../constants.js'; +import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBAFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, RGBA_BPTC_Format, _SRGBAFormat, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, SRGBColorSpace, NoColorSpace } from '../../constants.js'; function WebGLUtils( gl, extensions, capabilities ) { const isWebGL2 = capabilities.isWebGL2; - function convert( p, encoding = null ) { + function convert( p, colorSpace = NoColorSpace ) { let extension; @@ -74,7 +74,7 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - if ( encoding === sRGBEncoding ) { + if ( colorSpace === SRGBColorSpace ) { extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); @@ -159,8 +159,8 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; - if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + if ( p === RGB_ETC2_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; } else { @@ -182,20 +182,20 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; - if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; - if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; - if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; - if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; - if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; - if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; - if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; - if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; - if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; - if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; - if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; - if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; - if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; + if ( p === RGBA_ASTC_4x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; } else { @@ -213,7 +213,7 @@ function WebGLUtils( gl, extensions, capabilities ) { if ( extension !== null ) { - if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + if ( p === RGBA_BPTC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; } else { diff --git a/src/renderers/webxr/WebXRController.js b/src/renderers/webxr/WebXRController.js index 2d8fe1b3da0f1c..a9d08447e3a6b9 100644 --- a/src/renderers/webxr/WebXRController.js +++ b/src/renderers/webxr/WebXRController.js @@ -169,6 +169,7 @@ class WebXRController { joint.matrix.fromArray( jointPose.transform.matrix ); joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); + joint.matrixWorldNeedsUpdate = true; joint.jointRadius = jointPose.radius; } @@ -217,6 +218,7 @@ class WebXRController { grip.matrix.fromArray( gripPose.transform.matrix ); grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); + grip.matrixWorldNeedsUpdate = true; if ( gripPose.linearVelocity ) { @@ -261,6 +263,7 @@ class WebXRController { targetRay.matrix.fromArray( inputPose.transform.matrix ); targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); + targetRay.matrixWorldNeedsUpdate = true; if ( inputPose.linearVelocity ) { diff --git a/src/renderers/webxr/WebXRManager.js b/src/renderers/webxr/WebXRManager.js index e2d4799675e9e8..e86f39d8c5a33b 100644 --- a/src/renderers/webxr/WebXRManager.js +++ b/src/renderers/webxr/WebXRManager.js @@ -3,18 +3,12 @@ import { EventDispatcher } from '../../core/EventDispatcher.js'; import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js'; import { Vector3 } from '../../math/Vector3.js'; import { Vector4 } from '../../math/Vector4.js'; +import { RAD2DEG } from '../../math/MathUtils.js'; import { WebGLAnimation } from '../webgl/WebGLAnimation.js'; import { WebGLRenderTarget } from '../WebGLRenderTarget.js'; import { WebXRController } from './WebXRController.js'; import { DepthTexture } from '../../textures/DepthTexture.js'; -import { - DepthFormat, - DepthStencilFormat, - RGBAFormat, - UnsignedByteType, - UnsignedIntType, - UnsignedInt248Type, -} from '../../constants.js'; +import { DepthFormat, DepthStencilFormat, RGBAFormat, UnsignedByteType, UnsignedIntType, UnsignedInt248Type } from '../../constants.js'; class WebXRManager extends EventDispatcher { @@ -25,6 +19,7 @@ class WebXRManager extends EventDispatcher { const scope = this; let session = null; + let framebufferScaleFactor = 1.0; let referenceSpace = null; @@ -45,11 +40,10 @@ class WebXRManager extends EventDispatcher { const controllers = []; const controllerInputSources = []; - const planes = new Set(); - const planesLastChangedTimes = new Map(); - // + let userCamera = null; + const cameraL = new PerspectiveCamera(); cameraL.layers.enable( 1 ); cameraL.viewport = new Vector4(); @@ -60,20 +54,28 @@ class WebXRManager extends EventDispatcher { const cameras = [ cameraL, cameraR ]; - const cameraVR = new ArrayCamera(); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); + const cameraXR = new ArrayCamera(); + cameraXR.layers.enable( 1 ); + cameraXR.layers.enable( 2 ); let _currentDepthNear = null; let _currentDepthFar = null; // - this.cameraAutoUpdate = true; + this.cameraAutoUpdate = true; // @deprecated, r153 this.enabled = false; this.isPresenting = false; + this.getCamera = function () {}; // @deprecated, r153 + + this.setUserCamera = function ( value ) { + + userCamera = value; + + }; + this.getController = function ( index ) { let controller = controllers[ index ]; @@ -135,6 +137,7 @@ class WebXRManager extends EventDispatcher { if ( controller !== undefined ) { + controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); controller.dispatchEvent( { type: event.type, data: event.inputSource } ); } @@ -274,7 +277,7 @@ class WebXRManager extends EventDispatcher { const layerInit = { antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true, - alpha: attributes.alpha, + alpha: true, depth: attributes.depth, stencil: attributes.stencil, framebufferScaleFactor: framebufferScaleFactor @@ -290,7 +293,7 @@ class WebXRManager extends EventDispatcher { { format: RGBAFormat, type: UnsignedByteType, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, stencilBuffer: attributes.stencil } ); @@ -329,7 +332,7 @@ class WebXRManager extends EventDispatcher { type: UnsignedByteType, depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), stencilBuffer: attributes.stencil, - encoding: renderer.outputEncoding, + colorSpace: renderer.outputColorSpace, samples: attributes.antialias ? 4 : 0 } ); @@ -356,6 +359,16 @@ class WebXRManager extends EventDispatcher { }; + this.getEnvironmentBlendMode = function () { + + if ( session !== null ) { + + return session.environmentBlendMode; + + } + + }; + function onInputSourcesChange( event ) { // Notify disconnected @@ -479,6 +492,7 @@ class WebXRManager extends EventDispatcher { const bottom2 = bottomFov * far / far2 * near2; camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); } @@ -498,31 +512,37 @@ class WebXRManager extends EventDispatcher { } - this.updateCamera = function ( camera ) { + this.updateCameraXR = function ( camera ) { + + if ( session === null ) return camera; + + if ( userCamera ) { - if ( session === null ) return; + camera = userCamera; - cameraVR.near = cameraR.near = cameraL.near = camera.near; - cameraVR.far = cameraR.far = cameraL.far = camera.far; + } + + cameraXR.near = cameraR.near = cameraL.near = camera.near; + cameraXR.far = cameraR.far = cameraL.far = camera.far; - if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { + if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { // Note that the new renderState won't apply until the next frame. See #18320 session.updateRenderState( { - depthNear: cameraVR.near, - depthFar: cameraVR.far + depthNear: cameraXR.near, + depthFar: cameraXR.far } ); - _currentDepthNear = cameraVR.near; - _currentDepthFar = cameraVR.far; + _currentDepthNear = cameraXR.near; + _currentDepthFar = cameraXR.far; } const parent = camera.parent; - const cameras = cameraVR.cameras; + const cameras = cameraXR.cameras; - updateCamera( cameraVR, parent ); + updateCamera( cameraXR, parent ); for ( let i = 0; i < cameras.length; i ++ ) { @@ -530,42 +550,70 @@ class WebXRManager extends EventDispatcher { } - cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale ); + // update projection matrix for proper view frustum culling - // update user camera and its children + if ( cameras.length === 2 ) { - camera.matrix.copy( cameraVR.matrix ); - camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + setProjectionFromUnion( cameraXR, cameraL, cameraR ); - const children = camera.children; + } else { - for ( let i = 0, l = children.length; i < l; i ++ ) { + // assume single camera setup (AR) - children[ i ].updateMatrixWorld( true ); + cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); } - // update projection matrix for proper view frustum culling + // update user camera and its children - if ( cameras.length === 2 ) { + if ( userCamera ) { + + updateUserCamera( cameraXR, parent ); - setProjectionFromUnion( cameraVR, cameraL, cameraR ); + } + + return cameraXR; + + }; + + function updateUserCamera( cameraXR, parent ) { + + const camera = userCamera; + + if ( parent === null ) { + + camera.matrix.copy( cameraXR.matrixWorld ); } else { - // assume single camera setup (AR) + camera.matrix.copy( parent.matrixWorld ); + camera.matrix.invert(); + camera.matrix.multiply( cameraXR.matrixWorld ); + + } + + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); + camera.updateMatrixWorld( true ); - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); + const children = camera.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].updateMatrixWorld( true ); } - }; + camera.projectionMatrix.copy( cameraXR.projectionMatrix ); + camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); - this.getCamera = function () { + if ( camera.isPerspectiveCamera ) { - return cameraVR; + camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); + camera.zoom = 1; - }; + } + + } this.getFoveation = function () { @@ -600,12 +648,6 @@ class WebXRManager extends EventDispatcher { }; - this.getPlanes = function () { - - return planes; - - }; - // Animation Loop let onAnimationFrameCallback = null; @@ -626,14 +668,14 @@ class WebXRManager extends EventDispatcher { } - let cameraVRNeedsUpdate = false; + let cameraXRNeedsUpdate = false; - // check if it's necessary to rebuild cameraVR's camera list + // check if it's necessary to rebuild cameraXR's camera list - if ( views.length !== cameraVR.cameras.length ) { + if ( views.length !== cameraXR.cameras.length ) { - cameraVR.cameras.length = 0; - cameraVRNeedsUpdate = true; + cameraXR.cameras.length = 0; + cameraXRNeedsUpdate = true; } @@ -678,18 +720,21 @@ class WebXRManager extends EventDispatcher { } camera.matrix.fromArray( view.transform.matrix ); + camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); camera.projectionMatrix.fromArray( view.projectionMatrix ); + camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); if ( i === 0 ) { - cameraVR.matrix.copy( camera.matrix ); + cameraXR.matrix.copy( camera.matrix ); + cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); } - if ( cameraVRNeedsUpdate === true ) { + if ( cameraXRNeedsUpdate === true ) { - cameraVR.cameras.push( camera ); + cameraXR.cameras.push( camera ); } @@ -716,60 +761,7 @@ class WebXRManager extends EventDispatcher { if ( frame.detectedPlanes ) { - scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } ); - - let planesToRemove = null; - - for ( const plane of planes ) { - - if ( ! frame.detectedPlanes.has( plane ) ) { - - if ( planesToRemove === null ) { - - planesToRemove = []; - - } - - planesToRemove.push( plane ); - - } - - } - - if ( planesToRemove !== null ) { - - for ( const plane of planesToRemove ) { - - planes.delete( plane ); - planesLastChangedTimes.delete( plane ); - scope.dispatchEvent( { type: 'planeremoved', data: plane } ); - - } - - } - - for ( const plane of frame.detectedPlanes ) { - - if ( ! planes.has( plane ) ) { - - planes.add( plane ); - planesLastChangedTimes.set( plane, frame.lastChangedTime ); - scope.dispatchEvent( { type: 'planeadded', data: plane } ); - - } else { - - const lastKnownTime = planesLastChangedTimes.get( plane ); - - if ( plane.lastChangedTime > lastKnownTime ) { - - planesLastChangedTimes.set( plane, plane.lastChangedTime ); - scope.dispatchEvent( { type: 'planechanged', data: plane } ); - - } - - } - - } + scope.dispatchEvent( { type: 'planesdetected', data: frame } ); } diff --git a/src/scenes/Scene.js b/src/scenes/Scene.js index a81dfddfe0893c..9607ddb7221217 100644 --- a/src/scenes/Scene.js +++ b/src/scenes/Scene.js @@ -58,16 +58,14 @@ class Scene extends Object3D { } - // @deprecated - - get autoUpdate() { + get autoUpdate() { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); return this.matrixWorldAutoUpdate; } - set autoUpdate( value ) { + set autoUpdate( value ) { // @deprecated, r144 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); this.matrixWorldAutoUpdate = value; diff --git a/src/textures/CompressedTexture.js b/src/textures/CompressedTexture.js index 319a674da5f310..1ed3b3934c4c9d 100644 --- a/src/textures/CompressedTexture.js +++ b/src/textures/CompressedTexture.js @@ -2,9 +2,9 @@ import { Texture } from './Texture.js'; class CompressedTexture extends Texture { - constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { + constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCompressedTexture = true; diff --git a/src/textures/CubeTexture.js b/src/textures/CubeTexture.js index 0489f8225ab523..e686852f2ca45e 100644 --- a/src/textures/CubeTexture.js +++ b/src/textures/CubeTexture.js @@ -3,12 +3,12 @@ import { CubeReflectionMapping } from '../constants.js'; class CubeTexture extends Texture { - constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { images = images !== undefined ? images : []; mapping = mapping !== undefined ? mapping : CubeReflectionMapping; - super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isCubeTexture = true; diff --git a/src/textures/DataTexture.js b/src/textures/DataTexture.js index 9cefb13dc7b5d6..c0a9195042d73a 100644 --- a/src/textures/DataTexture.js +++ b/src/textures/DataTexture.js @@ -3,9 +3,9 @@ import { NearestFilter } from '../constants.js'; class DataTexture extends Texture { - constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding ) { + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { - super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); this.isDataTexture = true; diff --git a/src/textures/DepthTexture.js b/src/textures/DepthTexture.js index 59fcf0aacbea12..ea247e123bcc6d 100644 --- a/src/textures/DepthTexture.js +++ b/src/textures/DepthTexture.js @@ -28,9 +28,31 @@ class DepthTexture extends Texture { this.flipY = false; this.generateMipmaps = false; + this.compareFunction = null; + } + copy( source ) { + + super.copy( source ); + + this.compareFunction = source.compareFunction; + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; + + return data; + + } + } export { DepthTexture }; diff --git a/src/textures/FramebufferTexture.js b/src/textures/FramebufferTexture.js index 322d74031c7ad9..db87092f614e41 100644 --- a/src/textures/FramebufferTexture.js +++ b/src/textures/FramebufferTexture.js @@ -3,14 +3,12 @@ import { NearestFilter } from '../constants.js'; class FramebufferTexture extends Texture { - constructor( width, height, format ) { + constructor( width, height ) { super( { width, height } ); this.isFramebufferTexture = true; - this.format = format; - this.magFilter = NearestFilter; this.minFilter = NearestFilter; diff --git a/src/textures/Source.js b/src/textures/Source.js index 787d3a33024db1..d75fbeb68e1e74 100644 --- a/src/textures/Source.js +++ b/src/textures/Source.js @@ -1,12 +1,16 @@ import { ImageUtils } from '../extras/ImageUtils.js'; import * as MathUtils from '../math/MathUtils.js'; +let sourceId = 0; + class Source { constructor( data = null ) { this.isSource = true; + Object.defineProperty( this, 'id', { value: sourceId ++ } ); + this.uuid = MathUtils.generateUUID(); this.data = data; diff --git a/src/textures/Texture.js b/src/textures/Texture.js index d290dc5c05446b..98376beac54c1f 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -3,23 +3,27 @@ import { MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, - LinearEncoding, UnsignedByteType, RGBAFormat, LinearMipmapLinearFilter, LinearFilter, - UVMapping + UVMapping, + sRGBEncoding, + SRGBColorSpace, + NoColorSpace, + LinearEncoding } from '../constants.js'; import * as MathUtils from '../math/MathUtils.js'; import { Vector2 } from '../math/Vector2.js'; import { Matrix3 } from '../math/Matrix3.js'; import { Source } from './Source.js'; +import { warnOnce } from '../utils.js'; let textureId = 0; class Texture extends EventDispatcher { - constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, encoding = LinearEncoding ) { + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { super(); @@ -35,6 +39,7 @@ class Texture extends EventDispatcher { this.mipmaps = []; this.mapping = mapping; + this.channel = 0; this.wrapS = wrapS; this.wrapT = wrapT; @@ -61,11 +66,17 @@ class Texture extends EventDispatcher { this.flipY = true; this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding; + if ( typeof colorSpace === 'string' ) { + + this.colorSpace = colorSpace; + + } else { // @deprecated, r152 + + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace; + + } + this.userData = {}; @@ -83,7 +94,7 @@ class Texture extends EventDispatcher { } - set image( value ) { + set image( value = null ) { this.source.data = value; @@ -109,6 +120,7 @@ class Texture extends EventDispatcher { this.mipmaps = source.mipmaps.slice( 0 ); this.mapping = source.mapping; + this.channel = source.channel; this.wrapS = source.wrapS; this.wrapT = source.wrapT; @@ -134,7 +146,7 @@ class Texture extends EventDispatcher { this.premultiplyAlpha = source.premultiplyAlpha; this.flipY = source.flipY; this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; + this.colorSpace = source.colorSpace; this.userData = JSON.parse( JSON.stringify( source.userData ) ); @@ -157,7 +169,7 @@ class Texture extends EventDispatcher { const output = { metadata: { - version: 4.5, + version: 4.6, type: 'Texture', generator: 'Texture.toJSON' }, @@ -168,6 +180,7 @@ class Texture extends EventDispatcher { image: this.source.toJSON( meta ).uuid, mapping: this.mapping, + channel: this.channel, repeat: [ this.repeat.x, this.repeat.y ], offset: [ this.offset.x, this.offset.y ], @@ -177,8 +190,9 @@ class Texture extends EventDispatcher { wrap: [ this.wrapS, this.wrapT ], format: this.format, + internalFormat: this.internalFormat, type: this.type, - encoding: this.encoding, + colorSpace: this.colorSpace, minFilter: this.minFilter, magFilter: this.magFilter, @@ -301,6 +315,20 @@ class Texture extends EventDispatcher { } + get encoding() { // @deprecated, r152 + + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; + + } + + set encoding( encoding ) { // @deprecated, r152 + + warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); + this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; + + } + } Texture.DEFAULT_IMAGE = null; diff --git a/src/utils.js b/src/utils.js index 9cee434e7219d6..a71013613bae8d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -68,4 +68,16 @@ function createElementNS( name ) { } -export { arrayMin, arrayMax, arrayNeedsUint32, getTypedArray, createElementNS }; +const _cache = {}; + +function warnOnce( message ) { + + if ( message in _cache ) return; + + _cache[ message ] = true; + + console.warn( message ); + +} + +export { arrayMin, arrayMax, arrayNeedsUint32, getTypedArray, createElementNS, warnOnce }; diff --git a/test/benchmark/README.MD b/test/benchmark/README.MD deleted file mode 100644 index 6b54c390c8781a..00000000000000 --- a/test/benchmark/README.MD +++ /dev/null @@ -1,40 +0,0 @@ -# THREEJS Benchmark Suite - -### Example: Adding a New Suite - -For adding a new Tests we need two things - - Adding the Test File - - Linking it on the benchmark.html page - -Some example could be like this -```javascript -(function() { - // We want to make sure THREE.JS is loaded for this Benchmark - var THREE - if (Bench.isTHREELoaded()) { - THREE = Bench.THREE; - } else { - Bench.warning("Test Example Benchmark not loaded because THREEJS was not loaded"); - return; - } - - var s = Bench.newSuite("Example Benchmark Distance Calculation"); - - var v2a = new THREE.Vector2(3.0, 3.0); - var v2b = new THREE.Vector2(9.0, -3.0); - - var v3a = new THREE.Vector3(3.0, 3.0, 0.0); - var v3b = new THREE.Vector3(9.0, -3.0, 0.0); - - s.add("Vector3", function() { - v3a.distanceTo(v3b); - }) - - s.add("Vector2", function() { - v2a.distanceTo(v2b); - - }) -})(); -``` - -Remember that THREEJS library is only accesible via `Bench.THREE` diff --git a/test/benchmark/benchmark.js b/test/benchmark/benchmark.js deleted file mode 100644 index c39258143d985e..00000000000000 --- a/test/benchmark/benchmark.js +++ /dev/null @@ -1,103 +0,0 @@ -var BenchClass = function () { - - this.suites = []; - this.THREE = window.THREE; - window.THREE = undefined; - Benchmark.options.maxTime = 1.0; - return this; - -}; - -BenchClass.prototype.isTHREELoaded = function () { - - return _.isObject( this.THREE ); // eslint-disable-line no-undef - -}; - -BenchClass.prototype.newSuite = function ( name ) { - - var s = new Benchmark.Suite( name ); - this.suites.push( s ); - return s; - -}; - -BenchClass.prototype.display = function () { - - for ( var x of this.suites ) { - - var s = new SuiteUI( x ); - s.render(); - - } - -}; - -BenchClass.prototype.warning = function ( message ) { - - console.error( message ); - -}; - -var SuiteUI = function ( suite ) { - - this.suite = suite; - this.isRunning = false; - return this; - -}; - -SuiteUI.prototype.render = function () { - - var n = document.importNode( this.suiteTemplate, true ); - this.elem = n.querySelector( 'article' ); - this.results = n.querySelector( '.results' ); - this.title = n.querySelector( 'h2' ); - this.runButton = n.querySelector( 'h3' ); - - this.title.innerText = this.suite.name; - this.runButton.onclick = this.run.bind( this ); - - this.section.appendChild( n ); - -}; - -SuiteUI.prototype.run = function () { - - this.runButton.click = _.noop; // eslint-disable-line no-undef - this.runButton.innerText = 'Running...'; - this.suite.on( 'complete', this.complete.bind( this ) ); - this.suite.run( { - async: true - } ); - -}; - -SuiteUI.prototype.complete = function () { - - this.runButton.style.display = 'none'; - this.results.style.display = 'block'; - var f = _.orderBy( this.suite, [ 'hz' ], [ 'desc' ] ); // eslint-disable-line no-undef - for ( var i = 0; i < f.length; i ++ ) { - - var x = f[ i ]; - var n = document.importNode( this.suiteTestTemplate, true ); - n.querySelector( '.name' ).innerText = x.name; - n.querySelector( '.ops' ).innerText = x.hz.toFixed(); - n.querySelector( '.desv' ).innerText = x.stats.rme.toFixed( 2 ); - this.results.appendChild( n ); - - } - -}; - -var Bench = new BenchClass(); -window.addEventListener( 'load', function () { - - SuiteUI.prototype.suiteTemplate = document.querySelector( '#suite' ).content; - SuiteUI.prototype.suiteTestTemplate = document.querySelector( '#suite-test' ).content; - SuiteUI.prototype.section = document.querySelector( 'section' ); - - Bench.display(); - -} ); diff --git a/test/benchmark/benchmarks.html b/test/benchmark/benchmarks.html deleted file mode 100644 index 8134e9c1aac21f..00000000000000 --- a/test/benchmark/benchmarks.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - ThreeJS Benchmark Tests - Using Files in /src - - - - - - - - - - - - - - - - -
    -

    Three JS Benchmarks Suite

    -
    -
    -
    - - - - - - - diff --git a/test/benchmark/core/Float32Array.js b/test/benchmark/core/Float32Array.js deleted file mode 100644 index fccdea760a699b..00000000000000 --- a/test/benchmark/core/Float32Array.js +++ /dev/null @@ -1,92 +0,0 @@ -( function () { - - var input = new Float32Array( 10000 * 3 ); - var output = new Float32Array( 10000 * 3 ); - - for ( var j = 0, jl = input.length; j < jl; j ++ ) { - - input[ j ] = j; - - } - - var s = Bench.newSuite( 'Float 32 Arrays' ); - - s.add( 'Float32Array-Float32Array', function () { - - var value3 = new Float32Array( 3 ); - for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { - - value3[ 0 ] = input[ i + 0 ]; - value3[ 1 ] = input[ i + 1 ]; - value3[ 2 ] = input[ i + 2 ]; - value3[ 0 ] *= 1.01; - value3[ 1 ] *= 1.03; - value3[ 2 ] *= 0.98; - output[ i + 0 ] = value3[ 0 ]; - output[ i + 1 ] = value3[ 1 ]; - output[ i + 2 ] = value3[ 2 ]; - - } - - } ); - - s.add( 'Float32Array-Array', function () { - - var value2 = [ 0, 0, 0 ]; - for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { - - value2[ 0 ] = input[ i + 0 ]; - value2[ 1 ] = input[ i + 1 ]; - value2[ 2 ] = input[ i + 2 ]; - value2[ 0 ] *= 1.01; - value2[ 1 ] *= 1.03; - value2[ 2 ] *= 0.98; - output[ i + 0 ] = value2[ 0 ]; - output[ i + 1 ] = value2[ 1 ]; - output[ i + 2 ] = value2[ 2 ]; - - } - - } ); - - s.add( 'Float32Array-Literal', function () { - - var x, - y, - z; - for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { - - x = input[ i + 0 ]; - y = input[ i + 1 ]; - z = input[ i + 2 ]; - x *= 1.01; - y *= 1.03; - z *= 0.98; - output[ i + 0 ] = x; - output[ i + 1 ] = y; - output[ i + 2 ] = z; - - } - - } ); - - s.add( 'Float32Array-Vector3', function () { - - var value = new THREE.Vector3(); - for ( var i = 0, il = input.length / 3; i < il; i += 3 ) { - - value.x = input[ i + 0 ]; - value.y = input[ i + 1 ]; - value.z = input[ i + 2 ]; - value.x *= 1.01; - value.y *= 1.03; - value.z *= 0.98; - output[ i + 0 ] = value.x; - output[ i + 1 ] = value.y; - output[ i + 2 ] = value.z; - - } - - } ); - -} )(); diff --git a/test/benchmark/core/TriangleClosestPoint.js b/test/benchmark/core/TriangleClosestPoint.js deleted file mode 100644 index c2cb88065f114a..00000000000000 --- a/test/benchmark/core/TriangleClosestPoint.js +++ /dev/null @@ -1,80 +0,0 @@ -( function () { - - THREE = Bench.THREE; - - // these vertices and triangles are those of a unit icosahedron centered at the origin - var phi = 1.618; - var verts = [ - [ phi, 1, 0 ], [ - phi, 1, 0 ], [ phi, - 1, 0 ], [ - phi, - 1, 0 ], - [ 1, 0, phi ], [ 1, 0, - phi ], [ - 1, 0, phi ], [ - 1, 0, - phi ], - [ 0, phi, 1 ], [ 0, - phi, 1 ], [ 0, phi, - 1 ], [ 0, - phi, - 1 ], - ]; - var createVertex = function ( c ) { - - return new THREE.Vector3( c[ 0 ], c[ 1 ], c[ 2 ] ); - - }; - - var createTriangle = function ( i0, i1, i2 ) { - - return new THREE.Triangle( createVertex( verts[ i0 ] ), createVertex( verts[ i1 ] ), createVertex( verts[ i2 ] ) ); - - }; - - var triangles = [ - createTriangle( 0, 8, 4 ), - createTriangle( 0, 5, 10 ), - createTriangle( 2, 4, 9 ), - createTriangle( 2, 11, 5 ), - createTriangle( 1, 6, 8 ), - createTriangle( 1, 10, 7 ), - createTriangle( 3, 9, 6 ), - createTriangle( 3, 7, 11 ), - createTriangle( 0, 10, 8 ), - createTriangle( 1, 8, 10 ), - createTriangle( 2, 9, 11 ), - createTriangle( 3, 9, 11 ), - createTriangle( 4, 2, 0 ), - createTriangle( 5, 0, 2 ), - createTriangle( 6, 1, 3 ), - createTriangle( 7, 3, 1 ), - createTriangle( 8, 6, 4 ), - createTriangle( 9, 4, 6 ), - createTriangle( 10, 5, 7 ), - createTriangle( 11, 7, 5 ), - ]; - // test a variety of points all in and around the icosahedron - var testPoints = []; - for ( var x = - 2; x <= 2; x += 0.5 ) { - - for ( var y = - 2; y <= 2; y += 0.5 ) { - - for ( var z = - 2; z <= 2; z += 0.5 ) { - - testPoints.push( new THREE.Vector3( x, y, z ) ); - - } - - } - - } - - var s = Bench.newSuite( 'Clamping point into triangles' ); - - s.add( '9^3 points, 20 triangles', function () { - - var target = new THREE.Vector3(); - for ( var tidx = 0; tidx < triangles.length; tidx ++ ) { - - var triangle = triangles[ tidx ]; - for ( var pidx = 0; pidx < testPoints.length; pidx ++ ) { - - triangle.closestPointToPoint( testPoints[ pidx ], target ); - - } - - } - - } ); - -} )(); diff --git a/test/benchmark/core/UpdateMatrixWorld.js b/test/benchmark/core/UpdateMatrixWorld.js deleted file mode 100644 index 9dfd915c9a898c..00000000000000 --- a/test/benchmark/core/UpdateMatrixWorld.js +++ /dev/null @@ -1,70 +0,0 @@ -( function () { - - THREE = Bench.THREE; - - var position = new THREE.Vector3( 1, 1, 1 ); - var scale = new THREE.Vector3( 2, 1, 0.5 ); - var quaternion = new THREE.Quaternion(); - quaternion.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 8 ); - var createLocallyOffsetChild = function () { - - var child = new THREE.Object3D(); - child.position.copy( position ); - child.scale.copy( scale ); - child.quaternion.copy( quaternion ); - - return child; - - }; - - var generateSceneGraph = function ( root, depth, breadth, initObject ) { - - if ( depth > 0 ) { - - for ( var i = 0; i < breadth; i ++ ) { - - var child = initObject(); - root.add( child ); - generateSceneGraph( child, depth - 1, breadth, initObject ); - - } - - } - - return root; - - }; - - var nodeCount = function ( root ) { - - return root.children.reduce( function ( acc, x ) { - - return acc + nodeCount( x ); - - }, 1 ); - - }; - - var rootA = generateSceneGraph( new THREE.Object3D(), 100, 1, createLocallyOffsetChild ); - var rootB = generateSceneGraph( new THREE.Object3D(), 3, 10, createLocallyOffsetChild ); - var rootC = generateSceneGraph( new THREE.Object3D(), 9, 3, createLocallyOffsetChild ); - - var s = Bench.newSuite( 'Update world transforms' ); - - s.add( 'Update graph depth=100, breadth=1 (' + nodeCount( rootA ) + ' nodes)', function () { - - rootA.updateMatrixWorld( true ); - - } ); - s.add( 'Update graph depth=3, breadth=10 (' + nodeCount( rootB ) + ' nodes)', function () { - - rootB.updateMatrixWorld( true ); - - } ); - s.add( 'Update graph depth=9, breadth=3 (' + nodeCount( rootC ) + ' nodes)', function () { - - rootC.updateMatrixWorld( true ); - - } ); - -} )(); diff --git a/test/benchmark/core/Vector3Components.js b/test/benchmark/core/Vector3Components.js deleted file mode 100644 index 8cce6f6062d391..00000000000000 --- a/test/benchmark/core/Vector3Components.js +++ /dev/null @@ -1,154 +0,0 @@ -( function () { - - var s = Bench.newSuite( 'Vector 3 Components' ); - - THREE = {}; - - THREE.Vector3 = function ( x, y, z ) { - - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - - }; - - THREE.Vector3.prototype = { - constructor: THREE.Vector3, - setComponent: function ( index, value ) { - - this[ THREE.Vector3.__indexToName[ index ] ] = value; - - }, - - getComponent: function ( index ) { - - return this[ THREE.Vector3.__indexToName[ index ] ]; - - }, - - setComponent2: function ( index, value ) { - - switch ( index ) { - - case 0: - this.x = value; - break; - case 1: - this.y = value; - break; - case 2: - this.z = value; - break; - default: - throw new Error( 'index is out of range: ' + index ); - - } - - }, - - getComponent2: function ( index ) { - - switch ( index ) { - - case 0: - return this.x; - case 1: - return this.y; - case 2: - return this.z; - default: - throw new Error( 'index is out of range: ' + index ); - - } - - }, - - - getComponent3: function ( index ) { - - if ( index === 0 ) return this.x; - if ( index === 1 ) return this.y; - if ( index === 2 ) return this.z; - throw new Error( 'index is out of range: ' + index ); - - }, - - getComponent4: function ( index ) { - - if ( index === 0 ) return this.x; else if ( index === 1 ) return this.y; else if ( index === 2 ) return this.z; - else - throw new Error( 'index is out of range: ' + index ); - - } - }; - - - THREE.Vector3.__indexToName = { - 0: 'x', - 1: 'y', - 2: 'z' - }; - - var a = []; - for ( var i = 0; i < 100000; i ++ ) { - - a[ i ] = new THREE.Vector3( i * 0.01, i * 2, i * - 1.3 ); - - } - - - - - s.add( 'IndexToName', function () { - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - result += a[ i ].getComponent( i % 3 ); - - } - - return result; - - } ); - - s.add( 'SwitchStatement', function () { - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - result += a[ i ].getComponent2( i % 3 ); - - } - - return result; - - } ); - - s.add( 'IfAndReturnSeries', function () { - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - result += a[ i ].getComponent3( i % 3 ); - - } - - return result; - - } ); - - s.add( 'IfReturnElseSeries', function () { - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - result += a[ i ].getComponent4( i % 3 ); - - } - - return result; - - } ); - -} )(); diff --git a/test/benchmark/core/Vector3Length.js b/test/benchmark/core/Vector3Length.js deleted file mode 100644 index 63d13e0eff403d..00000000000000 --- a/test/benchmark/core/Vector3Length.js +++ /dev/null @@ -1,85 +0,0 @@ -( function () { - - var THREE = {}; - - THREE.Vector3 = function ( x, y, z ) { - - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - - }; - - THREE.Vector3.prototype = { - constructor: THREE.Vector3, - lengthSq: function () { - - return this.x * this.x + this.y * this.y + this.z * this.z; - - }, - - length: function () { - - return Math.sqrt( this.lengthSq() ); - - }, - - length2: function () { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - - } - - }; - - var a = []; - for ( var i = 0; i < 100000; i ++ ) { - - a[ i ] = new THREE.Vector3( i * 0.01, i * 2, i * - 1.3 ); - - } - - - var suite = Bench.newSuite( 'Vector 3 Length' ); - - suite.add( 'NoCallTest', function () { - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - var v = a[ i ]; - result += Math.sqrt( v.x * v.x + v.y * v.y + v.z * v.z ); - - } - - return result; - - } ); - - suite.add( 'InlineCallTest', function () { - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - result += a[ i ].length2(); - - } - - return result; - - } ); - - suite.add( 'FunctionCallTest', function () { - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - result += a[ i ].length(); - - } - - return result; - - } ); - -} )(); diff --git a/test/benchmark/core/Vector3Storage.js b/test/benchmark/core/Vector3Storage.js deleted file mode 100644 index f0396f2314be60..00000000000000 --- a/test/benchmark/core/Vector3Storage.js +++ /dev/null @@ -1,134 +0,0 @@ -( function () { - - THREE = {}; - - THREE.Vector3 = function ( x, y, z ) { - - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - - }; - - THREE.Vector3.prototype = { - - constructor: THREE.Vector3, - - length: function () { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - - } - - }; - - THREE.Vector3X = function ( x, y, z ) { - - var elements = this.elements = new Float32Array( 3 ); - elements[ 0 ] = x || 0; - elements[ 1 ] = y || 1; - elements[ 2 ] = z || 2; - - }; - - THREE.Vector3X.prototype = { - - constructor: THREE.Vector3X, - - length: function () { - - return Math.sqrt( this.elements[ 0 ] * this.elements[ 0 ] + this.elements[ 1 ] * this.elements[ 1 ] + this.elements[ 2 ] * this.elements[ 2 ] ); - - } - - }; - - - THREE.Vector3Y = function ( x, y, z ) { - - this.elements = [ x || 0, y || 1, z || 2 ]; - - }; - - THREE.Vector3Y.prototype = { - - constructor: THREE.Vector3Y, - - length: function () { - - return Math.sqrt( this.elements[ 0 ] * this.elements[ 0 ] + this.elements[ 1 ] * this.elements[ 1 ] + this.elements[ 2 ] * this.elements[ 2 ] ); - - } - - }; - - - var suite = Bench.newSuite( 'Vector 3 Storage' ); - - suite.add( 'Vector3-Set', function () { - - var array = []; - for ( var i = 0; i < 100000; i ++ ) { - - var v = new THREE.Vector3( i, i, i ); - array.push( v ); - - } - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - var v = array[ i ]; - result += v.length(); - - } - - return result; - - } ); - - suite.add( 'Vector3-Float32Array', function () { - - var array = []; - for ( var i = 0; i < 100000; i ++ ) { - - var v = new THREE.Vector3X( i, i, i ); - array.push( v ); - - } - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - var v = array[ i ]; - result += v.length(); - - } - - return result; - - } ); - - suite.add( 'Vector3-Array', function () { - - var array = []; - for ( var i = 0; i < 100000; i ++ ) { - - var v = new THREE.Vector3Y( i, i, i ); - array.push( v ); - - } - - var result = 0; - for ( var i = 0; i < 100000; i ++ ) { - - var v = array[ i ]; - result += v.length(); - - } - - return result; - - } ); - -} )(); diff --git a/test/benchmark/normalize.css b/test/benchmark/normalize.css deleted file mode 100644 index 18ddf7fede130e..00000000000000 --- a/test/benchmark/normalize.css +++ /dev/null @@ -1,419 +0,0 @@ -/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */ - -/** - * 1. Change the default font family in all browsers (opinionated). - * 2. Prevent adjustments of font size after orientation changes in IE and iOS. - */ - -html { - font-family: sans-serif; /* 1 */ - -ms-text-size-adjust: 100%; /* 2 */ - -webkit-text-size-adjust: 100%; /* 2 */ -} - -/** - * Remove the margin in all browsers (opinionated). - */ - -body { - margin: 0; -} - -/* HTML5 display definitions - ========================================================================== */ - -/** - * Add the correct display in IE 9-. - * 1. Add the correct display in Edge, IE, and Firefox. - * 2. Add the correct display in IE. - */ - -article, -aside, -details, /* 1 */ -figcaption, -figure, -footer, -header, -main, /* 2 */ -menu, -nav, -section, -summary { /* 1 */ - display: block; -} - -/** - * Add the correct display in IE 9-. - */ - -audio, -canvas, -progress, -video { - display: inline-block; -} - -/** - * Add the correct display in iOS 4-7. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/** - * Add the correct vertical alignment in Chrome, Firefox, and Opera. - */ - -progress { - vertical-align: baseline; -} - -/** - * Add the correct display in IE 10-. - * 1. Add the correct display in IE. - */ - -template, /* 1 */ -[hidden] { - display: none; -} - -/* Links - ========================================================================== */ - -/** - * 1. Remove the gray background on active links in IE 10. - * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. - */ - -a { - background-color: transparent; /* 1 */ - -webkit-text-decoration-skip: objects; /* 2 */ -} - -/** - * Remove the outline on focused links when they are also active or hovered - * in all browsers (opinionated). - */ - -a:active, -a:hover { - outline-width: 0; -} - -/* Text-level semantics - ========================================================================== */ - -/** - * 1. Remove the bottom border in Firefox 39-. - * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. - */ - -abbr[title] { - border-bottom: none; /* 1 */ - text-decoration: underline; /* 2 */ - text-decoration: underline dotted; /* 2 */ -} - -/** - * Prevent the duplicate application of `bolder` by the next rule in Safari 6. - */ - -b, -strong { - font-weight: inherit; -} - -/** - * Add the correct font weight in Chrome, Edge, and Safari. - */ - -b, -strong { - font-weight: bolder; -} - -/** - * Add the correct font style in Android 4.3-. - */ - -dfn { - font-style: italic; -} - -/** - * Correct the font size and margin on `h1` elements within `section` and - * `article` contexts in Chrome, Firefox, and Safari. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/** - * Add the correct background and color in IE 9-. - */ - -mark { - background-color: #ff0; - color: #000; -} - -/** - * Add the correct font size in all browsers. - */ - -small { - font-size: 80%; -} - -/** - * Prevent `sub` and `sup` elements from affecting the line height in - * all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* Embedded content - ========================================================================== */ - -/** - * Remove the border on images inside links in IE 10-. - */ - -img { - border-style: none; -} - -/** - * Hide the overflow in IE. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* Grouping content - ========================================================================== */ - -/** - * 1. Correct the inheritance and scaling of font size in all browsers. - * 2. Correct the odd `em` font sizing in all browsers. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, monospace; /* 1 */ - font-size: 1em; /* 2 */ -} - -/** - * Add the correct margin in IE 8. - */ - -figure { - margin: 1em 40px; -} - -/** - * 1. Add the correct box sizing in Firefox. - * 2. Show the overflow in Edge and IE. - */ - -hr { - box-sizing: content-box; /* 1 */ - height: 0; /* 1 */ - overflow: visible; /* 2 */ -} - -/* Forms - ========================================================================== */ - -/** - * 1. Change font properties to `inherit` in all browsers (opinionated). - * 2. Remove the margin in Firefox and Safari. - */ - -button, -input, -select, -textarea { - font: inherit; /* 1 */ - margin: 0; /* 2 */ -} - -/** - * Restore the font weight unset by the previous rule. - */ - -optgroup { - font-weight: bold; -} - -/** - * Show the overflow in IE. - * 1. Show the overflow in Edge. - */ - -button, -input { /* 1 */ - overflow: visible; -} - -/** - * Remove the inheritance of text transform in Edge, Firefox, and IE. - * 1. Remove the inheritance of text transform in Firefox. - */ - -button, -select { /* 1 */ - text-transform: none; -} - -/** - * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` - * controls in Android 4. - * 2. Correct the inability to style clickable types in iOS and Safari. - */ - -button, -html [type="button"], /* 1 */ -[type="reset"], -[type="submit"] { - -webkit-appearance: button; /* 2 */ -} - -/** - * Remove the inner border and padding in Firefox. - */ - -button::-moz-focus-inner, -[type="button"]::-moz-focus-inner, -[type="reset"]::-moz-focus-inner, -[type="submit"]::-moz-focus-inner { - border-style: none; - padding: 0; -} - -/** - * Restore the focus styles unset by the previous rule. - */ - -button:-moz-focusring, -[type="button"]:-moz-focusring, -[type="reset"]:-moz-focusring, -[type="submit"]:-moz-focusring { - outline: 1px dotted ButtonText; -} - -/** - * Change the border, margin, and padding in all browsers (opinionated). - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/** - * 1. Correct the text wrapping in Edge and IE. - * 2. Correct the color inheritance from `fieldset` elements in IE. - * 3. Remove the padding so developers are not caught out when they zero out - * `fieldset` elements in all browsers. - */ - -legend { - box-sizing: border-box; /* 1 */ - color: inherit; /* 2 */ - display: table; /* 1 */ - max-width: 100%; /* 1 */ - padding: 0; /* 3 */ - white-space: normal; /* 1 */ -} - -/** - * Remove the default vertical scrollbar in IE. - */ - -textarea { - overflow: auto; -} - -/** - * 1. Add the correct box sizing in IE 10-. - * 2. Remove the padding in IE 10-. - */ - -[type="checkbox"], -[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * Correct the cursor style of increment and decrement buttons in Chrome. - */ - -[type="number"]::-webkit-inner-spin-button, -[type="number"]::-webkit-outer-spin-button { - height: auto; -} - -/** - * 1. Correct the odd appearance in Chrome and Safari. - * 2. Correct the outline style in Safari. - */ - -[type="search"] { - -webkit-appearance: textfield; /* 1 */ - outline-offset: -2px; /* 2 */ -} - -/** - * Remove the inner padding and cancel buttons in Chrome and Safari on OS X. - */ - -[type="search"]::-webkit-search-cancel-button, -[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** - * Correct the text style of placeholders in Chrome, Edge, and Safari. - */ - -::-webkit-input-placeholder { - color: inherit; - opacity: 0.54; -} - -/** - * 1. Correct the inability to style clickable types in iOS and Safari. - * 2. Change font properties to `inherit` in Safari. - */ - -::-webkit-file-upload-button { - -webkit-appearance: button; /* 1 */ - font: inherit; /* 2 */ -} diff --git a/test/benchmark/style.css b/test/benchmark/style.css deleted file mode 100644 index 19c53ca2fffcc9..00000000000000 --- a/test/benchmark/style.css +++ /dev/null @@ -1,96 +0,0 @@ -html{ - background-color: #FFE0F7; -} - -body{ - font-family: 'Source Sans Pro', sans-serif; -} - -header{ - -} -header h1{ - color: #6F0752; - border-bottom: 4px solid #A23183; - margin: 10px; -} - -article{ - border: 2px solid #B8509B; - margin:5px 10px; - border-radius:10px; -} - -article header{ - - display: flex; -} - -article h2{ - color:#6F0752; - font-size:1.2em; - margin:10px; - flex-grow:1; -} - -article h3{ - color:#6F0752; - font-size:1.0em; - margin:7px; - text-align:right; - flex-grow:0; - background:transparent; - border: 1px solid #B8509B; - border-radius:3px; - padding:3px 7px; - cursor:pointer; -} - -article h3:hover{ - color:#6F0752; - font-size:1.0em; - margin:7px; - text-align:right; - flex-grow:0; - background:transparent; - border: 1px solid #B8509B; - border-radius:3px; - padding:3px 7px; -} - -article .results{ - margin:0 10px 10px; - display:none; -} -article .results > div{ - display: flex; -} -article .results > div p{ - color:#6F0752; - flex-grow: 1; - margin: 0 3px; - font-size:0.8em; -} - -.results > div:nth-child(1){ - margin-bottom: 3px; - border-bottom: 1px solid #A23183; -} - -.results > div:nth-child(2){ - background: #6F0752; -} - -.results > div:nth-child(2) p{ - color: #FFE0F7; -} - -.results .name{ - flex-basis:60%; -} -.results .time{ - flex-basis:20%; -} -.results .desv{ - flex-basis:20%; -} diff --git a/test/benchmark/vendor/benchmark-2.1.0.min.js b/test/benchmark/vendor/benchmark-2.1.0.min.js deleted file mode 100644 index e5fa6ea9cc77a3..00000000000000 --- a/test/benchmark/vendor/benchmark-2.1.0.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(){"use strict";function e(t){function s(e,n,t){var r=this;return r instanceof s?(Y.isPlainObject(e)?t=e:Y.isFunction(e)?(t=n,n=e):Y.isPlainObject(n)?(t=n,n=null,r.name=e):r.name=e,_(r,t),r.id||(r.id=++c),null==r.fn&&(r.fn=n),r.stats=ke(r.stats),void(r.times=ke(r.times))):new s(e,n,t)}function a(e){var n=this;return n instanceof a?(n.benchmark=e,void Q(n)):new a(e)}function l(e){var n=this;return e instanceof l?e:n instanceof l?Y.assign(n,{timeStamp:Y.now()},"string"==typeof e?{type:e}:e):new l(e)}function y(e,n){var t=this;return t instanceof y?(Y.isPlainObject(e)?n=e:t.name=e,void _(t,n)):new y(e,n)}function v(){return v=function(e,n){var t,r=o?o.amd:s,i=$e+"createFunction";return k((o?"define.amd.":"Benchmark.")+i+"=function("+e+"){"+n+"}"),t=r[i],delete r[i],t},v=Ce.browser&&(v("",'return"'+$e+'"')||Y.noop)()==$e?v:ne,v.apply(null,arguments)}function b(e,n){e._timerId=Y.delay(n,1e3*e.delay)}function w(e){Se.appendChild(e),Se.innerHTML=""}function T(e){return!Y.has(e,"toString")&&(/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(e)||0)[1]||""}function S(e){return Y.reduce(e,function(e,n){return e+n})/e.length||0}function $(e){var n="";return C(e)?n=oe(e):Ce.decompilation&&(n=Y.result(/^[^{]+\{([\s\S]*)\}\s*$/.exec(e),1)),n=(n||"").replace(/^\s+|\s+$/g,""),/^(?:\/\*+[\w\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(n)?"":n}function x(e,n){if(null==e)return!1;var t=typeof e[n];return!(f.test(t)||"object"==t&&!e[n])}function C(e){return Y.isString(e)||Y.has(e,"toString")&&Y.isFunction(e.toString)}function j(e){try{var n=i&&u(e)}catch(t){}return n||null}function k(e){var n=o?define.amd:s,t=be.createElement("script"),r=be.getElementsByTagName("script")[0],i=r.parentNode,a=$e+"runScript",u="("+(o?"define.amd.":"Benchmark.")+a+"||function(){})();";try{t.appendChild(be.createTextNode(u+e)),n[a]=function(){w(t)}}catch(c){i=i.cloneNode(!1),r=null,t.text=e}i.insertBefore(t,r),delete n[a]}function _(e,n){n=e.options=Y.assign({},ke(e.constructor.options),ke(n)),Y.forOwn(n,function(n,t){null!=n&&(/^on[A-Z]/.test(t)?Y.each(t.split(" "),function(t){e.on(t.slice(2).toLowerCase(),n)}):Y.has(e,t)||(e[t]=ke(n)))})}function O(){var e=this,n=e.benchmark,r=n._original;r.aborted?(e.teardown(),n.running=!1,V(e)):++e.cyclest.mean+t.moe?1:-1)*("fastest"===n?1:-1)});return Y.filter(t,function(e){return 0==t[0].compare(e)})}return Y.filter(e,n)}function E(e){return e=oe(e).split("."),e[0].replace(/(?=(?:\d{3})+$)(?!\b)/g,",")+(e[1]?"."+e[1]:"")}function F(e,t){function r(){var e,r=i(c);return r&&(c.on("complete",o),e=c.events.complete,e.splice(0,0,e.pop())),h[p]=Y.isFunction(c&&c[t])?c[t].apply(c,u):n,!r&&o()}function o(n){var t,s=c,u=i(s);if(u&&(s.off("complete",o),s.emit("complete")),m.type="cycle",m.target=s,t=l(m),d.onCycle.call(e,t),t.aborted||a()===!1)m.type="complete",d.onComplete.call(e,l(m));else if(c=f?e[0]:h[p],i(c))b(c,r);else{if(!u)return!0;for(;r(););}return n?void(n.aborted=!0):!1}function i(e){var n=u[0]&&u[0].async;return"run"==t&&e instanceof s&&((null==n?e.options.async:n)&&Ce.timeout||e.defer)}function a(){return p++,f&&p>0&&de.call(e),(f?e.length:p>>0;return t||(t=": "),Y.each(e,function(e,n){r.push(i?e:n+t+e)}),r.join(n||",")}function z(){var e,n=this,t=xe.resetSuite;return n.running&&(e=l("abort"),n.emit(e),(!e.cancelled||t)&&(xe.abortSuite=!0,n.reset(),delete xe.abortSuite,t||(n.aborted=!0,F(n,"abort")))),n}function q(e,n,t){var r=this,o=new s(e,n,t),i=l({type:"add",target:o});return r.emit(i),i.cancelled||r.push(o),r}function N(e){var n=this,t=new n.constructor(Y.assign({},n.options,e));return Y.forOwn(n,function(e,n){Y.has(t,n)||(t[n]=e&&Y.isFunction(e.clone)?e.clone():ke(e))}),t}function I(e){var n=this,t=new n.constructor(n.options);return t.push.apply(t,A(n,e)),t}function D(){var e,n=this,t=xe.abortSuite;return n.running&&!t?(xe.resetSuite=!0,n.abort(),delete xe.resetSuite):!n.aborted&&!n.running||(n.emit(e=l("reset")),e.cancelled)||(n.aborted=n.running=!1,t||F(n,"reset")),n}function P(e){var n=this;return n.reset(),n.running=!0,e||(e={}),F(n,{name:"run",args:e,queued:e.queued,onStart:function(e){n.emit(e)},onCycle:function(e){var t=e.target;t.error&&n.emit({type:"error",target:t}),n.emit(e),e.aborted=n.aborted},onComplete:function(e){n.running=!1,n.emit(e)}}),n}function M(e){var n,t=this,r=l(e),o=t.events,i=(arguments[0]=r,arguments);return r.currentTarget||(r.currentTarget=t),r.target||(r.target=t),delete r.result,o&&(n=Y.has(o,r.type)&&o[r.type])&&Y.each(n.slice(),function(e){return(r.result=e.apply(t,i))===!1&&(r.cancelled=!0),!r.aborted}),r.result}function R(e){var n=this,t=n.events||(n.events={});return Y.has(t,e)?t[e]:t[e]=[]}function L(e,n){var t=this,r=t.events;return r?(Y.each(e?e.split(" "):r,function(e,t){var o;"string"==typeof e&&(t=e,e=Y.has(r,t)&&r[t]),e&&(n?(o=Y.indexOf(e,n),o>-1&&e.splice(o,1)):e.length=0)}),t):t}function W(e,n){var t=this,r=t.events||(t.events={});return Y.each(e.split(" "),function(e){(Y.has(r,e)?r[e]:r[e]=[]).push(n)}),t}function H(){var e,n=this,t=xe.reset;return n.running&&(e=l("abort"),n.emit(e),(!e.cancelled||t)&&(xe.abort=!0,n.reset(),delete xe.abort,Ce.timeout&&(ue(n._timerId),delete n._timerId),t||(n.aborted=!0,n.running=!1))),n}function Z(e){var n=this,t=new n.constructor(Y.assign({},n,e));return t.options=Y.assign({},ke(n.options),ke(e)),Y.forOwn(n,function(e,n){Y.has(t,n)||(t[n]=ke(e))}),t}function G(e){function n(e,n){return Y.reduce(n,function(n,t){return n+(t>e?0:e>t?1:.5)},0)}function t(e,t){return Y.reduce(e,function(e,r){return e+n(r,t)},0)}function r(e){return(e-c*l/2)/ge(c*l*(c+l+1)/12)}var o=this;if(o==e)return 0;var i,s,a=o.stats.sample,u=e.stats.sample,c=a.length,l=u.length,f=le(c,l),p=fe(c,l),m=t(a,u),d=t(u,a),h=fe(m,d);return c+l>30?(s=r(h),ae(s)>1.96?h==m?1:-1:0):(i=5>f||3>p?0:g[f][p-3],i>=h?h==m?1:-1:0)}function J(){var e=this;if(e.running&&!xe.abort)return xe.reset=!0,e.abort(),delete xe.reset,e;var n,t=0,r=[],o=[],i={destination:e,source:Y.assign({},ke(e.constructor.prototype),ke(e.options))};do Y.forOwn(i.source,function(e,n){var t,s=i.destination,a=s[n];"_"!=n.charAt(0)&&(e&&"object"==typeof e?(Y.isArray(e)?(Y.isArray(a)||(t=a=[]),a.length!=e.length&&(t=a=a.slice(0,e.length),a.length=e.length)):a&&"object"==typeof a||(t=a={}),t&&r.push({destination:s,key:n,value:a}),o.push({destination:a,source:e})):e===a||null==e||Y.isFunction(e)||r.push({destination:s,key:n,value:e}))});while(i=o[t++]);return r.length&&(e.emit(n=l("reset")),!n.cancelled)&&Y.each(r,function(e){e.destination[e.key]=e.value}),e}function K(){var e=this,n=e.error,t=e.hz,r=e.id,o=e.stats,i=o.sample.length,s="±",a=e.name||(Y.isNaN(r)?r:"");return a+=n?": "+B(n):" x "+E(t.toFixed(100>t?2:0))+" ops/sec "+s+o.rme.toFixed(2)+"% ("+i+" run"+(1==i?"":"s")+" sampled)"}function Q(){function e(e,n,t,o){var s=e.fn,a=t?T(s)||"deferred":"";return i.uid=$e+p++,Y.assign(i,{setup:n?$(e.setup):r("m#.setup()"),fn:n?$(s):r("m#.fn("+a+")"),fnArg:a,teardown:n?$(e.teardown):r("m#.teardown()")}),"ns"==je.unit?Y.assign(i,{begin:r("s#=n#()"),end:r("r#=n#(s#);r#=r#[0]+(r#[1]/1e9)")}):"us"==je.unit?je.ns.stop?Y.assign(i,{begin:r("s#=n#.start()"),end:r("r#=n#.microseconds()/1e6")}):Y.assign(i,{begin:r("s#=n#()"),end:r("r#=(n#()-s#)/1e6")}):je.ns.now?Y.assign(i,{begin:r("s#=n#.now()"),end:r("r#=(n#.now()-s#)/1e3")}):Y.assign(i,{begin:r("s#=new n#().getTime()"),end:r("r#=(new n#().getTime()-s#)/1e3")}),je.start=v(r("o#"),r("var n#=this.ns,${begin};o#.elapsed=0;o#.timeStamp=s#")),je.stop=v(r("o#"),r("var n#=this.ns,s#=o#.timeStamp,${end};o#.elapsed=r#")),v(r("window,t#"),"var global = window, clearTimeout = global.clearTimeout, setTimeout = global.setTimeout;\n"+r(o))}function n(e){for(var n,t,r=30,o=1e3,i=je.ns,s=[];r--;){if("us"==e)if(o=1e6,i.stop)for(i.start();!(n=i.microseconds()););else for(t=i();!(n=i()-t););else if("ns"==e){for(o=1e9,t=(t=i())[0]+t[1]/o;!(n=(n=i())[0]+n[1]/o-t););o=1}else if(i.now)for(t=i.now();!(n=i.now()-t););else for(t=(new i).getTime();!(n=(new i).getTime()-t););if(!(n>0)){s.push(1/0);break}s.push(n)}return S(s)/o}function r(e){return Y.template(e.replace(/\#/g,/\d+/.exec(i.uid)))(i)}var o=s.options,i={},u=[{ns:je.ns,res:le(.0015,n("ms")),unit:"ms"}];Q=function(n){var r;n instanceof a&&(r=n,n=r.benchmark);var s=n._original,u=C(s.fn),c=s.count=n.count,l=u||Ce.decompilation&&(n.setup!==Y.noop||n.teardown!==Y.noop),f=s.id,p=s.name||("number"==typeof f?"":f),m=0;n.minTime=s.minTime||(s.minTime=s.options.minTime=o.minTime);var d=r?'var d#=this,${fnArg}=d#,m#=d#.benchmark._original,f#=m#.fn,su#=m#.setup,td#=m#.teardown;if(!d#.cycles){d#.fn=function(){var ${fnArg}=d#;if(typeof f#=="function"){try{${fn}\n}catch(e#){f#(d#)}}else{${fn}\n}};d#.teardown=function(){d#.cycles=0;if(typeof td#=="function"){try{${teardown}\n}catch(e#){td#()}}else{${teardown}\n}};if(typeof su#=="function"){try{${setup}\n}catch(e#){su#()}}else{${setup}\n};t#.start(d#);}d#.fn();return{uid:"${uid}"}':'var r#,s#,m#=this,f#=m#.fn,i#=m#.count,n#=t#.ns;${setup}\n${begin};while(i#--){${fn}\n}${end};${teardown}\nreturn{elapsed:r#,uid:"${uid}"}',h=s.compiled=n.compiled=e(s,l,r,d),g=!(i.fn||u);try{if(g)throw new Error('The test "'+p+'" is empty. This may be the result of dead code removal.');r||(s.count=1,h=l&&(h.call(s,t,je)||{}).uid==i.uid&&h,s.count=c)}catch(y){h=null,n.error=y||new Error(oe(y)),s.count=c}if(!h&&!r&&!g){d=(u||l&&!n.error?"function f#(){${fn}\n}var r#,s#,m#=this,i#=m#.count":"var r#,s#,m#=this,f#=m#.fn,i#=m#.count")+",n#=t#.ns;${setup}\n${begin};m#.f#=f#;while(i#--){m#.f#()}${end};delete m#.f#;${teardown}\nreturn{elapsed:r#}",h=e(s,l,r,d);try{s.count=1,h.call(s,t,je),s.count=c,delete n.error}catch(y){s.count=c,n.error||(n.error=y||new Error(oe(y)))}}return n.error||(h=s.compiled=n.compiled=e(s,l,r,d),m=h.call(r||s,t,je).elapsed),m};try{(je.ns=new(t.chrome||t.chromium).Interval)&&u.push({ns:je.ns,res:n("us"),unit:"us"})}catch(c){}if(Te&&"function"==typeof(je.ns=Te.hrtime)&&u.push({ns:je.ns,res:n("ns"),unit:"ns"}),we&&"function"==typeof(je.ns=we.now)&&u.push({ns:je.ns,res:n("us"),unit:"us"}),je=Y.minBy(u,"res"),je.res==1/0)throw new Error("Benchmark.js was unable to find a working timer.");return o.minTime||(o.minTime=le(je.res/2/.01,.05)),Q.apply(null,arguments)}function U(e,n){function t(){c.push(e.clone({_original:e,events:{abort:[r],cycle:[r],error:[r],start:[r]}}))}function r(n){var t=this,r=n.type;e.running?"start"==r?t.count=e.initCount:("error"==r&&(e.error=t.error),"abort"==r?(e.abort(),e.emit("cycle")):(n.currentTarget=n.target=e,e.emit(n))):e.aborted&&(t.events.abort.length=0,t.abort())}function o(n){var r,o,i,f,p,m,d,g,y=n.target,v=e.aborted,b=Y.now(),w=l.push(y.times.period),T=w>=u&&(s+=b-y.times.timeStamp)/1e3>e.maxTime,$=e.times,x=function(e,n){return e+pe(n-i,2)};(v||y.hz==1/0)&&(T=!(w=l.length=c.length=0)),v||(i=S(l),g=Y.reduce(l,x,0)/(w-1)||0,m=ge(g),d=m/ge(w),o=w-1,r=h[te.round(o)||1]||h.infinity,f=d*r,p=f/i*100||0,Y.assign(e.stats,{deviation:m,mean:i,moe:f,rme:p,sem:d,variance:g}),T&&(e.initCount=a,e.running=!1,v=!0,$.elapsed=(b-$.timeStamp)/1e3),e.hz!=1/0&&(e.hz=1/i,$.cycle=i*e.count,$.period=i)),c.length<2&&!T&&t(),n.aborted=v}n||(n={});var i=n.async,s=0,a=e.initCount,u=e.minSamples,c=[],l=e.stats.sample;t(),F(c,{name:"run",args:{async:i},queued:!0,onCycle:o,onComplete:function(){e.emit("complete")}})}function V(e,n){n||(n={});var r;e instanceof a&&(r=e,e=e.benchmark);var o,i,s,u,c,f,p=n.async,m=e._original,h=e.count,g=e.times;e.running&&(i=++e.cycles,o=r?r.elapsed:Q(e),c=e.minTime,i>m.cycles&&(m.cycles=i),e.error&&(u=l("error"),u.message=e.error,e.emit(u),u.cancelled||e.abort())),e.running&&(m.times.cycle=g.cycle=o,f=m.times.period=g.period=o/h,m.hz=e.hz=1/f,m.initCount=e.initCount=h,e.running=c>o,e.running&&(o||null==(s=d[e.cycles])||(h=ce(4e6/s)),h<=e.count&&(h+=te.ceil((c-o)/f)),e.running=h!=1/0)),u=l("cycle"),e.emit(u),u.aborted&&e.abort(),e.running?(e.count=h,r?e.compiled.call(r,t,je):p?b(e,function(){V(e,n)}):V(e)):(Ce.browser&&k($e+"=1;delete "+$e),e.emit("complete"))}function X(e){var n=this,t=l("start");return n.running=!1,n.reset(),n.running=!0,n.count=n.initCount,n.times.timeStamp=Y.now(),n.emit(t),t.cancelled||(e={async:(null==(e=e&&e.async)?n.async:e)&&Ce.timeout},n._original?n.defer?a(n):V(n,e):U(n,e)),n}var Y=t&&t._||j("lodash")||r._;if(!Y)return s.runInContext=e,s;t=t?Y.defaults(r.Object(),t,Y.pick(r,m)):r;var ee=(t.Array,t.Date),ne=t.Function,te=t.Math,re=t.Object,oe=(t.RegExp,t.String),ie=[],se=re.prototype,ae=te.abs,ue=t.clearTimeout,ce=te.floor,le=(te.log,te.max),fe=te.min,pe=te.pow,me=ie.push,de=(t.setTimeout,ie.shift),he=ie.slice,ge=te.sqrt,ye=(se.toString,ie.unshift),ve=j,be=x(t,"document")&&t.document,we=ve("microtime"),Te=x(t,"process")&&t.process,Se=be&&be.createElement("div"),$e="uid"+Y.now(),xe={},Ce={};!function(){Ce.browser=be&&x(t,"navigator")&&!x(t,"phantom"),Ce.timeout=x(t,"setTimeout")&&x(t,"clearTimeout");try{Ce.decompilation="1"===ne(("return ("+function(e){return{x:""+(1+e),y:0}}+")").replace(/__cov__[^;]+;/g,""))()(0).x}catch(e){Ce.decompilation=!1}}();var je={ns:ee,start:null,stop:null},ke=Y.partial(Y.cloneDeepWith,Y,function(e){return!Y.isObject(e)||Y.isArray(e)||Y.isPlainObject(e)?n:e});return Y.assign(s,{options:{async:!1,defer:!1,delay:.005,id:n,initCount:1,maxTime:5,minSamples:5,minTime:0,name:n,onAbort:n,onComplete:n,onCycle:n,onError:n,onReset:n,onStart:n},platform:t.platform||j("platform")||{description:t.navigator&&t.navigator.userAgent||null,layout:null,product:null,name:null,manufacturer:null,os:null,prerelease:null,version:null,toString:function(){return this.description||""}},version:"2.1.0"}),Y.assign(s,{filter:A,formatNumber:E,invoke:F,join:B,runInContext:e,support:Ce}),Y.each(["each","forEach","forOwn","has","indexOf","map","reduce"],function(e){s[e]=Y[e]}),Y.assign(s.prototype,{count:0,cycles:0,hz:0,compiled:n,error:n,fn:n,aborted:!1,running:!1,setup:Y.noop,teardown:Y.noop,stats:{moe:0,rme:0,sem:0,deviation:0,mean:0,sample:[],variance:0},times:{cycle:0,elapsed:0,period:0,timeStamp:0}}),Y.assign(s.prototype,{abort:H,clone:Z,compare:G,emit:M,listeners:R,off:L,on:W,reset:J,run:X,toString:K}),Y.assign(a.prototype,{benchmark:null,cycles:0,elapsed:0,timeStamp:0}),Y.assign(a.prototype,{resolve:O}),Y.assign(l.prototype,{aborted:!1,cancelled:!1,currentTarget:n,result:n,target:n,timeStamp:0,type:""}),y.options={name:n},Y.assign(y.prototype,{length:0,aborted:!1,running:!1}),Y.assign(y.prototype,{abort:z,add:q,clone:N,emit:M,filter:I,join:ie.join,listeners:R,off:L,on:W,pop:ie.pop,push:me,reset:D,run:P,reverse:ie.reverse,shift:de,slice:he,sort:ie.sort,splice:ie.splice,unshift:ye}),Y.assign(s,{Deferred:a,Event:l,Suite:y}),Y.each(["each","forEach","indexOf","map","reduce"],function(e){var n=Y[e];y.prototype[e]=function(){var e=[this];return me.apply(e,arguments),n.apply(Y,e)}}),Y.each(["pop","shift","splice"],function(e){var n=ie[e];y.prototype[e]=function(){var e=this,t=n.apply(e,arguments);return 0===e.length&&delete e[0],t}}),y.prototype.unshift=function(){var e=this;return ye.apply(e,arguments),e.length},s}var n,t={"function":!0,object:!0},r=t[typeof window]&&window||this,o="function"==typeof define&&"object"==typeof define.amd&&define.amd&&define,i=t[typeof exports]&&exports&&!exports.nodeType&&exports,s=t[typeof module]&&module&&!module.nodeType&&module,a=i&&s&&"object"==typeof global&&global;!a||a.global!==a&&a.window!==a&&a.self!==a||(r=a);var u="function"==typeof require&&require,c=0,l=s&&s.exports===i&&i,f=/^(?:boolean|number|string|undefined)$/,p=0,m=["Array","Date","Function","Math","Object","RegExp","String","_","clearTimeout","chrome","chromium","document","navigator","phantom","platform","process","runtime","setTimeout"],d={1:4096,2:512,3:64,4:8,5:0},h={1:12.706,2:4.303,3:3.182,4:2.776,5:2.571,6:2.447,7:2.365,8:2.306,9:2.262,10:2.228,11:2.201,12:2.179,13:2.16,14:2.145,15:2.131,16:2.12,17:2.11,18:2.101,19:2.093,20:2.086,21:2.08,22:2.074,23:2.069,24:2.064,25:2.06,26:2.056,27:2.052,28:2.048,29:2.045,30:2.042,infinity:1.96},g={5:[0,1,2],6:[1,2,3,5],7:[1,3,5,6,8],8:[2,4,6,8,10,13],9:[2,4,7,10,12,15,17],10:[3,5,8,11,14,17,20,23],11:[3,6,9,13,16,19,23,26,30],12:[4,7,11,14,18,22,26,29,33,37],13:[4,8,12,16,20,24,28,33,37,41,45],14:[5,9,13,17,22,26,31,36,40,45,50,55],15:[5,10,14,19,24,29,34,39,44,49,54,59,64],16:[6,11,15,21,26,31,37,42,47,53,59,64,70,75],17:[6,11,17,22,28,34,39,45,51,57,63,67,75,81,87],18:[7,12,18,24,30,36,42,48,55,61,67,74,80,86,93,99],19:[7,13,19,25,32,38,45,52,58,65,72,78,85,92,99,106,113],20:[8,14,20,27,34,41,48,55,62,69,76,83,90,98,105,112,119,127],21:[8,15,22,29,36,43,50,58,65,73,80,88,96,103,111,119,126,134,142],22:[9,16,23,30,38,45,53,61,69,77,85,93,101,109,117,125,133,141,150,158],23:[9,17,24,32,40,48,56,64,73,81,89,98,106,115,123,132,140,149,157,166,175],24:[10,17,25,33,42,50,59,67,76,85,94,102,111,120,129,138,147,156,165,174,183,192],25:[10,18,27,35,44,53,62,71,80,89,98,107,117,126,135,145,154,163,173,182,192,201,211],26:[11,19,28,37,46,55,64,74,83,93,102,112,122,132,141,151,161,171,181,191,200,210,220,230],27:[11,20,29,38,48,57,67,77,87,97,107,118,125,138,147,158,168,178,188,199,209,219,230,240,250],28:[12,21,30,40,50,60,70,80,90,101,111,122,132,143,154,164,175,186,196,207,218,228,239,250,261,272],29:[13,22,32,42,52,62,73,83,94,105,116,127,138,149,160,171,182,193,204,215,226,238,249,260,271,282,294],30:[13,23,33,43,54,65,76,87,98,109,120,131,143,154,166,177,189,200,212,223,235,247,258,270,282,293,305,317]};if("function"==typeof define&&"object"==typeof define.amd&&define.amd)define(["lodash","platform"],function(n,t){return e({_:n,platform:t})});else{var y=e();i&&s?(l&&((s.exports=y).Benchmark=y),i.Benchmark=y):r.Benchmark=y}}).call(this); \ No newline at end of file diff --git a/test/benchmark/vendor/lodash.min.js b/test/benchmark/vendor/lodash.min.js deleted file mode 100644 index 018b6a766868ee..00000000000000 --- a/test/benchmark/vendor/lodash.min.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @license - * lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE - */ -;(function(){function t(t,n){return t.set(n[0],n[1]),t}function n(t,n){return t.add(n),t}function r(t,n,r){switch(r.length){case 0:return t.call(n);case 1:return t.call(n,r[0]);case 2:return t.call(n,r[0],r[1]);case 3:return t.call(n,r[0],r[1],r[2])}return t.apply(n,r)}function e(t,n,r,e){for(var u=-1,o=t?t.length:0;++u=t?t:r),n!==T&&(t=t>=n?t:n)),t}function rn(t,n,r,e,o,i,f){var c;if(e&&(c=i?e(t,o,i,f):e(t)),c!==T)return c;if(!Ze(t))return t;if(o=yi(t)){if(c=Kr(t),!n)return lr(t,c)}else{var a=qr(t),l="[object Function]"==a||"[object GeneratorFunction]"==a;if(bi(t))return or(t,n);if("[object Object]"==a||"[object Arguments]"==a||l&&!i){if(C(t))return i?t:{};if(c=Gr(l?{}:t), -!n)return hr(t,Xt(c,t))}else{if(!Ct[a])return i?t:{};c=Jr(t,a,rn,n)}}if(f||(f=new qt),i=f.get(t))return i;if(f.set(t,c),!o)var s=r?gn(t,iu,Tr):iu(t);return u(s||t,function(u,o){s&&(o=u,u=t[o]),Yt(c,o,rn(u,n,r,e,o,t,f))}),c}function en(t){var n=iu(t),r=n.length;return function(e){if(null==e)return!r;for(var u=r;u--;){var o=n[u],i=t[o],f=e[o];if(f===T&&!(o in Object(e))||!i(f))return false}return true}}function un(t){return Ze(t)?Tu(t):{}}function on(t,n,r){if(typeof t!="function")throw new Au("Expected a function"); -return At(function(){t.apply(T,r)},n)}function fn(t,n,r,e){var u=-1,o=c,i=true,f=t.length,s=[],h=n.length;if(!f)return s;r&&(n=l(n,O(r))),e?(o=a,i=false):n.length>=200&&(o=E,i=false,n=new Zt(n));t:for(;++u0&&r(f)?n>1?sn(f,n-1,r,e,u):s(u,f):e||(u[u.length]=f)}return u}function hn(t,n){return t&&ko(t,n,iu)}function pn(t,n){return t&&Eo(t,n,iu)}function _n(t,n){return f(n,function(n){return Fe(t[n])})}function vn(t,n){n=ne(n,t)?[n]:er(n);for(var r=0,e=n.length;null!=t&&e>r;)t=t[fe(n[r++])];return r&&r==e?t:T}function gn(t,n,r){ -return n=n(t),yi(t)?n:s(n,r(t))}function dn(t,n){return t>n}function yn(t,n){return null!=t&&(Wu.call(t,n)||typeof t=="object"&&n in t&&null===Ju(Object(t)))}function bn(t,n){return null!=t&&n in Object(t)}function xn(t,n,r){for(var e=r?a:c,u=t[0].length,o=t.length,i=o,f=Array(o),s=1/0,h=[];i--;){var p=t[i];i&&n&&(p=l(p,O(n))),s=to(p.length,s),f[i]=!r&&(n||u>=120&&p.length>=120)?new Zt(i&&p):T}var p=t[0],_=-1,v=f[0];t:for(;++_h.length;){var g=p[_],d=n?n(g):g,g=r||0!==g?g:0;if(v?!E(v,d):!e(h,d,r)){ -for(i=o;--i;){var y=f[i];if(y?!E(y,d):!e(t[i],d,r))continue t}v&&v.push(d),h.push(g)}}return h}function jn(t,n,r){var e={};return hn(t,function(t,u,o){n(e,r(t),u,o)}),e}function wn(t,n,e){return ne(n,t)||(n=er(n),t=ie(t,n),n=ve(n)),n=null==t?t:t[fe(n)],null==n?T:r(n,t,e)}function mn(t,n,r,e,u){if(t===n)n=true;else if(null==t||null==n||!Ze(t)&&!Te(n))n=t!==t&&n!==n;else t:{var o=yi(t),i=yi(n),f="[object Array]",c="[object Array]";o||(f=qr(t),f="[object Arguments]"==f?"[object Object]":f),i||(c=qr(n), -c="[object Arguments]"==c?"[object Object]":c);var a="[object Object]"==f&&!C(t),i="[object Object]"==c&&!C(n);if((c=f==c)&&!a)u||(u=new qt),n=o||Ye(t)?zr(t,n,mn,r,e,u):Ur(t,n,f,mn,r,e,u);else{if(!(2&e)&&(o=a&&Wu.call(t,"__wrapped__"),f=i&&Wu.call(n,"__wrapped__"),o||f)){t=o?t.value():t,n=f?n.value():n,u||(u=new qt),n=mn(t,n,r,e,u);break t}if(c)n:if(u||(u=new qt),o=2&e,f=iu(t),i=f.length,c=iu(n).length,i==c||o){for(a=i;a--;){var l=f[a];if(!(o?l in n:yn(n,l))){n=false;break n}}if(c=u.get(t))n=c==n;else{ -c=true,u.set(t,n);for(var s=o;++at}function In(t,n){var r=-1,e=Ue(t)?Array(t.length):[]; -return Ao(t,function(t,u,o){e[++r]=n(t,u,o)}),e}function Rn(t){var n=Pr(t);return 1==n.length&&n[0][2]?ue(n[0][0],n[0][1]):function(r){return r===t||An(r,t,n)}}function Wn(t,n){return ne(t)&&n===n&&!Ze(n)?ue(fe(t),n):function(r){var e=uu(r,t);return e===T&&e===n?ou(r,t):mn(n,e,T,3)}}function Bn(t,n,r,e,o){if(t!==n){if(!yi(n)&&!Ye(n))var i=fu(n);u(i||n,function(u,f){if(i&&(f=u,u=n[f]),Ze(u)){o||(o=new qt);var c=f,a=o,l=t[c],s=n[c],h=a.get(s);if(h)Jt(t,c,h);else{var h=e?e(l,s,c+"",t,n,a):T,p=h===T;p&&(h=s, -yi(s)||Ye(s)?yi(l)?h=l:$e(l)?h=lr(l):(p=false,h=rn(s,true)):Ve(s)||ze(s)?ze(l)?h=ru(l):!Ze(l)||r&&Fe(l)?(p=false,h=rn(s,true)):h=l:p=false),a.set(s,h),p&&Bn(h,s,r,e,a),a["delete"](s),Jt(t,c,h)}}else c=e?e(t[f],u,f+"",t,n,o):T,c===T&&(c=u),Jt(t,f,c)})}}function Ln(t,n){var r=t.length;return r?(n+=0>n?r:0,Xr(n,r)?t[n]:T):void 0}function Mn(t,n,r){var e=-1;return n=l(n.length?n:[pu],O(Fr())),t=In(t,function(t){return{a:l(n,function(n){return n(t)}),b:++e,c:t}}),j(t,function(t,n){var e;t:{e=-1;for(var u=t.a,o=n.a,i=u.length,f=r.length;++e=f?c:c*("desc"==r[e]?-1:1);break t}}e=t.b-n.b}return e})}function Cn(t,n){return t=Object(t),h(n,function(n,r){return r in t&&(n[r]=t[r]),n},{})}function zn(t,n){for(var r=-1,e=gn(t,fu,Bo),u=e.length,o={};++rn||n>9007199254740991)return r;do n%2&&(r+=t),(n=Gu(n/2))&&(t+=t);while(n);return r}function Zn(t,n,r,e){n=ne(n,t)?[n]:er(n);for(var u=-1,o=n.length,i=o-1,f=t;null!=f&&++un&&(n=-n>u?0:u+n),r=r>u?u:r,0>r&&(r+=u),u=n>r?0:r-n>>>0,n>>>=0,r=Array(u);++e=u){for(;u>e;){var o=e+u>>>1,i=t[o];null!==i&&!Je(i)&&(r?n>=i:n>i)?e=o+1:u=o}return u} -return Kn(t,n,pu,r)}function Kn(t,n,r,e){n=r(n);for(var u=0,o=t?t.length:0,i=n!==n,f=null===n,c=Je(n),a=n===T;o>u;){var l=Gu((u+o)/2),s=r(t[l]),h=s!==T,p=null===s,_=s===s,v=Je(s);(i?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?n>=s:n>s)?u=l+1:o=l}return to(o,4294967294)}function Gn(t,n){for(var r=-1,e=t.length,u=0,o=[];++r=200){if(u=n?null:Io(t))return D(u);i=false,u=E,l=new Zt}else l=n?[]:f;t:for(;++ee?n[e]:T);return i}function rr(t){return $e(t)?t:[]}function er(t){return yi(t)?t:Co(t)}function ur(t,n,r){var e=t.length;return r=r===T?e:r,!n&&r>=e?t:Tn(t,n,r)}function or(t,n){ -if(n)return t.slice();var r=new t.constructor(t.length);return t.copy(r),r}function ir(t){var n=new t.constructor(t.byteLength);return new Fu(n).set(new Fu(t)),n}function fr(t,n){if(t!==n){var r=t!==T,e=null===t,u=t===t,o=Je(t),i=n!==T,f=null===n,c=n===n,a=Je(n);if(!f&&!a&&!o&&t>n||o&&i&&c&&!f&&!a||e&&i&&c||!r&&c||!u)return 1;if(!e&&!o&&!a&&n>t||a&&r&&u&&!e&&!o||f&&r&&u||!i&&u||!c)return-1}return 0}function cr(t,n,r,e){var u=-1,o=t.length,i=r.length,f=-1,c=n.length,a=Xu(o-i,0),l=Array(c+a);for(e=!e;++fu)&&(l[r[u]]=t[u]);for(;a--;)l[f++]=t[u++];return l}function ar(t,n,r,e){var u=-1,o=t.length,i=-1,f=r.length,c=-1,a=n.length,l=Xu(o-f,0),s=Array(l+a);for(e=!e;++uu)&&(s[l+r[i]]=t[u++]);return s}function lr(t,n){var r=-1,e=t.length;for(n||(n=Array(e));++r1?r[u-1]:T,i=u>2?r[2]:T,o=t.length>3&&typeof o=="function"?(u--,o):T;for(i&&te(r[0],r[1],i)&&(o=3>u?T:o,u=1),n=Object(n);++ei&&f[0]!==a&&f[i-1]!==a?[]:$(f,a), -i-=c.length,e>i?Br(t,n,Ar,u.placeholder,T,f,c,T,T,e-i):r(this&&this!==Kt&&this instanceof u?o:t,this,f)}var o=xr(t);return u}function wr(t){return function(n,r,e){var u=Object(n);if(r=Fr(r,3),!Ue(n))var o=iu(n);return e=t(o||n,function(t,n){return o&&(n=t,t=u[n]),r(t,n,u)},e),e>-1?n[o?o[e]:e]:T}}function mr(t){return Me(function(n){n=sn(n,1);var r=n.length,e=r,u=zt.prototype.thru;for(t&&n.reverse();e--;){var o=n[e];if(typeof o!="function")throw new Au("Expected a function");if(u&&!i&&"wrapper"==$r(o))var i=new zt([],true); -}for(e=i?e:r;++e=200)return i.plant(e).value();for(var u=0,t=r?n[u].apply(this,t):e;++ud)return j=$(y,j),Br(t,n,Ar,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[t]:t,d=y.length,f){x=y.length;for(var w=to(f.length,x),m=lr(y);w--;){var A=f[w];y[w]=Xr(A,x)?m[A]:T}}else v&&d>1&&y.reverse();return s&&d>c&&(y.length=c),this&&this!==Kt&&this instanceof l&&(b=g||xr(b)),b.apply(j,y)}var s=128&n,h=1&n,p=2&n,_=24&n,v=512&n,g=p?T:xr(t);return l}function Or(t,n){return function(r,e){return jn(r,t,n(e))}}function kr(t){return function(n,r){var e; -if(n===T&&r===T)return 0;if(n!==T&&(e=n),r!==T){if(e===T)return r;typeof n=="string"||typeof r=="string"?(n=Yn(n),r=Yn(r)):(n=Jn(n),r=Jn(r)),e=t(n,r)}return e}}function Er(t){return Me(function(n){return n=1==n.length&&yi(n[0])?l(n[0],O(Fr())):l(sn(n,1,Qr),O(Fr())),Me(function(e){var u=this;return t(n,function(t){return r(t,u,e)})})})}function Sr(t,n){n=n===T?" ":Yn(n);var r=n.length;return 2>r?r?Pn(n,t):n:(r=Pn(n,Ku(t/N(n))),Wt.test(n)?ur(r.match(It),0,t).join(""):r.slice(0,t))}function Ir(t,n,e,u){ -function o(){for(var n=-1,c=arguments.length,a=-1,l=u.length,s=Array(l+c),h=this&&this!==Kt&&this instanceof o?f:t;++an?1:-1:nu(e)||0;var u=-1;r=Xu(Ku((r-n)/(e||1)),0);for(var o=Array(r);r--;)o[t?r:++u]=n,n+=e;return o}}function Wr(t){return function(n,r){return typeof n=="string"&&typeof r=="string"||(n=nu(n), -r=nu(r)),t(n,r)}}function Br(t,n,r,e,u,o,i,f,c,a){var l=8&n,s=l?i:T;i=l?T:i;var h=l?o:T;return o=l?T:o,n=(n|(l?32:64))&~(l?64:32),4&n||(n&=-4),n=[t,n,u,h,s,o,i,f,c,a],r=r.apply(T,n),re(t)&&Mo(r,n),r.placeholder=e,r}function Lr(t){var n=wu[t];return function(t,r){if(t=nu(t),r=to(Xe(r),292)){var e=(eu(t)+"e").split("e"),e=n(e[0]+"e"+(+e[1]+r)),e=(eu(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return n(t)}}function Mr(t){return function(n){var r=qr(n);return"[object Map]"==r?U(n):"[object Set]"==r?F(n):A(n,t(n)); -}}function Cr(t,n,r,e,u,o,i,f){var c=2&n;if(!c&&typeof t!="function")throw new Au("Expected a function");var a=e?e.length:0;if(a||(n&=-97,e=u=T),i=i===T?i:Xu(Xe(i),0),f=f===T?f:Xe(f),a-=u?u.length:0,64&n){var l=e,s=u;e=u=T}var h=c?T:Ro(t);return o=[t,n,r,e,u,l,s,o,i,f],h&&(r=o[1],t=h[1],n=r|t,e=128==t&&8==r||128==t&&256==r&&h[8]>=o[7].length||384==t&&h[8]>=h[7].length&&8==r,131>n||e)&&(1&t&&(o[2]=h[2],n|=1&r?0:4),(r=h[3])&&(e=o[3],o[3]=e?cr(e,r,h[4]):r,o[4]=e?$(o[3],"__lodash_placeholder__"):h[4]), -(r=h[5])&&(e=o[5],o[5]=e?ar(e,r,h[6]):r,o[6]=e?$(o[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(o[7]=r),128&t&&(o[8]=null==o[8]?h[8]:to(o[8],h[8])),null==o[9]&&(o[9]=h[9]),o[0]=h[0],o[1]=n),t=o[0],n=o[1],r=o[2],e=o[3],u=o[4],f=o[9]=null==o[9]?c?0:t.length:Xu(o[9]-a,0),!f&&24&n&&(n&=-25),(h?So:Mo)(n&&1!=n?8==n||16==n?jr(t,n,f):32!=n&&33!=n||u.length?Ar.apply(T,o):Ir(t,n,r,e):dr(t,n,r),o)}function zr(t,n,r,e,u,o){var i=2&u,f=t.length,c=n.length;if(f!=c&&!(i&&c>f))return false;if(c=o.get(t))return c==n; -var c=-1,a=true,l=1&u?new Zt:T;for(o.set(t,n);++c-1&&0==t%1&&n>t}function te(t,n,r){if(!Ze(r))return false;var e=typeof n;return("number"==e?Ue(r)&&Xr(n,r.length):"string"==e&&n in r)?Ce(r[n],t):false}function ne(t,n){if(yi(t))return false;var r=typeof t;return"number"==r||"symbol"==r||"boolean"==r||null==t||Je(t)?true:ut.test(t)||!et.test(t)||null!=n&&t in Object(n)}function re(t){ -var n=$r(t),r=Ot[n];return typeof r=="function"&&n in Ut.prototype?t===r?true:(n=Ro(r),!!n&&t===n[0]):false}function ee(t){var n=t&&t.constructor;return t===(typeof n=="function"&&n.prototype||ku)}function ue(t,n){return function(r){return null==r?false:r[t]===n&&(n!==T||t in Object(r))}}function oe(t,n,r,e,u,o){return Ze(t)&&Ze(n)&&Bn(t,n,T,oe,o.set(n,t)),t}function ie(t,n){return 1==n.length?t:vn(t,Tn(n,0,-1))}function fe(t){if(typeof t=="string"||Je(t))return t;var n=t+"";return"0"==n&&1/t==-q?"-0":n}function ce(t){ -if(null!=t){try{return Ru.call(t)}catch(n){}return t+""}return""}function ae(t){if(t instanceof Ut)return t.clone();var n=new zt(t.__wrapped__,t.__chain__);return n.__actions__=lr(t.__actions__),n.__index__=t.__index__,n.__values__=t.__values__,n}function le(t,n,r){var e=t?t.length:0;return e?(n=r||n===T?1:Xe(n),Tn(t,0>n?0:n,e)):[]}function se(t,n,r){var e=t?t.length:0;return e?(n=r||n===T?1:Xe(n),n=e-n,Tn(t,0,0>n?0:n)):[]}function he(t,n,r){var e=t?t.length:0;return e?(r=null==r?0:Xe(r),0>r&&(r=Xu(e+r,0)), -g(t,Fr(n,3),r)):-1}function pe(t,n,r){var e=t?t.length:0;if(!e)return-1;var u=e-1;return r!==T&&(u=Xe(r),u=0>r?Xu(e+u,0):to(u,e-1)),g(t,Fr(n,3),u,true)}function _e(t){return t&&t.length?t[0]:T}function ve(t){var n=t?t.length:0;return n?t[n-1]:T}function ge(t,n){return t&&t.length&&n&&n.length?Dn(t,n):t}function de(t){return t?uo.call(t):t}function ye(t){if(!t||!t.length)return[];var n=0;return t=f(t,function(t){return $e(t)?(n=Xu(t.length,n),true):void 0}),m(n,function(n){return l(t,Un(n))})}function be(t,n){ -if(!t||!t.length)return[];var e=ye(t);return null==n?e:l(e,function(t){return r(n,T,t)})}function xe(t){return t=Ot(t),t.__chain__=true,t}function je(t,n){return n(t)}function we(){return this}function me(t,n){return(yi(t)?u:Ao)(t,Fr(n,3))}function Ae(t,n){return(yi(t)?o:Oo)(t,Fr(n,3))}function Oe(t,n){return(yi(t)?l:In)(t,Fr(n,3))}function ke(t,n,r){var e=-1,u=He(t),o=u.length,i=o-1;for(n=(r?te(t,n,r):n===T)?1:nn(Xe(n),0,o);++e=t&&(n=T),r}}function Re(t,n,r){return n=r?T:n,t=Cr(t,8,T,T,T,T,T,n),t.placeholder=Re.placeholder,t}function We(t,n,r){return n=r?T:n,t=Cr(t,16,T,T,T,T,T,n),t.placeholder=We.placeholder,t}function Be(t,n,r){function e(n){var r=c,e=a;return c=a=T,_=n,s=t.apply(e,r); -}function u(t){var r=t-p;return t-=_,p===T||r>=n||0>r||g&&t>=l}function o(){var t=Ee();if(u(t))return i(t);var r;r=t-_,t=n-(t-p),r=g?to(t,l-r):t,h=At(o,r)}function i(t){return h=T,d&&c?e(t):(c=a=T,s)}function f(){var t=Ee(),r=u(t);if(c=arguments,a=this,p=t,r){if(h===T)return _=t=p,h=At(o,n),v?e(t):s;if(g)return h=At(o,n),e(p)}return h===T&&(h=At(o,n)),s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof t!="function")throw new Au("Expected a function");return n=nu(n)||0,Ze(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Xu(nu(r.maxWait)||0,n):l, -d="trailing"in r?!!r.trailing:d),f.cancel=function(){_=0,c=p=a=h=T},f.flush=function(){return h===T?s:i(Ee())},f}function Le(t,n){function r(){var e=arguments,u=n?n.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=t.apply(this,e),r.cache=o.set(u,e),e)}if(typeof t!="function"||n&&typeof n!="function")throw new Au("Expected a function");return r.cache=new(Le.Cache||Pt),r}function Me(t,n){if(typeof t!="function")throw new Au("Expected a function");return n=Xu(n===T?t.length-1:Xe(n),0),function(){ -for(var e=arguments,u=-1,o=Xu(e.length-n,0),i=Array(o);++u-1&&0==t%1&&9007199254740991>=t}function Ze(t){var n=typeof t;return!!t&&("object"==n||"function"==n)}function Te(t){return!!t&&typeof t=="object"}function qe(t){return typeof t=="number"||Te(t)&&"[object Number]"==Mu.call(t); -}function Ve(t){return!Te(t)||"[object Object]"!=Mu.call(t)||C(t)?false:(t=Ju(Object(t)),null===t?true:(t=Wu.call(t,"constructor")&&t.constructor,typeof t=="function"&&t instanceof t&&Ru.call(t)==Lu))}function Ke(t){return Ze(t)&&"[object RegExp]"==Mu.call(t)}function Ge(t){return typeof t=="string"||!yi(t)&&Te(t)&&"[object String]"==Mu.call(t)}function Je(t){return typeof t=="symbol"||Te(t)&&"[object Symbol]"==Mu.call(t)}function Ye(t){return Te(t)&&Pe(t.length)&&!!Mt[Mu.call(t)]}function He(t){if(!t)return[]; -if(Ue(t))return Ge(t)?t.match(It):lr(t);if(Zu&&t[Zu])return z(t[Zu]());var n=qr(t);return("[object Map]"==n?U:"[object Set]"==n?D:cu)(t)}function Qe(t){return t?(t=nu(t),t===q||t===-q?1.7976931348623157e308*(0>t?-1:1):t===t?t:0):0===t?t:0}function Xe(t){t=Qe(t);var n=t%1;return t===t?n?t-n:t:0}function tu(t){return t?nn(Xe(t),0,4294967295):0}function nu(t){if(typeof t=="number")return t;if(Je(t))return V;if(Ze(t)&&(t=Fe(t.valueOf)?t.valueOf():t,t=Ze(t)?t+"":t),typeof t!="string")return 0===t?t:+t; -t=t.replace(ct,"");var n=dt.test(t);return n||bt.test(t)?Nt(t.slice(2),n?2:8):gt.test(t)?V:+t}function ru(t){return sr(t,fu(t))}function eu(t){return null==t?"":Yn(t)}function uu(t,n,r){return t=null==t?T:vn(t,n),t===T?r:t}function ou(t,n){return null!=t&&Vr(t,n,bn)}function iu(t){var n=ee(t);if(!n&&!Ue(t))return Qu(Object(t));var r,e=Yr(t),u=!!e,e=e||[],o=e.length;for(r in t)!yn(t,r)||u&&("length"==r||Xr(r,o))||n&&"constructor"==r||e.push(r);return e}function fu(t){for(var n=-1,r=ee(t),e=En(t),u=e.length,o=Yr(t),i=!!o,o=o||[],f=o.length;++nt?false:(t==n.length-1?n.pop():Vu.call(n,t,1),true)},Dt.prototype.get=function(t){ -var n=this.__data__;return t=Ht(n,t),0>t?T:n[t][1]},Dt.prototype.has=function(t){return-1e?r.push([t,n]):r[e][1]=n,this},Pt.prototype.clear=function(){this.__data__={hash:new $t,map:new(fo||Dt),string:new $t}},Pt.prototype["delete"]=function(t){return Nr(this,t)["delete"](t)},Pt.prototype.get=function(t){return Nr(this,t).get(t)},Pt.prototype.has=function(t){return Nr(this,t).has(t)},Pt.prototype.set=function(t,n){ -return Nr(this,t).set(t,n),this},Zt.prototype.add=Zt.prototype.push=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this},Zt.prototype.has=function(t){return this.__data__.has(t)},qt.prototype.clear=function(){this.__data__=new Dt},qt.prototype["delete"]=function(t){return this.__data__["delete"](t)},qt.prototype.get=function(t){return this.__data__.get(t)},qt.prototype.has=function(t){return this.__data__.has(t)},qt.prototype.set=function(t,n){var r=this.__data__;return r instanceof Dt&&200==r.__data__.length&&(r=this.__data__=new Pt(r.__data__)), -r.set(t,n),this};var Ao=vr(hn),Oo=vr(pn,true),ko=gr(),Eo=gr(true);Nu&&!qu.call({valueOf:1},"valueOf")&&(En=function(t){return z(Nu(t))});var So=ho?function(t,n){return ho.set(t,n),t}:pu,Io=ao&&1/D(new ao([,-0]))[1]==q?function(t){return new ao(t)}:gu,Ro=ho?function(t){return ho.get(t)}:gu,Wo=Un("length");Pu||(Tr=yu);var Bo=Pu?function(t){for(var n=[];t;)s(n,Tr(t)),t=Ju(Object(t));return n}:Tr;(io&&"[object DataView]"!=qr(new io(new ArrayBuffer(1)))||fo&&"[object Map]"!=qr(new fo)||co&&"[object Promise]"!=qr(co.resolve())||ao&&"[object Set]"!=qr(new ao)||lo&&"[object WeakMap]"!=qr(new lo))&&(qr=function(t){ -var n=Mu.call(t);if(t=(t="[object Object]"==n?t.constructor:T)?ce(t):T)switch(t){case vo:return"[object DataView]";case go:return"[object Map]";case yo:return"[object Promise]";case bo:return"[object Set]";case xo:return"[object WeakMap]"}return n});var Lo=Su?Fe:bu,Mo=function(){var t=0,n=0;return function(r,e){var u=Ee(),o=16-(u-n);if(n=u,o>0){if(150<=++t)return r}else t=0;return So(r,e)}}(),Co=Le(function(t){var n=[];return eu(t).replace(ot,function(t,r,e,u){n.push(e?u.replace(ht,"$1"):r||t)}), -n}),zo=Me(function(t,n){return $e(t)?fn(t,sn(n,1,$e,true)):[]}),Uo=Me(function(t,n){var r=ve(n);return $e(r)&&(r=T),$e(t)?fn(t,sn(n,1,$e,true),Fr(r)):[]}),$o=Me(function(t,n){var r=ve(n);return $e(r)&&(r=T),$e(t)?fn(t,sn(n,1,$e,true),T,r):[]}),Do=Me(function(t){var n=l(t,rr);return n.length&&n[0]===t[0]?xn(n):[]}),Fo=Me(function(t){var n=ve(t),r=l(t,rr);return n===ve(r)?n=T:r.pop(),r.length&&r[0]===t[0]?xn(r,Fr(n)):[]}),No=Me(function(t){var n=ve(t),r=l(t,rr);return n===ve(r)?n=T:r.pop(),r.length&&r[0]===t[0]?xn(r,T,n):[]; -}),Po=Me(ge),Zo=Me(function(t,n){n=sn(n,1);var r=t?t.length:0,e=tn(t,n);return Fn(t,l(n,function(t){return Xr(t,r)?+t:t}).sort(fr)),e}),To=Me(function(t){return Hn(sn(t,1,$e,true))}),qo=Me(function(t){var n=ve(t);return $e(n)&&(n=T),Hn(sn(t,1,$e,true),Fr(n))}),Vo=Me(function(t){var n=ve(t);return $e(n)&&(n=T),Hn(sn(t,1,$e,true),T,n)}),Ko=Me(function(t,n){return $e(t)?fn(t,n):[]}),Go=Me(function(t){return tr(f(t,$e))}),Jo=Me(function(t){var n=ve(t);return $e(n)&&(n=T),tr(f(t,$e),Fr(n))}),Yo=Me(function(t){ -var n=ve(t);return $e(n)&&(n=T),tr(f(t,$e),T,n)}),Ho=Me(ye),Qo=Me(function(t){var n=t.length,n=n>1?t[n-1]:T,n=typeof n=="function"?(t.pop(),n):T;return be(t,n)}),Xo=Me(function(t){function n(n){return tn(n,t)}t=sn(t,1);var r=t.length,e=r?t[0]:0,u=this.__wrapped__;return!(r>1||this.__actions__.length)&&u instanceof Ut&&Xr(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:je,args:[n],thisArg:T}),new zt(u,this.__chain__).thru(function(t){return r&&!t.length&&t.push(T),t})):this.thru(n)}),ti=pr(function(t,n,r){ -Wu.call(t,r)?++t[r]:t[r]=1}),ni=wr(he),ri=wr(pe),ei=pr(function(t,n,r){Wu.call(t,r)?t[r].push(n):t[r]=[n]}),ui=Me(function(t,n,e){var u=-1,o=typeof n=="function",i=ne(n),f=Ue(t)?Array(t.length):[];return Ao(t,function(t){var c=o?n:i&&null!=t?t[n]:T;f[++u]=c?r(c,t,e):wn(t,n,e)}),f}),oi=pr(function(t,n,r){t[r]=n}),ii=pr(function(t,n,r){t[r?0:1].push(n)},function(){return[[],[]]}),fi=Me(function(t,n){if(null==t)return[];var r=n.length;return r>1&&te(t,n[0],n[1])?n=[]:r>2&&te(n[0],n[1],n[2])&&(n=[n[0]]), -n=1==n.length&&yi(n[0])?n[0]:sn(n,1,Qr),Mn(t,n,[])}),ci=Me(function(t,n,r){var e=1;if(r.length)var u=$(r,Dr(ci)),e=32|e;return Cr(t,e,n,r,u)}),ai=Me(function(t,n,r){var e=3;if(r.length)var u=$(r,Dr(ai)),e=32|e;return Cr(n,e,t,r,u)}),li=Me(function(t,n){return on(t,1,n)}),si=Me(function(t,n,r){return on(t,nu(n)||0,r)});Le.Cache=Pt;var hi=Me(function(t,n){n=1==n.length&&yi(n[0])?l(n[0],O(Fr())):l(sn(n,1,Qr),O(Fr()));var e=n.length;return Me(function(u){for(var o=-1,i=to(u.length,e);++o=n}),yi=Array.isArray,bi=Uu?function(t){return t instanceof Uu}:bu,xi=Wr(Sn),ji=Wr(function(t,n){return n>=t}),wi=_r(function(t,n){if(po||ee(n)||Ue(n))sr(n,iu(n),t);else for(var r in n)Wu.call(n,r)&&Yt(t,r,n[r])}),mi=_r(function(t,n){if(po||ee(n)||Ue(n))sr(n,fu(n),t);else for(var r in n)Yt(t,r,n[r]); -}),Ai=_r(function(t,n,r,e){sr(n,fu(n),t,e)}),Oi=_r(function(t,n,r,e){sr(n,iu(n),t,e)}),ki=Me(function(t,n){return tn(t,sn(n,1))}),Ei=Me(function(t){return t.push(T,Vt),r(Ai,T,t)}),Si=Me(function(t){return t.push(T,oe),r(Li,T,t)}),Ii=Or(function(t,n,r){t[n]=r},hu(pu)),Ri=Or(function(t,n,r){Wu.call(t,n)?t[n].push(r):t[n]=[r]},Fr),Wi=Me(wn),Bi=_r(function(t,n,r){Bn(t,n,r)}),Li=_r(function(t,n,r,e){Bn(t,n,r,e)}),Mi=Me(function(t,n){return null==t?{}:(n=l(sn(n,1),fe),Cn(t,fn(gn(t,fu,Bo),n)))}),Ci=Me(function(t,n){ -return null==t?{}:Cn(t,l(sn(n,1),fe))}),zi=Mr(iu),Ui=Mr(fu),$i=br(function(t,n,r){return n=n.toLowerCase(),t+(r?au(n):n)}),Di=br(function(t,n,r){return t+(r?"-":"")+n.toLowerCase()}),Fi=br(function(t,n,r){return t+(r?" ":"")+n.toLowerCase()}),Ni=yr("toLowerCase"),Pi=br(function(t,n,r){return t+(r?"_":"")+n.toLowerCase()}),Zi=br(function(t,n,r){return t+(r?" ":"")+qi(n)}),Ti=br(function(t,n,r){return t+(r?" ":"")+n.toUpperCase()}),qi=yr("toUpperCase"),Vi=Me(function(t,n){try{return r(t,T,n)}catch(e){ -return De(e)?e:new ju(e)}}),Ki=Me(function(t,n){return u(sn(n,1),function(n){n=fe(n),t[n]=ci(t[n],t)}),t}),Gi=mr(),Ji=mr(true),Yi=Me(function(t,n){return function(r){return wn(r,t,n)}}),Hi=Me(function(t,n){return function(r){return wn(t,r,n)}}),Qi=Er(l),Xi=Er(i),tf=Er(_),nf=Rr(),rf=Rr(true),ef=kr(function(t,n){return t+n}),uf=Lr("ceil"),of=kr(function(t,n){return t/n}),ff=Lr("floor"),cf=kr(function(t,n){return t*n}),af=Lr("round"),lf=kr(function(t,n){return t-n});return Ot.after=function(t,n){if(typeof n!="function")throw new Au("Expected a function"); -return t=Xe(t),function(){return 1>--t?n.apply(this,arguments):void 0}},Ot.ary=Se,Ot.assign=wi,Ot.assignIn=mi,Ot.assignInWith=Ai,Ot.assignWith=Oi,Ot.at=ki,Ot.before=Ie,Ot.bind=ci,Ot.bindAll=Ki,Ot.bindKey=ai,Ot.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return yi(t)?t:[t]},Ot.chain=xe,Ot.chunk=function(t,n,r){if(n=(r?te(t,n,r):n===T)?1:Xu(Xe(n),0),r=t?t.length:0,!r||1>n)return[];for(var e=0,u=0,o=Array(Ku(r/n));r>e;)o[u++]=Tn(t,e,e+=n);return o},Ot.compact=function(t){for(var n=-1,r=t?t.length:0,e=0,u=[];++nr&&(r=-r>u?0:u+r),e=e===T||e>u?u:Xe(e),0>e&&(e+=u),e=r>e?0:tu(e);e>r;)t[r++]=n;return t},Ot.filter=function(t,n){return(yi(t)?f:ln)(t,Fr(n,3))},Ot.flatMap=function(t,n){return sn(Oe(t,n),1)},Ot.flatMapDeep=function(t,n){return sn(Oe(t,n),q)},Ot.flatMapDepth=function(t,n,r){return r=r===T?1:Xe(r),sn(Oe(t,n),r)},Ot.flatten=function(t){return t&&t.length?sn(t,1):[]},Ot.flattenDeep=function(t){return t&&t.length?sn(t,q):[]},Ot.flattenDepth=function(t,n){return t&&t.length?(n=n===T?1:Xe(n),sn(t,n)):[]; -},Ot.flip=function(t){return Cr(t,512)},Ot.flow=Gi,Ot.flowRight=Ji,Ot.fromPairs=function(t){for(var n=-1,r=t?t.length:0,e={};++n>>0,r?(t=eu(t))&&(typeof n=="string"||null!=n&&!Ke(n))&&(n=Yn(n),""==n&&Wt.test(t))?ur(t.match(It),0,r):oo.call(t,n,r):[]},Ot.spread=function(t,n){if(typeof t!="function")throw new Au("Expected a function");return n=n===T?0:Xu(Xe(n),0),Me(function(e){var u=e[n];return e=ur(e,0,n),u&&s(e,u),r(t,this,e)})},Ot.tail=function(t){return le(t,1)},Ot.take=function(t,n,r){return t&&t.length?(n=r||n===T?1:Xe(n), -Tn(t,0,0>n?0:n)):[]},Ot.takeRight=function(t,n,r){var e=t?t.length:0;return e?(n=r||n===T?1:Xe(n),n=e-n,Tn(t,0>n?0:n,e)):[]},Ot.takeRightWhile=function(t,n){return t&&t.length?Qn(t,Fr(n,3),false,true):[]},Ot.takeWhile=function(t,n){return t&&t.length?Qn(t,Fr(n,3)):[]},Ot.tap=function(t,n){return n(t),t},Ot.throttle=function(t,n,r){var e=true,u=true;if(typeof t!="function")throw new Au("Expected a function");return Ze(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),Be(t,n,{leading:e,maxWait:n, -trailing:u})},Ot.thru=je,Ot.toArray=He,Ot.toPairs=zi,Ot.toPairsIn=Ui,Ot.toPath=function(t){return yi(t)?l(t,fe):Je(t)?[t]:lr(Co(t))},Ot.toPlainObject=ru,Ot.transform=function(t,n,r){var e=yi(t)||Ye(t);if(n=Fr(n,4),null==r)if(e||Ze(t)){var o=t.constructor;r=e?yi(t)?new o:[]:Fe(o)?un(Ju(Object(t))):{}}else r={};return(e?u:hn)(t,function(t,e,u){return n(r,t,e,u)}),r},Ot.unary=function(t){return Se(t,1)},Ot.union=To,Ot.unionBy=qo,Ot.unionWith=Vo,Ot.uniq=function(t){return t&&t.length?Hn(t):[]},Ot.uniqBy=function(t,n){ -return t&&t.length?Hn(t,Fr(n)):[]},Ot.uniqWith=function(t,n){return t&&t.length?Hn(t,T,n):[]},Ot.unset=function(t,n){var r;if(null==t)r=true;else{r=t;var e=n,e=ne(e,r)?[e]:er(e);r=ie(r,e),e=fe(ve(e)),r=!(null!=r&&yn(r,e))||delete r[e]}return r},Ot.unzip=ye,Ot.unzipWith=be,Ot.update=function(t,n,r){return null==t?t:Zn(t,n,(typeof r=="function"?r:pu)(vn(t,n)),void 0)},Ot.updateWith=function(t,n,r,e){return e=typeof e=="function"?e:T,null!=t&&(t=Zn(t,n,(typeof r=="function"?r:pu)(vn(t,n)),e)),t},Ot.values=cu, -Ot.valuesIn=function(t){return null==t?[]:k(t,fu(t))},Ot.without=Ko,Ot.words=su,Ot.wrap=function(t,n){return n=null==n?pu:n,pi(n,t)},Ot.xor=Go,Ot.xorBy=Jo,Ot.xorWith=Yo,Ot.zip=Ho,Ot.zipObject=function(t,n){return nr(t||[],n||[],Yt)},Ot.zipObjectDeep=function(t,n){return nr(t||[],n||[],Zn)},Ot.zipWith=Qo,Ot.entries=zi,Ot.entriesIn=Ui,Ot.extend=mi,Ot.extendWith=Ai,vu(Ot,Ot),Ot.add=ef,Ot.attempt=Vi,Ot.camelCase=$i,Ot.capitalize=au,Ot.ceil=uf,Ot.clamp=function(t,n,r){return r===T&&(r=n,n=T),r!==T&&(r=nu(r), -r=r===r?r:0),n!==T&&(n=nu(n),n=n===n?n:0),nn(nu(t),n,r)},Ot.clone=function(t){return rn(t,false,true)},Ot.cloneDeep=function(t){return rn(t,true,true)},Ot.cloneDeepWith=function(t,n){return rn(t,true,true,n)},Ot.cloneWith=function(t,n){return rn(t,false,true,n)},Ot.deburr=lu,Ot.divide=of,Ot.endsWith=function(t,n,r){t=eu(t),n=Yn(n);var e=t.length;return r=r===T?e:nn(Xe(r),0,e),r-=n.length,r>=0&&t.indexOf(n,r)==r},Ot.eq=Ce,Ot.escape=function(t){return(t=eu(t))&&X.test(t)?t.replace(H,B):t},Ot.escapeRegExp=function(t){ -return(t=eu(t))&&ft.test(t)?t.replace(it,"\\$&"):t},Ot.every=function(t,n,r){var e=yi(t)?i:cn;return r&&te(t,n,r)&&(n=T),e(t,Fr(n,3))},Ot.find=ni,Ot.findIndex=he,Ot.findKey=function(t,n){return v(t,Fr(n,3),hn)},Ot.findLast=ri,Ot.findLastIndex=pe,Ot.findLastKey=function(t,n){return v(t,Fr(n,3),pn)},Ot.floor=ff,Ot.forEach=me,Ot.forEachRight=Ae,Ot.forIn=function(t,n){return null==t?t:ko(t,Fr(n,3),fu)},Ot.forInRight=function(t,n){return null==t?t:Eo(t,Fr(n,3),fu)},Ot.forOwn=function(t,n){return t&&hn(t,Fr(n,3)); -},Ot.forOwnRight=function(t,n){return t&&pn(t,Fr(n,3))},Ot.get=uu,Ot.gt=gi,Ot.gte=di,Ot.has=function(t,n){return null!=t&&Vr(t,n,yn)},Ot.hasIn=ou,Ot.head=_e,Ot.identity=pu,Ot.includes=function(t,n,r,e){return t=Ue(t)?t:cu(t),r=r&&!e?Xe(r):0,e=t.length,0>r&&(r=Xu(e+r,0)),Ge(t)?e>=r&&-1r&&(r=Xu(e+r,0)),d(t,n,r)):-1},Ot.inRange=function(t,n,r){return n=nu(n)||0,r===T?(r=n,n=0):r=nu(r)||0,t=nu(t), -t>=to(n,r)&&t=-9007199254740991&&9007199254740991>=t; -},Ot.isSet=function(t){return Te(t)&&"[object Set]"==qr(t)},Ot.isString=Ge,Ot.isSymbol=Je,Ot.isTypedArray=Ye,Ot.isUndefined=function(t){return t===T},Ot.isWeakMap=function(t){return Te(t)&&"[object WeakMap]"==qr(t)},Ot.isWeakSet=function(t){return Te(t)&&"[object WeakSet]"==Mu.call(t)},Ot.join=function(t,n){return t?Hu.call(t,n):""},Ot.kebabCase=Di,Ot.last=ve,Ot.lastIndexOf=function(t,n,r){var e=t?t.length:0;if(!e)return-1;var u=e;if(r!==T&&(u=Xe(r),u=(0>u?Xu(e+u,0):to(u,e-1))+1),n!==n)return M(t,u-1,true); -for(;u--;)if(t[u]===n)return u;return-1},Ot.lowerCase=Fi,Ot.lowerFirst=Ni,Ot.lt=xi,Ot.lte=ji,Ot.max=function(t){return t&&t.length?an(t,pu,dn):T},Ot.maxBy=function(t,n){return t&&t.length?an(t,Fr(n),dn):T},Ot.mean=function(t){return b(t,pu)},Ot.meanBy=function(t,n){return b(t,Fr(n))},Ot.min=function(t){return t&&t.length?an(t,pu,Sn):T},Ot.minBy=function(t,n){return t&&t.length?an(t,Fr(n),Sn):T},Ot.stubArray=yu,Ot.stubFalse=bu,Ot.stubObject=function(){return{}},Ot.stubString=function(){return""},Ot.stubTrue=function(){ -return true},Ot.multiply=cf,Ot.nth=function(t,n){return t&&t.length?Ln(t,Xe(n)):T},Ot.noConflict=function(){return Kt._===this&&(Kt._=Cu),this},Ot.noop=gu,Ot.now=Ee,Ot.pad=function(t,n,r){t=eu(t);var e=(n=Xe(n))?N(t):0;return!n||e>=n?t:(n=(n-e)/2,Sr(Gu(n),r)+t+Sr(Ku(n),r))},Ot.padEnd=function(t,n,r){t=eu(t);var e=(n=Xe(n))?N(t):0;return n&&n>e?t+Sr(n-e,r):t},Ot.padStart=function(t,n,r){t=eu(t);var e=(n=Xe(n))?N(t):0;return n&&n>e?Sr(n-e,r)+t:t},Ot.parseInt=function(t,n,r){return r||null==n?n=0:n&&(n=+n), -t=eu(t).replace(ct,""),no(t,n||(vt.test(t)?16:10))},Ot.random=function(t,n,r){if(r&&typeof r!="boolean"&&te(t,n,r)&&(n=r=T),r===T&&(typeof n=="boolean"?(r=n,n=T):typeof t=="boolean"&&(r=t,t=T)),t===T&&n===T?(t=0,n=1):(t=nu(t)||0,n===T?(n=t,t=0):n=nu(n)||0),t>n){var e=t;t=n,n=e}return r||t%1||n%1?(r=ro(),to(t+r*(n-t+Ft("1e-"+((r+"").length-1))),n)):Nn(t,n)},Ot.reduce=function(t,n,r){var e=yi(t)?h:x,u=3>arguments.length;return e(t,Fr(n,4),r,u,Ao)},Ot.reduceRight=function(t,n,r){var e=yi(t)?p:x,u=3>arguments.length; -return e(t,Fr(n,4),r,u,Oo)},Ot.repeat=function(t,n,r){return n=(r?te(t,n,r):n===T)?1:Xe(n),Pn(eu(t),n)},Ot.replace=function(){var t=arguments,n=eu(t[0]);return 3>t.length?n:eo.call(n,t[1],t[2])},Ot.result=function(t,n,r){n=ne(n,t)?[n]:er(n);var e=-1,u=n.length;for(u||(t=T,u=1);++e0?t[Nn(0,n-1)]:T},Ot.size=function(t){if(null==t)return 0; -if(Ue(t)){var n=t.length;return n&&Ge(t)?N(t):n}return Te(t)&&(n=qr(t),"[object Map]"==n||"[object Set]"==n)?t.size:iu(t).length},Ot.snakeCase=Pi,Ot.some=function(t,n,r){var e=yi(t)?_:qn;return r&&te(t,n,r)&&(n=T),e(t,Fr(n,3))},Ot.sortedIndex=function(t,n){return Vn(t,n)},Ot.sortedIndexBy=function(t,n,r){return Kn(t,n,Fr(r))},Ot.sortedIndexOf=function(t,n){var r=t?t.length:0;if(r){var e=Vn(t,n);if(r>e&&Ce(t[e],n))return e}return-1},Ot.sortedLastIndex=function(t,n){return Vn(t,n,true)},Ot.sortedLastIndexBy=function(t,n,r){ -return Kn(t,n,Fr(r),true)},Ot.sortedLastIndexOf=function(t,n){if(t&&t.length){var r=Vn(t,n,true)-1;if(Ce(t[r],n))return r}return-1},Ot.startCase=Zi,Ot.startsWith=function(t,n,r){return t=eu(t),r=nn(Xe(r),0,t.length),t.lastIndexOf(Yn(n),r)==r},Ot.subtract=lf,Ot.sum=function(t){return t&&t.length?w(t,pu):0},Ot.sumBy=function(t,n){return t&&t.length?w(t,Fr(n)):0},Ot.template=function(t,n,r){var e=Ot.templateSettings;r&&te(t,n,r)&&(n=T),t=eu(t),n=Ai({},n,e,Vt),r=Ai({},n.imports,e.imports,Vt);var u,o,i=iu(r),f=k(r,i),c=0; -r=n.interpolate||wt;var a="__p+='";r=mu((n.escape||wt).source+"|"+r.source+"|"+(r===rt?pt:wt).source+"|"+(n.evaluate||wt).source+"|$","g");var l="sourceURL"in n?"//# sourceURL="+n.sourceURL+"\n":"";if(t.replace(r,function(n,r,e,i,f,l){return e||(e=i),a+=t.slice(c,l).replace(mt,L),r&&(u=true,a+="'+__e("+r+")+'"),f&&(o=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+n.length,n}),a+="';",(n=n.variable)||(a="with(obj){"+a+"}"),a=(o?a.replace(K,""):a).replace(G,"$1").replace(J,"$1;"), -a="function("+(n||"obj")+"){"+(n?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",n=Vi(function(){return Function(i,l+"return "+a).apply(T,f)}),n.source=a,De(n))throw n;return n},Ot.times=function(t,n){if(t=Xe(t),1>t||t>9007199254740991)return[];var r=4294967295,e=to(t,4294967295);for(n=Fr(n),t-=4294967295,e=m(e,n);++r=o)return t;if(o=r-N(e),1>o)return e;if(r=i?ur(i,0,o).join(""):t.slice(0,o),u===T)return r+e;if(i&&(o+=r.length-o),Ke(u)){if(t.slice(o).search(u)){var f=r;for(u.global||(u=mu(u.source,eu(_t.exec(u))+"g")), -u.lastIndex=0;i=u.exec(f);)var c=i.index;r=r.slice(0,c===T?o:c)}}else t.indexOf(Yn(u),o)!=o&&(u=r.lastIndexOf(u),u>-1&&(r=r.slice(0,u)));return r+e},Ot.unescape=function(t){return(t=eu(t))&&Q.test(t)?t.replace(Y,P):t},Ot.uniqueId=function(t){var n=++Bu;return eu(t)+n},Ot.upperCase=Ti,Ot.upperFirst=qi,Ot.each=me,Ot.eachRight=Ae,Ot.first=_e,vu(Ot,function(){var t={};return hn(Ot,function(n,r){Wu.call(Ot.prototype,r)||(t[r]=n)}),t}(),{chain:false}),Ot.VERSION="4.13.1",u("bind bindKey curry curryRight partial partialRight".split(" "),function(t){ -Ot[t].placeholder=Ot}),u(["drop","take"],function(t,n){Ut.prototype[t]=function(r){var e=this.__filtered__;if(e&&!n)return new Ut(this);r=r===T?1:Xu(Xe(r),0);var u=this.clone();return e?u.__takeCount__=to(r,u.__takeCount__):u.__views__.push({size:to(r,4294967295),type:t+(0>u.__dir__?"Right":"")}),u},Ut.prototype[t+"Right"]=function(n){return this.reverse()[t](n).reverse()}}),u(["filter","map","takeWhile"],function(t,n){var r=n+1,e=1==r||3==r;Ut.prototype[t]=function(t){var n=this.clone();return n.__iteratees__.push({ -iteratee:Fr(t,3),type:r}),n.__filtered__=n.__filtered__||e,n}}),u(["head","last"],function(t,n){var r="take"+(n?"Right":"");Ut.prototype[t]=function(){return this[r](1).value()[0]}}),u(["initial","tail"],function(t,n){var r="drop"+(n?"":"Right");Ut.prototype[t]=function(){return this.__filtered__?new Ut(this):this[r](1)}}),Ut.prototype.compact=function(){return this.filter(pu)},Ut.prototype.find=function(t){return this.filter(t).head()},Ut.prototype.findLast=function(t){return this.reverse().find(t); -},Ut.prototype.invokeMap=Me(function(t,n){return typeof t=="function"?new Ut(this):this.map(function(r){return wn(r,t,n)})}),Ut.prototype.reject=function(t){return t=Fr(t,3),this.filter(function(n){return!t(n)})},Ut.prototype.slice=function(t,n){t=Xe(t);var r=this;return r.__filtered__&&(t>0||0>n)?new Ut(r):(0>t?r=r.takeRight(-t):t&&(r=r.drop(t)),n!==T&&(n=Xe(n),r=0>n?r.dropRight(-n):r.take(n-t)),r)},Ut.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},Ut.prototype.toArray=function(){ -return this.take(4294967295)},hn(Ut.prototype,function(t,n){var r=/^(?:filter|find|map|reject)|While$/.test(n),e=/^(?:head|last)$/.test(n),u=Ot[e?"take"+("last"==n?"Right":""):n],o=e||/^find/.test(n);u&&(Ot.prototype[n]=function(){function n(t){return t=u.apply(Ot,s([t],f)),e&&h?t[0]:t}var i=this.__wrapped__,f=e?[1]:arguments,c=i instanceof Ut,a=f[0],l=c||yi(i);l&&r&&typeof a=="function"&&1!=a.length&&(c=l=false);var h=this.__chain__,p=!!this.__actions__.length,a=o&&!h,c=c&&!p;return!o&&l?(i=c?i:new Ut(this), -i=t.apply(i,f),i.__actions__.push({func:je,args:[n],thisArg:T}),new zt(i,h)):a&&c?t.apply(this,f):(i=this.thru(n),a?e?i.value()[0]:i.value():i)})}),u("pop push shift sort splice unshift".split(" "),function(t){var n=Ou[t],r=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",e=/^(?:pop|shift)$/.test(t);Ot.prototype[t]=function(){var t=arguments;if(e&&!this.__chain__){var u=this.value();return n.apply(yi(u)?u:[],t)}return this[r](function(r){return n.apply(yi(r)?r:[],t)})}}),hn(Ut.prototype,function(t,n){ -var r=Ot[n];if(r){var e=r.name+"";(_o[e]||(_o[e]=[])).push({name:n,func:r})}}),_o[Ar(T,2).name]=[{name:"wrapper",func:T}],Ut.prototype.clone=function(){var t=new Ut(this.__wrapped__);return t.__actions__=lr(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=lr(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=lr(this.__views__),t},Ut.prototype.reverse=function(){if(this.__filtered__){var t=new Ut(this);t.__dir__=-1,t.__filtered__=true}else t=this.clone(), -t.__dir__*=-1;return t},Ut.prototype.value=function(){var t,n=this.__wrapped__.value(),r=this.__dir__,e=yi(n),u=0>r,o=e?n.length:0;t=o;for(var i=this.__views__,f=0,c=-1,a=i.length;++co||o==t&&a==t)return Xn(n,this.__actions__);e=[]; -t:for(;t--&&a>c;){for(u+=r,o=-1,l=n[u];++o=this.__values__.length,n=t?T:this.__values__[this.__index__++];return{done:t,value:n}},Ot.prototype.plant=function(t){ -for(var n,r=this;r instanceof kt;){var e=ae(r);e.__index__=0,e.__values__=T,n?u.__wrapped__=e:n=e;var u=e,r=r.__wrapped__}return u.__wrapped__=t,n},Ot.prototype.reverse=function(){var t=this.__wrapped__;return t instanceof Ut?(this.__actions__.length&&(t=new Ut(this)),t=t.reverse(),t.__actions__.push({func:je,args:[de],thisArg:T}),new zt(t,this.__chain__)):this.thru(de)},Ot.prototype.toJSON=Ot.prototype.valueOf=Ot.prototype.value=function(){return Xn(this.__wrapped__,this.__actions__)},Zu&&(Ot.prototype[Zu]=we), -Ot}var T,q=1/0,V=NaN,K=/\b__p\+='';/g,G=/\b(__p\+=)''\+/g,J=/(__e\(.*?\)|\b__t\))\+'';/g,Y=/&(?:amp|lt|gt|quot|#39|#96);/g,H=/[&<>"'`]/g,Q=RegExp(Y.source),X=RegExp(H.source),tt=/<%-([\s\S]+?)%>/g,nt=/<%([\s\S]+?)%>/g,rt=/<%=([\s\S]+?)%>/g,et=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,ut=/^\w*$/,ot=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g,it=/[\\^$.*+?()[\]{}|]/g,ft=RegExp(it.source),ct=/^\s+|\s+$/g,at=/^\s+/,lt=/\s+$/,st=/[a-zA-Z0-9]+/g,ht=/\\(\\)?/g,pt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_t=/\w*$/,vt=/^0x/i,gt=/^[-+]0x[0-9a-f]+$/i,dt=/^0b[01]+$/i,yt=/^\[object .+?Constructor\]$/,bt=/^0o[0-7]+$/i,xt=/^(?:0|[1-9]\d*)$/,jt=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,wt=/($^)/,mt=/['\n\r\u2028\u2029\\]/g,At="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?)*",Ot="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+At,kt="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]?|[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",Et=RegExp("['\u2019]","g"),St=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]","g"),It=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+kt+At,"g"),Rt=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d+",Ot].join("|"),"g"),Wt=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0\\ufe0e\\ufe0f]"),Bt=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Lt="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise Reflect RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ isFinite parseInt setTimeout".split(" "),Mt={}; -Mt["[object Float32Array]"]=Mt["[object Float64Array]"]=Mt["[object Int8Array]"]=Mt["[object Int16Array]"]=Mt["[object Int32Array]"]=Mt["[object Uint8Array]"]=Mt["[object Uint8ClampedArray]"]=Mt["[object Uint16Array]"]=Mt["[object Uint32Array]"]=true,Mt["[object Arguments]"]=Mt["[object Array]"]=Mt["[object ArrayBuffer]"]=Mt["[object Boolean]"]=Mt["[object DataView]"]=Mt["[object Date]"]=Mt["[object Error]"]=Mt["[object Function]"]=Mt["[object Map]"]=Mt["[object Number]"]=Mt["[object Object]"]=Mt["[object RegExp]"]=Mt["[object Set]"]=Mt["[object String]"]=Mt["[object WeakMap]"]=false; -var Ct={};Ct["[object Arguments]"]=Ct["[object Array]"]=Ct["[object ArrayBuffer]"]=Ct["[object DataView]"]=Ct["[object Boolean]"]=Ct["[object Date]"]=Ct["[object Float32Array]"]=Ct["[object Float64Array]"]=Ct["[object Int8Array]"]=Ct["[object Int16Array]"]=Ct["[object Int32Array]"]=Ct["[object Map]"]=Ct["[object Number]"]=Ct["[object Object]"]=Ct["[object RegExp]"]=Ct["[object Set]"]=Ct["[object String]"]=Ct["[object Symbol]"]=Ct["[object Uint8Array]"]=Ct["[object Uint8ClampedArray]"]=Ct["[object Uint16Array]"]=Ct["[object Uint32Array]"]=true, -Ct["[object Error]"]=Ct["[object Function]"]=Ct["[object WeakMap]"]=false;var zt={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O", -"\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss"},Ut={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},$t={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Dt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Ft=parseFloat,Nt=parseInt,Pt=typeof exports=="object"&&exports,Zt=Pt&&typeof module=="object"&&module,Tt=Zt&&Zt.exports===Pt,qt=R(typeof self=="object"&&self),Vt=R(typeof this=="object"&&this),Kt=R(typeof global=="object"&&global)||qt||Vt||Function("return this")(),Gt=Z(); -(qt||{})._=Gt,typeof define=="function"&&typeof define.amd=="object"&&define.amd? define(function(){return Gt}):Zt?((Zt.exports=Gt)._=Gt,Pt._=Gt):Kt._=Gt}).call(this); \ No newline at end of file diff --git a/test/e2e/puppeteer.js b/test/e2e/puppeteer.js index a676a30eb19d07..369523fd37a3a3 100644 --- a/test/e2e/puppeteer.js +++ b/test/e2e/puppeteer.js @@ -5,7 +5,35 @@ import path from 'path'; import pixelmatch from 'pixelmatch'; import jimp from 'jimp'; import * as fs from 'fs/promises'; -import fetch from 'node-fetch'; + +class PromiseQueue { + + constructor( func, ...args ) { + + this.func = func.bind( this, ...args ); + this.promises = []; + + } + + add( ...args ) { + + const promise = this.func( ...args ); + this.promises.push( promise ); + promise.then( () => this.promises.splice( this.promises.indexOf( promise ), 1 ) ); + + } + + async waitForAll() { + + while ( this.promises.length > 0 ) { + + await Promise.all( this.promises ); + + } + + } + +} /* CONFIG VARIABLES START */ @@ -18,55 +46,96 @@ const exceptionList = [ 'css3d_youtube', 'webgl_video_kinect', 'webgl_video_panorama_equirectangular', + 'webxr_vr_video', 'webaudio_visualizer', // audio can't be analyzed without proper audio hook - 'webgl_effects_ascii', // blink renders text differently in every platform - 'webxr_ar_lighting', // webxr 'webgl_worker_offscreencanvas', // in a worker, not robust + // Windows-Linux text rendering differences + // TODO: Fix these by setting a font in Puppeteer -- this can also fix a bunch of 0.1%-0.2% examples + 'css3d_periodictable', + 'misc_controls_pointerlock', + 'misc_uv_tests', + 'webgl_camera_logarithmicdepthbuffer', + 'webgl_effects_ascii', + 'webgl_loader_pdb', + 'webgl_multiple_elements_text', + + // Unknown // TODO: most of these can be fixed just by increasing idleTime and parseTime + 'webgl_animation_skinning_blending', + 'webgl_buffergeometry_glbufferattribute', + 'webgl_clipping_advanced', 'webgl_lensflares', - 'webgl_lines_sphere', + 'webgl_lights_spotlights', 'webgl_loader_imagebitmap', 'webgl_loader_texture_lottie', 'webgl_loader_texture_pvrtc', + 'webgl_materials_blending', + 'webgl_mirror', 'webgl_morphtargets_face', 'webgl_nodes_materials_standard', 'webgl_postprocessing_crossfade', + 'webgl_postprocessing_dof2', 'webgl_raymarching_reflect', 'webgl_renderer_pathtracer', + 'webgl_shadowmap', 'webgl_shadowmap_progressive', 'webgl_test_memory2', - 'webgl_tiled_forward' + 'webgl_tiled_forward', + + // TODO: implement determinism for setTimeout and setInterval + // could it fix some examples from above? + 'physics_rapier_instancing', + + // Awaiting for WebGPU support + 'webgpu_audio_processing', + 'webgpu_backdrop', + 'webgpu_compute', + 'webgpu_cubemap_adjustments', + 'webgpu_cubemap_mix', + 'webgpu_depth_texture', + 'webgpu_equirectangular', + 'webgpu_instance_mesh', + 'webgpu_instance_uniform', + 'webgpu_lights_custom', + 'webgpu_lights_ies_spotlight', + 'webgpu_lights_phong', + 'webgpu_lights_selective', + 'webgpu_loader_gltf', + 'webgpu_loader_gltf_compressed', + 'webgpu_materials', + 'webgpu_materials_video', + 'webgpu_particles', + 'webgpu_rtt', + 'webgpu_sandbox', + 'webgpu_shadowmap', + 'webgpu_skinning', + 'webgpu_skinning_instancing', + 'webgpu_skinning_points', + 'webgpu_sprites' ]; /* CONFIG VARIABLES END */ -const PLATFORMS = { - linux: 'linux', - mac: 'mac', - mac_arm: 'mac_am64', - win32: 'win', - win64: 'win64' -}; -const OMAHA_PROXY = 'https://omahaproxy.appspot.com/all.json'; - -const chromiumChannel = 'stable'; // stable -> beta -> dev -> canary (Mac and Windows) -> canary_asan (Windows) +const chromiumRevision = '1108766'; // Chromium 112.0.5614.0, Puppeteer 19.8.0, https://github.com/puppeteer/puppeteer/releases/tag/puppeteer-core-v19.8.0 const port = 1234; const pixelThreshold = 0.1; // threshold error in one pixel -const maxFailedPixels = 0.05; // at most 5% failed pixels +const maxDifferentPixels = 0.3; // at most 0.3% different pixels -const networkTimeout = 90; // 90 seconds, set to 0 to disable -const renderTimeout = 4.5; // 4.5 seconds, set to 0 to disable +const networkTimeout = 5; // 5 minutes, set to 0 to disable +const renderTimeout = 5; // 5 seconds, set to 0 to disable const numAttempts = 2; // perform 2 attempts before failing -const numCIJobs = 8; // GitHub Actions run the script in 8 threads +const numPages = 8; // use 8 browser pages + +const numCIJobs = 4; // GitHub Actions run the script in 4 threads const width = 400; const height = 250; @@ -89,6 +158,11 @@ process.on( 'SIGINT', () => close() ); async function main() { + /* Create output directories */ + + try { await fs.rm( 'test/e2e/output-screenshots', { recursive: true, force: true } ); } catch {} + try { await fs.mkdir( 'test/e2e/output-screenshots' ); } catch {} + /* Find files */ const isMakeScreenshot = process.argv[ 2 ] === '--make'; @@ -147,7 +221,8 @@ async function main() { headless: ! process.env.VISIBLE, args: flags, defaultViewport: viewport, - handleSIGINT: false + handleSIGINT: false, + protocolTimeout: 0 } ); // this line is intended to stop the script if the browser (in headful mode) is closed by user (while debugging) @@ -160,21 +235,26 @@ async function main() { const injection = await fs.readFile( 'test/e2e/deterministic-injection.js', 'utf8' ); const build = ( await fs.readFile( 'build/three.module.js', 'utf8' ) ).replace( /Math\.random\(\) \* 0xffffffff/g, 'Math._random() * 0xffffffff' ); - /* Prepare page */ + /* Prepare pages */ const errorMessagesCache = []; - const page = ( await browser.pages() )[ 0 ]; - await preparePage( page, injection, build, errorMessagesCache ); + const pages = await browser.pages(); + while ( pages.length < numPages && pages.length < files.length ) pages.push( await browser.newPage() ); + + for ( const page of pages ) await preparePage( page, injection, build, errorMessagesCache ); /* Loop for each file */ const failedScreenshots = []; - for ( const file of files ) await makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot, file ); + const queue = new PromiseQueue( makeAttempt, pages, failedScreenshots, cleanPage, isMakeScreenshot ); + for ( const file of files ) queue.add( file ); + await queue.waitForAll(); /* Finish */ + failedScreenshots.sort(); const list = failedScreenshots.join( ' ' ); if ( isMakeScreenshot && failedScreenshots.length ) { @@ -207,19 +287,7 @@ async function downloadLatestChromium() { const browserFetcher = new BrowserFetcher( { path: 'test/e2e/chromium' } ); - const os = PLATFORMS[ browserFetcher.platform() ]; - - const revisions = await ( await fetch( OMAHA_PROXY ) ).json(); - const omahaRevisionInfo = revisions.find( revs => revs.os === os ).versions.find( version => version.channel === chromiumChannel ); - - let revision = omahaRevisionInfo.branch_base_position; - while ( ! ( await browserFetcher.canDownload( revision ) ) ) { - - revision = String( revision - 1 ); - - } - - let revisionInfo = browserFetcher.revisionInfo( revision ); + let revisionInfo = browserFetcher.revisionInfo( chromiumRevision ); if ( revisionInfo.local === true ) { console.log( 'Latest Chromium has been already downloaded.' ); @@ -227,11 +295,11 @@ async function downloadLatestChromium() { } else { console.log( 'Downloading latest Chromium...' ); - revisionInfo = await browserFetcher.download( revision ); + revisionInfo = await browserFetcher.download( chromiumRevision ); console.log( 'Downloaded.' ); } - console.log( `Using Chromium ${ omahaRevisionInfo.current_version } (revision ${ revision }, ${ revisionInfo.url }), ${ chromiumChannel } channel on ${ os }` ); + console.log( `Using Chromium r${ chromiumRevision } (${ revisionInfo.url }), stable channel on ${ browserFetcher.platform() }` ); return revisionInfo; } @@ -264,7 +332,7 @@ async function preparePage( page, injection, build, errorMessages ) { const args = await Promise.all( msg.args().map( async arg => { try { return await arg.executionContext().evaluate( arg => arg instanceof Error ? arg.message : arg, arg ); - } catch (e) { // Execution context might have been already destroyed + } catch ( e ) { // Execution context might have been already destroyed return arg; } } ) ); @@ -276,9 +344,9 @@ async function preparePage( page, injection, build, errorMessages ) { text = file + ': ' + text.replace( /\[\.WebGL-(.+?)\] /g, '' ); - if ( errorMessages.includes( text ) ) { + if ( text === `${ file }: JSHandle@error` ) { - return; + text = `${ file }: Unknown error`; } @@ -288,6 +356,12 @@ async function preparePage( page, injection, build, errorMessages ) { } + if ( errorMessages.includes( text ) ) { + + return; + + } + errorMessages.push( text ); if ( type === 'warning' ) { @@ -336,11 +410,31 @@ async function preparePage( page, injection, build, errorMessages ) { } -async function makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot, file, attemptID = 0 ) { +async function makeAttempt( pages, failedScreenshots, cleanPage, isMakeScreenshot, file, attemptID = 0 ) { + + const page = await new Promise( ( resolve, reject ) => { + + const interval = setInterval( () => { + + for ( const page of pages ) { + + if ( page.file === undefined ) { + + page.file = file; // acquire lock + clearInterval( interval ); + resolve( page ); + break; + + } + + } + + }, 100 ); + + } ); try { - page.file = file; page.pageSize = 0; page.error = undefined; @@ -350,7 +444,7 @@ async function makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot await page.goto( `http://localhost:${ port }/examples/${ file }.html`, { waitUntil: 'networkidle0', - timeout: networkTimeout * 1000 + timeout: networkTimeout * 60000 } ); } catch ( e ) { @@ -366,7 +460,7 @@ async function makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot await page.evaluate( cleanPage ); await page.waitForNetworkIdle( { - timeout: networkTimeout * 1000, + timeout: networkTimeout * 60000, idleTime: idleTime * 1000 } ); @@ -414,7 +508,7 @@ async function makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot console.yellow( `Render timeout exceeded in file ${ file }` ); - } */ + } */ // TODO: fix this } @@ -438,10 +532,11 @@ async function makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot try { - expected = await jimp.read( `examples/screenshots/${ file }.jpg` ); + expected = ( await jimp.read( `examples/screenshots/${ file }.jpg` ) ).quality( jpgQuality ); } catch { + await screenshot.writeAsync( `test/e2e/output-screenshots/${ file }-actual.jpg` ); throw new Error( `Screenshot does not exist: ${ file }` ); } @@ -449,36 +544,37 @@ async function makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot const actual = screenshot.bitmap; const diff = screenshot.clone(); - let numFailedPixels; + let numDifferentPixels; try { - numFailedPixels = pixelmatch( expected.bitmap.data, actual.data, diff.bitmap.data, actual.width, actual.height, { + numDifferentPixels = pixelmatch( expected.bitmap.data, actual.data, diff.bitmap.data, actual.width, actual.height, { threshold: pixelThreshold, - alpha: 0.2, - diffMask: process.env.FORCE_COLOR === '0', - diffColor: process.env.FORCE_COLOR === '0' ? [ 255, 255, 255 ] : [ 255, 0, 0 ] + alpha: 0.2 } ); } catch { + await screenshot.writeAsync( `test/e2e/output-screenshots/${ file }-actual.jpg` ); + await expected.writeAsync( `test/e2e/output-screenshots/${ file }-expected.jpg` ); throw new Error( `Image sizes does not match in file: ${ file }` ); } - numFailedPixels /= actual.width * actual.height; - /* Print results */ - const percFailedPixels = 100 * numFailedPixels; + const differentPixels = numDifferentPixels / ( actual.width * actual.height ) * 100; - if ( numFailedPixels < maxFailedPixels ) { + if ( differentPixels < maxDifferentPixels ) { - console.green( `Diff ${ percFailedPixels.toFixed( 1 ) }% in file: ${ file }` ); + console.green( `Diff ${ differentPixels.toFixed( 1 ) }% in file: ${ file }` ); } else { - throw new Error( `Diff wrong in ${ percFailedPixels.toFixed( 1 ) }% of pixels in file: ${ file }` ); + await screenshot.writeAsync( `test/e2e/output-screenshots/${ file }-actual.jpg` ); + await expected.writeAsync( `test/e2e/output-screenshots/${ file }-expected.jpg` ); + await diff.writeAsync( `test/e2e/output-screenshots/${ file }-diff.jpg` ); + throw new Error( `Diff wrong in ${ differentPixels.toFixed( 1 ) }% of pixels in file: ${ file }` ); } @@ -494,12 +590,14 @@ async function makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot } else { console.yellow( `${ e }, another attempt...` ); - await makeAttempt( page, failedScreenshots, cleanPage, isMakeScreenshot, file, attemptID + 1 ); + this.add( file, attemptID + 1 ); } } + page.file = undefined; // release lock + } function close( exitCode = 1 ) { diff --git a/test/rollup.treeshake.config.js b/test/rollup.treeshake.config.js index 6adcb33eae0ed2..c77535b36e5b4a 100644 --- a/test/rollup.treeshake.config.js +++ b/test/rollup.treeshake.config.js @@ -3,7 +3,7 @@ import resolve from '@rollup/plugin-node-resolve'; import filesize from 'rollup-plugin-filesize'; import terser from '@rollup/plugin-terser'; import { visualizer } from 'rollup-plugin-visualizer'; -import { glconstants, glsl } from '../utils/build/rollup.config.js'; +import { glsl } from '../utils/build/rollup.config.js'; import chalk from 'chalk'; const statsFile = path.resolve( 'test/treeshake/stats.html' ); @@ -55,7 +55,6 @@ export default [ { input: 'test/treeshake/index-src.js', plugins: [ - glconstants(), glsl(), terser(), visualizer( { diff --git a/test/treeshake/utils/format-diff.js b/test/treeshake/utils/format-diff.js new file mode 100644 index 00000000000000..229265366498e1 --- /dev/null +++ b/test/treeshake/utils/format-diff.js @@ -0,0 +1,10 @@ +// used in report-size.yml +import { formatBytes } from './formatBytes.js'; + +const filesize = Number( process.argv[ 2 ] ); +const filesizeBase = Number( process.argv[ 3 ] ); + +const diff = filesize - filesizeBase; +const formatted = `${diff >= 0 ? '+' : '-'}${formatBytes( Math.abs( diff ), 2 )}`; + +console.log( formatted ); diff --git a/test/treeshake/utils/format-size.js b/test/treeshake/utils/format-size.js new file mode 100644 index 00000000000000..5b9054ee4ce1ea --- /dev/null +++ b/test/treeshake/utils/format-size.js @@ -0,0 +1,7 @@ +// used in report-size.yml +import { formatBytes } from './formatBytes.js'; + +const n = Number( process.argv[ 2 ] ); +const formatted = formatBytes( n ); + +console.log( formatted ); diff --git a/test/treeshake/utils/formatBytes.js b/test/treeshake/utils/formatBytes.js new file mode 100644 index 00000000000000..05bd999efa2ca5 --- /dev/null +++ b/test/treeshake/utils/formatBytes.js @@ -0,0 +1,13 @@ +export function formatBytes( bytes, decimals = 1 ) { + + if ( bytes === 0 ) return '0 B'; + + const k = 1000; + const dm = decimals < 0 ? 0 : decimals; + const sizes = [ 'B', 'kB', 'MB', 'GB' ]; + + const i = Math.floor( Math.log( bytes ) / Math.log( k ) ); + + return parseFloat( ( bytes / Math.pow( k, i ) ).toFixed( dm ) ) + ' ' + sizes[ i ]; + +} diff --git a/test/unit/README.md b/test/unit/README.md index d9ef28bdf500bf..b846f42305b96b 100644 --- a/test/unit/README.md +++ b/test/unit/README.md @@ -1,10 +1,29 @@ ## Setup -- Execute `npm i --prefix test` from root folder +- Execute `npm install` from the root folder ## Run You can run the unit tests in two environments: -- Node.js: Execute `npm run test-unit` from root folder -- Browser: Execute `npm start` (or run any other local web sever) from root folder and access `http://localhost:8080/test/unit/UnitTests.html` on web browser. (See [How to run things locally](https://threejs.org/docs/#manual/introduction/How-to-run-things-locally)) +- Node.js: Execute `npm run test-unit` from the root folder +- Browser: Execute `npx servez -p 8080 --ssl` (or run any other local web sever) from the root folder and access `https://localhost:8080/test/unit/UnitTests.html` in a web browser. + +See [Installation](https://threejs.org/docs/#manual/introduction/Installation) for more information. + +## Notes + +A small number of tests can only be run in a browser environment. + +For browser tests, futher changes to the library will not be reflected until the page is refreshed. + +## Troubleshooting + +When adding or updating tests, the most common cause of test failure is forgetting to change `QUnit.todo` to `QUnit.test` when the test is ready. + +An error that indicates "no tests were found" means that an import statement could not be resolved. This is usually caused by a typo in the import path. + +## Debugging + +To debug a test, add `debugger;` to the test code. Then, run the test in a browser and open the developer tools. The test will stop at the `debugger` statement and you can inspect the code. + diff --git a/test/unit/UnitTests.html b/test/unit/UnitTests.html index ad683889216a0c..4ca77b55b41ec7 100644 --- a/test/unit/UnitTests.html +++ b/test/unit/UnitTests.html @@ -3,14 +3,14 @@ ThreeJS Unit Tests - Using Files in /src - +
    - + + diff --git a/test/unit/src/animation/AnimationAction.tests.js b/test/unit/src/animation/AnimationAction.tests.js index 317fb3fd74645e..b6165131af8e53 100644 --- a/test/unit/src/animation/AnimationAction.tests.js +++ b/test/unit/src/animation/AnimationAction.tests.js @@ -1,6 +1,7 @@ /* global QUnit */ import { AnimationAction } from '../../../../src/animation/AnimationAction.js'; + import { AnimationMixer } from '../../../../src/animation/AnimationMixer.js'; import { AnimationClip } from '../../../../src/animation/AnimationClip.js'; import { NumberKeyframeTrack } from '../../../../src/animation/tracks/NumberKeyframeTrack.js'; @@ -10,12 +11,12 @@ import { LoopOnce, LoopRepeat, LoopPingPong } from '../../../../src/constants.js function createAnimation() { - var root = new Object3D(); - var mixer = new AnimationMixer( root ); - var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] ); - var clip = new AnimationClip( 'clip1', 1000, [ track ] ); + const root = new Object3D(); + const mixer = new AnimationMixer( root ); + const track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] ); + const clip = new AnimationClip( 'clip1', 1000, [ track ] ); - var animationAction = mixer.clipAction( clip ); + const animationAction = mixer.clipAction( clip ); return { root: root, mixer: mixer, @@ -28,15 +29,15 @@ function createAnimation() { function createTwoAnimations() { - var root = new Object3D(); - var mixer = new AnimationMixer( root ); - var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] ); - var clip = new AnimationClip( 'clip1', 1000, [ track ] ); - var animationAction = mixer.clipAction( clip ); + const root = new Object3D(); + const mixer = new AnimationMixer( root ); + const track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 1000 ], [ 0, 360 ] ); + const clip = new AnimationClip( 'clip1', 1000, [ track ] ); + const animationAction = mixer.clipAction( clip ); - var track2 = new NumberKeyframeTrack( '.rotation[y]', [ 0, 1000 ], [ 0, 360 ] ); - var clip2 = new AnimationClip( 'clip2', 1000, [ track ] ); - var animationAction2 = mixer.clipAction( clip2 ); + const track2 = new NumberKeyframeTrack( '.rotation[y]', [ 0, 1000 ], [ 0, 360 ] ); + const clip2 = new AnimationClip( 'clip2', 1000, [ track ] ); + const animationAction2 = mixer.clipAction( clip2 ); return { root: root, @@ -59,22 +60,89 @@ export default QUnit.module( 'Animation', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var mixer = new AnimationMixer(); - var clip = new AnimationClip( 'nonname', - 1, [] ); + const mixer = new AnimationMixer(); + const clip = new AnimationClip( 'nonname', - 1, [] ); - var animationAction = new AnimationAction( mixer, clip ); + const animationAction = new AnimationAction( mixer, clip ); assert.ok( animationAction, 'animationAction instanciated' ); } ); + // PROPERTIES + QUnit.todo( 'blendMode', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'loop', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'time', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'timeScale', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'weight', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'repetitions', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'paused', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'enabled', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'clampWhenFinished', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'zeroSlopeAtStart', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'zeroSlopeAtEnd', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + // PUBLIC STUFF QUnit.test( 'play', ( assert ) => { - var { mixer, animationAction } = createAnimation(); - var animationAction2 = animationAction.play(); + const { mixer, animationAction } = createAnimation(); + const animationAction2 = animationAction.play(); assert.equal( animationAction, animationAction2, 'AnimationAction.play can be chained.' ); - var UserException = function () { + const UserException = function () { this.message = 'AnimationMixer must activate AnimationAction on play.'; @@ -100,11 +168,11 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'stop', ( assert ) => { - var { mixer, animationAction } = createAnimation(); - var animationAction2 = animationAction.stop(); + const { mixer, animationAction } = createAnimation(); + const animationAction2 = animationAction.stop(); assert.equal( animationAction, animationAction2, 'AnimationAction.stop can be chained.' ); - var UserException = function () { + const UserException = function () { this.message = 'AnimationMixer must deactivate AnimationAction on stop.'; @@ -130,8 +198,8 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'reset', ( assert ) => { - var { animationAction } = createAnimation(); - var animationAction2 = animationAction.stop(); + const { animationAction } = createAnimation(); + const animationAction2 = animationAction.stop(); assert.equal( animationAction, animationAction2, 'AnimationAction.reset can be chained.' ); assert.equal( animationAction2.paused, false, 'AnimationAction.reset() sets paused false' ); assert.equal( animationAction2.enabled, true, 'AnimationAction.reset() sets enabled true' ); @@ -143,7 +211,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'isRunning', ( assert ) => { - var { animationAction } = createAnimation(); + const { animationAction } = createAnimation(); assert.notOk( animationAction.isRunning(), 'When an animation is just made, it is not running.' ); animationAction.play(); assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); @@ -162,7 +230,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'isScheduled', ( assert ) => { - var { mixer, animationAction } = createAnimation(); + const { mixer, animationAction } = createAnimation(); assert.notOk( animationAction.isScheduled(), 'When an animation is just made, it is not scheduled.' ); animationAction.play(); assert.ok( animationAction.isScheduled(), 'When an animation is started, it is scheduled.' ); @@ -176,7 +244,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'startAt', ( assert ) => { - var { mixer, animationAction } = createAnimation(); + const { mixer, animationAction } = createAnimation(); animationAction.startAt( 2 ); animationAction.play(); assert.notOk( animationAction.isRunning(), 'When an animation is started at a specific time, it is not running.' ); @@ -196,7 +264,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'setLoop LoopOnce', ( assert ) => { - var { mixer, animationAction } = createAnimation(); + const { mixer, animationAction } = createAnimation(); animationAction.setLoop( LoopOnce ); animationAction.play(); assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); @@ -211,7 +279,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'setLoop LoopRepeat', ( assert ) => { - var { root, mixer, animationAction } = createAnimation(); + const { root, mixer, animationAction } = createAnimation(); animationAction.setLoop( LoopRepeat, 3 ); animationAction.play(); assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); @@ -232,7 +300,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'setLoop LoopPingPong', ( assert ) => { - var { root, mixer, animationAction } = createAnimation(); + const { root, mixer, animationAction } = createAnimation(); animationAction.setLoop( LoopPingPong, 3 ); animationAction.play(); assert.ok( animationAction.isRunning(), 'When an animation is started, it is running.' ); @@ -253,20 +321,26 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'setEffectiveWeight', ( assert ) => { - var { animationAction } = createAnimation(); + const { animationAction } = createAnimation(); assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.setEffectiveWeight( 0.3 ); assert.equal( animationAction.getEffectiveWeight(), 0.3, 'When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3.' ); + } ); - var { animationAction } = createAnimation(); + QUnit.test( 'setEffectiveWeight - disabled', ( assert ) => { + + const { animationAction } = createAnimation(); assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.enabled = false; animationAction.setEffectiveWeight( 0.3 ); assert.equal( animationAction.getEffectiveWeight(), 0, 'When EffectiveWeight is set to 0.3 when disabled , EffectiveWeight is 0.' ); + } ); + + QUnit.test( 'setEffectiveWeight - over duration', ( assert ) => { - var { root, mixer, animationAction } = createAnimation(); + const { root, mixer, animationAction } = createAnimation(); animationAction.setEffectiveWeight( 0.5 ); animationAction.play(); mixer.update( 500 ); @@ -278,13 +352,13 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'getEffectiveWeight', ( assert ) => { - var { animationAction } = createAnimation(); + let { animationAction } = createAnimation(); assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.setEffectiveWeight( 0.3 ); assert.equal( animationAction.getEffectiveWeight(), 0.3, 'When EffectiveWeight is set to 0.3 , EffectiveWeight is 0.3.' ); - var { animationAction } = createAnimation(); + ( { animationAction } = createAnimation() ); assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation is created, EffectiveWeight is 1.' ); animationAction.enabled = false; animationAction.setEffectiveWeight( 0.3 ); @@ -294,7 +368,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'fadeIn', ( assert ) => { - var { mixer, animationAction } = createAnimation(); + const { mixer, animationAction } = createAnimation(); animationAction.fadeIn( 1000 ); animationAction.play(); assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeIn is started, EffectiveWeight is 1.' ); @@ -311,7 +385,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'fadeOut', ( assert ) => { - var { mixer, animationAction } = createAnimation(); + const { mixer, animationAction } = createAnimation(); animationAction.fadeOut( 1000 ); animationAction.play(); assert.equal( animationAction.getEffectiveWeight(), 1, 'When an animation fadeOut is started, EffectiveWeight is 1.' ); @@ -328,7 +402,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'crossFadeFrom', ( assert ) => { - var { mixer, animationAction, animationAction2 } = createTwoAnimations(); + const { mixer, animationAction, animationAction2 } = createTwoAnimations(); animationAction.crossFadeFrom( animationAction2, 1000, false ); animationAction.play(); animationAction2.play(); @@ -351,7 +425,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'crossFadeTo', ( assert ) => { - var { mixer, animationAction, animationAction2 } = createTwoAnimations(); + const { mixer, animationAction, animationAction2 } = createTwoAnimations(); animationAction2.crossFadeTo( animationAction, 1000, false ); animationAction.play(); animationAction2.play(); @@ -422,36 +496,37 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'getMixer', ( assert ) => { - var { mixer, animationAction } = createAnimation(); - var mixer2 = animationAction.getMixer(); + const { mixer, animationAction } = createAnimation(); + const mixer2 = animationAction.getMixer(); assert.equal( mixer, mixer2, 'mixer should be returned by getMixer.' ); } ); QUnit.test( 'getClip', ( assert ) => { - var { clip, animationAction } = createAnimation(); - var clip2 = animationAction.getClip(); + const { clip, animationAction } = createAnimation(); + const clip2 = animationAction.getClip(); assert.equal( clip, clip2, 'clip should be returned by getClip.' ); } ); QUnit.test( 'getRoot', ( assert ) => { - var { root, animationAction } = createAnimation(); - var root2 = animationAction.getRoot(); + const { root, animationAction } = createAnimation(); + const root2 = animationAction.getRoot(); assert.equal( root, root2, 'root should be returned by getRoot.' ); } ); + // OTHERS QUnit.test( 'StartAt when already executed once', ( assert ) => { - var root = new Object3D(); - var mixer = new AnimationMixer( root ); - var track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 750 ], [ 0, 270 ] ); - var clip = new AnimationClip( 'clip1', 750, [ track ] ); + const root = new Object3D(); + const mixer = new AnimationMixer( root ); + const track = new NumberKeyframeTrack( '.rotation[x]', [ 0, 750 ], [ 0, 270 ] ); + const clip = new AnimationClip( 'clip1', 750, [ track ] ); - var animationAction = mixer.clipAction( clip ); + const animationAction = mixer.clipAction( clip ); animationAction.setLoop( LoopOnce ); animationAction.clampWhenFinished = true; animationAction.play(); diff --git a/test/unit/src/animation/AnimationClip.tests.js b/test/unit/src/animation/AnimationClip.tests.js index 9dda2b43324da8..d93b2d09aa9854 100644 --- a/test/unit/src/animation/AnimationClip.tests.js +++ b/test/unit/src/animation/AnimationClip.tests.js @@ -1,19 +1,55 @@ /* global QUnit */ -// import { AnimationClip } from '../../../../src/animation/AnimationClip.js'; +import { AnimationClip } from '../../../../src/animation/AnimationClip.js'; export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationClip', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const clip = new AnimationClip( 'clip1', 1000, [ {} ] ); + assert.ok( clip, 'AnimationClip can be instanciated' ); + + } ); + + // PROPERTIES + QUnit.test( 'name', ( assert ) => { + + const clip = new AnimationClip( 'clip1', 1000, [ {} ] ); + assert.strictEqual( + clip.name === 'clip1', true, + 'AnimationClip can be named' + ); + + } ); + + QUnit.todo( 'tracks', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'duration', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'blendMode', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // STATIC STUFF + QUnit.todo( 'uuid', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // STATIC QUnit.todo( 'parse', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -22,6 +58,7 @@ export default QUnit.module( 'Animation', () => { QUnit.todo( 'toJSON', ( assert ) => { + // static toJSON assert.ok( false, 'everything\'s gonna be alright' ); } ); @@ -50,7 +87,7 @@ export default QUnit.module( 'Animation', () => { } ); - // PUBLIC STUFF + // PUBLIC QUnit.todo( 'resetDuration', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -63,14 +100,27 @@ export default QUnit.module( 'Animation', () => { } ); + QUnit.todo( 'validate', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.todo( 'optimize', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - QUnit.todo( 'validate', ( assert ) => { + QUnit.todo( 'clone', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'toJSON', ( assert ) => { + // member method toJSON assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/animation/AnimationMixer.tests.js b/test/unit/src/animation/AnimationMixer.tests.js index 5f22fb6d6f0ab9..09bb04d5de1d68 100644 --- a/test/unit/src/animation/AnimationMixer.tests.js +++ b/test/unit/src/animation/AnimationMixer.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ import { AnimationMixer } from '../../../../src/animation/AnimationMixer.js'; + +import { EventDispatcher } from '../../../../src/core/EventDispatcher.js'; import { AnimationClip } from '../../../../src/animation/AnimationClip.js'; import { VectorKeyframeTrack } from '../../../../src/animation/tracks/VectorKeyframeTrack.js'; import { Object3D } from '../../../../src/core/Object3D.js'; @@ -25,20 +27,38 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationMixer', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new AnimationMixer(); + assert.strictEqual( + object instanceof EventDispatcher, true, + 'AnimationMixer extends from EventDispatcher' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new AnimationMixer(); + assert.ok( object, 'Can instantiate a AnimationMixer.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'time', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + QUnit.todo( 'timeScale', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC QUnit.todo( 'clipAction', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -89,6 +109,12 @@ export default QUnit.module( 'Animation', () => { } ); + QUnit.todo( 'setTime', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'getRoot', ( assert ) => { const obj = new Object3D(); diff --git a/test/unit/src/animation/AnimationObjectGroup.tests.js b/test/unit/src/animation/AnimationObjectGroup.tests.js index bdb00c318e8f69..39b36d6ab99372 100644 --- a/test/unit/src/animation/AnimationObjectGroup.tests.js +++ b/test/unit/src/animation/AnimationObjectGroup.tests.js @@ -1,6 +1,7 @@ /* global QUnit */ import { AnimationObjectGroup } from '../../../../src/animation/AnimationObjectGroup.js'; + import { Object3D } from '../../../../src/core/Object3D.js'; import { PropertyBinding } from '../../../../src/animation/PropertyBinding.js'; @@ -8,7 +9,7 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationObjectGroup', () => { - var ObjectA = new Object3D(), + const ObjectA = new Object3D(), ObjectB = new Object3D(), ObjectC = new Object3D(), @@ -21,19 +22,40 @@ export default QUnit.module( 'Animation', () => { ParsedPathC = PropertyBinding.parseTrackName( PathC ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const groupA = new AnimationObjectGroup(); + assert.ok( + groupA instanceof AnimationObjectGroup, + 'AnimationObjectGroup can be instanciated' + ); + + } ); + + // PROPERTIES + QUnit.todo( 'uuid', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isAnimationObjectGroup', ( assert ) => { + QUnit.todo( 'stats', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + // PUBLIC + QUnit.test( 'isAnimationObjectGroup', ( assert ) => { + + const object = new AnimationObjectGroup(); + assert.ok( + object.isAnimationObjectGroup, + 'AnimationObjectGroup.isAnimationObjectGroup should be true' + ); + + } ); + QUnit.todo( 'add', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -81,16 +103,16 @@ export default QUnit.module( 'Animation', () => { // initial state - var groupA = new AnimationObjectGroup(); + const groupA = new AnimationObjectGroup(); assert.ok( groupA instanceof AnimationObjectGroup, 'constructor (w/o args)' ); - var bindingsAA = groupA.subscribe_( PathA, ParsedPathA ); + const bindingsAA = groupA.subscribe_( PathA, ParsedPathA ); expect( 0, groupA, bindingsAA, PathA, 0, [] ); - var groupB = new AnimationObjectGroup( ObjectA, ObjectB ); + const groupB = new AnimationObjectGroup( ObjectA, ObjectB ); assert.ok( groupB instanceof AnimationObjectGroup, 'constructor (with args)' ); - var bindingsBB = groupB.subscribe_( PathB, ParsedPathB ); + const bindingsBB = groupB.subscribe_( PathB, ParsedPathB ); expect( 1, groupB, bindingsBB, PathB, 0, [ ObjectA, ObjectB ] ); // add @@ -113,18 +135,18 @@ export default QUnit.module( 'Animation', () => { groupA.add( ObjectC ); expect( 6, groupA, bindingsAA, PathA, 1, [ ObjectB, ObjectC ] ); - var bindingsAC = groupA.subscribe_( PathC, ParsedPathC ); + const bindingsAC = groupA.subscribe_( PathC, ParsedPathC ); expect( 7, groupA, bindingsAC, PathC, 1, [ ObjectB, ObjectC ] ); // re-add after subscribe - var bindingsBC = groupB.subscribe_( PathC, ParsedPathC ); + const bindingsBC = groupB.subscribe_( PathC, ParsedPathC ); groupB.add( ObjectA, ObjectB ); expect( 8, groupB, bindingsBB, PathB, 1, [ ObjectA, ObjectB ] ); // unsubscribe - var copyOfBindingsBC = bindingsBC.slice(); + const copyOfBindingsBC = bindingsBC.slice(); groupB.unsubscribe_( PathC ); groupB.add( ObjectC ); assert.deepEqual( bindingsBC, copyOfBindingsBC, 'no more update after unsubscribe' ); diff --git a/test/unit/src/animation/AnimationUtils.tests.js b/test/unit/src/animation/AnimationUtils.tests.js index 13499ad26f88f0..f737ce677772ea 100644 --- a/test/unit/src/animation/AnimationUtils.tests.js +++ b/test/unit/src/animation/AnimationUtils.tests.js @@ -6,7 +6,7 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'AnimationUtils', () => { - // PUBLIC STUFF + // PUBLIC QUnit.todo( 'arraySlice', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -43,6 +43,18 @@ export default QUnit.module( 'Animation', () => { } ); + QUnit.todo( 'subclip', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'makeClipAdditive', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + } ); } ); diff --git a/test/unit/src/animation/KeyframeTrack.tests.js b/test/unit/src/animation/KeyframeTrack.tests.js index ac07fe80a8256b..55d246a33b1efc 100644 --- a/test/unit/src/animation/KeyframeTrack.tests.js +++ b/test/unit/src/animation/KeyframeTrack.tests.js @@ -1,27 +1,65 @@ /* global QUnit */ import { NumberKeyframeTrack } from '../../../../src/animation/tracks/NumberKeyframeTrack.js'; + +import { KeyframeTrack } from '../../../../src/animation/KeyframeTrack.js'; import { CONSOLE_LEVEL } from '../../utils/console-wrapper.js'; export default QUnit.module( 'Animation', () => { QUnit.module( 'KeyframeTrack', () => { + const parameters = { + name: '.material.opacity', + times: [ 0, 1 ], + values: [ 0, 0.5 ], + interpolation: NumberKeyframeTrack.DefaultInterpolation + }; + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new NumberKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.strictEqual( + object instanceof KeyframeTrack, true, + 'NumberKeyframeTrack extends from KeyframeTrack' + ); + + } ); + // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + // name, times, values + const object = new NumberKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.ok( object, 'Can instantiate a NumberKeyframeTrack.' ); + + // name, times, values, interpolation + const object_all = new NumberKeyframeTrack( parameters.name, parameters.times, parameters.values, parameters.interpolation ); + assert.ok( object_all, 'Can instantiate a NumberKeyframeTrack with name, times, values, interpolation.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'name', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // STATIC STUFF - QUnit.todo( 'toJSON', ( assert ) => { + QUnit.todo( 'times', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'values', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + // PROPERTIES - PROTOTYPE QUnit.todo( 'TimeBufferType', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -40,6 +78,15 @@ export default QUnit.module( 'Animation', () => { } ); + // STATIC + QUnit.todo( 'toJSON', ( assert ) => { + + // static method toJSON + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC QUnit.todo( 'InterpolantFactoryMethodDiscrete', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -96,8 +143,8 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'validate', ( assert ) => { - var validTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, 0.5 ] ); - var invalidTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, NaN ] ); + const validTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, 0.5 ] ); + const invalidTrack = new NumberKeyframeTrack( '.material.opacity', [ 0, 1 ], [ 0, NaN ] ); assert.ok( validTrack.validate() ); @@ -109,7 +156,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'optimize', ( assert ) => { - var track = new NumberKeyframeTrack( '.material.opacity', [ 0, 1, 2, 3, 4 ], [ 0, 0, 0, 0, 1 ] ); + const track = new NumberKeyframeTrack( '.material.opacity', [ 0, 1, 2, 3, 4 ], [ 0, 0, 0, 0, 1 ] ); assert.equal( track.values.length, 5 ); @@ -120,6 +167,12 @@ export default QUnit.module( 'Animation', () => { } ); + QUnit.todo( 'clone', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + } ); } ); diff --git a/test/unit/src/animation/PropertyBinding.tests.js b/test/unit/src/animation/PropertyBinding.tests.js index fde1b51f9db28a..d7b45d77700166 100644 --- a/test/unit/src/animation/PropertyBinding.tests.js +++ b/test/unit/src/animation/PropertyBinding.tests.js @@ -1,6 +1,7 @@ /* global QUnit */ import { PropertyBinding } from '../../../../src/animation/PropertyBinding.js'; + import { BoxGeometry } from '../../../../src/geometries/BoxGeometry.js'; import { Mesh } from '../../../../src/objects/Mesh.js'; import { MeshBasicMaterial } from '../../../../src/materials/MeshBasicMaterial.js'; @@ -10,13 +11,31 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'PropertyBinding', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { - - assert.ok( false, 'everything\'s gonna be alright' ); + QUnit.test( 'Instancing', ( assert ) => { + + const geometry = new BoxGeometry(); + const material = new MeshBasicMaterial(); + const mesh = new Mesh( geometry, material ); + const path = '.material.opacity'; + const parsedPath = { + nodeName: '', + objectName: 'material', + objectIndex: undefined, + propertyName: 'opacity', + propertyIndex: undefined + }; + + // mesh, path + const object = new PropertyBinding( mesh, path ); + assert.ok( object, 'Can instantiate a PropertyBinding.' ); + + // mesh, path, parsedPath + const object_all = new PropertyBinding( mesh, path, parsedPath ); + assert.ok( object_all, 'Can instantiate a PropertyBinding with mesh, path, and parsedPath.' ); } ); - // STATIC STUFF + // STATIC QUnit.todo( 'Composite', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -65,7 +84,7 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'parseTrackName', ( assert ) => { - var paths = [ + const paths = [ [ '.property', @@ -321,22 +340,22 @@ export default QUnit.module( 'Animation', () => { QUnit.test( 'setValue', ( assert ) => { - var paths = [ + const paths = [ '.material.opacity', '.material[opacity]' ]; paths.forEach( function ( path ) { - var originalValue = 0; - var expectedValue = 1; + const originalValue = 0; + const expectedValue = 1; - var geometry = new BoxGeometry(); - var material = new MeshBasicMaterial(); + const geometry = new BoxGeometry(); + const material = new MeshBasicMaterial(); material.opacity = originalValue; - var mesh = new Mesh( geometry, material ); + const mesh = new Mesh( geometry, material ); - var binding = new PropertyBinding( mesh, path, null ); + const binding = new PropertyBinding( mesh, path, null ); binding.bind(); assert.equal( diff --git a/test/unit/src/animation/PropertyMixer.tests.js b/test/unit/src/animation/PropertyMixer.tests.js index 42ff6dcbd9dfc8..2f56aaead665b5 100644 --- a/test/unit/src/animation/PropertyMixer.tests.js +++ b/test/unit/src/animation/PropertyMixer.tests.js @@ -13,13 +13,62 @@ export default QUnit.module( 'Animation', () => { } ); - // PUBLIC STUFF + // PROPERTIES + QUnit.todo( 'binding', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'valueSize', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'buffer', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'cumulativeWeight', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'cumulativeWeightAdditive', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'useCount', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'referenceCount', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC QUnit.todo( 'accumulate', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + QUnit.todo( 'accumulateAdditive', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.todo( 'apply', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js b/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js index 7cb73ecbe29fc7..a206386f7f5114 100644 --- a/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/BooleanKeyframeTrack.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ -// import { BooleanKeyframeTrack } from '../../../../../src/animation/tracks/BooleanKeyframeTrack.js'; +import { BooleanKeyframeTrack } from '../../../../../src/animation/tracks/BooleanKeyframeTrack.js'; + +import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js'; export default QUnit.module( 'Animation', () => { @@ -8,9 +10,34 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'BooleanKeyframeTrack', () => { - QUnit.todo( 'write me !', ( assert ) => { + const parameters = { + name: '.visible', + times: [ 0, 1 ], + values: [ true, false ], + interpolation: BooleanKeyframeTrack.DefaultInterpolation + }; + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new BooleanKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.strictEqual( + object instanceof KeyframeTrack, true, + 'BooleanKeyframeTrack extends from KeyframeTrack' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + // name, times, values + const object = new BooleanKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.ok( object, 'Can instantiate a BooleanKeyframeTrack.' ); - assert.ok( false, 'everything\'s gonna be alright' ); + // name, times, values, interpolation + const object_all = new BooleanKeyframeTrack( parameters.name, parameters.times, parameters.values, parameters.interpolation ); + assert.ok( object_all, 'Can instantiate a BooleanKeyframeTrack with name, times, values, interpolation.' ); } ); diff --git a/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js b/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js index daafe301d3be00..fc26cf683a2665 100644 --- a/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/ColorKeyframeTrack.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ -// import { ColorKeyframeTrack } from '../../../../../src/animation/tracks/ColorKeyframeTrack.js'; +import { ColorKeyframeTrack } from '../../../../../src/animation/tracks/ColorKeyframeTrack.js'; + +import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js'; export default QUnit.module( 'Animation', () => { @@ -8,9 +10,34 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'ColorKeyframeTrack', () => { - QUnit.todo( 'write me !', ( assert ) => { + const parameters = { + name: '.material.diffuse', + times: [ 0, 1 ], + values: [ 0, 0.5, 1.0 ], + interpolation: ColorKeyframeTrack.DefaultInterpolation + }; + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new ColorKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.strictEqual( + object instanceof KeyframeTrack, true, + 'ColorKeyframeTrack extends from KeyframeTrack' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + // name, times, values + const object = new ColorKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.ok( object, 'Can instantiate a ColorKeyframeTrack.' ); - assert.ok( false, 'everything\'s gonna be alright' ); + // name, times, values, interpolation + const object_all = new ColorKeyframeTrack( parameters.name, parameters.times, parameters.values, parameters.interpolation ); + assert.ok( object_all, 'Can instantiate a ColorKeyframeTrack with name, times, values, interpolation.' ); } ); diff --git a/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js b/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js index 385743c39535c1..5c6dfc524023fd 100644 --- a/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/NumberKeyframeTrack.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ -// import { NumberKeyframeTrack } from '../../../../../src/animation/tracks/NumberKeyframeTrack.js'; +import { NumberKeyframeTrack } from '../../../../../src/animation/tracks/NumberKeyframeTrack.js'; + +import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js'; export default QUnit.module( 'Animation', () => { @@ -8,9 +10,34 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'NumberKeyframeTrack', () => { - QUnit.todo( 'write me !', ( assert ) => { + const parameters = { + name: '.material.opacity', + times: [ 0, 1 ], + values: [ 0, 0.5 ], + interpolation: NumberKeyframeTrack.DefaultInterpolation + }; + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new NumberKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.strictEqual( + object instanceof KeyframeTrack, true, + 'NumberKeyframeTrack extends from KeyframeTrack' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + // name, times, values + const object = new NumberKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.ok( object, 'Can instantiate a NumberKeyframeTrack.' ); - assert.ok( false, 'everything\'s gonna be alright' ); + // name, times, values, interpolation + const object_all = new NumberKeyframeTrack( parameters.name, parameters.times, parameters.values, parameters.interpolation ); + assert.ok( object_all, 'Can instantiate a NumberKeyframeTrack with name, times, values, interpolation.' ); } ); diff --git a/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js b/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js index f005ef155c3b20..1503c9276317d0 100644 --- a/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/QuaternionKeyframeTrack.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ -// import { QuaternionKeyframeTrack } from '../../../../../src/animation/tracks/QuaternionKeyframeTrack.js'; +import { QuaternionKeyframeTrack } from '../../../../../src/animation/tracks/QuaternionKeyframeTrack.js'; + +import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js'; export default QUnit.module( 'Animation', () => { @@ -8,9 +10,34 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'QuaternionKeyframeTrack', () => { - QUnit.todo( 'write me !', ( assert ) => { + const parameters = { + name: '.rotation', + times: [ 0 ], + values: [ 0.5, 0.5, 0.5, 1 ], + interpolation: QuaternionKeyframeTrack.DefaultInterpolation + }; + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new QuaternionKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.strictEqual( + object instanceof KeyframeTrack, true, + 'QuaternionKeyframeTrack extends from KeyframeTrack' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + // name, times, values + const object = new QuaternionKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.ok( object, 'Can instantiate a QuaternionKeyframeTrack.' ); - assert.ok( false, 'everything\'s gonna be alright' ); + // name, times, values, interpolation + const object_all = new QuaternionKeyframeTrack( parameters.name, parameters.times, parameters.values, parameters.interpolation ); + assert.ok( object_all, 'Can instantiate a QuaternionKeyframeTrack with name, times, values, interpolation.' ); } ); diff --git a/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js b/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js index a98335c0b032ee..8c75d030fa7345 100644 --- a/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/StringKeyframeTrack.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ -// import { StringKeyframeTrack } from '../../../../../src/animation/tracks/StringKeyframeTrack.js'; +import { StringKeyframeTrack } from '../../../../../src/animation/tracks/StringKeyframeTrack.js'; + +import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js'; export default QUnit.module( 'Animation', () => { @@ -8,9 +10,34 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'StringKeyframeTrack', () => { - QUnit.todo( 'write me !', ( assert ) => { + const parameters = { + name: '.name', + times: [ 0, 1 ], + values: [ 'foo', 'bar' ], + interpolation: StringKeyframeTrack.DefaultInterpolation + }; + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new StringKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.strictEqual( + object instanceof KeyframeTrack, true, + 'StringKeyframeTrack extends from KeyframeTrack' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + // name, times, values + const object = new StringKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.ok( object, 'Can instantiate a StringKeyframeTrack.' ); - assert.ok( false, 'everything\'s gonna be alright' ); + // name, times, values, interpolation + const object_all = new StringKeyframeTrack( parameters.name, parameters.times, parameters.values, parameters.interpolation ); + assert.ok( object_all, 'Can instantiate a StringKeyframeTrack with name, times, values, interpolation.' ); } ); diff --git a/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js b/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js index 2094ca04e938c0..75aa3b86633bb5 100644 --- a/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js +++ b/test/unit/src/animation/tracks/VectorKeyframeTrack.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ -//import { VectorKeyframeTrack } from '../../../../../src/animation/tracks/VectorKeyframeTrack.js'; +import { VectorKeyframeTrack } from '../../../../../src/animation/tracks/VectorKeyframeTrack.js'; + +import { KeyframeTrack } from '../../../../../src/animation/KeyframeTrack.js'; export default QUnit.module( 'Animation', () => { @@ -8,9 +10,34 @@ export default QUnit.module( 'Animation', () => { QUnit.module( 'VectorKeyframeTrack', () => { - QUnit.todo( 'write me !', ( assert ) => { + const parameters = { + name: '.force', + times: [ 0 ], + values: [ 0.5, 0.5, 0.5 ], + interpolation: VectorKeyframeTrack.DefaultInterpolation + }; + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new VectorKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.strictEqual( + object instanceof KeyframeTrack, true, + 'VectorKeyframeTrack extends from KeyframeTrack' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + // name, times, values + const object = new VectorKeyframeTrack( parameters.name, parameters.times, parameters.values ); + assert.ok( object, 'Can instantiate a VectorKeyframeTrack.' ); - assert.ok( false, 'everything\'s gonna be alright' ); + // name, times, values, interpolation + const object_all = new VectorKeyframeTrack( parameters.name, parameters.times, parameters.values, parameters.interpolation ); + assert.ok( object_all, 'Can instantiate a VectorKeyframeTrack with name, times, values, interpolation.' ); } ); diff --git a/test/unit/src/audio/Audio.tests.js b/test/unit/src/audio/Audio.tests.js index 9d9d481aeca20a..7b16f23ba10668 100644 --- a/test/unit/src/audio/Audio.tests.js +++ b/test/unit/src/audio/Audio.tests.js @@ -1,26 +1,166 @@ /* global QUnit */ -// import { Audio } from '../../../../src/audio/Audio.js'; +import { Audio } from '../../../../src/audio/Audio.js'; + +import { Object3D } from '../../../../src/core/Object3D.js'; export default QUnit.module( 'Audios', () => { QUnit.module( 'Audio', () => { + function mockListener() { + + return { + context: { + createGain: () => { + + return { + connect: () => {}, + }; + + } + }, + getInput: () => {}, + }; + + } + // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const listener = mockListener(); + const object = new Audio( listener ); + assert.strictEqual( + object instanceof Object3D, true, + 'Audio extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const listener = mockListener(); + const object = new Audio( listener ); + assert.ok( object, 'Can instantiate an Audio.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const listener = mockListener(); + const object = new Audio( listener ); + assert.ok( + object.type === 'Audio', + 'Audio.type should be Audio' + ); + + } ); + + QUnit.todo( 'listener', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'context', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'gain', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'autoplay', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + QUnit.todo( 'buffer', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'detune', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'loop', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'loopStart', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'loopEnd', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'offset', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'duration', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'playbackRate', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'isPlaying', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'hasPlaybackControl', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'source', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'sourceType', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'filters', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC QUnit.todo( 'getOutput', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -33,6 +173,18 @@ export default QUnit.module( 'Audios', () => { } ); + QUnit.todo( 'setMediaElementSource', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'setMediaStreamSource', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.todo( 'setBuffer', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -81,6 +233,18 @@ export default QUnit.module( 'Audios', () => { } ); + QUnit.todo( 'setDetune', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'getDetune', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.todo( 'getFilter', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -123,6 +287,18 @@ export default QUnit.module( 'Audios', () => { } ); + QUnit.todo( 'setLoopStart', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'setLoopEnd', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.todo( 'getVolume', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/audio/AudioAnalyser.tests.js b/test/unit/src/audio/AudioAnalyser.tests.js index 3766130c9146c4..30dd1b51a34505 100644 --- a/test/unit/src/audio/AudioAnalyser.tests.js +++ b/test/unit/src/audio/AudioAnalyser.tests.js @@ -13,7 +13,20 @@ export default QUnit.module( 'Audios', () => { } ); - // PUBLIC STUFF + // PROPERTIES + QUnit.todo( 'analyser', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'data', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC QUnit.todo( 'getFrequencyData', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/audio/AudioContext.tests.js b/test/unit/src/audio/AudioContext.tests.js index 153e47fae6ea20..bcc9c794fb742d 100644 --- a/test/unit/src/audio/AudioContext.tests.js +++ b/test/unit/src/audio/AudioContext.tests.js @@ -1,21 +1,66 @@ /* global QUnit */ -// import { AudioContext } from '../../../../src/audio/AudioContext.js'; +import { AudioContext } from '../../../../src/audio/AudioContext.js'; export default QUnit.module( 'Audios', () => { - QUnit.module( 'AudioContext', () => { + QUnit.module( 'AudioContext', ( hooks ) => { - // PUBLIC STUFF - QUnit.todo( 'getContext', ( assert ) => { + function mockWindowAudioContext() { - assert.ok( false, 'everything\'s gonna be alright' ); + global.window = { + AudioContext: function () { + + return { + createGain: () => { + + return { + connect: () => {}, + }; + + } + }; + + }, + }; + + } + + if ( typeof window === 'undefined' ) { + + hooks.before( function () { + + mockWindowAudioContext(); + + } ); + + hooks.after( function () { + + global.window = undefined; + + } ); + + } + + // STATIC + QUnit.test( 'getContext', ( assert ) => { + + const context = AudioContext.getContext(); + assert.strictEqual( + context instanceof Object, true, + 'AudioContext.getContext creates a context.' + ); } ); - QUnit.todo( 'setContext', ( assert ) => { + QUnit.test( 'setContext', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + AudioContext.setContext( new window.AudioContext() ); + const context = AudioContext.getContext(); + assert.strictEqual( + context instanceof Object, true, + 'AudioContext.setContext updates the context.' + ); } ); diff --git a/test/unit/src/audio/AudioListener.tests.js b/test/unit/src/audio/AudioListener.tests.js index ef9bc41fc68c99..102d885066aeb1 100644 --- a/test/unit/src/audio/AudioListener.tests.js +++ b/test/unit/src/audio/AudioListener.tests.js @@ -1,26 +1,104 @@ /* global QUnit */ -// import { AudioListener } from '../../../../src/audio/AudioListener.js'; +import { AudioListener } from '../../../../src/audio/AudioListener.js'; + +import { Object3D } from '../../../../src/core/Object3D.js'; export default QUnit.module( 'Audios', () => { - QUnit.module( 'AudioListener', () => { + QUnit.module( 'AudioListener', ( hooks ) => { + + function mockWindowAudioContext() { + + global.window = { + AudioContext: function () { + + return { + createGain: () => { + + return { + connect: () => {}, + }; + + } + }; + + }, + }; + + } + + if ( typeof window === 'undefined' ) { + + hooks.before( function () { + + mockWindowAudioContext(); + + } ); + + hooks.after( function () { + + global.window = undefined; + + } ); + + } // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new AudioListener(); + assert.strictEqual( + object instanceof Object3D, true, + 'AudioListener extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new AudioListener(); + assert.ok( object, 'Can instantiate an AudioListener.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const object = new AudioListener(); + assert.ok( + object.type === 'AudioListener', + 'AudioListener.type should be AudioListener' + ); + + } ); + + QUnit.todo( 'context', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'gain', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'filter', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'timeDelta', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + // PUBLIC QUnit.todo( 'getInput', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/audio/PositionalAudio.tests.js b/test/unit/src/audio/PositionalAudio.tests.js index 0feda11d8118a9..6c69853ae18ad0 100644 --- a/test/unit/src/audio/PositionalAudio.tests.js +++ b/test/unit/src/audio/PositionalAudio.tests.js @@ -1,26 +1,73 @@ /* global QUnit */ -// import { PositionalAudio } from '../../../../src/audio/PositionalAudio.js'; +import { PositionalAudio } from '../../../../src/audio/PositionalAudio.js'; + +import { Audio } from '../../../../src/audio/Audio.js'; export default QUnit.module( 'Audios', () => { QUnit.module( 'PositionalAudio', () => { + function mock3DListener() { + + return { + context: { + createGain: () => { + + return { + connect: () => {}, + }; + + }, + createPanner: () => { + + return { + connect: () => {}, + }; + + } + + }, + getInput: () => {}, + }; + + } + // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const listener = mock3DListener(); + const object = new PositionalAudio( listener ); + assert.strictEqual( + object instanceof Audio, true, + 'PositionalAudio extends from Audio' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const listener = mock3DListener(); + const object = new PositionalAudio( listener ); + assert.ok( object, 'Can instantiate a PositionalAudio.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'panner', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.todo( 'disconnect', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF QUnit.todo( 'getOutput', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -75,12 +122,17 @@ export default QUnit.module( 'Audios', () => { } ); - QUnit.todo( 'updateMatrixWorld', ( assert ) => { + QUnit.todo( 'setDirectionalCone', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + QUnit.todo( 'updateMatrixWorld', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); } ); diff --git a/test/unit/src/cameras/ArrayCamera.tests.js b/test/unit/src/cameras/ArrayCamera.tests.js index c78a880e499bf1..0b0c04f626be46 100644 --- a/test/unit/src/cameras/ArrayCamera.tests.js +++ b/test/unit/src/cameras/ArrayCamera.tests.js @@ -1,32 +1,51 @@ /* global QUnit */ -// import { ArrayCamera } from '../../../../src/cameras/ArrayCamera.js'; +import { ArrayCamera } from '../../../../src/cameras/ArrayCamera.js'; + +import { PerspectiveCamera } from '../../../../src/cameras/PerspectiveCamera.js'; export default QUnit.module( 'Cameras', () => { QUnit.module( 'ArrayCamera', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ArrayCamera(); + assert.strictEqual( + object instanceof PerspectiveCamera, true, + 'ArrayCamera extends from PerspectiveCamera' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ArrayCamera(); + assert.ok( object, 'Can instantiate an ArrayCamera.' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isArrayCamera', ( assert ) => { + // PROPERTIES + QUnit.todo( 'cameras', ( assert ) => { + // array assert.ok( false, 'everything\'s gonna be alright' ); } ); + // PUBLIC + QUnit.test( 'isArrayCamera', ( assert ) => { + + const object = new ArrayCamera(); + assert.ok( + object.isArrayCamera, + 'ArrayCamera.isArrayCamera should be true' + ); + + } ); + } ); } ); diff --git a/test/unit/src/cameras/Camera.tests.js b/test/unit/src/cameras/Camera.tests.js index 5341572caa7124..b9cf25e3d88319 100644 --- a/test/unit/src/cameras/Camera.tests.js +++ b/test/unit/src/cameras/Camera.tests.js @@ -1,33 +1,73 @@ /* global QUnit */ import { Camera } from '../../../../src/cameras/Camera.js'; + import { Vector3 } from '../../../../src/math/Vector3.js'; +import { Object3D } from '../../../../src/core/Object3D.js'; export default QUnit.module( 'Cameras', () => { QUnit.module( 'Camera', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Camera(); + assert.strictEqual( + object instanceof Object3D, true, + 'Camera extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new Camera(); + assert.ok( object, 'Can instantiate a Camera.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const object = new Camera(); + assert.ok( + object.type === 'Camera', + 'Camera.type should be Camera' + ); + + } ); + + QUnit.todo( 'matrixWorldInverse', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'projectionMatrix', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isCamera', ( assert ) => { + QUnit.todo( 'projectionMatrixInverse', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + // PUBLIC + QUnit.test( 'isCamera', ( assert ) => { + + const object = new Camera(); + assert.ok( + object.isCamera, + 'Camera.isCamera should be true' + ); + + } ); + QUnit.todo( 'copy', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -46,18 +86,24 @@ export default QUnit.module( 'Cameras', () => { } ); + QUnit.todo( 'updateWorldMatrix', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'clone', ( assert ) => { - var cam = new Camera(); + const cam = new Camera(); // fill the matrices with any nonsense values just to see if they get copied cam.matrixWorldInverse.set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); cam.projectionMatrix.set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var clonedCam = cam.clone(); + const clonedCam = cam.clone(); - // TODO: Uuuummmhhh DO NOT relie equality on object methods ! - // TODO: What's append if matrix.equal is wrongly implemented ??? + // TODO: do not rely equality on object methods + // TODO: What's append if matrix.equal is wrongly implemented // TODO: this MUST be check by assert assert.ok( cam.matrixWorldInverse.equals( clonedCam.matrixWorldInverse ), 'matrixWorldInverse is equal' ); assert.ok( cam.projectionMatrix.equals( clonedCam.projectionMatrix ), 'projectionMatrix is equal' ); @@ -65,10 +111,10 @@ export default QUnit.module( 'Cameras', () => { } ); // OTHERS - // TODO: this should not be here !!! This is Object3D stuff !!! + // TODO: this should not be here, Object3D related QUnit.test( 'lookAt', ( assert ) => { - var cam = new Camera(); + const cam = new Camera(); cam.lookAt( new Vector3( 0, 1, - 1 ) ); assert.numEqual( cam.rotation.x * ( 180 / Math.PI ), 45, 'x is equal' ); diff --git a/test/unit/src/cameras/CubeCamera.tests.js b/test/unit/src/cameras/CubeCamera.tests.js index e2a071734bacbb..41de2df65a0292 100644 --- a/test/unit/src/cameras/CubeCamera.tests.js +++ b/test/unit/src/cameras/CubeCamera.tests.js @@ -1,21 +1,53 @@ /* global QUnit */ -// import { CubeCamera } from '../../../../src/cameras/CubeCamera.js'; +import { CubeCamera } from '../../../../src/cameras/CubeCamera.js'; + +import { Object3D } from '../../../../src/core/Object3D.js'; export default QUnit.module( 'Cameras', () => { QUnit.module( 'CubeCamera', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CubeCamera(); + assert.strictEqual( + object instanceof Object3D, true, + 'CubeCamera extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new CubeCamera(); + assert.ok( object, 'Can instantiate a CubeCamera.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const object = new CubeCamera(); + assert.ok( + object.type === 'CubeCamera', + 'CubeCamera.type should be CubeCamera' + ); + + } ); + + QUnit.todo( 'renderTarget', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.todo( 'update', ( assert ) => { + // update( renderer, scene ) assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/cameras/OrthographicCamera.tests.js b/test/unit/src/cameras/OrthographicCamera.tests.js index eeabaf33cdf361..c4d21b5968f73e 100644 --- a/test/unit/src/cameras/OrthographicCamera.tests.js +++ b/test/unit/src/cameras/OrthographicCamera.tests.js @@ -2,31 +2,101 @@ import { OrthographicCamera } from '../../../../src/cameras/OrthographicCamera.js'; +import { Camera } from '../../../../src/cameras/Camera.js'; + export default QUnit.module( 'Cameras', () => { QUnit.module( 'OrthographicCamera', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new OrthographicCamera(); + assert.strictEqual( + object instanceof Camera, true, + 'OrthographicCamera extends from Camera' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new OrthographicCamera(); + assert.ok( object, 'Can instantiate an OrthographicCamera.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const object = new OrthographicCamera(); + assert.ok( + object.type === 'OrthographicCamera', + 'OrthographicCamera.type should be OrthographicCamera' + ); + + } ); + + QUnit.todo( 'zoom', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'view', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'left', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'right', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'top', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'bottom', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isOrthographicCamera', ( assert ) => { + QUnit.todo( 'near', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + QUnit.todo( 'far', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.test( 'isOrthographicCamera', ( assert ) => { + + const object = new OrthographicCamera(); + assert.ok( + object.isOrthographicCamera, + 'OrthographicCamera.isOrthographicCamera should be true' + ); + + } ); + QUnit.todo( 'copy', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -47,11 +117,11 @@ export default QUnit.module( 'Cameras', () => { QUnit.test( 'updateProjectionMatrix', ( assert ) => { - var left = - 1, right = 1, top = 1, bottom = - 1, near = 1, far = 3; - var cam = new OrthographicCamera( left, right, top, bottom, near, far ); + const left = - 1, right = 1, top = 1, bottom = - 1, near = 1, far = 3; + const cam = new OrthographicCamera( left, right, top, bottom, near, far ); // updateProjectionMatrix is called in constructor - var pMatrix = cam.projectionMatrix.elements; + const pMatrix = cam.projectionMatrix.elements; // orthographic projection is given my the 4x4 Matrix // 2/r-l 0 0 -(l+r/r-l) @@ -75,13 +145,13 @@ export default QUnit.module( 'Cameras', () => { } ); // OTHERS - // TODO: no no no clone is a camera methods that relied to copy method + // TODO: clone is a camera methods that relied to copy method QUnit.test( 'clone', ( assert ) => { - var left = - 1.5, right = 1.5, top = 1, bottom = - 1, near = 0.1, far = 42; - var cam = new OrthographicCamera( left, right, top, bottom, near, far ); + const left = - 1.5, right = 1.5, top = 1, bottom = - 1, near = 0.1, far = 42; + const cam = new OrthographicCamera( left, right, top, bottom, near, far ); - var clonedCam = cam.clone(); + const clonedCam = cam.clone(); assert.ok( cam.left === clonedCam.left, 'left is equal' ); assert.ok( cam.right === clonedCam.right, 'right is equal' ); diff --git a/test/unit/src/cameras/PerspectiveCamera.tests.js b/test/unit/src/cameras/PerspectiveCamera.tests.js index 8063dbe43518d7..27cfcd4e554160 100644 --- a/test/unit/src/cameras/PerspectiveCamera.tests.js +++ b/test/unit/src/cameras/PerspectiveCamera.tests.js @@ -1,14 +1,16 @@ /* global QUnit */ import { PerspectiveCamera } from '../../../../src/cameras/PerspectiveCamera.js'; + import { Matrix4 } from '../../../../src/math/Matrix4.js'; +import { Camera } from '../../../../src/cameras/Camera.js'; export default QUnit.module( 'Cameras', () => { QUnit.module( 'PerspectiveCamera', () => { // see e.g. math/Matrix4.js - var matrixEquals4 = function ( a, b, tolerance ) { + const matrixEquals4 = function ( a, b, tolerance ) { tolerance = tolerance || 0.0001; if ( a.elements.length != b.elements.length ) { @@ -17,9 +19,9 @@ export default QUnit.module( 'Cameras', () => { } - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { + for ( let i = 0, il = a.elements.length; i < il; i ++ ) { - var delta = a.elements[ i ] - b.elements[ i ]; + const delta = a.elements[ i ] - b.elements[ i ]; if ( delta > tolerance ) { return false; @@ -33,26 +35,100 @@ export default QUnit.module( 'Cameras', () => { }; // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PerspectiveCamera(); + assert.strictEqual( + object instanceof Camera, true, + 'PerspectiveCamera extends from Camera' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new PerspectiveCamera(); + assert.ok( object, 'Can instantiate a PerspectiveCamera.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const object = new PerspectiveCamera(); + assert.ok( + object.type === 'PerspectiveCamera', + 'PerspectiveCamera.type should be PerspectiveCamera' + ); + + } ); + + QUnit.todo( 'fov', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'zoom', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'near', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'far', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'focus', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'aspect', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'view', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isPerspectiveCamera', ( assert ) => { + QUnit.todo( 'filmGauge', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + QUnit.todo( 'filmOffset', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.test( 'isPerspectiveCamera', ( assert ) => { + + const object = new PerspectiveCamera(); + assert.ok( + object.isPerspectiveCamera, + 'PerspectiveCamera.isPerspectiveCamera should be true' + ); + + } ); + QUnit.todo( 'copy', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -103,10 +179,10 @@ export default QUnit.module( 'Cameras', () => { QUnit.test( 'updateProjectionMatrix', ( assert ) => { - var cam = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); + const cam = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); // updateProjectionMatrix is called in constructor - var m = cam.projectionMatrix; + const m = cam.projectionMatrix; // perspective projection is given my the 4x4 Matrix // 2n/r-l 0 l+r/r-l 0 @@ -116,7 +192,7 @@ export default QUnit.module( 'Cameras', () => { // this matrix was calculated by hand via glMatrix.perspective(75, 16 / 9, 0.1, 300.0, pMatrix) // to get a reference matrix from plain WebGL - var reference = new Matrix4().set( + const reference = new Matrix4().set( 0.7330642938613892, 0, 0, 0, 0, 1.3032253980636597, 0, 0, 0, 0, - 1.000666856765747, - 0.2000666856765747, @@ -135,17 +211,17 @@ export default QUnit.module( 'Cameras', () => { } ); // OTHERS - // TODO: no no no clone is a camera methods that relied to copy method + // TODO: clone is a camera methods that relied to copy method QUnit.test( 'clone', ( assert ) => { - var near = 1, + const near = 1, far = 3, aspect = 16 / 9, fov = 90; - var cam = new PerspectiveCamera( fov, aspect, near, far ); + const cam = new PerspectiveCamera( fov, aspect, near, far ); - var clonedCam = cam.clone(); + const clonedCam = cam.clone(); assert.ok( cam.fov === clonedCam.fov, 'fov is equal' ); assert.ok( cam.aspect === clonedCam.aspect, 'aspect is equal' ); diff --git a/test/unit/src/cameras/StereoCamera.tests.js b/test/unit/src/cameras/StereoCamera.tests.js index c396d311c913f1..207219bdb835df 100644 --- a/test/unit/src/cameras/StereoCamera.tests.js +++ b/test/unit/src/cameras/StereoCamera.tests.js @@ -1,19 +1,55 @@ /* global QUnit */ -// import { StereoCamera } from '../../../../src/cameras/StereoCamera.js'; +import { StereoCamera } from '../../../../src/cameras/StereoCamera.js'; export default QUnit.module( 'Cameras', () => { QUnit.module( 'StereoCamera', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new StereoCamera(); + assert.ok( object, 'Can instantiate a StereoCamera.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const object = new StereoCamera(); + assert.ok( + object.type === 'StereoCamera', + 'StereoCamera.type should be StereoCamera' + ); + + } ); + + QUnit.todo( 'aspect', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'eyeSep', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'cameraL', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'cameraR', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + // PUBLIC QUnit.todo( 'update', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/constants.tests.js b/test/unit/src/constants.tests.js index e233ecf2c93534..e97bdcce4ef459 100644 --- a/test/unit/src/constants.tests.js +++ b/test/unit/src/constants.tests.js @@ -8,27 +8,34 @@ export default QUnit.module( 'Constants', () => { assert.propEqual( Constants.MOUSE, { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }, 'MOUSE equal { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }' ); assert.propEqual( Constants.TOUCH, { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }, 'TOUCH equal { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }' ); + assert.equal( Constants.CullFaceNone, 0, 'CullFaceNone equal 0' ); assert.equal( Constants.CullFaceBack, 1, 'CullFaceBack equal 1' ); assert.equal( Constants.CullFaceFront, 2, 'CullFaceFront is equal to 2' ); assert.equal( Constants.CullFaceFrontBack, 3, 'CullFaceFrontBack is equal to 3' ); + assert.equal( Constants.BasicShadowMap, 0, 'BasicShadowMap is equal to 0' ); assert.equal( Constants.PCFShadowMap, 1, 'PCFShadowMap is equal to 1' ); assert.equal( Constants.PCFSoftShadowMap, 2, 'PCFSoftShadowMap is equal to 2' ); + assert.equal( Constants.VSMShadowMap, 3, 'VSMShadowMap is equal to 3' ); + assert.equal( Constants.FrontSide, 0, 'FrontSide is equal to 0' ); assert.equal( Constants.BackSide, 1, 'BackSide is equal to 1' ); assert.equal( Constants.DoubleSide, 2, 'DoubleSide is equal to 2' ); + assert.equal( Constants.NoBlending, 0, 'NoBlending is equal to 0' ); assert.equal( Constants.NormalBlending, 1, 'NormalBlending is equal to 1' ); assert.equal( Constants.AdditiveBlending, 2, 'AdditiveBlending is equal to 2' ); assert.equal( Constants.SubtractiveBlending, 3, 'SubtractiveBlending is equal to 3' ); assert.equal( Constants.MultiplyBlending, 4, 'MultiplyBlending is equal to 4' ); assert.equal( Constants.CustomBlending, 5, 'CustomBlending is equal to 5' ); + assert.equal( Constants.AddEquation, 100, 'AddEquation is equal to 100' ); assert.equal( Constants.SubtractEquation, 101, 'SubtractEquation is equal to 101' ); assert.equal( Constants.ReverseSubtractEquation, 102, 'ReverseSubtractEquation is equal to 102' ); assert.equal( Constants.MinEquation, 103, 'MinEquation is equal to 103' ); assert.equal( Constants.MaxEquation, 104, 'MaxEquation is equal to 104' ); + assert.equal( Constants.ZeroFactor, 200, 'ZeroFactor is equal to 200' ); assert.equal( Constants.OneFactor, 201, 'OneFactor is equal to 201' ); assert.equal( Constants.SrcColorFactor, 202, 'SrcColorFactor is equal to 202' ); @@ -40,6 +47,7 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.DstColorFactor, 208, 'DstColorFactor is equal to 208' ); assert.equal( Constants.OneMinusDstColorFactor, 209, 'OneMinusDstColorFactor is equal to 209' ); assert.equal( Constants.SrcAlphaSaturateFactor, 210, 'SrcAlphaSaturateFactor is equal to 210' ); + assert.equal( Constants.NeverDepth, 0, 'NeverDepth is equal to 0' ); assert.equal( Constants.AlwaysDepth, 1, 'AlwaysDepth is equal to 1' ); assert.equal( Constants.LessDepth, 2, 'LessDepth is equal to 2' ); @@ -48,23 +56,29 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.GreaterEqualDepth, 5, 'GreaterEqualDepth is equal to 5' ); assert.equal( Constants.GreaterDepth, 6, 'GreaterDepth is equal to 6' ); assert.equal( Constants.NotEqualDepth, 7, 'NotEqualDepth is equal to 7' ); + assert.equal( Constants.MultiplyOperation, 0, 'MultiplyOperation is equal to 0' ); assert.equal( Constants.MixOperation, 1, 'MixOperation is equal to 1' ); assert.equal( Constants.AddOperation, 2, 'AddOperation is equal to 2' ); + assert.equal( Constants.NoToneMapping, 0, 'NoToneMapping is equal to 0' ); assert.equal( Constants.LinearToneMapping, 1, 'LinearToneMapping is equal to 1' ); assert.equal( Constants.ReinhardToneMapping, 2, 'ReinhardToneMapping is equal to 2' ); assert.equal( Constants.CineonToneMapping, 3, 'CineonToneMapping is equal to 3' ); assert.equal( Constants.ACESFilmicToneMapping, 4, 'ACESFilmicToneMapping is equal to 4' ); + assert.equal( Constants.CustomToneMapping, 5, 'CustomToneMapping is equal to 5' ); + assert.equal( Constants.UVMapping, 300, 'UVMapping is equal to 300' ); assert.equal( Constants.CubeReflectionMapping, 301, 'CubeReflectionMapping is equal to 301' ); assert.equal( Constants.CubeRefractionMapping, 302, 'CubeRefractionMapping is equal to 302' ); assert.equal( Constants.EquirectangularReflectionMapping, 303, 'EquirectangularReflectionMapping is equal to 303' ); assert.equal( Constants.EquirectangularRefractionMapping, 304, 'EquirectangularRefractionMapping is equal to 304' ); assert.equal( Constants.CubeUVReflectionMapping, 306, 'CubeUVReflectionMapping is equal to 306' ); + assert.equal( Constants.RepeatWrapping, 1000, 'RepeatWrapping is equal to 1000' ); assert.equal( Constants.ClampToEdgeWrapping, 1001, 'ClampToEdgeWrapping is equal to 1001' ); assert.equal( Constants.MirroredRepeatWrapping, 1002, 'MirroredRepeatWrapping is equal to 1002' ); + assert.equal( Constants.NearestFilter, 1003, 'NearestFilter is equal to 1003' ); assert.equal( Constants.NearestMipMapNearestFilter, 1004, 'NearestMipMapNearestFilter is equal to 1004' ); assert.equal( Constants.NearestMipMapLinearFilter, 1005, 'NearestMipMapLinearFilter is equal to 1005' ); @@ -72,6 +86,7 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.LinearMipMapNearestFilter, 1007, 'LinearMipMapNearestFilter is equal to 1007' ); assert.equal( Constants.LinearMipMapLinearFilter, 1008, 'LinearMipMapLinearFilter is equal to 1008' ); assert.equal( Constants.UnsignedByteType, 1009, 'UnsignedByteType is equal to 1009' ); + assert.equal( Constants.ByteType, 1010, 'ByteType is equal to 1010' ); assert.equal( Constants.ShortType, 1011, 'ShortType is equal to 1011' ); assert.equal( Constants.UnsignedShortType, 1012, 'UnsignedShortType is equal to 1012' ); @@ -82,12 +97,19 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.UnsignedShort4444Type, 1017, 'UnsignedShort4444Type is equal to 1017' ); assert.equal( Constants.UnsignedShort5551Type, 1018, 'UnsignedShort5551Type is equal to 1018' ); assert.equal( Constants.UnsignedInt248Type, 1020, 'UnsignedInt248Type is equal to 1020' ); + assert.equal( Constants.AlphaFormat, 1021, 'AlphaFormat is equal to 1021' ); assert.equal( Constants.RGBAFormat, 1023, 'RGBAFormat is equal to 1023' ); assert.equal( Constants.LuminanceFormat, 1024, 'LuminanceFormat is equal to 1024' ); assert.equal( Constants.LuminanceAlphaFormat, 1025, 'LuminanceAlphaFormat is equal to 1025' ); assert.equal( Constants.DepthFormat, 1026, 'DepthFormat is equal to 1026' ); assert.equal( Constants.DepthStencilFormat, 1027, 'DepthStencilFormat is equal to 1027' ); + assert.equal( Constants.RedFormat, 1028, 'RedFormat is equal to 1028' ); + assert.equal( Constants.RedIntegerFormat, 1029, 'RedIntegerFormat is equal to 1029' ); + assert.equal( Constants.RGFormat, 1030, 'RGFormat is equal to 1030' ); + assert.equal( Constants.RGIntegerFormat, 1031, 'RGIntegerFormat is equal to 1031' ); + assert.equal( Constants.RGBAIntegerFormat, 1033, 'RGBAIntegerFormat is equal to 1033' ); + assert.equal( Constants.RGB_S3TC_DXT1_Format, 33776, 'RGB_S3TC_DXT1_Format is equal to 33776' ); assert.equal( Constants.RGBA_S3TC_DXT1_Format, 33777, 'RGBA_S3TC_DXT1_Format is equal to 33777' ); assert.equal( Constants.RGBA_S3TC_DXT3_Format, 33778, 'RGBA_S3TC_DXT3_Format is equal to 33778' ); @@ -97,6 +119,7 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.RGBA_PVRTC_4BPPV1_Format, 35842, 'RGBA_PVRTC_4BPPV1_Format is equal to 35842' ); assert.equal( Constants.RGBA_PVRTC_2BPPV1_Format, 35843, 'RGBA_PVRTC_2BPPV1_Format is equal to 35843' ); assert.equal( Constants.RGB_ETC1_Format, 36196, 'RGB_ETC1_Format is equal to 36196' ); + assert.equal( Constants.RGB_ETC2_Format, 37492, 'RGB_ETC2_Format is equal to 37492' ); assert.equal( Constants.RGBA_ASTC_4x4_Format, 37808, 'Constants.RGBA_ASTC_4x4_Format is equal to 37808' ); assert.equal( Constants.RGBA_ASTC_5x4_Format, 37809, 'Constants.RGBA_ASTC_5x4_Format is equal to 37809' ); assert.equal( Constants.RGBA_ASTC_5x5_Format, 37810, 'Constants.RGBA_ASTC_5x5_Format is equal to 37810' ); @@ -111,23 +134,75 @@ export default QUnit.module( 'Constants', () => { assert.equal( Constants.RGBA_ASTC_10x10_Format, 37819, 'Constants.RGBA_ASTC_10x10_Format is equal to 37819' ); assert.equal( Constants.RGBA_ASTC_12x10_Format, 37820, 'Constants.RGBA_ASTC_12x10_Format is equal to 37820' ); assert.equal( Constants.RGBA_ASTC_12x12_Format, 37821, 'Constants.RGBA_ASTC_12x12_Format is equal to 37821' ); + assert.equal( Constants.RGBA_BPTC_Format, 36492, 'Constants.RGBA_BPTC_Format is equal to 36492' ); + assert.equal( Constants.RED_RGTC1_Format, 36283, 'Constants.RED_RGTC1_Format is equal to 36283' ); + assert.equal( Constants.SIGNED_RED_RGTC1_Format, 36284, 'Constants.SIGNED_RED_RGTC1_Format is equal to 36284' ); + assert.equal( Constants.RED_GREEN_RGTC2_Format, 36285, 'Constants.RED_GREEN_RGTC2_Format is equal to 36285' ); + assert.equal( Constants.SIGNED_RED_GREEN_RGTC2_Format, 36286, 'Constants.SIGNED_RED_GREEN_RGTC2_Format is equal to 36286' ); + assert.equal( Constants.LoopOnce, 2200, 'LoopOnce is equal to 2200' ); assert.equal( Constants.LoopRepeat, 2201, 'LoopRepeat is equal to 2201' ); assert.equal( Constants.LoopPingPong, 2202, 'LoopPingPong is equal to 2202' ); + assert.equal( Constants.InterpolateDiscrete, 2300, 'InterpolateDiscrete is equal to 2300' ); assert.equal( Constants.InterpolateLinear, 2301, 'InterpolateLinear is equal to 2301' ); assert.equal( Constants.InterpolateSmooth, 2302, 'InterpolateSmooth is equal to 2302' ); + assert.equal( Constants.ZeroCurvatureEnding, 2400, 'ZeroCurvatureEnding is equal to 2400' ); assert.equal( Constants.ZeroSlopeEnding, 2401, 'ZeroSlopeEnding is equal to 2401' ); assert.equal( Constants.WrapAroundEnding, 2402, 'WrapAroundEnding is equal to 2402' ); + + assert.equal( Constants.NormalAnimationBlendMode, 2500, 'NormalAnimationBlendMode is equal to 2500' ); + assert.equal( Constants.AdditiveAnimationBlendMode, 2501, 'AdditiveAnimationBlendMode is equal to 2501' ); + assert.equal( Constants.TrianglesDrawMode, 0, 'TrianglesDrawMode is equal to 0' ); assert.equal( Constants.TriangleStripDrawMode, 1, 'TriangleStripDrawMode is equal to 1' ); assert.equal( Constants.TriangleFanDrawMode, 2, 'TriangleFanDrawMode is equal to 2' ); - assert.equal( Constants.LinearEncoding, 3000, 'LinearEncoding is equal to 3000' ); - assert.equal( Constants.sRGBEncoding, 3001, 'sRGBEncoding is equal to 3001' ); + assert.equal( Constants.BasicDepthPacking, 3200, 'BasicDepthPacking is equal to 3200' ); assert.equal( Constants.RGBADepthPacking, 3201, 'RGBADepthPacking is equal to 3201' ); + assert.equal( Constants.TangentSpaceNormalMap, 0, 'TangentSpaceNormalMap is equal to 0' ); + assert.equal( Constants.ObjectSpaceNormalMap, 1, 'ObjectSpaceNormalMap is equal to 1' ); + + assert.equal( Constants.NoColorSpace, '', 'NoColorSpace is equal to ""' ); + assert.equal( Constants.SRGBColorSpace, 'srgb', 'SRGBColorSpace is equal to srgb' ); + assert.equal( Constants.LinearSRGBColorSpace, 'srgb-linear', 'LinearSRGBColorSpace is equal to srgb-linear' ); + assert.equal( Constants.DisplayP3ColorSpace, 'display-p3', 'DisplayP3ColorSpace is equal to display-p3' ); + + assert.equal( Constants.ZeroStencilOp, 0, 'ZeroStencilOp is equal to 0' ); + assert.equal( Constants.KeepStencilOp, 7680, 'KeepStencilOp is equal to 7680' ); + assert.equal( Constants.ReplaceStencilOp, 7681, 'ReplaceStencilOp is equal to 7681' ); + assert.equal( Constants.IncrementStencilOp, 7682, 'IncrementStencilOp is equal to 7682' ); + assert.equal( Constants.DecrementStencilOp, 7683, 'DecrementStencilOp is equal to 7683' ); + assert.equal( Constants.IncrementWrapStencilOp, 34055, 'IncrementWrapStencilOp is equal to 34055' ); + assert.equal( Constants.DecrementWrapStencilOp, 34056, 'DecrementWrapStencilOp is equal to 34056' ); + assert.equal( Constants.InvertStencilOp, 5386, 'InvertStencilOp is equal to 5386' ); + + assert.equal( Constants.NeverStencilFunc, 512, 'NeverStencilFunc is equal to 512' ); + assert.equal( Constants.LessStencilFunc, 513, 'LessStencilFunc is equal to 513' ); + assert.equal( Constants.EqualStencilFunc, 514, 'EqualStencilFunc is equal to 514' ); + assert.equal( Constants.LessEqualStencilFunc, 515, 'LessEqualStencilFunc is equal to 515' ); + assert.equal( Constants.GreaterStencilFunc, 516, 'GreaterStencilFunc is equal to 516' ); + assert.equal( Constants.NotEqualStencilFunc, 517, 'NotEqualStencilFunc is equal to 517' ); + assert.equal( Constants.GreaterEqualStencilFunc, 518, 'GreaterEqualStencilFunc is equal to 518' ); + assert.equal( Constants.AlwaysStencilFunc, 519, 'AlwaysStencilFunc is equal to 519' ); + + assert.equal( Constants.StaticDrawUsage, 35044, 'StaticDrawUsage is equal to 35044' ); + assert.equal( Constants.DynamicDrawUsage, 35048, 'DynamicDrawUsage is equal to 35048' ); + assert.equal( Constants.StreamDrawUsage, 35040, 'StreamDrawUsage is equal to 35040' ); + assert.equal( Constants.StaticReadUsage, 35045, 'StaticReadUsage is equal to 35045' ); + assert.equal( Constants.DynamicReadUsage, 35049, 'DynamicReadUsage is equal to 35049' ); + assert.equal( Constants.StreamReadUsage, 35041, 'StreamReadUsage is equal to 35041' ); + assert.equal( Constants.StaticCopyUsage, 35046, 'StaticCopyUsage is equal to 35046' ); + assert.equal( Constants.DynamicCopyUsage, 35050, 'DynamicCopyUsage is equal to 35050' ); + assert.equal( Constants.StreamCopyUsage, 35042, 'StreamCopyUsage is equal to 35042' ); + + assert.equal( Constants.GLSL1, '100', 'GLSL1 is equal to 100' ); + assert.equal( Constants.GLSL3, '300 es', 'GLSL3 is equal to 300 es' ); + + assert.equal( Constants._SRGBAFormat, 1035, '_SRGBAFormat is equal to 1035' ); + } ); } ); diff --git a/test/unit/src/core/BufferAttribute.tests.js b/test/unit/src/core/BufferAttribute.tests.js index 3eba471d2188c2..d7837508b7e0d9 100644 --- a/test/unit/src/core/BufferAttribute.tests.js +++ b/test/unit/src/core/BufferAttribute.tests.js @@ -1,7 +1,22 @@ /* global QUnit */ import { BufferAttribute } from '../../../../src/core/BufferAttribute.js'; + +import { + Int8BufferAttribute, + Uint8BufferAttribute, + Uint8ClampedBufferAttribute, + Int16BufferAttribute, + Uint16BufferAttribute, + Int32BufferAttribute, + Uint32BufferAttribute, + Float16BufferAttribute, + Float32BufferAttribute, + Float64BufferAttribute +} from '../../../../src/core/BufferAttribute.js'; + import { DynamicDrawUsage } from '../../../../src/constants.js'; +import { toHalfFloat, fromHalfFloat } from '../../../../src/extras/DataUtils.js'; export default QUnit.module( 'Core', () => { @@ -23,22 +38,83 @@ export default QUnit.module( 'Core', () => { } ); // PROPERTIES - QUnit.todo( 'needsUpdate', ( assert ) => { + QUnit.todo( 'name', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'array', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'itemSize', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'count', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'normalized', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'usage', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'updateRange', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'version', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'onUploadCallback', ( assert ) => { + // onUploadCallback() {} + // defined as member function but set property. refactor req assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isBufferAttribute', ( assert ) => { + QUnit.todo( 'needsUpdate', ( assert ) => { + // set needsUpdate( value ) assert.ok( false, 'everything\'s gonna be alright' ); } ); + // PUBLIC + QUnit.test( 'isBufferAttribute', ( assert ) => { + + const object = new BufferAttribute(); + assert.ok( + object.isBufferAttribute, + 'BufferAttribute.isBufferAttribute should be true' + ); + + } ); + QUnit.test( 'setUsage', ( assert ) => { - var attr = new BufferAttribute(); + const attr = new BufferAttribute(); attr.setUsage( DynamicDrawUsage ); assert.strictEqual( attr.usage, DynamicDrawUsage, 'Usage was set' ); @@ -47,11 +123,11 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'copy', ( assert ) => { - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); + const attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); attr.setUsage( DynamicDrawUsage ); attr.needsUpdate = true; - var attrCopy = new BufferAttribute().copy( attr ); + const attrCopy = new BufferAttribute().copy( attr ); assert.ok( attr.count === attrCopy.count, 'count is equal' ); assert.ok( attr.itemSize === attrCopy.itemSize, 'itemSize is equal' ); @@ -63,15 +139,15 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'copyAt', ( assert ) => { - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); - var attr2 = new BufferAttribute( new Float32Array( 9 ), 3 ); + const attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); + const attr2 = new BufferAttribute( new Float32Array( 9 ), 3 ); attr2.copyAt( 1, attr, 2 ); attr2.copyAt( 0, attr, 1 ); attr2.copyAt( 2, attr, 0 ); - var i = attr.array; - var i2 = attr2.array; // should be [4, 5, 6, 7, 8, 9, 1, 2, 3] + const i = attr.array; + const i2 = attr2.array; // should be [4, 5, 6, 7, 8, 9, 1, 2, 3] assert.ok( i2[ 0 ] === i[ 3 ] && i2[ 1 ] === i[ 4 ] && i2[ 2 ] === i[ 5 ], 'chunck copied to correct place' ); assert.ok( i2[ 3 ] === i[ 6 ] && i2[ 4 ] === i[ 7 ] && i2[ 5 ] === i[ 8 ], 'chunck copied to correct place' ); @@ -81,8 +157,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'copyArray', ( assert ) => { - var f32a = new Float32Array( [ 5, 6, 7, 8 ] ); - var a = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2, false ); + const f32a = new Float32Array( [ 5, 6, 7, 8 ] ); + const a = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2, false ); a.copyArray( f32a ); @@ -90,11 +166,39 @@ export default QUnit.module( 'Core', () => { } ); + QUnit.todo( 'applyMatrix3', ( assert ) => { + + // applyMatrix3( m ) + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'applyMatrix4', ( assert ) => { + + // applyMatrix4( m ) + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'applyNormalMatrix', ( assert ) => { + + // applyNormalMatrix( m ) + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'transformDirection', ( assert ) => { + + // transformDirection( m ) + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'set', ( assert ) => { - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var a = new BufferAttribute( f32a, 2, false ); - var expected = new Float32Array( [ 9, 2, 8, 4 ] ); + const f32a = new Float32Array( [ 1, 2, 3, 4 ] ); + const a = new BufferAttribute( f32a, 2, false ); + const expected = new Float32Array( [ 9, 2, 8, 4 ] ); a.set( [ 9 ] ); a.set( [ 8 ], 2 ); @@ -105,9 +209,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'set[X, Y, Z, W, XYZ, XYZW]/get[X, Y, Z, W]', ( assert ) => { - var f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); - var a = new BufferAttribute( f32a, 4, false ); - var expected = new Float32Array( [ 1, 2, - 3, - 4, - 5, - 6, 7, 8 ] ); + const f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + const a = new BufferAttribute( f32a, 4, false ); + const expected = new Float32Array( [ 1, 2, - 3, - 4, - 5, - 6, 7, 8 ] ); a.setX( 1, a.getX( 1 ) * - 1 ); a.setY( 1, a.getY( 1 ) * - 1 ); @@ -120,9 +224,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setXY', ( assert ) => { - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var a = new BufferAttribute( f32a, 2, false ); - var expected = new Float32Array( [ - 1, - 2, 3, 4 ] ); + const f32a = new Float32Array( [ 1, 2, 3, 4 ] ); + const a = new BufferAttribute( f32a, 2, false ); + const expected = new Float32Array( [ - 1, - 2, 3, 4 ] ); a.setXY( 0, - 1, - 2 ); @@ -132,9 +236,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setXYZ', ( assert ) => { - var f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ); - var a = new BufferAttribute( f32a, 3, false ); - var expected = new Float32Array( [ 1, 2, 3, - 4, - 5, - 6 ] ); + const f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ); + const a = new BufferAttribute( f32a, 3, false ); + const expected = new Float32Array( [ 1, 2, 3, - 4, - 5, - 6 ] ); a.setXYZ( 1, - 4, - 5, - 6 ); @@ -144,9 +248,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setXYZW', ( assert ) => { - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var a = new BufferAttribute( f32a, 4, false ); - var expected = new Float32Array( [ - 1, - 2, - 3, - 4 ] ); + const f32a = new Float32Array( [ 1, 2, 3, 4 ] ); + const a = new BufferAttribute( f32a, 4, false ); + const expected = new Float32Array( [ - 1, - 2, - 3, - 4 ] ); a.setXYZW( 0, - 1, - 2, - 3, - 4 ); @@ -156,8 +260,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'onUpload', ( assert ) => { - var a = new BufferAttribute(); - var func = function () { }; + const a = new BufferAttribute(); + const func = function () { }; a.onUpload( func ); @@ -167,11 +271,11 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'clone', ( assert ) => { - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 0.12, - 12 ] ), 2 ); - var attrCopy = attr.clone(); + const attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 0.12, - 12 ] ), 2 ); + const attrCopy = attr.clone(); assert.ok( attr.array.length === attrCopy.array.length, 'attribute was cloned' ); - for ( var i = 0; i < attr.array.length; i ++ ) { + for ( let i = 0; i < attr.array.length; i ++ ) { assert.ok( attr.array[ i ] === attrCopy.array[ i ], 'array item is equal' ); @@ -221,16 +325,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Int8BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Int8BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Int8BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Int8BufferAttribute(); + assert.ok( object, 'Can instantiate an Int8BufferAttribute.' ); } ); @@ -239,16 +348,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint8BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint8BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Uint8BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint8BufferAttribute(); + assert.ok( object, 'Can instantiate a Uint8BufferAttribute.' ); } ); @@ -257,16 +371,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint8ClampedBufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint8ClampedBufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Uint8ClampedBufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint8ClampedBufferAttribute(); + assert.ok( object, 'Can instantiate a Uint8ClampedBufferAttribute.' ); } ); @@ -275,16 +394,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Int16BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Int16BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Int16BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Int16BufferAttribute(); + assert.ok( object, 'Can instantiate an Int16BufferAttribute.' ); } ); @@ -293,16 +417,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint16BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint16BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Uint16BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint16BufferAttribute(); + assert.ok( object, 'Can instantiate a Uint16BufferAttribute.' ); } ); @@ -311,16 +440,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Int32BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Int32BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Int32BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Int32BufferAttribute(); + assert.ok( object, 'Can instantiate an Int32BufferAttribute.' ); } ); @@ -329,16 +463,121 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Uint32BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint32BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Uint32BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Uint32BufferAttribute(); + assert.ok( object, 'Can instantiate a Uint32BufferAttribute.' ); + + } ); + + } ); + + QUnit.module( 'Float16BufferAttribute', () => { + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new Float16BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Float16BufferAttribute extends from BufferAttribute' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + const object = new Float16BufferAttribute(); + assert.ok( object, 'Can instantiate a Float16BufferAttribute.' ); + + } ); + + const toHalfFloatArray = ( f32Array ) => { + + const f16Array = new Uint16Array( f32Array.length ); + for ( let i = 0, n = f32Array.length; i < n; ++i ) { + + f16Array[ i ] = toHalfFloat( f32Array[ i ] ); + + } + + return f16Array; + + }; + + const fromHalfFloatArray = ( f16Array ) => { + + const f32Array = new Float32Array( f16Array.length ); + for ( let i = 0, n = f16Array.length; i < n; ++i ) { + + f32Array[ i ] = fromHalfFloat( f16Array[ i ] ); + + } + + return f32Array; + + }; + + QUnit.test( 'set[X, Y, Z, W, XYZ, XYZW]/get[X, Y, Z, W]', ( assert ) => { + + const f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + const a = new Float16BufferAttribute( toHalfFloatArray( f32a ), 4, false ); + const expected = new Float32Array( [ 1, 2, - 3, - 4, - 5, - 6, 7, 8 ] ); + + a.setX( 1, a.getX( 1 ) * - 1 ); + a.setY( 1, a.getY( 1 ) * - 1 ); + a.setZ( 0, a.getZ( 0 ) * - 1 ); + a.setW( 0, a.getW( 0 ) * - 1 ); + + assert.deepEqual( fromHalfFloatArray( a.array ), expected, 'Check all set* calls set the correct values' ); + + } ); + + QUnit.test( 'setXY', ( assert ) => { + + const f32a = new Float32Array( [ 1, 2, 3, 4 ] ); + const a = new Float16BufferAttribute( toHalfFloatArray( f32a ), 2, false ); + const expected = new Float32Array( [ - 1, - 2, 3, 4 ] ); + + a.setXY( 0, - 1, - 2 ); + + assert.deepEqual( fromHalfFloatArray( a.array ), expected, 'Check for the correct values' ); + + } ); + + QUnit.test( 'setXYZ', ( assert ) => { + + const f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ); + const a = new Float16BufferAttribute( toHalfFloatArray( f32a ), 3, false ); + const expected = new Float32Array( [ 1, 2, 3, - 4, - 5, - 6 ] ); + + a.setXYZ( 1, - 4, - 5, - 6 ); + + assert.deepEqual( fromHalfFloatArray( a.array ), expected, 'Check for the correct values' ); + + } ); + + QUnit.test( 'setXYZW', ( assert ) => { + + const f32a = new Float32Array( [ 1, 2, 3, 4 ] ); + const a = new Float16BufferAttribute( toHalfFloatArray( f32a ), 4, false ); + const expected = new Float32Array( [ - 1, - 2, - 3, - 4 ] ); + + a.setXYZW( 0, - 1, - 2, - 3, - 4 ); + + assert.deepEqual( fromHalfFloatArray( a.array ), expected, 'Check for the correct values' ); } ); @@ -347,16 +586,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Float32BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Float32BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Float32BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Float32BufferAttribute(); + assert.ok( object, 'Can instantiate a Float32BufferAttribute.' ); } ); @@ -365,16 +609,21 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Float64BufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Float64BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'Float64BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Float64BufferAttribute(); + assert.ok( object, 'Can instantiate a Float64BufferAttribute.' ); } ); diff --git a/test/unit/src/core/BufferGeometry.tests.js b/test/unit/src/core/BufferGeometry.tests.js index b31ff7ed407482..c9cb0a02195838 100644 --- a/test/unit/src/core/BufferGeometry.tests.js +++ b/test/unit/src/core/BufferGeometry.tests.js @@ -1,8 +1,10 @@ /* global QUnit */ import { BufferGeometry } from '../../../../src/core/BufferGeometry.js'; + import { BufferAttribute, + Float16BufferAttribute, Uint16BufferAttribute, Uint32BufferAttribute } from '../../../../src/core/BufferAttribute.js'; @@ -11,8 +13,10 @@ import { Matrix4 } from '../../../../src/math/Matrix4.js'; import { Quaternion } from '../../../../src/math/Quaternion.js'; import { Sphere } from '../../../../src/math/Sphere.js'; import { x, y, z } from '../../utils/math-constants.js'; +import { EventDispatcher } from '../../../../src/core/EventDispatcher.js'; +import { toHalfFloat } from '../../../../src/extras/DataUtils.js'; -var DegToRad = Math.PI / 180; +const DegToRad = Math.PI / 180; function bufferAttributeEquals( a, b, tolerance ) { @@ -24,9 +28,9 @@ function bufferAttributeEquals( a, b, tolerance ) { } - for ( var i = 0, il = a.count * a.itemSize; i < il; i ++ ) { + for ( let i = 0, il = a.count * a.itemSize; i < il; i ++ ) { - var delta = a[ i ] - b[ i ]; + const delta = a[ i ] - b[ i ]; if ( delta > tolerance ) { return false; @@ -41,7 +45,7 @@ function bufferAttributeEquals( a, b, tolerance ) { function getBBForVertices( vertices ) { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); geometry.computeBoundingBox(); @@ -52,7 +56,7 @@ function getBBForVertices( vertices ) { function getBSForVertices( vertices ) { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); geometry.computeBoundingSphere(); @@ -63,7 +67,7 @@ function getBSForVertices( vertices ) { function getNormalsForVertices( vertices, assert ) { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); @@ -80,32 +84,124 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'BufferGeometry', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new BufferGeometry(); + assert.strictEqual( + object instanceof EventDispatcher, true, + 'BufferGeometry extends from EventDispatcher' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new BufferGeometry(); + assert.ok( object, 'Can instantiate a BufferGeometry.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'id', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'uuid', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'name', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isBufferGeometry', ( assert ) => { + QUnit.test( 'type', ( assert ) => { + + const object = new BufferGeometry(); + assert.ok( + object.type === 'BufferGeometry', + 'BufferGeometry.type should be BufferGeometry' + ); + + } ); + + QUnit.todo( 'index', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + QUnit.todo( 'attributes', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'morphAttributes', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'morphTargetsRelative', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'groups', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'boundingBox', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'boundingSphere', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'drawRange', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'userData', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.test( 'isBufferGeometry', ( assert ) => { + + const object = new BufferGeometry(); + assert.ok( + object.isBufferGeometry, + 'BufferGeometry.isBufferGeometry should be true' + ); + + } ); + QUnit.test( 'setIndex/getIndex', ( assert ) => { - var a = new BufferGeometry(); - var uint16 = [ 1, 2, 3 ]; - var uint32 = [ 65535, 65536, 65537 ]; - var str = 'foo'; + const a = new BufferGeometry(); + const uint16 = [ 1, 2, 3 ]; + const uint32 = [ 65535, 65536, 65537 ]; + const str = 'foo'; a.setIndex( uint16 ); assert.ok( a.getIndex() instanceof Uint16BufferAttribute, 'Index has the right type' ); @@ -128,8 +224,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'set / delete Attribute', ( assert ) => { - var geometry = new BufferGeometry(); - var attributeName = 'position'; + const geometry = new BufferGeometry(); + const attributeName = 'position'; assert.ok( geometry.attributes[ attributeName ] === undefined, 'no attribute defined' ); @@ -145,8 +241,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'addGroup', ( assert ) => { - var a = new BufferGeometry(); - var expected = [ + const a = new BufferGeometry(); + const expected = [ { start: 0, count: 1, @@ -176,7 +272,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setDrawRange', ( assert ) => { - var a = new BufferGeometry(); + const a = new BufferGeometry(); a.setDrawRange( 1.0, 7 ); @@ -189,10 +285,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( 6 ), 3 ) ); - var matrix = new Matrix4().set( + const matrix = new Matrix4().set( 1, 0, 0, 1.5, 0, 1, 0, - 2, 0, 0, 1, 3, @@ -200,8 +296,8 @@ export default QUnit.module( 'Core', () => { ); geometry.applyMatrix4( matrix ); - var position = geometry.attributes.position.array; - var m = matrix.elements; + const position = geometry.attributes.position.array; + const m = matrix.elements; assert.ok( position[ 0 ] === m[ 12 ] && position[ 1 ] === m[ 13 ] && position[ 2 ] === m[ 14 ], 'position was extracted from matrix' ); assert.ok( position[ 3 ] === m[ 12 ] && position[ 4 ] === m[ 13 ] && position[ 5 ] === m[ 14 ], 'position was extracted from matrix twice' ); assert.ok( geometry.attributes.position.version === 1, 'version was increased during update' ); @@ -210,13 +306,13 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'applyQuaternion', ( assert ) => { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - var q = new Quaternion( 0.5, 0.5, 0.5, 0.5 ); + const q = new Quaternion( 0.5, 0.5, 0.5, 0.5 ); geometry.applyQuaternion( q ); - var pos = geometry.attributes.position.array; + const pos = geometry.attributes.position.array; // geometry was rotated around the (1, 1, 1) axis. assert.ok( pos[ 0 ] === 3 && pos[ 1 ] === 1 && pos[ 2 ] === 2 && @@ -226,10 +322,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'rotateX/Y/Z', ( assert ) => { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - var pos = geometry.attributes.position.array; + const pos = geometry.attributes.position.array; geometry.rotateX( 180 * DegToRad ); @@ -253,10 +349,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'translate', ( assert ) => { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - var pos = geometry.attributes.position.array; + const pos = geometry.attributes.position.array; geometry.translate( 10, 20, 30 ); @@ -267,10 +363,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'scale', ( assert ) => { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ - 1, - 1, - 1, 2, 2, 2 ] ), 3 ) ); - var pos = geometry.attributes.position.array; + const pos = geometry.attributes.position.array; geometry.scale( 1, 2, 3 ); @@ -281,8 +377,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'lookAt', ( assert ) => { - var a = new BufferGeometry(); - var vertices = new Float32Array( [ + const a = new BufferGeometry(); + const vertices = new Float32Array( [ - 1.0, - 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, @@ -293,8 +389,8 @@ export default QUnit.module( 'Core', () => { ] ); a.setAttribute( 'position', new BufferAttribute( vertices, 3 ) ); - var sqrt = Math.sqrt( 2 ); - var expected = new Float32Array( [ + const sqrt = Math.sqrt( 2 ); + const expected = new Float32Array( [ 1, 0, - sqrt, - 1, 0, - sqrt, - 1, sqrt, 0, @@ -312,7 +408,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'center', ( assert ) => { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( [ - 1, - 1, - 1, 1, 1, 1, @@ -321,7 +417,7 @@ export default QUnit.module( 'Core', () => { geometry.center(); - var pos = geometry.attributes.position.array; + const pos = geometry.attributes.position.array; // the boundingBox should go from (-1, -1, -1) to (4, 4, 4) so it has a size of (5, 5, 5) // after centering it the vertices should be placed between (-2.5, -2.5, -2.5) and (2.5, 2.5, 2.5) @@ -331,14 +427,20 @@ export default QUnit.module( 'Core', () => { } ); + QUnit.todo( 'setFromPoints', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'computeBoundingBox', ( assert ) => { - var bb = getBBForVertices( [ - 1, - 2, - 3, 13, - 2, - 3.5, - 1, - 20, 0, - 4, 5, 6 ] ); + let bb = getBBForVertices( [ - 1, - 2, - 3, 13, - 2, - 3.5, - 1, - 20, 0, - 4, 5, 6 ] ); assert.ok( bb.min.x === - 4 && bb.min.y === - 20 && bb.min.z === - 3.5, 'min values are set correctly' ); assert.ok( bb.max.x === 13 && bb.max.y === 5 && bb.max.z === 6, 'max values are set correctly' ); - var bb = getBBForVertices( [ - 1, - 1, - 1 ] ); + bb = getBBForVertices( [ - 1, - 1, - 1 ] ); assert.ok( bb.min.x === bb.max.x && bb.min.y === bb.max.y && bb.min.z === bb.max.z, 'since there is only one vertex, max and min are equal' ); assert.ok( bb.min.x === - 1 && bb.min.y === - 1 && bb.min.z === - 1, 'since there is only one vertex, min and max are this vertex' ); @@ -347,23 +449,76 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'computeBoundingSphere', ( assert ) => { - var bs = getBSForVertices( [ - 10, 0, 0, 10, 0, 0 ] ); + let bs = getBSForVertices( [ - 10, 0, 0, 10, 0, 0 ] ); + + assert.ok( bs.radius === 10, 'radius is equal to deltaMinMax / 2' ); + assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, 'bounding sphere is at ( 0, 0, 0 )' ); + + bs = getBSForVertices( [ - 5, 11, - 3, 5, - 11, 3 ] ); + const radius = new Vector3( 5, 11, 3 ).length(); + + assert.ok( bs.radius === radius, 'radius is equal to directionLength' ); + assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, 'bounding sphere is at ( 0, 0, 0 )' ); + + } ); + + const toHalfFloatArray = ( f32Array ) => { + const f16Array = new Uint16Array( f32Array.length ); + for ( let i = 0, n = f32Array.length; i < n; ++i ) { + f16Array[ i ] = toHalfFloat( f32Array[ i ] ); + } + return f16Array; + }; + + QUnit.test( 'computeBoundingBox - Float16', ( assert ) => { + const vertices = [ - 1, - 2, - 3, 13, - 2, - 3.5, - 1, - 20, 0, - 4, 5, 6 ]; + const geometry = new BufferGeometry(); + + geometry.setAttribute( 'position', new Float16BufferAttribute( toHalfFloatArray( vertices ), 3 ) ); + geometry.computeBoundingBox(); + + let bb = geometry.boundingBox; + + assert.ok( bb.min.x === - 4 && bb.min.y === - 20 && bb.min.z === - 3.5, 'min values are set correctly' ); + assert.ok( bb.max.x === 13 && bb.max.y === 5 && bb.max.z === 6, 'max values are set correctly' ); + + bb = getBBForVertices( [ - 1, - 1, - 1 ] ); + + assert.ok( bb.min.x === bb.max.x && bb.min.y === bb.max.y && bb.min.z === bb.max.z, 'since there is only one vertex, max and min are equal' ); + assert.ok( bb.min.x === - 1 && bb.min.y === - 1 && bb.min.z === - 1, 'since there is only one vertex, min and max are this vertex' ); + + } ); + + QUnit.test( 'computeBoundingSphere - Float16', ( assert ) => { + const vertices = [ - 10, 0, 0, 10, 0, 0 ]; + const geometry = new BufferGeometry(); + + geometry.setAttribute( 'position', new Float16BufferAttribute( toHalfFloatArray( vertices ), 3 ) ); + geometry.computeBoundingSphere(); + + let bs = geometry.boundingSphere; assert.ok( bs.radius === 10, 'radius is equal to deltaMinMax / 2' ); assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, 'bounding sphere is at ( 0, 0, 0 )' ); - var bs = getBSForVertices( [ - 5, 11, - 3, 5, - 11, 3 ] ); - var radius = new Vector3( 5, 11, 3 ).length(); + bs = getBSForVertices( [ - 5, 11, - 3, 5, - 11, 3 ] ); + const radius = new Vector3( 5, 11, 3 ).length(); assert.ok( bs.radius === radius, 'radius is equal to directionLength' ); assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, 'bounding sphere is at ( 0, 0, 0 )' ); } ); + QUnit.todo( 'computeTangents', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'computeVertexNormals', ( assert ) => { // get normals for a counter clockwise created triangle - var normals = getNormalsForVertices( [ - 1, 0, 0, 1, 0, 0, 0, 1, 0 ], assert ); + let normals = getNormalsForVertices( [ - 1, 0, 0, 1, 0, 0, 0, 1, 0 ], assert ); assert.ok( normals[ 0 ] === 0 && normals[ 1 ] === 0 && normals[ 2 ] === 1, 'first normal is pointing to screen since the the triangle was created counter clockwise' ); @@ -375,7 +530,7 @@ export default QUnit.module( 'Core', () => { 'third normal is pointing to screen since the the triangle was created counter clockwise' ); // get normals for a clockwise created triangle - var normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0, 0, 1, 0 ], assert ); + normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0, 0, 1, 0 ], assert ); assert.ok( normals[ 0 ] === 0 && normals[ 1 ] === 0 && normals[ 2 ] === - 1, 'first normal is pointing to screen since the the triangle was created clockwise' ); @@ -386,7 +541,7 @@ export default QUnit.module( 'Core', () => { assert.ok( normals[ 6 ] === 0 && normals[ 7 ] === 0 && normals[ 8 ] === - 1, 'third normal is pointing to screen since the the triangle was created clockwise' ); - var normals = getNormalsForVertices( [ 0, 0, 1, 0, 0, - 1, 1, 1, 0 ], assert ); + normals = getNormalsForVertices( [ 0, 0, 1, 0, 0, - 1, 1, 1, 0 ], assert ); // the triangle is rotated by 45 degrees to the right so the normals of the three vertices // should point to (1, -1, 0).normalized(). The simplest solution is to check against a normalized @@ -394,37 +549,38 @@ export default QUnit.module( 'Core', () => { // valid technique is to create a vector which stands in 90 degrees to the normals and calculate the // dot product which is the cos of the angle between them. This should be < floating calculation error // which can be taken from Number.EPSILON - var direction = new Vector3( 1, 1, 0 ).normalize(); // a vector which should have 90 degrees difference to normals - var difference = direction.dot( new Vector3( normals[ 0 ], normals[ 1 ], normals[ 2 ] ) ); + const direction = new Vector3( 1, 1, 0 ).normalize(); // a vector which should have 90 degrees difference to normals + const difference = direction.dot( new Vector3( normals[ 0 ], normals[ 1 ], normals[ 2 ] ) ); assert.ok( difference < Number.EPSILON, 'normal is equal to reference vector' ); // get normals for a line should be NAN because you need min a triangle to calculate normals - var normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0 ], assert ); - for ( var i = 0; i < normals.length; i ++ ) { + normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0 ], assert ); + for ( let i = 0; i < normals.length; i ++ ) { assert.ok( ! normals[ i ], 'normals can\'t be calculated which is good' ); } } ); + QUnit.test( 'computeVertexNormals (indexed)', ( assert ) => { - var sqrt = 0.5 * Math.sqrt( 2 ); - var normal = new BufferAttribute( new Float32Array( [ + const sqrt = 0.5 * Math.sqrt( 2 ); + const normal = new BufferAttribute( new Float32Array( [ - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, sqrt, sqrt, 0, sqrt, sqrt, 0, sqrt, sqrt, 0, - 1, 0, 0 ] ), 3 ); - var position = new BufferAttribute( new Float32Array( [ + const position = new BufferAttribute( new Float32Array( [ 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, - 0.5, 0.5, 0.5, - 0.5, - 0.5, - 0.5, 0.5, - 0.5, - 0.5, 0.5, 0.5, - 0.5, - 0.5, - 0.5 ] ), 3 ); - var index = new BufferAttribute( new Uint16Array( [ + const index = new BufferAttribute( new Uint16Array( [ 0, 2, 1, 2, 3, 1, 4, 6, 5, 6, 7, 5 ] ), 1 ); - var a = new BufferGeometry(); + let a = new BufferGeometry(); a.setAttribute( 'position', position ); a.computeVertexNormals(); assert.ok( @@ -440,7 +596,7 @@ export default QUnit.module( 'Core', () => { ); // indexed geometry - var a = new BufferGeometry(); + a = new BufferGeometry(); a.setAttribute( 'position', position ); a.setIndex( index ); a.computeVertexNormals(); @@ -456,12 +612,12 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'toNonIndexed', ( assert ) => { - var geometry = new BufferGeometry(); - var vertices = new Float32Array( [ + const geometry = new BufferGeometry(); + const vertices = new Float32Array( [ 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, - 0.5, 0.5, 0.5, - 0.5, - 0.5 ] ); - var index = new BufferAttribute( new Uint16Array( [ 0, 2, 1, 2, 3, 1 ] ) ); - var expected = new Float32Array( [ + const index = new BufferAttribute( new Uint16Array( [ 0, 2, 1, 2, 3, 1 ] ) ); + const expected = new Float32Array( [ 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, - 0.5, 0.5, 0.5, - 0.5, - 0.5, 0.5, 0.5, - 0.5 ] ); @@ -469,7 +625,7 @@ export default QUnit.module( 'Core', () => { geometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) ); geometry.setIndex( index ); - var nonIndexed = geometry.toNonIndexed(); + const nonIndexed = geometry.toNonIndexed(); assert.deepEqual( nonIndexed.getAttribute( 'position' ).array, expected, 'Expected vertices' ); @@ -477,20 +633,20 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'toJSON', ( assert ) => { - var index = new BufferAttribute( new Uint16Array( [ 0, 1, 2, 3 ] ), 1 ); - var attribute1 = new BufferAttribute( new Uint16Array( [ 1, 3, 5, 7 ] ), 1 ); + const index = new BufferAttribute( new Uint16Array( [ 0, 1, 2, 3 ] ), 1 ); + const attribute1 = new BufferAttribute( new Uint16Array( [ 1, 3, 5, 7 ] ), 1 ); attribute1.name = 'attribute1'; - var a = new BufferGeometry(); + const a = new BufferGeometry(); a.name = 'JSONQUnit.test'; // a.parameters = { "placeholder": 0 }; a.setAttribute( 'attribute1', attribute1 ); a.setIndex( index ); a.addGroup( 0, 1, 2 ); a.boundingSphere = new Sphere( new Vector3( x, y, z ), 0.5 ); - var j = a.toJSON(); - var gold = { + let j = a.toJSON(); + const gold = { 'metadata': { - 'version': 4.5, + 'version': 4.6, 'type': 'BufferGeometry', 'generator': 'BufferGeometry.toJSON' }, @@ -548,14 +704,14 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'clone', ( assert ) => { - var a = new BufferGeometry(); + const a = new BufferGeometry(); a.setAttribute( 'attribute1', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); a.setAttribute( 'attribute2', new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); a.addGroup( 0, 1, 2 ); a.computeBoundingBox(); a.computeBoundingSphere(); a.setDrawRange( 0, 1 ); - var b = a.clone(); + const b = a.clone(); assert.notEqual( a, b, 'A new object was created' ); assert.notEqual( a.id, b.id, 'New object has a different GUID' ); @@ -585,20 +741,20 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'copy', ( assert ) => { - var geometry = new BufferGeometry(); + const geometry = new BufferGeometry(); geometry.setAttribute( 'attrName', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); geometry.setAttribute( 'attrName2', new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); - var copy = new BufferGeometry().copy( geometry ); + const copy = new BufferGeometry().copy( geometry ); assert.ok( copy !== geometry && geometry.id !== copy.id, 'new object was created' ); Object.keys( geometry.attributes ).forEach( function ( key ) { - var attribute = geometry.attributes[ key ]; + const attribute = geometry.attributes[ key ]; assert.ok( attribute !== undefined, 'all attributes where copied' ); - for ( var i = 0; i < attribute.array.length; i ++ ) { + for ( let i = 0; i < attribute.array.length; i ++ ) { assert.ok( attribute.array[ i ] === copy.attributes[ key ].array[ i ], 'values of the attribute are equal' ); @@ -608,9 +764,12 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new BufferGeometry(); + object.dispose(); } ); diff --git a/test/unit/src/core/Clock.tests.js b/test/unit/src/core/Clock.tests.js index 53f6e5358207e4..46bfc41c49ae6b 100644 --- a/test/unit/src/core/Clock.tests.js +++ b/test/unit/src/core/Clock.tests.js @@ -30,13 +30,50 @@ export default QUnit.module( 'Core', () => { } // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + // no params + const object = new Clock(); + assert.ok( object, 'Can instantiate a Clock.' ); + + // autostart + const object_all = new Clock( false ); + assert.ok( object_all, 'Can instantiate a Clock with autostart.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'autoStart', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'startTime', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'oldTime', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'elapsedTime', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'running', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + // PUBLIC QUnit.todo( 'start', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -73,7 +110,7 @@ export default QUnit.module( 'Core', () => { mockPerformance(); - var clock = new Clock( false ); + const clock = new Clock( false ); clock.start(); diff --git a/test/unit/src/core/EventDispatcher.tests.js b/test/unit/src/core/EventDispatcher.tests.js index a464336ec6da07..a9a66a6385f65c 100644 --- a/test/unit/src/core/EventDispatcher.tests.js +++ b/test/unit/src/core/EventDispatcher.tests.js @@ -7,18 +7,19 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'EventDispatcher', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new EventDispatcher(); + assert.ok( object, 'Can instantiate an EventDispatcher.' ); } ); - // PUBLIC STUFF + // PUBLIC QUnit.test( 'addEventListener', ( assert ) => { - var eventDispatcher = new EventDispatcher(); + const eventDispatcher = new EventDispatcher(); - var listener = {}; + const listener = {}; eventDispatcher.addEventListener( 'anyType', listener ); assert.ok( eventDispatcher._listeners.anyType.length === 1, 'listener with unknown type was added' ); @@ -33,9 +34,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'hasEventListener', ( assert ) => { - var eventDispatcher = new EventDispatcher(); + const eventDispatcher = new EventDispatcher(); - var listener = {}; + const listener = {}; eventDispatcher.addEventListener( 'anyType', listener ); assert.ok( eventDispatcher.hasEventListener( 'anyType', listener ), 'listener was found' ); @@ -45,9 +46,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'removeEventListener', ( assert ) => { - var eventDispatcher = new EventDispatcher(); + const eventDispatcher = new EventDispatcher(); - var listener = {}; + const listener = {}; assert.ok( eventDispatcher._listeners === undefined, 'there are no listeners by default' ); @@ -68,10 +69,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'dispatchEvent', ( assert ) => { - var eventDispatcher = new EventDispatcher(); + const eventDispatcher = new EventDispatcher(); - var callCount = 0; - var listener = function () { + let callCount = 0; + const listener = function () { callCount ++; diff --git a/test/unit/src/core/GLBufferAttribute.tests.js b/test/unit/src/core/GLBufferAttribute.tests.js new file mode 100644 index 00000000000000..95213ef18581e0 --- /dev/null +++ b/test/unit/src/core/GLBufferAttribute.tests.js @@ -0,0 +1,104 @@ +/* global QUnit */ + +import { GLBufferAttribute } from '../../../../src/core/GLBufferAttribute.js'; + +export default QUnit.module( 'Core', () => { + + QUnit.module( 'GLBufferAttribute', () => { + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + const object = new GLBufferAttribute(); + assert.ok( object, 'Can instantiate a GLBufferAttribute.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'name', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'buffer', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'type', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'itemSize', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'elementSize', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'count', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'version', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'needsUpdate', ( assert ) => { + + // set needsUpdate( value ) + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.test( 'isGLBufferAttribute', ( assert ) => { + + const object = new GLBufferAttribute(); + assert.ok( + object.isGLBufferAttribute, + 'GLBufferAttribute.isGLBufferAttribute should be true' + ); + + } ); + + QUnit.todo( 'setBuffer', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'setType', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'setItemSize', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'setCount', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + } ); + +} ); diff --git a/test/unit/src/core/InstancedBufferAttribute.tests.js b/test/unit/src/core/InstancedBufferAttribute.tests.js index 18c0dcc78bf7b2..6bb3e5796a1bf2 100644 --- a/test/unit/src/core/InstancedBufferAttribute.tests.js +++ b/test/unit/src/core/InstancedBufferAttribute.tests.js @@ -2,41 +2,69 @@ import { InstancedBufferAttribute } from '../../../../src/core/InstancedBufferAttribute.js'; +import { BufferAttribute } from '../../../../src/core/BufferAttribute.js'; + export default QUnit.module( 'Core', () => { QUnit.module( 'InstancedBufferAttribute', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new BufferAttribute(); + assert.strictEqual( + object instanceof BufferAttribute, true, + 'BufferAttribute extends from BufferAttribute' + ); } ); // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2 ); - assert.ok( instance.meshPerAttribute === 1, 'ok' ); + // array, itemSize + let instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2 ); + assert.ok( instance.meshPerAttribute === 1, 'Can instantiate an InstancedBufferGeometry.' ); + + // array, itemSize, normalized, meshPerAttribute + instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2, false, 123 ); + assert.ok( + instance.meshPerAttribute === 123, + 'Can instantiate an InstancedBufferGeometry with array, itemSize, normalized, and meshPerAttribute.' + ); + + } ); + + // PROPERTIES + QUnit.todo( 'meshPerAttribute', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.test( 'isInstancedBufferAttribute', ( assert ) => { - var instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2, false, 123 ); - assert.ok( instance.meshPerAttribute === 123, 'ok' ); + const object = new InstancedBufferAttribute(); + assert.ok( + object.isInstancedBufferAttribute, + 'InstancedBufferAttribute.isInstancedBufferAttribute should be true' + ); } ); - // PUBLIC STUFF QUnit.test( 'copy', ( assert ) => { - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InstancedBufferAttribute( array, 2, true, 123 ); - var copiedInstance = instance.copy( instance ); + const array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); + const instance = new InstancedBufferAttribute( array, 2, true, 123 ); + const copiedInstance = instance.copy( instance ); assert.ok( copiedInstance instanceof InstancedBufferAttribute, 'the clone has the correct type' ); assert.ok( copiedInstance.itemSize === 2, 'itemSize was copied' ); assert.ok( copiedInstance.normalized === true, 'normalized was copied' ); assert.ok( copiedInstance.meshPerAttribute === 123, 'meshPerAttribute was copied' ); - for ( var i = 0; i < array.length; i ++ ) { + for ( let i = 0; i < array.length; i ++ ) { assert.ok( copiedInstance.array[ i ] === array[ i ], 'array was copied' ); @@ -44,6 +72,12 @@ export default QUnit.module( 'Core', () => { } ); + QUnit.todo( 'toJSON', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + } ); } ); diff --git a/test/unit/src/core/InstancedBufferGeometry.tests.js b/test/unit/src/core/InstancedBufferGeometry.tests.js index 49250cfe699878..ab1a630f9a17bd 100644 --- a/test/unit/src/core/InstancedBufferGeometry.tests.js +++ b/test/unit/src/core/InstancedBufferGeometry.tests.js @@ -1,6 +1,8 @@ /* global QUnit */ import { InstancedBufferGeometry } from '../../../../src/core/InstancedBufferGeometry.js'; + +import { BufferGeometry } from '../../../../src/core/BufferGeometry.js'; import { BufferAttribute } from '../../../../src/core/BufferAttribute.js'; export default QUnit.module( 'Core', () => { @@ -22,29 +24,61 @@ export default QUnit.module( 'Core', () => { } // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new InstancedBufferGeometry(); + assert.strictEqual( + object instanceof BufferGeometry, true, + 'InstancedBufferGeometry extends from BufferGeometry' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new InstancedBufferGeometry(); + assert.ok( object, 'Can instantiate an InstancedBufferGeometry.' ); + + } ); + + // PROPERTIES + QUnit.test( 'type', ( assert ) => { + + const object = new InstancedBufferGeometry(); + assert.ok( + object.type === 'InstancedBufferGeometry', + 'InstancedBufferGeometry.type should be InstancedBufferGeometry' + ); + + } ); + + QUnit.todo( 'instanceCount', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + // PUBLIC + QUnit.test( 'isInstancedBufferGeometry', ( assert ) => { + + const object = new InstancedBufferGeometry(); + assert.ok( + object.isInstancedBufferGeometry, + 'InstancedBufferGeometry.isInstancedBufferGeometry should be true' + ); + + } ); + QUnit.test( 'copy', ( assert ) => { - var instanceMock1 = {}; - var instanceMock2 = {}; - var indexMock = createClonableMock(); - var defaultAttribute1 = new BufferAttribute( new Float32Array( [ 1 ] ) ); - var defaultAttribute2 = new BufferAttribute( new Float32Array( [ 2 ] ) ); + const instanceMock1 = {}; + const instanceMock2 = {}; + const indexMock = createClonableMock(); + const defaultAttribute1 = new BufferAttribute( new Float32Array( [ 1 ] ) ); + const defaultAttribute2 = new BufferAttribute( new Float32Array( [ 2 ] ) ); - var instance = new InstancedBufferGeometry(); + const instance = new InstancedBufferGeometry(); instance.addGroup( 0, 10, instanceMock1 ); instance.addGroup( 10, 5, instanceMock2 ); @@ -52,7 +86,7 @@ export default QUnit.module( 'Core', () => { instance.setAttribute( 'defaultAttribute1', defaultAttribute1 ); instance.setAttribute( 'defaultAttribute2', defaultAttribute2 ); - var copiedInstance = new InstancedBufferGeometry().copy( instance ); + const copiedInstance = new InstancedBufferGeometry().copy( instance ); assert.ok( copiedInstance instanceof InstancedBufferGeometry, 'the clone has the correct type' ); @@ -73,7 +107,7 @@ export default QUnit.module( 'Core', () => { } ); - QUnit.todo( 'clone', ( assert ) => { + QUnit.todo( 'toJSON', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/core/InstancedInterleavedBuffer.tests.js b/test/unit/src/core/InstancedInterleavedBuffer.tests.js index 98948f215d37f7..5b9de616f4c981 100644 --- a/test/unit/src/core/InstancedInterleavedBuffer.tests.js +++ b/test/unit/src/core/InstancedInterleavedBuffer.tests.js @@ -2,44 +2,73 @@ import { InstancedInterleavedBuffer } from '../../../../src/core/InstancedInterleavedBuffer.js'; +import { InterleavedBuffer } from '../../../../src/core/InterleavedBuffer.js'; + export default QUnit.module( 'Core', () => { QUnit.module( 'InstancedInterleavedBuffer', () => { // INHERITANCE - QUnit.todo( 'Extending', ( assert ) => { + QUnit.test( 'Extending', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new InstancedInterleavedBuffer(); + assert.strictEqual( + object instanceof InterleavedBuffer, true, + 'InstancedInterleavedBuffer extends from InterleavedBuffer' + ); } ); // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InstancedInterleavedBuffer( array, 3 ); + const array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); + const instance = new InstancedInterleavedBuffer( array, 3 ); assert.ok( instance.meshPerAttribute === 1, 'ok' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isInstancedInterleavedBuffer', ( assert ) => { + // PROPERTIES + QUnit.todo( 'meshPerAttribute', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); + // PUBLIC + QUnit.test( 'isInstancedInterleavedBuffer', ( assert ) => { + + const object = new InstancedInterleavedBuffer(); + assert.ok( + object.isInstancedInterleavedBuffer, + 'InstancedInterleavedBuffer.isInstancedInterleavedBuffer should be true' + ); + + } ); + QUnit.test( 'copy', ( assert ) => { - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InstancedInterleavedBuffer( array, 3 ); - var copiedInstance = instance.copy( instance ); + const array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); + const instance = new InstancedInterleavedBuffer( array, 3 ); + const copiedInstance = instance.copy( instance ); assert.ok( copiedInstance.meshPerAttribute === 1, 'additional attribute was copied' ); } ); + QUnit.todo( 'clone', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'toJSON', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + } ); } ); diff --git a/test/unit/src/core/InterleavedBuffer.tests.js b/test/unit/src/core/InterleavedBuffer.tests.js index 011ede04c334fa..981222e786ad76 100644 --- a/test/unit/src/core/InterleavedBuffer.tests.js +++ b/test/unit/src/core/InterleavedBuffer.tests.js @@ -1,6 +1,7 @@ /* global QUnit */ import { InterleavedBuffer } from '../../../../src/core/InterleavedBuffer.js'; + import { DynamicDrawUsage } from '../../../../src/constants.js'; export default QUnit.module( 'Core', () => { @@ -11,7 +12,7 @@ export default QUnit.module( 'Core', () => { assert.ok( copiedInstance instanceof InterleavedBuffer, 'the clone has the correct type' ); - for ( var i = 0; i < instance.array.length; i ++ ) { + for ( let i = 0; i < instance.array.length; i ++ ) { assert.ok( copiedInstance.array[ i ] === instance.array[ i ], 'array was copied' ); @@ -23,33 +24,86 @@ export default QUnit.module( 'Core', () => { } // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new InterleavedBuffer(); + assert.ok( object, 'Can instantiate an InterleavedBuffer.' ); } ); // PROPERTIES - QUnit.test( 'needsUpdate', ( assert ) => { + QUnit.todo( 'array', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'stride', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'count', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'usage', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'updateRange', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); - var a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4 ] ), 2 ); + QUnit.todo( 'version', ( assert ) => { + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'uuid', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'onUploadCallback', ( assert ) => { + + // onUploadCallback() {} declared but used as property, refactor req + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.test( 'needsUpdate', ( assert ) => { + + const a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4 ] ), 2 ); a.needsUpdate = true; assert.strictEqual( a.version, 1, 'Check version increased' ); } ); - // PUBLIC STUFF - QUnit.todo( 'isInterleavedBuffer', ( assert ) => { + // PUBLIC + QUnit.test( 'isInterleavedBuffer', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new InterleavedBuffer(); + assert.ok( + object.isInterleavedBuffer, + 'InterleavedBuffer.isInterleavedBuffer should be true' + ); } ); QUnit.test( 'setUsage', ( assert ) => { - var instance = new InterleavedBuffer(); + const instance = new InterleavedBuffer(); instance.setUsage( DynamicDrawUsage ); assert.strictEqual( instance.usage, DynamicDrawUsage, 'Usage was set' ); @@ -58,8 +112,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'copy', ( assert ) => { - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InterleavedBuffer( array, 3 ); + const array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); + const instance = new InterleavedBuffer( array, 3 ); instance.setUsage( DynamicDrawUsage ); checkInstanceAgainstCopy( instance, instance.copy( instance ), assert ); @@ -68,9 +122,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'copyAt', ( assert ) => { - var a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); - var b = new InterleavedBuffer( new Float32Array( 9 ), 3 ); - var expected = new Float32Array( [ 4, 5, 6, 7, 8, 9, 1, 2, 3 ] ); + const a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); + const b = new InterleavedBuffer( new Float32Array( 9 ), 3 ); + const expected = new Float32Array( [ 4, 5, 6, 7, 8, 9, 1, 2, 3 ] ); b.copyAt( 1, a, 2 ); b.copyAt( 0, a, 1 ); @@ -82,17 +136,23 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'set', ( assert ) => { - var instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); + const instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); instance.set( [ 0, - 1 ] ); assert.ok( instance.array[ 0 ] === 0 && instance.array[ 1 ] === - 1, 'replace at first by default' ); } ); + QUnit.todo( 'clone', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'onUpload', ( assert ) => { - var a = new InterleavedBuffer(); - var func = function () { }; + const a = new InterleavedBuffer(); + const func = function () { }; a.onUpload( func ); @@ -100,10 +160,16 @@ export default QUnit.module( 'Core', () => { } ); + QUnit.todo( 'toJSON', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + // OTHERS QUnit.test( 'count', ( assert ) => { - var instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); + const instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); assert.equal( instance.count, 2, 'count is calculated via array length / stride' ); diff --git a/test/unit/src/core/InterleavedBufferAttribute.tests.js b/test/unit/src/core/InterleavedBufferAttribute.tests.js index 2a70ef0cb85d95..739d1c8ae9ae69 100644 --- a/test/unit/src/core/InterleavedBufferAttribute.tests.js +++ b/test/unit/src/core/InterleavedBufferAttribute.tests.js @@ -1,24 +1,56 @@ /* global QUnit */ -import { InterleavedBuffer } from '../../../../src/core/InterleavedBuffer.js'; import { InterleavedBufferAttribute } from '../../../../src/core/InterleavedBufferAttribute.js'; +import { InterleavedBuffer } from '../../../../src/core/InterleavedBuffer.js'; + export default QUnit.module( 'Core', () => { QUnit.module( 'InterleavedBufferAttribute', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new InterleavedBufferAttribute(); + assert.ok( object, 'Can instantiate an InterleavedBufferAttribute.' ); } ); // PROPERTIES + QUnit.todo( 'name', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'data', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'itemSize', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'offset', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'normalized', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'count', ( assert ) => { - var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - var instance = new InterleavedBufferAttribute( buffer, 2, 0 ); + const buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); + const instance = new InterleavedBufferAttribute( buffer, 2, 0 ); assert.ok( instance.count === 2, 'count is calculated via array length / stride' ); @@ -30,13 +62,48 @@ export default QUnit.module( 'Core', () => { } ); - // PUBLIC STUFF + QUnit.todo( 'needsUpdate', ( assert ) => { + + // set needsUpdate( value ) + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.test( 'isInterleavedBufferAttribute', ( assert ) => { + + const object = new InterleavedBufferAttribute(); + assert.ok( + object.isInterleavedBufferAttribute, + 'InterleavedBufferAttribute.isInterleavedBufferAttribute should be true' + ); + + } ); + + QUnit.todo( 'applyMatrix4', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'applyNormalMatrix', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'transformDirection', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + // setY, setZ and setW are calculated in the same way so not QUnit.testing this // TODO: ( you can't be sure that will be the case in future, or a mistake was introduce in one off them ! ) QUnit.test( 'setX', ( assert ) => { - var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - var instance = new InterleavedBufferAttribute( buffer, 2, 0 ); + let buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); + let instance = new InterleavedBufferAttribute( buffer, 2, 0 ); instance.setX( 0, 123 ); instance.setX( 1, 321 ); @@ -44,8 +111,8 @@ export default QUnit.module( 'Core', () => { assert.ok( instance.data.array[ 0 ] === 123 && instance.data.array[ 3 ] === 321, 'x was calculated correct based on index and default offset' ); - var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - var instance = new InterleavedBufferAttribute( buffer, 2, 1 ); + buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); + instance = new InterleavedBufferAttribute( buffer, 2, 1 ); instance.setX( 0, 123 ); instance.setX( 1, 321 ); @@ -116,6 +183,18 @@ export default QUnit.module( 'Core', () => { } ); + QUnit.todo( 'clone', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'toJSON', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + } ); } ); diff --git a/test/unit/src/core/Layers.tests.js b/test/unit/src/core/Layers.tests.js index 4b46e210c9aa87..c353ee366fec31 100644 --- a/test/unit/src/core/Layers.tests.js +++ b/test/unit/src/core/Layers.tests.js @@ -7,18 +7,26 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Layers', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new Layers(); + assert.ok( object, 'Can instantiate a Layers.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'mask', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + // PUBLIC QUnit.test( 'set', ( assert ) => { - var a = new Layers(); + const a = new Layers(); - for ( var i = 0; i < 31; i ++ ) { + for ( let i = 0; i < 31; i ++ ) { a.set( i ); assert.strictEqual( a.mask, Math.pow( 2, i ), 'Mask has the expected value for channel: ' + i ); @@ -29,7 +37,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'enable', ( assert ) => { - var a = new Layers(); + const a = new Layers(); a.set( 0 ); a.enable( 0 ); @@ -49,9 +57,15 @@ export default QUnit.module( 'Core', () => { } ); + QUnit.todo( 'enableAll', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'toggle', ( assert ) => { - var a = new Layers(); + const a = new Layers(); a.set( 0 ); a.toggle( 0 ); @@ -73,7 +87,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'disable', ( assert ) => { - var a = new Layers(); + const a = new Layers(); a.set( 0 ); a.disable( 0 ); @@ -93,10 +107,16 @@ export default QUnit.module( 'Core', () => { } ); + QUnit.todo( 'disableAll', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + QUnit.test( 'test', ( assert ) => { - var a = new Layers(); - var b = new Layers(); + const a = new Layers(); + const b = new Layers(); assert.ok( a.test( b ), 'Start out true' ); @@ -110,7 +130,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'isEnabled', ( assert ) => { - var a = new Layers(); + const a = new Layers(); a.enable( 1 ); assert.ok( a.isEnabled( 1 ), 'Enable channel 1 and pass the QUnit.test' ); diff --git a/test/unit/src/core/Object3D.tests.js b/test/unit/src/core/Object3D.tests.js index a1005640aa8bae..38261bde43412c 100644 --- a/test/unit/src/core/Object3D.tests.js +++ b/test/unit/src/core/Object3D.tests.js @@ -1,6 +1,7 @@ /* global QUnit */ import { Object3D } from '../../../../src/core/Object3D.js'; + import { Vector3 } from '../../../../src/math/Vector3.js'; import { Euler } from '../../../../src/math/Euler.js'; import { Quaternion } from '../../../../src/math/Quaternion.js'; @@ -34,9 +35,9 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Object3D', () => { - var RadToDeg = 180 / Math.PI; + const RadToDeg = 180 / Math.PI; - var eulerEquals = function ( a, b, tolerance ) { + const eulerEquals = function ( a, b, tolerance ) { tolerance = tolerance || 0.0001; @@ -57,20 +58,184 @@ export default QUnit.module( 'Core', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new Object3D(); - - assert.strictEqual( object instanceof EventDispatcher, true, 'Object3D extends from EventDispatcher' ); + const object = new Object3D(); + assert.strictEqual( + object instanceof EventDispatcher, true, + 'Object3D extends from EventDispatcher' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + const object = new Object3D(); + assert.ok( object, 'Can instantiate an Object3D.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'id', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'uuid', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'name', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.test( 'type', ( assert ) => { + + const object = new Object3D(); + assert.ok( + object.type === 'Object3D', + 'Object3D.type should be Object3D' + ); + + } ); + + QUnit.todo( 'parent', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'children', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'up', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // STATIC STUFF + QUnit.todo( 'position', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'rotation', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'quaternion', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'scale', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'modelViewMatrix', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'normalMatrix', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'matrix', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'matrixWorld', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'matrixAutoUpdate', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'matrixWorldNeedsUpdate', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'matrixWorldAutoUpdate', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'layers', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'visible', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'castShadow', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'receiveShadow', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'frustumCulled', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'renderOrder', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'animations', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'userData', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // STATIC QUnit.test( 'DEFAULT_UP', ( assert ) => { const currentDefaultUp = new Vector3().copy( Object3D.DEFAULT_UP ); @@ -108,13 +273,19 @@ export default QUnit.module( 'Core', () => { const object = new Object3D(); - assert.equal( object.matrixAutoUpdate, true, '.matrixAutoUpdate of a new object inherits Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true' ); + assert.equal( + object.matrixAutoUpdate, true, + '.matrixAutoUpdate of a new object inherits Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true' + ); Object3D.DEFAULT_MATRIX_AUTO_UPDATE = false; const object2 = new Object3D(); - assert.equal( object2.matrixAutoUpdate, false, '.matrixAutoUpdate of a new object inherits Object3D.DEFAULT_MATRIX_AUTO_UPDATE = false' ); + assert.equal( + object2.matrixAutoUpdate, false, + '.matrixAutoUpdate of a new object inherits Object3D.DEFAULT_MATRIX_AUTO_UPDATE = false' + ); } finally { @@ -124,14 +295,20 @@ export default QUnit.module( 'Core', () => { } ); - // PUBLIC STUFF + // PUBLIC QUnit.test( 'isObject3D', ( assert ) => { const object = new Object3D(); - assert.ok( object.isObject3D, 'Object3D.isObject3D should be true' ); + assert.ok( + object.isObject3D, + 'Object3D.isObject3D should be true' + ); const object2 = {}; - assert.ok( object2.isObject3D === undefined, 'other object isObject3D should be undefined' ); + assert.ok( + object2.isObject3D === undefined, + 'other object isObject3D should be undefined' + ); } ); @@ -149,10 +326,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var a = new Object3D(); - var m = new Matrix4(); - var expectedPos = new Vector3( x, y, z ); - var expectedQuat = new Quaternion( 0.5 * Math.sqrt( 2 ), 0, 0, 0.5 * Math.sqrt( 2 ) ); + const a = new Object3D(); + const m = new Matrix4(); + const expectedPos = new Vector3( x, y, z ); + const expectedQuat = new Quaternion( 0.5 * Math.sqrt( 2 ), 0, 0, 0.5 * Math.sqrt( 2 ) ); m.makeRotationX( Math.PI / 2 ); m.setPosition( new Vector3( x, y, z ) ); @@ -171,10 +348,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'applyQuaternion', ( assert ) => { - var a = new Object3D(); - var sqrt = 0.5 * Math.sqrt( 2 ); - var quat = new Quaternion( 0, sqrt, 0, sqrt ); - var expected = new Quaternion( sqrt / 2, sqrt / 2, 0, 0 ); + const a = new Object3D(); + const sqrt = 0.5 * Math.sqrt( 2 ); + const quat = new Quaternion( 0, sqrt, 0, sqrt ); + const expected = new Quaternion( sqrt / 2, sqrt / 2, 0, 0 ); a.quaternion.set( 0.25, 0.25, 0.25, 0.25 ); a.applyQuaternion( quat ); @@ -190,18 +367,18 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setRotationFromAxisAngle', ( assert ) => { - var a = new Object3D(); - var axis = new Vector3( 0, 1, 0 ); - var angle = Math.PI; - var expected = new Euler( - Math.PI, 0, - Math.PI ); - var euler = new Euler(); + const a = new Object3D(); + const axis = new Vector3( 0, 1, 0 ); + let angle = Math.PI; + const expected = new Euler( - Math.PI, 0, - Math.PI ); + const euler = new Euler(); a.setRotationFromAxisAngle( axis, angle ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); assert.ok( eulerEquals( euler, expected ), 'Correct values after rotation' ); axis.set( 1, 0, 0 ); - var angle = 0; + angle = 0; expected.set( 0, 0, 0 ); a.setRotationFromAxisAngle( axis, angle ); @@ -212,10 +389,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setRotationFromEuler', ( assert ) => { - var a = new Object3D(); - var rotation = new Euler( ( 45 / RadToDeg ), 0, Math.PI ); - var expected = rotation.clone(); // bit obvious - var euler = new Euler(); + const a = new Object3D(); + const rotation = new Euler( ( 45 / RadToDeg ), 0, Math.PI ); + const expected = rotation.clone(); // bit obvious + const euler = new Euler(); a.setRotationFromEuler( rotation ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); @@ -225,12 +402,12 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setRotationFromMatrix', ( assert ) => { - var a = new Object3D(); - var m = new Matrix4(); - var eye = new Vector3( 0, 0, 0 ); - var target = new Vector3( 0, 1, - 1 ); - var up = new Vector3( 0, 1, 0 ); - var euler = new Euler(); + const a = new Object3D(); + const m = new Matrix4(); + const eye = new Vector3( 0, 0, 0 ); + const target = new Vector3( 0, 1, - 1 ); + const up = new Vector3( 0, 1, 0 ); + const euler = new Euler(); m.lookAt( eye, target, up ); a.setRotationFromMatrix( m ); @@ -241,9 +418,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setRotationFromQuaternion', ( assert ) => { - var a = new Object3D(); - var rotation = new Quaternion().setFromEuler( new Euler( Math.PI, 0, - Math.PI ) ); - var euler = new Euler(); + const a = new Object3D(); + const rotation = new Quaternion().setFromEuler( new Euler( Math.PI, 0, - Math.PI ) ); + const euler = new Euler(); a.setRotationFromQuaternion( rotation ); euler.setFromQuaternion( a.getWorldQuaternion( new Quaternion() ) ); @@ -265,9 +442,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'rotateX', ( assert ) => { - var obj = new Object3D(); - - var angleInRad = 1.562; + const obj = new Object3D(); + const angleInRad = 1.562; obj.rotateX( angleInRad ); assert.numEqual( obj.rotation.x, angleInRad, 'x is equal' ); @@ -276,9 +452,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'rotateY', ( assert ) => { - var obj = new Object3D(); - - var angleInRad = - 0.346; + const obj = new Object3D(); + const angleInRad = - 0.346; obj.rotateY( angleInRad ); assert.numEqual( obj.rotation.y, angleInRad, 'y is equal' ); @@ -287,9 +462,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'rotateZ', ( assert ) => { - var obj = new Object3D(); - - var angleInRad = 1; + const obj = new Object3D(); + const angleInRad = 1; obj.rotateZ( angleInRad ); assert.numEqual( obj.rotation.z, angleInRad, 'z is equal' ); @@ -298,8 +472,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'translateOnAxis', ( assert ) => { - var obj = new Object3D(); - + const obj = new Object3D(); obj.translateOnAxis( new Vector3( 1, 0, 0 ), 1 ); obj.translateOnAxis( new Vector3( 0, 1, 0 ), 1.23 ); obj.translateOnAxis( new Vector3( 0, 0, 1 ), - 4.56 ); @@ -314,7 +487,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'translateX', ( assert ) => { - var obj = new Object3D(); + const obj = new Object3D(); obj.translateX( 1.234 ); assert.numEqual( obj.position.x, 1.234, 'x is equal' ); @@ -323,7 +496,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'translateY', ( assert ) => { - var obj = new Object3D(); + const obj = new Object3D(); obj.translateY( 1.234 ); assert.numEqual( obj.position.y, 1.234, 'y is equal' ); @@ -332,7 +505,7 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'translateZ', ( assert ) => { - var obj = new Object3D(); + const obj = new Object3D(); obj.translateZ( 1.234 ); assert.numEqual( obj.position.z, 1.234, 'z is equal' ); @@ -401,18 +574,18 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'lookAt', ( assert ) => { - var obj = new Object3D(); + const obj = new Object3D(); obj.lookAt( new Vector3( 0, - 1, 1 ) ); assert.numEqual( obj.rotation.x * RadToDeg, 45, 'x is equal' ); } ); - QUnit.test( 'add/remove/clear', ( assert ) => { + QUnit.test( 'add/remove/removeFromParent/clear', ( assert ) => { - var a = new Object3D(); - var child1 = new Object3D(); - var child2 = new Object3D(); + const a = new Object3D(); + const child1 = new Object3D(); + const child2 = new Object3D(); assert.strictEqual( a.children.length, 0, 'Starts with no children' ); @@ -514,10 +687,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'getObjectById/getObjectByName/getObjectByProperty', ( assert ) => { - var parent = new Object3D(); - var childName = new Object3D(); - var childId = new Object3D(); // id = parent.id + 2 - var childNothing = new Object3D(); + const parent = new Object3D(); + const childName = new Object3D(); + const childId = new Object3D(); // id = parent.id + 2 + const childNothing = new Object3D(); parent.prop = true; childName.name = 'foo'; @@ -535,11 +708,11 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'getObjectsByProperty', ( assert ) => { - var parent = new Object3D(); - var childName = new Object3D(); - var childNothing = new Object3D(); - var childName2 = new Object3D(); - var childName3 = new Object3D(); + const parent = new Object3D(); + const childName = new Object3D(); + const childNothing = new Object3D(); + const childName2 = new Object3D(); + const childName3 = new Object3D(); parent.prop = true; childName.name = 'foo'; @@ -556,12 +729,12 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'getWorldPosition', ( assert ) => { - var a = new Object3D(); - var b = new Object3D(); - var expectedSingle = new Vector3( x, y, z ); - var expectedParent = new Vector3( x, y, 0 ); - var expectedChild = new Vector3( x, y, 7 ); - var position = new Vector3(); + const a = new Object3D(); + const b = new Object3D(); + const expectedSingle = new Vector3( x, y, z ); + const expectedParent = new Vector3( x, y, 0 ); + const expectedChild = new Vector3( x, y, 7 ); + const position = new Vector3(); a.translateX( x ); a.translateY( y ); @@ -587,9 +760,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'getWorldScale', ( assert ) => { - var a = new Object3D(); - var m = new Matrix4().makeScale( x, y, z ); - var expected = new Vector3( x, y, z ); + const a = new Object3D(); + const m = new Matrix4().makeScale( x, y, z ); + const expected = new Vector3( x, y, z ); a.applyMatrix4( m ); @@ -599,9 +772,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'getWorldDirection', ( assert ) => { - var a = new Object3D(); - var expected = new Vector3( 0, - 0.5 * Math.sqrt( 2 ), 0.5 * Math.sqrt( 2 ) ); - var direction = new Vector3(); + const a = new Object3D(); + const expected = new Vector3( 0, - 0.5 * Math.sqrt( 2 ), 0.5 * Math.sqrt( 2 ) ); + const direction = new Vector3(); a.lookAt( new Vector3( 0, - 1, 1 ) ); a.getWorldDirection( direction ); @@ -617,10 +790,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'localTransformVariableInstantiation', ( assert ) => { - var a = new Object3D(); - var b = new Object3D(); - var c = new Object3D(); - var d = new Object3D(); + const a = new Object3D(); + const b = new Object3D(); + const c = new Object3D(); + const d = new Object3D(); a.getWorldDirection( new Vector3() ); a.lookAt( new Vector3( 0, - 1, 1 ) ); @@ -652,14 +825,14 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'traverse/traverseVisible/traverseAncestors', ( assert ) => { - var a = new Object3D(); - var b = new Object3D(); - var c = new Object3D(); - var d = new Object3D(); - var names = []; - var expectedNormal = [ 'parent', 'child', 'childchild 1', 'childchild 2' ]; - var expectedVisible = [ 'parent', 'child', 'childchild 2' ]; - var expectedAncestors = [ 'child', 'parent' ]; + const a = new Object3D(); + const b = new Object3D(); + const c = new Object3D(); + const d = new Object3D(); + let names = []; + const expectedNormal = [ 'parent', 'child', 'childchild 1', 'childchild 2' ]; + const expectedVisible = [ 'parent', 'child', 'childchild 2' ]; + const expectedAncestors = [ 'child', 'parent' ]; a.name = 'parent'; b.name = 'child'; @@ -678,7 +851,7 @@ export default QUnit.module( 'Core', () => { } ); assert.deepEqual( names, expectedNormal, 'Traversed objects in expected order' ); - var names = []; + names = []; a.traverseVisible( function ( obj ) { names.push( obj.name ); @@ -686,7 +859,7 @@ export default QUnit.module( 'Core', () => { } ); assert.deepEqual( names, expectedVisible, 'Traversed visible objects in expected order' ); - var names = []; + names = []; c.traverseAncestors( function ( obj ) { names.push( obj.name ); @@ -1078,9 +1251,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'toJSON', ( assert ) => { - var a = new Object3D(); - var child = new Object3D(); - var childChild = new Object3D(); + const a = new Object3D(); + const child = new Object3D(); + const childChild = new Object3D(); a.name = 'a\'s name'; a.matrix.set( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ); @@ -1088,15 +1261,16 @@ export default QUnit.module( 'Core', () => { a.castShadow = true; a.receiveShadow = true; a.userData[ 'foo' ] = 'bar'; + a.up.set( 1, 0, 0 ); child.uuid = '5D4E9AE8-DA61-4912-A575-71A5BE3D72CD'; childChild.uuid = 'B43854B3-E970-4E85-BD41-AAF8D7BFA189'; child.add( childChild ); a.add( child ); - var gold = { + const gold = { 'metadata': { - 'version': 4.5, + 'version': 4.6, 'type': 'Object', 'generator': 'Object3D.toJSON' }, @@ -1121,16 +1295,19 @@ export default QUnit.module( 'Core', () => { 'uuid': 'B43854B3-E970-4E85-BD41-AAF8D7BFA189', 'type': 'Object3D', 'layers': 1, - 'matrix': [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] + 'matrix': [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], + 'up': [ 0, 1, 0 ] } - ] + ], + 'up': [ 0, 1, 0 ] } - ] + ], + 'up': [ 1, 0, 0 ] } }; // hacks - var out = a.toJSON(); + const out = a.toJSON(); out.object.uuid = '0A1E4F43-CB5B-4097-8F82-DC2969C0B8C2'; assert.deepEqual( out, gold, 'JSON is as expected' ); @@ -1139,8 +1316,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'clone', ( assert ) => { - var a; - var b = new Object3D(); + let a; + const b = new Object3D(); assert.strictEqual( a, undefined, 'Undefined pre-clone()' ); @@ -1154,10 +1331,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Object3D(); - var b = new Object3D(); - var child = new Object3D(); - var childChild = new Object3D(); + const a = new Object3D(); + const b = new Object3D(); + const child = new Object3D(); + const childChild = new Object3D(); a.name = 'original'; b.name = 'to-be-copied'; diff --git a/test/unit/src/core/Raycaster.tests.js b/test/unit/src/core/Raycaster.tests.js index 6420b5a9507bcf..f71b2aa4671044 100644 --- a/test/unit/src/core/Raycaster.tests.js +++ b/test/unit/src/core/Raycaster.tests.js @@ -30,29 +30,29 @@ function getRaycaster() { function getObjectsToCheck() { - var objects = []; + const objects = []; - var sphere1 = getSphere(); + const sphere1 = getSphere(); sphere1.position.set( 0, 0, - 10 ); sphere1.name = 1; objects.push( sphere1 ); - var sphere11 = getSphere(); + const sphere11 = getSphere(); sphere11.position.set( 0, 0, 1 ); sphere11.name = 11; sphere1.add( sphere11 ); - var sphere12 = getSphere(); + const sphere12 = getSphere(); sphere12.position.set( 0, 0, - 1 ); sphere12.name = 12; sphere1.add( sphere12 ); - var sphere2 = getSphere(); + const sphere2 = getSphere(); sphere2.position.set( - 5, 0, - 5 ); sphere2.name = 2; objects.push( sphere2 ); - for ( var i = 0; i < objects.length; i ++ ) { + for ( let i = 0; i < objects.length; i ++ ) { objects[ i ].updateMatrixWorld(); @@ -73,18 +73,57 @@ export default QUnit.module( 'Core', () => { QUnit.module( 'Raycaster', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { + + // no params + const object = new Raycaster(); + assert.ok( object, 'Can instantiate a Raycaster.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'ray', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'near', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'far', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'camera', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); } ); - // PUBLIC STUFF + QUnit.todo( 'layers', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'params', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC QUnit.test( 'set', ( assert ) => { - var origin = new Vector3( 0, 0, 0 ); - var direction = new Vector3( 0, 0, - 1 ); - var a = new Raycaster( origin.clone(), direction.clone() ); + const origin = new Vector3( 0, 0, 0 ); + const direction = new Vector3( 0, 0, - 1 ); + const a = new Raycaster( origin.clone(), direction.clone() ); assert.deepEqual( a.ray.origin, origin, 'Origin is correct' ); assert.deepEqual( a.ray.direction, direction, 'Direction is correct' ); @@ -100,9 +139,9 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setFromCamera (Perspective)', ( assert ) => { - var raycaster = new Raycaster(); - var rayDirection = raycaster.ray.direction; - var camera = new PerspectiveCamera( 90, 1, 1, 1000 ); + const raycaster = new Raycaster(); + const rayDirection = raycaster.ray.direction; + const camera = new PerspectiveCamera( 90, 1, 1, 1000 ); raycaster.setFromCamera( { x: 0, @@ -111,18 +150,18 @@ export default QUnit.module( 'Core', () => { assert.ok( rayDirection.x === 0 && rayDirection.y === 0 && rayDirection.z === - 1, 'camera is looking straight to -z and so does the ray in the middle of the screen' ); - var step = 0.1; + const step = 0.1; - for ( var x = - 1; x <= 1; x += step ) { + for ( let x = - 1; x <= 1; x += step ) { - for ( var y = - 1; y <= 1; y += step ) { + for ( let y = - 1; y <= 1; y += step ) { raycaster.setFromCamera( { x, y }, camera ); - var refVector = new Vector3( x, y, - 1 ).normalize(); + const refVector = new Vector3( x, y, - 1 ).normalize(); checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert ); @@ -134,12 +173,12 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'setFromCamera (Orthographic)', ( assert ) => { - var raycaster = new Raycaster(); - var rayOrigin = raycaster.ray.origin; - var rayDirection = raycaster.ray.direction; - var camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1000 ); - var expectedOrigin = new Vector3( 0, 0, 0 ); - var expectedDirection = new Vector3( 0, 0, - 1 ); + const raycaster = new Raycaster(); + const rayOrigin = raycaster.ray.origin; + const rayDirection = raycaster.ray.direction; + const camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1000 ); + const expectedOrigin = new Vector3( 0, 0, 0 ); + const expectedDirection = new Vector3( 0, 0, - 1 ); raycaster.setFromCamera( { x: 0, @@ -152,8 +191,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'intersectObject', ( assert ) => { - var raycaster = getRaycaster(); - var objectsToCheck = getObjectsToCheck(); + const raycaster = getRaycaster(); + const objectsToCheck = getObjectsToCheck(); assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ], false ).length === 1, 'no recursive search should lead to one hit' ); @@ -161,8 +200,8 @@ export default QUnit.module( 'Core', () => { assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ] ).length === 3, 'recursive search should lead to three hits' ); - var intersections = raycaster.intersectObject( objectsToCheck[ 0 ] ); - for ( var i = 0; i < intersections.length - 1; i ++ ) { + const intersections = raycaster.intersectObject( objectsToCheck[ 0 ] ); + for ( let i = 0; i < intersections.length - 1; i ++ ) { assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, 'intersections are sorted' ); @@ -172,8 +211,8 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'intersectObjects', ( assert ) => { - var raycaster = getRaycaster(); - var objectsToCheck = getObjectsToCheck(); + const raycaster = getRaycaster(); + const objectsToCheck = getObjectsToCheck(); assert.ok( raycaster.intersectObjects( objectsToCheck, false ).length === 1, 'no recursive search should lead to one hit' ); @@ -181,8 +220,8 @@ export default QUnit.module( 'Core', () => { assert.ok( raycaster.intersectObjects( objectsToCheck ).length === 3, 'recursive search should lead to three hits' ); - var intersections = raycaster.intersectObjects( objectsToCheck ); - for ( var i = 0; i < intersections.length - 1; i ++ ) { + const intersections = raycaster.intersectObjects( objectsToCheck ); + for ( let i = 0; i < intersections.length - 1; i ++ ) { assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, 'intersections are sorted' ); @@ -192,10 +231,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'Line intersection threshold', ( assert ) => { - var raycaster = getRaycaster(); - var points = [ new Vector3( - 2, - 10, - 5 ), new Vector3( - 2, 10, - 5 ) ]; - var geometry = new BufferGeometry().setFromPoints( points ); - var line = new Line( geometry, null ); + const raycaster = getRaycaster(); + const points = [ new Vector3( - 2, - 10, - 5 ), new Vector3( - 2, 10, - 5 ) ]; + const geometry = new BufferGeometry().setFromPoints( points ); + const line = new Line( geometry, null ); raycaster.params.Line.threshold = 1.999; assert.ok( raycaster.intersectObject( line ).length === 0, @@ -209,10 +248,10 @@ export default QUnit.module( 'Core', () => { QUnit.test( 'Points intersection threshold', ( assert ) => { - var raycaster = getRaycaster(); - var coordinates = [ new Vector3( - 2, 0, - 5 ) ]; - var geometry = new BufferGeometry().setFromPoints( coordinates ); - var points = new Points( geometry, null ); + const raycaster = getRaycaster(); + const coordinates = [ new Vector3( - 2, 0, - 5 ) ]; + const geometry = new BufferGeometry().setFromPoints( coordinates ); + const points = new Points( geometry, null ); raycaster.params.Points.threshold = 1.999; assert.ok( raycaster.intersectObject( points ).length === 0, @@ -224,7 +263,6 @@ export default QUnit.module( 'Core', () => { } ); - } ); } ); diff --git a/test/unit/src/core/Uniform.tests.js b/test/unit/src/core/Uniform.tests.js index ba7235ec50cfce..98af988ef2218b 100644 --- a/test/unit/src/core/Uniform.tests.js +++ b/test/unit/src/core/Uniform.tests.js @@ -15,8 +15,8 @@ export default QUnit.module( 'Core', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a; - var b = new Vector3( x, y, z ); + let a; + const b = new Vector3( x, y, z ); a = new Uniform( 5 ); assert.strictEqual( a.value, 5, 'New constructor works with simple values' ); @@ -26,16 +26,23 @@ export default QUnit.module( 'Core', () => { } ); - // PUBLIC STUFF + // PROPERTIES + QUnit.todo( 'value', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC QUnit.test( 'clone', ( assert ) => { - var a = new Uniform( 23 ); - var b = a.clone(); + let a = new Uniform( 23 ); + let b = a.clone(); assert.strictEqual( b.value, a.value, 'clone() with simple values works' ); - var a = new Uniform( new Vector3( 1, 2, 3 ) ); - var b = a.clone(); + a = new Uniform( new Vector3( 1, 2, 3 ) ); + b = a.clone(); assert.ok( b.value.equals( a.value ), 'clone() with complex values works' ); diff --git a/test/unit/src/core/UniformsGroup.tests.js b/test/unit/src/core/UniformsGroup.tests.js new file mode 100644 index 00000000000000..30fa51b9993b6f --- /dev/null +++ b/test/unit/src/core/UniformsGroup.tests.js @@ -0,0 +1,113 @@ +/* global QUnit */ + +import { UniformsGroup } from '../../../../src/core/UniformsGroup.js'; + +import { EventDispatcher } from '../../../../src/core/EventDispatcher.js'; + +export default QUnit.module( 'Core', () => { + + QUnit.module( 'UniformsGroup', () => { + + // INHERITANCE + QUnit.test( 'Extending', ( assert ) => { + + const object = new UniformsGroup(); + assert.strictEqual( + object instanceof EventDispatcher, true, + 'UniformsGroup extends from EventDispatcher' + ); + + } ); + + // INSTANCING + QUnit.test( 'Instancing', ( assert ) => { + + const object = new UniformsGroup(); + assert.ok( object, 'Can instantiate a UniformsGroup.' ); + + } ); + + // PROPERTIES + QUnit.todo( 'id', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'name', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'usage', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'uniforms', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + // PUBLIC + QUnit.test( 'isUniformsGroup', ( assert ) => { + + const object = new UniformsGroup(); + assert.ok( + object.isUniformsGroup, + 'UniformsGroup.isUniformsGroup should be true' + ); + + } ); + + QUnit.todo( 'add', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'remove', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'setName', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'setUsage', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.test( 'dispose', ( assert ) => { + + assert.expect( 0 ); + + const object = new UniformsGroup(); + object.dispose(); + + } ); + + QUnit.todo( 'copy', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + QUnit.todo( 'clone', ( assert ) => { + + assert.ok( false, 'everything\'s gonna be alright' ); + + } ); + + } ); + +} ); diff --git a/test/unit/src/extras/DataUtils.tests.js b/test/unit/src/extras/DataUtils.tests.js index 9aa97552086910..74b549dbb52fd4 100644 --- a/test/unit/src/extras/DataUtils.tests.js +++ b/test/unit/src/extras/DataUtils.tests.js @@ -2,6 +2,8 @@ import * as DataUtils from '../../../../src/extras/DataUtils.js'; +import { CONSOLE_LEVEL } from '../../utils/console-wrapper.js'; + export default QUnit.module( 'Extras', () => { QUnit.module( 'DataUtils', () => { @@ -10,8 +12,15 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'toHalfFloat', ( assert ) => { assert.ok( DataUtils.toHalfFloat( 0 ) === 0, 'Passed!' ); + + // surpress the following console message during testing + // THREE.DataUtils.toHalfFloat(): Value out of range. + + console.level = CONSOLE_LEVEL.OFF; assert.ok( DataUtils.toHalfFloat( 100000 ) === 31743, 'Passed!' ); assert.ok( DataUtils.toHalfFloat( - 100000 ) === 64511, 'Passed!' ); + console.level = CONSOLE_LEVEL.DEFAULT; + assert.ok( DataUtils.toHalfFloat( 65504 ) === 31743, 'Passed!' ); assert.ok( DataUtils.toHalfFloat( - 65504 ) === 64511, 'Passed!' ); assert.ok( DataUtils.toHalfFloat( Math.PI ) === 16968, 'Passed!' ); diff --git a/test/unit/src/extras/core/Curve.tests.js b/test/unit/src/extras/core/Curve.tests.js index e1ca50b2e56cd8..c13fd816c64b01 100644 --- a/test/unit/src/extras/core/Curve.tests.js +++ b/test/unit/src/extras/core/Curve.tests.js @@ -9,9 +9,10 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'Curve', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Curve(); + assert.ok( object, 'Can instantiate a Curve.' ); } ); diff --git a/test/unit/src/extras/core/CurvePath.tests.js b/test/unit/src/extras/core/CurvePath.tests.js index 5951d71d9b07d9..1cd08c56603553 100644 --- a/test/unit/src/extras/core/CurvePath.tests.js +++ b/test/unit/src/extras/core/CurvePath.tests.js @@ -22,9 +22,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CurvePath(); + assert.ok( object, 'Can instantiate a CurvePath.' ); } ); diff --git a/test/unit/src/extras/core/Path.tests.js b/test/unit/src/extras/core/Path.tests.js index 5ed468ca97ac4e..a7eccb337a0a4b 100644 --- a/test/unit/src/extras/core/Path.tests.js +++ b/test/unit/src/extras/core/Path.tests.js @@ -22,9 +22,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Path(); + assert.ok( object, 'Can instantiate a Path.' ); } ); diff --git a/test/unit/src/extras/core/Shape.tests.js b/test/unit/src/extras/core/Shape.tests.js index 500797c0503a53..9c1e52f1c0108f 100644 --- a/test/unit/src/extras/core/Shape.tests.js +++ b/test/unit/src/extras/core/Shape.tests.js @@ -22,9 +22,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Shape(); + assert.ok( object, 'Can instantiate a Shape.' ); } ); diff --git a/test/unit/src/extras/core/ShapePath.tests.js b/test/unit/src/extras/core/ShapePath.tests.js index 8dee8191de71f9..a2ad5acb9cd7d7 100644 --- a/test/unit/src/extras/core/ShapePath.tests.js +++ b/test/unit/src/extras/core/ShapePath.tests.js @@ -9,9 +9,10 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'ShapePath', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ShapePath(); + assert.ok( object, 'Can instantiate a ShapePath.' ); } ); diff --git a/test/unit/src/extras/curves/ArcCurve.tests.js b/test/unit/src/extras/curves/ArcCurve.tests.js index 495da1e25dfa80..a1467c7ea41f1d 100644 --- a/test/unit/src/extras/curves/ArcCurve.tests.js +++ b/test/unit/src/extras/curves/ArcCurve.tests.js @@ -22,9 +22,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ArcCurve(); + assert.ok( object, 'Can instantiate an ArcCurve.' ); } ); diff --git a/test/unit/src/extras/curves/CatmullRomCurve3.tests.js b/test/unit/src/extras/curves/CatmullRomCurve3.tests.js index cf90ffac7c8ecc..09f62fcd20c018 100644 --- a/test/unit/src/extras/curves/CatmullRomCurve3.tests.js +++ b/test/unit/src/extras/curves/CatmullRomCurve3.tests.js @@ -12,7 +12,7 @@ export default QUnit.module( 'Extras', () => { QUnit.module( 'CatmullRomCurve3', () => { /* eslint-disable */ - var positions = [ + const positions = [ new Vector3( - 60, - 100, 60 ), new Vector3( - 60, 20, 60 ), new Vector3( - 60, 120, 60 ), @@ -33,9 +33,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CatmullRomCurve3(); + assert.ok( object, 'Can instantiate a CatmullRomCurve3.' ); } ); @@ -112,10 +113,10 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'catmullrom check', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 60, - 100, 60 ), new Vector3( - 60, - 51.04, 60 ), @@ -131,7 +132,7 @@ export default QUnit.module( 'Extras', () => { ]; - var points = curve.getPoints( 10 ); + const points = curve.getPoints( 10 ); assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); @@ -147,11 +148,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'chordal basic check', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'chordal'; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 60, - 100, 60 ), new Vector3( - 60, - 52, 60 ), new Vector3( - 60, - 4, 60 ), @@ -165,7 +166,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( 60.00000000000001, - 100, - 60.00000000000001 ) ]; - var points = curve.getPoints( 10 ); + const points = curve.getPoints( 10 ); assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); @@ -181,10 +182,10 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'centripetal basic check', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'centripetal'; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 60, - 100, 60 ), new Vector3( - 60, - 51.47527724919028, 60 ), new Vector3( - 60, - 3.300369665587032, 60 ), @@ -198,7 +199,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( 59.99999999999999, - 100, - 59.99999999999999 ), ]; - var points = curve.getPoints( 10 ); + const points = curve.getPoints( 10 ); assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); @@ -214,11 +215,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'closed catmullrom basic check', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; curve.closed = true; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 60, - 100, 60 ), new Vector3( - 67.5, - 46.25, 67.5 ), new Vector3( - 60, 20, 60 ), @@ -232,7 +233,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( - 60, - 100, 60 ), ]; - var points = curve.getPoints( 10 ); + const points = curve.getPoints( 10 ); assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); @@ -251,22 +252,22 @@ export default QUnit.module( 'Extras', () => { // QUnit.test( 'getLength/getLengths', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; - var length = curve.getLength(); - var expectedLength = 551.549686276872; + const length = curve.getLength(); + const expectedLength = 551.549686276872; assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var expectedLengths = [ + const expectedLengths = [ 0, 120, 220, 416.9771560359221, 536.9771560359221 ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); + const lengths = curve.getLengths( expectedLengths.length - 1 ); assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); @@ -280,17 +281,17 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 60, - 100, 60 ), new Vector3( - 64.84177333183106, 64.86956465359813, 64.84177333183106 ), new Vector3( - 28.288507045700854, 104.83101184518996, 28.288507045700854 ), new Vector3( 60, - 100, - 60 ) ]; - var points = [ + const points = [ curve.getPointAt( 0, new Vector3() ), curve.getPointAt( 0.3, new Vector3() ), curve.getPointAt( 0.5, new Vector3() ), @@ -303,10 +304,10 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent/getTangentAt', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; - var expectedTangents = [ + let expectedTangents = [ new Vector3( 0, 1, 0 ), new Vector3( - 0.0001090274561657922, 0.9999999881130137, 0.0001090274561657922 ), new Vector3( 0.7071067811865475, - 2.0930381713877622e-13, - 0.7071067811865475 ), @@ -314,7 +315,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( - 0.00019991333100812723, - 0.9999999600346592, 0.00019991333100812723 ) ]; - var tangents = [ + let tangents = [ curve.getTangent( 0, new Vector3() ), curve.getTangent( 0.25, new Vector3() ), curve.getTangent( 0.5, new Vector3() ), @@ -324,7 +325,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); @@ -351,7 +352,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); @@ -362,10 +363,10 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'computeFrenetFrames', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; - var expected = { + const expected = { binormals: [ new Vector3( - 1, 0, 0 ), new Vector3( - 0.28685061854203, 0.6396363672964267, - 0.7131493814579701 ), @@ -383,7 +384,7 @@ export default QUnit.module( 'Extras', () => { ] }; - var frames = curve.computeFrenetFrames( 2, false ); + const frames = curve.computeFrenetFrames( 2, false ); Object.keys( expected ).forEach( function ( group, i ) { @@ -401,14 +402,14 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 500 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.5, 500 ); - var expectedSomewhere = 0.8964116382083199; + const expectedSomewhere = 0.8964116382083199; assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -418,10 +419,10 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var curve = new CatmullRomCurve3( positions ); + const curve = new CatmullRomCurve3( positions ); curve.curveType = 'catmullrom'; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 60, - 100, 60 ), new Vector3( - 60, 10.311489426555056, 60 ), new Vector3( - 65.05889864636504, 117.99691802595966, 65.05889864636504 ), @@ -430,7 +431,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( 60, - 100, - 60 ) ]; - var points = curve.getSpacedPoints(); + const points = curve.getSpacedPoints(); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); diff --git a/test/unit/src/extras/curves/CubicBezierCurve.tests.js b/test/unit/src/extras/curves/CubicBezierCurve.tests.js index 8ab2531bc2e824..388431efda6296 100644 --- a/test/unit/src/extras/curves/CubicBezierCurve.tests.js +++ b/test/unit/src/extras/curves/CubicBezierCurve.tests.js @@ -35,9 +35,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CubicBezierCurve(); + assert.ok( object, 'Can instantiate a CubicBezierCurve.' ); } ); @@ -119,7 +120,7 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( - 3.359375, 8.4375 ), new Vector2( 5.625, 11.25 ), @@ -127,17 +128,17 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 0 ) ]; - var points = curve.getPoints( expectedPoints.length - 1 ); + let points = curve.getPoints( expectedPoints.length - 1 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry - var curveRev = new CubicBezierCurve( + const curveRev = new CubicBezierCurve( curve.v3, curve.v2, curve.v1, curve.v0 ); - var points = curveRev.getPoints( expectedPoints.length - 1 ); + points = curveRev.getPoints( expectedPoints.length - 1 ); assert.strictEqual( points.length, expectedPoints.length, 'Reversed: Correct number of points' ); assert.deepEqual( points, expectedPoints.reverse(), 'Reversed: Correct points curve' ); @@ -146,19 +147,19 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var length = curve.getLength(); - var expectedLength = 36.64630888504102; + const length = curve.getLength(); + const expectedLength = 36.64630888504102; assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var expectedLengths = [ + const expectedLengths = [ 0, 10.737285813492393, 20.15159143794633, 26.93408340370825, 35.56079575637337 ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); + const lengths = curve.getLengths( expectedLengths.length - 1 ); assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); @@ -172,14 +173,14 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( - 3.3188282598022596, 8.463722639089221 ), new Vector2( 3.4718554735926617, 11.07899406116314 ), new Vector2( 10, 0 ) ]; - var points = [ + const points = [ curve.getPointAt( 0, new Vector2() ), curve.getPointAt( 0.3, new Vector2() ), curve.getPointAt( 0.5, new Vector2() ), @@ -192,7 +193,7 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent/getTangentAt', ( assert ) => { - var expectedTangents = [ + let expectedTangents = [ new Vector2( 0.316370061632252, 0.9486358543207215 ), new Vector2( 0.838961283088303, 0.5441911111721949 ), new Vector2( 1, 0 ), @@ -200,7 +201,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( - 0.5546041767829665, - 0.8321142992972107 ) ]; - var tangents = [ + let tangents = [ curve.getTangent( 0, new Vector2() ), curve.getTangent( 0.25, new Vector2() ), curve.getTangent( 0.5, new Vector2() ), @@ -210,7 +211,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); @@ -219,7 +220,7 @@ export default QUnit.module( 'Extras', () => { // - var expectedTangents = [ + expectedTangents = [ new Vector2( 0.316370061632252, 0.9486358543207215 ), new Vector2( 0.7794223085548987, 0.6264988945935596 ), new Vector2( 0.988266153082452, 0.15274164681452052 ), @@ -227,7 +228,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( - 0.5546041767829665, - 0.8321142992972107 ) ]; - var tangents = [ + tangents = [ curve.getTangentAt( 0, new Vector2() ), curve.getTangentAt( 0.25, new Vector2() ), curve.getTangentAt( 0.5, new Vector2() ), @@ -237,7 +238,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); @@ -248,11 +249,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.5, 1 ); - var expectedSomewhere = 0.02130029182257093; + const expectedSomewhere = 0.02130029182257093; assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -262,7 +263,7 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( - 6.16826457740703, 6.17025727295411 ), new Vector2( - 0.058874033259857184, 10.1240558653185 ), @@ -271,7 +272,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 0 ) ]; - var points = curve.getSpacedPoints(); + const points = curve.getSpacedPoints(); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); diff --git a/test/unit/src/extras/curves/CubicBezierCurve3.tests.js b/test/unit/src/extras/curves/CubicBezierCurve3.tests.js index 436035573d71f3..1063ca92343c5c 100644 --- a/test/unit/src/extras/curves/CubicBezierCurve3.tests.js +++ b/test/unit/src/extras/curves/CubicBezierCurve3.tests.js @@ -35,9 +35,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CubicBezierCurve3(); + assert.ok( object, 'Can instantiate a CubicBezierCurve3.' ); } ); @@ -119,7 +120,7 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 10, 0, 2 ), new Vector3( - 3.359375, 8.4375, 1.984375 ), new Vector3( 5.625, 11.25, 1.125 ), @@ -127,13 +128,13 @@ export default QUnit.module( 'Extras', () => { new Vector3( 10, 0, 10 ) ]; - var points = curve.getPoints( expectedPoints.length - 1 ); + let points = curve.getPoints( expectedPoints.length - 1 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry - var curveRev = new CubicBezierCurve3( + const curveRev = new CubicBezierCurve3( curve.v3, curve.v2, curve.v1, curve.v0 ); @@ -146,19 +147,19 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var length = curve.getLength(); - var expectedLength = 39.58103024989427; + const length = curve.getLength(); + const expectedLength = 39.58103024989427; assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var expectedLengths = [ + const expectedLengths = [ 0, 10.73729718231036, 20.19074500737662, 27.154413277853756, 38.453287150114214 ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); + const lengths = curve.getLengths( expectedLengths.length - 1 ); assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); @@ -172,14 +173,14 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 10, 0, 2 ), new Vector3( - 2.591880240484318, 8.908333501170798, 1.8953420625251136 ), new Vector3( 4.866251460832755, 11.22787914038507, 1.150832855206874 ), new Vector3( 10, 0, 10 ) ]; - var points = [ + const points = [ curve.getPointAt( 0, new Vector3() ), curve.getPointAt( 0.3, new Vector3() ), curve.getPointAt( 0.5, new Vector3() ), @@ -192,7 +193,7 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent/getTangentAt', ( assert ) => { - var expectedTangents = [ + let expectedTangents = [ new Vector3( 0.3138715439944244, 0.9411440474105875, 0.12542940601858074 ), new Vector3( 0.8351825262580098, 0.54174002562179, - 0.09480449605683638 ), new Vector3( 0.9997531780538501, 0, - 0.02221672728433752 ), @@ -200,7 +201,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( - 0.42632467075185815, - 0.6396469221230213, 0.6396085444448543 ) ]; - var tangents = [ + let tangents = [ curve.getTangent( 0, new Vector3() ), curve.getTangent( 0.25, new Vector3() ), curve.getTangent( 0.5, new Vector3() ), @@ -210,7 +211,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); @@ -237,7 +238,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); @@ -248,11 +249,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.5, 1 ); - var expectedSomewhere = 0.021163245321323316; + const expectedSomewhere = 0.021163245321323316; assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -262,7 +263,7 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 10, 0, 2 ), new Vector3( - 5.756524515061918, 6.568020242700483, 2.22116711170301 ), new Vector3( 1.0003511895116906, 10.49656064587831, 1.4727101010850698 ), @@ -271,7 +272,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( 10, 0, 10 ) ]; - var points = curve.getSpacedPoints(); + const points = curve.getSpacedPoints(); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); @@ -280,7 +281,7 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'computeFrenetFrames', ( assert ) => { - var expected = { + const expected = { binormals: [ new Vector3( - 0.9486358543207215, 0.316370061632252, - 6.938893903907228e-18 ), new Vector3( - 0.05491430765311864, 0.9969838307670049, 0.054842137122173326 ), @@ -298,7 +299,7 @@ export default QUnit.module( 'Extras', () => { ] }; - var frames = curve.computeFrenetFrames( 2, false ); + const frames = curve.computeFrenetFrames( 2, false ); Object.keys( expected ).forEach( function ( group, i ) { diff --git a/test/unit/src/extras/curves/EllipseCurve.tests.js b/test/unit/src/extras/curves/EllipseCurve.tests.js index b480b79223d48b..a548b5cf39603c 100644 --- a/test/unit/src/extras/curves/EllipseCurve.tests.js +++ b/test/unit/src/extras/curves/EllipseCurve.tests.js @@ -36,9 +36,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new EllipseCurve(); + assert.ok( object, 'Can instantiate an EllipseCurve.' ); } ); @@ -139,7 +140,7 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector2( 10, 0 ), new Vector2( 0, 10 ), new Vector2( - 10, 0 ), @@ -147,7 +148,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 0 ) ]; - var points = curve.getPoints( expectedPoints.length - 1 ); + const points = curve.getPoints( expectedPoints.length - 1 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); @@ -162,13 +163,13 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var length = curve.getLength(); - var expectedLength = 62.829269247282795; + const length = curve.getLength(); + const expectedLength = 62.829269247282795; assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var lengths = curve.getLengths( 5 ); - var expectedLengths = [ + const lengths = curve.getLengths( 5 ); + const expectedLengths = [ 0, 11.755705045849462, 23.51141009169892, @@ -189,15 +190,15 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPoint/getPointAt', ( assert ) => { - var testValues = [ 0, 0.3, 0.5, 0.7, 1 ]; + const testValues = [ 0, 0.3, 0.5, 0.7, 1 ]; - var p = new Vector2(); - var a = new Vector2(); + const p = new Vector2(); + const a = new Vector2(); testValues.forEach( function ( val ) { - var expectedX = Math.cos( val * Math.PI * 2 ) * 10; - var expectedY = Math.sin( val * Math.PI * 2 ) * 10; + const expectedX = Math.cos( val * Math.PI * 2 ) * 10; + const expectedY = Math.sin( val * Math.PI * 2 ) * 10; curve.getPoint( val, p ); curve.getPointAt( val, a ); @@ -214,7 +215,7 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent', ( assert ) => { - var expectedTangents = [ + const expectedTangents = [ new Vector2( - 0.000314159260186071, 0.9999999506519786 ), new Vector2( - 1, 0 ), new Vector2( 0, - 1 ), @@ -222,7 +223,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 0.00031415926018600165, 0.9999999506519784 ) ]; - var tangents = [ + const tangents = [ curve.getTangent( 0, new Vector2() ), curve.getTangent( 0.25, new Vector2() ), curve.getTangent( 0.5, new Vector2() ), @@ -232,7 +233,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); @@ -243,11 +244,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.7, 1 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.7, 1 ); - var expectedSomewhere = 0.01591614882650014; + const expectedSomewhere = 0.01591614882650014; assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -257,7 +258,7 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var expectedPoints = [ + const expectedPoints = [ new Vector2( 10, 0 ), new Vector2( 3.0901699437494603, 9.51056516295154 ), new Vector2( - 8.090169943749492, 5.877852522924707 ), @@ -266,13 +267,13 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, - 2.4492935982947065e-15 ) ]; - var points = curve.getSpacedPoints(); + const points = curve.getSpacedPoints(); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); expectedPoints.forEach( function ( exp, i ) { - var point = points[ i ]; + const point = points[ i ]; assert.numEqual( point.x, exp.x, 'Point #' + i + ': x correct' ); assert.numEqual( point.y, exp.y, 'Point #' + i + ': y correct' ); diff --git a/test/unit/src/extras/curves/LineCurve.tests.js b/test/unit/src/extras/curves/LineCurve.tests.js index d760237e01b759..5706a718e1a066 100644 --- a/test/unit/src/extras/curves/LineCurve.tests.js +++ b/test/unit/src/extras/curves/LineCurve.tests.js @@ -38,9 +38,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new LineCurve(); + assert.ok( object, 'Can instantiate a LineCurve.' ); } ); @@ -86,16 +87,16 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var curve = new LineCurve( _points[ 0 ], _points[ 3 ] ); + const curve = new LineCurve( _points[ 0 ], _points[ 3 ] ); - var expectedPoints = [ + const expectedPoints = [ new Vector2( 0, 0 ), new Vector2( - 2.4, 1.5 ), new Vector2( - 4, 2.5 ), new Vector2( - 8, 5 ) ]; - var points = [ + const points = [ curve.getPointAt( 0, new Vector2() ), curve.getPointAt( 0.3, new Vector2() ), curve.getPointAt( 0.5, new Vector2() ), @@ -106,17 +107,22 @@ export default QUnit.module( 'Extras', () => { } ); - QUnit.test( 'getTangent', ( assert ) => { + QUnit.test( 'getTangent/getTangentAt', ( assert ) => { - var curve = _curve; - var tangent = new Vector2(); + const curve = _curve; + const tangent = new Vector2(); curve.getTangent( 0, tangent ); - var expectedTangent = Math.sqrt( 0.5 ); + const expectedTangent = Math.sqrt( 0.5 ); assert.numEqual( tangent.x, expectedTangent, 'tangent.x correct' ); assert.numEqual( tangent.y, expectedTangent, 'tangent.y correct' ); + curve.getTangentAt( 0, tangent ); + + assert.numEqual( tangent.x, expectedTangent, 'tangentAt.x correct' ); + assert.numEqual( tangent.y, expectedTangent, 'tangentAt.y correct' ); + } ); QUnit.todo( 'copy', ( assert ) => { @@ -140,9 +146,9 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var curve = _curve; + let curve = _curve; - var expectedPoints = [ + let expectedPoints = [ new Vector2( 0, 0 ), new Vector2( 2, 2 ), new Vector2( 4, 4 ), @@ -151,7 +157,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 10 ) ]; - var points = curve.getPoints(); + let points = curve.getPoints(); assert.deepEqual( points, expectedPoints, 'Correct points for first curve' ); @@ -176,15 +182,15 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var curve = _curve; + const curve = _curve; - var length = curve.getLength(); - var expectedLength = Math.sqrt( 200 ); + const length = curve.getLength(); + const expectedLength = Math.sqrt( 200 ); assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var lengths = curve.getLengths( 5 ); - var expectedLengths = [ + const lengths = curve.getLengths( 5 ); + const expectedLengths = [ 0.0, Math.sqrt( 8 ), Math.sqrt( 32 ), @@ -205,11 +211,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var curve = _curve; + const curve = _curve; - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.3, 0 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.3, 0 ); assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -219,9 +225,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector2( 0, 0 ), new Vector2( 2.5, 2.5 ), new Vector2( 5, 5 ), @@ -229,7 +235,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 10 ) ]; - var points = curve.getSpacedPoints( 4 ); + const points = curve.getSpacedPoints( 4 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); diff --git a/test/unit/src/extras/curves/LineCurve3.tests.js b/test/unit/src/extras/curves/LineCurve3.tests.js index bbfd9d10854530..1e48047674150a 100644 --- a/test/unit/src/extras/curves/LineCurve3.tests.js +++ b/test/unit/src/extras/curves/LineCurve3.tests.js @@ -38,9 +38,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new LineCurve3(); + assert.ok( object, 'Can instantiate a LineCurve3.' ); } ); @@ -88,16 +89,16 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var curve = new LineCurve3( _points[ 0 ], _points[ 3 ] ); + const curve = new LineCurve3( _points[ 0 ], _points[ 3 ] ); - var expectedPoints = [ + const expectedPoints = [ new Vector3( 0, 0, 0 ), new Vector3( - 2.4, 1.5, - 2.1 ), new Vector3( - 4, 2.5, - 3.5 ), new Vector3( - 8, 5, - 7 ) ]; - var points = [ + const points = [ curve.getPointAt( 0, new Vector3() ), curve.getPointAt( 0.3, new Vector3() ), curve.getPointAt( 0.5, new Vector3() ), @@ -129,9 +130,9 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var curve = _curve; + let curve = _curve; - var expectedPoints = [ + let expectedPoints = [ new Vector3( 0, 0, 0 ), new Vector3( 2, 2, 2 ), new Vector3( 4, 4, 4 ), @@ -140,7 +141,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( 10, 10, 10 ) ]; - var points = curve.getPoints(); + let points = curve.getPoints(); assert.deepEqual( points, expectedPoints, 'Correct points for first curve' ); @@ -165,15 +166,15 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var curve = _curve; + const curve = _curve; - var length = curve.getLength(); - var expectedLength = Math.sqrt( 300 ); + const length = curve.getLength(); + const expectedLength = Math.sqrt( 300 ); assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var lengths = curve.getLengths( 5 ); - var expectedLengths = [ + const lengths = curve.getLengths( 5 ); + const expectedLengths = [ 0.0, Math.sqrt( 12 ), Math.sqrt( 48 ), @@ -194,11 +195,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent/getTangentAt', ( assert ) => { - var curve = _curve; - var tangent = new Vector3(); + const curve = _curve; + let tangent = new Vector3(); curve.getTangent( 0.5, tangent ); - var expectedTangent = Math.sqrt( 1 / 3 ); + const expectedTangent = Math.sqrt( 1 / 3 ); assert.numEqual( tangent.x, expectedTangent, 'tangent.x correct' ); assert.numEqual( tangent.y, expectedTangent, 'tangent.y correct' ); @@ -214,17 +215,17 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'computeFrenetFrames', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expected = { + const expected = { binormals: new Vector3( - 0.5 * Math.sqrt( 2 ), 0.5 * Math.sqrt( 2 ), 0 ), normals: new Vector3( Math.sqrt( 1 / 6 ), Math.sqrt( 1 / 6 ), - Math.sqrt( 2 / 3 ) ), tangents: new Vector3( Math.sqrt( 1 / 3 ), Math.sqrt( 1 / 3 ), Math.sqrt( 1 / 3 ) ) }; - var frames = curve.computeFrenetFrames( 1, false ); + const frames = curve.computeFrenetFrames( 1, false ); - for ( var val in expected ) { + for ( const val in expected ) { assert.numEqual( frames[ val ][ 0 ].x, expected[ val ].x, 'Frenet frames ' + val + '.x correct' ); assert.numEqual( frames[ val ][ 0 ].y, expected[ val ].y, 'Frenet frames ' + val + '.y correct' ); @@ -236,11 +237,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var curve = _curve; + const curve = _curve; - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.7, 0 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.7, 0 ); assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -250,9 +251,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector3( 0, 0, 0 ), new Vector3( 2.5, 2.5, 2.5 ), new Vector3( 5, 5, 5 ), @@ -260,7 +261,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( 10, 10, 10 ) ]; - var points = curve.getSpacedPoints( 4 ); + const points = curve.getSpacedPoints( 4 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); diff --git a/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js b/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js index 68f440b3309fa6..9f9a1b375dcca1 100644 --- a/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js +++ b/test/unit/src/extras/curves/QuadraticBezierCurve.tests.js @@ -34,9 +34,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new QuadraticBezierCurve(); + assert.ok( object, 'Can instantiate a QuadraticBezierCurve.' ); } ); @@ -110,9 +111,9 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( 2.5, 5.625 ), new Vector2( 10, 7.5 ), @@ -120,13 +121,13 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 0 ) ]; - var points = curve.getPoints( expectedPoints.length - 1 ); + let points = curve.getPoints( expectedPoints.length - 1 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry - var curveRev = new QuadraticBezierCurve( + const curveRev = new QuadraticBezierCurve( curve.v2, curve.v1, curve.v0 ); @@ -139,21 +140,21 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var curve = _curve; + const curve = _curve; - var length = curve.getLength(); - var expectedLength = 31.269026549416683; + const length = curve.getLength(); + const expectedLength = 31.269026549416683; assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var expectedLengths = [ + const expectedLengths = [ 0, 13.707320124663317, 21.43814317269643, 24.56314317269643, 30.718679298818998 ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); + const lengths = curve.getLengths( expectedLengths.length - 1 ); assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); @@ -167,16 +168,16 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( - 1.5127849599387615, 3.993582003773624 ), new Vector2( 4.310076165722796, 6.269921971403917 ), new Vector2( 10, 0 ) ]; - var points = [ + const points = [ curve.getPointAt( 0, new Vector2() ), curve.getPointAt( 0.3, new Vector2() ), curve.getPointAt( 0.5, new Vector2() ), @@ -189,9 +190,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent/getTangentAt', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedTangents = [ + let expectedTangents = [ new Vector2( 0.89443315420562, 0.44720166888975904 ), new Vector2( 0.936329177569021, 0.3511234415884543 ), new Vector2( 1, 0 ), @@ -199,7 +200,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( - 0.5546617882904897, - 0.8320758983472577 ) ]; - var tangents = [ + let tangents = [ curve.getTangent( 0, new Vector2() ), curve.getTangent( 0.25, new Vector2() ), curve.getTangent( 0.5, new Vector2() ), @@ -209,7 +210,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); @@ -236,7 +237,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); @@ -247,13 +248,13 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var curve = _curve; + const curve = _curve; - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.5, 1 ); - var expectedSomewhere = 0.015073978276116116; + const expectedSomewhere = 0.015073978276116116; assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -263,9 +264,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( - 4.366603655406173, 2.715408933540383 ), new Vector2( 1.3752241477827831, 5.191972084404416 ), @@ -274,7 +275,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 0 ) ]; - var points = curve.getSpacedPoints(); + const points = curve.getSpacedPoints(); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); diff --git a/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js b/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js index 60cf81c260ef8f..dde3e56a3557b9 100644 --- a/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js +++ b/test/unit/src/extras/curves/QuadraticBezierCurve3.tests.js @@ -34,9 +34,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new QuadraticBezierCurve3(); + assert.ok( object, 'Can instantiate a QuadraticBezierCurve3.' ); } ); @@ -110,9 +111,9 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 10, 0, 2 ), new Vector3( 2.5, 5.625, - 0.125 ), new Vector3( 10, 7.5, 0.5 ), @@ -120,13 +121,13 @@ export default QUnit.module( 'Extras', () => { new Vector3( 10, 0, 10 ) ]; - var points = curve.getPoints( expectedPoints.length - 1 ); + let points = curve.getPoints( expectedPoints.length - 1 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); // symmetry - var curveRev = new QuadraticBezierCurve3( + const curveRev = new QuadraticBezierCurve3( curve.v2, curve.v1, curve.v0 ); @@ -139,21 +140,21 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var curve = _curve; + const curve = _curve; - var length = curve.getLength(); - var expectedLength = 35.47294274967861; + const length = curve.getLength(); + const expectedLength = 35.47294274967861; assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var expectedLengths = [ + const expectedLengths = [ 0, 13.871057998581074, 21.62710402732536, 26.226696400568883, 34.91037361704809 ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); + const lengths = curve.getLengths( expectedLengths.length - 1 ); assert.strictEqual( lengths.length, expectedLengths.length, 'Correct number of segments' ); @@ -167,16 +168,16 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 10, 0, 2 ), new Vector3( - 0.4981634504454243, 4.427089043881476, 0.19308849757196012 ), new Vector3( 6.149415812887238, 6.838853310980195, - 0.20278120208668637 ), new Vector3( 10, 0, 10 ) ]; - var points = [ + const points = [ curve.getPointAt( 0, new Vector3() ), curve.getPointAt( 0.3, new Vector3() ), curve.getPointAt( 0.5, new Vector3() ), @@ -189,9 +190,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent/getTangentAt', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedTangents = [ + let expectedTangents = [ new Vector3( 0.8755715084258769, 0.4377711603816079, - 0.2042815331129452 ), new Vector3( 0.9340289249885844, 0.3502608468707904, - 0.07005216937416067 ), new Vector3( 0.9284766908853163, 0, 0.37139067635396156 ), @@ -199,7 +200,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( - 0.4263618889888853, - 0.6396068005601663, 0.6396238584473043 ) ]; - var tangents = [ + let tangents = [ curve.getTangent( 0, new Vector3() ), curve.getTangent( 0.25, new Vector3() ), curve.getTangent( 0.5, new Vector3() ), @@ -209,7 +210,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangent #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangent #' + i + ': y correct' ); @@ -236,7 +237,7 @@ export default QUnit.module( 'Extras', () => { expectedTangents.forEach( function ( exp, i ) { - var tangent = tangents[ i ]; + const tangent = tangents[ i ]; assert.numEqual( tangent.x, exp.x, 'getTangentAt #' + i + ': x correct' ); assert.numEqual( tangent.y, exp.y, 'getTangentAt #' + i + ': y correct' ); @@ -247,13 +248,13 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var curve = _curve; + const curve = _curve; - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const somewhere = curve.getUtoTmapping( 0.5, 1 ); - var expectedSomewhere = 0.014760890927167196; + const expectedSomewhere = 0.014760890927167196; assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -263,9 +264,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector3( - 10, 0, 2 ), new Vector3( - 3.712652983516992, 3.015179001762753, 0.6957120710270492 ), new Vector3( 2.7830973773262975, 5.730399338061483, - 0.1452668772806931 ), @@ -274,7 +275,7 @@ export default QUnit.module( 'Extras', () => { new Vector3( 10, 0, 10 ) ]; - var points = curve.getSpacedPoints(); + const points = curve.getSpacedPoints(); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); assert.deepEqual( points, expectedPoints, 'Correct points calculated' ); @@ -283,9 +284,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'computeFrenetFrames', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expected = { + const expected = { binormals: [ new Vector3( - 0.447201668889759, 0.8944331542056199, 0 ), new Vector3( - 0.2684231751110917, 0.9631753839815436, - 0.01556209353802903 ), @@ -303,7 +304,7 @@ export default QUnit.module( 'Extras', () => { ] }; - var frames = curve.computeFrenetFrames( 2, false ); + const frames = curve.computeFrenetFrames( 2, false ); Object.keys( expected ).forEach( function ( group, i ) { diff --git a/test/unit/src/extras/curves/SplineCurve.tests.js b/test/unit/src/extras/curves/SplineCurve.tests.js index 8380d1d6b1138f..d75379da0e28a0 100644 --- a/test/unit/src/extras/curves/SplineCurve.tests.js +++ b/test/unit/src/extras/curves/SplineCurve.tests.js @@ -36,9 +36,10 @@ export default QUnit.module( 'Extras', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new SplineCurve(); + assert.ok( object, 'Can instantiate a SplineCurve.' ); } ); @@ -97,9 +98,9 @@ export default QUnit.module( 'Extras', () => { // OTHERS QUnit.test( 'Simple curve', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( - 6.08, 4.56 ), new Vector2( - 2, 2.48 ), @@ -108,7 +109,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 0 ) ]; - var points = curve.getPoints( 5 ); + let points = curve.getPoints( 5 ); assert.strictEqual( points.length, expectedPoints.length, '1st: Correct number of points' ); @@ -129,14 +130,14 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getLength/getLengths', ( assert ) => { - var curve = _curve; + const curve = _curve; - var length = curve.getLength(); - var expectedLength = 28.876950901868135; + const length = curve.getLength(); + const expectedLength = 28.876950901868135; assert.numEqual( length, expectedLength, 'Correct length of curve' ); - var expectedLengths = [ + const expectedLengths = [ 0.0, Math.sqrt( 50 ), Math.sqrt( 200 ), @@ -144,7 +145,7 @@ export default QUnit.module( 'Extras', () => { Math.sqrt( 800 ) ]; - var lengths = curve.getLengths( 4 ); + const lengths = curve.getLengths( 4 ); assert.deepEqual( lengths, expectedLengths, 'Correct segment lengths' ); @@ -152,8 +153,8 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getPointAt', ( assert ) => { - var curve = _curve; - var point = new Vector2(); + const curve = _curve; + const point = new Vector2(); assert.ok( curve.getPointAt( 0, point ).equals( curve.points[ 0 ] ), 'PointAt 0.0 correct' ); assert.ok( curve.getPointAt( 1, point ).equals( curve.points[ 4 ] ), 'PointAt 1.0 correct' ); @@ -167,15 +168,15 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getTangent', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedTangent = [ + const expectedTangent = [ new Vector2( 0.7068243340243188, 0.7073891155729485 ), // 0 new Vector2( 0.7069654305325396, - 0.7072481035902046 ), // 0.5 new Vector2( 0.7068243340245123, 0.7073891155727552 ) // 1 ]; - var tangents = [ + const tangents = [ curve.getTangent( 0, new Vector2() ), curve.getTangent( 0.5, new Vector2() ), curve.getTangent( 1, new Vector2() ) @@ -192,11 +193,11 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getUtoTmapping', ( assert ) => { - var curve = _curve; + const curve = _curve; - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var middle = curve.getUtoTmapping( 0.5, 0 ); + const start = curve.getUtoTmapping( 0, 0 ); + const end = curve.getUtoTmapping( 0, curve.getLength() ); + const middle = curve.getUtoTmapping( 0.5, 0 ); assert.strictEqual( start, 0, 'getUtoTmapping( 0, 0 ) is the starting point' ); assert.strictEqual( end, 1, 'getUtoTmapping( 0, length ) is the ending point' ); @@ -206,9 +207,9 @@ export default QUnit.module( 'Extras', () => { QUnit.test( 'getSpacedPoints', ( assert ) => { - var curve = _curve; + const curve = _curve; - var expectedPoints = [ + const expectedPoints = [ new Vector2( - 10, 0 ), new Vector2( - 4.996509634683014, 4.999995128640857 ), new Vector2( 0, 0 ), @@ -216,7 +217,7 @@ export default QUnit.module( 'Extras', () => { new Vector2( 10, 0 ) ]; - var points = curve.getSpacedPoints( 4 ); + const points = curve.getSpacedPoints( 4 ); assert.strictEqual( points.length, expectedPoints.length, 'Correct number of points' ); diff --git a/test/unit/src/geometries/BoxGeometry.tests.js b/test/unit/src/geometries/BoxGeometry.tests.js index adca3fc3627264..707e74b92c6f0a 100644 --- a/test/unit/src/geometries/BoxGeometry.tests.js +++ b/test/unit/src/geometries/BoxGeometry.tests.js @@ -41,9 +41,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new BoxGeometry(); + assert.ok( object, 'Can instantiate a BoxGeometry.' ); } ); diff --git a/test/unit/src/geometries/CapsuleGeometry.tests.js b/test/unit/src/geometries/CapsuleGeometry.tests.js index 95222625dd18fe..ff81e38a2ee4b0 100644 --- a/test/unit/src/geometries/CapsuleGeometry.tests.js +++ b/test/unit/src/geometries/CapsuleGeometry.tests.js @@ -41,9 +41,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CapsuleGeometry(); + assert.ok( object, 'Can instantiate a CapsuleGeometry.' ); } ); diff --git a/test/unit/src/geometries/CircleGeometry.tests.js b/test/unit/src/geometries/CircleGeometry.tests.js index 6704204d41565e..3fb7f63b6991c4 100644 --- a/test/unit/src/geometries/CircleGeometry.tests.js +++ b/test/unit/src/geometries/CircleGeometry.tests.js @@ -41,9 +41,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CircleGeometry(); + assert.ok( object, 'Can instantiate a CircleGeometry.' ); } ); diff --git a/test/unit/src/geometries/ConeGeometry.tests.js b/test/unit/src/geometries/ConeGeometry.tests.js index 8dc63251d74bf1..d48e0520fcfb47 100644 --- a/test/unit/src/geometries/ConeGeometry.tests.js +++ b/test/unit/src/geometries/ConeGeometry.tests.js @@ -30,13 +30,13 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ConeGeometry(); + assert.ok( object, 'Can instantiate a ConeGeometry.' ); } ); - // PROPERTIES QUnit.test( 'type', ( assert ) => { diff --git a/test/unit/src/geometries/CylinderGeometry.tests.js b/test/unit/src/geometries/CylinderGeometry.tests.js index 1d6f31dd632c73..9201c83e569180 100644 --- a/test/unit/src/geometries/CylinderGeometry.tests.js +++ b/test/unit/src/geometries/CylinderGeometry.tests.js @@ -49,9 +49,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CylinderGeometry(); + assert.ok( object, 'Can instantiate a CylinderGeometry.' ); } ); diff --git a/test/unit/src/geometries/DodecahedronGeometry.tests.js b/test/unit/src/geometries/DodecahedronGeometry.tests.js index 14add3265b1126..ae86db279896ed 100644 --- a/test/unit/src/geometries/DodecahedronGeometry.tests.js +++ b/test/unit/src/geometries/DodecahedronGeometry.tests.js @@ -37,13 +37,13 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new DodecahedronGeometry(); + assert.ok( object, 'Can instantiate a DodecahedronGeometry.' ); } ); - // PROPERTIES QUnit.test( 'type', ( assert ) => { diff --git a/test/unit/src/geometries/EdgesGeometry.tests.js b/test/unit/src/geometries/EdgesGeometry.tests.js index 7cf5f92b6674cf..b75014c4ec97b2 100644 --- a/test/unit/src/geometries/EdgesGeometry.tests.js +++ b/test/unit/src/geometries/EdgesGeometry.tests.js @@ -225,9 +225,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new EdgesGeometry(); + assert.ok( object, 'Can instantiate an EdgesGeometry.' ); } ); @@ -269,7 +270,7 @@ export default QUnit.module( 'Geometries', () => { QUnit.test( 'two isolated triangles', ( assert ) => { - var vertList = [ + const vertList = [ new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 1, 1, 0 ), diff --git a/test/unit/src/geometries/ExtrudeGeometry.tests.js b/test/unit/src/geometries/ExtrudeGeometry.tests.js index ebadc51aeb872e..723370c0e2bf93 100644 --- a/test/unit/src/geometries/ExtrudeGeometry.tests.js +++ b/test/unit/src/geometries/ExtrudeGeometry.tests.js @@ -21,9 +21,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ExtrudeGeometry(); + assert.ok( object, 'Can instantiate an ExtrudeGeometry.' ); } ); diff --git a/test/unit/src/geometries/IcosahedronGeometry.tests.js b/test/unit/src/geometries/IcosahedronGeometry.tests.js index bbb37a7b0953e8..1a6feec512976c 100644 --- a/test/unit/src/geometries/IcosahedronGeometry.tests.js +++ b/test/unit/src/geometries/IcosahedronGeometry.tests.js @@ -37,9 +37,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new IcosahedronGeometry(); + assert.ok( object, 'Can instantiate an IcosahedronGeometry.' ); } ); diff --git a/test/unit/src/geometries/LatheGeometry.tests.js b/test/unit/src/geometries/LatheGeometry.tests.js index 1bb8183f6b356f..1521c501d0d4d6 100644 --- a/test/unit/src/geometries/LatheGeometry.tests.js +++ b/test/unit/src/geometries/LatheGeometry.tests.js @@ -37,9 +37,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new LatheGeometry(); + assert.ok( object, 'Can instantiate a LatheGeometry.' ); } ); diff --git a/test/unit/src/geometries/OctahedronGeometry.tests.js b/test/unit/src/geometries/OctahedronGeometry.tests.js index 9b84e860ceef92..787cee74c4ca6c 100644 --- a/test/unit/src/geometries/OctahedronGeometry.tests.js +++ b/test/unit/src/geometries/OctahedronGeometry.tests.js @@ -37,9 +37,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new OctahedronGeometry(); + assert.ok( object, 'Can instantiate an OctahedronGeometry.' ); } ); diff --git a/test/unit/src/geometries/PlaneGeometry.tests.js b/test/unit/src/geometries/PlaneGeometry.tests.js index 0150557116d7b4..ae6a62c8d2ab5c 100644 --- a/test/unit/src/geometries/PlaneGeometry.tests.js +++ b/test/unit/src/geometries/PlaneGeometry.tests.js @@ -41,9 +41,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PlaneGeometry(); + assert.ok( object, 'Can instantiate a PlaneGeometry.' ); } ); diff --git a/test/unit/src/geometries/PolyhedronGeometry.tests.js b/test/unit/src/geometries/PolyhedronGeometry.tests.js index db5da5a043ac9e..fd4eae61a8631f 100644 --- a/test/unit/src/geometries/PolyhedronGeometry.tests.js +++ b/test/unit/src/geometries/PolyhedronGeometry.tests.js @@ -38,9 +38,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PolyhedronGeometry(); + assert.ok( object, 'Can instantiate a PolyhedronGeometry.' ); } ); diff --git a/test/unit/src/geometries/RingGeometry.tests.js b/test/unit/src/geometries/RingGeometry.tests.js index 276bde5ac3abb9..93a2a6bd39d260 100644 --- a/test/unit/src/geometries/RingGeometry.tests.js +++ b/test/unit/src/geometries/RingGeometry.tests.js @@ -45,9 +45,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new RingGeometry(); + assert.ok( object, 'Can instantiate a RingGeometry.' ); } ); diff --git a/test/unit/src/geometries/ShapeGeometry.tests.js b/test/unit/src/geometries/ShapeGeometry.tests.js index ca69a23ca261a4..68f266722129f1 100644 --- a/test/unit/src/geometries/ShapeGeometry.tests.js +++ b/test/unit/src/geometries/ShapeGeometry.tests.js @@ -36,9 +36,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ShapeGeometry(); + assert.ok( object, 'Can instantiate a ShapeGeometry.' ); } ); diff --git a/test/unit/src/geometries/SphereGeometry.tests.js b/test/unit/src/geometries/SphereGeometry.tests.js index 0b35a08239f848..3bd5b51690aed4 100644 --- a/test/unit/src/geometries/SphereGeometry.tests.js +++ b/test/unit/src/geometries/SphereGeometry.tests.js @@ -47,9 +47,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new SphereGeometry(); + assert.ok( object, 'Can instantiate a SphereGeometry.' ); } ); diff --git a/test/unit/src/geometries/TetrahedronGeometry.tests.js b/test/unit/src/geometries/TetrahedronGeometry.tests.js index cea812758531ce..0a041d51cfe373 100644 --- a/test/unit/src/geometries/TetrahedronGeometry.tests.js +++ b/test/unit/src/geometries/TetrahedronGeometry.tests.js @@ -37,9 +37,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new TetrahedronGeometry(); + assert.ok( object, 'Can instantiate a TetrahedronGeometry.' ); } ); diff --git a/test/unit/src/geometries/TorusGeometry.tests.js b/test/unit/src/geometries/TorusGeometry.tests.js index 81a03e12c8b361..96d135fc7fcf83 100644 --- a/test/unit/src/geometries/TorusGeometry.tests.js +++ b/test/unit/src/geometries/TorusGeometry.tests.js @@ -43,9 +43,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new TorusGeometry(); + assert.ok( object, 'Can instantiate a TorusGeometry.' ); } ); diff --git a/test/unit/src/geometries/TorusKnotGeometry.tests.js b/test/unit/src/geometries/TorusKnotGeometry.tests.js index 21cb538deeaf59..73a8b8388290b7 100644 --- a/test/unit/src/geometries/TorusKnotGeometry.tests.js +++ b/test/unit/src/geometries/TorusKnotGeometry.tests.js @@ -44,9 +44,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new TorusKnotGeometry(); + assert.ok( object, 'Can instantiate a TorusKnotGeometry.' ); } ); diff --git a/test/unit/src/geometries/TubeGeometry.tests.js b/test/unit/src/geometries/TubeGeometry.tests.js index 2cae64a0fbb938..01aa3d2a1d00ab 100644 --- a/test/unit/src/geometries/TubeGeometry.tests.js +++ b/test/unit/src/geometries/TubeGeometry.tests.js @@ -35,9 +35,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new TubeGeometry(); + assert.ok( object, 'Can instantiate a TubeGeometry.' ); } ); diff --git a/test/unit/src/geometries/WireframeGeometry.tests.js b/test/unit/src/geometries/WireframeGeometry.tests.js index 8aa78265260ceb..d2e5f2e9ec9df3 100644 --- a/test/unit/src/geometries/WireframeGeometry.tests.js +++ b/test/unit/src/geometries/WireframeGeometry.tests.js @@ -30,9 +30,10 @@ export default QUnit.module( 'Geometries', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new WireframeGeometry(); + assert.ok( object, 'Can instantiate a WireframeGeometry.' ); } ); diff --git a/test/unit/src/helpers/ArrowHelper.tests.js b/test/unit/src/helpers/ArrowHelper.tests.js index b688469aa12918..720bc6870eb5c4 100644 --- a/test/unit/src/helpers/ArrowHelper.tests.js +++ b/test/unit/src/helpers/ArrowHelper.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ArrowHelper(); + assert.ok( object, 'Can instantiate an ArrowHelper.' ); } ); @@ -80,9 +81,12 @@ export default QUnit.module( 'Helpers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new ArrowHelper(); + object.dispose(); } ); diff --git a/test/unit/src/helpers/AxesHelper.tests.js b/test/unit/src/helpers/AxesHelper.tests.js index 343c0519bf49c5..bbc49c4cf18295 100644 --- a/test/unit/src/helpers/AxesHelper.tests.js +++ b/test/unit/src/helpers/AxesHelper.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new AxesHelper(); + assert.ok( object, 'Can instantiate an AxesHelper.' ); } ); @@ -44,9 +45,12 @@ export default QUnit.module( 'Helpers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new AxesHelper(); + object.dispose(); } ); diff --git a/test/unit/src/helpers/Box3Helper.tests.js b/test/unit/src/helpers/Box3Helper.tests.js index 763cdcccba6af6..abee0c637691e0 100644 --- a/test/unit/src/helpers/Box3Helper.tests.js +++ b/test/unit/src/helpers/Box3Helper.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Box3Helper(); + assert.ok( object, 'Can instantiate a Box3Helper.' ); } ); @@ -50,9 +51,12 @@ export default QUnit.module( 'Helpers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new Box3Helper(); + object.dispose(); } ); diff --git a/test/unit/src/helpers/BoxHelper.tests.js b/test/unit/src/helpers/BoxHelper.tests.js index 9c425b5ba9fce9..9ac5c03295d5e5 100644 --- a/test/unit/src/helpers/BoxHelper.tests.js +++ b/test/unit/src/helpers/BoxHelper.tests.js @@ -12,20 +12,22 @@ export default QUnit.module( 'Helpers', () => { QUnit.module( 'BoxHelper', ( hooks ) => { - var geometries = undefined; + let geometries = undefined; + hooks.beforeEach( function () { // Test with a normal cube and a box helper - var boxGeometry = new BoxGeometry(); - var box = new Mesh( boxGeometry ); - var boxHelper = new BoxHelper( box ); + const boxGeometry = new BoxGeometry(); + const box = new Mesh( boxGeometry ); + const boxHelper = new BoxHelper( box ); // The same should happen with a comparable sphere - var sphereGeometry = new SphereGeometry(); - var sphere = new Mesh( sphereGeometry ); - var sphereBoxHelper = new BoxHelper( sphere ); + const sphereGeometry = new SphereGeometry(); + const sphere = new Mesh( sphereGeometry ); + const sphereBoxHelper = new BoxHelper( sphere ); - // Note that unlike what I'd like to, these doesn't check the equivalency of the two generated geometries + // Note that unlike what I'd like to, these doesn't check the equivalency + // of the two generated geometries geometries = [ boxHelper.geometry, sphereBoxHelper.geometry ]; } ); @@ -42,9 +44,10 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new BoxHelper(); + assert.ok( object, 'Can instantiate a BoxHelper.' ); } ); @@ -90,9 +93,12 @@ export default QUnit.module( 'Helpers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new BoxHelper(); + object.dispose(); } ); diff --git a/test/unit/src/helpers/CameraHelper.tests.js b/test/unit/src/helpers/CameraHelper.tests.js index 93576ac97fc732..2f0a571d65d6aa 100644 --- a/test/unit/src/helpers/CameraHelper.tests.js +++ b/test/unit/src/helpers/CameraHelper.tests.js @@ -22,9 +22,11 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const camera = new PerspectiveCamera(); + const object = new CameraHelper( camera ); + assert.ok( object, 'Can instantiate a CameraHelper.' ); } ); @@ -77,9 +79,13 @@ export default QUnit.module( 'Helpers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const camera = new PerspectiveCamera(); + const object = new CameraHelper( camera ); + object.dispose(); } ); diff --git a/test/unit/src/helpers/DirectionalLightHelper.tests.js b/test/unit/src/helpers/DirectionalLightHelper.tests.js index cf52323a3a9d11..6a4fa621771bc8 100644 --- a/test/unit/src/helpers/DirectionalLightHelper.tests.js +++ b/test/unit/src/helpers/DirectionalLightHelper.tests.js @@ -28,9 +28,11 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const light = new DirectionalLight( parameters.color ); + const object = new DirectionalLightHelper( light, parameters.size, parameters.color ); + assert.ok( object, 'Can instantiate a DirectionalLightHelper.' ); } ); @@ -71,9 +73,13 @@ export default QUnit.module( 'Helpers', () => { } ); // PUBLIC - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const light = new DirectionalLight( parameters.color ); + const object = new DirectionalLightHelper( light, parameters.size, parameters.color ); + object.dispose(); } ); diff --git a/test/unit/src/helpers/GridHelper.tests.js b/test/unit/src/helpers/GridHelper.tests.js index e6cb0a65bc3ea7..a0d00425c2bf35 100644 --- a/test/unit/src/helpers/GridHelper.tests.js +++ b/test/unit/src/helpers/GridHelper.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new GridHelper(); + assert.ok( object, 'Can instantiate a GridHelper.' ); } ); @@ -38,9 +39,12 @@ export default QUnit.module( 'Helpers', () => { } ); // PUBLIC - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { + + assert.expect( 0 ); - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new GridHelper(); + object.dispose(); } ); diff --git a/test/unit/src/helpers/HemisphereLightHelper.tests.js b/test/unit/src/helpers/HemisphereLightHelper.tests.js index 180f8be3e7d231..1ce0681e4cb0ba 100644 --- a/test/unit/src/helpers/HemisphereLightHelper.tests.js +++ b/test/unit/src/helpers/HemisphereLightHelper.tests.js @@ -30,9 +30,11 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const light = new HemisphereLight( parameters.skyColor ); + const object = new HemisphereLightHelper( light, parameters.size, parameters.color ); + assert.ok( object, 'Can instantiate a HemisphereLightHelper.' ); } ); @@ -79,9 +81,13 @@ export default QUnit.module( 'Helpers', () => { } ); // PUBLIC - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const light = new HemisphereLight( parameters.skyColor ); + const object = new HemisphereLightHelper( light, parameters.size, parameters.color ); + object.dispose(); } ); diff --git a/test/unit/src/helpers/PlaneHelper.tests.js b/test/unit/src/helpers/PlaneHelper.tests.js index 1e20191db11fb9..3124577909ba73 100644 --- a/test/unit/src/helpers/PlaneHelper.tests.js +++ b/test/unit/src/helpers/PlaneHelper.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PlaneHelper(); + assert.ok( object, 'Can instantiate a PlaneHelper.' ); } ); @@ -56,9 +57,12 @@ export default QUnit.module( 'Helpers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new PlaneHelper(); + object.dispose(); } ); diff --git a/test/unit/src/helpers/PointLightHelper.tests.js b/test/unit/src/helpers/PointLightHelper.tests.js index 8785fcfc6e9424..ccccd4124d49d5 100644 --- a/test/unit/src/helpers/PointLightHelper.tests.js +++ b/test/unit/src/helpers/PointLightHelper.tests.js @@ -30,9 +30,11 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const light = new PointLight( parameters.color ); + const object = new PointLightHelper( light, parameters.sphereSize, parameters.color ); + assert.ok( object, 'Can instantiate a PointLightHelper.' ); } ); @@ -73,9 +75,13 @@ export default QUnit.module( 'Helpers', () => { } ); // PUBLIC - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const light = new PointLight( parameters.color ); + const object = new PointLightHelper( light, parameters.sphereSize, parameters.color ); + object.dispose(); } ); diff --git a/test/unit/src/helpers/PolarGridHelper.tests.js b/test/unit/src/helpers/PolarGridHelper.tests.js index 479b5f74316f2e..2067b7050e28e9 100644 --- a/test/unit/src/helpers/PolarGridHelper.tests.js +++ b/test/unit/src/helpers/PolarGridHelper.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PolarGridHelper(); + assert.ok( object, 'Can instantiate a PolarGridHelper.' ); } ); @@ -38,9 +39,12 @@ export default QUnit.module( 'Helpers', () => { } ); // PUBLIC - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { + + assert.expect( 0 ); - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PolarGridHelper(); + object.dispose(); } ); diff --git a/test/unit/src/helpers/SkeletonHelper.tests.js b/test/unit/src/helpers/SkeletonHelper.tests.js index 3bd4f9d4f3eeba..ad66cbeaed14d3 100644 --- a/test/unit/src/helpers/SkeletonHelper.tests.js +++ b/test/unit/src/helpers/SkeletonHelper.tests.js @@ -22,9 +22,11 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const bone = new Bone(); + const object = new SkeletonHelper( bone ); + assert.ok( object, 'Can instantiate a SkeletonHelper.' ); } ); @@ -82,9 +84,13 @@ export default QUnit.module( 'Helpers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const bone = new Bone(); + const object = new SkeletonHelper( bone ); + object.dispose(); } ); diff --git a/test/unit/src/helpers/SpotLightHelper.tests.js b/test/unit/src/helpers/SpotLightHelper.tests.js index c9d3afa72c2420..13583836a2f6bc 100644 --- a/test/unit/src/helpers/SpotLightHelper.tests.js +++ b/test/unit/src/helpers/SpotLightHelper.tests.js @@ -31,9 +31,11 @@ export default QUnit.module( 'Helpers', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const light = new SpotLight( parameters.color ); + const object = new SpotLightHelper( light, parameters.color ); + assert.ok( object, 'Can instantiate a SpotLightHelper.' ); } ); @@ -80,9 +82,13 @@ export default QUnit.module( 'Helpers', () => { } ); // PUBLIC - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const light = new SpotLight( parameters.color ); + const object = new SpotLightHelper( light, parameters.color ); + object.dispose(); } ); diff --git a/test/unit/src/lights/AmbientLight.tests.js b/test/unit/src/lights/AmbientLight.tests.js index 61d296db05049d..1e5c293966f728 100644 --- a/test/unit/src/lights/AmbientLight.tests.js +++ b/test/unit/src/lights/AmbientLight.tests.js @@ -37,9 +37,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new AmbientLight(); + assert.ok( object, 'Can instantiate an AmbientLight.' ); } ); diff --git a/test/unit/src/lights/AmbientLightProbe.tests.js b/test/unit/src/lights/AmbientLightProbe.tests.js index c1b892cf183e11..317b71dc3dff84 100644 --- a/test/unit/src/lights/AmbientLightProbe.tests.js +++ b/test/unit/src/lights/AmbientLightProbe.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new AmbientLightProbe(); + assert.ok( object, 'Can instantiate an AmbientLightProbe.' ); } ); diff --git a/test/unit/src/lights/DirectionalLight.tests.js b/test/unit/src/lights/DirectionalLight.tests.js index e0ee792a11f073..e75fa2d5e08fad 100644 --- a/test/unit/src/lights/DirectionalLight.tests.js +++ b/test/unit/src/lights/DirectionalLight.tests.js @@ -37,9 +37,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new DirectionalLight(); + assert.ok( object, 'Can instantiate a DirectionalLight.' ); } ); @@ -83,10 +84,14 @@ export default QUnit.module( 'Lights', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - // dispose() is called on shadow - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new DirectionalLight(); + object.dispose(); + + // ensure calls dispose() on shadow } ); diff --git a/test/unit/src/lights/DirectionalLightShadow.tests.js b/test/unit/src/lights/DirectionalLightShadow.tests.js index 65ed36033939c4..6fd382b1458609 100644 --- a/test/unit/src/lights/DirectionalLightShadow.tests.js +++ b/test/unit/src/lights/DirectionalLightShadow.tests.js @@ -22,9 +22,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new DirectionalLightShadow(); + assert.ok( object, 'Can instantiate a DirectionalLightShadow.' ); } ); diff --git a/test/unit/src/lights/HemisphereLight.tests.js b/test/unit/src/lights/HemisphereLight.tests.js index f0a7a966ffbe31..0c6ac25e047086 100644 --- a/test/unit/src/lights/HemisphereLight.tests.js +++ b/test/unit/src/lights/HemisphereLight.tests.js @@ -39,9 +39,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new HemisphereLight(); + assert.ok( object, 'Can instantiate a HemisphereLight.' ); } ); diff --git a/test/unit/src/lights/HemisphereLightProbe.tests.js b/test/unit/src/lights/HemisphereLightProbe.tests.js index d6ae4c0be1309d..9226428a8534de 100644 --- a/test/unit/src/lights/HemisphereLightProbe.tests.js +++ b/test/unit/src/lights/HemisphereLightProbe.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new HemisphereLightProbe(); + assert.ok( object, 'Can instantiate a HemisphereLightProbe.' ); } ); diff --git a/test/unit/src/lights/Light.tests.js b/test/unit/src/lights/Light.tests.js index 107332206852e5..bb7c10b265918e 100644 --- a/test/unit/src/lights/Light.tests.js +++ b/test/unit/src/lights/Light.tests.js @@ -37,9 +37,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Light(); + assert.ok( object, 'Can instantiate a Light.' ); } ); @@ -77,10 +78,13 @@ export default QUnit.module( 'Lights', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { + + assert.expect( 0 ); // empty, test exists - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Light(); + object.dispose(); } ); diff --git a/test/unit/src/lights/LightShadow.tests.js b/test/unit/src/lights/LightShadow.tests.js index 69bef01d52cdd4..0ee12b023de221 100644 --- a/test/unit/src/lights/LightShadow.tests.js +++ b/test/unit/src/lights/LightShadow.tests.js @@ -1,6 +1,7 @@ /* global QUnit */ import { LightShadow } from '../../../../src/lights/LightShadow.js'; + import { OrthographicCamera } from '../../../../src/cameras/OrthographicCamera.js'; export default QUnit.module( 'Lights', () => { @@ -8,9 +9,11 @@ export default QUnit.module( 'Lights', () => { QUnit.module( 'LightShadow', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const camera = new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ); + const object = new LightShadow( camera ); + assert.ok( object, 'Can instantiate a LightShadow.' ); } ); @@ -112,9 +115,12 @@ export default QUnit.module( 'Lights', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new LightShadow(); + object.dispose(); } ); diff --git a/test/unit/src/lights/PointLight.tests.js b/test/unit/src/lights/PointLight.tests.js index a46ba760abebae..d3ef923fb721f0 100644 --- a/test/unit/src/lights/PointLight.tests.js +++ b/test/unit/src/lights/PointLight.tests.js @@ -41,9 +41,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PointLight(); + assert.ok( object, 'Can instantiate a PointLight.' ); } ); @@ -102,10 +103,14 @@ export default QUnit.module( 'Lights', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { + + assert.expect( 0 ); + + const object = new PointLight(); + object.dispose(); // ensure calls dispose() on shadow - assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/PointLightShadow.tests.js b/test/unit/src/lights/PointLightShadow.tests.js index 73bb60c0d5855c..bc0a6c08fe848f 100644 --- a/test/unit/src/lights/PointLightShadow.tests.js +++ b/test/unit/src/lights/PointLightShadow.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PointLightShadow(); + assert.ok( object, 'Can instantiate a PointLightShadow.' ); } ); diff --git a/test/unit/src/lights/RectAreaLight.tests.js b/test/unit/src/lights/RectAreaLight.tests.js index 6a1b7d8568f8a1..5c1abe98e3ccdb 100644 --- a/test/unit/src/lights/RectAreaLight.tests.js +++ b/test/unit/src/lights/RectAreaLight.tests.js @@ -40,9 +40,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new RectAreaLight(); + assert.ok( object, 'Can instantiate a RectAreaLight.' ); } ); diff --git a/test/unit/src/lights/SpotLight.tests.js b/test/unit/src/lights/SpotLight.tests.js index 5a995fb88537af..b30efe8f74fc7b 100644 --- a/test/unit/src/lights/SpotLight.tests.js +++ b/test/unit/src/lights/SpotLight.tests.js @@ -44,9 +44,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new SpotLight(); + assert.ok( object, 'Can instantiate a SpotLight.' ); } ); @@ -135,10 +136,14 @@ export default QUnit.module( 'Lights', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { + + assert.expect( 0 ); + + const object = new SpotLight(); + object.dispose(); // ensure calls dispose() on shadow - assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/lights/SpotLightShadow.tests.js b/test/unit/src/lights/SpotLightShadow.tests.js index 5623ae6f10b7ce..87e782b02f9d49 100644 --- a/test/unit/src/lights/SpotLightShadow.tests.js +++ b/test/unit/src/lights/SpotLightShadow.tests.js @@ -22,9 +22,10 @@ export default QUnit.module( 'Lights', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new SpotLightShadow(); + assert.ok( object, 'Can instantiate a SpotLightShadow.' ); } ); @@ -82,16 +83,16 @@ export default QUnit.module( 'Lights', () => { QUnit.test( 'toJSON', ( assert ) => { - var light = new SpotLight(); - var shadow = new SpotLightShadow(); + const light = new SpotLight(); + const shadow = new SpotLightShadow(); shadow.bias = 10; shadow.radius = 5; shadow.mapSize.set( 128, 128 ); light.shadow = shadow; - var json = light.toJSON(); - var newLight = new ObjectLoader().parse( json ); + const json = light.toJSON(); + const newLight = new ObjectLoader().parse( json ); assert.smartEqual( newLight.shadow, light.shadow, 'Reloaded shadow is equal to the original one' ); diff --git a/test/unit/src/loaders/AnimationLoader.tests.js b/test/unit/src/loaders/AnimationLoader.tests.js index 8e45011a723447..0ac83227b5c43c 100644 --- a/test/unit/src/loaders/AnimationLoader.tests.js +++ b/test/unit/src/loaders/AnimationLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new AnimationLoader(); + assert.ok( object, 'Can instantiate an AnimationLoader.' ); } ); diff --git a/test/unit/src/loaders/AudioLoader.tests.js b/test/unit/src/loaders/AudioLoader.tests.js index ab8e5aac91d42b..44521852dad204 100644 --- a/test/unit/src/loaders/AudioLoader.tests.js +++ b/test/unit/src/loaders/AudioLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new AudioLoader(); + assert.ok( object, 'Can instantiate an AudioLoader.' ); } ); diff --git a/test/unit/src/loaders/BufferGeometryLoader.tests.js b/test/unit/src/loaders/BufferGeometryLoader.tests.js index 0e4aab3269cd0a..1fe327f1a10181 100644 --- a/test/unit/src/loaders/BufferGeometryLoader.tests.js +++ b/test/unit/src/loaders/BufferGeometryLoader.tests.js @@ -23,9 +23,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new BufferGeometryLoader(); + assert.ok( object, 'Can instantiate a BufferGeometryLoader.' ); } ); diff --git a/test/unit/src/loaders/CompressedTextureLoader.tests.js b/test/unit/src/loaders/CompressedTextureLoader.tests.js index b8c9899a39512d..4dc457c8433dad 100644 --- a/test/unit/src/loaders/CompressedTextureLoader.tests.js +++ b/test/unit/src/loaders/CompressedTextureLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CompressedTextureLoader(); + assert.ok( object, 'Can instantiate a CompressedTextureLoader.' ); } ); diff --git a/test/unit/src/loaders/CubeTextureLoader.tests.js b/test/unit/src/loaders/CubeTextureLoader.tests.js index 53c48ac6beed23..a424d610738c61 100644 --- a/test/unit/src/loaders/CubeTextureLoader.tests.js +++ b/test/unit/src/loaders/CubeTextureLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CubeTextureLoader(); + assert.ok( object, 'Can instantiate a CubeTextureLoader.' ); } ); diff --git a/test/unit/src/loaders/DataTextureLoader.tests.js b/test/unit/src/loaders/DataTextureLoader.tests.js index 532a14f7396442..bf0b3c4037745a 100644 --- a/test/unit/src/loaders/DataTextureLoader.tests.js +++ b/test/unit/src/loaders/DataTextureLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new DataTextureLoader(); + assert.ok( object, 'Can instantiate a DataTextureLoader.' ); } ); diff --git a/test/unit/src/loaders/FileLoader.tests.js b/test/unit/src/loaders/FileLoader.tests.js index 37d0f15526e976..92dd3300b03568 100644 --- a/test/unit/src/loaders/FileLoader.tests.js +++ b/test/unit/src/loaders/FileLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new FileLoader(); + assert.ok( object, 'Can instantiate a FileLoader.' ); } ); diff --git a/test/unit/src/loaders/ImageBitmapLoader.tests.js b/test/unit/src/loaders/ImageBitmapLoader.tests.js index 93ab42e9fec8e8..aa609dcbb8ef46 100644 --- a/test/unit/src/loaders/ImageBitmapLoader.tests.js +++ b/test/unit/src/loaders/ImageBitmapLoader.tests.js @@ -3,6 +3,7 @@ import { ImageBitmapLoader } from '../../../../src/loaders/ImageBitmapLoader.js'; import { Loader } from '../../../../src/loaders/Loader.js'; +import { CONSOLE_LEVEL } from '../../utils/console-wrapper.js'; export default QUnit.module( 'Loaders', () => { @@ -11,7 +12,13 @@ export default QUnit.module( 'Loaders', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { + // surpress the following console message when testing + // THREE.ImageBitmapLoader: createImageBitmap() not supported. + + console.level = CONSOLE_LEVEL.OFF; const object = new ImageBitmapLoader(); + console.level = CONSOLE_LEVEL.DEFAULT; + assert.strictEqual( object instanceof Loader, true, 'ImageBitmapLoader extends from Loader' @@ -20,16 +27,29 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // surpress the following console message when testing + // THREE.ImageBitmapLoader: createImageBitmap() not supported. + + console.level = CONSOLE_LEVEL.OFF; + const object = new ImageBitmapLoader(); + console.level = CONSOLE_LEVEL.DEFAULT; + + assert.ok( object, 'Can instantiate an ImageBitmapLoader.' ); } ); // PROPERTIES QUnit.test( 'options', ( assert ) => { + // surpress the following console message when testing in node + // THREE.ImageBitmapLoader: createImageBitmap() not supported. + + console.level = CONSOLE_LEVEL.OFF; const actual = new ImageBitmapLoader().options; + console.level = CONSOLE_LEVEL.DEFAULT; + const expected = { premultiplyAlpha: 'none' }; assert.deepEqual( actual, expected, 'ImageBitmapLoader defines options.' ); @@ -38,7 +58,13 @@ export default QUnit.module( 'Loaders', () => { // PUBLIC QUnit.test( 'isImageBitmapLoader', ( assert ) => { + // surpress the following console message when testing in node + // THREE.ImageBitmapLoader: createImageBitmap() not supported. + + console.level = CONSOLE_LEVEL.OFF; const object = new ImageBitmapLoader(); + console.level = CONSOLE_LEVEL.DEFAULT; + assert.ok( object.isImageBitmapLoader, 'ImageBitmapLoader.isImageBitmapLoader should be true' diff --git a/test/unit/src/loaders/ImageLoader.tests.js b/test/unit/src/loaders/ImageLoader.tests.js index b316e5d77059ff..36cb4aab728208 100644 --- a/test/unit/src/loaders/ImageLoader.tests.js +++ b/test/unit/src/loaders/ImageLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ImageLoader(); + assert.ok( object, 'Can instantiate an ImageLoader.' ); } ); diff --git a/test/unit/src/loaders/Loader.tests.js b/test/unit/src/loaders/Loader.tests.js index f411199c233530..93ade8bed2ae4f 100644 --- a/test/unit/src/loaders/Loader.tests.js +++ b/test/unit/src/loaders/Loader.tests.js @@ -9,9 +9,10 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'Loader', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Loader(); + assert.ok( object, 'Can instantiate a Loader.' ); } ); diff --git a/test/unit/src/loaders/LoaderUtils.tests.js b/test/unit/src/loaders/LoaderUtils.tests.js index 978d3c86895682..af7655e84bf610 100644 --- a/test/unit/src/loaders/LoaderUtils.tests.js +++ b/test/unit/src/loaders/LoaderUtils.tests.js @@ -9,10 +9,10 @@ export default QUnit.module( 'Loaders', () => { // STATIC QUnit.test( 'decodeText', ( assert ) => { - var jsonArray = new Uint8Array( [ 123, 34, 106, 115, 111, 110, 34, 58, 32, 116, 114, 117, 101, 125 ] ); + const jsonArray = new Uint8Array( [ 123, 34, 106, 115, 111, 110, 34, 58, 32, 116, 114, 117, 101, 125 ] ); assert.equal( '{"json": true}', LoaderUtils.decodeText( jsonArray ) ); - var multibyteArray = new Uint8Array( [ 230, 151, 165, 230, 156, 172, 229, 155, 189 ] ); + const multibyteArray = new Uint8Array( [ 230, 151, 165, 230, 156, 172, 229, 155, 189 ] ); assert.equal( '日本国', LoaderUtils.decodeText( multibyteArray ) ); } ); diff --git a/test/unit/src/loaders/LoadingManager.tests.js b/test/unit/src/loaders/LoadingManager.tests.js index 61e15ae657f2a3..0c1fb6939b2afd 100644 --- a/test/unit/src/loaders/LoadingManager.tests.js +++ b/test/unit/src/loaders/LoadingManager.tests.js @@ -9,10 +9,13 @@ export default QUnit.module( 'Loaders', () => { QUnit.module( 'LoadingManager', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - // constructor( onLoad, onProgress, onError ) - assert.ok( false, 'everything\'s gonna be alright' ); + // no params + const object = new LoadingManager(); + assert.ok( object, 'Can instantiate a LoadingManager.' ); + + // onLoad, onProgress, onError } ); diff --git a/test/unit/src/loaders/MaterialLoader.tests.js b/test/unit/src/loaders/MaterialLoader.tests.js index 2a6ba158f272c1..33062d391fe92b 100644 --- a/test/unit/src/loaders/MaterialLoader.tests.js +++ b/test/unit/src/loaders/MaterialLoader.tests.js @@ -29,9 +29,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MaterialLoader(); + assert.ok( object, 'Can instantiate a MaterialLoader.' ); } ); diff --git a/test/unit/src/loaders/ObjectLoader.tests.js b/test/unit/src/loaders/ObjectLoader.tests.js index 10403cbb9cd857..30c3ea0d977d31 100644 --- a/test/unit/src/loaders/ObjectLoader.tests.js +++ b/test/unit/src/loaders/ObjectLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ObjectLoader(); + assert.ok( object, 'Can instantiate an ObjectLoader.' ); } ); diff --git a/test/unit/src/loaders/TextureLoader.tests.js b/test/unit/src/loaders/TextureLoader.tests.js index 199b3fa65dbb4c..3b4897a323c1a0 100644 --- a/test/unit/src/loaders/TextureLoader.tests.js +++ b/test/unit/src/loaders/TextureLoader.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Loaders', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new TextureLoader(); + assert.ok( object, 'Can instantiate a TextureLoader.' ); } ); diff --git a/test/unit/src/materials/LineBasicMaterial.tests.js b/test/unit/src/materials/LineBasicMaterial.tests.js index 37da45ac032d03..b279b58a53bf73 100644 --- a/test/unit/src/materials/LineBasicMaterial.tests.js +++ b/test/unit/src/materials/LineBasicMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new LineBasicMaterial(); + assert.ok( object, 'Can instantiate a LineBasicMaterial.' ); } ); diff --git a/test/unit/src/materials/LineDashedMaterial.tests.js b/test/unit/src/materials/LineDashedMaterial.tests.js index f4670e3d440d80..39fd7895d47dcc 100644 --- a/test/unit/src/materials/LineDashedMaterial.tests.js +++ b/test/unit/src/materials/LineDashedMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new LineDashedMaterial(); + assert.ok( object, 'Can instantiate a LineDashedMaterial.' ); } ); diff --git a/test/unit/src/materials/Material.tests.js b/test/unit/src/materials/Material.tests.js index f5bd172c0755c4..96a256109cbf18 100644 --- a/test/unit/src/materials/Material.tests.js +++ b/test/unit/src/materials/Material.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Material(); + assert.ok( object, 'Can instantiate a Material.' ); } ); @@ -356,9 +357,12 @@ export default QUnit.module( 'Materials', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new Material(); + object.dispose(); } ); diff --git a/test/unit/src/materials/MeshBasicMaterial.tests.js b/test/unit/src/materials/MeshBasicMaterial.tests.js index 457338d7cc5b18..77d6526d1fcf43 100644 --- a/test/unit/src/materials/MeshBasicMaterial.tests.js +++ b/test/unit/src/materials/MeshBasicMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshBasicMaterial(); + assert.ok( object, 'Can instantiate a MeshBasicMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshDepthMaterial.tests.js b/test/unit/src/materials/MeshDepthMaterial.tests.js index 818d1b84ee1a39..372cbddc7086de 100644 --- a/test/unit/src/materials/MeshDepthMaterial.tests.js +++ b/test/unit/src/materials/MeshDepthMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshDepthMaterial(); + assert.ok( object, 'Can instantiate a MeshDepthMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshDistanceMaterial.tests.js b/test/unit/src/materials/MeshDistanceMaterial.tests.js index d051ebcd4e0d0b..e7b8307f459434 100644 --- a/test/unit/src/materials/MeshDistanceMaterial.tests.js +++ b/test/unit/src/materials/MeshDistanceMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshDistanceMaterial(); + assert.ok( object, 'Can instantiate a MeshDistanceMaterial.' ); } ); @@ -37,24 +38,6 @@ export default QUnit.module( 'Materials', () => { } ); - QUnit.todo( 'referencePosition', ( assert ) => { - - assert.ok( false, 'everything\'s gonna be alright' ); - - } ); - - QUnit.todo( 'nearDistance', ( assert ) => { - - assert.ok( false, 'everything\'s gonna be alright' ); - - } ); - - QUnit.todo( 'farDistance', ( assert ) => { - - assert.ok( false, 'everything\'s gonna be alright' ); - - } ); - QUnit.todo( 'map', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/materials/MeshLambertMaterial.tests.js b/test/unit/src/materials/MeshLambertMaterial.tests.js index 3349bcf291b506..b61fb64f3728c8 100644 --- a/test/unit/src/materials/MeshLambertMaterial.tests.js +++ b/test/unit/src/materials/MeshLambertMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshLambertMaterial(); + assert.ok( object, 'Can instantiate a MeshLambertMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshMatcapMaterial.tests.js b/test/unit/src/materials/MeshMatcapMaterial.tests.js index beadcab2c3c15f..9f23bc3e438b92 100644 --- a/test/unit/src/materials/MeshMatcapMaterial.tests.js +++ b/test/unit/src/materials/MeshMatcapMaterial.tests.js @@ -21,9 +21,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshMatcapMaterial(); + assert.ok( object, 'Can instantiate a MeshMatcapMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshNormalMaterial.tests.js b/test/unit/src/materials/MeshNormalMaterial.tests.js index 5389d492218f97..f1fe005d85ef7d 100644 --- a/test/unit/src/materials/MeshNormalMaterial.tests.js +++ b/test/unit/src/materials/MeshNormalMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshNormalMaterial(); + assert.ok( object, 'Can instantiate a MeshNormalMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshPhongMaterial.tests.js b/test/unit/src/materials/MeshPhongMaterial.tests.js index a22697dcfa6ad6..c3f5a206bd9d8e 100644 --- a/test/unit/src/materials/MeshPhongMaterial.tests.js +++ b/test/unit/src/materials/MeshPhongMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshPhongMaterial(); + assert.ok( object, 'Can instantiate a MeshPhongMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshPhysicalMaterial.tests.js b/test/unit/src/materials/MeshPhysicalMaterial.tests.js index 0d56e71e6b1f24..5f4882ce49f435 100644 --- a/test/unit/src/materials/MeshPhysicalMaterial.tests.js +++ b/test/unit/src/materials/MeshPhysicalMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshPhysicalMaterial(); + assert.ok( object, 'Can instantiate a MeshPhysicalMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshStandardMaterial.tests.js b/test/unit/src/materials/MeshStandardMaterial.tests.js index e738030fe69a06..9db8db00137d70 100644 --- a/test/unit/src/materials/MeshStandardMaterial.tests.js +++ b/test/unit/src/materials/MeshStandardMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshStandardMaterial(); + assert.ok( object, 'Can instantiate a MeshStandardMaterial.' ); } ); diff --git a/test/unit/src/materials/MeshToonMaterial.tests.js b/test/unit/src/materials/MeshToonMaterial.tests.js index ae5a78e3e3a850..547717eb376f29 100644 --- a/test/unit/src/materials/MeshToonMaterial.tests.js +++ b/test/unit/src/materials/MeshToonMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new MeshToonMaterial(); + assert.ok( object, 'Can instantiate a MeshToonMaterial.' ); } ); diff --git a/test/unit/src/materials/PointsMaterial.tests.js b/test/unit/src/materials/PointsMaterial.tests.js index 7f0c0739922042..6392b86f244776 100644 --- a/test/unit/src/materials/PointsMaterial.tests.js +++ b/test/unit/src/materials/PointsMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new PointsMaterial(); + assert.ok( object, 'Can instantiate a PointsMaterial.' ); } ); diff --git a/test/unit/src/materials/RawShaderMaterial.tests.js b/test/unit/src/materials/RawShaderMaterial.tests.js index 69401ae65c44d3..bcea52a1ae6972 100644 --- a/test/unit/src/materials/RawShaderMaterial.tests.js +++ b/test/unit/src/materials/RawShaderMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new RawShaderMaterial(); + assert.ok( object, 'Can instantiate a RawShaderMaterial.' ); } ); diff --git a/test/unit/src/materials/ShaderMaterial.tests.js b/test/unit/src/materials/ShaderMaterial.tests.js index a002428c42d51a..93a8aaed3c71ae 100644 --- a/test/unit/src/materials/ShaderMaterial.tests.js +++ b/test/unit/src/materials/ShaderMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ShaderMaterial(); + assert.ok( object, 'Can instantiate a ShaderMaterial.' ); } ); diff --git a/test/unit/src/materials/ShadowMaterial.tests.js b/test/unit/src/materials/ShadowMaterial.tests.js index 4bd194c4fa14fd..52a28d36e622a9 100644 --- a/test/unit/src/materials/ShadowMaterial.tests.js +++ b/test/unit/src/materials/ShadowMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new ShadowMaterial(); + assert.ok( object, 'Can instantiate a ShadowMaterial.' ); } ); diff --git a/test/unit/src/materials/SpriteMaterial.tests.js b/test/unit/src/materials/SpriteMaterial.tests.js index 49f0774266be97..4ec9b58b037eb3 100644 --- a/test/unit/src/materials/SpriteMaterial.tests.js +++ b/test/unit/src/materials/SpriteMaterial.tests.js @@ -20,9 +20,10 @@ export default QUnit.module( 'Materials', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new SpriteMaterial(); + assert.ok( object, 'Can instantiate a SpriteMaterial.' ); } ); diff --git a/test/unit/src/math/Box2.tests.js b/test/unit/src/math/Box2.tests.js index 739a37772b87eb..e4c742307797e5 100644 --- a/test/unit/src/math/Box2.tests.js +++ b/test/unit/src/math/Box2.tests.js @@ -18,15 +18,15 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Box2(); + let a = new Box2(); assert.ok( a.min.equals( posInf2 ), 'Passed!' ); assert.ok( a.max.equals( negInf2 ), 'Passed!' ); - var a = new Box2( zero2.clone(), zero2.clone() ); + a = new Box2( zero2.clone(), zero2.clone() ); assert.ok( a.min.equals( zero2 ), 'Passed!' ); assert.ok( a.max.equals( zero2 ), 'Passed!' ); - var a = new Box2( zero2.clone(), one2.clone() ); + a = new Box2( zero2.clone(), one2.clone() ); assert.ok( a.min.equals( zero2 ), 'Passed!' ); assert.ok( a.max.equals( one2 ), 'Passed!' ); @@ -35,17 +35,17 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'isBox2', ( assert ) => { - var a = new Box2(); + const a = new Box2(); assert.ok( a.isBox2 === true, 'Passed!' ); - var b = new Object(); + const b = new Object(); assert.ok( ! b.isBox2, 'Passed!' ); } ); QUnit.test( 'set', ( assert ) => { - var a = new Box2(); + const a = new Box2(); a.set( zero2, one2 ); assert.ok( a.min.equals( zero2 ), 'Passed!' ); @@ -55,7 +55,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromPoints', ( assert ) => { - var a = new Box2(); + const a = new Box2(); a.setFromPoints( [ zero2, one2, two2 ] ); assert.ok( a.min.equals( zero2 ), 'Passed!' ); @@ -72,7 +72,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromCenterAndSize', ( assert ) => { - var a = new Box2(); + const a = new Box2(); a.setFromCenterAndSize( zero2, two2 ); assert.ok( a.min.equals( negOne2 ), 'Passed!' ); @@ -90,15 +90,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { + let a = new Box2( zero2, zero2 ); - var a = new Box2( zero2, zero2 ); - - var b = a.clone(); + let b = a.clone(); assert.ok( b.min.equals( zero2 ), 'Passed!' ); assert.ok( b.max.equals( zero2 ), 'Passed!' ); a = new Box2(); - var b = a.clone(); + b = a.clone(); assert.ok( b.min.equals( posInf2 ), 'Passed!' ); assert.ok( b.max.equals( negInf2 ), 'Passed!' ); @@ -106,8 +105,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Box2( zero2.clone(), one2.clone() ); - var b = new Box2().copy( a ); + const a = new Box2( zero2.clone(), one2.clone() ); + const b = new Box2().copy( a ); assert.ok( b.min.equals( zero2 ), 'Passed!' ); assert.ok( b.max.equals( one2 ), 'Passed!' ); @@ -121,11 +120,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'empty/makeEmpty', ( assert ) => { - var a = new Box2(); + let a = new Box2(); assert.ok( a.isEmpty(), 'Passed!' ); - var a = new Box2( zero2.clone(), one2.clone() ); + a = new Box2( zero2.clone(), one2.clone() ); assert.ok( ! a.isEmpty(), 'Passed!' ); a.makeEmpty(); @@ -135,49 +134,49 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'isEmpty', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); + let a = new Box2( zero2.clone(), zero2.clone() ); assert.ok( ! a.isEmpty(), 'Passed!' ); - var a = new Box2( zero2.clone(), one2.clone() ); + a = new Box2( zero2.clone(), one2.clone() ); assert.ok( ! a.isEmpty(), 'Passed!' ); - var a = new Box2( two2.clone(), one2.clone() ); + a = new Box2( two2.clone(), one2.clone() ); assert.ok( a.isEmpty(), 'Passed!' ); - var a = new Box2( posInf2.clone(), negInf2.clone() ); + a = new Box2( posInf2.clone(), negInf2.clone() ); assert.ok( a.isEmpty(), 'Passed!' ); } ); QUnit.test( 'getCenter', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var center = new Vector2(); + let a = new Box2( zero2.clone(), zero2.clone() ); + const center = new Vector2(); assert.ok( a.getCenter( center ).equals( zero2 ), 'Passed!' ); - var a = new Box2( zero2, one2 ); - var midpoint = one2.clone().multiplyScalar( 0.5 ); + a = new Box2( zero2, one2 ); + const midpoint = one2.clone().multiplyScalar( 0.5 ); assert.ok( a.getCenter( center ).equals( midpoint ), 'Passed!' ); } ); QUnit.test( 'getSize', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var size = new Vector2(); + let a = new Box2( zero2.clone(), zero2.clone() ); + const size = new Vector2(); assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); - var a = new Box2( zero2.clone(), one2.clone() ); + a = new Box2( zero2.clone(), one2.clone() ); assert.ok( a.getSize( size ).equals( one2 ), 'Passed!' ); } ); QUnit.test( 'expandByPoint', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var size = new Vector2(); - var center = new Vector2(); + const a = new Box2( zero2.clone(), zero2.clone() ); + const size = new Vector2(); + const center = new Vector2(); a.expandByPoint( zero2 ); assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); @@ -193,9 +192,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'expandByVector', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var size = new Vector2(); - var center = new Vector2(); + const a = new Box2( zero2.clone(), zero2.clone() ); + const size = new Vector2(); + const center = new Vector2(); a.expandByVector( zero2 ); assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); @@ -208,9 +207,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'expandByScalar', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var size = new Vector2(); - var center = new Vector2(); + const a = new Box2( zero2.clone(), zero2.clone() ); + const size = new Vector2(); + const center = new Vector2(); a.expandByScalar( 0 ); assert.ok( a.getSize( size ).equals( zero2 ), 'Passed!' ); @@ -223,7 +222,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'containsPoint', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); assert.ok( a.containsPoint( zero2 ), 'Passed!' ); assert.ok( ! a.containsPoint( one2 ), 'Passed!' ); @@ -237,9 +236,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'containsBox', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); + const b = new Box2( zero2.clone(), one2.clone() ); + const c = new Box2( one2.clone().negate(), one2.clone() ); assert.ok( a.containsBox( a ), 'Passed!' ); assert.ok( ! a.containsBox( b ), 'Passed!' ); @@ -253,10 +252,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getParameter', ( assert ) => { - var a = new Box2( zero2.clone(), one2.clone() ); - var b = new Box2( one2.clone().negate(), one2.clone() ); + const a = new Box2( zero2.clone(), one2.clone() ); + const b = new Box2( one2.clone().negate(), one2.clone() ); - var parameter = new Vector2(); + const parameter = new Vector2(); a.getParameter( zero2, parameter ); assert.ok( parameter.equals( zero2 ), 'Passed!' ); @@ -274,9 +273,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsBox', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); + const b = new Box2( zero2.clone(), one2.clone() ); + const c = new Box2( one2.clone().negate(), one2.clone() ); assert.ok( a.intersectsBox( a ), 'Passed!' ); assert.ok( a.intersectsBox( b ), 'Passed!' ); @@ -295,10 +294,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clampPoint', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( one2.clone().negate(), one2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); + const b = new Box2( one2.clone().negate(), one2.clone() ); - var point = new Vector2(); + const point = new Vector2(); a.clampPoint( zero2, point ); assert.ok( point.equals( new Vector2( 0, 0 ) ), 'Passed!' ); @@ -322,8 +321,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceToPoint', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( one2.clone().negate(), one2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); + const b = new Box2( one2.clone().negate(), one2.clone() ); assert.ok( a.distanceToPoint( new Vector2( 0, 0 ) ) == 0, 'Passed!' ); assert.ok( a.distanceToPoint( new Vector2( 1, 1 ) ) == Math.sqrt( 2 ), 'Passed!' ); @@ -339,9 +338,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersect', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); + const b = new Box2( zero2.clone(), one2.clone() ); + const c = new Box2( one2.clone().negate(), one2.clone() ); assert.ok( a.clone().intersect( a ).equals( a ), 'Passed!' ); assert.ok( a.clone().intersect( b ).equals( a ), 'Passed!' ); @@ -350,13 +349,18 @@ export default QUnit.module( 'Maths', () => { assert.ok( b.clone().intersect( c ).equals( b ), 'Passed!' ); assert.ok( c.clone().intersect( c ).equals( c ), 'Passed!' ); + const d = new Box2( one2.clone().negate(), zero2.clone() ); + const e = new Box2( one2.clone(), two2.clone() ).intersect( d ); + + assert.ok( e.min.equals( posInf2 ) && e.max.equals( negInf2 ), 'Infinite empty' ); + } ); QUnit.test( 'union', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); + const b = new Box2( zero2.clone(), one2.clone() ); + const c = new Box2( one2.clone().negate(), one2.clone() ); assert.ok( a.clone().union( a ).equals( a ), 'Passed!' ); assert.ok( a.clone().union( b ).equals( b ), 'Passed!' ); @@ -367,9 +371,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'translate', ( assert ) => { - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), zero2.clone() ); + const a = new Box2( zero2.clone(), zero2.clone() ); + const b = new Box2( zero2.clone(), one2.clone() ); + const c = new Box2( one2.clone().negate(), zero2.clone() ); assert.ok( a.clone().translate( one2 ).equals( new Box2( one2, one2 ) ), 'Passed!' ); assert.ok( a.clone().translate( one2 ).translate( one2.clone().negate() ).equals( a ), 'Passed!' ); @@ -381,8 +385,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Box2(); - var b = new Box2(); + let a = new Box2(); + let b = new Box2(); assert.ok( b.equals( a ), 'Passed!' ); assert.ok( a.equals( b ), 'Passed!' ); diff --git a/test/unit/src/math/Box3.tests.js b/test/unit/src/math/Box3.tests.js index ae3681f0621346..14da461e2bfd69 100644 --- a/test/unit/src/math/Box3.tests.js +++ b/test/unit/src/math/Box3.tests.js @@ -35,15 +35,15 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Box3(); + let a = new Box3(); assert.ok( a.min.equals( posInf3 ), 'Passed!' ); assert.ok( a.max.equals( negInf3 ), 'Passed!' ); - var a = new Box3( zero3.clone(), zero3.clone() ); + a = new Box3( zero3.clone(), zero3.clone() ); assert.ok( a.min.equals( zero3 ), 'Passed!' ); assert.ok( a.max.equals( zero3 ), 'Passed!' ); - var a = new Box3( zero3.clone(), one3.clone() ); + a = new Box3( zero3.clone(), one3.clone() ); assert.ok( a.min.equals( zero3 ), 'Passed!' ); assert.ok( a.max.equals( one3 ), 'Passed!' ); @@ -52,17 +52,17 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'isBox3', ( assert ) => { - var a = new Box3(); + const a = new Box3(); assert.ok( a.isBox3 === true, 'Passed!' ); - var b = new Sphere(); + const b = new Sphere(); assert.ok( ! b.isBox3, 'Passed!' ); } ); QUnit.test( 'set', ( assert ) => { - var a = new Box3(); + const a = new Box3(); a.set( zero3, one3 ); assert.ok( a.min.equals( zero3 ), 'Passed!' ); @@ -72,7 +72,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromArray', ( assert ) => { - var a = new Box3(); + const a = new Box3(); a.setFromArray( [ 0, 0, 0, 1, 1, 1, 2, 2, 2 ] ); assert.ok( a.min.equals( zero3 ), 'Passed!' ); @@ -82,15 +82,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromBufferAttribute', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var bigger = new BufferAttribute( new Float32Array( [ + const a = new Box3( zero3.clone(), one3.clone() ); + const bigger = new BufferAttribute( new Float32Array( [ - 2, - 2, - 2, 2, 2, 2, 1.5, 1.5, 1.5, 0, 0, 0 ] ), 3 ); - var smaller = new BufferAttribute( new Float32Array( [ + const smaller = new BufferAttribute( new Float32Array( [ - 0.5, - 0.5, - 0.5, 0.5, 0.5, 0.5, 0, 0, 0 ] ), 3 ); - var newMin = new Vector3( - 2, - 2, - 2 ); - var newMax = new Vector3( 2, 2, 2 ); + const newMin = new Vector3( - 2, - 2, - 2 ); + const newMax = new Vector3( 2, 2, 2 ); a.setFromBufferAttribute( bigger ); assert.ok( a.min.equals( newMin ), 'Bigger box: correct new minimum' ); @@ -107,7 +107,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromPoints', ( assert ) => { - var a = new Box3(); + const a = new Box3(); a.setFromPoints( [ zero3, one3, two3 ] ); assert.ok( a.min.equals( zero3 ), 'Passed!' ); @@ -124,13 +124,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromCenterAndSize', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var b = a.clone(); - var centerA = new Vector3(); - var sizeA = new Vector3(); - var sizeB = new Vector3(); - var newCenter = one3; - var newSize = two3; + const a = new Box3( zero3.clone(), one3.clone() ); + const b = a.clone(); + const centerA = new Vector3(); + const sizeA = new Vector3(); + const sizeB = new Vector3(); + const newCenter = one3; + const newSize = two3; a.getCenter( centerA ); a.getSize( sizeA ); @@ -157,9 +157,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromObject/BufferGeometry', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var object = new Mesh( new BoxGeometry( 2, 2, 2 ) ); - var child = new Mesh( new BoxGeometry( 1, 1, 1 ) ); + const a = new Box3( zero3.clone(), one3.clone() ); + const object = new Mesh( new BoxGeometry( 2, 2, 2 ) ); + const child = new Mesh( new BoxGeometry( 1, 1, 1 ) ); object.add( child ); a.setFromObject( object ); @@ -170,22 +170,22 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromObject/Precise', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var object = new Mesh( new SphereGeometry( 1, 32, 32 ) ); - var child = new Mesh( new SphereGeometry( 2, 32, 32 ) ); + const a = new Box3( zero3.clone(), one3.clone() ); + const object = new Mesh( new SphereGeometry( 1, 32, 32 ) ); + const child = new Mesh( new SphereGeometry( 2, 32, 32 ) ); object.add( child ); object.rotation.setFromVector3( new Vector3( 0, 0, Math.PI / 4.0 ) ); a.setFromObject( object ); - var rotatedBox = new Box3( + const rotatedBox = new Box3( new Vector3( - 2 * Math.SQRT2, - 2 * Math.SQRT2, - 2 ), new Vector3( 2 * Math.SQRT2, 2 * Math.SQRT2, 2 ) ); assert.ok( compareBox( a, rotatedBox ), 'Passed!' ); a.setFromObject( object, true ); - var rotatedMinBox = new Box3( + const rotatedMinBox = new Box3( new Vector3( - 2, - 2, - 2 ), new Vector3( 2, 2, 2 ) ); @@ -195,14 +195,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); + let a = new Box3( zero3.clone(), one3.clone() ); - var b = a.clone(); + let b = a.clone(); assert.ok( b.min.equals( zero3 ), 'Passed!' ); assert.ok( b.max.equals( one3 ), 'Passed!' ); a = new Box3(); - var b = a.clone(); + b = a.clone(); assert.ok( b.min.equals( posInf3 ), 'Passed!' ); assert.ok( b.max.equals( negInf3 ), 'Passed!' ); @@ -210,8 +210,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Box3().copy( a ); + const a = new Box3( zero3.clone(), one3.clone() ); + const b = new Box3().copy( a ); assert.ok( b.min.equals( zero3 ), 'Passed!' ); assert.ok( b.max.equals( one3 ), 'Passed!' ); @@ -225,11 +225,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'empty/makeEmpty', ( assert ) => { - var a = new Box3(); + let a = new Box3(); assert.ok( a.isEmpty(), 'Passed!' ); - var a = new Box3( zero3.clone(), one3.clone() ); + a = new Box3( zero3.clone(), one3.clone() ); assert.ok( ! a.isEmpty(), 'Passed!' ); a.makeEmpty(); @@ -239,51 +239,50 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'isEmpty', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); + let a = new Box3( zero3.clone(), zero3.clone() ); assert.ok( ! a.isEmpty(), 'Passed!' ); - var a = new Box3( zero3.clone(), one3.clone() ); + a = new Box3( zero3.clone(), one3.clone() ); assert.ok( ! a.isEmpty(), 'Passed!' ); - var a = new Box3( two3.clone(), one3.clone() ); + a = new Box3( two3.clone(), one3.clone() ); assert.ok( a.isEmpty(), 'Passed!' ); - var a = new Box3( posInf3.clone(), negInf3.clone() ); + a = new Box3( posInf3.clone(), negInf3.clone() ); assert.ok( a.isEmpty(), 'Passed!' ); - } ); QUnit.test( 'getCenter', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var center = new Vector3(); + let a = new Box3( zero3.clone(), zero3.clone() ); + const center = new Vector3(); assert.ok( a.getCenter( center ).equals( zero3 ), 'Passed!' ); - var a = new Box3( zero3.clone(), one3.clone() ); - var midpoint = one3.clone().multiplyScalar( 0.5 ); + a = new Box3( zero3.clone(), one3.clone() ); + const midpoint = one3.clone().multiplyScalar( 0.5 ); assert.ok( a.getCenter( center ).equals( midpoint ), 'Passed!' ); } ); QUnit.test( 'getSize', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var size = new Vector3(); + let a = new Box3( zero3.clone(), zero3.clone() ); + const size = new Vector3(); assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); - var a = new Box3( zero3.clone(), one3.clone() ); + a = new Box3( zero3.clone(), one3.clone() ); assert.ok( a.getSize( size ).equals( one3 ), 'Passed!' ); } ); QUnit.test( 'expandByPoint', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var center = new Vector3(); - var size = new Vector3(); + const a = new Box3( zero3.clone(), zero3.clone() ); + const center = new Vector3(); + const size = new Vector3(); a.expandByPoint( zero3 ); assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); @@ -299,9 +298,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'expandByVector', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var center = new Vector3(); - var size = new Vector3(); + const a = new Box3( zero3.clone(), zero3.clone() ); + const center = new Vector3(); + const size = new Vector3(); a.expandByVector( zero3 ); assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); @@ -314,9 +313,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'expandByScalar', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var center = new Vector3(); - var size = new Vector3(); + const a = new Box3( zero3.clone(), zero3.clone() ); + const center = new Vector3(); + const size = new Vector3(); a.expandByScalar( 0 ); assert.ok( a.getSize( size ).equals( zero3 ), 'Passed!' ); @@ -329,11 +328,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'expandByObject', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var b = a.clone(); - var bigger = new Mesh( new BoxGeometry( 2, 2, 2 ) ); - var smaller = new Mesh( new BoxGeometry( 0.5, 0.5, 0.5 ) ); - var child = new Mesh( new BoxGeometry( 1, 1, 1 ) ); + const a = new Box3( zero3.clone(), one3.clone() ); + const b = a.clone(); + const bigger = new Mesh( new BoxGeometry( 2, 2, 2 ) ); + const smaller = new Mesh( new BoxGeometry( 0.5, 0.5, 0.5 ) ); + const child = new Mesh( new BoxGeometry( 1, 1, 1 ) ); // just a bigger box to begin with a.expandByObject( bigger ); @@ -374,7 +373,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'containsPoint', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); assert.ok( a.containsPoint( zero3 ), 'Passed!' ); assert.ok( ! a.containsPoint( one3 ), 'Passed!' ); @@ -388,9 +387,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'containsBox', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( zero3.clone(), one3.clone() ); + const c = new Box3( one3.clone().negate(), one3.clone() ); assert.ok( a.containsBox( a ), 'Passed!' ); assert.ok( ! a.containsBox( b ), 'Passed!' ); @@ -404,9 +403,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getParameter', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Box3( one3.clone().negate(), one3.clone() ); - var parameter = new Vector3(); + const a = new Box3( zero3.clone(), one3.clone() ); + const b = new Box3( one3.clone().negate(), one3.clone() ); + const parameter = new Vector3(); a.getParameter( zero3, parameter ); assert.ok( parameter.equals( zero3 ), 'Passed!' ); @@ -424,9 +423,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsBox', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( zero3.clone(), one3.clone() ); + const c = new Box3( one3.clone().negate(), one3.clone() ); assert.ok( a.intersectsBox( a ), 'Passed!' ); assert.ok( a.intersectsBox( b ), 'Passed!' ); @@ -445,8 +444,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsSphere', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Sphere( zero3.clone(), 1 ); + const a = new Box3( zero3.clone(), one3.clone() ); + const b = new Sphere( zero3.clone(), 1 ); assert.ok( a.intersectsSphere( b ), 'Passed!' ); @@ -457,16 +456,16 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsPlane', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); - var d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); - var e = new Plane( new Vector3( 0, 1, 0 ), 0.25 ); - var f = new Plane( new Vector3( 0, 1, 0 ), - 0.25 ); - var g = new Plane( new Vector3( 0, 1, 0 ), - 0.75 ); - var h = new Plane( new Vector3( 0, 1, 0 ), - 1 ); - var i = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.732 ); - var j = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.733 ); + const a = new Box3( zero3.clone(), one3.clone() ); + const b = new Plane( new Vector3( 0, 1, 0 ), 1 ); + const c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); + const d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); + const e = new Plane( new Vector3( 0, 1, 0 ), 0.25 ); + const f = new Plane( new Vector3( 0, 1, 0 ), - 0.25 ); + const g = new Plane( new Vector3( 0, 1, 0 ), - 0.75 ); + const h = new Plane( new Vector3( 0, 1, 0 ), - 1 ); + const i = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.732 ); + const j = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.733 ); assert.ok( ! a.intersectsPlane( b ), 'Passed!' ); assert.ok( ! a.intersectsPlane( c ), 'Passed!' ); @@ -482,12 +481,12 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsTriangle', ( assert ) => { - var a = new Box3( one3.clone(), two3.clone() ); - var b = new Triangle( new Vector3( 1.5, 1.5, 2.5 ), new Vector3( 2.5, 1.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - var c = new Triangle( new Vector3( 1.5, 1.5, 3.5 ), new Vector3( 3.5, 1.5, 1.5 ), new Vector3( 1.5, 1.5, 1.5 ) ); - var d = new Triangle( new Vector3( 1.5, 1.75, 3 ), new Vector3( 3, 1.75, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - var e = new Triangle( new Vector3( 1.5, 1.8, 3 ), new Vector3( 3, 1.8, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - var f = new Triangle( new Vector3( 1.5, 2.5, 3 ), new Vector3( 3, 2.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const a = new Box3( one3.clone(), two3.clone() ); + const b = new Triangle( new Vector3( 1.5, 1.5, 2.5 ), new Vector3( 2.5, 1.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const c = new Triangle( new Vector3( 1.5, 1.5, 3.5 ), new Vector3( 3.5, 1.5, 1.5 ), new Vector3( 1.5, 1.5, 1.5 ) ); + const d = new Triangle( new Vector3( 1.5, 1.75, 3 ), new Vector3( 3, 1.75, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const e = new Triangle( new Vector3( 1.5, 1.8, 3 ), new Vector3( 3, 1.8, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const f = new Triangle( new Vector3( 1.5, 2.5, 3 ), new Vector3( 3, 2.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); assert.ok( a.intersectsTriangle( b ), 'Passed!' ); assert.ok( a.intersectsTriangle( c ), 'Passed!' ); @@ -499,9 +498,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clampPoint', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( one3.clone().negate(), one3.clone() ); - var point = new Vector3(); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( one3.clone().negate(), one3.clone() ); + const point = new Vector3(); a.clampPoint( zero3, point ); assert.ok( point.equals( zero3 ), 'Passed!' ); @@ -525,8 +524,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceToPoint', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( one3.clone().negate(), one3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( one3.clone().negate(), one3.clone() ); assert.ok( a.distanceToPoint( new Vector3( 0, 0, 0 ) ) == 0, 'Passed!' ); assert.ok( a.distanceToPoint( new Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), 'Passed!' ); @@ -542,22 +541,25 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getBoundingSphere', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - var sphere = new Sphere(); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( zero3.clone(), one3.clone() ); + const c = new Box3( one3.clone().negate(), one3.clone() ); + const sphere = new Sphere(); assert.ok( a.getBoundingSphere( sphere ).equals( new Sphere( zero3, 0 ) ), 'Passed!' ); assert.ok( b.getBoundingSphere( sphere ).equals( new Sphere( one3.clone().multiplyScalar( 0.5 ), Math.sqrt( 3 ) * 0.5 ) ), 'Passed!' ); assert.ok( c.getBoundingSphere( sphere ).equals( new Sphere( zero3, Math.sqrt( 12 ) * 0.5 ) ), 'Passed!' ); + const d = new Box3().makeEmpty(); + assert.ok( d.getBoundingSphere( sphere ).isEmpty(), 'Empty box\'s bounding sphere is empty' ); + } ); QUnit.test( 'intersect', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( zero3.clone(), one3.clone() ); + const c = new Box3( one3.clone().negate(), one3.clone() ); assert.ok( a.clone().intersect( a ).equals( a ), 'Passed!' ); assert.ok( a.clone().intersect( b ).equals( a ), 'Passed!' ); @@ -570,9 +572,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'union', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( zero3.clone(), one3.clone() ); + const c = new Box3( one3.clone().negate(), one3.clone() ); assert.ok( a.clone().union( a ).equals( a ), 'Passed!' ); assert.ok( a.clone().union( b ).equals( b ), 'Passed!' ); @@ -583,13 +585,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - var d = new Box3( one3.clone().negate(), zero3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( zero3.clone(), one3.clone() ); + const c = new Box3( one3.clone().negate(), one3.clone() ); + const d = new Box3( one3.clone().negate(), zero3.clone() ); - var m = new Matrix4().makeTranslation( 1, - 2, 1 ); - var t1 = new Vector3( 1, - 2, 1 ); + const m = new Matrix4().makeTranslation( 1, - 2, 1 ); + const t1 = new Vector3( 1, - 2, 1 ); assert.ok( compareBox( a.clone().applyMatrix4( m ), a.clone().translate( t1 ) ), 'Passed!' ); assert.ok( compareBox( b.clone().applyMatrix4( m ), b.clone().translate( t1 ) ), 'Passed!' ); @@ -600,9 +602,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'translate', ( assert ) => { - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), zero3.clone() ); + const a = new Box3( zero3.clone(), zero3.clone() ); + const b = new Box3( zero3.clone(), one3.clone() ); + const c = new Box3( one3.clone().negate(), zero3.clone() ); assert.ok( a.clone().translate( one3 ).equals( new Box3( one3, one3 ) ), 'Passed!' ); assert.ok( a.clone().translate( one3 ).translate( one3.clone().negate() ).equals( a ), 'Passed!' ); @@ -613,8 +615,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Box3(); - var b = new Box3(); + let a = new Box3(); + let b = new Box3(); assert.ok( b.equals( a ), 'Passed!' ); assert.ok( a.equals( b ), 'Passed!' ); diff --git a/test/unit/src/math/Color.tests.js b/test/unit/src/math/Color.tests.js index 50141a201b6f5f..b6c9a19688b320 100644 --- a/test/unit/src/math/Color.tests.js +++ b/test/unit/src/math/Color.tests.js @@ -1,24 +1,36 @@ /* global QUnit */ import { Color } from '../../../../src/math/Color.js'; +import { ColorManagement } from '../../../../src/math/ColorManagement.js'; import { eps } from '../../utils/math-constants.js'; import { CONSOLE_LEVEL } from '../../utils/console-wrapper.js'; +import { DisplayP3ColorSpace, SRGBColorSpace } from '../../../../src/constants.js'; export default QUnit.module( 'Maths', () => { QUnit.module( 'Color', () => { + const colorManagementEnabled = ColorManagement.enabled; + + QUnit.testDone( () => { + + ColorManagement.enabled = colorManagementEnabled; + + } ); + // INSTANCING QUnit.test( 'Instancing', ( assert ) => { + ColorManagement.enabled = false; // TODO: Update and enable. + // default ctor - var c = new Color(); + let c = new Color(); assert.ok( c.r, 'Red: ' + c.r ); assert.ok( c.g, 'Green: ' + c.g ); assert.ok( c.b, 'Blue: ' + c.b ); // rgb ctor - var c = new Color( 1, 1, 1 ); + c = new Color( 1, 1, 1 ); assert.ok( c.r == 1, 'Passed' ); assert.ok( c.g == 1, 'Passed' ); assert.ok( c.b == 1, 'Passed' ); @@ -28,6 +40,9 @@ export default QUnit.module( 'Maths', () => { // EXPOSED CONSTANTS QUnit.test( 'Color.NAMES', ( assert ) => { + ColorManagement.enabled = false; // TODO: Update and enable. + + assert.ok( Color.NAMES.aliceblue == 0xF0F8FF, 'Exposed Color.NAMES' ); } ); @@ -35,20 +50,25 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'isColor', ( assert ) => { - var a = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color(); assert.ok( a.isColor === true, 'Passed!' ); - var b = new Object(); + const b = new Object(); assert.ok( ! b.isColor, 'Passed!' ); } ); QUnit.test( 'set', ( assert ) => { - var a = new Color(); - var b = new Color( 0.5, 0, 0 ); - var c = new Color( 0xFF0000 ); - var d = new Color( 0, 1.0, 0 ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color(); + const b = new Color( 0.5, 0, 0 ); + const c = new Color( 0xFF0000 ); + const d = new Color( 0, 1.0, 0 ); + const e = new Color( 0.5, 0.5, 0.5 ); a.set( b ); assert.ok( a.equals( b ), 'Set with Color instance' ); @@ -59,11 +79,16 @@ export default QUnit.module( 'Maths', () => { a.set( 'rgb(0,255,0)' ); assert.ok( a.equals( d ), 'Set with style' ); + a.set( 0.5, 0.5, 0.5 ); + assert.ok( a.equals( e ), 'Set with r,g,b components' ); + } ); QUnit.test( 'setScalar', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setScalar( 0.5 ); assert.ok( c.r == 0.5, 'Red: ' + c.r ); assert.ok( c.g == 0.5, 'Green: ' + c.g ); @@ -73,7 +98,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setHex', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setHex( 0xFA8072 ); assert.ok( c.getHex() == 0xFA8072, 'Hex: ' + c.getHex() ); assert.ok( c.r == 0xFA / 0xFF, 'Red: ' + c.r ); @@ -84,18 +111,42 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setRGB', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = true; + + const c = new Color(); + c.setRGB( 0.3, 0.5, 0.7 ); - assert.ok( c.r == 0.3, 'Red: ' + c.r ); - assert.ok( c.g == 0.5, 'Green: ' + c.g ); - assert.ok( c.b == 0.7, 'Blue: ' + c.b ); + + assert.equal( c.r, 0.3, 'Red: ' + c.r + ' (srgb-linear)' ); + assert.equal( c.g, 0.5, 'Green: ' + c.g + ' (srgb-linear)' ); + assert.equal( c.b, 0.7, 'Blue: ' + c.b + ' (srgb-linear)' ); + + c.setRGB( 0.3, 0.5, 0.7, SRGBColorSpace ); + + assert.equal( c.r.toFixed( 3 ), 0.073, 'Red: ' + c.r + ' (srgb)' ); + assert.equal( c.g.toFixed( 3 ), 0.214, 'Green: ' + c.g + ' (srgb)' ); + assert.equal( c.b.toFixed( 3 ), 0.448, 'Blue: ' + c.b + ' (srgb)' ); + + c.setRGB( 0.614, 0.731, 0.843, DisplayP3ColorSpace ); + + assert.numEqual( c.r.toFixed( 2 ), 0.3, 'Red: ' + c.r + ' (display-p3, in gamut)' ); + assert.numEqual( c.g.toFixed( 2 ), 0.5, 'Green: ' + c.g + ' (display-p3, in gamut)' ); + assert.numEqual( c.b.toFixed( 2 ), 0.7, 'Blue: ' + c.b + ' (display-p3, in gamut)' ); + + c.setRGB( 1.0, 0.5, 0.0, DisplayP3ColorSpace ); + + assert.numEqual( c.r.toFixed( 3 ), 1.179, 'Red: ' + c.r + ' (display-p3, out of gamut)' ); + assert.numEqual( c.g.toFixed( 3 ), 0.181, 'Green: ' + c.g + ' (display-p3, out of gamut)' ); + assert.numEqual( c.b.toFixed( 3 ), - 0.036, 'Blue: ' + c.b + ' (display-p3, out of gamut)' ); } ); QUnit.test( 'setHSL', ( assert ) => { - var c = new Color(); - var hsl = { h: 0, s: 0, l: 0 }; + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); + const hsl = { h: 0, s: 0, l: 0 }; c.setHSL( 0.75, 1.0, 0.25 ); c.getHSL( hsl ); @@ -107,9 +158,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyle', ( assert ) => { - var a = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. - var b = new Color( 8 / 255, 25 / 255, 178 / 255 ); + const a = new Color(); + + let b = new Color( 8 / 255, 25 / 255, 178 / 255 ); a.setStyle( 'rgb(8,25,178)' ); assert.ok( a.equals( b ), 'Passed' ); @@ -117,7 +170,7 @@ export default QUnit.module( 'Maths', () => { a.setStyle( 'rgba(8,25,178,200)' ); assert.ok( a.equals( b ), 'Passed' ); - var hsl = { h: 0, s: 0, l: 0 }; + let hsl = { h: 0, s: 0, l: 0 }; a.setStyle( 'hsl(270,50%,75%)' ); a.getHSL( hsl ); assert.ok( hsl.h == 0.75, 'hue: ' + hsl.h ); @@ -150,8 +203,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setColorName', ( assert ) => { - var c = new Color(); - var res = c.setColorName( 'aliceblue' ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); + const res = c.setColorName( 'aliceblue' ); assert.ok( c.getHex() == 0xF0F8FF, 'Hex: ' + c.getHex() ); assert.ok( c == res, 'Returns Self' ); @@ -160,16 +215,20 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var c = new Color( 'teal' ); - var c2 = c.clone(); + + ColorManagement.enabled = false; // TODO: Update and enable. + const c = new Color( 'teal' ); + const c2 = c.clone(); assert.ok( c2.getHex() == 0x008080, 'Hex c2: ' + c2.getHex() ); } ); QUnit.test( 'copy', ( assert ) => { - var a = new Color( 'teal' ); - var b = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 'teal' ); + const b = new Color(); b.copy( a ); assert.ok( b.r == 0x00 / 255, 'Red: ' + b.r ); assert.ok( b.g == 0x80 / 255, 'Green: ' + b.g ); @@ -179,8 +238,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copySRGBToLinear', ( assert ) => { - var c = new Color(); - var c2 = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); + const c2 = new Color(); c2.setRGB( 0.3, 0.5, 0.9 ); c.copySRGBToLinear( c2 ); assert.numEqual( c.r, 0.09, 'Red c: ' + c.r + ' Red c2: ' + c2.r ); @@ -191,8 +252,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copyLinearToSRGB', ( assert ) => { - var c = new Color(); - var c2 = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); + const c2 = new Color(); c2.setRGB( 0.09, 0.25, 0.81 ); c.copyLinearToSRGB( c2 ); assert.numEqual( c.r, 0.3, 'Red c: ' + c.r + ' Red c2: ' + c2.r ); @@ -203,7 +266,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'convertSRGBToLinear', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setRGB( 0.3, 0.5, 0.9 ); c.convertSRGBToLinear(); assert.numEqual( c.r, 0.09, 'Red: ' + c.r ); @@ -214,7 +279,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'convertLinearToSRGB', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setRGB( 4, 9, 16 ); c.convertLinearToSRGB(); assert.numEqual( c.r, 1.82, 'Red: ' + c.r ); @@ -225,24 +292,30 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getHex', ( assert ) => { - var c = new Color( 'red' ); - var res = c.getHex(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color( 'red' ); + const res = c.getHex(); assert.ok( res == 0xFF0000, 'Hex: ' + res ); } ); QUnit.test( 'getHexString', ( assert ) => { - var c = new Color( 'tomato' ); - var res = c.getHexString(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color( 'tomato' ); + const res = c.getHexString(); assert.ok( res == 'ff6347', 'Hex: ' + res ); } ); QUnit.test( 'getHSL', ( assert ) => { - var c = new Color( 0x80ffff ); - var hsl = { h: 0, s: 0, l: 0 }; + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color( 0x80ffff ); + const hsl = { h: 0, s: 0, l: 0 }; c.getHSL( hsl ); assert.ok( hsl.h == 0.5, 'hue: ' + hsl.h ); @@ -251,25 +324,50 @@ export default QUnit.module( 'Maths', () => { } ); - QUnit.todo( 'getRGB', ( assert ) => { + QUnit.test( 'getRGB', ( assert ) => { - // getRGB( target, colorSpace = ColorManagement.workingColorSpace ) - assert.ok( false, 'everything\'s gonna be alright' ); + ColorManagement.enabled = true; + + const c = new Color( 'plum' ); + const t = { r: 0, g: 0, b: 0 }; + + c.getRGB( t ); + + assert.equal( t.r.toFixed( 3 ), 0.723, 'r (srgb-linear)' ); + assert.equal( t.g.toFixed( 3 ), 0.352, 'g (srgb-linear)' ); + assert.equal( t.b.toFixed( 3 ), 0.723, 'b (srgb-linear)' ); + + c.getRGB( t, SRGBColorSpace ); + + assert.equal( t.r.toFixed( 3 ), ( 221 / 255 ).toFixed( 3 ), 'r (srgb)' ); + assert.equal( t.g.toFixed( 3 ), ( 160 / 255 ).toFixed( 3 ), 'g (srgb)' ); + assert.equal( t.b.toFixed( 3 ), ( 221 / 255 ).toFixed( 3 ), 'b (srgb)' ); + + c.getRGB( t, DisplayP3ColorSpace ); + + assert.equal( t.r.toFixed( 3 ), 0.831, 'r (display-p3)' ); + assert.equal( t.g.toFixed( 3 ), 0.637, 'g (display-p3)' ); + assert.equal( t.b.toFixed( 3 ), 0.852, 'b (display-p3)' ); } ); QUnit.test( 'getStyle', ( assert ) => { - var c = new Color( 'plum' ); - var res = c.getStyle(); - assert.ok( res == 'rgb(221,160,221)', 'style: ' + res ); + ColorManagement.enabled = true; + + const c = new Color( 'plum' ); + + assert.equal( c.getStyle(), 'rgb(221,160,221)', 'style: srgb' ); + assert.equal( c.getStyle( DisplayP3ColorSpace ), 'color(display-p3 0.831 0.637 0.852)', 'style: display-p3' ); } ); QUnit.test( 'offsetHSL', ( assert ) => { - var a = new Color( 'hsl(120,50%,50%)' ); - var b = new Color( 0.36, 0.84, 0.648 ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 'hsl(120,50%,50%)' ); + const b = new Color( 0.36, 0.84, 0.648 ); a.offsetHSL( 0.1, 0.1, 0.1 ); @@ -281,9 +379,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'add', ( assert ) => { - var a = new Color( 0x0000FF ); - var b = new Color( 0xFF0000 ); - var c = new Color( 0xFF00FF ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 0x0000FF ); + const b = new Color( 0xFF0000 ); + const c = new Color( 0xFF00FF ); a.add( b ); @@ -293,10 +393,12 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'addColors', ( assert ) => { - var a = new Color( 0x0000FF ); - var b = new Color( 0xFF0000 ); - var c = new Color( 0xFF00FF ); - var d = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 0x0000FF ); + const b = new Color( 0xFF0000 ); + const c = new Color( 0xFF00FF ); + const d = new Color(); d.addColors( a, b ); @@ -307,8 +409,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'addScalar', ( assert ) => { - var a = new Color( 0.1, 0.0, 0.0 ); - var b = new Color( 0.6, 0.5, 0.5 ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 0.1, 0.0, 0.0 ); + const b = new Color( 0.6, 0.5, 0.5 ); a.addScalar( 0.5 ); @@ -318,9 +422,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'sub', ( assert ) => { - var a = new Color( 0x0000CC ); - var b = new Color( 0xFF0000 ); - var c = new Color( 0x0000AA ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 0x0000CC ); + const b = new Color( 0xFF0000 ); + const c = new Color( 0x0000AA ); a.sub( b ); assert.strictEqual( a.getHex(), 0xCC, 'Difference too large' ); @@ -332,9 +438,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiply', ( assert ) => { - var a = new Color( 1, 0, 0.5 ); - var b = new Color( 0.5, 1, 0.5 ); - var c = new Color( 0.5, 0, 0.25 ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 1, 0, 0.5 ); + const b = new Color( 0.5, 1, 0.5 ); + const c = new Color( 0.5, 0, 0.25 ); a.multiply( b ); assert.ok( a.equals( c ), 'Check new value' ); @@ -343,8 +451,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiplyScalar', ( assert ) => { - var a = new Color( 0.25, 0, 0.5 ); - var b = new Color( 0.5, 0, 1 ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 0.25, 0, 0.5 ); + const b = new Color( 0.5, 0, 1 ); a.multiplyScalar( 2 ); assert.ok( a.equals( b ), 'Check new value' ); @@ -353,8 +463,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'lerp', ( assert ) => { - var c = new Color(); - var c2 = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); + const c2 = new Color(); c.setRGB( 0, 0, 0 ); c.lerp( c2, 0.2 ); assert.ok( c.r == 0.2, 'Red: ' + c.r ); @@ -379,8 +491,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Color( 0.5, 0.0, 1.0 ); - var b = new Color( 0.5, 1.0, 0.0 ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 0.5, 0.0, 1.0 ); + const b = new Color( 0.5, 1.0, 0.0 ); assert.strictEqual( a.r, b.r, 'Components: r is equal' ); assert.notStrictEqual( a.g, b.g, 'Components: g is not equal' ); @@ -401,8 +515,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var a = new Color(); - var array = [ 0.5, 0.6, 0.7, 0, 1, 0 ]; + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color(); + const array = [ 0.5, 0.6, 0.7, 0, 1, 0 ]; a.fromArray( array ); assert.strictEqual( a.r, 0.5, 'No offset: check r' ); @@ -418,21 +534,23 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var r = 0.5, g = 1.0, b = 0.0; - var a = new Color( r, g, b ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const r = 0.5, g = 1.0, b = 0.0; + const a = new Color( r, g, b ); - var array = a.toArray(); + let array = a.toArray(); assert.strictEqual( array[ 0 ], r, 'No array, no offset: check r' ); assert.strictEqual( array[ 1 ], g, 'No array, no offset: check g' ); assert.strictEqual( array[ 2 ], b, 'No array, no offset: check b' ); - var array = []; + array = []; a.toArray( array ); assert.strictEqual( array[ 0 ], r, 'With array, no offset: check r' ); assert.strictEqual( array[ 1 ], g, 'With array, no offset: check g' ); assert.strictEqual( array[ 2 ], b, 'With array, no offset: check b' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); assert.strictEqual( array[ 1 ], r, 'With array and offset: check r' ); @@ -450,13 +568,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toJSON', ( assert ) => { - var a = new Color( 0.0, 0.0, 0.0 ); - var b = new Color( 0.0, 0.5, 0.0 ); - var c = new Color( 1.0, 0.0, 0.0 ); - var d = new Color( 1.0, 1.0, 1.0 ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const a = new Color( 0.0, 0.0, 0.0 ); + const b = new Color( 0.0, 0.5, 0.0 ); + const c = new Color( 1.0, 0.0, 0.0 ); + const d = new Color( 1.0, 1.0, 1.0 ); assert.strictEqual( a.toJSON(), 0x000000, 'Check black' ); - assert.strictEqual( b.toJSON(), 0x007F00, 'Check half-blue' ); + assert.strictEqual( b.toJSON(), 0x008000, 'Check half-blue' ); assert.strictEqual( c.toJSON(), 0xFF0000, 'Check red' ); assert.strictEqual( d.toJSON(), 0xFFFFFF, 'Check white' ); @@ -465,8 +585,10 @@ export default QUnit.module( 'Maths', () => { // OTHERS - FUNCTIONAL QUnit.test( 'copyHex', ( assert ) => { - var c = new Color(); - var c2 = new Color( 0xF5FFFA ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); + const c2 = new Color( 0xF5FFFA ); c.copy( c2 ); assert.ok( c.getHex() == c2.getHex(), 'Hex c: ' + c.getHex() + ' Hex c2: ' + c2.getHex() ); @@ -474,8 +596,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copyColorString', ( assert ) => { - var c = new Color(); - var c2 = new Color( 'ivory' ); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); + const c2 = new Color( 'ivory' ); c.copy( c2 ); assert.ok( c.getHex() == c2.getHex(), 'Hex c: ' + c.getHex() + ' Hex c2: ' + c2.getHex() ); @@ -483,7 +607,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setWithNum', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.set( 0xFF0000 ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g === 0, 'Green: ' + c.g ); @@ -493,7 +619,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setWithString', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.set( 'silver' ); assert.ok( c.getHex() == 0xC0C0C0, 'Hex c: ' + c.getHex() ); @@ -501,7 +629,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBRed', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'rgb(255,0,0)' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g === 0, 'Green: ' + c.g ); @@ -511,7 +641,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBARed', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); console.level = CONSOLE_LEVEL.ERROR; c.setStyle( 'rgba(255,0,0,0.5)' ); @@ -525,7 +657,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBRedWithSpaces', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'rgb( 255 , 0, 0 )' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g === 0, 'Green: ' + c.g ); @@ -535,7 +669,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBARedWithSpaces', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'rgba( 255, 0, 0 , 1 )' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g === 0, 'Green: ' + c.g ); @@ -545,7 +681,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBPercent', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'rgb(100%,50%,10%)' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g == 0.5, 'Green: ' + c.g ); @@ -555,7 +693,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBAPercent', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); console.level = CONSOLE_LEVEL.ERROR; c.setStyle( 'rgba(100%,50%,10%, 0.5)' ); @@ -569,7 +709,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBPercentWithSpaces', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'rgb( 100% ,50% , 10% )' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g == 0.5, 'Green: ' + c.g ); @@ -579,7 +721,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleRGBAPercentWithSpaces', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); console.level = CONSOLE_LEVEL.ERROR; c.setStyle( 'rgba( 100% ,50% , 10%, 0.5 )' ); @@ -593,7 +737,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHSLRed', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'hsl(360,100%,50%)' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g === 0, 'Green: ' + c.g ); @@ -603,7 +749,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHSLARed', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); console.level = CONSOLE_LEVEL.ERROR; c.setStyle( 'hsla(360,100%,50%,0.5)' ); @@ -617,7 +765,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHSLRedWithSpaces', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'hsl(360, 100% , 50% )' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g === 0, 'Green: ' + c.g ); @@ -627,7 +777,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHSLARedWithSpaces', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); console.level = CONSOLE_LEVEL.ERROR; c.setStyle( 'hsla( 360, 100% , 50%, 0.5 )' ); @@ -641,7 +793,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHSLRedWithDecimals', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'hsl(360,100.0%,50.0%)' ); assert.ok( c.r == 1, 'Red: ' + c.r ); assert.ok( c.g === 0, 'Green: ' + c.g ); @@ -651,7 +805,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHSLARedWithDecimals', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); console.level = CONSOLE_LEVEL.ERROR; c.setStyle( 'hsla(360,100.0%,50.0%,0.5)' ); @@ -665,7 +821,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHexSkyBlue', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( '#87CEEB' ); assert.ok( c.getHex() == 0x87CEEB, 'Hex c: ' + c.getHex() ); @@ -673,7 +831,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHexSkyBlueMixed', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( '#87cEeB' ); assert.ok( c.getHex() == 0x87CEEB, 'Hex c: ' + c.getHex() ); @@ -681,7 +841,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHex2Olive', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( '#F00' ); assert.ok( c.getHex() == 0xFF0000, 'Hex c: ' + c.getHex() ); @@ -689,7 +851,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleHex2OliveMixed', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( '#f00' ); assert.ok( c.getHex() == 0xFF0000, 'Hex c: ' + c.getHex() ); @@ -697,7 +861,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setStyleColorName', ( assert ) => { - var c = new Color(); + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color(); c.setStyle( 'powderblue' ); assert.ok( c.getHex() == 0xB0E0E6, 'Hex c: ' + c.getHex() ); @@ -705,8 +871,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'iterable', ( assert ) => { - var c = new Color( 0.5, 0.75, 1 ); - var array = [ ...c ]; + ColorManagement.enabled = false; // TODO: Update and enable. + + const c = new Color( 0.5, 0.75, 1 ); + const array = [ ...c ]; assert.strictEqual( array[ 0 ], 0.5, 'Color is iterable.' ); assert.strictEqual( array[ 1 ], 0.75, 'Color is iterable.' ); assert.strictEqual( array[ 2 ], 1, 'Color is iterable.' ); diff --git a/test/unit/src/math/ColorManagement.tests.js b/test/unit/src/math/ColorManagement.tests.js index afad9695c89c3c..21bf42bf3b82fb 100644 --- a/test/unit/src/math/ColorManagement.tests.js +++ b/test/unit/src/math/ColorManagement.tests.js @@ -2,16 +2,34 @@ import { ColorManagement } from '../../../../src/math/ColorManagement.js'; +import { CONSOLE_LEVEL } from '../../utils/console-wrapper.js'; + export default QUnit.module( 'Maths', () => { QUnit.module( 'ColorManagement', () => { // PROPERTIES + QUnit.test( 'enabled', ( assert ) => { + + assert.strictEqual( + ColorManagement.enabled, true, + 'ColorManagement.enabled is true by default.' + ); + + } ); + QUnit.test( 'legacyMode', ( assert ) => { + // surpress the following console message during testing + // THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150. + + console.level = CONSOLE_LEVEL.OFF; + const expected = ColorManagement.legacyMode === false; + console.level = CONSOLE_LEVEL.DEFAULT; + assert.ok( - ColorManagement.legacyMode == true, - 'ColorManagement.legacyMode is true by default.' + expected, + 'ColorManagement.legacyMode is false by default.' ); } ); diff --git a/test/unit/src/math/Cylindrical.tests.js b/test/unit/src/math/Cylindrical.tests.js index a6d95a154e16be..d65686bd850c77 100644 --- a/test/unit/src/math/Cylindrical.tests.js +++ b/test/unit/src/math/Cylindrical.tests.js @@ -11,16 +11,16 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Cylindrical(); - var radius = 10.0; - var theta = Math.PI; - var y = 5; + let a = new Cylindrical(); + const radius = 10.0; + const theta = Math.PI; + const y = 5; assert.strictEqual( a.radius, 1.0, 'Default values: check radius' ); assert.strictEqual( a.theta, 0, 'Default values: check theta' ); assert.strictEqual( a.y, 0, 'Default values: check y' ); - var a = new Cylindrical( radius, theta, y ); + a = new Cylindrical( radius, theta, y ); assert.strictEqual( a.radius, radius, 'Custom values: check radius' ); assert.strictEqual( a.theta, theta, 'Custom values: check theta' ); assert.strictEqual( a.y, y, 'Custom values: check y' ); @@ -30,10 +30,10 @@ export default QUnit.module( 'Maths', () => { // PUBLIC QUnit.test( 'set', ( assert ) => { - var a = new Cylindrical(); - var radius = 10.0; - var theta = Math.PI; - var y = 5; + const a = new Cylindrical(); + const radius = 10.0; + const theta = Math.PI; + const y = 5; a.set( radius, theta, y ); assert.strictEqual( a.radius, radius, 'Check radius' ); @@ -44,11 +44,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var radius = 10.0; - var theta = Math.PI; - var y = 5; - var a = new Cylindrical( radius, theta, y ); - var b = a.clone(); + const radius = 10.0; + const theta = Math.PI; + const y = 5; + const a = new Cylindrical( radius, theta, y ); + const b = a.clone(); assert.propEqual( a, b, 'Check a and b are equal after clone()' ); @@ -59,11 +59,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var radius = 10.0; - var theta = Math.PI; - var y = 5; - var a = new Cylindrical( radius, theta, y ); - var b = new Cylindrical().copy( a ); + const radius = 10.0; + const theta = Math.PI; + const y = 5; + const a = new Cylindrical( radius, theta, y ); + const b = new Cylindrical().copy( a ); assert.propEqual( a, b, 'Check a and b are equal after copy()' ); @@ -74,10 +74,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromVector3', ( assert ) => { - var a = new Cylindrical( 1, 1, 1 ); - var b = new Vector3( 0, 0, 0 ); - var c = new Vector3( 3, - 1, - 3 ); - var expected = new Cylindrical( Math.sqrt( 9 + 9 ), Math.atan2( 3, - 3 ), - 1 ); + const a = new Cylindrical( 1, 1, 1 ); + const b = new Vector3( 0, 0, 0 ); + const c = new Vector3( 3, - 1, - 3 ); + const expected = new Cylindrical( Math.sqrt( 9 + 9 ), Math.atan2( 3, - 3 ), - 1 ); a.setFromVector3( b ); assert.strictEqual( a.radius, 0, 'Zero-length vector: check radius' ); diff --git a/test/unit/src/math/Euler.tests.js b/test/unit/src/math/Euler.tests.js index b6c7f778ce060f..7332661c58c7b1 100644 --- a/test/unit/src/math/Euler.tests.js +++ b/test/unit/src/math/Euler.tests.js @@ -19,9 +19,9 @@ function matrixEquals4( a, b, tolerance ) { } - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { + for ( let i = 0, il = a.elements.length; i < il; i ++ ) { - var delta = a.elements[ i ] - b.elements[ i ]; + const delta = a.elements[ i ] - b.elements[ i ]; if ( delta > tolerance ) { return false; @@ -37,7 +37,7 @@ function matrixEquals4( a, b, tolerance ) { function quatEquals( a, b, tolerance ) { tolerance = tolerance || 0.0001; - var diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ) + Math.abs( a.w - b.w ); + const diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ) + Math.abs( a.w - b.w ); return ( diff < tolerance ); @@ -50,7 +50,7 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Euler(); + const a = new Euler(); assert.ok( a.equals( eulerZero ), 'Passed!' ); assert.ok( ! a.equals( eulerAxyz ), 'Passed!' ); assert.ok( ! a.equals( eulerAzyx ), 'Passed!' ); @@ -69,7 +69,7 @@ export default QUnit.module( 'Maths', () => { // PROPERTIES STUFF QUnit.test( 'x', ( assert ) => { - var a = new Euler(); + let a = new Euler(); assert.ok( a.x === 0, 'Passed!' ); a = new Euler( 1, 2, 3 ); @@ -83,7 +83,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.x === 10, 'Passed!' ); a = new Euler( 11, 12, 13, 'XYZ' ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -98,7 +98,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'y', ( assert ) => { - var a = new Euler(); + let a = new Euler(); assert.ok( a.y === 0, 'Passed!' ); a = new Euler( 1, 2, 3 ); @@ -112,7 +112,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.y === 10, 'Passed!' ); a = new Euler( 11, 12, 13, 'XYZ' ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -127,7 +127,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'z', ( assert ) => { - var a = new Euler(); + let a = new Euler(); assert.ok( a.z === 0, 'Passed!' ); a = new Euler( 1, 2, 3 ); @@ -141,7 +141,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.z === 10, 'Passed!' ); a = new Euler( 11, 12, 13, 'XYZ' ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -156,7 +156,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'order', ( assert ) => { - var a = new Euler(); + let a = new Euler(); assert.ok( a.order === Euler.DEFAULT_ORDER, 'Passed!' ); a = new Euler( 1, 2, 3 ); @@ -170,7 +170,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.order === 'ZXY', 'Passed!' ); a = new Euler( 11, 12, 13, 'YZX' ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -186,9 +186,9 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'isEuler', ( assert ) => { - var a = new Euler(); + const a = new Euler(); assert.ok( a.isEuler, 'Passed!' ); - var b = new Vector3(); + const b = new Vector3(); assert.ok( ! b.isEuler, 'Passed!' ); @@ -196,7 +196,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone/copy/equals', ( assert ) => { - var a = eulerAxyz.clone(); + const a = eulerAxyz.clone(); assert.ok( a.equals( eulerAxyz ), 'Passed!' ); assert.ok( ! a.equals( eulerZero ), 'Passed!' ); assert.ok( ! a.equals( eulerAzyx ), 'Passed!' ); @@ -210,14 +210,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'Quaternion.setFromEuler/Euler.setFromQuaternion', ( assert ) => { - var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; - for ( var i = 0; i < testValues.length; i ++ ) { + const testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; + for ( let i = 0; i < testValues.length; i ++ ) { - var v = testValues[ i ]; - var q = new Quaternion().setFromEuler( v ); + const v = testValues[ i ]; + const q = new Quaternion().setFromEuler( v ); - var v2 = new Euler().setFromQuaternion( q, v.order ); - var q2 = new Quaternion().setFromEuler( v2 ); + const v2 = new Euler().setFromQuaternion( q, v.order ); + const q2 = new Quaternion().setFromEuler( v2 ); assert.ok( quatEquals( q, q2 ), 'Passed!' ); } @@ -226,14 +226,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'Matrix4.makeRotationFromEuler/Euler.setFromRotationMatrix', ( assert ) => { - var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; - for ( var i = 0; i < testValues.length; i ++ ) { + const testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; + for ( let i = 0; i < testValues.length; i ++ ) { - var v = testValues[ i ]; - var m = new Matrix4().makeRotationFromEuler( v ); + const v = testValues[ i ]; + const m = new Matrix4().makeRotationFromEuler( v ); - var v2 = new Euler().setFromRotationMatrix( m, v.order ); - var m2 = new Matrix4().makeRotationFromEuler( v2 ); + const v2 = new Euler().setFromRotationMatrix( m, v.order ); + const m2 = new Matrix4().makeRotationFromEuler( v2 ); assert.ok( matrixEquals4( m, m2, 0.0001 ), 'Passed!' ); } @@ -249,18 +249,18 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'reorder', ( assert ) => { - var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; - for ( var i = 0; i < testValues.length; i ++ ) { + const testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; + for ( let i = 0; i < testValues.length; i ++ ) { - var v = testValues[ i ]; - var q = new Quaternion().setFromEuler( v ); + const v = testValues[ i ]; + const q = new Quaternion().setFromEuler( v ); v.reorder( 'YZX' ); - var q2 = new Quaternion().setFromEuler( v ); + const q2 = new Quaternion().setFromEuler( v ); assert.ok( quatEquals( q, q2 ), 'Passed!' ); v.reorder( 'ZXY' ); - var q3 = new Quaternion().setFromEuler( v ); + const q3 = new Quaternion().setFromEuler( v ); assert.ok( quatEquals( q, q3 ), 'Passed!' ); } @@ -269,7 +269,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'set/get properties, check callbacks', ( assert ) => { - var a = new Euler(); + const a = new Euler(); a._onChange( function () { assert.step( 'set: onChange called' ); @@ -292,16 +292,16 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone/copy, check callbacks', ( assert ) => { - var a = new Euler( 1, 2, 3, 'ZXY' ); - var b = new Euler( 4, 5, 6, 'XZY' ); - var cbSucceed = function () { + let a = new Euler( 1, 2, 3, 'ZXY' ); + const b = new Euler( 4, 5, 6, 'XZY' ); + const cbSucceed = function () { assert.ok( true ); assert.step( 'onChange called' ); }; - var cbFail = function () { + const cbFail = function () { assert.ok( false ); @@ -325,23 +325,23 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var order = 'YXZ'; - var a = new Euler( x, y, z, order ); + const order = 'YXZ'; + const a = new Euler( x, y, z, order ); - var array = a.toArray(); + let array = a.toArray(); assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); assert.strictEqual( array[ 3 ], order, 'No array, no offset: check order' ); - var array = []; + array = []; a.toArray( array ); assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); assert.strictEqual( array[ 3 ], order, 'With array, no offset: check order' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); @@ -353,9 +353,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var a = new Euler(); - var array = [ x, y, z ]; - var cb = function () { + let a = new Euler(); + let array = [ x, y, z ]; + const cb = function () { assert.step( 'onChange called' ); @@ -384,11 +384,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( '_onChange', ( assert ) => { - var f = function () { + const f = function () { }; - var a = new Euler( 11, 12, 13, 'XYZ' ); + const a = new Euler( 11, 12, 13, 'XYZ' ); a._onChange( f ); assert.ok( a._onChangeCallback === f, 'Passed!' ); @@ -396,9 +396,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( '_onChangeCallback', ( assert ) => { - var b = false; - var a = new Euler( 11, 12, 13, 'XYZ' ); - var f = function () { + let b = false; + const a = new Euler( 11, 12, 13, 'XYZ' ); + const f = function () { b = true; assert.ok( a === this, 'Passed!' ); @@ -416,8 +416,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'iterable', ( assert ) => { - var e = new Euler( 0.5, 0.75, 1, 'YZX' ); - var array = [ ...e ]; + const e = new Euler( 0.5, 0.75, 1, 'YZX' ); + const array = [ ...e ]; assert.strictEqual( array[ 0 ], 0.5, 'Euler is iterable.' ); assert.strictEqual( array[ 1 ], 0.75, 'Euler is iterable.' ); assert.strictEqual( array[ 2 ], 1, 'Euler is iterable.' ); diff --git a/test/unit/src/math/Frustum.tests.js b/test/unit/src/math/Frustum.tests.js index b4e5df6863691f..13458284235996 100644 --- a/test/unit/src/math/Frustum.tests.js +++ b/test/unit/src/math/Frustum.tests.js @@ -1,6 +1,7 @@ /* global QUnit */ import { Frustum } from '../../../../src/math/Frustum.js'; + import { Sphere } from '../../../../src/math/Sphere.js'; import { Plane } from '../../../../src/math/Plane.js'; import { Sprite } from '../../../../src/objects/Sprite.js'; @@ -20,26 +21,26 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Frustum(); + let a = new Frustum(); assert.ok( a.planes !== undefined, 'Passed!' ); assert.ok( a.planes.length === 6, 'Passed!' ); - var pDefault = new Plane(); - for ( var i = 0; i < 6; i ++ ) { + const pDefault = new Plane(); + for ( let i = 0; i < 6; i ++ ) { assert.ok( a.planes[ i ].equals( pDefault ), 'Passed!' ); } - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); + const p0 = new Plane( unit3, - 1 ); + const p1 = new Plane( unit3, 1 ); + const p2 = new Plane( unit3, 2 ); + const p3 = new Plane( unit3, 3 ); + const p4 = new Plane( unit3, 4 ); + const p5 = new Plane( unit3, 5 ); - var a = new Frustum( p0, p1, p2, p3, p4, p5 ); + a = new Frustum( p0, p1, p2, p3, p4, p5 ); assert.ok( a.planes[ 0 ].equals( p0 ), 'Passed!' ); assert.ok( a.planes[ 1 ].equals( p1 ), 'Passed!' ); assert.ok( a.planes[ 2 ].equals( p2 ), 'Passed!' ); @@ -52,13 +53,13 @@ export default QUnit.module( 'Maths', () => { // PUBLIC QUnit.test( 'set', ( assert ) => { - var a = new Frustum(); - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); + const a = new Frustum(); + const p0 = new Plane( unit3, - 1 ); + const p1 = new Plane( unit3, 1 ); + const p2 = new Plane( unit3, 2 ); + const p3 = new Plane( unit3, 3 ); + const p4 = new Plane( unit3, 4 ); + const p5 = new Plane( unit3, 5 ); a.set( p0, p1, p2, p3, p4, p5 ); @@ -73,15 +74,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); + const p0 = new Plane( unit3, - 1 ); + const p1 = new Plane( unit3, 1 ); + const p2 = new Plane( unit3, 2 ); + const p3 = new Plane( unit3, 3 ); + const p4 = new Plane( unit3, 4 ); + const p5 = new Plane( unit3, 5 ); - var b = new Frustum( p0, p1, p2, p3, p4, p5 ); - var a = b.clone(); + const b = new Frustum( p0, p1, p2, p3, p4, p5 ); + const a = b.clone(); assert.ok( a.planes[ 0 ].equals( p0 ), 'Passed!' ); assert.ok( a.planes[ 1 ].equals( p1 ), 'Passed!' ); assert.ok( a.planes[ 2 ].equals( p2 ), 'Passed!' ); @@ -97,15 +98,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); + const p0 = new Plane( unit3, - 1 ); + const p1 = new Plane( unit3, 1 ); + const p2 = new Plane( unit3, 2 ); + const p3 = new Plane( unit3, 3 ); + const p4 = new Plane( unit3, 4 ); + const p5 = new Plane( unit3, 5 ); - var b = new Frustum( p0, p1, p2, p3, p4, p5 ); - var a = new Frustum().copy( b ); + const b = new Frustum( p0, p1, p2, p3, p4, p5 ); + const a = new Frustum().copy( b ); assert.ok( a.planes[ 0 ].equals( p0 ), 'Passed!' ); assert.ok( a.planes[ 1 ].equals( p1 ), 'Passed!' ); assert.ok( a.planes[ 2 ].equals( p2 ), 'Passed!' ); @@ -121,8 +122,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromProjectionMatrix/makeOrthographic/containsPoint', ( assert ) => { - var m = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); - var a = new Frustum().setFromProjectionMatrix( m ); + const m = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); + const a = new Frustum().setFromProjectionMatrix( m ); assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), 'Passed!' ); assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), 'Passed!' ); @@ -142,8 +143,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromProjectionMatrix/makePerspective/containsPoint', ( assert ) => { - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromProjectionMatrix( m ); + const m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); + const a = new Frustum().setFromProjectionMatrix( m ); assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), 'Passed!' ); assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), 'Passed!' ); @@ -163,8 +164,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromProjectionMatrix/makePerspective/intersectsSphere', ( assert ) => { - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromProjectionMatrix( m ); + const m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); + const a = new Frustum().setFromProjectionMatrix( m ); assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0 ) ), 'Passed!' ); assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0.9 ) ), 'Passed!' ); @@ -191,10 +192,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsObject', ( assert ) => { - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromProjectionMatrix( m ); - var object = new Mesh( new BoxGeometry( 1, 1, 1 ) ); - var intersects; + const m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); + const a = new Frustum().setFromProjectionMatrix( m ); + const object = new Mesh( new BoxGeometry( 1, 1, 1 ) ); + let intersects; intersects = a.intersectsObject( object ); assert.notOk( intersects, 'No intersection' ); @@ -215,10 +216,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsSprite', ( assert ) => { - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromProjectionMatrix( m ); - var sprite = new Sprite(); - var intersects; + const m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); + const a = new Frustum().setFromProjectionMatrix( m ); + const sprite = new Sprite(); + let intersects; intersects = a.intersectsSprite( sprite ); assert.notOk( intersects, 'No intersection' ); @@ -239,10 +240,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsBox', ( assert ) => { - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromProjectionMatrix( m ); - var box = new Box3( zero3.clone(), one3.clone() ); - var intersects; + const m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); + const a = new Frustum().setFromProjectionMatrix( m ); + const box = new Box3( zero3.clone(), one3.clone() ); + let intersects; intersects = a.intersectsBox( box ); assert.notOk( intersects, 'No intersection' ); diff --git a/test/unit/src/math/Interpolant.tests.js b/test/unit/src/math/Interpolant.tests.js index 8dfc2730a02ca7..d14c3e455a787a 100644 --- a/test/unit/src/math/Interpolant.tests.js +++ b/test/unit/src/math/Interpolant.tests.js @@ -56,8 +56,7 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var interpolant = new Mock( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); - + const interpolant = new Mock( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); assert.strictEqual( interpolant instanceof Interpolant, true, 'Mock extends from Interpolant' @@ -106,7 +105,7 @@ export default QUnit.module( 'Maths', () => { // PRIVATE QUnit.test( 'copySampleValue_', ( assert ) => { - var interpolant = new Mock( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); + const interpolant = new Mock( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); assert.deepEqual( interpolant.copySampleValue_( 0 ), [ 1, 11 ], 'sample fetch (0)' ); assert.deepEqual( interpolant.copySampleValue_( 1 ), [ 2, 22 ], 'sample fetch (1)' ); @@ -116,9 +115,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'evaluate -> intervalChanged_ / interpolate_', ( assert ) => { - var actual, expect; + let actual, expect; - var interpolant = new Mock( [ 11, 22, 33, 44, 55, 66, 77, 88, 99 ], null, 0, null ); + const interpolant = new Mock( [ 11, 22, 33, 44, 55, 66, 77, 88, 99 ], null, 0, null ); Mock.calls = []; interpolant.evaluate( 11 ); diff --git a/test/unit/src/math/Line3.tests.js b/test/unit/src/math/Line3.tests.js index 3d61e7537b0b08..64575d6baa4432 100644 --- a/test/unit/src/math/Line3.tests.js +++ b/test/unit/src/math/Line3.tests.js @@ -20,11 +20,11 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Line3(); + let a = new Line3(); assert.ok( a.start.equals( zero3 ), 'Passed!' ); assert.ok( a.end.equals( zero3 ), 'Passed!' ); - var a = new Line3( two3.clone(), one3.clone() ); + a = new Line3( two3.clone(), one3.clone() ); assert.ok( a.start.equals( two3 ), 'Passed!' ); assert.ok( a.end.equals( one3 ), 'Passed!' ); @@ -33,7 +33,7 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'set', ( assert ) => { - var a = new Line3(); + const a = new Line3(); a.set( one3, one3 ); assert.ok( a.start.equals( one3 ), 'Passed!' ); @@ -43,8 +43,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy/equals', ( assert ) => { - var a = new Line3( zero3.clone(), one3.clone() ); - var b = new Line3().copy( a ); + const a = new Line3( zero3.clone(), one3.clone() ); + const b = new Line3().copy( a ); assert.ok( b.start.equals( zero3 ), 'Passed!' ); assert.ok( b.end.equals( one3 ), 'Passed!' ); @@ -58,15 +58,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone/equal', ( assert ) => { - var a = new Line3(); - var b = new Line3( zero3, new Vector3( 1, 1, 1 ) ); - var c = new Line3( zero3, new Vector3( 1, 1, 0 ) ); + let a = new Line3(); + const b = new Line3( zero3, new Vector3( 1, 1, 1 ) ); + const c = new Line3( zero3, new Vector3( 1, 1, 0 ) ); assert.notOk( a.equals( b ), 'Check a and b aren\'t equal' ); assert.notOk( a.equals( c ), 'Check a and c aren\'t equal' ); assert.notOk( b.equals( c ), 'Check b and c aren\'t equal' ); - var a = b.clone(); + a = b.clone(); assert.ok( a.equals( b ), 'Check a and b are equal after clone()' ); assert.notOk( a.equals( c ), 'Check a and c aren\'t equal after clone()' ); @@ -77,28 +77,28 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getCenter', ( assert ) => { - var center = new Vector3(); + const center = new Vector3(); - var a = new Line3( zero3.clone(), two3.clone() ); + const a = new Line3( zero3.clone(), two3.clone() ); assert.ok( a.getCenter( center ).equals( one3.clone() ), 'Passed' ); } ); QUnit.test( 'delta', ( assert ) => { - var delta = new Vector3(); + const delta = new Vector3(); - var a = new Line3( zero3.clone(), two3.clone() ); + const a = new Line3( zero3.clone(), two3.clone() ); assert.ok( a.delta( delta ).equals( two3.clone() ), 'Passed' ); } ); QUnit.test( 'distanceSq', ( assert ) => { - var a = new Line3( zero3, zero3 ); - var b = new Line3( zero3, one3 ); - var c = new Line3( one3.clone().negate(), one3 ); - var d = new Line3( two3.clone().multiplyScalar( - 2 ), two3.clone().negate() ); + const a = new Line3( zero3, zero3 ); + const b = new Line3( zero3, one3 ); + const c = new Line3( one3.clone().negate(), one3 ); + const d = new Line3( two3.clone().multiplyScalar( - 2 ), two3.clone().negate() ); assert.numEqual( a.distanceSq(), 0, 'Check squared distance for zero-length line' ); assert.numEqual( b.distanceSq(), 3, 'Check squared distance for simple line' ); @@ -110,10 +110,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distance', ( assert ) => { - var a = new Line3( zero3, zero3 ); - var b = new Line3( zero3, one3 ); - var c = new Line3( one3.clone().negate(), one3 ); - var d = new Line3( two3.clone().multiplyScalar( - 2 ), two3.clone().negate() ); + const a = new Line3( zero3, zero3 ); + const b = new Line3( zero3, one3 ); + const c = new Line3( one3.clone().negate(), one3 ); + const d = new Line3( two3.clone().multiplyScalar( - 2 ), two3.clone().negate() ); assert.numEqual( a.distance(), 0, 'Check distance for zero-length line' ); assert.numEqual( b.distance(), Math.sqrt( 3 ), 'Check distance for simple line' ); @@ -124,8 +124,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'at', ( assert ) => { - var a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); - var point = new Vector3(); + const a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); + const point = new Vector3(); a.at( - 1, point ); assert.ok( point.distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, 'Passed!' ); @@ -140,8 +140,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'closestPointToPoint/closestPointToPointParameter', ( assert ) => { - var a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); - var point = new Vector3(); + const a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); + const point = new Vector3(); // nearby the ray assert.ok( a.closestPointToPointParameter( zero3.clone(), true ) == 0, 'Passed!' ); @@ -150,7 +150,7 @@ export default QUnit.module( 'Maths', () => { // nearby the ray assert.ok( a.closestPointToPointParameter( zero3.clone(), false ) == - 1, 'Passed!' ); - a.closestPointToPoint( zero3.clone(), false, point ); + a.closestPointToPoint( zero3.clone(), false, point ); assert.ok( point.distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, 'Passed!' ); // nearby the ray @@ -167,10 +167,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var a = new Line3( zero3.clone(), two3.clone() ); - var b = new Vector4( two3.x, two3.y, two3.z, 1 ); - var m = new Matrix4().makeTranslation( x, y, z ); - var v = new Vector3( x, y, z ); + const a = new Line3( zero3.clone(), two3.clone() ); + const b = new Vector4( two3.x, two3.y, two3.z, 1 ); + const m = new Matrix4().makeTranslation( x, y, z ); + const v = new Vector3( x, y, z ); a.applyMatrix4( m ); assert.ok( a.start.equals( v ), 'Translation: check start' ); @@ -205,8 +205,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Line3( zero3.clone(), zero3.clone() ); - var b = new Line3(); + const a = new Line3( zero3.clone(), zero3.clone() ); + const b = new Line3(); assert.ok( a.equals( b ), 'Passed' ); } ); diff --git a/test/unit/src/math/MathUtils.tests.js b/test/unit/src/math/MathUtils.tests.js index 39c0b19d4fd9d3..eddd6d70def64a 100644 --- a/test/unit/src/math/MathUtils.tests.js +++ b/test/unit/src/math/MathUtils.tests.js @@ -9,8 +9,8 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'generateUUID', ( assert ) => { - var a = MathUtils.generateUUID(); - var regex = /[A-Z0-9]{8}-[A-Z0-9]{4}-4[A-Z0-9]{3}-[A-Z0-9]{4}-[A-Z0-9]{12}/i; + const a = MathUtils.generateUUID(); + const regex = /[A-Z0-9]{8}-[A-Z0-9]{4}-4[A-Z0-9]{3}-[A-Z0-9]{4}-[A-Z0-9]{12}/i; // note the fixed '4' here ----------^ assert.ok( regex.test( a ), 'Generated UUID matches the expected pattern' ); @@ -103,8 +103,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'randInt', ( assert ) => { - var low = 1, high = 3; - var a = MathUtils.randInt( low, high ); + const low = 1, high = 3; + const a = MathUtils.randInt( low, high ); assert.ok( a >= low, 'Value equal to or higher than lower limit' ); assert.ok( a <= high, 'Value equal to or lower than upper limit' ); @@ -113,8 +113,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'randFloat', ( assert ) => { - var low = 1, high = 3; - var a = MathUtils.randFloat( low, high ); + const low = 1, high = 3; + const a = MathUtils.randFloat( low, high ); assert.ok( a >= low, 'Value equal to or higher than lower limit' ); assert.ok( a <= high, 'Value equal to or lower than upper limit' ); @@ -123,7 +123,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'randFloatSpread', ( assert ) => { - var a = MathUtils.randFloatSpread( 3 ); + const a = MathUtils.randFloatSpread( 3 ); assert.ok( a > - 3 / 2, 'Value higher than lower limit' ); assert.ok( a < 3 / 2, 'Value lower than upper limit' ); diff --git a/test/unit/src/math/Matrix3.tests.js b/test/unit/src/math/Matrix3.tests.js index c3464eaee42265..af4f0433c16614 100644 --- a/test/unit/src/math/Matrix3.tests.js +++ b/test/unit/src/math/Matrix3.tests.js @@ -12,9 +12,9 @@ function matrixEquals3( a, b, tolerance ) { } - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { + for ( let i = 0, il = a.elements.length; i < il; i ++ ) { - var delta = a.elements[ i ] - b.elements[ i ]; + const delta = a.elements[ i ] - b.elements[ i ]; if ( delta > tolerance ) { return false; @@ -29,9 +29,9 @@ function matrixEquals3( a, b, tolerance ) { function toMatrix4( m3 ) { - var result = new Matrix4(); - var re = result.elements; - var me = m3.elements; + const result = new Matrix4(); + const re = result.elements; + const me = m3.elements; re[ 0 ] = me[ 0 ]; re[ 1 ] = me[ 1 ]; re[ 2 ] = me[ 2 ]; @@ -53,10 +53,10 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Matrix3(); + const a = new Matrix3(); assert.ok( a.determinant() == 1, 'Passed!' ); - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); assert.ok( b.elements[ 0 ] == 0 ); assert.ok( b.elements[ 1 ] == 3 ); assert.ok( b.elements[ 2 ] == 6 ); @@ -69,22 +69,35 @@ export default QUnit.module( 'Maths', () => { assert.ok( ! matrixEquals3( a, b ), 'Passed!' ); + const c = new Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + assert.ok( c.elements[ 0 ] == 0 ); + assert.ok( c.elements[ 1 ] == 3 ); + assert.ok( c.elements[ 2 ] == 6 ); + assert.ok( c.elements[ 3 ] == 1 ); + assert.ok( c.elements[ 4 ] == 4 ); + assert.ok( c.elements[ 5 ] == 7 ); + assert.ok( c.elements[ 6 ] == 2 ); + assert.ok( c.elements[ 7 ] == 5 ); + assert.ok( c.elements[ 8 ] == 8 ); + + assert.ok( ! matrixEquals3( a, c ), 'Passed!' ); + } ); // PUBLIC STUFF QUnit.test( 'isMatrix3', ( assert ) => { - var a = new Matrix3(); + const a = new Matrix3(); assert.ok( a.isMatrix3 === true, 'Passed!' ); - var b = new Matrix4(); + const b = new Matrix4(); assert.ok( ! b.isMatrix3, 'Passed!' ); } ); QUnit.test( 'set', ( assert ) => { - var b = new Matrix3(); + const b = new Matrix3(); assert.ok( b.determinant() == 1, 'Passed!' ); b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); @@ -102,7 +115,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'identity', ( assert ) => { - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); assert.ok( b.elements[ 0 ] == 0 ); assert.ok( b.elements[ 1 ] == 3 ); assert.ok( b.elements[ 2 ] == 6 ); @@ -113,7 +126,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( b.elements[ 7 ] == 5 ); assert.ok( b.elements[ 8 ] == 8 ); - var a = new Matrix3(); + const a = new Matrix3(); assert.ok( ! matrixEquals3( a, b ), 'Passed!' ); b.identity(); @@ -123,8 +136,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = a.clone(); + const a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const b = a.clone(); assert.ok( matrixEquals3( a, b ), 'Passed!' ); @@ -136,8 +149,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = new Matrix3().copy( a ); + const a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const b = new Matrix3().copy( a ); assert.ok( matrixEquals3( a, b ), 'Passed!' ); @@ -157,9 +170,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromMatrix4', ( assert ) => { - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = new Matrix3(); - var c = new Matrix3().set( 0, 1, 2, 4, 5, 6, 8, 9, 10 ); + const a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const b = new Matrix3(); + const c = new Matrix3().set( 0, 1, 2, 4, 5, 6, 8, 9, 10 ); b.setFromMatrix4( a ); assert.ok( b.equals( c ) ); @@ -168,10 +181,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiply/premultiply', ( assert ) => { // both simply just wrap multiplyMatrices - var a = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); - var b = new Matrix3().set( 29, 31, 37, 41, 43, 47, 53, 59, 61 ); - var expectedMultiply = [ 446, 1343, 2491, 486, 1457, 2701, 520, 1569, 2925 ]; - var expectedPremultiply = [ 904, 1182, 1556, 1131, 1489, 1967, 1399, 1845, 2435 ]; + const a = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); + const b = new Matrix3().set( 29, 31, 37, 41, 43, 47, 53, 59, 61 ); + const expectedMultiply = [ 446, 1343, 2491, 486, 1457, 2701, 520, 1569, 2925 ]; + const expectedPremultiply = [ 904, 1182, 1556, 1131, 1489, 1967, 1399, 1845, 2435 ]; a.multiply( b ); assert.deepEqual( a.elements, expectedMultiply, 'multiply: check result' ); @@ -199,9 +212,9 @@ export default QUnit.module( 'Maths', () => { // [[ 446 486 520] // [1343 1457 1569] // [2491 2701 2925]] - var lhs = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); - var rhs = new Matrix3().set( 29, 31, 37, 41, 43, 47, 53, 59, 61 ); - var ans = new Matrix3(); + const lhs = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); + const rhs = new Matrix3().set( 29, 31, 37, 41, 43, 47, 53, 59, 61 ); + const ans = new Matrix3(); ans.multiplyMatrices( lhs, rhs ); @@ -219,7 +232,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiplyScalar', ( assert ) => { - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); assert.ok( b.elements[ 0 ] == 0 ); assert.ok( b.elements[ 1 ] == 3 ); assert.ok( b.elements[ 2 ] == 6 ); @@ -245,7 +258,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'determinant', ( assert ) => { - var a = new Matrix3(); + const a = new Matrix3(); assert.ok( a.determinant() == 1, 'Passed!' ); a.elements[ 0 ] = 2; @@ -262,15 +275,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'invert', ( assert ) => { - var zero = new Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var identity4 = new Matrix4(); - var a = new Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var b = new Matrix3(); + const zero = new Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + const identity4 = new Matrix4(); + const a = new Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + const b = new Matrix3(); b.copy( a ).invert(); assert.ok( matrixEquals3( b, zero ), 'Matrix a is zero matrix' ); - var testMatrices = [ + const testMatrices = [ new Matrix4().makeRotationX( 0.3 ), new Matrix4().makeRotationX( - 0.3 ), new Matrix4().makeRotationY( 0.3 ), @@ -281,20 +294,20 @@ export default QUnit.module( 'Maths', () => { new Matrix4().makeScale( 1 / 8, 1 / 2, 1 / 3 ) ]; - for ( var i = 0, il = testMatrices.length; i < il; i ++ ) { + for ( let i = 0, il = testMatrices.length; i < il; i ++ ) { - var m = testMatrices[ i ]; + const m = testMatrices[ i ]; a.setFromMatrix4( m ); - var mInverse3 = b.copy( a ).invert(); + const mInverse3 = b.copy( a ).invert(); - var mInverse = toMatrix4( mInverse3 ); + const mInverse = toMatrix4( mInverse3 ); // the determinant of the inverse should be the reciprocal assert.ok( Math.abs( a.determinant() * mInverse3.determinant() - 1 ) < 0.0001, 'Passed!' ); assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, 'Passed!' ); - var mProduct = new Matrix4().multiplyMatrices( m, mInverse ); + const mProduct = new Matrix4().multiplyMatrices( m, mInverse ); assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, 'Passed!' ); assert.ok( matrixEquals3( mProduct, identity4 ), 'Passed!' ); @@ -304,12 +317,12 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'transpose', ( assert ) => { - var a = new Matrix3(); - var b = a.clone().transpose(); + const a = new Matrix3(); + let b = a.clone().transpose(); assert.ok( matrixEquals3( a, b ), 'Passed!' ); - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var c = b.clone().transpose(); + b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const c = b.clone().transpose(); assert.ok( ! matrixEquals3( b, c ), 'Passed!' ); c.transpose(); assert.ok( matrixEquals3( b, c ), 'Passed!' ); @@ -318,14 +331,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getNormalMatrix', ( assert ) => { - var a = new Matrix3(); - var b = new Matrix4().set( + const a = new Matrix3(); + const b = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 57 ); - var expected = new Matrix3().set( + const expected = new Matrix3().set( - 1.2857142857142856, 0.7142857142857143, 0.2857142857142857, 0.7428571428571429, - 0.7571428571428571, 0.15714285714285714, - 0.19999999999999998, 0.3, - 0.09999999999999999 @@ -338,8 +351,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'transposeIntoArray', ( assert ) => { - var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = []; + const a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const b = []; a.transposeIntoArray( b ); assert.ok( b[ 0 ] == 0 ); @@ -357,13 +370,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setUvTransform', ( assert ) => { - var a = new Matrix3().set( + const a = new Matrix3().set( 0.1767766952966369, 0.17677669529663687, 0.32322330470336313, - 0.17677669529663687, 0.1767766952966369, 0.5, 0, 0, 1 ); - var b = new Matrix3(); - var params = { + const b = new Matrix3(); + const params = { centerX: 0.5, centerY: 0.5, offsetX: 0, @@ -372,7 +385,7 @@ export default QUnit.module( 'Maths', () => { repeatY: 0.25, rotation: 0.7753981633974483 }; - var expected = new Matrix3().set( + const expected = new Matrix3().set( 0.1785355940258599, 0.17500011904519763, 0.32323214346447127, - 0.17500011904519763, 0.1785355940258599, 0.4982322625096689, 0, 0, 1 @@ -399,8 +412,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'scale', ( assert ) => { - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var expected = new Matrix3().set( + const a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + const expected = new Matrix3().set( 0.25, 0.5, 0.75, 1, 1.25, 1.5, 7, 8, 9 @@ -413,8 +426,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'rotate', ( assert ) => { - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var expected = new Matrix3().set( + const a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + const expected = new Matrix3().set( 3.5355339059327373, 4.949747468305833, 6.363961030678928, 2.121320343559643, 2.121320343559643, 2.1213203435596433, 7, 8, 9 @@ -427,8 +440,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'translate', ( assert ) => { - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var expected = new Matrix3().set( 22, 26, 30, 53, 61, 69, 7, 8, 9 ); + const a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + const expected = new Matrix3().set( 22, 26, 30, 53, 61, 69, 7, 8, 9 ); a.translate( 3, 7 ); assert.ok( matrixEquals3( a, expected ), 'Check translation result' ); @@ -437,8 +450,15 @@ export default QUnit.module( 'Maths', () => { QUnit.todo( 'makeTranslation', ( assert ) => { - // makeTranslation( x, y ) - assert.ok( false, 'everything\'s gonna be alright' ); + const a = new Matrix3(); + const b = new Vector2( 1, 2 ); + const c = new Matrix3().set( 1, 0, 1, 0, 1, 2, 0, 0, 1 ); + + a.makeTranslation( b.x, b.y ); + assert.ok( matrixEquals3( a, c ), 'Check translation result' ); + + a.makeTranslation( b ); + assert.ok( matrixEquals3( a, c ), 'Check translation result' ); } ); @@ -458,8 +478,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = new Matrix3().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8 ); + const a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + const b = new Matrix3().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8 ); assert.notOk( a.equals( b ), 'Check that a does not equal b' ); assert.notOk( b.equals( a ), 'Check that b does not equal a' ); @@ -472,7 +492,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var b = new Matrix3(); + let b = new Matrix3(); b.fromArray( [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ] ); assert.ok( b.elements[ 0 ] == 0 ); @@ -502,18 +522,18 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var noOffset = [ 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; - var withOffset = [ undefined, 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; + const a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + const noOffset = [ 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; + const withOffset = [ undefined, 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; - var array = a.toArray(); + let array = a.toArray(); assert.deepEqual( array, noOffset, 'No array, no offset' ); - var array = []; + array = []; a.toArray( array ); assert.deepEqual( array, noOffset, 'With array, no offset' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.deepEqual( array, withOffset, 'With array, with offset' ); diff --git a/test/unit/src/math/Matrix4.tests.js b/test/unit/src/math/Matrix4.tests.js index 71dc02c672252a..db8f826de055af 100644 --- a/test/unit/src/math/Matrix4.tests.js +++ b/test/unit/src/math/Matrix4.tests.js @@ -18,9 +18,9 @@ function matrixEquals4( a, b, tolerance ) { } - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { + for ( let i = 0, il = a.elements.length; i < il; i ++ ) { - var delta = a.elements[ i ] - b.elements[ i ]; + const delta = a.elements[ i ] - b.elements[ i ]; if ( delta > tolerance ) { return false; @@ -37,7 +37,7 @@ function matrixEquals4( a, b, tolerance ) { function eulerEquals( a, b, tolerance ) { tolerance = tolerance || 0.0001; - var diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ); + const diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ); return ( diff < tolerance ); } @@ -49,10 +49,10 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Matrix4(); + const a = new Matrix4(); assert.ok( a.determinant() == 1, 'Passed!' ); - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); assert.ok( b.elements[ 0 ] == 0 ); assert.ok( b.elements[ 1 ] == 4 ); assert.ok( b.elements[ 2 ] == 8 ); @@ -72,22 +72,42 @@ export default QUnit.module( 'Maths', () => { assert.ok( ! matrixEquals4( a, b ), 'Passed!' ); + const c = new Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + assert.ok( c.elements[ 0 ] == 0 ); + assert.ok( c.elements[ 1 ] == 4 ); + assert.ok( c.elements[ 2 ] == 8 ); + assert.ok( c.elements[ 3 ] == 12 ); + assert.ok( c.elements[ 4 ] == 1 ); + assert.ok( c.elements[ 5 ] == 5 ); + assert.ok( c.elements[ 6 ] == 9 ); + assert.ok( c.elements[ 7 ] == 13 ); + assert.ok( c.elements[ 8 ] == 2 ); + assert.ok( c.elements[ 9 ] == 6 ); + assert.ok( c.elements[ 10 ] == 10 ); + assert.ok( c.elements[ 11 ] == 14 ); + assert.ok( c.elements[ 12 ] == 3 ); + assert.ok( c.elements[ 13 ] == 7 ); + assert.ok( c.elements[ 14 ] == 11 ); + assert.ok( c.elements[ 15 ] == 15 ); + + assert.ok( ! matrixEquals4( a, c ), 'Passed!' ); + } ); // PUBLIC STUFF QUnit.test( 'isMatrix4', ( assert ) => { - var a = new Matrix4(); + const a = new Matrix4(); assert.ok( a.isMatrix4 === true, 'Passed!' ); - var b = new Vector3(); + const b = new Vector3(); assert.ok( ! b.isMatrix4, 'Passed!' ); } ); QUnit.test( 'set', ( assert ) => { - var b = new Matrix4(); + const b = new Matrix4(); assert.ok( b.determinant() == 1, 'Passed!' ); b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); @@ -112,7 +132,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'identity', ( assert ) => { - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); assert.ok( b.elements[ 0 ] == 0 ); assert.ok( b.elements[ 1 ] == 4 ); assert.ok( b.elements[ 2 ] == 8 ); @@ -130,7 +150,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( b.elements[ 14 ] == 11 ); assert.ok( b.elements[ 15 ] == 15 ); - var a = new Matrix4(); + const a = new Matrix4(); assert.ok( ! matrixEquals4( a, b ), 'Passed!' ); b.identity(); @@ -140,8 +160,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = a.clone(); + const a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const b = a.clone(); assert.ok( matrixEquals4( a, b ), 'Passed!' ); @@ -153,8 +173,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = new Matrix4().copy( a ); + const a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const b = new Matrix4().copy( a ); assert.ok( matrixEquals4( a, b ), 'Passed!' ); @@ -166,13 +186,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromMatrix3', ( assert ) => { - var a = new Matrix3().set( + const a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = new Matrix4(); - var c = new Matrix4().set( + const b = new Matrix4(); + const c = new Matrix4().set( 0, 1, 2, 0, 3, 4, 5, 0, 6, 7, 8, 0, @@ -185,8 +205,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copyPosition', ( assert ) => { - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var b = new Matrix4().set( 1, 2, 3, 0, 5, 6, 7, 0, 9, 10, 11, 0, 13, 14, 15, 16 ); + const a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); + const b = new Matrix4().set( 1, 2, 3, 0, 5, 6, 7, 0, 9, 10, 11, 0, 13, 14, 15, 16 ); assert.notOk( matrixEquals4( a, b ), 'a and b initially not equal' ); @@ -197,27 +217,27 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeBasis/extractBasis', ( assert ) => { - var identityBasis = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; - var a = new Matrix4().makeBasis( identityBasis[ 0 ], identityBasis[ 1 ], identityBasis[ 2 ] ); - var identity = new Matrix4(); + const identityBasis = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; + const a = new Matrix4().makeBasis( identityBasis[ 0 ], identityBasis[ 1 ], identityBasis[ 2 ] ); + const identity = new Matrix4(); assert.ok( matrixEquals4( a, identity ), 'Passed!' ); - var testBases = [[ new Vector3( 0, 1, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ) ]]; - for ( var i = 0; i < testBases.length; i ++ ) { + const testBases = [[ new Vector3( 0, 1, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ) ]]; + for ( let i = 0; i < testBases.length; i ++ ) { - var testBasis = testBases[ i ]; - var b = new Matrix4().makeBasis( testBasis[ 0 ], testBasis[ 1 ], testBasis[ 2 ] ); - var outBasis = [ new Vector3(), new Vector3(), new Vector3() ]; + const testBasis = testBases[ i ]; + const b = new Matrix4().makeBasis( testBasis[ 0 ], testBasis[ 1 ], testBasis[ 2 ] ); + const outBasis = [ new Vector3(), new Vector3(), new Vector3() ]; b.extractBasis( outBasis[ 0 ], outBasis[ 1 ], outBasis[ 2 ] ); // check what goes in, is what comes out. - for ( var j = 0; j < outBasis.length; j ++ ) { + for ( let j = 0; j < outBasis.length; j ++ ) { assert.ok( outBasis[ j ].equals( testBasis[ j ] ), 'Passed!' ); } // get the basis out the hard war - for ( var j = 0; j < identityBasis.length; j ++ ) { + for ( let j = 0; j < identityBasis.length; j ++ ) { outBasis[ j ].copy( identityBasis[ j ] ); outBasis[ j ].applyMatrix4( b ); @@ -225,7 +245,7 @@ export default QUnit.module( 'Maths', () => { } // did the multiply method of basis extraction work? - for ( var j = 0; j < outBasis.length; j ++ ) { + for ( let j = 0; j < outBasis.length; j ++ ) { assert.ok( outBasis[ j ].equals( testBasis[ j ] ), 'Passed!' ); @@ -237,7 +257,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeRotationFromEuler/extractRotation', ( assert ) => { - var testValues = [ + const testValues = [ new Euler( 0, 0, 0, 'XYZ' ), new Euler( 1, 0, 0, 'XYZ' ), new Euler( 0, 1, 0, 'ZYX' ), @@ -245,20 +265,20 @@ export default QUnit.module( 'Maths', () => { new Euler( 0, 0, - 0.5, 'YZX' ) ]; - for ( var i = 0; i < testValues.length; i ++ ) { + for ( let i = 0; i < testValues.length; i ++ ) { - var v = testValues[ i ]; + const v = testValues[ i ]; - var m = new Matrix4().makeRotationFromEuler( v ); + const m = new Matrix4().makeRotationFromEuler( v ); - var v2 = new Euler().setFromRotationMatrix( m, v.order ); - var m2 = new Matrix4().makeRotationFromEuler( v2 ); + const v2 = new Euler().setFromRotationMatrix( m, v.order ); + const m2 = new Matrix4().makeRotationFromEuler( v2 ); assert.ok( matrixEquals4( m, m2, eps ), 'makeRotationFromEuler #' + i + ': original and Euler-derived matrices are equal' ); assert.ok( eulerEquals( v, v2, eps ), 'makeRotationFromEuler #' + i + ': original and matrix-derived Eulers are equal' ); - var m3 = new Matrix4().extractRotation( m2 ); - var v3 = new Euler().setFromRotationMatrix( m3, v.order ); + const m3 = new Matrix4().extractRotation( m2 ); + const v3 = new Euler().setFromRotationMatrix( m3, v.order ); assert.ok( matrixEquals4( m, m3, eps ), 'extractRotation #' + i + ': original and extracted matrices are equal' ); assert.ok( eulerEquals( v, v3, eps ), 'extractRotation #' + i + ': original and extracted Eulers are equal' ); @@ -276,14 +296,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'lookAt', ( assert ) => { - var a = new Matrix4(); - var expected = new Matrix4().identity(); - var eye = new Vector3( 0, 0, 0 ); - var target = new Vector3( 0, 1, - 1 ); - var up = new Vector3( 0, 1, 0 ); + const a = new Matrix4(); + const expected = new Matrix4().identity(); + const eye = new Vector3( 0, 0, 0 ); + const target = new Vector3( 0, 1, - 1 ); + const up = new Vector3( 0, 1, 0 ); a.lookAt( eye, target, up ); - var rotation = new Euler().setFromRotationMatrix( a ); + const rotation = new Euler().setFromRotationMatrix( a ); assert.numEqual( rotation.x * ( 180 / Math.PI ), 45, 'Check the rotation' ); // eye and target are in the same position @@ -307,8 +327,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiply', ( assert ) => { - var lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - var rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); + const lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); + const rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); lhs.multiply( rhs ); @@ -333,8 +353,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'premultiply', ( assert ) => { - var lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - var rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); + const lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); + const rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); rhs.premultiply( lhs ); @@ -376,9 +396,9 @@ export default QUnit.module( 'Maths', () => { // [ 5318 5562 5980 6246] // [10514 11006 11840 12378] // [15894 16634 17888 18710]] - var lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - var rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); - var ans = new Matrix4(); + const lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); + const rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); + const ans = new Matrix4(); ans.multiplyMatrices( lhs, rhs ); @@ -403,7 +423,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiplyScalar', ( assert ) => { - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); assert.ok( b.elements[ 0 ] == 0 ); assert.ok( b.elements[ 1 ] == 4 ); assert.ok( b.elements[ 2 ] == 8 ); @@ -443,7 +463,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'determinant', ( assert ) => { - var a = new Matrix4(); + const a = new Matrix4(); assert.ok( a.determinant() == 1, 'Passed!' ); a.elements[ 0 ] = 2; @@ -460,12 +480,12 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'transpose', ( assert ) => { - var a = new Matrix4(); - var b = a.clone().transpose(); + const a = new Matrix4(); + let b = a.clone().transpose(); assert.ok( matrixEquals4( a, b ), 'Passed!' ); - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var c = b.clone().transpose(); + b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const c = b.clone().transpose(); assert.ok( ! matrixEquals4( b, c ), 'Passed!' ); c.transpose(); assert.ok( matrixEquals4( b, c ), 'Passed!' ); @@ -474,15 +494,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setPosition', ( assert ) => { - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = new Vector3( - 1, - 2, - 3 ); - var c = new Matrix4().set( 0, 1, 2, - 1, 4, 5, 6, - 2, 8, 9, 10, - 3, 12, 13, 14, 15 ); + const a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const b = new Vector3( - 1, - 2, - 3 ); + const c = new Matrix4().set( 0, 1, 2, - 1, 4, 5, 6, - 2, 8, 9, 10, - 3, 12, 13, 14, 15 ); a.setPosition( b ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); - var d = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var e = new Matrix4().set( 0, 1, 2, - 1, 4, 5, 6, - 2, 8, 9, 10, - 3, 12, 13, 14, 15 ); + const d = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + const e = new Matrix4().set( 0, 1, 2, - 1, 4, 5, 6, - 2, 8, 9, 10, - 3, 12, 13, 14, 15 ); d.setPosition( - 1, - 2, - 3 ); assert.ok( matrixEquals4( d, e ), 'Passed!' ); @@ -491,17 +511,17 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'invert', ( assert ) => { - var zero = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var identity = new Matrix4(); + const zero = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + const identity = new Matrix4(); - var a = new Matrix4(); - var b = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + const a = new Matrix4(); + const b = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); a.copy( b ).invert(); assert.ok( matrixEquals4( a, zero ), 'Passed!' ); - var testMatrices = [ + const testMatrices = [ new Matrix4().makeRotationX( 0.3 ), new Matrix4().makeRotationX( - 0.3 ), new Matrix4().makeRotationY( 0.3 ), @@ -515,12 +535,12 @@ export default QUnit.module( 'Maths', () => { new Matrix4().makeTranslation( 1, 2, 3 ) ]; - for ( var i = 0, il = testMatrices.length; i < il; i ++ ) { + for ( let i = 0, il = testMatrices.length; i < il; i ++ ) { - var m = testMatrices[ i ]; + const m = testMatrices[ i ]; - var mInverse = new Matrix4().copy( m ).invert(); - var mSelfInverse = m.clone(); + const mInverse = new Matrix4().copy( m ).invert(); + const mSelfInverse = m.clone(); mSelfInverse.copy( mSelfInverse ).invert(); // self-inverse should the same as inverse @@ -529,7 +549,7 @@ export default QUnit.module( 'Maths', () => { // the determinant of the inverse should be the reciprocal assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, 'Passed!' ); - var mProduct = new Matrix4().multiplyMatrices( m, mInverse ); + const mProduct = new Matrix4().multiplyMatrices( m, mInverse ); // the determinant of the identity matrix is 1 assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, 'Passed!' ); @@ -541,9 +561,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'scale', ( assert ) => { - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var b = new Vector3( 2, 3, 4 ); - var c = new Matrix4().set( 2, 6, 12, 4, 10, 18, 28, 8, 18, 30, 44, 12, 26, 42, 60, 16 ); + const a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); + const b = new Vector3( 2, 3, 4 ); + const c = new Matrix4().set( 2, 6, 12, 4, 10, 18, 28, 8, 18, 30, 44, 12, 26, 42, 60, 16 ); a.scale( b ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); @@ -552,8 +572,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getMaxScaleOnAxis', ( assert ) => { - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var expected = Math.sqrt( 3 * 3 + 7 * 7 + 11 * 11 ); + const a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); + const expected = Math.sqrt( 3 * 3 + 7 * 7 + 11 * 11 ); assert.ok( Math.abs( a.getMaxScaleOnAxis() - expected ) <= eps, 'Check result' ); @@ -561,20 +581,23 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeTranslation', ( assert ) => { - var a = new Matrix4(); - var b = new Vector3( 2, 3, 4 ); - var c = new Matrix4().set( 1, 0, 0, 2, 0, 1, 0, 3, 0, 0, 1, 4, 0, 0, 0, 1 ); + const a = new Matrix4(); + const b = new Vector3( 2, 3, 4 ); + const c = new Matrix4().set( 1, 0, 0, 2, 0, 1, 0, 3, 0, 0, 1, 4, 0, 0, 0, 1 ); a.makeTranslation( b.x, b.y, b.z ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); + a.makeTranslation( b ); + assert.ok( matrixEquals4( a, c ), 'Passed!' ); + } ); QUnit.test( 'makeRotationX', ( assert ) => { - var a = new Matrix4(); - var b = Math.sqrt( 3 ) / 2; - var c = new Matrix4().set( 1, 0, 0, 0, 0, b, - 0.5, 0, 0, 0.5, b, 0, 0, 0, 0, 1 ); + const a = new Matrix4(); + const b = Math.sqrt( 3 ) / 2; + const c = new Matrix4().set( 1, 0, 0, 0, 0, b, - 0.5, 0, 0, 0.5, b, 0, 0, 0, 0, 1 ); a.makeRotationX( Math.PI / 6 ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); @@ -584,9 +607,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeRotationY', ( assert ) => { - var a = new Matrix4(); - var b = Math.sqrt( 3 ) / 2; - var c = new Matrix4().set( b, 0, 0.5, 0, 0, 1, 0, 0, - 0.5, 0, b, 0, 0, 0, 0, 1 ); + const a = new Matrix4(); + const b = Math.sqrt( 3 ) / 2; + const c = new Matrix4().set( b, 0, 0.5, 0, 0, 1, 0, 0, - 0.5, 0, b, 0, 0, 0, 0, 1 ); a.makeRotationY( Math.PI / 6 ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); @@ -596,9 +619,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeRotationZ', ( assert ) => { - var a = new Matrix4(); - var b = Math.sqrt( 3 ) / 2; - var c = new Matrix4().set( b, - 0.5, 0, 0, 0.5, b, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); + const a = new Matrix4(); + const b = Math.sqrt( 3 ) / 2; + const c = new Matrix4().set( b, - 0.5, 0, 0, 0.5, b, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); a.makeRotationZ( Math.PI / 6 ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); @@ -607,11 +630,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeRotationAxis', ( assert ) => { - var axis = new Vector3( 1.5, 0.0, 1.0 ).normalize(); - var radians = MathUtils.degToRad( 45 ); - var a = new Matrix4().makeRotationAxis( axis, radians ); + const axis = new Vector3( 1.5, 0.0, 1.0 ).normalize(); + const radians = MathUtils.degToRad( 45 ); + const a = new Matrix4().makeRotationAxis( axis, radians ); - var expected = new Matrix4().set( + const expected = new Matrix4().set( 0.9098790095958609, - 0.39223227027636803, 0.13518148560620882, 0, 0.39223227027636803, 0.7071067811865476, - 0.588348405414552, 0, 0.13518148560620882, 0.588348405414552, 0.7972277715906868, 0, @@ -624,8 +647,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeScale', ( assert ) => { - var a = new Matrix4(); - var c = new Matrix4().set( 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1 ); + const a = new Matrix4(); + const c = new Matrix4().set( 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1 ); a.makeScale( 2, 3, 4 ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); @@ -634,8 +657,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeShear', ( assert ) => { - var a = new Matrix4(); - var c = new Matrix4().set( 1, 3, 5, 0, 1, 1, 6, 0, 2, 4, 1, 0, 0, 0, 0, 1 ); + const a = new Matrix4(); + const c = new Matrix4().set( 1, 3, 5, 0, 1, 1, 6, 0, 2, 4, 1, 0, 0, 0, 0, 1 ); a.makeShear( 1, 2, 3, 4, 5, 6 ); assert.ok( matrixEquals4( a, c ), 'Passed!' ); @@ -644,7 +667,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'compose/decompose', ( assert ) => { - var tValues = [ + const tValues = [ new Vector3(), new Vector3( 3, 0, 0 ), new Vector3( 0, 4, 0 ), @@ -656,7 +679,7 @@ export default QUnit.module( 'Maths', () => { new Vector3( - 2, - 5, - 9 ) ]; - var sValues = [ + const sValues = [ new Vector3( 1, 1, 1 ), new Vector3( 2, 2, 2 ), new Vector3( 1, - 1, 1 ), @@ -668,35 +691,35 @@ export default QUnit.module( 'Maths', () => { new Vector3( - 2, - 2, - 2 ) ]; - var rValues = [ + const rValues = [ new Quaternion(), new Quaternion().setFromEuler( new Euler( 1, 1, 0 ) ), new Quaternion().setFromEuler( new Euler( 1, - 1, 1 ) ), new Quaternion( 0, 0.9238795292366128, 0, 0.38268342717215614 ) ]; - for ( var ti = 0; ti < tValues.length; ti ++ ) { + for ( let ti = 0; ti < tValues.length; ti ++ ) { - for ( var si = 0; si < sValues.length; si ++ ) { + for ( let si = 0; si < sValues.length; si ++ ) { - for ( var ri = 0; ri < rValues.length; ri ++ ) { + for ( let ri = 0; ri < rValues.length; ri ++ ) { - var t = tValues[ ti ]; - var s = sValues[ si ]; - var r = rValues[ ri ]; + const t = tValues[ ti ]; + const s = sValues[ si ]; + const r = rValues[ ri ]; - var m = new Matrix4().compose( t, r, s ); - var t2 = new Vector3(); - var r2 = new Quaternion(); - var s2 = new Vector3(); + const m = new Matrix4().compose( t, r, s ); + const t2 = new Vector3(); + const r2 = new Quaternion(); + const s2 = new Vector3(); m.decompose( t2, r2, s2 ); - var m2 = new Matrix4().compose( t2, r2, s2 ); + const m2 = new Matrix4().compose( t2, r2, s2 ); /* // debug code - var matrixIsSame = matrixEquals4( m, m2 ); + const matrixIsSame = matrixEquals4( m, m2 ); if ( ! matrixIsSame ) { console.log( t, s, r ); @@ -718,8 +741,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makePerspective', ( assert ) => { - var a = new Matrix4().makePerspective( - 1, 1, - 1, 1, 1, 100 ); - var expected = new Matrix4().set( + const a = new Matrix4().makePerspective( - 1, 1, - 1, 1, 1, 100 ); + const expected = new Matrix4().set( 1, 0, 0, 0, 0, - 1, 0, 0, 0, 0, - 101 / 99, - 200 / 99, @@ -731,8 +754,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeOrthographic', ( assert ) => { - var a = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); - var expected = new Matrix4().set( + const a = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); + const expected = new Matrix4().set( 1, 0, 0, 0, 0, - 1, 0, 0, 0, 0, - 2 / 99, - 101 / 99, @@ -745,8 +768,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var b = new Matrix4().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); + const a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); + const b = new Matrix4().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); assert.notOk( a.equals( b ), 'Check that a does not equal b' ); assert.notOk( b.equals( a ), 'Check that b does not equal a' ); @@ -759,8 +782,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var a = new Matrix4(); - var b = new Matrix4().set( 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ); + const a = new Matrix4(); + const b = new Matrix4().set( 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ); a.fromArray( [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ] ); assert.ok( a.equals( b ), 'Passed' ); @@ -769,18 +792,18 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var noOffset = [ 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; - var withOffset = [ undefined, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; + const a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); + const noOffset = [ 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; + const withOffset = [ undefined, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; - var array = a.toArray(); + let array = a.toArray(); assert.deepEqual( array, noOffset, 'No array, no offset' ); - var array = []; + array = []; a.toArray( array ); assert.deepEqual( array, noOffset, 'With array, no offset' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.deepEqual( array, withOffset, 'With array, with offset' ); diff --git a/test/unit/src/math/Plane.tests.js b/test/unit/src/math/Plane.tests.js index 136087b91f7981..236d9a94ce89da 100644 --- a/test/unit/src/math/Plane.tests.js +++ b/test/unit/src/math/Plane.tests.js @@ -30,19 +30,19 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Plane(); + let a = new Plane(); assert.ok( a.normal.x == 1, 'Passed!' ); assert.ok( a.normal.y == 0, 'Passed!' ); assert.ok( a.normal.z == 0, 'Passed!' ); assert.ok( a.constant == 0, 'Passed!' ); - var a = new Plane( one3.clone(), 0 ); + a = new Plane( one3.clone(), 0 ); assert.ok( a.normal.x == 1, 'Passed!' ); assert.ok( a.normal.y == 1, 'Passed!' ); assert.ok( a.normal.z == 1, 'Passed!' ); assert.ok( a.constant == 0, 'Passed!' ); - var a = new Plane( one3.clone(), 1 ); + a = new Plane( one3.clone(), 1 ); assert.ok( a.normal.x == 1, 'Passed!' ); assert.ok( a.normal.y == 1, 'Passed!' ); assert.ok( a.normal.z == 1, 'Passed!' ); @@ -53,10 +53,10 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'isPlane', ( assert ) => { - var a = new Plane(); + const a = new Plane(); assert.ok( a.isPlane === true, 'Passed!' ); - var b = new Vector3(); + const b = new Vector3(); assert.ok( ! b.isPlane, 'Passed!' ); @@ -64,13 +64,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'set', ( assert ) => { - var a = new Plane(); + const a = new Plane(); assert.ok( a.normal.x == 1, 'Passed!' ); assert.ok( a.normal.y == 0, 'Passed!' ); assert.ok( a.normal.z == 0, 'Passed!' ); assert.ok( a.constant == 0, 'Passed!' ); - var b = a.clone().set( new Vector3( x, y, z ), w ); + const b = a.clone().set( new Vector3( x, y, z ), w ); assert.ok( b.normal.x == x, 'Passed!' ); assert.ok( b.normal.y == y, 'Passed!' ); assert.ok( b.normal.z == z, 'Passed!' ); @@ -80,13 +80,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setComponents', ( assert ) => { - var a = new Plane(); + const a = new Plane(); assert.ok( a.normal.x == 1, 'Passed!' ); assert.ok( a.normal.y == 0, 'Passed!' ); assert.ok( a.normal.z == 0, 'Passed!' ); assert.ok( a.constant == 0, 'Passed!' ); - var b = a.clone().setComponents( x, y, z, w ); + const b = a.clone().setComponents( x, y, z, w ); assert.ok( b.normal.x == x, 'Passed!' ); assert.ok( b.normal.y == y, 'Passed!' ); assert.ok( b.normal.z == z, 'Passed!' ); @@ -96,8 +96,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromNormalAndCoplanarPoint', ( assert ) => { - var normal = one3.clone().normalize(); - var a = new Plane().setFromNormalAndCoplanarPoint( normal, zero3 ); + const normal = one3.clone().normalize(); + const a = new Plane().setFromNormalAndCoplanarPoint( normal, zero3 ); assert.ok( a.normal.equals( normal ), 'Passed!' ); assert.ok( a.constant == 0, 'Passed!' ); @@ -106,12 +106,12 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromCoplanarPoints', ( assert ) => { - var a = new Plane(); - var v1 = new Vector3( 2.0, 0.5, 0.25 ); - var v2 = new Vector3( 2.0, - 0.5, 1.25 ); - var v3 = new Vector3( 2.0, - 3.5, 2.2 ); - var normal = new Vector3( 1, 0, 0 ); - var constant = - 2; + const a = new Plane(); + const v1 = new Vector3( 2.0, 0.5, 0.25 ); + const v2 = new Vector3( 2.0, - 0.5, 1.25 ); + const v3 = new Vector3( 2.0, - 3.5, 2.2 ); + const normal = new Vector3( 1, 0, 0 ); + const constant = - 2; a.setFromCoplanarPoints( v1, v2, v3 ); @@ -122,8 +122,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var a = new Plane( new Vector3( 2.0, 0.5, 0.25 ) ); - var b = a.clone(); + const a = new Plane( new Vector3( 2.0, 0.5, 0.25 ) ); + const b = a.clone(); assert.ok( a.equals( b ), 'clones are equal' ); @@ -132,8 +132,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Plane( new Vector3( x, y, z ), w ); - var b = new Plane().copy( a ); + const a = new Plane( new Vector3( x, y, z ), w ); + const b = new Plane().copy( a ); assert.ok( b.normal.x == x, 'Passed!' ); assert.ok( b.normal.y == y, 'Passed!' ); assert.ok( b.normal.z == z, 'Passed!' ); @@ -153,7 +153,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'normalize', ( assert ) => { - var a = new Plane( new Vector3( 2, 0, 0 ), 2 ); + const a = new Plane( new Vector3( 2, 0, 0 ), 2 ); a.normalize(); assert.ok( a.normal.length() == 1, 'Passed!' ); @@ -164,7 +164,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'negate/distanceToPoint', ( assert ) => { - var a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); + const a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); a.normalize(); assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === 3, 'Passed!' ); @@ -178,8 +178,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceToPoint', ( assert ) => { - var a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); - var point = new Vector3(); + const a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); + const point = new Vector3(); a.normalize().projectPoint( zero3.clone(), point ); assert.ok( a.distanceToPoint( point ) === 0, 'Passed!' ); @@ -189,9 +189,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceToSphere', ( assert ) => { - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); + const a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - var b = new Sphere( new Vector3( 2, 0, 0 ), 1 ); + const b = new Sphere( new Vector3( 2, 0, 0 ), 1 ); assert.ok( a.distanceToSphere( b ) === 1, 'Passed!' ); @@ -204,15 +204,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'projectPoint', ( assert ) => { - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - var point = new Vector3(); + let a = new Plane( new Vector3( 1, 0, 0 ), 0 ); + const point = new Vector3(); a.projectPoint( new Vector3( 10, 0, 0 ), point ); assert.ok( point.equals( zero3 ), 'Passed!' ); a.projectPoint( new Vector3( - 10, 0, 0 ), point ); assert.ok( point.equals( zero3 ), 'Passed!' ); - var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); + a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); a.projectPoint( new Vector3( 0, 0, 0 ), point ); assert.ok( point.equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); a.projectPoint( new Vector3( 0, 1, 0 ), point ); @@ -222,14 +222,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectLine', ( assert ) => { - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - var point = new Vector3(); + let a = new Plane( new Vector3( 1, 0, 0 ), 0 ); + const point = new Vector3(); - var l1 = new Line3( new Vector3( - 10, 0, 0 ), new Vector3( 10, 0, 0 ) ); + const l1 = new Line3( new Vector3( - 10, 0, 0 ), new Vector3( 10, 0, 0 ) ); a.intersectLine( l1, point ); assert.ok( point.equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); - var a = new Plane( new Vector3( 1, 0, 0 ), - 3 ); + a = new Plane( new Vector3( 1, 0, 0 ), - 3 ); a.intersectLine( l1, point ); assert.ok( point.equals( new Vector3( 3, 0, 0 ) ), 'Passed!' ); @@ -244,16 +244,16 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsBox', ( assert ) => { - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); - var d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); - var e = new Plane( new Vector3( 0, 1, 0 ), 0.25 ); - var f = new Plane( new Vector3( 0, 1, 0 ), - 0.25 ); - var g = new Plane( new Vector3( 0, 1, 0 ), - 0.75 ); - var h = new Plane( new Vector3( 0, 1, 0 ), - 1 ); - var i = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.732 ); - var j = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.733 ); + const a = new Box3( zero3.clone(), one3.clone() ); + const b = new Plane( new Vector3( 0, 1, 0 ), 1 ); + const c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); + const d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); + const e = new Plane( new Vector3( 0, 1, 0 ), 0.25 ); + const f = new Plane( new Vector3( 0, 1, 0 ), - 0.25 ); + const g = new Plane( new Vector3( 0, 1, 0 ), - 0.75 ); + const h = new Plane( new Vector3( 0, 1, 0 ), - 1 ); + const i = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.732 ); + const j = new Plane( new Vector3( 1, 1, 1 ).normalize(), - 1.733 ); assert.ok( ! b.intersectsBox( a ), 'Passed!' ); assert.ok( ! c.intersectsBox( a ), 'Passed!' ); @@ -269,10 +269,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsSphere', ( assert ) => { - var a = new Sphere( zero3.clone(), 1 ); - var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); - var d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); + const a = new Sphere( zero3.clone(), 1 ); + const b = new Plane( new Vector3( 0, 1, 0 ), 1 ); + const c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); + const d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); assert.ok( b.intersectsSphere( a ), 'Passed!' ); assert.ok( ! c.intersectsSphere( a ), 'Passed!' ); @@ -282,13 +282,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'coplanarPoint', ( assert ) => { - var point = new Vector3(); + const point = new Vector3(); - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); + let a = new Plane( new Vector3( 1, 0, 0 ), 0 ); a.coplanarPoint( point ); assert.ok( a.distanceToPoint( point ) === 0, 'Passed!' ); - var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); + a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); a.coplanarPoint( point ); assert.ok( a.distanceToPoint( point ) === 0, 'Passed!' ); @@ -296,14 +296,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix4/translate', ( assert ) => { - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); + let a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - var m = new Matrix4(); + const m = new Matrix4(); m.makeRotationZ( Math.PI * 0.5 ); assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( 0, 1, 0 ), 0 ) ), 'Passed!' ); - var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); + a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( - 1, 0, 0 ), - 1 ) ), 'Passed!' ); m.makeTranslation( 1, 1, 1 ); @@ -313,9 +313,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - var b = new Plane( new Vector3( 1, 0, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 0 ); + const a = new Plane( new Vector3( 1, 0, 0 ), 0 ); + const b = new Plane( new Vector3( 1, 0, 0 ), 1 ); + const c = new Plane( new Vector3( 0, 1, 0 ), 0 ); assert.ok( a.normal.equals( b.normal ), 'Normals: equal' ); assert.notOk( a.normal.equals( c.normal ), 'Normals: not equal' ); diff --git a/test/unit/src/math/Quaternion.tests.js b/test/unit/src/math/Quaternion.tests.js index 37c5d18b54b171..e80dca9993e3da 100644 --- a/test/unit/src/math/Quaternion.tests.js +++ b/test/unit/src/math/Quaternion.tests.js @@ -19,7 +19,7 @@ const eulerAngles = new Euler( 0.1, - 0.3, 0.25 ); function qSub( a, b ) { - var result = new Quaternion(); + const result = new Quaternion(); result.copy( a ); result.x -= b.x; @@ -33,7 +33,7 @@ function qSub( a, b ) { function doSlerpObject( aArr, bArr, t ) { - var a = new Quaternion().fromArray( aArr ), + const a = new Quaternion().fromArray( aArr ), b = new Quaternion().fromArray( bArr ), c = new Quaternion().fromArray( aArr ); @@ -63,7 +63,7 @@ function doSlerpObject( aArr, bArr, t ) { function doSlerpArray( a, b, t ) { - var result = [ 0, 0, 0, 0 ]; + const result = [ 0, 0, 0, 0 ]; Quaternion.slerpFlat( result, 0, a, 0, b, 0, t ); @@ -98,27 +98,27 @@ function doSlerpArray( a, b, t ) { function slerpTestSkeleton( doSlerp, maxError, assert ) { - var a, b, result; + let result; - a = [ + const a = [ 0.6753410084407496, 0.4087830051091744, 0.32856700410659473, 0.5185120064806223 ]; - b = [ + const b = [ 0.6602792107657797, 0.43647413932562285, 0.35119011210236006, 0.5001871596632682 ]; - var maxNormError = 0; + let maxNormError = 0; function isNormal( result ) { - var normError = Math.abs( 1 - result.length ); + const normError = Math.abs( 1 - result.length ); maxNormError = Math.max( maxNormError, normError ); return normError <= maxError; @@ -144,7 +144,7 @@ function slerpTestSkeleton( doSlerp, maxError, assert ) { assert.ok( result.dotA < result.dotB, 'Interpolating at 0.75' ); assert.ok( isNormal( result ), 'Approximately normal (at 0.75)' ); - var D = Math.SQRT1_2; + const D = Math.SQRT1_2; result = doSlerp( [ 1, 0, 0, 0 ], [ 0, 0, 1, 0 ], 0.5 ); assert.ok( result.equals( D, 0, D, 0 ), 'X/Z diagonal from axes' ); @@ -169,13 +169,13 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Quaternion(); + let a = new Quaternion(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); assert.ok( a.w == 1, 'Passed!' ); - var a = new Quaternion( x, y, z, w ); + a = new Quaternion( x, y, z, w ); assert.ok( a.x === x, 'Passed!' ); assert.ok( a.y === y, 'Passed!' ); assert.ok( a.z === z, 'Passed!' ); @@ -201,7 +201,7 @@ export default QUnit.module( 'Maths', () => { assert.expect( 8 ); - var a = new Quaternion(); + const a = new Quaternion(); a._onChange( function () { assert.ok( true, 'onChange called' ); @@ -222,7 +222,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'x', ( assert ) => { - var a = new Quaternion(); + let a = new Quaternion(); assert.ok( a.x === 0, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); @@ -236,7 +236,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.x === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -251,7 +251,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'y', ( assert ) => { - var a = new Quaternion(); + let a = new Quaternion(); assert.ok( a.y === 0, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); @@ -265,7 +265,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.y === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -281,7 +281,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'z', ( assert ) => { - var a = new Quaternion(); + let a = new Quaternion(); assert.ok( a.z === 0, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); @@ -295,7 +295,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.z === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -310,7 +310,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'w', ( assert ) => { - var a = new Quaternion(); + let a = new Quaternion(); assert.ok( a.w === 1, 'Passed!' ); a = new Quaternion( 1, 2, 3 ); @@ -324,7 +324,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.w === 10, 'Passed!' ); a = new Quaternion( 11, 12, 13 ); - var b = false; + let b = false; a._onChange( function () { b = true; @@ -347,7 +347,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'set', ( assert ) => { - var a = new Quaternion(); + const a = new Quaternion(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); @@ -364,13 +364,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var a = new Quaternion().clone(); + const a = new Quaternion().clone(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); assert.ok( a.w == 1, 'Passed!' ); - var b = a.set( x, y, z, w ).clone(); + const b = a.set( x, y, z, w ).clone(); assert.ok( b.x == x, 'Passed!' ); assert.ok( b.y == y, 'Passed!' ); assert.ok( b.z === z, 'Passed!' ); @@ -380,8 +380,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion().copy( a ); + const a = new Quaternion( x, y, z, w ); + const b = new Quaternion().copy( a ); assert.ok( b.x == x, 'Passed!' ); assert.ok( b.y == y, 'Passed!' ); assert.ok( b.z == z, 'Passed!' ); @@ -399,15 +399,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromEuler/setFromQuaternion', ( assert ) => { - var angles = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; + const angles = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; // ensure euler conversion to/from Quaternion matches. - for ( var i = 0; i < orders.length; i ++ ) { + for ( let i = 0; i < orders.length; i ++ ) { - for ( var j = 0; j < angles.length; j ++ ) { + for ( let j = 0; j < angles.length; j ++ ) { - var eulers2 = new Euler().setFromQuaternion( new Quaternion().setFromEuler( new Euler( angles[ j ].x, angles[ j ].y, angles[ j ].z, orders[ i ] ) ), orders[ i ] ); - var newAngle = new Vector3( eulers2.x, eulers2.y, eulers2.z ); + const eulers2 = new Euler().setFromQuaternion( new Quaternion().setFromEuler( new Euler( angles[ j ].x, angles[ j ].y, angles[ j ].z, orders[ i ] ) ), orders[ i ] ); + const newAngle = new Vector3( eulers2.x, eulers2.y, eulers2.z ); assert.ok( newAngle.distanceTo( angles[ j ] ) < 0.001, 'Passed!' ); } @@ -421,18 +421,18 @@ export default QUnit.module( 'Maths', () => { // TODO: find cases to validate. // assert.ok( true, "Passed!" ); - var zero = new Quaternion(); + const zero = new Quaternion(); - var a = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), 0 ); + let a = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), 0 ); assert.ok( a.equals( zero ), 'Passed!' ); a = new Quaternion().setFromAxisAngle( new Vector3( 0, 1, 0 ), 0 ); assert.ok( a.equals( zero ), 'Passed!' ); a = new Quaternion().setFromAxisAngle( new Vector3( 0, 0, 1 ), 0 ); assert.ok( a.equals( zero ), 'Passed!' ); - var b1 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), Math.PI ); + const b1 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), Math.PI ); assert.ok( ! a.equals( b1 ), 'Passed!' ); - var b2 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), - Math.PI ); + const b2 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), - Math.PI ); assert.ok( ! a.equals( b2 ), 'Passed!' ); b1.multiply( b2 ); @@ -443,11 +443,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromEuler/setFromRotationMatrix', ( assert ) => { // ensure euler conversion for Quaternion matches that of Matrix4 - for ( var i = 0; i < orders.length; i ++ ) { + for ( let i = 0; i < orders.length; i ++ ) { - var q = new Quaternion().setFromEuler( changeEulerOrder( eulerAngles, orders[ i ] ) ); - var m = new Matrix4().makeRotationFromEuler( changeEulerOrder( eulerAngles, orders[ i ] ) ); - var q2 = new Quaternion().setFromRotationMatrix( m ); + const q = new Quaternion().setFromEuler( changeEulerOrder( eulerAngles, orders[ i ] ) ); + const m = new Matrix4().makeRotationFromEuler( changeEulerOrder( eulerAngles, orders[ i ] ) ); + const q2 = new Quaternion().setFromRotationMatrix( m ); assert.ok( qSub( q, q2 ).length() < 0.001, 'Passed!' ); @@ -460,10 +460,10 @@ export default QUnit.module( 'Maths', () => { // contrived examples purely to please the god of code coverage... // match conditions in various 'else [if]' blocks - var a = new Quaternion(); - var q = new Quaternion( - 9, - 2, 3, - 4 ).normalize(); - var m = new Matrix4().makeRotationFromQuaternion( q ); - var expected = new Vector4( 0.8581163303210332, 0.19069251784911848, - 0.2860387767736777, 0.38138503569823695 ); + const a = new Quaternion(); + let q = new Quaternion( - 9, - 2, 3, - 4 ).normalize(); + const m = new Matrix4().makeRotationFromQuaternion( q ); + let expected = new Vector4( 0.8581163303210332, 0.19069251784911848, - 0.2860387767736777, 0.38138503569823695 ); a.setFromRotationMatrix( m ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'm11 > m22 && m11 > m33: check x' ); @@ -471,9 +471,9 @@ export default QUnit.module( 'Maths', () => { assert.ok( Math.abs( a.z - expected.z ) <= eps, 'm11 > m22 && m11 > m33: check z' ); assert.ok( Math.abs( a.w - expected.w ) <= eps, 'm11 > m22 && m11 > m33: check w' ); - var q = new Quaternion( - 1, - 2, 1, - 1 ).normalize(); + q = new Quaternion( - 1, - 2, 1, - 1 ).normalize(); m.makeRotationFromQuaternion( q ); - var expected = new Vector4( 0.37796447300922714, 0.7559289460184544, - 0.37796447300922714, 0.37796447300922714 ); + expected = new Vector4( 0.37796447300922714, 0.7559289460184544, - 0.37796447300922714, 0.37796447300922714 ); a.setFromRotationMatrix( m ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'm22 > m33: check x' ); @@ -485,10 +485,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromUnitVectors', ( assert ) => { - var a = new Quaternion(); - var b = new Vector3( 1, 0, 0 ); - var c = new Vector3( 0, 1, 0 ); - var expected = new Quaternion( 0, 0, Math.sqrt( 2 ) / 2, Math.sqrt( 2 ) / 2 ); + const a = new Quaternion(); + const b = new Vector3( 1, 0, 0 ); + const c = new Vector3( 0, 1, 0 ); + const expected = new Quaternion( 0, 0, Math.sqrt( 2 ) / 2, Math.sqrt( 2 ) / 2 ); a.setFromUnitVectors( b, c ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -500,9 +500,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'angleTo', ( assert ) => { - var a = new Quaternion(); - var b = new Quaternion().setFromEuler( new Euler( 0, Math.PI, 0 ) ); - var c = new Quaternion().setFromEuler( new Euler( 0, Math.PI * 2, 0 ) ); + const a = new Quaternion(); + const b = new Quaternion().setFromEuler( new Euler( 0, Math.PI, 0 ) ); + const c = new Quaternion().setFromEuler( new Euler( 0, Math.PI * 2, 0 ) ); assert.ok( a.angleTo( a ) === 0, 'Passed!' ); assert.ok( a.angleTo( b ) === Math.PI, 'Passed!' ); @@ -512,11 +512,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'rotateTowards', ( assert ) => { - var a = new Quaternion(); - var b = new Quaternion().setFromEuler( new Euler( 0, Math.PI, 0 ) ); - var c = new Quaternion(); + const a = new Quaternion(); + const b = new Quaternion().setFromEuler( new Euler( 0, Math.PI, 0 ) ); + const c = new Quaternion(); - var halfPI = Math.PI * 0.5; + const halfPI = Math.PI * 0.5; a.rotateTowards( b, 0 ); assert.ok( a.equals( a ) === true, 'Passed!' ); @@ -532,7 +532,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'identity', ( assert ) => { - var a = new Quaternion(); + const a = new Quaternion(); a.set( x, y, z, w ); a.identity(); @@ -546,11 +546,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'invert/conjugate', ( assert ) => { - var a = new Quaternion( x, y, z, w ); + const a = new Quaternion( x, y, z, w ); // TODO: add better validation here. - var b = a.clone().conjugate(); + const b = a.clone().conjugate(); assert.ok( a.x == - b.x, 'Passed!' ); assert.ok( a.y == - b.y, 'Passed!' ); @@ -561,8 +561,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'dot', ( assert ) => { - var a = new Quaternion(); - var b = new Quaternion(); + let a = new Quaternion(); + let b = new Quaternion(); assert.ok( a.dot( b ) === 1, 'Passed!' ); a = new Quaternion( 1, 2, 3, 1 ); @@ -575,7 +575,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'normalize/length/lengthSq', ( assert ) => { - var a = new Quaternion( x, y, z, w ); + const a = new Quaternion( x, y, z, w ); assert.ok( a.length() != 1, 'Passed!' ); assert.ok( a.lengthSq() != 1, 'Passed!' ); @@ -594,21 +594,21 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiplyQuaternions/multiply', ( assert ) => { - var angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; + const angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; - var q1 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 0 ], 'XYZ' ) ); - var q2 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 1 ], 'XYZ' ) ); - var q3 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 2 ], 'XYZ' ) ); + const q1 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 0 ], 'XYZ' ) ); + const q2 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 1 ], 'XYZ' ) ); + const q3 = new Quaternion().setFromEuler( changeEulerOrder( angles[ 2 ], 'XYZ' ) ); - var q = new Quaternion().multiplyQuaternions( q1, q2 ).multiply( q3 ); + const q = new Quaternion().multiplyQuaternions( q1, q2 ).multiply( q3 ); - var m1 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 0 ], 'XYZ' ) ); - var m2 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 1 ], 'XYZ' ) ); - var m3 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 2 ], 'XYZ' ) ); + const m1 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 0 ], 'XYZ' ) ); + const m2 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 1 ], 'XYZ' ) ); + const m3 = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ 2 ], 'XYZ' ) ); - var m = new Matrix4().multiplyMatrices( m1, m2 ).multiply( m3 ); + const m = new Matrix4().multiplyMatrices( m1, m2 ).multiply( m3 ); - var qFromM = new Quaternion().setFromRotationMatrix( m ); + const qFromM = new Quaternion().setFromRotationMatrix( m ); assert.ok( qSub( q, qFromM ).length() < 0.001, 'Passed!' ); @@ -616,9 +616,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'premultiply', ( assert ) => { - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion( 2 * x, - y, - 2 * z, w ); - var expected = new Quaternion( 42, - 32, - 2, 58 ); + const a = new Quaternion( x, y, z, w ); + const b = new Quaternion( 2 * x, - y, - 2 * z, w ); + const expected = new Quaternion( 42, - 32, - 2, 58 ); a.premultiply( b ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -630,30 +630,30 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'slerp', ( assert ) => { - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion( - x, - y, - z, - w ); + const a = new Quaternion( x, y, z, w ); + const b = new Quaternion( - x, - y, - z, - w ); - var c = a.clone().slerp( b, 0 ); - var d = a.clone().slerp( b, 1 ); + const c = a.clone().slerp( b, 0 ); + const d = a.clone().slerp( b, 1 ); assert.ok( a.equals( c ), 'Passed' ); assert.ok( b.equals( d ), 'Passed' ); - var D = Math.SQRT1_2; + const D = Math.SQRT1_2; - var e = new Quaternion( 1, 0, 0, 0 ); - var f = new Quaternion( 0, 0, 1, 0 ); - var expected = new Quaternion( D, 0, D, 0 ); - var result = e.clone().slerp( f, 0.5 ); + const e = new Quaternion( 1, 0, 0, 0 ); + const f = new Quaternion( 0, 0, 1, 0 ); + let expected = new Quaternion( D, 0, D, 0 ); + let result = e.clone().slerp( f, 0.5 ); assert.ok( Math.abs( result.x - expected.x ) <= eps, 'Check x' ); assert.ok( Math.abs( result.y - expected.y ) <= eps, 'Check y' ); assert.ok( Math.abs( result.z - expected.z ) <= eps, 'Check z' ); assert.ok( Math.abs( result.w - expected.w ) <= eps, 'Check w' ); - var g = new Quaternion( 0, D, 0, D ); - var h = new Quaternion( 0, - D, 0, D ); + const g = new Quaternion( 0, D, 0, D ); + const h = new Quaternion( 0, - D, 0, D ); expected = new Quaternion( 0, 0, 0, 1 ); result = g.clone().slerp( h, 0.5 ); @@ -666,11 +666,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'slerpQuaternions', ( assert ) => { - var e = new Quaternion( 1, 0, 0, 0 ); - var f = new Quaternion( 0, 0, 1, 0 ); - var expected = new Quaternion( Math.SQRT1_2, 0, Math.SQRT1_2, 0 ); + const e = new Quaternion( 1, 0, 0, 0 ); + const f = new Quaternion( 0, 0, 1, 0 ); + const expected = new Quaternion( Math.SQRT1_2, 0, Math.SQRT1_2, 0 ); - var a = new Quaternion(); + const a = new Quaternion(); a.slerpQuaternions( e, f, 0.5 ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -682,11 +682,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'random', ( assert ) => { - var a = new Quaternion(); + const a = new Quaternion(); a.random(); - var identity = new Quaternion(); + const identity = new Quaternion(); assert.notDeepEqual( a, identity, @@ -699,8 +699,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion( - x, - y, - z, - w ); + const a = new Quaternion( x, y, z, w ); + const b = new Quaternion( - x, - y, - z, - w ); assert.ok( a.x != b.x, 'Passed!' ); assert.ok( a.y != b.y, 'Passed!' ); @@ -719,7 +719,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var a = new Quaternion(); + const a = new Quaternion(); a.fromArray( [ x, y, z, w ] ); assert.ok( a.x == x, 'Passed!' ); assert.ok( a.y == y, 'Passed!' ); @@ -736,22 +736,22 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var a = new Quaternion( x, y, z, w ); + const a = new Quaternion( x, y, z, w ); - var array = a.toArray(); + let array = a.toArray(); assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); assert.strictEqual( array[ 3 ], w, 'No array, no offset: check w' ); - var array = []; + array = []; a.toArray( array ); assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); assert.strictEqual( array[ 3 ], w, 'With array, no offset: check w' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); @@ -763,9 +763,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromBufferAttribute', ( assert ) => { - var a = new Quaternion(); + const a = new Quaternion(); - var attribute = new BufferAttribute( new Float32Array( [ + const attribute = new BufferAttribute( new Float32Array( [ 0, 0, 0, 1, .7, 0, 0, .7, @@ -795,14 +795,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( '_onChange', ( assert ) => { - var b = false; - var f = function () { + let b = false; + const f = function () { b = true; }; - var a = new Quaternion( 11, 12, 13, 1 ); + const a = new Quaternion( 11, 12, 13, 1 ); a._onChange( f ); assert.ok( a._onChangeCallback === f, 'Passed!' ); @@ -814,9 +814,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( '_onChangeCallback', ( assert ) => { - var b = false; - var a = new Quaternion( 11, 12, 13, 1 ); - var f = function () { + let b = false; + const a = new Quaternion( 11, 12, 13, 1 ); + const f = function () { b = true; assert.ok( a === this, 'Passed!' ); @@ -835,19 +835,19 @@ export default QUnit.module( 'Maths', () => { // OTHERS QUnit.test( 'multiplyVector3', ( assert ) => { - var angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; + const angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; // ensure euler conversion for Quaternion matches that of Matrix4 - for ( var i = 0; i < orders.length; i ++ ) { + for ( let i = 0; i < orders.length; i ++ ) { - for ( var j = 0; j < angles.length; j ++ ) { + for ( let j = 0; j < angles.length; j ++ ) { - var q = new Quaternion().setFromEuler( changeEulerOrder( angles[ j ], orders[ i ] ) ); - var m = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ j ], orders[ i ] ) ); + const q = new Quaternion().setFromEuler( changeEulerOrder( angles[ j ], orders[ i ] ) ); + const m = new Matrix4().makeRotationFromEuler( changeEulerOrder( angles[ j ], orders[ i ] ) ); - var v0 = new Vector3( 1, 0, 0 ); - var qv = v0.clone().applyQuaternion( q ); - var mv = v0.clone().applyMatrix4( m ); + const v0 = new Vector3( 1, 0, 0 ); + const qv = v0.clone().applyQuaternion( q ); + const mv = v0.clone().applyMatrix4( m ); assert.ok( qv.distanceTo( mv ) < 0.001, 'Passed!' ); @@ -857,10 +857,21 @@ export default QUnit.module( 'Maths', () => { } ); + QUnit.test( 'toJSON', ( assert ) => { + + const q = new Quaternion( 0, 0.5, 0.7, 1 ); + const array = q.toJSON(); + assert.strictEqual( array[ 0 ], 0, 'Quaternion is serializable.' ); + assert.strictEqual( array[ 1 ], 0.5, 'Quaternion is serializable.' ); + assert.strictEqual( array[ 2 ], 0.7, 'Quaternion is serializable.' ); + assert.strictEqual( array[ 3 ], 1, 'Quaternion is serializable.' ); + + } ); + QUnit.test( 'iterable', ( assert ) => { - var q = new Quaternion( 0, 0.5, 0.7, 1 ); - var array = [ ...q ]; + const q = new Quaternion( 0, 0.5, 0.7, 1 ); + const array = [ ...q ]; assert.strictEqual( array[ 0 ], 0, 'Quaternion is iterable.' ); assert.strictEqual( array[ 1 ], 0.5, 'Quaternion is iterable.' ); assert.strictEqual( array[ 2 ], 0.7, 'Quaternion is iterable.' ); diff --git a/test/unit/src/math/Ray.tests.js b/test/unit/src/math/Ray.tests.js index 66e90348846a11..7556c96a7e8580 100644 --- a/test/unit/src/math/Ray.tests.js +++ b/test/unit/src/math/Ray.tests.js @@ -21,11 +21,11 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Ray(); + let a = new Ray(); assert.ok( a.origin.equals( zero3 ), 'Passed!' ); assert.ok( a.direction.equals( new Vector3( 0, 0, - 1 ) ), 'Passed!' ); - var a = new Ray( two3.clone(), one3.clone() ); + a = new Ray( two3.clone(), one3.clone() ); assert.ok( a.origin.equals( two3 ), 'Passed!' ); assert.ok( a.direction.equals( one3 ), 'Passed!' ); @@ -34,7 +34,7 @@ export default QUnit.module( 'Maths', () => { // PUBLIC QUnit.test( 'set', ( assert ) => { - var a = new Ray(); + const a = new Ray(); a.set( one3, one3 ); assert.ok( a.origin.equals( one3 ), 'Passed!' ); @@ -44,18 +44,18 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'recast/clone', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); assert.ok( a.recast( 0 ).equals( a ), 'Passed!' ); - var b = a.clone(); + const b = a.clone(); assert.ok( b.recast( - 1 ).equals( new Ray( new Vector3( 1, 1, 0 ), new Vector3( 0, 0, 1 ) ) ), 'Passed!' ); - var c = a.clone(); + const c = a.clone(); assert.ok( c.recast( 1 ).equals( new Ray( new Vector3( 1, 1, 2 ), new Vector3( 0, 0, 1 ) ) ), 'Passed!' ); - var d = a.clone(); - var e = d.clone().recast( 1 ); + const d = a.clone(); + const e = d.clone().recast( 1 ); assert.ok( d.equals( a ), 'Passed!' ); assert.ok( ! e.equals( d ), 'Passed!' ); assert.ok( e.equals( c ), 'Passed!' ); @@ -64,8 +64,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy/equals', ( assert ) => { - var a = new Ray( zero3.clone(), one3.clone() ); - var b = new Ray().copy( a ); + const a = new Ray( zero3.clone(), one3.clone() ); + const b = new Ray().copy( a ); assert.ok( b.origin.equals( zero3 ), 'Passed!' ); assert.ok( b.direction.equals( one3 ), 'Passed!' ); @@ -79,8 +79,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'at', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var point = new Vector3(); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const point = new Vector3(); a.at( 0, point ); assert.ok( point.equals( one3 ), 'Passed!' ); @@ -93,9 +93,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'lookAt', ( assert ) => { - var a = new Ray( two3.clone(), one3.clone() ); - var target = one3.clone(); - var expected = target.sub( two3 ).normalize(); + const a = new Ray( two3.clone(), one3.clone() ); + const target = one3.clone(); + const expected = target.sub( two3 ).normalize(); a.lookAt( target ); assert.ok( a.direction.equals( expected ), 'Check if we\'re looking in the right direction' ); @@ -104,8 +104,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'closestPointToPoint', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var point = new Vector3(); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const point = new Vector3(); // behind the ray a.closestPointToPoint( zero3, point ); @@ -123,50 +123,50 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceToPoint', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); // behind the ray - var b = a.distanceToPoint( zero3 ); + const b = a.distanceToPoint( zero3 ); assert.ok( b === Math.sqrt( 3 ), 'Passed!' ); // front of the ray - var c = a.distanceToPoint( new Vector3( 0, 0, 50 ) ); + const c = a.distanceToPoint( new Vector3( 0, 0, 50 ) ); assert.ok( c === Math.sqrt( 2 ), 'Passed!' ); // exactly on the ray - var d = a.distanceToPoint( one3 ); + const d = a.distanceToPoint( one3 ); assert.ok( d === 0, 'Passed!' ); } ); QUnit.test( 'distanceSqToPoint', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); // behind the ray - var b = a.distanceSqToPoint( zero3 ); + const b = a.distanceSqToPoint( zero3 ); assert.ok( b === 3, 'Passed!' ); // front of the ray - var c = a.distanceSqToPoint( new Vector3( 0, 0, 50 ) ); + const c = a.distanceSqToPoint( new Vector3( 0, 0, 50 ) ); assert.ok( c === 2, 'Passed!' ); // exactly on the ray - var d = a.distanceSqToPoint( one3 ); + const d = a.distanceSqToPoint( one3 ); assert.ok( d === 0, 'Passed!' ); } ); QUnit.test( 'distanceSqToSegment', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var ptOnLine = new Vector3(); - var ptOnSegment = new Vector3(); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const ptOnLine = new Vector3(); + const ptOnSegment = new Vector3(); //segment in front of the ray - var v0 = new Vector3( 3, 5, 50 ); - var v1 = new Vector3( 50, 50, 50 ); // just a far away point - var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); + let v0 = new Vector3( 3, 5, 50 ); + let v1 = new Vector3( 50, 50, 50 ); // just a far away point + let distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); assert.ok( ptOnSegment.distanceTo( v0 ) < 0.0001, 'Passed!' ); assert.ok( ptOnLine.distanceTo( new Vector3( 1, 1, 50 ) ) < 0.0001, 'Passed!' ); @@ -174,9 +174,9 @@ export default QUnit.module( 'Maths', () => { assert.ok( Math.abs( distSqr - 20 ) < 0.0001, 'Passed!' ); //segment behind the ray - var v0 = new Vector3( - 50, - 50, - 50 ); // just a far away point - var v1 = new Vector3( - 3, - 5, - 4 ); - var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); + v0 = new Vector3( - 50, - 50, - 50 ); // just a far away point + v1 = new Vector3( - 3, - 5, - 4 ); + distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); assert.ok( ptOnSegment.distanceTo( v1 ) < 0.0001, 'Passed!' ); assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, 'Passed!' ); @@ -184,9 +184,9 @@ export default QUnit.module( 'Maths', () => { assert.ok( Math.abs( distSqr - 77 ) < 0.0001, 'Passed!' ); //exact intersection between the ray and the segment - var v0 = new Vector3( - 50, - 50, - 50 ); - var v1 = new Vector3( 50, 50, 50 ); - var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); + v0 = new Vector3( - 50, - 50, - 50 ); + v1 = new Vector3( 50, 50, 50 ); + distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); assert.ok( ptOnSegment.distanceTo( one3 ) < 0.0001, 'Passed!' ); assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, 'Passed!' ); @@ -196,46 +196,46 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectSphere', ( assert ) => { - var TOL = 0.0001; - var point = new Vector3(); + const TOL = 0.0001; + const point = new Vector3(); // ray a0 origin located at ( 0, 0, 0 ) and points outward in negative-z direction - var a0 = new Ray( zero3.clone(), new Vector3( 0, 0, - 1 ) ); + const a0 = new Ray( zero3.clone(), new Vector3( 0, 0, - 1 ) ); // ray a1 origin located at ( 1, 1, 1 ) and points left in negative-x direction - var a1 = new Ray( one3.clone(), new Vector3( - 1, 0, 0 ) ); + const a1 = new Ray( one3.clone(), new Vector3( - 1, 0, 0 ) ); // sphere (radius of 2) located behind ray a0, should result in null - var b = new Sphere( new Vector3( 0, 0, 3 ), 2 ); + let b = new Sphere( new Vector3( 0, 0, 3 ), 2 ); a0.intersectSphere( b, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); // sphere (radius of 2) located in front of, but too far right of ray a0, should result in null - var b = new Sphere( new Vector3( 3, 0, - 1 ), 2 ); + b = new Sphere( new Vector3( 3, 0, - 1 ), 2 ); a0.intersectSphere( b, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); // sphere (radius of 2) located below ray a1, should result in null - var b = new Sphere( new Vector3( 1, - 2, 1 ), 2 ); + b = new Sphere( new Vector3( 1, - 2, 1 ), 2 ); a1.intersectSphere( b, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); // sphere (radius of 1) located to the left of ray a1, should result in intersection at 0, 1, 1 - var b = new Sphere( new Vector3( - 1, 1, 1 ), 1 ); + b = new Sphere( new Vector3( - 1, 1, 1 ), 1 ); a1.intersectSphere( b, point ); assert.ok( point.distanceTo( new Vector3( 0, 1, 1 ) ) < TOL, 'Passed!' ); // sphere (radius of 1) located in front of ray a0, should result in intersection at 0, 0, -1 - var b = new Sphere( new Vector3( 0, 0, - 2 ), 1 ); + b = new Sphere( new Vector3( 0, 0, - 2 ), 1 ); a0.intersectSphere( b, point ); assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, 'Passed!' ); // sphere (radius of 2) located in front & right of ray a0, should result in intersection at 0, 0, -1, or left-most edge of sphere - var b = new Sphere( new Vector3( 2, 0, - 1 ), 2 ); + b = new Sphere( new Vector3( 2, 0, - 1 ), 2 ); a0.intersectSphere( b, point ); assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, 'Passed!' ); // same situation as above, but move the sphere a fraction more to the right, and ray a0 should now just miss - var b = new Sphere( new Vector3( 2.01, 0, - 1 ), 2 ); + b = new Sphere( new Vector3( 2.01, 0, - 1 ), 2 ); a0.intersectSphere( b, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); @@ -244,21 +244,21 @@ export default QUnit.module( 'Maths', () => { // sphere (radius of 1) center located at ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 1, // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -1 // thus keeping the intersection point always in front of the ray. - var b = new Sphere( zero3.clone(), 1 ); + b = new Sphere( zero3.clone(), 1 ); a0.intersectSphere( b, point ); assert.ok( point.distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, 'Passed!' ); // sphere (radius of 4) center located behind ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 5, // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -3 // thus keeping the intersection point always in front of the ray. - var b = new Sphere( new Vector3( 0, 0, 1 ), 4 ); + b = new Sphere( new Vector3( 0, 0, 1 ), 4 ); a0.intersectSphere( b, point ); assert.ok( point.distanceTo( new Vector3( 0, 0, - 3 ) ) < TOL, 'Passed!' ); // sphere (radius of 4) center located in front of ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 3, // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -5 // thus keeping the intersection point always in front of the ray. - var b = new Sphere( new Vector3( 0, 0, - 1 ), 4 ); + b = new Sphere( new Vector3( 0, 0, - 1 ), 4 ); a0.intersectSphere( b, point ); assert.ok( point.distanceTo( new Vector3( 0, 0, - 5 ) ) < TOL, 'Passed!' ); @@ -266,12 +266,12 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsSphere', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var b = new Sphere( zero3, 0.5 ); - var c = new Sphere( zero3, 1.5 ); - var d = new Sphere( one3, 0.1 ); - var e = new Sphere( two3, 0.1 ); - var f = new Sphere( two3, 1 ); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const b = new Sphere( zero3, 0.5 ); + const c = new Sphere( zero3, 1.5 ); + const d = new Sphere( one3, 0.1 ); + const e = new Sphere( two3, 0.1 ); + const f = new Sphere( two3, 1 ); assert.ok( ! a.intersectsSphere( b ), 'Passed!' ); assert.ok( ! a.intersectsSphere( c ), 'Passed!' ); @@ -289,31 +289,31 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectPlane', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var point = new Vector3(); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const point = new Vector3(); // parallel plane behind - var b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, - 1 ) ); + const b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, - 1 ) ); a.intersectPlane( b, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); // parallel plane coincident with origin - var c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 0 ) ); + const c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 0 ) ); a.intersectPlane( c, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); // parallel plane infront - var d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 1 ) ); + const d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 1 ) ); a.intersectPlane( d, point.copy( posInf3 ) ); assert.ok( point.equals( a.origin ), 'Passed!' ); // perpendical ray that overlaps exactly - var e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); + const e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); a.intersectPlane( e, point.copy( posInf3 ) ); assert.ok( point.equals( a.origin ), 'Passed!' ); // perpendical ray that doesn't overlap - var f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); + const f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); a.intersectPlane( f, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); @@ -321,68 +321,68 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsPlane', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); // parallel plane in front of the ray - var b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, - 1 ) ) ); + const b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, - 1 ) ) ); assert.ok( a.intersectsPlane( b ), 'Passed!' ); // parallel plane coincident with origin - var c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 0 ) ) ); + const c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 0 ) ) ); assert.ok( a.intersectsPlane( c ), 'Passed!' ); // parallel plane behind the ray - var d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 1 ) ) ); + const d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 1 ) ) ); assert.ok( ! a.intersectsPlane( d ), 'Passed!' ); // perpendical ray that overlaps exactly - var e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); + const e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); assert.ok( a.intersectsPlane( e ), 'Passed!' ); // perpendical ray that doesn't overlap - var f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); + const f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); assert.ok( ! a.intersectsPlane( f ), 'Passed!' ); } ); QUnit.test( 'intersectBox', ( assert ) => { - var TOL = 0.0001; + const TOL = 0.0001; - var box = new Box3( new Vector3( - 1, - 1, - 1 ), new Vector3( 1, 1, 1 ) ); - var point = new Vector3(); + const box = new Box3( new Vector3( - 1, - 1, - 1 ), new Vector3( 1, 1, 1 ) ); + const point = new Vector3(); - var a = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( 1, 0, 0 ) ); + const a = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( 1, 0, 0 ) ); //ray should intersect box at -1,0,0 assert.ok( a.intersectsBox( box ) === true, 'Passed!' ); a.intersectBox( box, point ); assert.ok( point.distanceTo( new Vector3( - 1, 0, 0 ) ) < TOL, 'Passed!' ); - var b = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( - 1, 0, 0 ) ); + const b = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( - 1, 0, 0 ) ); //ray is point away from box, it should not intersect assert.ok( b.intersectsBox( box ) === false, 'Passed!' ); b.intersectBox( box, point.copy( posInf3 ) ); assert.ok( point.equals( posInf3 ), 'Passed!' ); - var c = new Ray( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ) ); + const c = new Ray( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ) ); // ray is inside box, should return exit point assert.ok( c.intersectsBox( box ) === true, 'Passed!' ); c.intersectBox( box, point ); assert.ok( point.distanceTo( new Vector3( 1, 0, 0 ) ) < TOL, 'Passed!' ); - var d = new Ray( new Vector3( 0, 2, 1 ), new Vector3( 0, - 1, - 1 ).normalize() ); + const d = new Ray( new Vector3( 0, 2, 1 ), new Vector3( 0, - 1, - 1 ).normalize() ); //tilted ray should intersect box at 0,1,0 assert.ok( d.intersectsBox( box ) === true, 'Passed!' ); d.intersectBox( box, point ); assert.ok( point.distanceTo( new Vector3( 0, 1, 0 ) ) < TOL, 'Passed!' ); - var e = new Ray( new Vector3( 1, - 2, 1 ), new Vector3( 0, 1, 0 ).normalize() ); + const e = new Ray( new Vector3( 1, - 2, 1 ), new Vector3( 0, 1, 0 ).normalize() ); //handle case where ray is coplanar with one of the boxes side - box in front of ray assert.ok( e.intersectsBox( box ) === true, 'Passed!' ); e.intersectBox( box, point ); assert.ok( point.distanceTo( new Vector3( 1, - 1, 1 ) ) < TOL, 'Passed!' ); - var f = new Ray( new Vector3( 1, - 2, 0 ), new Vector3( 0, - 1, 0 ).normalize() ); + const f = new Ray( new Vector3( 1, - 2, 0 ), new Vector3( 0, - 1, 0 ).normalize() ); //handle case where ray is coplanar with one of the boxes side - box behind ray assert.ok( f.intersectsBox( box ) === false, 'Passed!' ); f.intersectBox( box, point.copy( posInf3 ) ); @@ -398,11 +398,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectTriangle', ( assert ) => { - var ray = new Ray(); - var a = new Vector3( 1, 1, 0 ); - var b = new Vector3( 0, 1, 1 ); - var c = new Vector3( 1, 0, 1 ); - var point = new Vector3(); + const ray = new Ray(); + const a = new Vector3( 1, 1, 0 ); + const b = new Vector3( 0, 1, 1 ); + const c = new Vector3( 1, 0, 1 ); + const point = new Vector3(); // DdN == 0 ray.set( ray.origin, zero3.clone() ); @@ -447,25 +447,25 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var m = new Matrix4(); + let a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); + const m = new Matrix4(); assert.ok( a.clone().applyMatrix4( m ).equals( a ), 'Passed!' ); - var a = new Ray( zero3.clone(), new Vector3( 0, 0, 1 ) ); + a = new Ray( zero3.clone(), new Vector3( 0, 0, 1 ) ); m.makeRotationZ( Math.PI ); assert.ok( a.clone().applyMatrix4( m ).equals( a ), 'Passed!' ); m.makeRotationX( Math.PI ); - var b = a.clone(); + const b = a.clone(); b.direction.negate(); - var a2 = a.clone().applyMatrix4( m ); + let a2 = a.clone().applyMatrix4( m ); assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, 'Passed!' ); assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, 'Passed!' ); a.origin = new Vector3( 0, 0, 1 ); b.origin = new Vector3( 0, 0, - 1 ); - var a2 = a.clone().applyMatrix4( m ); + a2 = a.clone().applyMatrix4( m ); assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, 'Passed!' ); assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, 'Passed!' ); diff --git a/test/unit/src/math/Sphere.tests.js b/test/unit/src/math/Sphere.tests.js index 2a29f6cbdc9c45..2e2887008d6058 100644 --- a/test/unit/src/math/Sphere.tests.js +++ b/test/unit/src/math/Sphere.tests.js @@ -19,11 +19,11 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Sphere(); + let a = new Sphere(); assert.ok( a.center.equals( zero3 ), 'Passed!' ); assert.ok( a.radius == - 1, 'Passed!' ); - var a = new Sphere( one3.clone(), 1 ); + a = new Sphere( one3.clone(), 1 ); assert.ok( a.center.equals( one3 ), 'Passed!' ); assert.ok( a.radius == 1, 'Passed!' ); @@ -32,7 +32,7 @@ export default QUnit.module( 'Maths', () => { // PUBLIC QUnit.test( 'set', ( assert ) => { - var a = new Sphere(); + const a = new Sphere(); assert.ok( a.center.equals( zero3 ), 'Passed!' ); assert.ok( a.radius == - 1, 'Passed!' ); @@ -44,11 +44,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromPoints', ( assert ) => { - var a = new Sphere(); - var expectedCenter = new Vector3( 0.9330126941204071, 0, 0 ); - var expectedRadius = 1.3676668773461689; - var optionalCenter = new Vector3( 1, 1, 1 ); - var points = [ + const a = new Sphere(); + const expectedCenter = new Vector3( 0.9330126941204071, 0, 0 ); + let expectedRadius = 1.3676668773461689; + const optionalCenter = new Vector3( 1, 1, 1 ); + const points = [ new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ), new Vector3( 0.8660253882408142, 0.5, 0 ), @@ -67,7 +67,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( Math.abs( a.center.z - expectedCenter.z ) <= eps, 'Default center: check center.z' ); assert.ok( Math.abs( a.radius - expectedRadius ) <= eps, 'Default center: check radius' ); - var expectedRadius = 2.5946195770400102; + expectedRadius = 2.5946195770400102; a.setFromPoints( points, optionalCenter ); assert.ok( Math.abs( a.center.x - optionalCenter.x ) <= eps, 'Optional center: check center.x' ); assert.ok( Math.abs( a.center.y - optionalCenter.y ) <= eps, 'Optional center: check center.y' ); @@ -84,8 +84,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); - var b = new Sphere().copy( a ); + const a = new Sphere( one3.clone(), 1 ); + const b = new Sphere().copy( a ); assert.ok( b.center.equals( one3 ), 'Passed!' ); assert.ok( b.radius == 1, 'Passed!' ); @@ -100,7 +100,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'isEmpty', ( assert ) => { - var a = new Sphere(); + const a = new Sphere(); assert.ok( a.isEmpty(), 'Passed!' ); a.set( one3, 1 ); @@ -118,7 +118,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeEmpty', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); + const a = new Sphere( one3.clone(), 1 ); assert.ok( ! a.isEmpty(), 'Passed!' ); @@ -130,7 +130,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'containsPoint', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); + const a = new Sphere( one3.clone(), 1 ); assert.ok( ! a.containsPoint( zero3 ), 'Passed!' ); assert.ok( a.containsPoint( one3 ), 'Passed!' ); @@ -142,7 +142,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceToPoint', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); + const a = new Sphere( one3.clone(), 1 ); assert.ok( ( a.distanceToPoint( zero3 ) - 0.7320 ) < 0.001, 'Passed!' ); assert.ok( a.distanceToPoint( one3 ) === - 1, 'Passed!' ); @@ -151,9 +151,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsSphere', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); - var b = new Sphere( zero3.clone(), 1 ); - var c = new Sphere( zero3.clone(), 0.25 ); + const a = new Sphere( one3.clone(), 1 ); + const b = new Sphere( zero3.clone(), 1 ); + const c = new Sphere( zero3.clone(), 0.25 ); assert.ok( a.intersectsSphere( b ), 'Passed!' ); assert.ok( ! a.intersectsSphere( c ), 'Passed!' ); @@ -162,9 +162,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsBox', ( assert ) => { - var a = new Sphere( zero3, 1 ); - var b = new Sphere( new Vector3( - 5, - 5, - 5 ), 1 ); - var box = new Box3( zero3, one3 ); + const a = new Sphere( zero3, 1 ); + const b = new Sphere( new Vector3( - 5, - 5, - 5 ), 1 ); + const box = new Box3( zero3, one3 ); assert.strictEqual( a.intersectsBox( box ), true, 'Check unit sphere' ); assert.strictEqual( b.intersectsBox( box ), false, 'Check shifted sphere' ); @@ -173,10 +173,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsPlane', ( assert ) => { - var a = new Sphere( zero3.clone(), 1 ); - var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); - var d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); + const a = new Sphere( zero3.clone(), 1 ); + const b = new Plane( new Vector3( 0, 1, 0 ), 1 ); + const c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); + const d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); assert.ok( a.intersectsPlane( b ), 'Passed!' ); assert.ok( ! a.intersectsPlane( c ), 'Passed!' ); @@ -186,8 +186,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clampPoint', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); - var point = new Vector3(); + const a = new Sphere( one3.clone(), 1 ); + const point = new Vector3(); a.clampPoint( new Vector3( 1, 1, 3 ), point ); assert.ok( point.equals( new Vector3( 1, 1, 2 ) ), 'Passed!' ); @@ -198,8 +198,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getBoundingBox', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); - var aabb = new Box3(); + const a = new Sphere( one3.clone(), 1 ); + const aabb = new Box3(); a.getBoundingBox( aabb ); assert.ok( aabb.equals( new Box3( zero3, two3 ) ), 'Passed!' ); @@ -217,10 +217,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); - var m = new Matrix4().makeTranslation( 1, - 2, 1 ); - var aabb1 = new Box3(); - var aabb2 = new Box3(); + const a = new Sphere( one3.clone(), 1 ); + const m = new Matrix4().makeTranslation( 1, - 2, 1 ); + const aabb1 = new Box3(); + const aabb2 = new Box3(); a.clone().applyMatrix4( m ).getBoundingBox( aabb1 ); a.getBoundingBox( aabb2 ); @@ -231,7 +231,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'translate', ( assert ) => { - var a = new Sphere( one3.clone(), 1 ); + const a = new Sphere( one3.clone(), 1 ); a.translate( one3.clone().negate() ); assert.ok( a.center.equals( zero3 ), 'Passed!' ); @@ -240,8 +240,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'expandByPoint', ( assert ) => { - var a = new Sphere( zero3.clone(), 1 ); - var p = new Vector3( 2, 0, 0 ); + const a = new Sphere( zero3.clone(), 1 ); + const p = new Vector3( 2, 0, 0 ); assert.ok( a.containsPoint( p ) === false, 'a does not contain p' ); @@ -255,8 +255,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'union', ( assert ) => { - var a = new Sphere( zero3.clone(), 1 ); - var b = new Sphere( new Vector3( 2, 0, 0 ), 1 ); + const a = new Sphere( zero3.clone(), 1 ); + const b = new Sphere( new Vector3( 2, 0, 0 ), 1 ); a.union( b ); @@ -265,8 +265,8 @@ export default QUnit.module( 'Maths', () => { // d contains c (demonstrates why it is necessary to process two points in union) - var c = new Sphere( new Vector3(), 1 ); - var d = new Sphere( new Vector3( 1, 0, 0 ), 4 ); + const c = new Sphere( new Vector3(), 1 ); + const d = new Sphere( new Vector3( 1, 0, 0 ), 4 ); c.union( d ); @@ -275,8 +275,8 @@ export default QUnit.module( 'Maths', () => { // edge case: both spheres have the same center point - var e = new Sphere( new Vector3(), 1 ); - var f = new Sphere( new Vector3(), 4 ); + const e = new Sphere( new Vector3(), 1 ); + const f = new Sphere( new Vector3(), 4 ); e.union( f ); @@ -287,9 +287,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Sphere(); - var b = new Sphere( new Vector3( 1, 0, 0 ) ); - var c = new Sphere( new Vector3( 1, 0, 0 ), 1.0 ); + const a = new Sphere(); + const b = new Sphere( new Vector3( 1, 0, 0 ) ); + const c = new Sphere( new Vector3( 1, 0, 0 ), 1.0 ); assert.strictEqual( a.equals( b ), false, 'a does not equal b' ); assert.strictEqual( a.equals( c ), false, 'a does not equal c' ); diff --git a/test/unit/src/math/Spherical.tests.js b/test/unit/src/math/Spherical.tests.js index 07938a89d7643f..06735d2f73c7c5 100644 --- a/test/unit/src/math/Spherical.tests.js +++ b/test/unit/src/math/Spherical.tests.js @@ -13,16 +13,16 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Spherical(); - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; + let a = new Spherical(); + const radius = 10.0; + const phi = Math.acos( - 0.5 ); + const theta = Math.sqrt( Math.PI ) * phi; assert.strictEqual( a.radius, 1.0, 'Default values: check radius' ); assert.strictEqual( a.phi, 0, 'Default values: check phi' ); assert.strictEqual( a.theta, 0, 'Default values: check theta' ); - var a = new Spherical( radius, phi, theta ); + a = new Spherical( radius, phi, theta ); assert.strictEqual( a.radius, radius, 'Custom values: check radius' ); assert.strictEqual( a.phi, phi, 'Custom values: check phi' ); assert.strictEqual( a.theta, theta, 'Custom values: check theta' ); @@ -32,10 +32,10 @@ export default QUnit.module( 'Maths', () => { // PUBLIC STUFF QUnit.test( 'set', ( assert ) => { - var a = new Spherical(); - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; + const a = new Spherical(); + const radius = 10.0; + const phi = Math.acos( - 0.5 ); + const theta = Math.sqrt( Math.PI ) * phi; a.set( radius, phi, theta ); assert.strictEqual( a.radius, radius, 'Check radius' ); @@ -46,11 +46,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clone', ( assert ) => { - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - var a = new Spherical( radius, phi, theta ); - var b = a.clone(); + const radius = 10.0; + const phi = Math.acos( - 0.5 ); + const theta = Math.sqrt( Math.PI ) * phi; + const a = new Spherical( radius, phi, theta ); + const b = a.clone(); assert.propEqual( a, b, 'Check a and b are equal after clone()' ); @@ -61,11 +61,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - var a = new Spherical( radius, phi, theta ); - var b = new Spherical().copy( a ); + const radius = 10.0; + const phi = Math.acos( - 0.5 ); + const theta = Math.sqrt( Math.PI ) * phi; + const a = new Spherical( radius, phi, theta ); + const b = new Spherical().copy( a ); assert.propEqual( a, b, 'Check a and b are equal after copy()' ); @@ -76,11 +76,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'makeSafe', ( assert ) => { - var EPS = 0.000001; // from source - var tooLow = 0.0; - var tooHigh = Math.PI; - var justRight = 1.5; - var a = new Spherical( 1, tooLow, 0 ); + const EPS = 0.000001; // from source + const tooLow = 0.0; + const tooHigh = Math.PI; + const justRight = 1.5; + const a = new Spherical( 1, tooLow, 0 ); a.makeSafe(); assert.strictEqual( a.phi, EPS, 'Check if small values are set to EPS' ); @@ -97,10 +97,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromVector3', ( assert ) => { - var a = new Spherical( 1, 1, 1 ); - var b = new Vector3( 0, 0, 0 ); - var c = new Vector3( Math.PI, 1, - Math.PI ); - var expected = new Spherical( 4.554032147688322, 1.3494066171539107, 2.356194490192345 ); + const a = new Spherical( 1, 1, 1 ); + const b = new Vector3( 0, 0, 0 ); + const c = new Vector3( Math.PI, 1, - Math.PI ); + const expected = new Spherical( 4.554032147688322, 1.3494066171539107, 2.356194490192345 ); a.setFromVector3( b ); assert.strictEqual( a.radius, 0, 'Zero-length vector: check radius' ); @@ -116,8 +116,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromCartesianCoords', ( assert ) => { - var a = new Spherical( 1, 1, 1 ); - var expected = new Spherical( 4.554032147688322, 1.3494066171539107, 2.356194490192345 ); + const a = new Spherical( 1, 1, 1 ); + const expected = new Spherical( 4.554032147688322, 1.3494066171539107, 2.356194490192345 ); a.setFromCartesianCoords( 0, 0, 0 ); assert.strictEqual( a.radius, 0, 'Zero-length vector: check radius' ); diff --git a/test/unit/src/math/SphericalHarmonics3.tests.js b/test/unit/src/math/SphericalHarmonics3.tests.js index 8aeb4f8cd7c875..5e679620e93adf 100644 --- a/test/unit/src/math/SphericalHarmonics3.tests.js +++ b/test/unit/src/math/SphericalHarmonics3.tests.js @@ -7,9 +7,10 @@ export default QUnit.module( 'Maths', () => { QUnit.module( 'SphericalHarmonics3', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new SphericalHarmonics3(); + assert.ok( object, 'Can instantiate a SphericalHarmonics3.' ); } ); diff --git a/test/unit/src/math/Triangle.tests.js b/test/unit/src/math/Triangle.tests.js index d817f8732124b8..5c6374607df7e9 100644 --- a/test/unit/src/math/Triangle.tests.js +++ b/test/unit/src/math/Triangle.tests.js @@ -18,12 +18,12 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Triangle(); + let a = new Triangle(); assert.ok( a.a.equals( zero3 ), 'Passed!' ); assert.ok( a.b.equals( zero3 ), 'Passed!' ); assert.ok( a.c.equals( zero3 ), 'Passed!' ); - var a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); + a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); assert.ok( a.b.equals( one3 ), 'Passed!' ); assert.ok( a.c.equals( two3 ), 'Passed!' ); @@ -68,7 +68,7 @@ export default QUnit.module( 'Maths', () => { // PUBLIC QUnit.test( 'set', ( assert ) => { - var a = new Triangle(); + const a = new Triangle(); a.set( one3.clone().negate(), one3, two3 ); assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); @@ -79,9 +79,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromPointsAndIndices', ( assert ) => { - var a = new Triangle(); + const a = new Triangle(); - var points = [ one3, one3.clone().negate(), two3 ]; + const points = [ one3, one3.clone().negate(), two3 ]; a.setFromPointsAndIndices( points, 1, 0, 2 ); assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); assert.ok( a.b.equals( one3 ), 'Passed!' ); @@ -91,8 +91,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromAttributeAndIndices', ( assert ) => { - var a = new Triangle(); - var attribute = new BufferAttribute( new Float32Array( [ 1, 1, 1, - 1, - 1, - 1, 2, 2, 2 ] ), 3 ); + const a = new Triangle(); + const attribute = new BufferAttribute( new Float32Array( [ 1, 1, 1, - 1, - 1, - 1, 2, 2, 2 ] ), 3 ); a.setFromAttributeAndIndices( attribute, 1, 0, 2 ); assert.ok( a.a.equals( one3.clone().negate() ), 'Passed!' ); @@ -109,8 +109,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); - var b = new Triangle().copy( a ); + const a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); + const b = new Triangle().copy( a ); assert.ok( b.a.equals( one3.clone().negate() ), 'Passed!' ); assert.ok( b.b.equals( one3 ), 'Passed!' ); assert.ok( b.c.equals( two3 ), 'Passed!' ); @@ -127,57 +127,57 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getArea', ( assert ) => { - var a = new Triangle(); + let a = new Triangle(); assert.ok( a.getArea() == 0, 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); assert.ok( a.getArea() == 0.5, 'Passed!' ); - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); + a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); assert.ok( a.getArea() == 2, 'Passed!' ); // colinear triangle. - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 3, 0, 0 ) ); + a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 3, 0, 0 ) ); assert.ok( a.getArea() == 0, 'Passed!' ); } ); QUnit.test( 'getMidpoint', ( assert ) => { - var a = new Triangle(); - var midpoint = new Vector3(); + let a = new Triangle(); + const midpoint = new Vector3(); assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 1 / 3, 1 / 3, 0 ) ), 'Passed!' ); - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); + a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); assert.ok( a.getMidpoint( midpoint ).equals( new Vector3( 2 / 3, 0, 2 / 3 ) ), 'Passed!' ); } ); QUnit.test( 'getNormal', ( assert ) => { - var a = new Triangle(); - var normal = new Vector3(); + let a = new Triangle(); + const normal = new Vector3(); assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 0, 1 ) ), 'Passed!' ); - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); + a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); assert.ok( a.getNormal( normal ).equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); } ); QUnit.test( 'getPlane', ( assert ) => { - var a = new Triangle(); - var plane = new Plane(); - var normal = new Vector3(); + let a = new Triangle(); + const plane = new Plane(); + const normal = new Vector3(); a.getPlane( plane ); assert.notOk( isNaN( plane.distanceToPoint( a.a ) ), 'Passed!' ); @@ -189,7 +189,7 @@ export default QUnit.module( 'Maths', () => { z: NaN }, 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); a.getPlane( plane ); a.getNormal( normal ); assert.ok( plane.distanceToPoint( a.a ) == 0, 'Passed!' ); @@ -197,7 +197,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( plane.distanceToPoint( a.c ) == 0, 'Passed!' ); assert.ok( plane.normal.equals( normal ), 'Passed!' ); - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); + a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); a.getPlane( plane ); a.getNormal( normal ); assert.ok( plane.distanceToPoint( a.a ) == 0, 'Passed!' ); @@ -209,11 +209,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'getBarycoord', ( assert ) => { - var a = new Triangle(); + let a = new Triangle(); - var bad = new Vector3( - 2, - 1, - 1 ); - var barycoord = new Vector3(); - var midpoint = new Vector3(); + const bad = new Vector3( - 2, - 1, - 1 ); + const barycoord = new Vector3(); + const midpoint = new Vector3(); a.getBarycoord( a.a, barycoord ); assert.ok( barycoord.equals( bad ), 'Passed!' ); @@ -222,7 +222,7 @@ export default QUnit.module( 'Maths', () => { a.getBarycoord( a.c, barycoord ); assert.ok( barycoord.equals( bad ), 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); a.getMidpoint( midpoint ); a.getBarycoord( a.a, barycoord ); @@ -234,7 +234,7 @@ export default QUnit.module( 'Maths', () => { a.getBarycoord( midpoint, barycoord ); assert.ok( barycoord.distanceTo( new Vector3( 1 / 3, 1 / 3, 1 / 3 ) ) < 0.0001, 'Passed!' ); - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); + a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); a.getMidpoint( midpoint ); a.getBarycoord( a.a, barycoord ); @@ -258,14 +258,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'containsPoint', ( assert ) => { - var a = new Triangle(); - var midpoint = new Vector3(); + let a = new Triangle(); + const midpoint = new Vector3(); assert.ok( ! a.containsPoint( a.a ), 'Passed!' ); assert.ok( ! a.containsPoint( a.b ), 'Passed!' ); assert.ok( ! a.containsPoint( a.c ), 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); a.getMidpoint( midpoint ); assert.ok( a.containsPoint( a.a ), 'Passed!' ); assert.ok( a.containsPoint( a.b ), 'Passed!' ); @@ -273,7 +273,7 @@ export default QUnit.module( 'Maths', () => { assert.ok( a.containsPoint( midpoint ), 'Passed!' ); assert.ok( ! a.containsPoint( new Vector3( - 1, - 1, - 1 ) ), 'Passed!' ); - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); + a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); a.getMidpoint( midpoint ); assert.ok( a.containsPoint( a.a ), 'Passed!' ); assert.ok( a.containsPoint( a.b ), 'Passed!' ); @@ -285,12 +285,12 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'intersectsBox', ( assert ) => { - var a = new Box3( one3.clone(), two3.clone() ); - var b = new Triangle( new Vector3( 1.5, 1.5, 2.5 ), new Vector3( 2.5, 1.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - var c = new Triangle( new Vector3( 1.5, 1.5, 3.5 ), new Vector3( 3.5, 1.5, 1.5 ), new Vector3( 1.5, 1.5, 1.5 ) ); - var d = new Triangle( new Vector3( 1.5, 1.75, 3 ), new Vector3( 3, 1.75, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - var e = new Triangle( new Vector3( 1.5, 1.8, 3 ), new Vector3( 3, 1.8, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); - var f = new Triangle( new Vector3( 1.5, 2.5, 3 ), new Vector3( 3, 2.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const a = new Box3( one3.clone(), two3.clone() ); + const b = new Triangle( new Vector3( 1.5, 1.5, 2.5 ), new Vector3( 2.5, 1.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const c = new Triangle( new Vector3( 1.5, 1.5, 3.5 ), new Vector3( 3.5, 1.5, 1.5 ), new Vector3( 1.5, 1.5, 1.5 ) ); + const d = new Triangle( new Vector3( 1.5, 1.75, 3 ), new Vector3( 3, 1.75, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const e = new Triangle( new Vector3( 1.5, 1.8, 3 ), new Vector3( 3, 1.8, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); + const f = new Triangle( new Vector3( 1.5, 2.5, 3 ), new Vector3( 3, 2.5, 1.5 ), new Vector3( 1.5, 2.5, 1.5 ) ); assert.ok( b.intersectsBox( a ), 'Passed!' ); assert.ok( c.intersectsBox( a ), 'Passed!' ); @@ -302,8 +302,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'closestPointToPoint', ( assert ) => { - var a = new Triangle( new Vector3( - 1, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - var point = new Vector3(); + const a = new Triangle( new Vector3( - 1, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + const point = new Vector3(); // point lies inside the triangle a.closestPointToPoint( new Vector3( 0, 0.5, 0 ), point ); @@ -340,32 +340,32 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'isFrontFacing', ( assert ) => { - var a = new Triangle(); - var dir = new Vector3(); + let a = new Triangle(); + let dir = new Vector3(); assert.ok( ! a.isFrontFacing( dir ), 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - var dir = new Vector3( 0, 0, - 1 ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); + dir = new Vector3( 0, 0, - 1 ); assert.ok( a.isFrontFacing( dir ), 'Passed!' ); - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 1, 0, 0 ) ); + a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 1, 0, 0 ) ); assert.ok( ! a.isFrontFacing( dir ), 'Passed!' ); } ); QUnit.test( 'equals', ( assert ) => { - var a = new Triangle( + const a = new Triangle( new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ); - var b = new Triangle( + const b = new Triangle( new Vector3( 0, 0, 1 ), new Vector3( 0, 1, 0 ), new Vector3( 1, 0, 0 ) ); - var c = new Triangle( + const c = new Triangle( new Vector3( - 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) diff --git a/test/unit/src/math/Vector2.tests.js b/test/unit/src/math/Vector2.tests.js index 1554626b568777..42b5675e000872 100644 --- a/test/unit/src/math/Vector2.tests.js +++ b/test/unit/src/math/Vector2.tests.js @@ -16,11 +16,11 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Vector2(); + let a = new Vector2(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); - var a = new Vector2( x, y ); + a = new Vector2( x, y ); assert.ok( a.x === x, 'Passed!' ); assert.ok( a.y === y, 'Passed!' ); @@ -29,9 +29,9 @@ export default QUnit.module( 'Maths', () => { // PROPERTIES // ( [Itee] WHAT ??? o_O ) QUnit.test( 'properties', ( assert ) => { - var a = new Vector2( 0, 0 ); - var width = 100; - var height = 200; + const a = new Vector2( 0, 0 ); + const width = 100; + const height = 200; assert.ok( a.width = width, 'Set width' ); assert.ok( a.height = height, 'Set height' ); @@ -64,7 +64,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'set', ( assert ) => { - var a = new Vector2(); + const a = new Vector2(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); @@ -112,8 +112,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2().copy( a ); + const a = new Vector2( x, y ); + const b = new Vector2().copy( a ); assert.ok( b.x == x, 'Passed!' ); assert.ok( b.y == y, 'Passed!' ); @@ -127,14 +127,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'add', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); + const a = new Vector2( x, y ); + const b = new Vector2( - x, - y ); a.add( b ); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); - var c = new Vector2().addVectors( b, b ); + const c = new Vector2().addVectors( b, b ); assert.ok( c.x == - 2 * x, 'Passed!' ); assert.ok( c.y == - 2 * y, 'Passed!' ); @@ -154,9 +154,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'addScaledVector', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( 2, 3 ); - var s = 3; + const a = new Vector2( x, y ); + const b = new Vector2( 2, 3 ); + const s = 3; a.addScaledVector( b, s ); assert.strictEqual( a.x, x + b.x * s, 'Check x' ); @@ -166,14 +166,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'sub', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); + const a = new Vector2( x, y ); + const b = new Vector2( - x, - y ); a.sub( b ); assert.ok( a.x == 2 * x, 'Passed!' ); assert.ok( a.y == 2 * y, 'Passed!' ); - var c = new Vector2().subVectors( a, a ); + const c = new Vector2().subVectors( a, a ); assert.ok( c.x == 0, 'Passed!' ); assert.ok( c.y == 0, 'Passed!' ); @@ -217,8 +217,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix3', ( assert ) => { - var a = new Vector2( x, y ); - var m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); + const a = new Vector2( x, y ); + const m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); a.applyMatrix3( m ); assert.strictEqual( a.x, 18, 'Check x' ); @@ -282,7 +282,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'negate', ( assert ) => { - var a = new Vector2( x, y ); + const a = new Vector2( x, y ); a.negate(); assert.ok( a.x == - x, 'Passed!' ); @@ -292,24 +292,24 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'dot', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); - var c = new Vector2(); + const a = new Vector2( x, y ); + const b = new Vector2( - x, - y ); + const c = new Vector2(); - var result = a.dot( b ); + let result = a.dot( b ); assert.ok( result == ( - x * x - y * y ), 'Passed!' ); - var result = a.dot( c ); + result = a.dot( c ); assert.ok( result == 0, 'Passed!' ); } ); QUnit.test( 'cross', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( 2 * x, - y ); - var answer = - 18; - var crossed = a.cross( b ); + const a = new Vector2( x, y ); + const b = new Vector2( 2 * x, - y ); + const answer = - 18; + const crossed = a.cross( b ); assert.ok( Math.abs( answer - crossed ) <= eps, 'Check cross' ); @@ -329,9 +329,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'manhattanLength', ( assert ) => { - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - var c = new Vector2(); + const a = new Vector2( x, 0 ); + const b = new Vector2( 0, - y ); + const c = new Vector2(); assert.strictEqual( a.manhattanLength(), x, 'Positive component' ); assert.strictEqual( b.manhattanLength(), y, 'Negative component' ); @@ -344,8 +344,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'normalize', ( assert ) => { - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); + const a = new Vector2( x, 0 ); + const b = new Vector2( 0, - y ); a.normalize(); assert.ok( a.length() == 1, 'Passed!' ); @@ -363,6 +363,24 @@ export default QUnit.module( 'Maths', () => { } ); + QUnit.test( 'angleTo', ( assert ) => { + + const a = new Vector2( - 0.18851655680720186, 0.9820700116639124 ); + const b = new Vector2( 0.18851655680720186, - 0.9820700116639124 ); + + assert.equal( a.angleTo( a ), 0 ); + assert.equal( a.angleTo( b ), Math.PI ); + + const x = new Vector2( 1, 0 ); + const y = new Vector2( 0, 1 ); + + assert.equal( x.angleTo( y ), Math.PI / 2 ); + assert.equal( y.angleTo( x ), Math.PI / 2 ); + + assert.ok( Math.abs( x.angleTo( new Vector2( 1, 1 ) ) - ( Math.PI / 4 ) ) < 0.0000001 ); + + } ); + QUnit.todo( 'distanceTo', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -383,13 +401,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setLength', ( assert ) => { - var a = new Vector2( x, 0 ); + let a = new Vector2( x, 0 ); assert.ok( a.length() == x, 'Passed!' ); a.setLength( y ); assert.ok( a.length() == y, 'Passed!' ); - var a = new Vector2( 0, 0 ); + a = new Vector2( 0, 0 ); assert.ok( a.length() == 0, 'Passed!' ); a.setLength( y ); assert.ok( a.length() == 0, 'Passed!' ); @@ -412,8 +430,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); + const a = new Vector2( x, 0 ); + const b = new Vector2( 0, - y ); assert.ok( a.x != b.x, 'Passed!' ); assert.ok( a.y != b.y, 'Passed!' ); @@ -432,8 +450,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var a = new Vector2(); - var array = [ 1, 2, 3, 4 ]; + const a = new Vector2(); + const array = [ 1, 2, 3, 4 ]; a.fromArray( array ); assert.strictEqual( a.x, 1, 'No offset: check x' ); @@ -447,18 +465,18 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var a = new Vector2( x, y ); + const a = new Vector2( x, y ); - var array = a.toArray(); + let array = a.toArray(); assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); - var array = []; + array = []; a.toArray( array ); assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); @@ -468,8 +486,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromBufferAttribute', ( assert ) => { - var a = new Vector2(); - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2 ); + const a = new Vector2(); + const attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2 ); a.fromBufferAttribute( attr, 0 ); assert.strictEqual( a.x, 1, 'Offset 0: check x' ); @@ -487,11 +505,10 @@ export default QUnit.module( 'Maths', () => { } ); - // TODO (Itee) refactor/split QUnit.test( 'setX,setY', ( assert ) => { - var a = new Vector2(); + const a = new Vector2(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); @@ -504,7 +521,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setComponent,getComponent', ( assert ) => { - var a = new Vector2(); + const a = new Vector2(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); @@ -517,8 +534,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiply/divide', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); + const a = new Vector2( x, y ); + const b = new Vector2( - x, - y ); a.multiplyScalar( - 2 ); assert.ok( a.x == x * - 2, 'Passed!' ); @@ -540,9 +557,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'min/max/clamp', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); - var c = new Vector2(); + const a = new Vector2( x, y ); + const b = new Vector2( - x, - y ); + const c = new Vector2(); c.copy( a ).min( b ); assert.ok( c.x == - x, 'Passed!' ); @@ -589,9 +606,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'length/lengthSq', ( assert ) => { - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - var c = new Vector2(); + const a = new Vector2( x, 0 ); + const b = new Vector2( 0, - y ); + const c = new Vector2(); assert.ok( a.length() == x, 'Passed!' ); assert.ok( a.lengthSq() == x * x, 'Passed!' ); @@ -608,9 +625,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceTo/distanceToSquared', ( assert ) => { - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - var c = new Vector2(); + const a = new Vector2( x, 0 ); + const b = new Vector2( 0, - y ); + const c = new Vector2(); assert.ok( a.distanceTo( c ) == x, 'Passed!' ); assert.ok( a.distanceToSquared( c ) == x * x, 'Passed!' ); @@ -622,8 +639,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'lerp/clone', ( assert ) => { - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); + const a = new Vector2( x, 0 ); + const b = new Vector2( 0, - y ); assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), 'Passed!' ); assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), 'Passed!' ); @@ -639,7 +656,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setComponent/getComponent exceptions', ( assert ) => { - var a = new Vector2( 0, 0 ); + const a = new Vector2( 0, 0 ); assert.throws( function () { @@ -664,8 +681,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setScalar/addScalar/subScalar', ( assert ) => { - var a = new Vector2( 1, 1 ); - var s = 3; + const a = new Vector2( 1, 1 ); + const s = 3; a.setScalar( s ); assert.strictEqual( a.x, s, 'setScalar: check x' ); @@ -683,9 +700,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiply/divide', ( assert ) => { - var a = new Vector2( x, y ); - var b = new Vector2( 2 * x, 2 * y ); - var c = new Vector2( 4 * x, 4 * y ); + const a = new Vector2( x, y ); + const b = new Vector2( 2 * x, 2 * y ); + const c = new Vector2( 4 * x, 4 * y ); a.multiply( b ); assert.strictEqual( a.x, x * b.x, 'multiply: check x' ); @@ -700,8 +717,8 @@ export default QUnit.module( 'Maths', () => { // OTHERS QUnit.test( 'iterable', ( assert ) => { - var v = new Vector2( 0, 1 ); - var array = [ ...v ]; + const v = new Vector2( 0, 1 ); + const array = [ ...v ]; assert.strictEqual( array[ 0 ], 0, 'Vector2 is iterable.' ); assert.strictEqual( array[ 1 ], 1, 'Vector2 is iterable.' ); diff --git a/test/unit/src/math/Vector3.tests.js b/test/unit/src/math/Vector3.tests.js index 0a94e48453f151..43ab4dc44d434b 100644 --- a/test/unit/src/math/Vector3.tests.js +++ b/test/unit/src/math/Vector3.tests.js @@ -25,12 +25,12 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Vector3(); + let a = new Vector3(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); - var a = new Vector3( x, y, z ); + a = new Vector3( x, y, z ); assert.ok( a.x === x, 'Passed!' ); assert.ok( a.y === y, 'Passed!' ); assert.ok( a.z === z, 'Passed!' ); @@ -47,7 +47,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'set', ( assert ) => { - var a = new Vector3(); + const a = new Vector3(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); @@ -103,8 +103,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3().copy( a ); + const a = new Vector3( x, y, z ); + const b = new Vector3().copy( a ); assert.ok( b.x == x, 'Passed!' ); assert.ok( b.y == y, 'Passed!' ); assert.ok( b.z == z, 'Passed!' ); @@ -121,15 +121,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'add', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); + const a = new Vector3( x, y, z ); + const b = new Vector3( - x, - y, - z ); a.add( b ); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); - var c = new Vector3().addVectors( b, b ); + const c = new Vector3().addVectors( b, b ); assert.ok( c.x == - 2 * x, 'Passed!' ); assert.ok( c.y == - 2 * y, 'Passed!' ); assert.ok( c.z == - 2 * z, 'Passed!' ); @@ -150,9 +150,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'addScaledVector', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( 2, 3, 4 ); - var s = 3; + const a = new Vector3( x, y, z ); + const b = new Vector3( 2, 3, 4 ); + const s = 3; a.addScaledVector( b, s ); assert.strictEqual( a.x, x + b.x * s, 'Check x' ); @@ -163,15 +163,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'sub', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); + const a = new Vector3( x, y, z ); + const b = new Vector3( - x, - y, - z ); a.sub( b ); assert.ok( a.x == 2 * x, 'Passed!' ); assert.ok( a.y == 2 * y, 'Passed!' ); assert.ok( a.z == 2 * z, 'Passed!' ); - var c = new Vector3().subVectors( a, a ); + const c = new Vector3().subVectors( a, a ); assert.ok( c.x == 0, 'Passed!' ); assert.ok( c.y == 0, 'Passed!' ); assert.ok( c.z == 0, 'Passed!' ); @@ -204,10 +204,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiplyVectors', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( 2, 3, - 5 ); + const a = new Vector3( x, y, z ); + const b = new Vector3( 2, 3, - 5 ); - var c = new Vector3().multiplyVectors( a, b ); + const c = new Vector3().multiplyVectors( a, b ); assert.strictEqual( c.x, x * 2, 'Check x' ); assert.strictEqual( c.y, y * 3, 'Check y' ); assert.strictEqual( c.z, z * - 5, 'Check z' ); @@ -216,9 +216,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyEuler', ( assert ) => { - var a = new Vector3( x, y, z ); - var euler = new Euler( 90, - 45, 0 ); - var expected = new Vector3( - 2.352970120501014, - 4.7441750936226645, 0.9779234597246458 ); + const a = new Vector3( x, y, z ); + const euler = new Euler( 90, - 45, 0 ); + const expected = new Vector3( - 2.352970120501014, - 4.7441750936226645, 0.9779234597246458 ); a.applyEuler( euler ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -229,10 +229,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyAxisAngle', ( assert ) => { - var a = new Vector3( x, y, z ); - var axis = new Vector3( 0, 1, 0 ); - var angle = Math.PI / 4.0; - var expected = new Vector3( 3 * Math.sqrt( 2 ), 3, Math.sqrt( 2 ) ); + const a = new Vector3( x, y, z ); + const axis = new Vector3( 0, 1, 0 ); + const angle = Math.PI / 4.0; + const expected = new Vector3( 3 * Math.sqrt( 2 ), 3, Math.sqrt( 2 ) ); a.applyAxisAngle( axis, angle ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -243,8 +243,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix3', ( assert ) => { - var a = new Vector3( x, y, z ); - var m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); + const a = new Vector3( x, y, z ); + const m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); a.applyMatrix3( m ); assert.strictEqual( a.x, 33, 'Check x' ); @@ -263,24 +263,24 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector4( x, y, z, 1 ); + const a = new Vector3( x, y, z ); + const b = new Vector4( x, y, z, 1 ); - var m = new Matrix4().makeRotationX( Math.PI ); + let m = new Matrix4().makeRotationX( Math.PI ); a.applyMatrix4( m ); b.applyMatrix4( m ); assert.ok( a.x == b.x / b.w, 'Passed!' ); assert.ok( a.y == b.y / b.w, 'Passed!' ); assert.ok( a.z == b.z / b.w, 'Passed!' ); - var m = new Matrix4().makeTranslation( 3, 2, 1 ); + m = new Matrix4().makeTranslation( 3, 2, 1 ); a.applyMatrix4( m ); b.applyMatrix4( m ); assert.ok( a.x == b.x / b.w, 'Passed!' ); assert.ok( a.y == b.y / b.w, 'Passed!' ); assert.ok( a.z == b.z / b.w, 'Passed!' ); - var m = new Matrix4().set( + m = new Matrix4().set( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, @@ -296,7 +296,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyQuaternion', ( assert ) => { - var a = new Vector3( x, y, z ); + const a = new Vector3( x, y, z ); a.applyQuaternion( new Quaternion() ); assert.strictEqual( a.x, x, 'Identity rotation: check x' ); @@ -324,9 +324,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'transformDirection', ( assert ) => { - var a = new Vector3( x, y, z ); - var m = new Matrix4(); - var transformed = new Vector3( 0.3713906763541037, 0.5570860145311556, 0.7427813527082074 ); + const a = new Vector3( x, y, z ); + const m = new Matrix4(); + const transformed = new Vector3( 0.3713906763541037, 0.5570860145311556, 0.7427813527082074 ); a.transformDirection( m ); assert.ok( Math.abs( a.x - transformed.x ) <= eps, 'Check x' ); @@ -367,8 +367,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clampScalar', ( assert ) => { - var a = new Vector3( - 0.01, 0.5, 1.5 ); - var clamped = new Vector3( 0.1, 0.5, 1.0 ); + const a = new Vector3( - 0.01, 0.5, 1.5 ); + const clamped = new Vector3( 0.1, 0.5, 1.0 ); a.clampScalar( 0.1, 1.0 ); assert.ok( Math.abs( a.x - clamped.x ) <= 0.001, 'Check x' ); @@ -409,7 +409,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'negate', ( assert ) => { - var a = new Vector3( x, y, z ); + const a = new Vector3( x, y, z ); a.negate(); assert.ok( a.x == - x, 'Passed!' ); @@ -420,14 +420,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'dot', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); - var c = new Vector3(); + const a = new Vector3( x, y, z ); + const b = new Vector3( - x, - y, - z ); + const c = new Vector3(); - var result = a.dot( b ); + let result = a.dot( b ); assert.ok( result == ( - x * x - y * y - z * z ), 'Passed!' ); - var result = a.dot( c ); + result = a.dot( c ); assert.ok( result == 0, 'Passed!' ); } ); @@ -446,10 +446,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'manhattanLength', ( assert ) => { - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); - var d = new Vector3(); + const a = new Vector3( x, 0, 0 ); + const b = new Vector3( 0, - y, 0 ); + const c = new Vector3( 0, 0, z ); + const d = new Vector3(); assert.ok( a.manhattanLength() == x, 'Positive x' ); assert.ok( b.manhattanLength() == y, 'Negative y' ); @@ -463,9 +463,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'normalize', ( assert ) => { - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); + const a = new Vector3( x, 0, 0 ); + const b = new Vector3( 0, - y, 0 ); + const c = new Vector3( 0, 0, z ); a.normalize(); assert.ok( a.length() == 1, 'Passed!' ); @@ -483,13 +483,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setLength', ( assert ) => { - var a = new Vector3( x, 0, 0 ); + let a = new Vector3( x, 0, 0 ); assert.ok( a.length() == x, 'Passed!' ); a.setLength( y ); assert.ok( a.length() == y, 'Passed!' ); - var a = new Vector3( 0, 0, 0 ); + a = new Vector3( 0, 0, 0 ); assert.ok( a.length() == 0, 'Passed!' ); a.setLength( y ); assert.ok( a.length() == 0, 'Passed!' ); @@ -512,9 +512,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'cross', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( 2 * x, - y, 0.5 * z ); - var crossed = new Vector3( 18, 12, - 18 ); + const a = new Vector3( x, y, z ); + const b = new Vector3( 2 * x, - y, 0.5 * z ); + const crossed = new Vector3( 18, 12, - 18 ); a.cross( b ); assert.ok( Math.abs( a.x - crossed.x ) <= eps, 'Check x' ); @@ -525,10 +525,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'crossVectors', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( x, - y, z ); - var c = new Vector3(); - var crossed = new Vector3( 24, 0, - 12 ); + const a = new Vector3( x, y, z ); + const b = new Vector3( x, - y, z ); + const c = new Vector3(); + const crossed = new Vector3( 24, 0, - 12 ); c.crossVectors( a, b ); assert.ok( Math.abs( c.x - crossed.x ) <= eps, 'Check x' ); @@ -539,9 +539,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'projectOnVector', ( assert ) => { - var a = new Vector3( 1, 0, 0 ); - var b = new Vector3(); - var normal = new Vector3( 10, 0, 0 ); + const a = new Vector3( 1, 0, 0 ); + const b = new Vector3(); + const normal = new Vector3( 10, 0, 0 ); assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 1, 0, 0 ) ), 'Passed!' ); @@ -558,9 +558,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'projectOnPlane', ( assert ) => { - var a = new Vector3( 1, 0, 0 ); - var b = new Vector3(); - var normal = new Vector3( 1, 0, 0 ); + const a = new Vector3( 1, 0, 0 ); + const b = new Vector3(); + const normal = new Vector3( 1, 0, 0 ); assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, 0 ) ), 'Passed!' ); @@ -577,9 +577,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'reflect', ( assert ) => { - var a = new Vector3(); - var normal = new Vector3( 0, 1, 0 ); - var b = new Vector3(); + const a = new Vector3(); + const normal = new Vector3( 0, 1, 0 ); + const b = new Vector3(); a.set( 0, - 1, 0 ); assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 0, 1, 0 ) ), 'Passed!' ); @@ -595,15 +595,15 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'angleTo', ( assert ) => { - var a = new Vector3( 0, - 0.18851655680720186, 0.9820700116639124 ); - var b = new Vector3( 0, 0.18851655680720186, - 0.9820700116639124 ); + const a = new Vector3( 0, - 0.18851655680720186, 0.9820700116639124 ); + const b = new Vector3( 0, 0.18851655680720186, - 0.9820700116639124 ); assert.equal( a.angleTo( a ), 0 ); assert.equal( a.angleTo( b ), Math.PI ); - var x = new Vector3( 1, 0, 0 ); - var y = new Vector3( 0, 1, 0 ); - var z = new Vector3( 0, 0, 1 ); + const x = new Vector3( 1, 0, 0 ); + const y = new Vector3( 0, 1, 0 ); + const z = new Vector3( 0, 0, 1 ); assert.equal( x.angleTo( y ), Math.PI / 2 ); assert.equal( x.angleTo( z ), Math.PI / 2 ); @@ -633,11 +633,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromSpherical', ( assert ) => { - var a = new Vector3(); - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - var sph = new Spherical( 10, phi, theta ); - var expected = new Vector3( - 4.677914006701843, - 5, - 7.288149322420796 ); + const a = new Vector3(); + const phi = Math.acos( - 0.5 ); + const theta = Math.sqrt( Math.PI ) * phi; + const sph = new Spherical( 10, phi, theta ); + const expected = new Vector3( - 4.677914006701843, - 5, - 7.288149322420796 ); a.setFromSpherical( sph ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -655,9 +655,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromCylindrical', ( assert ) => { - var a = new Vector3(); - var cyl = new Cylindrical( 10, Math.PI * 0.125, 20 ); - var expected = new Vector3( 3.826834323650898, 20, 9.238795325112868 ); + const a = new Vector3(); + const cyl = new Cylindrical( 10, Math.PI * 0.125, 20 ); + const expected = new Vector3( 3.826834323650898, 20, 9.238795325112868 ); a.setFromCylindrical( cyl ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -675,8 +675,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromMatrixPosition', ( assert ) => { - var a = new Vector3(); - var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); + const a = new Vector3(); + const m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); a.setFromMatrixPosition( m ); assert.strictEqual( a.x, 7, 'Check x' ); @@ -687,9 +687,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromMatrixScale', ( assert ) => { - var a = new Vector3(); - var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - var expected = new Vector3( 25.573423705088842, 31.921779399024736, 35.70714214271425 ); + const a = new Vector3(); + const m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); + const expected = new Vector3( 25.573423705088842, 31.921779399024736, 35.70714214271425 ); a.setFromMatrixScale( m ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Check x' ); @@ -700,8 +700,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setFromMatrixColumn', ( assert ) => { - var a = new Vector3(); - var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); + const a = new Vector3(); + const m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); a.setFromMatrixColumn( m, 0 ); assert.strictEqual( a.x, 2, 'Index 0: check x' ); @@ -731,8 +731,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Vector3( x, 0, z ); - var b = new Vector3( 0, - y, 0 ); + const a = new Vector3( x, 0, z ); + const b = new Vector3( 0, - y, 0 ); assert.ok( a.x != b.x, 'Passed!' ); assert.ok( a.y != b.y, 'Passed!' ); @@ -753,8 +753,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var a = new Vector3(); - var array = [ 1, 2, 3, 4, 5, 6 ]; + const a = new Vector3(); + const array = [ 1, 2, 3, 4, 5, 6 ]; a.fromArray( array ); assert.strictEqual( a.x, 1, 'No offset: check x' ); @@ -770,20 +770,20 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var a = new Vector3( x, y, z ); + const a = new Vector3( x, y, z ); - var array = a.toArray(); + let array = a.toArray(); assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); - var array = []; + array = []; a.toArray( array ); assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); @@ -794,8 +794,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromBufferAttribute', ( assert ) => { - var a = new Vector3(); - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); + const a = new Vector3(); + const attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); a.fromBufferAttribute( attr, 0 ); assert.strictEqual( a.x, 1, 'Offset 0: check x' ); @@ -818,11 +818,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'randomDirection', ( assert ) => { - var vec = new Vector3(); + const vec = new Vector3(); vec.randomDirection(); - var zero = new Vector3(); + const zero = new Vector3(); assert.notDeepEqual( vec, zero, @@ -836,7 +836,7 @@ export default QUnit.module( 'Maths', () => { // TODO (Itee) refactor/split QUnit.test( 'setX,setY,setZ', ( assert ) => { - var a = new Vector3(); + const a = new Vector3(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); @@ -853,7 +853,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setComponent,getComponent', ( assert ) => { - var a = new Vector3(); + const a = new Vector3(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); @@ -869,7 +869,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setComponent/getComponent exceptions', ( assert ) => { - var a = new Vector3(); + const a = new Vector3(); assert.throws( function () { @@ -894,9 +894,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'min/max/clamp', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); - var c = new Vector3(); + const a = new Vector3( x, y, z ); + const b = new Vector3( - x, - y, - z ); + const c = new Vector3(); c.copy( a ).min( b ); assert.ok( c.x == - x, 'Passed!' ); @@ -918,10 +918,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'distanceTo/distanceToSquared', ( assert ) => { - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); - var d = new Vector3(); + const a = new Vector3( x, 0, 0 ); + const b = new Vector3( 0, - y, 0 ); + const c = new Vector3( 0, 0, z ); + const d = new Vector3(); assert.ok( a.distanceTo( d ) == x, 'Passed!' ); assert.ok( a.distanceToSquared( d ) == x * x, 'Passed!' ); @@ -936,8 +936,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setScalar/addScalar/subScalar', ( assert ) => { - var a = new Vector3(); - var s = 3; + const a = new Vector3(); + const s = 3; a.setScalar( s ); assert.strictEqual( a.x, s, 'setScalar: check x' ); @@ -958,9 +958,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiply/divide', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( 2 * x, 2 * y, 2 * z ); - var c = new Vector3( 4 * x, 4 * y, 4 * z ); + const a = new Vector3( x, y, z ); + const b = new Vector3( 2 * x, 2 * y, 2 * z ); + const c = new Vector3( 4 * x, 4 * y, 4 * z ); a.multiply( b ); assert.strictEqual( a.x, x * b.x, 'multiply: check x' ); @@ -976,8 +976,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiply/divide', ( assert ) => { - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); + const a = new Vector3( x, y, z ); + const b = new Vector3( - x, - y, - z ); a.multiplyScalar( - 2 ); assert.ok( a.x == x * - 2, 'Passed!' ); @@ -1003,9 +1003,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'project/unproject', ( assert ) => { - var a = new Vector3( x, y, z ); - var camera = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); - var projected = new Vector3( - 0.36653213611158914, - 0.9774190296309043, 1.0506835611870624 ); + const a = new Vector3( x, y, z ); + const camera = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); + const projected = new Vector3( - 0.36653213611158914, - 0.9774190296309043, 1.0506835611870624 ); a.project( camera ); assert.ok( Math.abs( a.x - projected.x ) <= eps, 'project: check x' ); @@ -1021,10 +1021,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'length/lengthSq', ( assert ) => { - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); - var d = new Vector3(); + const a = new Vector3( x, 0, 0 ); + const b = new Vector3( 0, - y, 0 ); + const c = new Vector3( 0, 0, z ); + const d = new Vector3(); assert.ok( a.length() == x, 'Passed!' ); assert.ok( a.lengthSq() == x * x, 'Passed!' ); @@ -1043,8 +1043,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'lerp/clone', ( assert ) => { - var a = new Vector3( x, 0, z ); - var b = new Vector3( 0, - y, 0 ); + const a = new Vector3( x, 0, z ); + const b = new Vector3( 0, - y, 0 ); assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), 'Passed!' ); assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), 'Passed!' ); @@ -1062,8 +1062,8 @@ export default QUnit.module( 'Maths', () => { // OTHERS QUnit.test( 'iterable', ( assert ) => { - var v = new Vector3( 0, 0.5, 1 ); - var array = [ ...v ]; + const v = new Vector3( 0, 0.5, 1 ); + const array = [ ...v ]; assert.strictEqual( array[ 0 ], 0, 'Vector3 is iterable.' ); assert.strictEqual( array[ 1 ], 0.5, 'Vector3 is iterable.' ); assert.strictEqual( array[ 2 ], 1, 'Vector3 is iterable.' ); diff --git a/test/unit/src/math/Vector4.tests.js b/test/unit/src/math/Vector4.tests.js index e5def1795223de..6b19875b19f67c 100644 --- a/test/unit/src/math/Vector4.tests.js +++ b/test/unit/src/math/Vector4.tests.js @@ -18,13 +18,13 @@ export default QUnit.module( 'Maths', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - var a = new Vector4(); + let a = new Vector4(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); assert.ok( a.w == 1, 'Passed!' ); - var a = new Vector4( x, y, z, w ); + a = new Vector4( x, y, z, w ); assert.ok( a.x === x, 'Passed!' ); assert.ok( a.y === y, 'Passed!' ); assert.ok( a.z === z, 'Passed!' ); @@ -42,7 +42,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'set', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); @@ -64,7 +64,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setX', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.ok( a.x == 0, 'Passed!' ); a.setX( x ); @@ -74,7 +74,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setY', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.ok( a.y == 0, 'Passed!' ); a.setY( y ); @@ -84,7 +84,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setZ', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.ok( a.z == 0, 'Passed!' ); a.setZ( z ); @@ -94,7 +94,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setW', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.ok( a.w == 1, 'Passed!' ); a.setW( w ); @@ -122,8 +122,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'copy', ( assert ) => { - var a = new Vector4( x, y, z, w ); - var b = new Vector4().copy( a ); + const a = new Vector4( x, y, z, w ); + const b = new Vector4().copy( a ); assert.ok( b.x == x, 'Passed!' ); assert.ok( b.y == y, 'Passed!' ); assert.ok( b.z == z, 'Passed!' ); @@ -174,9 +174,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'addScaledVector', ( assert ) => { - var a = new Vector4( x, y, z, w ); - var b = new Vector4( 6, 7, 8, 9 ); - var s = 3; + const a = new Vector4( x, y, z, w ); + const b = new Vector4( 6, 7, 8, 9 ); + const s = 3; a.addScaledVector( b, s ); assert.strictEqual( a.x, x + b.x * s, 'Check x' ); @@ -230,9 +230,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'applyMatrix4', ( assert ) => { - var a = new Vector4( x, y, z, w ); - var m = new Matrix4().makeRotationX( Math.PI ); - var expected = new Vector4( 2, - 3, - 4, 5 ); + const a = new Vector4( x, y, z, w ); + const m = new Matrix4().makeRotationX( Math.PI ); + const expected = new Vector4( 2, - 3, - 4, 5 ); a.applyMatrix4( m ); assert.ok( Math.abs( a.x - expected.x ) <= eps, 'Rotation matrix: check x' ); @@ -310,8 +310,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'clampScalar', ( assert ) => { - var a = new Vector4( - 0.1, 0.01, 0.5, 1.5 ); - var clamped = new Vector4( 0.1, 0.1, 0.5, 1.0 ); + const a = new Vector4( - 0.1, 0.01, 0.5, 1.5 ); + const clamped = new Vector4( 0.1, 0.1, 0.5, 1.0 ); a.clampScalar( 0.1, 1.0 ); assert.ok( Math.abs( a.x - clamped.x ) <= eps, 'Check x' ); @@ -353,7 +353,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'negate', ( assert ) => { - var a = new Vector4( x, y, z, w ); + const a = new Vector4( x, y, z, w ); a.negate(); assert.ok( a.x == - x, 'Passed!' ); @@ -365,14 +365,14 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'dot', ( assert ) => { - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); - var c = new Vector4( 0, 0, 0, 0 ); + const a = new Vector4( x, y, z, w ); + const b = new Vector4( - x, - y, - z, - w ); + const c = new Vector4( 0, 0, 0, 0 ); - var result = a.dot( b ); + let result = a.dot( b ); assert.ok( result == ( - x * x - y * y - z * z - w * w ), 'Passed!' ); - var result = a.dot( c ); + result = a.dot( c ); assert.ok( result == 0, 'Passed!' ); } ); @@ -391,11 +391,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'manhattanLength', ( assert ) => { - var a = new Vector4( x, 0, 0, 0 ); - var b = new Vector4( 0, - y, 0, 0 ); - var c = new Vector4( 0, 0, z, 0 ); - var d = new Vector4( 0, 0, 0, w ); - var e = new Vector4( 0, 0, 0, 0 ); + const a = new Vector4( x, 0, 0, 0 ); + const b = new Vector4( 0, - y, 0, 0 ); + const c = new Vector4( 0, 0, z, 0 ); + const d = new Vector4( 0, 0, 0, w ); + const e = new Vector4( 0, 0, 0, 0 ); assert.ok( a.manhattanLength() == x, 'Positive x' ); assert.ok( b.manhattanLength() == y, 'Negative y' ); @@ -413,10 +413,10 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'normalize', ( assert ) => { - var a = new Vector4( x, 0, 0, 0 ); - var b = new Vector4( 0, - y, 0, 0 ); - var c = new Vector4( 0, 0, z, 0 ); - var d = new Vector4( 0, 0, 0, - w ); + const a = new Vector4( x, 0, 0, 0 ); + const b = new Vector4( 0, - y, 0, 0 ); + const c = new Vector4( 0, 0, z, 0 ); + const d = new Vector4( 0, 0, 0, - w ); a.normalize(); assert.ok( a.length() == 1, 'Passed!' ); @@ -438,13 +438,13 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setLength', ( assert ) => { - var a = new Vector4( x, 0, 0, 0 ); + let a = new Vector4( x, 0, 0, 0 ); assert.ok( a.length() == x, 'Passed!' ); a.setLength( y ); assert.ok( a.length() == y, 'Passed!' ); - var a = new Vector4( 0, 0, 0, 0 ); + a = new Vector4( 0, 0, 0, 0 ); assert.ok( a.length() == 0, 'Passed!' ); a.setLength( y ); assert.ok( a.length() == 0, 'Passed!' ); @@ -467,8 +467,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'equals', ( assert ) => { - var a = new Vector4( x, 0, z, 0 ); - var b = new Vector4( 0, - y, 0, - w ); + const a = new Vector4( x, 0, z, 0 ); + const b = new Vector4( 0, - y, 0, - w ); assert.ok( a.x != b.x, 'Passed!' ); assert.ok( a.y != b.y, 'Passed!' ); @@ -491,8 +491,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromArray', ( assert ) => { - var a = new Vector4(); - var array = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; + const a = new Vector4(); + const array = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; a.fromArray( array ); assert.strictEqual( a.x, 1, 'No offset: check x' ); @@ -510,22 +510,22 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'toArray', ( assert ) => { - var a = new Vector4( x, y, z, w ); + const a = new Vector4( x, y, z, w ); - var array = a.toArray(); + let array = a.toArray(); assert.strictEqual( array[ 0 ], x, 'No array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'No array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'No array, no offset: check z' ); assert.strictEqual( array[ 3 ], w, 'No array, no offset: check w' ); - var array = []; + array = []; a.toArray( array ); assert.strictEqual( array[ 0 ], x, 'With array, no offset: check x' ); assert.strictEqual( array[ 1 ], y, 'With array, no offset: check y' ); assert.strictEqual( array[ 2 ], z, 'With array, no offset: check z' ); assert.strictEqual( array[ 3 ], w, 'With array, no offset: check w' ); - var array = []; + array = []; a.toArray( array, 1 ); assert.strictEqual( array[ 0 ], undefined, 'With array and offset: check [0]' ); assert.strictEqual( array[ 1 ], x, 'With array and offset: check x' ); @@ -537,8 +537,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'fromBufferAttribute', ( assert ) => { - var a = new Vector4(); - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ), 4 ); + const a = new Vector4(); + const attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ), 4 ); a.fromBufferAttribute( attr, 0 ); assert.strictEqual( a.x, 1, 'Offset 0: check x' ); @@ -557,7 +557,7 @@ export default QUnit.module( 'Maths', () => { // TODO (Itee) refactor/split QUnit.test( 'setX,setY,setZ,setW', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); @@ -577,7 +577,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setComponent,getComponent', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.ok( a.x == 0, 'Passed!' ); assert.ok( a.y == 0, 'Passed!' ); assert.ok( a.z == 0, 'Passed!' ); @@ -596,7 +596,7 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setComponent/getComponent exceptions', ( assert ) => { - var a = new Vector4(); + const a = new Vector4(); assert.throws( function () { @@ -621,8 +621,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'setScalar/addScalar/subScalar', ( assert ) => { - var a = new Vector4(); - var s = 3; + const a = new Vector4(); + const s = 3; a.setScalar( s ); assert.strictEqual( a.x, s, 'setScalar: check x' ); @@ -646,8 +646,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'multiplyScalar/divideScalar', ( assert ) => { - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); + const a = new Vector4( x, y, z, w ); + const b = new Vector4( - x, - y, - z, - w ); a.multiplyScalar( - 2 ); assert.ok( a.x == x * - 2, 'Passed!' ); @@ -677,9 +677,9 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'min/max/clamp', ( assert ) => { - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); - var c = new Vector4(); + const a = new Vector4( x, y, z, w ); + const b = new Vector4( - x, - y, - z, - w ); + const c = new Vector4(); c.copy( a ).min( b ); assert.ok( c.x == - x, 'Passed!' ); @@ -704,11 +704,11 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'length/lengthSq', ( assert ) => { - var a = new Vector4( x, 0, 0, 0 ); - var b = new Vector4( 0, - y, 0, 0 ); - var c = new Vector4( 0, 0, z, 0 ); - var d = new Vector4( 0, 0, 0, w ); - var e = new Vector4( 0, 0, 0, 0 ); + const a = new Vector4( x, 0, 0, 0 ); + const b = new Vector4( 0, - y, 0, 0 ); + const c = new Vector4( 0, 0, z, 0 ); + const d = new Vector4( 0, 0, 0, w ); + const e = new Vector4( 0, 0, 0, 0 ); assert.ok( a.length() == x, 'Passed!' ); assert.ok( a.lengthSq() == x * x, 'Passed!' ); @@ -729,8 +729,8 @@ export default QUnit.module( 'Maths', () => { QUnit.test( 'lerp/clone', ( assert ) => { - var a = new Vector4( x, 0, z, 0 ); - var b = new Vector4( 0, - y, 0, - w ); + const a = new Vector4( x, 0, z, 0 ); + const b = new Vector4( 0, - y, 0, - w ); assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), 'Passed!' ); assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), 'Passed!' ); @@ -749,8 +749,8 @@ export default QUnit.module( 'Maths', () => { // OTHERS QUnit.test( 'iterable', ( assert ) => { - var v = new Vector4( 0, 0.3, 0.7, 1 ); - var array = [ ...v ]; + const v = new Vector4( 0, 0.3, 0.7, 1 ); + const array = [ ...v ]; assert.strictEqual( array[ 0 ], 0, 'Vector4 is iterable.' ); assert.strictEqual( array[ 1 ], 0.3, 'Vector4 is iterable.' ); assert.strictEqual( array[ 2 ], 0.7, 'Vector4 is iterable.' ); diff --git a/test/unit/src/math/interpolants/CubicInterpolant.tests.js b/test/unit/src/math/interpolants/CubicInterpolant.tests.js index 8de0db980bd962..6c9b8cfc854fd4 100644 --- a/test/unit/src/math/interpolants/CubicInterpolant.tests.js +++ b/test/unit/src/math/interpolants/CubicInterpolant.tests.js @@ -13,8 +13,7 @@ export default QUnit.module( 'Maths', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new CubicInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); - + const object = new CubicInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); assert.strictEqual( object instanceof Interpolant, true, 'CubicInterpolant extends from Interpolant' @@ -23,9 +22,11 @@ export default QUnit.module( 'Maths', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // parameterPositions, sampleValues, sampleSize, resultBuffer + const object = new CubicInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); + assert.ok( object, 'Can instantiate a CubicInterpolant.' ); } ); diff --git a/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js b/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js index 713e6dcf5a2c2e..cf07aec3f1cb32 100644 --- a/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js +++ b/test/unit/src/math/interpolants/DiscreteInterpolant.tests.js @@ -13,8 +13,7 @@ export default QUnit.module( 'Maths', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new DiscreteInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); - + const object = new DiscreteInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); assert.strictEqual( object instanceof Interpolant, true, 'DiscreteInterpolant extends from Interpolant' @@ -23,9 +22,11 @@ export default QUnit.module( 'Maths', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // parameterPositions, sampleValues, sampleSize, resultBuffer + const object = new DiscreteInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); + assert.ok( object, 'Can instantiate a DiscreteInterpolant.' ); } ); diff --git a/test/unit/src/math/interpolants/LinearInterpolant.tests.js b/test/unit/src/math/interpolants/LinearInterpolant.tests.js index 55562d42365b88..41b91929c45c1d 100644 --- a/test/unit/src/math/interpolants/LinearInterpolant.tests.js +++ b/test/unit/src/math/interpolants/LinearInterpolant.tests.js @@ -13,8 +13,7 @@ export default QUnit.module( 'Maths', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new LinearInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); - + const object = new LinearInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); assert.strictEqual( object instanceof Interpolant, true, 'LinearInterpolant extends from Interpolant' @@ -23,9 +22,11 @@ export default QUnit.module( 'Maths', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // parameterPositions, sampleValues, sampleSize, resultBuffer + const object = new LinearInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); + assert.ok( object, 'Can instantiate a LinearInterpolant.' ); } ); diff --git a/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js b/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js index 5ba48ae58f4c1b..d41f3ad3fc6b2e 100644 --- a/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js +++ b/test/unit/src/math/interpolants/QuaternionLinearInterpolant.tests.js @@ -13,8 +13,7 @@ export default QUnit.module( 'Maths', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new QuaternionLinearInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); - + const object = new QuaternionLinearInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); assert.strictEqual( object instanceof Interpolant, true, 'QuaternionLinearInterpolant extends from Interpolant' @@ -23,9 +22,11 @@ export default QUnit.module( 'Maths', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // parameterPositions, sampleValues, sampleSize, resultBuffer + const object = new QuaternionLinearInterpolant( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); + assert.ok( object, 'Can instantiate a QuaternionLinearInterpolant.' ); } ); diff --git a/test/unit/src/objects/Bone.tests.js b/test/unit/src/objects/Bone.tests.js index e54b96ed39ff62..7059a1e54ddb1d 100644 --- a/test/unit/src/objects/Bone.tests.js +++ b/test/unit/src/objects/Bone.tests.js @@ -1,8 +1,9 @@ /* global QUnit */ -import { Object3D } from '../../../../src/core/Object3D.js'; import { Bone } from '../../../../src/objects/Bone.js'; +import { Object3D } from '../../../../src/core/Object3D.js'; + export default QUnit.module( 'Objects', () => { QUnit.module( 'Bone', () => { @@ -10,16 +11,19 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var bone = new Bone(); - - assert.strictEqual( bone instanceof Object3D, true, 'Bone extends from Object3D' ); + const bone = new Bone(); + assert.strictEqual( + bone instanceof Object3D, true, + 'Bone extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Bone(); + assert.ok( object, 'Can instantiate a Bone.' ); } ); diff --git a/test/unit/src/objects/Group.tests.js b/test/unit/src/objects/Group.tests.js index 6d1803a602a769..a8908e722349b8 100644 --- a/test/unit/src/objects/Group.tests.js +++ b/test/unit/src/objects/Group.tests.js @@ -1,8 +1,9 @@ /* global QUnit */ -import { Object3D } from '../../../../src/core/Object3D.js'; import { Group } from '../../../../src/objects/Group.js'; +import { Object3D } from '../../../../src/core/Object3D.js'; + export default QUnit.module( 'Objects', () => { QUnit.module( 'Group', () => { @@ -10,16 +11,19 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var group = new Group(); - - assert.strictEqual( group instanceof Object3D, true, 'Group extends from Object3D' ); + const group = new Group(); + assert.strictEqual( + group instanceof Object3D, true, + 'Group extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Group(); + assert.ok( object, 'Can instantiate a Group.' ); } ); diff --git a/test/unit/src/objects/InstancedMesh.tests.js b/test/unit/src/objects/InstancedMesh.tests.js index efc30407cffbfe..1eb0987c91e4b6 100644 --- a/test/unit/src/objects/InstancedMesh.tests.js +++ b/test/unit/src/objects/InstancedMesh.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new InstancedMesh(); - - assert.strictEqual( object instanceof Mesh, true, 'InstancedMesh extends from Mesh' ); + const object = new InstancedMesh(); + assert.strictEqual( + object instanceof Mesh, true, + 'InstancedMesh extends from Mesh' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new InstancedMesh(); + assert.ok( object, 'Can instantiate a InstancedMesh.' ); } ); @@ -104,9 +107,12 @@ export default QUnit.module( 'Objects', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new InstancedMesh(); + object.dispose(); } ); diff --git a/test/unit/src/objects/LOD.tests.js b/test/unit/src/objects/LOD.tests.js index a1176d888c6734..9ceda7d2ff2fdb 100644 --- a/test/unit/src/objects/LOD.tests.js +++ b/test/unit/src/objects/LOD.tests.js @@ -11,7 +11,7 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var lod = new LOD(); + const lod = new LOD(); assert.strictEqual( ( lod instanceof Object3D ), true, 'LOD extends from Object3D' ); @@ -30,8 +30,8 @@ export default QUnit.module( 'Objects', () => { QUnit.test( 'levels', ( assert ) => { - var lod = new LOD(); - var levels = lod.levels; + const lod = new LOD(); + const levels = lod.levels; assert.strictEqual( Array.isArray( levels ), true, 'LOD.levels is of type array.' ); assert.strictEqual( levels.length, 0, 'LOD.levels is empty by default.' ); @@ -57,12 +57,12 @@ export default QUnit.module( 'Objects', () => { QUnit.test( 'copy', ( assert ) => { - var lod1 = new LOD(); - var lod2 = new LOD(); + const lod1 = new LOD(); + const lod2 = new LOD(); - var high = new Object3D(); - var mid = new Object3D(); - var low = new Object3D(); + const high = new Object3D(); + const mid = new Object3D(); + const low = new Object3D(); lod1.addLevel( high, 5 ); lod1.addLevel( mid, 25 ); @@ -79,11 +79,11 @@ export default QUnit.module( 'Objects', () => { QUnit.test( 'addLevel', ( assert ) => { - var lod = new LOD(); + const lod = new LOD(); - var high = new Object3D(); - var mid = new Object3D(); - var low = new Object3D(); + const high = new Object3D(); + const mid = new Object3D(); + const low = new Object3D(); lod.addLevel( high, 5, 0.00 ); lod.addLevel( mid, 25, 0.05 ); @@ -104,11 +104,11 @@ export default QUnit.module( 'Objects', () => { QUnit.test( 'getObjectForDistance', ( assert ) => { - var lod = new LOD(); + const lod = new LOD(); - var high = new Object3D(); - var mid = new Object3D(); - var low = new Object3D(); + const high = new Object3D(); + const mid = new Object3D(); + const low = new Object3D(); assert.strictEqual( lod.getObjectForDistance( 5 ), null, 'Returns null if no LOD levels are defined.' ); @@ -130,9 +130,9 @@ export default QUnit.module( 'Objects', () => { QUnit.test( 'raycast', ( assert ) => { - var lod = new LOD(); - var raycaster = new Raycaster(); - var intersections = []; + const lod = new LOD(); + const raycaster = new Raycaster(); + const intersections = []; lod.raycast( raycaster, intersections ); diff --git a/test/unit/src/objects/Line.tests.js b/test/unit/src/objects/Line.tests.js index 6fe2566b9fa9d3..7258948db6748a 100644 --- a/test/unit/src/objects/Line.tests.js +++ b/test/unit/src/objects/Line.tests.js @@ -1,8 +1,9 @@ /* global QUnit */ -import { Object3D } from '../../../../src/core/Object3D.js'; import { Line } from '../../../../src/objects/Line.js'; +import { Object3D } from '../../../../src/core/Object3D.js'; + export default QUnit.module( 'Objects', () => { QUnit.module( 'Line', () => { @@ -10,16 +11,19 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var line = new Line(); - - assert.strictEqual( line instanceof Object3D, true, 'Line extends from Object3D' ); + const line = new Line(); + assert.strictEqual( + line instanceof Object3D, true, + 'Line extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Line(); + assert.ok( object, 'Can instantiate a Line.' ); } ); diff --git a/test/unit/src/objects/LineLoop.tests.js b/test/unit/src/objects/LineLoop.tests.js index 7cb6a01ed83dfe..0060bc4bcac00a 100644 --- a/test/unit/src/objects/LineLoop.tests.js +++ b/test/unit/src/objects/LineLoop.tests.js @@ -11,7 +11,7 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var lineLoop = new LineLoop(); + const lineLoop = new LineLoop(); assert.strictEqual( lineLoop instanceof Object3D, true, 'LineLoop extends from Object3D' ); assert.strictEqual( lineLoop instanceof Line, true, 'LineLoop extends from Line' ); @@ -19,9 +19,10 @@ export default QUnit.module( 'Objects', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new LineLoop(); + assert.ok( object, 'Can instantiate a LineLoop.' ); } ); diff --git a/test/unit/src/objects/LineSegments.tests.js b/test/unit/src/objects/LineSegments.tests.js index 909abefa5c44c1..b1184988788792 100644 --- a/test/unit/src/objects/LineSegments.tests.js +++ b/test/unit/src/objects/LineSegments.tests.js @@ -11,17 +11,17 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var lineSegments = new LineSegments(); - + const lineSegments = new LineSegments(); assert.strictEqual( lineSegments instanceof Object3D, true, 'LineSegments extends from Object3D' ); assert.strictEqual( lineSegments instanceof Line, true, 'LineSegments extends from Line' ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new LineSegments(); + assert.ok( object, 'Can instantiate a LineSegments.' ); } ); diff --git a/test/unit/src/objects/Mesh.tests.js b/test/unit/src/objects/Mesh.tests.js index 044d62145b5a28..17286362256b72 100644 --- a/test/unit/src/objects/Mesh.tests.js +++ b/test/unit/src/objects/Mesh.tests.js @@ -4,9 +4,11 @@ import { Object3D } from '../../../../src/core/Object3D.js'; import { Mesh } from '../../../../src/objects/Mesh.js'; import { Raycaster } from '../../../../src/core/Raycaster.js'; import { PlaneGeometry } from '../../../../src/geometries/PlaneGeometry.js'; +import { BoxGeometry } from '../../../../src/geometries/BoxGeometry.js'; import { MeshBasicMaterial } from '../../../../src/materials/MeshBasicMaterial.js'; import { Vector2 } from '../../../../src/math/Vector2.js'; import { Vector3 } from '../../../../src/math/Vector3.js'; +import { DoubleSide } from '../../../../src/constants.js'; export default QUnit.module( 'Objects', () => { @@ -15,16 +17,19 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var mesh = new Mesh(); - - assert.strictEqual( mesh instanceof Object3D, true, 'Mesh extends from Object3D' ); + const mesh = new Mesh(); + assert.strictEqual( + mesh instanceof Object3D, true, + 'Mesh extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Mesh(); + assert.ok( object, 'Can instantiate a Mesh.' ); } ); @@ -106,6 +111,64 @@ export default QUnit.module( 'Objects', () => { } ); + QUnit.test( 'raycast/range', ( assert ) => { + + const geometry = new BoxGeometry( 1, 1, 1 ); + const material = new MeshBasicMaterial( { side: DoubleSide } ); + const mesh = new Mesh( geometry, material ); + const raycaster = new Raycaster(); + const intersections = []; + + raycaster.ray.origin.set( 0, 0, 0 ); + raycaster.ray.direction.set( 1, 0, 0 ); + raycaster.near = 100; + raycaster.far = 200; + + mesh.matrixWorld.identity(); + mesh.position.setX( 150 ); + mesh.updateMatrixWorld( true ); + intersections.length = 0; + mesh.raycast( raycaster, intersections ); + assert.ok( intersections.length > 0, 'bounding sphere between near and far' ); + + mesh.matrixWorld.identity(); + mesh.position.setX( raycaster.near ); + mesh.updateMatrixWorld( true ); + intersections.length = 0; + mesh.raycast( raycaster, intersections ); + assert.ok( intersections.length > 0, 'bounding sphere across near' ); + + mesh.matrixWorld.identity(); + mesh.position.setX( raycaster.far ); + mesh.updateMatrixWorld( true ); + intersections.length = 0; + mesh.raycast( raycaster, intersections ); + assert.ok( intersections.length > 0, 'bounding sphere across far' ); + + mesh.matrixWorld.identity(); + mesh.position.setX( 150 ); + mesh.scale.setY( 9999 ); + mesh.updateMatrixWorld( true ); + intersections.length = 0; + mesh.raycast( raycaster, intersections ); + assert.ok( intersections.length > 0, 'bounding sphere across near and far' ); + + mesh.matrixWorld.identity(); + mesh.position.setX( - 9999 ); + mesh.updateMatrixWorld( true ); + intersections.length = 0; + mesh.raycast( raycaster, intersections ); + assert.ok( intersections.length === 0, 'bounding sphere behind near' ); + + mesh.matrixWorld.identity(); + mesh.position.setX( 9999 ); + mesh.updateMatrixWorld( true ); + intersections.length = 0; + mesh.raycast( raycaster, intersections ); + assert.ok( intersections.length === 0, 'bounding sphere beyond far' ); + + } ); + } ); } ); diff --git a/test/unit/src/objects/Points.tests.js b/test/unit/src/objects/Points.tests.js index 20c742f1af5c79..e03640239b1412 100644 --- a/test/unit/src/objects/Points.tests.js +++ b/test/unit/src/objects/Points.tests.js @@ -10,16 +10,19 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var points = new Points(); - - assert.strictEqual( points instanceof Object3D, true, 'Points extends from Object3D' ); + const points = new Points(); + assert.strictEqual( + points instanceof Object3D, true, + 'Points extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Points(); + assert.ok( object, 'Can instantiate a Points.' ); } ); diff --git a/test/unit/src/objects/Skeleton.tests.js b/test/unit/src/objects/Skeleton.tests.js index f3a08cfe94fda9..fc39efcf6f4494 100644 --- a/test/unit/src/objects/Skeleton.tests.js +++ b/test/unit/src/objects/Skeleton.tests.js @@ -1,15 +1,16 @@ /* global QUnit */ -// import { Skeleton } from '../../../../src/objects/Skeleton.js'; +import { Skeleton } from '../../../../src/objects/Skeleton.js'; export default QUnit.module( 'Objects', () => { QUnit.module( 'Skeleton', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Skeleton(); + assert.ok( object, 'Can instantiate a Skeleton.' ); } ); @@ -99,9 +100,12 @@ export default QUnit.module( 'Objects', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new Skeleton(); + object.dispose(); } ); diff --git a/test/unit/src/objects/SkinnedMesh.tests.js b/test/unit/src/objects/SkinnedMesh.tests.js index 33ddfe7b0bb8bd..154df94837dba1 100644 --- a/test/unit/src/objects/SkinnedMesh.tests.js +++ b/test/unit/src/objects/SkinnedMesh.tests.js @@ -11,7 +11,7 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var skinnedMesh = new SkinnedMesh(); + const skinnedMesh = new SkinnedMesh(); assert.strictEqual( skinnedMesh instanceof Object3D, true, 'SkinnedMesh extends from Object3D' ); assert.strictEqual( skinnedMesh instanceof Mesh, true, 'SkinnedMesh extends from Mesh' ); @@ -19,9 +19,10 @@ export default QUnit.module( 'Objects', () => { } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new SkinnedMesh(); + assert.ok( object, 'Can instantiate a SkinnedMesh.' ); } ); @@ -99,7 +100,7 @@ export default QUnit.module( 'Objects', () => { } ); - QUnit.todo( 'boneTransform', ( assert ) => { + QUnit.todo( 'applyBoneTransform', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/objects/Sprite.tests.js b/test/unit/src/objects/Sprite.tests.js index 499d8321cd6ded..83cd795a943ba9 100644 --- a/test/unit/src/objects/Sprite.tests.js +++ b/test/unit/src/objects/Sprite.tests.js @@ -10,16 +10,19 @@ export default QUnit.module( 'Objects', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var sprite = new Sprite(); - - assert.strictEqual( sprite instanceof Object3D, true, 'Sprite extends from Object3D' ); + const sprite = new Sprite(); + assert.strictEqual( + sprite instanceof Object3D, true, + 'Sprite extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Sprite(); + assert.ok( object, 'Can instantiate a Sprite.' ); } ); diff --git a/test/unit/src/renderers/WebGL1Renderer.tests.js b/test/unit/src/renderers/WebGL1Renderer.tests.js index 6ae5f12c4e3339..2ff820f592991e 100644 --- a/test/unit/src/renderers/WebGL1Renderer.tests.js +++ b/test/unit/src/renderers/WebGL1Renderer.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Renderers', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new WebGL1Renderer(); - - assert.strictEqual( object instanceof WebGLRenderer, true, 'WebGL1Renderer extends from WebGLRenderer' ); + const object = new WebGL1Renderer(); + assert.strictEqual( + object instanceof WebGLRenderer, true, + 'WebGL1Renderer extends from WebGLRenderer' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const renderer = new WebGL1Renderer(); + assert.ok( renderer, 'Can instantiate a WebGL1Renderer.' ); } ); diff --git a/test/unit/src/renderers/WebGL3DRenderTarget.tests.js b/test/unit/src/renderers/WebGL3DRenderTarget.tests.js index 2f131a2d5bdff0..f0997f88cc6970 100644 --- a/test/unit/src/renderers/WebGL3DRenderTarget.tests.js +++ b/test/unit/src/renderers/WebGL3DRenderTarget.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Renderers', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new WebGL3DRenderTarget(); - - assert.strictEqual( object instanceof WebGLRenderTarget, true, 'WebGL3DRenderTarget extends from WebGLRenderTarget' ); + const object = new WebGL3DRenderTarget(); + assert.strictEqual( + object instanceof WebGLRenderTarget, true, + 'WebGL3DRenderTarget extends from WebGLRenderTarget' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new WebGL3DRenderTarget(); + assert.ok( object, 'Can instantiate a WebGL3DRenderTarget.' ); } ); diff --git a/test/unit/src/renderers/WebGLArrayRenderTarget.tests.js b/test/unit/src/renderers/WebGLArrayRenderTarget.tests.js index 40dd54f30cf1b0..d219dce04aa9e4 100644 --- a/test/unit/src/renderers/WebGLArrayRenderTarget.tests.js +++ b/test/unit/src/renderers/WebGLArrayRenderTarget.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Renderers', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new WebGLArrayRenderTarget(); - - assert.strictEqual( object instanceof WebGLRenderTarget, true, 'WebGLArrayRenderTarget extends from WebGLRenderTarget' ); + const object = new WebGLArrayRenderTarget(); + assert.strictEqual( + object instanceof WebGLRenderTarget, true, + 'WebGLArrayRenderTarget extends from WebGLRenderTarget' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new WebGLArrayRenderTarget(); + assert.ok( object, 'Can instantiate a WebGLArrayRenderTarget.' ); } ); diff --git a/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js b/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js index fa20b264a652c6..2167cf9c931f9f 100644 --- a/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js +++ b/test/unit/src/renderers/WebGLCubeRenderTarget.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Renderers', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new WebGLCubeRenderTarget(); - - assert.strictEqual( object instanceof WebGLRenderTarget, true, 'WebGLCubeRenderTarget extends from WebGLRenderTarget' ); + const object = new WebGLCubeRenderTarget(); + assert.strictEqual( + object instanceof WebGLRenderTarget, true, + 'WebGLCubeRenderTarget extends from WebGLRenderTarget' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new WebGLCubeRenderTarget(); + assert.ok( object, 'Can instantiate a WebGLCubeRenderTarget.' ); } ); diff --git a/test/unit/src/renderers/WebGLMultipleRenderTargets.tests.js b/test/unit/src/renderers/WebGLMultipleRenderTargets.tests.js index 682588ea2047f2..367d75888424da 100644 --- a/test/unit/src/renderers/WebGLMultipleRenderTargets.tests.js +++ b/test/unit/src/renderers/WebGLMultipleRenderTargets.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Renderers', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new WebGLMultipleRenderTargets(); - - assert.strictEqual( object instanceof WebGLRenderTarget, true, 'WebGLMultipleRenderTargets extends from WebGLRenderTarget' ); + const object = new WebGLMultipleRenderTargets(); + assert.strictEqual( + object instanceof WebGLRenderTarget, true, + 'WebGLMultipleRenderTargets extends from WebGLRenderTarget' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new WebGLMultipleRenderTargets(); + assert.ok( object, 'Can instantiate a WebGLMultipleRenderTargets.' ); } ); diff --git a/test/unit/src/renderers/WebGLRenderTarget.tests.js b/test/unit/src/renderers/WebGLRenderTarget.tests.js index b196a97358a7a5..d6055a9f5b1172 100644 --- a/test/unit/src/renderers/WebGLRenderTarget.tests.js +++ b/test/unit/src/renderers/WebGLRenderTarget.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Renderers', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new WebGLRenderTarget(); - - assert.strictEqual( object instanceof EventDispatcher, true, 'WebGLRenderTarget extends from EventDispatcher' ); + const object = new WebGLRenderTarget(); + assert.strictEqual( + object instanceof EventDispatcher, true, + 'WebGLRenderTarget extends from EventDispatcher' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new WebGLRenderTarget(); + assert.ok( object, 'Can instantiate a WebGLRenderTarget.' ); } ); @@ -116,9 +119,12 @@ export default QUnit.module( 'Renderers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new WebGLRenderTarget(); + object.dispose(); } ); diff --git a/test/unit/src/renderers/WebGLRenderer.tests.js b/test/unit/src/renderers/WebGLRenderer.tests.js index 83266ca24cb090..0947956c67fff2 100644 --- a/test/unit/src/renderers/WebGLRenderer.tests.js +++ b/test/unit/src/renderers/WebGLRenderer.tests.js @@ -9,7 +9,8 @@ export default QUnit.module( 'Renderers', () => { // INSTANCING QUnit.test( 'Instancing', ( assert ) => { - assert.ok( new WebGLRenderer(), 'Can instantiate a renderer.' ); + const renderer = new WebGLRenderer(); + assert.ok( renderer, 'Can instantiate a WebGLRenderer.' ); } ); @@ -68,7 +69,7 @@ export default QUnit.module( 'Renderers', () => { } ); - QUnit.todo( 'outputEncoding', ( assert ) => { + QUnit.todo( 'outputColorSpace', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -261,9 +262,12 @@ export default QUnit.module( 'Renderers', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new WebGLRenderer(); + object.dispose(); } ); diff --git a/test/unit/src/renderers/shaders/UniformsUtils.tests.js b/test/unit/src/renderers/shaders/UniformsUtils.tests.js index eb0acd4cf0b1c4..81d2980f09756b 100644 --- a/test/unit/src/renderers/shaders/UniformsUtils.tests.js +++ b/test/unit/src/renderers/shaders/UniformsUtils.tests.js @@ -1,6 +1,16 @@ /* global QUnit */ import { UniformsUtils } from '../../../../../src/renderers/shaders/UniformsUtils.js'; +import { Color } from '../../../../../src/math/Color.js'; +import { Vector2 } from '../../../../../src/math/Vector2.js'; +import { Vector3 } from '../../../../../src/math/Vector3.js'; +import { Vector4 } from '../../../../../src/math/Vector4.js'; +import { Matrix3 } from '../../../../../src/math/Matrix3.js'; +import { Matrix4 } from '../../../../../src/math/Matrix4.js'; +import { Quaternion } from '../../../../../src/math/Quaternion.js'; +import { Texture } from '../../../../../src/textures/Texture.js'; +import { CubeReflectionMapping, UVMapping } from '../../../../../src/constants.js'; +import { CONSOLE_LEVEL } from '../../../utils/console-wrapper.js'; export default QUnit.module( 'Renderers', () => { @@ -29,12 +39,110 @@ export default QUnit.module( 'Renderers', () => { } ); // PUBLIC - QUnit.todo( 'cloneUniforms', ( assert ) => { + QUnit.test( 'cloneUniforms copies values', ( assert ) => { + + const uniforms = { + floatValue: { value: 1.23 }, + intValue: { value: 1 }, + boolValue: { value: true }, + colorValue: { value: new Color(0xFF00FF) }, + vector2Value: { value: new Vector2(1, 2) }, + vector3Value: { value: new Vector3(1, 2, 3) }, + vector4Value: { value: new Vector4(1, 2, 3, 4) }, + matrix3Value: { value: new Matrix3() }, + matrix4Value: { value: new Matrix4() }, + quatValue: { value: new Quaternion(1, 2, 3, 4) }, + arrayValue: { value: [1, 2, 3, 4] }, + textureValue: { value: new Texture(null, CubeReflectionMapping) }, + }; + + const uniformClones = UniformsUtils.clone(uniforms); + + assert.ok( uniforms.floatValue.value === uniformClones.floatValue.value ); + assert.ok( uniforms.intValue.value === uniformClones.intValue.value ); + assert.ok( uniforms.boolValue.value === uniformClones.boolValue.value ); + assert.ok( uniforms.colorValue.value.equals(uniformClones.colorValue.value) ); + assert.ok( uniforms.vector2Value.value.equals(uniformClones.vector2Value.value) ); + assert.ok( uniforms.vector3Value.value.equals(uniformClones.vector3Value.value) ); + assert.ok( uniforms.vector4Value.value.equals(uniformClones.vector4Value.value) ); + assert.ok( uniforms.matrix3Value.value.equals(uniformClones.matrix3Value.value) ); + assert.ok( uniforms.matrix4Value.value.equals(uniformClones.matrix4Value.value) ); + assert.ok( uniforms.quatValue.value.equals(uniformClones.quatValue.value) ); + assert.ok( uniforms.textureValue.value.source.uuid === uniformClones.textureValue.value.source.uuid ); + assert.ok( uniforms.textureValue.value.mapping === uniformClones.textureValue.value.mapping ); + for ( let i = 0; i < uniforms.arrayValue.value.length; ++i ) { + assert.ok( uniforms.arrayValue.value[i] === uniformClones.arrayValue.value[i] ); + } + } ); - assert.ok( false, 'everything\'s gonna be alright' ); + QUnit.test( 'cloneUniforms clones properties', ( assert ) => { + + const uniforms = { + floatValue: { value: 1.23 }, + intValue: { value: 1 }, + boolValue: { value: true }, + colorValue: { value: new Color(0xFF00FF) }, + vector2Value: { value: new Vector2(1, 2) }, + vector3Value: { value: new Vector3(1, 2, 3) }, + vector4Value: { value: new Vector4(1, 2, 3, 4) }, + matrix3Value: { value: new Matrix3() }, + matrix4Value: { value: new Matrix4() }, + quatValue: { value: new Quaternion(1, 2, 3, 4) }, + arrayValue: { value: [1, 2, 3, 4] }, + textureValue: { value: new Texture(null, CubeReflectionMapping) }, + }; + + const uniformClones = UniformsUtils.clone(uniforms); + + // Modify the originals + uniforms.floatValue.value = 123.0; + uniforms.intValue.value = 123; + uniforms.boolValue.value = false; + uniforms.colorValue.value.r = 123.0; + uniforms.vector2Value.value.x = 123.0; + uniforms.vector3Value.value.x = 123.0; + uniforms.vector4Value.value.x = 123.0; + uniforms.matrix3Value.value.elements[0] = 123.0; + uniforms.matrix4Value.value.elements[0] = 123.0; + uniforms.quatValue.value.x = 123.0; + uniforms.arrayValue.value[0] = 123.0; + uniforms.textureValue.value.mapping = UVMapping; + + assert.ok( uniforms.floatValue.value !== uniformClones.floatValue.value ); + assert.ok( uniforms.intValue.value !== uniformClones.intValue.value ); + assert.ok( uniforms.boolValue.value !== uniformClones.boolValue.value ); + assert.ok( !uniforms.colorValue.value.equals(uniformClones.colorValue.value) ); + assert.ok( !uniforms.vector2Value.value.equals(uniformClones.vector2Value.value) ); + assert.ok( !uniforms.vector3Value.value.equals(uniformClones.vector3Value.value) ); + assert.ok( !uniforms.vector4Value.value.equals(uniformClones.vector4Value.value) ); + assert.ok( !uniforms.matrix3Value.value.equals(uniformClones.matrix3Value.value) ); + assert.ok( !uniforms.matrix4Value.value.equals(uniformClones.matrix4Value.value) ); + assert.ok( !uniforms.quatValue.value.equals(uniformClones.quatValue.value) ); + assert.ok( uniforms.textureValue.value.mapping !== uniformClones.textureValue.value.mapping ); + assert.ok( uniforms.arrayValue.value[0] !== uniformClones.arrayValue.value[0] ); + + // Texture source remains same + assert.ok( uniforms.textureValue.value.source.uuid === uniformClones.textureValue.value.source.uuid ); + + } ); + + QUnit.test( 'cloneUniforms skips render target textures', ( assert ) => { + + const uniforms = { + textureValue: { value: new Texture(null, CubeReflectionMapping) }, + }; + + uniforms.textureValue.value.isRenderTargetTexture = true; + + console.level = CONSOLE_LEVEL.OFF; + const uniformClones = UniformsUtils.clone(uniforms); + console.level = CONSOLE_LEVEL.DEFAULT; + + assert.ok( uniformClones.textureValue.value === null ); } ); + QUnit.todo( 'mergeUniforms', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); diff --git a/test/unit/src/renderers/webgl/WebGLExtensions.tests.js b/test/unit/src/renderers/webgl/WebGLExtensions.tests.js index cdd03f945365a8..a89abddaaeb5f2 100644 --- a/test/unit/src/renderers/webgl/WebGLExtensions.tests.js +++ b/test/unit/src/renderers/webgl/WebGLExtensions.tests.js @@ -2,6 +2,8 @@ import { WebGLExtensions } from '../../../../../src/renderers/webgl/WebGLExtensions.js'; +import { CONSOLE_LEVEL } from '../../../utils/console-wrapper.js'; + const WebglContextMock = function ( supportedExtensions ) { this.supportedExtensions = supportedExtensions || []; @@ -65,7 +67,13 @@ export default QUnit.module( 'Renderers', () => { assert.ok( extensions.get( 'Extension1' ) ); assert.ok( extensions.get( 'Extension2' ) ); assert.ok( extensions.get( 'Extension1' ) ); + + // surpress the following console message when testing + // THREE.WebGLRenderer: NonExistingExtension extension not supported. + + console.level = CONSOLE_LEVEL.OFF; assert.notOk( extensions.get( 'NonExistingExtension' ) ); + console.level = CONSOLE_LEVEL.DEFAULT; } ); @@ -75,8 +83,15 @@ export default QUnit.module( 'Renderers', () => { const extensions = new WebGLExtensions( gl ); assert.ok( extensions.get( 'WEBGL_depth_texture' ) ); assert.ok( extensions.get( 'WEBKIT_WEBGL_depth_texture' ) ); + + // surpress the following console message when testing + // THREE.WebGLRenderer: EXT_texture_filter_anisotropic extension not supported. + // THREE.WebGLRenderer: NonExistingExtension extension not supported. + + console.level = CONSOLE_LEVEL.OFF; assert.notOk( extensions.get( 'EXT_texture_filter_anisotropic' ) ); assert.notOk( extensions.get( 'NonExistingExtension' ) ); + console.level = CONSOLE_LEVEL.DEFAULT; } ); diff --git a/test/unit/src/renderers/webgl/WebGLRenderLists.tests.js b/test/unit/src/renderers/webgl/WebGLRenderLists.tests.js index c0ed83449e4962..0b5b95e3f74365 100644 --- a/test/unit/src/renderers/webgl/WebGLRenderLists.tests.js +++ b/test/unit/src/renderers/webgl/WebGLRenderLists.tests.js @@ -9,31 +9,29 @@ export default QUnit.module( 'Renderers', () => { QUnit.module( 'WebGLRenderLists', () => { - // PUBLIC STUFF + // PUBLIC QUnit.test( 'get', ( assert ) => { - var renderLists = new WebGLRenderLists(); - var sceneA = new Scene(); - var sceneB = new Scene(); + const renderLists = new WebGLRenderLists(); + const sceneA = new Scene(); + const sceneB = new Scene(); - var listA = renderLists.get( sceneA ); - var listB = renderLists.get( sceneB ); + const listA = renderLists.get( sceneA ); + const listB = renderLists.get( sceneB ); assert.propEqual( listA, new WebGLRenderList(), 'listA is type of WebGLRenderList.' ); assert.propEqual( listB, new WebGLRenderList(), 'listB is type of WebGLRenderList.' ); assert.ok( listA !== listB, 'Render lists are different.' ); - } ); } ); - QUnit.module( 'WebGLRenderList', () => { QUnit.test( 'init', ( assert ) => { - var list = new WebGLRenderList(); + const list = new WebGLRenderList(); assert.ok( list.transparent.length === 0, 'Transparent list defaults to length 0.' ); assert.ok( list.opaque.length === 0, 'Opaque list defaults to length 0.' ); @@ -53,22 +51,22 @@ export default QUnit.module( 'Renderers', () => { QUnit.test( 'push', ( assert ) => { - var list = new WebGLRenderList(); - var objA = { id: 'A', renderOrder: 0 }; - var matA = { transparent: true }; - var geoA = {}; + const list = new WebGLRenderList(); + const objA = { id: 'A', renderOrder: 0 }; + const matA = { transparent: true }; + const geoA = {}; - var objB = { id: 'B', renderOrder: 0 }; - var matB = { transparent: true }; - var geoB = {}; + const objB = { id: 'B', renderOrder: 0 }; + const matB = { transparent: true }; + const geoB = {}; - var objC = { id: 'C', renderOrder: 0 }; - var matC = { transparent: false }; - var geoC = {}; + const objC = { id: 'C', renderOrder: 0 }; + const matC = { transparent: false }; + const geoC = {}; - var objD = { id: 'D', renderOrder: 0 }; - var matD = { transparent: false }; - var geoD = {}; + const objD = { id: 'D', renderOrder: 0 }; + const matD = { transparent: false }; + const geoD = {}; list.push( objA, geoA, matA, 0, 0.5, {} ); assert.ok( list.transparent.length === 1, 'Transparent list is length 1 after adding transparent item.' ); @@ -146,22 +144,22 @@ export default QUnit.module( 'Renderers', () => { QUnit.test( 'unshift', ( assert ) => { - var list = new WebGLRenderList(); - var objA = { id: 'A', renderOrder: 0 }; - var matA = { transparent: true }; - var geoA = {}; + const list = new WebGLRenderList(); + const objA = { id: 'A', renderOrder: 0 }; + const matA = { transparent: true }; + const geoA = {}; - var objB = { id: 'B', renderOrder: 0 }; - var matB = { transparent: true }; - var geoB = {}; + const objB = { id: 'B', renderOrder: 0 }; + const matB = { transparent: true }; + const geoB = {}; - var objC = { id: 'C', renderOrder: 0 }; - var matC = { transparent: false }; - var geoC = {}; + const objC = { id: 'C', renderOrder: 0 }; + const matC = { transparent: false }; + const geoC = {}; - var objD = { id: 'D', renderOrder: 0 }; - var matD = { transparent: false }; - var geoD = {}; + const objD = { id: 'D', renderOrder: 0 }; + const matD = { transparent: false }; + const geoD = {}; list.unshift( objA, geoA, matA, 0, 0.5, {} ); @@ -240,8 +238,8 @@ export default QUnit.module( 'Renderers', () => { QUnit.test( 'sort', ( assert ) => { - var list = new WebGLRenderList(); - var items = [ { id: 4 }, { id: 5 }, { id: 2 }, { id: 3 } ]; + const list = new WebGLRenderList(); + const items = [ { id: 4 }, { id: 5 }, { id: 2 }, { id: 3 } ]; items.forEach( item => { diff --git a/test/unit/src/scenes/Fog.tests.js b/test/unit/src/scenes/Fog.tests.js index acb5895874eebc..1540f82ecaf89c 100644 --- a/test/unit/src/scenes/Fog.tests.js +++ b/test/unit/src/scenes/Fog.tests.js @@ -7,9 +7,21 @@ export default QUnit.module( 'Scenes', () => { QUnit.module( 'Fog', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // Fog( color, near = 1, far = 1000 ) + + // no params + const object = new Fog(); + assert.ok( object, 'Can instantiate a Fog.' ); + + // color + const object_color = new Fog( 0xffffff ); + assert.ok( object_color, 'Can instantiate a Fog with color.' ); + + // color, near, far + const object_all = new Fog( 0xffffff, 0.015, 100 ); + assert.ok( object_all, 'Can instantiate a Fog with color, near, far.' ); } ); diff --git a/test/unit/src/scenes/FogExp2.tests.js b/test/unit/src/scenes/FogExp2.tests.js index 9981fba692ef56..0caf0de7d0e703 100644 --- a/test/unit/src/scenes/FogExp2.tests.js +++ b/test/unit/src/scenes/FogExp2.tests.js @@ -7,9 +7,21 @@ export default QUnit.module( 'Scenes', () => { QUnit.module( 'FoxExp2', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // FoxExp2( color, density = 0.00025 ) + + // no params + const object = new FogExp2(); + assert.ok( object, 'Can instantiate a FogExp2.' ); + + // color + const object_color = new FogExp2( 0xffffff ); + assert.ok( object_color, 'Can instantiate a FogExp2 with color.' ); + + // color, density + const object_all = new FogExp2( 0xffffff, 0.00030 ); + assert.ok( object_all, 'Can instantiate a FogExp2 with color, density.' ); } ); diff --git a/test/unit/src/scenes/Scene.tests.js b/test/unit/src/scenes/Scene.tests.js index 0a091f2b6eb984..0eee4361ccd7c0 100644 --- a/test/unit/src/scenes/Scene.tests.js +++ b/test/unit/src/scenes/Scene.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Scenes', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new Scene(); - - assert.strictEqual( object instanceof Object3D, true, 'Scene extends from Object3D' ); + const object = new Scene(); + assert.strictEqual( + object instanceof Object3D, true, + 'Scene extends from Object3D' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Scene(); + assert.ok( object, 'Can instantiate a Scene.' ); } ); diff --git a/test/unit/src/textures/CanvasTexture.tests.js b/test/unit/src/textures/CanvasTexture.tests.js index 70e176e24bbdb0..a7802062391382 100644 --- a/test/unit/src/textures/CanvasTexture.tests.js +++ b/test/unit/src/textures/CanvasTexture.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new CanvasTexture(); - - assert.strictEqual( object instanceof Texture, true, 'CanvasTexture extends from Texture' ); + const object = new CanvasTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'CanvasTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CanvasTexture(); + assert.ok( object, 'Can instantiate a CanvasTexture.' ); } ); diff --git a/test/unit/src/textures/CompressedArrayTexture.tests.js b/test/unit/src/textures/CompressedArrayTexture.tests.js index 2968a2b562bbf2..2c632118c14167 100644 --- a/test/unit/src/textures/CompressedArrayTexture.tests.js +++ b/test/unit/src/textures/CompressedArrayTexture.tests.js @@ -2,7 +2,7 @@ import { CompressedArrayTexture } from '../../../../src/textures/CompressedArrayTexture.js'; -import { Texture } from '../../../../src/textures/Texture.js'; +import { CompressedTexture } from '../../../../src/textures/CompressedTexture.js'; export default QUnit.module( 'Textures', () => { @@ -11,22 +11,26 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new CompressedArrayTexture(); - - assert.strictEqual( object instanceof Texture, true, 'CompressedArrayTexture extends from Texture' ); + const object = new CompressedArrayTexture(); + assert.strictEqual( + object instanceof CompressedTexture, true, + 'CompressedArrayTexture extends from CompressedTexture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CompressedArrayTexture(); + assert.ok( object, 'Can instantiate a CompressedArrayTexture.' ); } ); // PROPERTIES QUnit.todo( 'image.depth', ( assert ) => { + // { width: width, height: height, depth: depth } assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/CompressedTexture.tests.js b/test/unit/src/textures/CompressedTexture.tests.js index 3f2c942e679d43..ae12c0e44436fb 100644 --- a/test/unit/src/textures/CompressedTexture.tests.js +++ b/test/unit/src/textures/CompressedTexture.tests.js @@ -11,22 +11,26 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new CompressedTexture(); - - assert.strictEqual( object instanceof Texture, true, 'CompressedTexture extends from Texture' ); + const object = new CompressedTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'CompressedTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CompressedTexture(); + assert.ok( object, 'Can instantiate a CompressedTexture.' ); } ); // PROPERTIES QUnit.todo( 'image', ( assert ) => { + // { width: width, height: height } assert.ok( false, 'everything\'s gonna be alright' ); } ); diff --git a/test/unit/src/textures/CubeTexture.tests.js b/test/unit/src/textures/CubeTexture.tests.js index dc50acb5b22dee..b7f89cf60f458a 100644 --- a/test/unit/src/textures/CubeTexture.tests.js +++ b/test/unit/src/textures/CubeTexture.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new CubeTexture(); - - assert.strictEqual( object instanceof Texture, true, 'CubeTexture extends from Texture' ); + const object = new CubeTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'CubeTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new CubeTexture(); + assert.ok( object, 'Can instantiate a CubeTexture.' ); } ); diff --git a/test/unit/src/textures/Data3DTexture.tests.js b/test/unit/src/textures/Data3DTexture.tests.js index 2439980102a196..a60f6387a5f0e9 100644 --- a/test/unit/src/textures/Data3DTexture.tests.js +++ b/test/unit/src/textures/Data3DTexture.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new Data3DTexture(); - - assert.strictEqual( object instanceof Texture, true, 'Data3DTexture extends from Texture' ); + const object = new Data3DTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'Data3DTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Data3DTexture(); + assert.ok( object, 'Can instantiate a Data3DTexture.' ); } ); diff --git a/test/unit/src/textures/DataArrayTexture.tests.js b/test/unit/src/textures/DataArrayTexture.tests.js index abe0aea5b4a3ea..6d7802f23982b0 100644 --- a/test/unit/src/textures/DataArrayTexture.tests.js +++ b/test/unit/src/textures/DataArrayTexture.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new DataArrayTexture(); - - assert.strictEqual( object instanceof Texture, true, 'DataArrayTexture extends from Texture' ); + const object = new DataArrayTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'DataArrayTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new DataArrayTexture(); + assert.ok( object, 'Can instantiate a DataArrayTexture.' ); } ); diff --git a/test/unit/src/textures/DataTexture.tests.js b/test/unit/src/textures/DataTexture.tests.js index ec4c2ed2df3ca1..424d0b1427e675 100644 --- a/test/unit/src/textures/DataTexture.tests.js +++ b/test/unit/src/textures/DataTexture.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new DataTexture(); - - assert.strictEqual( object instanceof Texture, true, 'DataTexture extends from Texture' ); + const object = new DataTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'DataTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new DataTexture(); + assert.ok( object, 'Can instantiate a DataTexture.' ); } ); diff --git a/test/unit/src/textures/DepthTexture.tests.js b/test/unit/src/textures/DepthTexture.tests.js index f23444b74b682e..9b91a1ae697dbf 100644 --- a/test/unit/src/textures/DepthTexture.tests.js +++ b/test/unit/src/textures/DepthTexture.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new DepthTexture(); - - assert.strictEqual( object instanceof Texture, true, 'DepthTexture extends from Texture' ); + const object = new DepthTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'DepthTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new DepthTexture(); + assert.ok( object, 'Can instantiate a DepthTexture.' ); } ); diff --git a/test/unit/src/textures/FramebufferTexture.tests.js b/test/unit/src/textures/FramebufferTexture.tests.js index ce8766670d38fa..af5fd587db6b7a 100644 --- a/test/unit/src/textures/FramebufferTexture.tests.js +++ b/test/unit/src/textures/FramebufferTexture.tests.js @@ -11,16 +11,19 @@ export default QUnit.module( 'Textures', () => { // INHERITANCE QUnit.test( 'Extending', ( assert ) => { - var object = new FramebufferTexture(); - - assert.strictEqual( object instanceof Texture, true, 'FramebufferTexture extends from Texture' ); + const object = new FramebufferTexture(); + assert.strictEqual( + object instanceof Texture, true, + 'FramebufferTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new FramebufferTexture(); + assert.ok( object, 'Can instantiate a FramebufferTexture.' ); } ); diff --git a/test/unit/src/textures/Source.tests.js b/test/unit/src/textures/Source.tests.js index ac719917d740e8..5d8a8df8258898 100644 --- a/test/unit/src/textures/Source.tests.js +++ b/test/unit/src/textures/Source.tests.js @@ -7,9 +7,10 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'Source', () => { // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const object = new Source(); + assert.ok( object, 'Can instantiate a Source.' ); } ); diff --git a/test/unit/src/textures/Texture.tests.js b/test/unit/src/textures/Texture.tests.js index 401a4a5413776a..0e8987aa642c16 100644 --- a/test/unit/src/textures/Texture.tests.js +++ b/test/unit/src/textures/Texture.tests.js @@ -9,18 +9,22 @@ export default QUnit.module( 'Textures', () => { QUnit.module( 'Texture', () => { // INHERITANCE - QUnit.test( 'Instancing', ( assert ) => { - - var object = new Texture(); + QUnit.test( 'Extending', ( assert ) => { - assert.strictEqual( object instanceof EventDispatcher, true, 'Texture extends from EventDispatcher' ); + const object = new Texture(); + assert.strictEqual( + object instanceof EventDispatcher, true, + 'Texture extends from EventDispatcher' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + // no params + const object = new Texture(); + assert.ok( object, 'Can instantiate a Texture.' ); } ); @@ -175,7 +179,7 @@ export default QUnit.module( 'Textures', () => { } ); - QUnit.todo( 'encoding', ( assert ) => { + QUnit.todo( 'colorSpace', ( assert ) => { assert.ok( false, 'everything\'s gonna be alright' ); @@ -240,9 +244,12 @@ export default QUnit.module( 'Textures', () => { } ); - QUnit.todo( 'dispose', ( assert ) => { + QUnit.test( 'dispose', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + assert.expect( 0 ); + + const object = new Texture(); + object.dispose(); } ); diff --git a/test/unit/src/textures/VideoTexture.tests.js b/test/unit/src/textures/VideoTexture.tests.js index ac73886ab134c0..04e2d29d622a00 100644 --- a/test/unit/src/textures/VideoTexture.tests.js +++ b/test/unit/src/textures/VideoTexture.tests.js @@ -12,17 +12,20 @@ export default QUnit.module( 'Textures', () => { QUnit.test( 'Extending', ( assert ) => { const videoDocumentElement = {}; - const object = new VideoTexture( videoDocumentElement ); - - assert.strictEqual( object instanceof Texture, true, 'VideoTexture extends from Texture' ); + assert.strictEqual( + object instanceof Texture, true, + 'VideoTexture extends from Texture' + ); } ); // INSTANCING - QUnit.todo( 'Instancing', ( assert ) => { + QUnit.test( 'Instancing', ( assert ) => { - assert.ok( false, 'everything\'s gonna be alright' ); + const videoDocumentElement = {}; + const object = new VideoTexture( videoDocumentElement ); + assert.ok( object, 'Can instantiate a VideoTexture.' ); } ); @@ -49,9 +52,7 @@ export default QUnit.module( 'Textures', () => { QUnit.test( 'isVideoTexture', ( assert ) => { const videoDocumentElement = {}; - const object = new VideoTexture( videoDocumentElement ); - assert.ok( object.isVideoTexture, 'VideoTexture.isVideoTexture should be true' diff --git a/test/unit/three.source.unit.js b/test/unit/three.source.unit.js index 2e36c1ebfaabe6..d70a237838cc69 100644 --- a/test/unit/three.source.unit.js +++ b/test/unit/three.source.unit.js @@ -47,6 +47,7 @@ import './src/core/BufferAttribute.tests.js'; import './src/core/BufferGeometry.tests.js'; import './src/core/Clock.tests.js'; import './src/core/EventDispatcher.tests.js'; +import './src/core/GLBufferAttribute.tests.js'; import './src/core/InstancedBufferAttribute.tests.js'; import './src/core/InstancedBufferGeometry.tests.js'; import './src/core/InstancedInterleavedBuffer.tests.js'; @@ -56,6 +57,7 @@ import './src/core/Layers.tests.js'; import './src/core/Object3D.tests.js'; import './src/core/Raycaster.tests.js'; import './src/core/Uniform.tests.js'; +import './src/core/UniformsGroup.tests.js'; //src/extras diff --git a/test/unit/utils/SmartComparer.js b/test/unit/utils/SmartComparer.js index e21abee26a9bf5..8c84bebe76ee80 100644 --- a/test/unit/utils/SmartComparer.js +++ b/test/unit/utils/SmartComparer.js @@ -8,7 +8,7 @@ function SmartComparer() { 'use strict'; // Diagnostic message, when comparison fails. - var message; + let message; return { @@ -22,7 +22,6 @@ function SmartComparer() { }; - // val1 - first value to compare (typically the actual value) // val2 - other value to compare (typically the expected value) function areEqual( val1, val2 ) { @@ -49,7 +48,7 @@ function SmartComparer() { if ( isFunction( val1 ) && isFunction( val2 ) ) return true; // Array comparison. - var arrCmp = compareArrays( val1, val2 ); + const arrCmp = compareArrays( val1, val2 ); if ( arrCmp !== undefined ) return arrCmp; // Has custom equality comparer. @@ -62,7 +61,7 @@ function SmartComparer() { } // Object comparison. - var objCmp = compareObjects( val1, val2 ); + const objCmp = compareObjects( val1, val2 ); if ( objCmp !== undefined ) return objCmp; // if (JSON.stringify( val1 ) == JSON.stringify( val2 ) ) return true; @@ -77,7 +76,7 @@ function SmartComparer() { // The use of `Object#toString` avoids issues with the `typeof` operator // in Safari 8 which returns 'object' for typed array constructors, and // PhantomJS 1.9 which returns 'function' for `NodeList` instances. - var tag = isObject( value ) ? Object.prototype.toString.call( value ) : ''; + const tag = isObject( value ) ? Object.prototype.toString.call( value ) : ''; return tag == '[object Function]' || tag == '[object GeneratorFunction]'; @@ -87,7 +86,7 @@ function SmartComparer() { // Avoid a V8 JIT bug in Chrome 19-20. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. - var type = typeof value; + const type = typeof value; return !! value && ( type == 'object' || type == 'function' ); @@ -95,8 +94,8 @@ function SmartComparer() { function compareArrays( val1, val2 ) { - var isArr1 = Array.isArray( val1 ); - var isArr2 = Array.isArray( val2 ); + const isArr1 = Array.isArray( val1 ); + const isArr2 = Array.isArray( val2 ); // Compare type. if ( isArr1 !== isArr2 ) return makeFail( 'Values are not both arrays' ); @@ -105,14 +104,14 @@ function SmartComparer() { if ( ! isArr1 ) return undefined; // Compare length. - var N1 = val1.length; - var N2 = val2.length; + const N1 = val1.length; + const N2 = val2.length; if ( N1 !== val2.length ) return makeFail( 'Array length differs', N1, N2 ); // Compare content at each index. - for ( var i = 0; i < N1; i ++ ) { + for ( let i = 0; i < N1; i ++ ) { - var cmp = areEqual( val1[ i ], val2[ i ] ); + const cmp = areEqual( val1[ i ], val2[ i ] ); if ( ! cmp ) return addContext( 'array index "' + i + '"' ); } @@ -122,11 +121,10 @@ function SmartComparer() { } - function compareObjects( val1, val2 ) { - var isObj1 = isObject( val1 ); - var isObj2 = isObject( val2 ); + const isObj1 = isObject( val1 ); + const isObj2 = isObject( val2 ); // Compare type. if ( isObj1 !== isObj2 ) return makeFail( 'Values are not both objects' ); @@ -135,10 +133,10 @@ function SmartComparer() { if ( ! isObj1 ) return undefined; // Compare keys. - var keys1 = Object.keys( val1 ); - var keys2 = Object.keys( val2 ); + const keys1 = Object.keys( val1 ); + const keys2 = Object.keys( val2 ); - for ( var i = 0, l = keys1.length; i < l; i ++ ) { + for ( let i = 0, l = keys1.length; i < l; i ++ ) { if ( keys2.indexOf( keys1[ i ] ) < 0 ) { @@ -148,7 +146,7 @@ function SmartComparer() { } - for ( var i = 0, l = keys2.length; i < l; i ++ ) { + for ( let i = 0, l = keys2.length; i < l; i ++ ) { if ( keys1.indexOf( keys2[ i ] ) < 0 ) { @@ -159,11 +157,11 @@ function SmartComparer() { } // Keys are the same. For each key, compare content until a difference is found. - var hadDifference = false; + let hadDifference = false; - for ( var i = 0, l = keys1.length; i < l; i ++ ) { + for ( let i = 0, l = keys1.length; i < l; i ++ ) { - var key = keys1[ i ]; + const key = keys1[ i ]; if ( key === 'uuid' || key === 'id' ) { @@ -171,11 +169,11 @@ function SmartComparer() { } - var prop1 = val1[ key ]; - var prop2 = val2[ key ]; + const prop1 = val1[ key ]; + const prop2 = val2[ key ]; // Compare property content. - var eq = areEqual( prop1, prop2 ); + const eq = areEqual( prop1, prop2 ); // In case of failure, an message should already be set. // Add context to low level message. @@ -192,7 +190,6 @@ function SmartComparer() { } - function makeFail( msg, val1, val2 ) { message = msg; diff --git a/test/unit/utils/qunit-utils.js b/test/unit/utils/qunit-utils.js index 30680254372339..695db27fb5b031 100644 --- a/test/unit/utils/qunit-utils.js +++ b/test/unit/utils/qunit-utils.js @@ -121,7 +121,7 @@ function getDifferingProp( geometryA, geometryB ) { // Compare json file with its source geometry. function checkGeometryJsonWriting( geom, json ) { - QUnit.assert.equal( json.metadata.version, '4.5', 'check metadata version' ); + QUnit.assert.equal( json.metadata.version, '4.6', 'check metadata version' ); QUnit.assert.equalKey( geom, json, 'type' ); QUnit.assert.equalKey( geom, json, 'uuid' ); QUnit.assert.equal( json.id, undefined, 'should not persist id' ); @@ -247,7 +247,7 @@ function checkLightCopyClone( assert, light ) { ); // Clone - const clone = light.clone(); // better get a new var + const clone = light.clone(); // better get a new clone QUnit.assert.notEqual( clone.uuid, light.uuid, 'Cloned light\'s UUID differs from original' ); QUnit.assert.notEqual( clone.id, light.id, 'Clone light\'s id differs from original' ); QUnit.assert.smartEqual( clone, light, 'Clone light is equal to original' ); @@ -270,7 +270,7 @@ function checkLightCopyClone( assert, light ) { // Compare json file with its source Light. function checkLightJsonWriting( assert, light, json ) { - assert.equal( json.metadata.version, '4.5', 'check metadata version' ); + assert.equal( json.metadata.version, '4.6', 'check metadata version' ); const object = json.object; assert.equalKey( light, object, 'type' ); diff --git a/utils/build/rollup.config.js b/utils/build/rollup.config.js index 1c3dce7414cb01..e77a171b621035 100644 --- a/utils/build/rollup.config.js +++ b/utils/build/rollup.config.js @@ -1,195 +1,5 @@ import terser from '@rollup/plugin-terser'; - -export function glconstants() { - - const constants = { - POINTS: 0, ZERO: 0, NONE: 0, - LINES: 1, ONE: 1, - LINE_LOOP: 2, - LINE_STRIP: 3, - TRIANGLES: 4, - TRIANGLE_STRIP: 5, - TRIANGLE_FAN: 6, - DEPTH_BUFFER_BIT: 256, - LESS: 513, - NEVER: 512, - EQUAL: 514, - LEQUAL: 515, - GREATER: 516, - NOTEQUAL: 517, - GEQUAL: 518, - ALWAYS: 519, - SRC_COLOR: 768, - ONE_MINUS_SRC_COLOR: 769, - SRC_ALPHA: 770, - ONE_MINUS_SRC_ALPHA: 771, - DST_ALPHA: 772, - ONE_MINUS_DST_ALPHA: 773, - DST_COLOR: 774, - ONE_MINUS_DST_COLOR: 775, - SRC_ALPHA_SATURATE: 776, - STENCIL_BUFFER_BIT: 1024, - FRONT: 1028, - BACK: 1029, - FRONT_AND_BACK: 1032, - CW: 2304, - CCW: 2305, - CULL_FACE: 2884, - DEPTH_TEST: 2929, - STENCIL_TEST: 2960, - VIEWPORT: 2978, - BLEND: 3042, - SCISSOR_BOX: 3088, - SCISSOR_TEST: 3089, - UNPACK_ALIGNMENT: 3317, - MAX_TEXTURE_SIZE: 3379, - DEPTH24_STENCIL8: 35056, - TEXTURE_2D: 3553, - BYTE: 5120, - UNSIGNED_BYTE: 5121, - SHORT: 5122, - UNSIGNED_INT: 5125, - UNSIGNED_SHORT: 5123, - INT: 5124, - FLOAT: 5126, - HALF_FLOAT: 5131, - DEPTH_COMPONENT: 6402, - RED: 6403, - ALPHA: 6406, - RGB: 6407, - RGBA: 6408, - LUMINANCE: 6409, - LUMINANCE_ALPHA: 6410, - KEEP: 7680, - RED_INTEGER: 36244, - RG: 33319, - RG_INTEGER: 33320, - RGB_INTEGER: 36248, - RGBA_INTEGER: 36249, - VERSION: 7938, - NEAREST: 9728, - LINEAR: 9729, - NEAREST_MIPMAP_NEAREST: 9984, - LINEAR_MIPMAP_NEAREST: 9985, - NEAREST_MIPMAP_LINEAR: 9986, - LINEAR_MIPMAP_LINEAR: 9987, - TEXTURE_MAG_FILTER: 10240, - TEXTURE_MIN_FILTER: 10241, - TEXTURE_WRAP_S: 10242, - TEXTURE_WRAP_T: 10243, - TEXTURE_WRAP_R: 32882, - REPEAT: 10497, - COLOR_BUFFER_BIT: 16384, - FUNC_ADD: 32774, - MIN: 32775, - MAX: 32776, - FUNC_SUBTRACT: 32778, - FUNC_REVERSE_SUBTRACT: 32779, - UNSIGNED_SHORT_4_4_4_4: 32819, - UNSIGNED_SHORT_5_5_5_1: 32820, - POLYGON_OFFSET_FILL: 32823, - RGB8: 32849, - RGBA4: 32854, - RGB5_A1: 32855, - RGBA8: 32856, - TEXTURE_3D: 32879, - CLAMP_TO_EDGE: 33071, - DEPTH_COMPONENT16: 33189, - DEPTH_COMPONENT24: 33190, - DEPTH_COMPONENT32F: 36012, - DEPTH_STENCIL_ATTACHMENT: 33306, - R8: 33321, - RG8: 33323, - R16F: 33325, - R32F: 33326, - RG16F: 33327, - RG32F: 33328, - UNSIGNED_SHORT_5_6_5: 33635, - MIRRORED_REPEAT: 33648, - TEXTURE0: 33984, - DEPTH_STENCIL: 34041, - UNSIGNED_INT_24_8: 34042, - TEXTURE_CUBE_MAP: 34067, - TEXTURE_CUBE_MAP_POSITIVE_X: 34069, - TEXTURE_CUBE_MAP_NEGATIVE_Z: 34074, - MAX_CUBE_MAP_TEXTURE_SIZE: 34076, - COMPRESSED_TEXTURE_FORMATS: 34467, - RGBA32F: 34836, - RGB32F: 34837, - RGBA16F: 34842, - RGB16F: 34843, - MAX_VERTEX_ATTRIBS: 34921, - MAX_TEXTURE_IMAGE_UNITS: 34930, - ARRAY_BUFFER: 34962, - UNIFORM_BUFFER: 35345, - ELEMENT_ARRAY_BUFFER: 34963, - STATIC_DRAW: 35044, - DYNAMIC_DRAW: 35048, - VERTEX_SHADER: 35633, - FRAGMENT_SHADER: 35632, - MAX_VERTEX_TEXTURE_IMAGE_UNITS: 35660, - MAX_COMBINED_TEXTURE_IMAGE_UNITS: 35661, - FLOAT_MAT2: 35674, - FLOAT_MAT3: 35675, - FLOAT_MAT4: 35676, - COMPILE_STATUS: 35713, - LINK_STATUS: 35714, - VALIDATE_STATUS: 35715, - ACTIVE_UNIFORMS: 35718, - ACTIVE_ATTRIBUTES: 35721, - IMPLEMENTATION_COLOR_READ_TYPE: 35738, - IMPLEMENTATION_COLOR_READ_FORMAT: 35739, - TEXTURE_2D_ARRAY: 35866, - COLOR_ATTACHMENT0: 36064, - FRAMEBUFFER_COMPLETE: 36053, - DEPTH_ATTACHMENT: 36096, - FRAMEBUFFER: 36160, - RENDERBUFFER: 36161, - LOW_FLOAT: 36336, - MEDIUM_FLOAT: 36337, - HIGH_FLOAT: 36338, - MAX_VERTEX_UNIFORM_VECTORS: 36347, - MAX_VARYING_VECTORS: 36348, - MAX_FRAGMENT_UNIFORM_VECTORS: 36349, - UNPACK_FLIP_Y_WEBGL: 37440, - UNPACK_PREMULTIPLY_ALPHA_WEBGL: 37441, - UNPACK_COLORSPACE_CONVERSION_WEBGL: 37443, - UNPACK_ROW_LENGTH: 3314, - UNPACK_IMAGE_HEIGHT: 32878, - UNPACK_SKIP_PIXELS: 3316, - UNPACK_SKIP_ROWS: 3315, - UNPACK_SKIP_IMAGES: 32877, - MAX_SAMPLES: 36183, - READ_FRAMEBUFFER: 36008, - DRAW_FRAMEBUFFER: 36009, - SAMPLE_ALPHA_TO_COVERAGE: 32926, - SRGB8: 35905, - SRGB8_ALPHA8: 35907, - MAX_UNIFORM_BUFFER_BINDINGS: 35375 - }; - - return { - - transform( code ) { - - code = code.replace( /_?gl\.([A-Z0-9_]+)/g, function ( match, p1 ) { - - if ( p1 in constants ) return constants[ p1 ]; - console.log( '* Unhandled GL Constant:', p1 ); - return match; - - } ); - - return { - code: code, - map: null - }; - - } - - }; - -} +import MagicString from 'magic-string'; function addons() { @@ -199,11 +9,13 @@ function addons() { if ( /\/examples\/jsm\//.test( id ) === false ) return; - code = code.replace( 'build/three.module.js', 'src/Three.js' ); + code = new MagicString( code ); + + code.replace( 'build/three.module.js', 'src/Three.js' ); return { - code: code, - map: null + code: code.toString(), + map: code.generateMap().toString() }; } @@ -220,7 +32,9 @@ export function glsl() { if ( /\.glsl.js$/.test( id ) === false ) return; - code = code.replace( /\/\* glsl \*\/\`(.*?)\`/sg, function ( match, p1 ) { + code = new MagicString( code ); + + code.replace( /\/\* glsl \*\/\`(.*?)\`/sg, function ( match, p1 ) { return JSON.stringify( p1 @@ -234,8 +48,8 @@ export function glsl() { } ); return { - code: code, - map: null + code: code.toString(), + map: code.generateMap().toString() }; } @@ -250,12 +64,39 @@ function header() { renderChunk( code ) { - return `/** + code = new MagicString( code ); + + code.prepend( `/** * @license * Copyright 2010-2023 Three.js Authors * SPDX-License-Identifier: MIT - */ -${ code }`; + */\n` ); + + return { + code: code.toString(), + map: code.generateMap().toString() + }; + + } + + }; + +} + +function deprecationWarning() { + + return { + + renderChunk( code ) { + + code = new MagicString( code ); + + code.prepend( `console.warn( 'Scripts "build/three.js" and "build/three.min.js" are deprecated with r150+, and will be removed with r160. Please use ES Modules or alternatives: https://threejs.org/docs/index.html#manual/en/introduction/Installation' );\n` ); + + return { + code: code.toString(), + map: code.generateMap().toString() + }; } @@ -268,7 +109,6 @@ const builds = [ input: 'src/Three.js', plugins: [ addons(), - glconstants(), glsl(), header() ], @@ -284,15 +124,24 @@ const builds = [ plugins: [ addons(), glsl(), + terser(), header() ], output: [ { - format: 'umd', - name: 'THREE', - file: 'build/three.js', - indent: '\t' - }, + format: 'esm', + file: 'build/three.module.min.js' + } + ] + }, + { + input: 'src/Three.js', + plugins: [ + addons(), + glsl(), + header() + ], + output: [ { format: 'cjs', name: 'THREE', @@ -301,14 +150,32 @@ const builds = [ } ] }, - { + + { // @deprecated, r150 + input: 'src/Three.js', + plugins: [ + addons(), + glsl(), + header(), + deprecationWarning() + ], + output: [ + { + format: 'umd', + name: 'THREE', + file: 'build/three.js', + indent: '\t' + } + ] + }, + { // @deprecated, r150 input: 'src/Three.js', plugins: [ addons(), - glconstants(), glsl(), terser(), - header() + header(), + deprecationWarning() ], output: [ {