sparcoon 0.7.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -76
- package/dist/artifact/FXArtifact.d.ts +120 -0
- package/dist/artifact/FXArtifact.js +1 -0
- package/dist/coreLayout.d.ts +22 -0
- package/dist/coreLayout.js +32 -0
- package/dist/effect/FXEffect.d.ts +77 -0
- package/dist/effect/FXEffect.js +454 -0
- package/dist/effect/FXEffectSampling.Internal.d.ts +24 -0
- package/dist/effect/FXEffectSampling.Internal.js +165 -0
- package/dist/effect/FXEffectSpec.d.ts +115 -0
- package/dist/effect/FXEffectSpec.js +1 -0
- package/dist/emitter/FXEmitter.Internal.d.ts +23 -58
- package/dist/emitter/FXEmitter.Internal.js +13 -29
- package/dist/emitter/FXEmitter.d.ts +46 -48
- package/dist/emitter/FXEmitter.js +355 -186
- package/dist/emitter/FXFromArtifactsOptions.d.ts +13 -0
- package/dist/emitter/FXFromArtifactsOptions.js +1 -0
- package/dist/emitter/FXObjectMotion.Internal.d.ts +33 -0
- package/dist/emitter/FXObjectMotion.Internal.js +87 -0
- package/dist/emitter/FXSimulationHolder.d.ts +1 -0
- package/dist/emitter/FXSimulationHolder.js +43 -0
- package/dist/index.d.ts +10 -39
- package/dist/index.js +13 -36
- package/dist/instancedParticle/FXInstancedParticle.d.ts +1 -22
- package/dist/instancedParticle/FXInstancedParticle.js +145 -85
- package/dist/instancedParticle/glTypeInfo.d.ts +5 -0
- package/dist/instancedParticle/glTypeInfo.js +3 -0
- package/dist/instancedParticle/primitiveGeometry.d.ts +1 -0
- package/dist/instancedParticle/primitiveGeometry.js +30 -0
- package/dist/miscellaneous/asserts.d.ts +1 -18
- package/dist/miscellaneous/asserts.js +21 -28
- package/dist/miscellaneous/fxMath.d.ts +26 -0
- package/dist/miscellaneous/fxMath.js +261 -0
- package/dist/miscellaneous/math.d.ts +2 -7
- package/dist/miscellaneous/math.js +8 -9
- package/dist/miscellaneous/texture/fxDataTexture.d.ts +26 -0
- package/dist/miscellaneous/texture/fxDataTexture.js +20 -0
- package/dist/render/FXArtifactMaterial.Internal.d.ts +16 -0
- package/dist/render/FXArtifactMaterial.Internal.js +944 -0
- package/dist/render/FXArtifactMaterial.d.ts +1 -0
- package/dist/render/FXArtifactMaterial.js +79 -0
- package/dist/render/FXMaterialOptions.d.ts +27 -0
- package/dist/render/FXMaterialOptions.js +5 -0
- package/dist/render/FXMeshMaterial.d.ts +40 -0
- package/dist/render/FXMeshMaterial.js +77 -0
- package/dist/world/FXWorld.d.ts +42 -0
- package/dist/world/FXWorld.js +103 -0
- package/package.json +45 -29
- package/dist/_virtual/2d.js +0 -3
- package/dist/_virtual/3d.js +0 -3
- package/dist/_virtual/4d.js +0 -3
- package/dist/_virtual/mod.js +0 -5
- package/dist/_virtual/mod2.js +0 -3
- package/dist/emitter/behavior/FXBehavior.d.ts +0 -24
- package/dist/emitter/behavior/FXBehavior.js +0 -10
- package/dist/emitter/behavior/FXBehaviorDirectionalForce.d.ts +0 -23
- package/dist/emitter/behavior/FXBehaviorDirectionalForce.js +0 -72
- package/dist/emitter/behavior/FXBehaviorPointForce.d.ts +0 -36
- package/dist/emitter/behavior/FXBehaviorPointForce.js +0 -94
- package/dist/emitter/behavior/FXBehaviorScaleOverLife.d.ts +0 -24
- package/dist/emitter/behavior/FXBehaviorScaleOverLife.js +0 -55
- package/dist/emitter/behavior/FXBehaviorTorqueDamping.d.ts +0 -20
- package/dist/emitter/behavior/FXBehaviorTorqueDamping.js +0 -48
- package/dist/emitter/behavior/FXBehaviorTorqueNoise.d.ts +0 -25
- package/dist/emitter/behavior/FXBehaviorTorqueNoise.js +0 -67
- package/dist/emitter/behavior/FXBehaviorTorqueOverLife.d.ts +0 -19
- package/dist/emitter/behavior/FXBehaviorTorqueOverLife.js +0 -41
- package/dist/emitter/behavior/FXBehaviorVelocityDamping.d.ts +0 -20
- package/dist/emitter/behavior/FXBehaviorVelocityDamping.js +0 -50
- package/dist/emitter/behavior/FXBehaviorVelocityNoise.d.ts +0 -25
- package/dist/emitter/behavior/FXBehaviorVelocityNoise.js +0 -76
- package/dist/emitter/behavior/FXBehaviorVelocityOverLife.d.ts +0 -22
- package/dist/emitter/behavior/FXBehaviorVelocityOverLife.js +0 -55
- package/dist/emitter/spawn/FXSpawn.d.ts +0 -11
- package/dist/emitter/spawn/FXSpawn.js +0 -10
- package/dist/emitter/spawn/FXSpawnBox.d.ts +0 -18
- package/dist/emitter/spawn/FXSpawnBox.js +0 -50
- package/dist/emitter/spawn/FXSpawnLifetime.d.ts +0 -17
- package/dist/emitter/spawn/FXSpawnLifetime.js +0 -44
- package/dist/emitter/spawn/FXSpawnOffset.d.ts +0 -21
- package/dist/emitter/spawn/FXSpawnOffset.js +0 -49
- package/dist/emitter/spawn/FXSpawnPoint.d.ts +0 -18
- package/dist/emitter/spawn/FXSpawnPoint.js +0 -46
- package/dist/emitter/spawn/FXSpawnRotation.d.ts +0 -17
- package/dist/emitter/spawn/FXSpawnRotation.js +0 -42
- package/dist/emitter/spawn/FXSpawnScale.d.ts +0 -22
- package/dist/emitter/spawn/FXSpawnScale.js +0 -56
- package/dist/emitter/spawn/FXSpawnSphere.d.ts +0 -36
- package/dist/emitter/spawn/FXSpawnSphere.js +0 -87
- package/dist/emitter/spawn/FXSpawnTorque.d.ts +0 -17
- package/dist/emitter/spawn/FXSpawnTorque.js +0 -42
- package/dist/emitter/spawn/FXSpawnVelocity.d.ts +0 -29
- package/dist/emitter/spawn/FXSpawnVelocity.js +0 -91
- package/dist/instancedParticle/FXInstancedParticle.Internal.d.ts +0 -2
- package/dist/instancedParticle/shared.d.ts +0 -19
- package/dist/instancedParticle/shared.js +0 -116
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.Internal.d.ts +0 -24
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.Internal.js +0 -275
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.d.ts +0 -75
- package/dist/materials/FXDiffuseMaterial/FXDiffuseMaterial.js +0 -63
- package/dist/materials/FXMaterial/FXBlending.Internal.d.ts +0 -24
- package/dist/materials/FXMaterial/FXBlending.Internal.js +0 -64
- package/dist/materials/FXMaterial/FXDepthMaterial.Internal.d.ts +0 -4
- package/dist/materials/FXMaterial/FXDepthMaterial.Internal.js +0 -144
- package/dist/materials/FXMaterial/FXDistanceMaterial.Internal.d.ts +0 -4
- package/dist/materials/FXMaterial/FXDistanceMaterial.Internal.js +0 -175
- package/dist/materials/FXMaterial/FXMaterial.d.ts +0 -70
- package/dist/materials/FXMaterial/FXMaterial.js +0 -51
- package/dist/materials/FXUnlitMaterial/FXUnlitMaterial.Internal.d.ts +0 -7
- package/dist/materials/FXUnlitMaterial/FXUnlitMaterial.Internal.js +0 -103
- package/dist/materials/FXUnlitMaterial/FXUnlitMaterial.d.ts +0 -7
- package/dist/materials/FXUnlitMaterial/FXUnlitMaterial.js +0 -21
- package/dist/miscellaneous/color/FXColor.Internal.d.ts +0 -7
- package/dist/miscellaneous/color/FXColor.Internal.js +0 -42
- package/dist/miscellaneous/color/FXColor.d.ts +0 -234
- package/dist/miscellaneous/color/FXColor.js +0 -636
- package/dist/miscellaneous/curve/FXCurve1D.Internal.d.ts +0 -20
- package/dist/miscellaneous/curve/FXCurve1D.d.ts +0 -17
- package/dist/miscellaneous/curve/FXCurve1D.js +0 -94
- package/dist/miscellaneous/miscellaneous.d.ts +0 -34
- package/dist/miscellaneous/miscellaneous.js +0 -85
- package/dist/miscellaneous/texture/FXTextureView.Internal.d.ts +0 -49
- package/dist/miscellaneous/texture/FXTextureView.Internal.js +0 -6
- package/dist/miscellaneous/texture/FXTextureView.d.ts +0 -72
- package/dist/miscellaneous/texture/FXTextureView.js +0 -234
- package/dist/miscellaneous/webglCapabilities.d.ts +0 -1
- package/dist/miscellaneous/webglCapabilities.js +0 -45
- package/dist/node_modules/fast-simplex-noise/lib/2d.js +0 -93
- package/dist/node_modules/fast-simplex-noise/lib/3d.js +0 -142
- package/dist/node_modules/fast-simplex-noise/lib/4d.js +0 -196
- package/dist/node_modules/fast-simplex-noise/lib/mod.js +0 -24
- package/dist/nodes/FXNode.d.ts +0 -5
- package/dist/nodes/FXNode.js +0 -10
- package/dist/nodes/blending/FXNodeBlending.d.ts +0 -6
- package/dist/nodes/blending/FXNodeBlending.js +0 -9
- package/dist/nodes/blending/FXNodeLightnessBlendingMask.d.ts +0 -19
- package/dist/nodes/blending/FXNodeLightnessBlendingMask.js +0 -65
- package/dist/nodes/color/FXNodeColor.d.ts +0 -6
- package/dist/nodes/color/FXNodeColor.js +0 -9
- package/dist/nodes/color/FXNodeColorOverLife.d.ts +0 -22
- package/dist/nodes/color/FXNodeColorOverLife.js +0 -64
- package/dist/nodes/color/FXNodeSphericalClip.d.ts +0 -21
- package/dist/nodes/color/FXNodeSphericalClip.js +0 -54
- package/dist/nodes/normal/FXNodeFlatNormal.d.ts +0 -6
- package/dist/nodes/normal/FXNodeFlatNormal.js +0 -17
- package/dist/nodes/normal/FXNodeNormal.d.ts +0 -6
- package/dist/nodes/normal/FXNodeNormal.js +0 -9
- package/dist/nodes/normal/FXNodeSphericalNormal.d.ts +0 -6
- package/dist/nodes/normal/FXNodeSphericalNormal.js +0 -24
- package/dist/nodes/texture/FXNodeAnimatedTexture.d.ts +0 -52
- package/dist/nodes/texture/FXNodeAnimatedTexture.js +0 -151
- package/dist/nodes/texture/FXNodeStaticTexture.d.ts +0 -20
- package/dist/nodes/texture/FXNodeStaticTexture.js +0 -67
- package/dist/nodes/texture/FXNodeTexture.d.ts +0 -6
- package/dist/nodes/texture/FXNodeTexture.js +0 -9
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { MathUtils } from 'three';
|
|
2
|
-
import { assertValidNumber } from '../../miscellaneous/asserts.js';
|
|
3
|
-
import { resolveFXRangeConfig, BUILTIN_OFFSET_TORQUE } from '../../miscellaneous/miscellaneous.js';
|
|
4
|
-
import { FXSpawn } from './FXSpawn.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Assigns a random initial angular velocity to each spawned particle
|
|
8
|
-
*/
|
|
9
|
-
class FXSpawnTorque extends FXSpawn {
|
|
10
|
-
/**
|
|
11
|
-
* @param torque - Angular velocity range in radians/second. Defaults to `{ min: -Math.PI, max: Math.PI }`
|
|
12
|
-
*/
|
|
13
|
-
constructor(torque = { min: -Math.PI, max: Math.PI }) {
|
|
14
|
-
super();
|
|
15
|
-
/** @internal */
|
|
16
|
-
this.requiredProperties = { builtin: "Matrix4" };
|
|
17
|
-
this._private_torqueInternal = resolveFXRangeConfig(torque);
|
|
18
|
-
assertValidNumber(this._private_torqueInternal.min, "FXSpawnTorque.constructor.torque.min");
|
|
19
|
-
assertValidNumber(this._private_torqueInternal.max, "FXSpawnTorque.constructor.torque.max");
|
|
20
|
-
}
|
|
21
|
-
/** Angular velocity range in radians/second */
|
|
22
|
-
get torque() {
|
|
23
|
-
return this._private_torqueInternal;
|
|
24
|
-
}
|
|
25
|
-
set torque(value) {
|
|
26
|
-
this._private_torqueInternal = resolveFXRangeConfig(value);
|
|
27
|
-
assertValidNumber(this._private_torqueInternal.min, "FXSpawnTorque.torque.min");
|
|
28
|
-
assertValidNumber(this._private_torqueInternal.max, "FXSpawnTorque.torque.max");
|
|
29
|
-
}
|
|
30
|
-
/** @internal */
|
|
31
|
-
spawn(properties, instanceBegin, instanceEnd) {
|
|
32
|
-
const { builtin } = properties;
|
|
33
|
-
const { array, itemSize } = builtin;
|
|
34
|
-
const { min: torqueMin, max: torqueMax } = this._private_torqueInternal;
|
|
35
|
-
for (let i = instanceBegin; i < instanceEnd; i++) {
|
|
36
|
-
array[i * itemSize + BUILTIN_OFFSET_TORQUE] = MathUtils.randFloat(torqueMin, torqueMax);
|
|
37
|
-
}
|
|
38
|
-
builtin.needsUpdate = true;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export { FXSpawnTorque };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Vector3 } from "three";
|
|
2
|
-
import type { FXRange, FXRangeConfig } from "../../miscellaneous/miscellaneous";
|
|
3
|
-
import { FXSpawn } from "./FXSpawn";
|
|
4
|
-
/**
|
|
5
|
-
* Assigns a random initial velocity to each spawned particle within a cone around a direction axis
|
|
6
|
-
*/
|
|
7
|
-
export declare class FXSpawnVelocity extends FXSpawn<{
|
|
8
|
-
builtin: "Matrix4";
|
|
9
|
-
}> {
|
|
10
|
-
private angleInternal;
|
|
11
|
-
private magnitudeInternal;
|
|
12
|
-
private readonly directionInternal;
|
|
13
|
-
/**
|
|
14
|
-
* @param direction - Cone axis; normalized automatically. Defaults to `(0, 1, 0)`
|
|
15
|
-
* @param angle - Cone half-angle range in radians; `{ min: 0, max: 0 }` fires in a straight line.
|
|
16
|
-
* Defaults to `{ min: 0, max: Math.PI }`
|
|
17
|
-
* @param magnitude - Speed range in units/second. Defaults to `{ min: -1, max: 1 }`
|
|
18
|
-
*/
|
|
19
|
-
constructor(direction?: Vector3, angle?: FXRangeConfig, magnitude?: FXRangeConfig);
|
|
20
|
-
/** Cone axis (always normalized) */
|
|
21
|
-
get direction(): Vector3;
|
|
22
|
-
/** Cone half-angle range in radians */
|
|
23
|
-
get angle(): FXRange;
|
|
24
|
-
/** Speed range in units/second */
|
|
25
|
-
get magnitude(): FXRange;
|
|
26
|
-
set direction(value: Vector3);
|
|
27
|
-
set angle(value: FXRangeConfig);
|
|
28
|
-
set magnitude(value: FXRangeConfig);
|
|
29
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { Vector3, MathUtils } from 'three';
|
|
2
|
-
import { assertValidNumber } from '../../miscellaneous/asserts.js';
|
|
3
|
-
import { resolveFXRangeConfig, BUILTIN_OFFSET_VELOCITY_X, BUILTIN_OFFSET_VELOCITY_Y, BUILTIN_OFFSET_VELOCITY_Z } from '../../miscellaneous/miscellaneous.js';
|
|
4
|
-
import { FXSpawn } from './FXSpawn.js';
|
|
5
|
-
|
|
6
|
-
const TEMP_TANGENT = new Vector3();
|
|
7
|
-
const TEMP_BITANGENT = new Vector3();
|
|
8
|
-
const TEMP_VELOCITY = new Vector3();
|
|
9
|
-
/**
|
|
10
|
-
* Assigns a random initial velocity to each spawned particle within a cone around a direction axis
|
|
11
|
-
*/
|
|
12
|
-
class FXSpawnVelocity extends FXSpawn {
|
|
13
|
-
/**
|
|
14
|
-
* @param direction - Cone axis; normalized automatically. Defaults to `(0, 1, 0)`
|
|
15
|
-
* @param angle - Cone half-angle range in radians; `{ min: 0, max: 0 }` fires in a straight line.
|
|
16
|
-
* Defaults to `{ min: 0, max: Math.PI }`
|
|
17
|
-
* @param magnitude - Speed range in units/second. Defaults to `{ min: -1, max: 1 }`
|
|
18
|
-
*/
|
|
19
|
-
constructor(direction = new Vector3(0, 1, 0), angle = { min: 0, max: Math.PI }, magnitude = { min: -1, max: 1 }) {
|
|
20
|
-
super();
|
|
21
|
-
/** @internal */
|
|
22
|
-
this.requiredProperties = { builtin: "Matrix4" };
|
|
23
|
-
this._private_directionInternal = direction.clone().normalize();
|
|
24
|
-
this._private_angleInternal = resolveFXRangeConfig(angle);
|
|
25
|
-
this._private_magnitudeInternal = resolveFXRangeConfig(magnitude);
|
|
26
|
-
assertValidNumber(this._private_angleInternal.min, "FXSpawnVelocity.constructor.angle.min");
|
|
27
|
-
assertValidNumber(this._private_angleInternal.max, "FXSpawnVelocity.constructor.angle.max");
|
|
28
|
-
assertValidNumber(this._private_magnitudeInternal.min, "FXSpawnVelocity.constructor.magnitude.min");
|
|
29
|
-
assertValidNumber(this._private_magnitudeInternal.max, "FXSpawnVelocity.constructor.magnitude.max");
|
|
30
|
-
}
|
|
31
|
-
/** Cone axis (always normalized) */
|
|
32
|
-
get direction() {
|
|
33
|
-
return this._private_directionInternal;
|
|
34
|
-
}
|
|
35
|
-
/** Cone half-angle range in radians */
|
|
36
|
-
get angle() {
|
|
37
|
-
return this._private_angleInternal;
|
|
38
|
-
}
|
|
39
|
-
/** Speed range in units/second */
|
|
40
|
-
get magnitude() {
|
|
41
|
-
return this._private_magnitudeInternal;
|
|
42
|
-
}
|
|
43
|
-
set direction(value) {
|
|
44
|
-
this._private_directionInternal.copy(value).normalize();
|
|
45
|
-
}
|
|
46
|
-
set angle(value) {
|
|
47
|
-
this._private_angleInternal = resolveFXRangeConfig(value);
|
|
48
|
-
assertValidNumber(this._private_angleInternal.min, "FXSpawnVelocity.angle.min");
|
|
49
|
-
assertValidNumber(this._private_angleInternal.max, "FXSpawnVelocity.angle.max");
|
|
50
|
-
}
|
|
51
|
-
set magnitude(value) {
|
|
52
|
-
this._private_magnitudeInternal = resolveFXRangeConfig(value);
|
|
53
|
-
assertValidNumber(this._private_magnitudeInternal.min, "FXSpawnVelocity.magnitude.min");
|
|
54
|
-
assertValidNumber(this._private_magnitudeInternal.max, "FXSpawnVelocity.magnitude.max");
|
|
55
|
-
}
|
|
56
|
-
/** @internal */
|
|
57
|
-
spawn(properties, instanceBegin, instanceEnd) {
|
|
58
|
-
const { builtin } = properties;
|
|
59
|
-
const { array, itemSize } = builtin;
|
|
60
|
-
const { min: angleMin, max: angleMax } = this._private_angleInternal;
|
|
61
|
-
const { min: magnitudeMin, max: magnitudeMax } = this._private_magnitudeInternal;
|
|
62
|
-
const dir = this._private_directionInternal;
|
|
63
|
-
if (Math.abs(dir.y) < 0.999) {
|
|
64
|
-
TEMP_TANGENT.set(0, 1, 0).cross(dir).normalize();
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
TEMP_TANGENT.set(1, 0, 0).cross(dir).normalize();
|
|
68
|
-
}
|
|
69
|
-
TEMP_BITANGENT.crossVectors(dir, TEMP_TANGENT);
|
|
70
|
-
const cosMin = Math.cos(angleMax);
|
|
71
|
-
const cosMax = Math.cos(angleMin);
|
|
72
|
-
for (let i = instanceBegin; i < instanceEnd; i++) {
|
|
73
|
-
const itemOffset = i * itemSize;
|
|
74
|
-
const cosTheta = MathUtils.lerp(cosMin, cosMax, Math.random());
|
|
75
|
-
const sinTheta = Math.sqrt(1 - cosTheta * cosTheta);
|
|
76
|
-
const phi = Math.random() * Math.PI * 2;
|
|
77
|
-
const magnitude = MathUtils.randFloat(magnitudeMin, magnitudeMax);
|
|
78
|
-
TEMP_VELOCITY.copy(dir)
|
|
79
|
-
.multiplyScalar(cosTheta)
|
|
80
|
-
.addScaledVector(TEMP_TANGENT, Math.cos(phi) * sinTheta)
|
|
81
|
-
.addScaledVector(TEMP_BITANGENT, Math.sin(phi) * sinTheta)
|
|
82
|
-
.multiplyScalar(magnitude);
|
|
83
|
-
array[itemOffset + BUILTIN_OFFSET_VELOCITY_X] = TEMP_VELOCITY.x;
|
|
84
|
-
array[itemOffset + BUILTIN_OFFSET_VELOCITY_Y] = TEMP_VELOCITY.y;
|
|
85
|
-
array[itemOffset + BUILTIN_OFFSET_VELOCITY_Z] = TEMP_VELOCITY.z;
|
|
86
|
-
}
|
|
87
|
-
builtin.needsUpdate = true;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export { FXSpawnVelocity };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { IUniform, ShaderMaterial } from "three";
|
|
2
|
-
import { Matrix3, Matrix4, Texture, Vector2, Vector3, Vector4 } from "three";
|
|
3
|
-
import { FXColor } from "../miscellaneous/color/FXColor";
|
|
4
|
-
export type FXProperty = Texture | FXColor | Vector2 | Vector3 | Vector4 | Matrix3 | Matrix4 | number;
|
|
5
|
-
export type FXPropertyName = "Texture" | "FXColor" | "Vector2" | "Vector3" | "Vector4" | "Matrix3" | "Matrix4" | "number";
|
|
6
|
-
export type FXPropertyConstructor = typeof Texture | typeof FXColor | typeof Vector2 | typeof Vector3 | typeof Vector4 | typeof Matrix3 | typeof Matrix4 | NumberConstructor;
|
|
7
|
-
export type FXPropertyCopyTo = FXColor | Vector2 | Vector3 | Vector4 | Matrix3 | Matrix4;
|
|
8
|
-
export type FXPropertyCopyFrom = FXColor & Vector2 & Vector3 & Vector4 & Matrix3 & Matrix4;
|
|
9
|
-
export interface GLTypeInfo {
|
|
10
|
-
glslTypeName: string;
|
|
11
|
-
bufferSize: number;
|
|
12
|
-
instantiable: boolean;
|
|
13
|
-
}
|
|
14
|
-
export interface GLProperty {
|
|
15
|
-
value: FXProperty;
|
|
16
|
-
glslTypeInfo: GLTypeInfo;
|
|
17
|
-
}
|
|
18
|
-
export declare function resolveGLSLTypeInfo(value: FXProperty | FXPropertyName | FXPropertyConstructor): GLTypeInfo;
|
|
19
|
-
export declare function resolvePropertyUniform(name: string, material: ShaderMaterial): IUniform<FXProperty>;
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { Texture, Vector2, Vector3, Vector4, Matrix3, Matrix4 } from 'three';
|
|
2
|
-
import { FXColor } from '../miscellaneous/color/FXColor.js';
|
|
3
|
-
|
|
4
|
-
const GLSL_TYPE_INFO_FLOAT = Object.freeze({
|
|
5
|
-
glslTypeName: "float",
|
|
6
|
-
bufferSize: 1,
|
|
7
|
-
instantiable: true,
|
|
8
|
-
});
|
|
9
|
-
const GLSL_TYPE_INFO_SAMPLER2D = Object.freeze({
|
|
10
|
-
glslTypeName: "sampler2D",
|
|
11
|
-
bufferSize: -1,
|
|
12
|
-
instantiable: false,
|
|
13
|
-
});
|
|
14
|
-
const GLSL_TYPE_INFO_VEC2 = Object.freeze({
|
|
15
|
-
glslTypeName: "vec2",
|
|
16
|
-
bufferSize: 2,
|
|
17
|
-
instantiable: true,
|
|
18
|
-
});
|
|
19
|
-
const GLSL_TYPE_INFO_VEC3 = Object.freeze({
|
|
20
|
-
glslTypeName: "vec3",
|
|
21
|
-
bufferSize: 3,
|
|
22
|
-
instantiable: true,
|
|
23
|
-
});
|
|
24
|
-
const GLSL_TYPE_INFO_VEC4 = Object.freeze({
|
|
25
|
-
glslTypeName: "vec4",
|
|
26
|
-
bufferSize: 4,
|
|
27
|
-
instantiable: true,
|
|
28
|
-
});
|
|
29
|
-
const GLSL_TYPE_INFO_MAT3 = Object.freeze({
|
|
30
|
-
glslTypeName: "mat3",
|
|
31
|
-
bufferSize: 9,
|
|
32
|
-
instantiable: true,
|
|
33
|
-
});
|
|
34
|
-
const GLSL_TYPE_INFO_MAT4 = Object.freeze({
|
|
35
|
-
glslTypeName: "mat4",
|
|
36
|
-
bufferSize: 16,
|
|
37
|
-
instantiable: true,
|
|
38
|
-
});
|
|
39
|
-
function resolveGLSLTypeInfo(value) {
|
|
40
|
-
if (typeof value === "string") {
|
|
41
|
-
switch (value) {
|
|
42
|
-
case "number":
|
|
43
|
-
return GLSL_TYPE_INFO_FLOAT;
|
|
44
|
-
case "Texture":
|
|
45
|
-
return GLSL_TYPE_INFO_SAMPLER2D;
|
|
46
|
-
case "FXColor":
|
|
47
|
-
return GLSL_TYPE_INFO_VEC4;
|
|
48
|
-
case "Vector2":
|
|
49
|
-
return GLSL_TYPE_INFO_VEC2;
|
|
50
|
-
case "Vector3":
|
|
51
|
-
return GLSL_TYPE_INFO_VEC3;
|
|
52
|
-
case "Vector4":
|
|
53
|
-
return GLSL_TYPE_INFO_VEC4;
|
|
54
|
-
case "Matrix3":
|
|
55
|
-
return GLSL_TYPE_INFO_MAT3;
|
|
56
|
-
case "Matrix4":
|
|
57
|
-
return GLSL_TYPE_INFO_MAT4;
|
|
58
|
-
default:
|
|
59
|
-
throw new Error(`resolveGLSLTypeInfo.value: unsupported property type name`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (typeof value === "function") {
|
|
63
|
-
if (value === Number) {
|
|
64
|
-
return GLSL_TYPE_INFO_FLOAT;
|
|
65
|
-
}
|
|
66
|
-
if (value === Texture) {
|
|
67
|
-
return GLSL_TYPE_INFO_SAMPLER2D;
|
|
68
|
-
}
|
|
69
|
-
if (value === FXColor) {
|
|
70
|
-
return GLSL_TYPE_INFO_VEC4;
|
|
71
|
-
}
|
|
72
|
-
if (value === Vector2) {
|
|
73
|
-
return GLSL_TYPE_INFO_VEC2;
|
|
74
|
-
}
|
|
75
|
-
if (value === Vector3) {
|
|
76
|
-
return GLSL_TYPE_INFO_VEC3;
|
|
77
|
-
}
|
|
78
|
-
if (value === Vector4) {
|
|
79
|
-
return GLSL_TYPE_INFO_VEC4;
|
|
80
|
-
}
|
|
81
|
-
if (value === Matrix3) {
|
|
82
|
-
return GLSL_TYPE_INFO_MAT3;
|
|
83
|
-
}
|
|
84
|
-
if (value === Matrix4) {
|
|
85
|
-
return GLSL_TYPE_INFO_MAT4;
|
|
86
|
-
}
|
|
87
|
-
throw new Error(`resolveGLSLTypeInfo.value: unsupported property type constructor`);
|
|
88
|
-
}
|
|
89
|
-
if (typeof value === "number") {
|
|
90
|
-
return GLSL_TYPE_INFO_FLOAT;
|
|
91
|
-
}
|
|
92
|
-
if (value instanceof Texture) {
|
|
93
|
-
return GLSL_TYPE_INFO_SAMPLER2D;
|
|
94
|
-
}
|
|
95
|
-
if (value instanceof FXColor) {
|
|
96
|
-
return GLSL_TYPE_INFO_VEC4;
|
|
97
|
-
}
|
|
98
|
-
if (value instanceof Vector2) {
|
|
99
|
-
return GLSL_TYPE_INFO_VEC2;
|
|
100
|
-
}
|
|
101
|
-
if (value instanceof Vector3) {
|
|
102
|
-
return GLSL_TYPE_INFO_VEC3;
|
|
103
|
-
}
|
|
104
|
-
if (value instanceof Vector4) {
|
|
105
|
-
return GLSL_TYPE_INFO_VEC4;
|
|
106
|
-
}
|
|
107
|
-
if (value instanceof Matrix3) {
|
|
108
|
-
return GLSL_TYPE_INFO_MAT3;
|
|
109
|
-
}
|
|
110
|
-
if (value instanceof Matrix4) {
|
|
111
|
-
return GLSL_TYPE_INFO_MAT4;
|
|
112
|
-
}
|
|
113
|
-
throw new Error(`resolveGLSLTypeInfo.value: unsupported property type`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export { resolveGLSLTypeInfo };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Color, MeshLambertMaterial } from "three";
|
|
2
|
-
import type { GLTypeInfo } from "../../instancedParticle/shared";
|
|
3
|
-
import type { FXNodeBlending } from "../../nodes/blending/FXNodeBlending";
|
|
4
|
-
import { FXNodeColor } from "../../nodes/color/FXNodeColor";
|
|
5
|
-
import type { FXNodeNormal } from "../../nodes/normal/FXNodeNormal";
|
|
6
|
-
import { FXNodeTexture } from "../../nodes/texture/FXNodeTexture";
|
|
7
|
-
import { FXBlending } from "../FXMaterial/FXMaterial";
|
|
8
|
-
export interface FXScatterUniforms {
|
|
9
|
-
u_ScatterTint: {
|
|
10
|
-
value: Color;
|
|
11
|
-
};
|
|
12
|
-
u_ScatterPower: {
|
|
13
|
-
value: number;
|
|
14
|
-
};
|
|
15
|
-
u_ForwardScatterStrength: {
|
|
16
|
-
value: number;
|
|
17
|
-
};
|
|
18
|
-
u_BackScatterStrength: {
|
|
19
|
-
value: number;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
export declare function buildFXDiffuseMaterial(varyings: Record<string, GLTypeInfo>, blending: FXBlending, useAlphaHashing: boolean, alphaTest: number, albedoNodes: readonly (FXNodeColor | FXNodeTexture | FXNodeBlending)[], normalNodes: readonly (FXNodeTexture | FXNodeNormal)[], emissionNodes: readonly (FXNodeColor | FXNodeTexture)[], scatterUniforms?: FXScatterUniforms, shadowSensitivity?: {
|
|
23
|
-
value: number;
|
|
24
|
-
}): MeshLambertMaterial;
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { MeshLambertMaterial, Color, DoubleSide, NormalBlending } from 'three';
|
|
2
|
-
import { PARTICLE_DEFINES } from '../../miscellaneous/miscellaneous.js';
|
|
3
|
-
import { FXNodeColor } from '../../nodes/color/FXNodeColor.js';
|
|
4
|
-
import { CURRENT_EXPRESSION_VALUE_PLACEHOLDER } from '../../nodes/FXNode.js';
|
|
5
|
-
import { FXNodeTexture } from '../../nodes/texture/FXNodeTexture.js';
|
|
6
|
-
import { buildAlbedoAndBlendingCode } from '../FXMaterial/FXBlending.Internal.js';
|
|
7
|
-
import { FXBlending } from '../FXMaterial/FXMaterial.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Wraps every `getShadow(...)` call in the shader source with
|
|
11
|
-
* `mix(1.0, getShadow(...), <uniformName>)` so that a uniform
|
|
12
|
-
* can scale shadow influence from 0 (no shadows) to 1 (full shadows).
|
|
13
|
-
*/
|
|
14
|
-
function wrapShadowCalls(source, uniformName) {
|
|
15
|
-
const target = "getShadow(";
|
|
16
|
-
let result = "";
|
|
17
|
-
let position = 0;
|
|
18
|
-
while (position < source.length) {
|
|
19
|
-
const callStart = source.indexOf(target, position);
|
|
20
|
-
if (callStart === -1) {
|
|
21
|
-
result += source.slice(position);
|
|
22
|
-
break;
|
|
23
|
-
}
|
|
24
|
-
result += source.slice(position, callStart);
|
|
25
|
-
let depth = 0;
|
|
26
|
-
let cursor = callStart + target.length - 1;
|
|
27
|
-
for (; cursor < source.length; cursor++) {
|
|
28
|
-
if (source[cursor] === "(") {
|
|
29
|
-
depth++;
|
|
30
|
-
}
|
|
31
|
-
if (source[cursor] === ")") {
|
|
32
|
-
depth--;
|
|
33
|
-
}
|
|
34
|
-
if (depth === 0) {
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
const originalCall = source.slice(callStart, cursor + 1);
|
|
39
|
-
result += `mix(1.0, ${originalCall}, ${uniformName})`;
|
|
40
|
-
position = cursor + 1;
|
|
41
|
-
}
|
|
42
|
-
return result;
|
|
43
|
-
}
|
|
44
|
-
function buildFXDiffuseMaterial(varyings, blending, useAlphaHashing, alphaTest, albedoNodes, normalNodes, emissionNodes, scatterUniforms, shadowSensitivity) {
|
|
45
|
-
const useScatter = scatterUniforms !== undefined;
|
|
46
|
-
const useShadowSensitivity = shadowSensitivity !== undefined;
|
|
47
|
-
const useNormals = normalNodes.length > 0;
|
|
48
|
-
const attributeDeclarations = [];
|
|
49
|
-
const varyingDeclarations = [];
|
|
50
|
-
const vertexAssignments = [];
|
|
51
|
-
for (const name in varyings) {
|
|
52
|
-
const { glslTypeName } = varyings[name];
|
|
53
|
-
attributeDeclarations.push(`attribute ${glslTypeName} a_${name};`);
|
|
54
|
-
varyingDeclarations.push(`varying ${glslTypeName} p_${name};`);
|
|
55
|
-
vertexAssignments.push(`p_${name} = a_${name};`);
|
|
56
|
-
}
|
|
57
|
-
const material = new MeshLambertMaterial({
|
|
58
|
-
name: "FXDiffuseMaterial",
|
|
59
|
-
transparent: !useAlphaHashing,
|
|
60
|
-
depthWrite: useAlphaHashing,
|
|
61
|
-
depthTest: true,
|
|
62
|
-
alphaHash: useAlphaHashing,
|
|
63
|
-
blending: NormalBlending,
|
|
64
|
-
side: DoubleSide,
|
|
65
|
-
forceSinglePass: true,
|
|
66
|
-
alphaTest,
|
|
67
|
-
emissive: emissionNodes.length > 0 ? new Color(1, 1, 1) : new Color(0, 0, 0),
|
|
68
|
-
premultipliedAlpha: true,
|
|
69
|
-
});
|
|
70
|
-
material.onBeforeCompile = (shader) => {
|
|
71
|
-
const vertexPreamble = [
|
|
72
|
-
PARTICLE_DEFINES,
|
|
73
|
-
attributeDeclarations.join("\n"),
|
|
74
|
-
"varying vec2 p_uv;",
|
|
75
|
-
useNormals ? "varying vec2 p_billboardSinCos;" : "",
|
|
76
|
-
useScatter ? "varying vec3 v_viewPosition;" : "",
|
|
77
|
-
varyingDeclarations.join("\n"),
|
|
78
|
-
].join("\n");
|
|
79
|
-
shader.vertexShader =
|
|
80
|
-
vertexPreamble +
|
|
81
|
-
"\n" +
|
|
82
|
-
shader.vertexShader
|
|
83
|
-
.replace("#include <beginnormal_vertex>", "vec3 objectNormal = vec3(0.0, 0.0, 1.0);")
|
|
84
|
-
.replace("#include <defaultnormal_vertex>", "vec3 transformedNormal = vec3(0.0, 0.0, 1.0);")
|
|
85
|
-
.replace("#include <begin_vertex>", [
|
|
86
|
-
"p_uv = uv;",
|
|
87
|
-
vertexAssignments.join("\n"),
|
|
88
|
-
"vec3 transformed = position;",
|
|
89
|
-
"#ifdef USE_ALPHAHASH",
|
|
90
|
-
" vPosition = vec3(PARTICLE_POSITION_X, PARTICLE_POSITION_Y, PARTICLE_POSITION_Z) + vec3(position.xy, 0.0);",
|
|
91
|
-
"#endif",
|
|
92
|
-
].join("\n"))
|
|
93
|
-
.replace("#include <project_vertex>", [
|
|
94
|
-
"vec2 billboardOffset = position.xy;",
|
|
95
|
-
"billboardOffset.x *= PARTICLE_SCALE_X;",
|
|
96
|
-
"billboardOffset.y *= PARTICLE_SCALE_Y;",
|
|
97
|
-
"",
|
|
98
|
-
"float cosRotation = cos(PARTICLE_ROTATION);",
|
|
99
|
-
"float sinRotation = sin(PARTICLE_ROTATION);",
|
|
100
|
-
"billboardOffset = vec2(",
|
|
101
|
-
" billboardOffset.x * cosRotation - billboardOffset.y * sinRotation,",
|
|
102
|
-
" billboardOffset.x * sinRotation + billboardOffset.y * cosRotation",
|
|
103
|
-
");",
|
|
104
|
-
"",
|
|
105
|
-
// Pass the exact sin/cos that rotated the billboard to the fragment shader.
|
|
106
|
-
useNormals ? "p_billboardSinCos = vec2(sinRotation, cosRotation);" : "",
|
|
107
|
-
"",
|
|
108
|
-
"vec3 particleCenter = vec3(PARTICLE_POSITION_X, PARTICLE_POSITION_Y, PARTICLE_POSITION_Z);",
|
|
109
|
-
"vec4 mvPosition = modelViewMatrix * vec4(particleCenter, 1.0);",
|
|
110
|
-
"mvPosition.xy += billboardOffset;",
|
|
111
|
-
useScatter ? "v_viewPosition = mvPosition.xyz;" : "",
|
|
112
|
-
"gl_Position = projectionMatrix * mvPosition;",
|
|
113
|
-
].join("\n"))
|
|
114
|
-
.replace("#include <worldpos_vertex>", `
|
|
115
|
-
#if defined(USE_SHADOWMAP) || defined(USE_ENVMAP) || defined(DISTANCE) || (NUM_SPOT_LIGHT_COORDS > 0)
|
|
116
|
-
vec3 cameraRight = vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]);
|
|
117
|
-
vec3 cameraUp = vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]);
|
|
118
|
-
vec4 worldPosition = vec4(
|
|
119
|
-
(modelMatrix * vec4(particleCenter, 1.0)).xyz + cameraRight * billboardOffset.x + cameraUp * billboardOffset.y,
|
|
120
|
-
1.0
|
|
121
|
-
);
|
|
122
|
-
#endif
|
|
123
|
-
`);
|
|
124
|
-
const seenCacheKeys = new Set();
|
|
125
|
-
const uniqueHelpers = (nodes) => nodes
|
|
126
|
-
.filter((node) => {
|
|
127
|
-
if (seenCacheKeys.has(node.cacheKey)) {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
seenCacheKeys.add(node.cacheKey);
|
|
131
|
-
return true;
|
|
132
|
-
})
|
|
133
|
-
.map((node) => node.helperFunctions)
|
|
134
|
-
.join("\n");
|
|
135
|
-
const scatterDeclarations = useScatter
|
|
136
|
-
? [
|
|
137
|
-
"varying vec3 v_viewPosition;",
|
|
138
|
-
"uniform vec3 u_ScatterTint;",
|
|
139
|
-
"uniform float u_ScatterPower;",
|
|
140
|
-
"uniform float u_ForwardScatterStrength;",
|
|
141
|
-
"uniform float u_BackScatterStrength;",
|
|
142
|
-
`vec3 calculateScatter(vec3 viewDirection, vec3 lightDirection, vec3 lightColor, float alpha) {
|
|
143
|
-
float viewDotLight = dot(viewDirection, lightDirection);
|
|
144
|
-
float scatterForward = pow(max(-viewDotLight, 0.0), u_ScatterPower) * u_ForwardScatterStrength;
|
|
145
|
-
float scatterBackward = pow(max( viewDotLight, 0.0), 2.0) * u_BackScatterStrength;
|
|
146
|
-
return lightColor * u_ScatterTint * (scatterForward + scatterBackward) * alpha;
|
|
147
|
-
}`,
|
|
148
|
-
]
|
|
149
|
-
: [];
|
|
150
|
-
const shadowSensitivityDeclarations = useShadowSensitivity
|
|
151
|
-
? ["uniform float u_shadowSensitivity;"]
|
|
152
|
-
: [];
|
|
153
|
-
const fragmentPreamble = [
|
|
154
|
-
PARTICLE_DEFINES,
|
|
155
|
-
"varying vec2 p_uv;",
|
|
156
|
-
useNormals ? "varying vec2 p_billboardSinCos;" : "",
|
|
157
|
-
varyingDeclarations.join("\n"),
|
|
158
|
-
albedoNodes.flatMap((node) => node.uniformDeclarations).join("\n"),
|
|
159
|
-
uniqueHelpers(albedoNodes),
|
|
160
|
-
normalNodes.flatMap((node) => node.uniformDeclarations).join("\n"),
|
|
161
|
-
uniqueHelpers(normalNodes),
|
|
162
|
-
emissionNodes.flatMap((node) => node.uniformDeclarations).join("\n"),
|
|
163
|
-
uniqueHelpers(emissionNodes),
|
|
164
|
-
...scatterDeclarations,
|
|
165
|
-
...shadowSensitivityDeclarations,
|
|
166
|
-
].join("\n");
|
|
167
|
-
if (useScatter) {
|
|
168
|
-
shader.uniforms["u_ScatterTint"] = scatterUniforms.u_ScatterTint;
|
|
169
|
-
shader.uniforms["u_ScatterPower"] = scatterUniforms.u_ScatterPower;
|
|
170
|
-
shader.uniforms["u_ForwardScatterStrength"] = scatterUniforms.u_ForwardScatterStrength;
|
|
171
|
-
shader.uniforms["u_BackScatterStrength"] = scatterUniforms.u_BackScatterStrength;
|
|
172
|
-
}
|
|
173
|
-
if (useShadowSensitivity) {
|
|
174
|
-
shader.uniforms["u_shadowSensitivity"] = shadowSensitivity;
|
|
175
|
-
}
|
|
176
|
-
for (const node of albedoNodes) {
|
|
177
|
-
Object.assign(shader.uniforms, node.uniforms);
|
|
178
|
-
}
|
|
179
|
-
for (const node of normalNodes) {
|
|
180
|
-
Object.assign(shader.uniforms, node.uniforms);
|
|
181
|
-
}
|
|
182
|
-
for (const node of emissionNodes) {
|
|
183
|
-
Object.assign(shader.uniforms, node.uniforms);
|
|
184
|
-
}
|
|
185
|
-
let fragmentShader = shader.fragmentShader;
|
|
186
|
-
if (useNormals) {
|
|
187
|
-
const normalLines = [
|
|
188
|
-
"float faceDirection = gl_FrontFacing ? 1.0 : -1.0;",
|
|
189
|
-
"vec3 fxNormal = vec3(0.0, 0.0, 1.0);",
|
|
190
|
-
];
|
|
191
|
-
for (const node of normalNodes) {
|
|
192
|
-
if (node instanceof FXNodeTexture || node instanceof FXNodeColor) {
|
|
193
|
-
normalLines.push(`fxNormal = normalize((${node.colorExpression.replace(CURRENT_EXPRESSION_VALUE_PLACEHOLDER, "vec4(fxNormal, 1.0)")}).rgb * 2.0 - 1.0);`);
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
normalLines.push(`fxNormal = ${node.normalExpression.replace(CURRENT_EXPRESSION_VALUE_PLACEHOLDER, "fxNormal")};`);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
normalLines.push("", "float sinR = p_billboardSinCos.x;", "float cosR = p_billboardSinCos.y;", "vec3 normal = vec3(", " fxNormal.x * cosR - fxNormal.y * sinR,", " fxNormal.x * sinR + fxNormal.y * cosR,", " fxNormal.z", ");", "", "normal *= faceDirection;");
|
|
200
|
-
fragmentShader = fragmentShader.replace("#include <normal_fragment_begin>", normalLines.join("\n"));
|
|
201
|
-
}
|
|
202
|
-
const albedoCode = buildAlbedoAndBlendingCode(albedoNodes, blending, useAlphaHashing);
|
|
203
|
-
if (albedoCode.mapFragment !== null) {
|
|
204
|
-
fragmentShader = fragmentShader.replace("#include <map_fragment>", albedoCode.mapFragment);
|
|
205
|
-
}
|
|
206
|
-
if (emissionNodes.length > 0) {
|
|
207
|
-
const emissiveLines = ["vec4 fxEmissive = vec4(1.0);"];
|
|
208
|
-
for (const node of emissionNodes) {
|
|
209
|
-
emissiveLines.push(`fxEmissive = ${node.colorExpression.replace(CURRENT_EXPRESSION_VALUE_PLACEHOLDER, "fxEmissive")};`);
|
|
210
|
-
}
|
|
211
|
-
emissiveLines.push("totalEmissiveRadiance = fxEmissive.rgb;");
|
|
212
|
-
fragmentShader = fragmentShader.replace("#include <emissivemap_fragment>", emissiveLines.join("\n"));
|
|
213
|
-
}
|
|
214
|
-
if (useScatter) {
|
|
215
|
-
fragmentShader = fragmentShader.replace("#include <opaque_fragment>", `
|
|
216
|
-
#ifdef OPAQUE
|
|
217
|
-
diffuseColor.a = 1.0;
|
|
218
|
-
#endif
|
|
219
|
-
|
|
220
|
-
vec3 viewDirection = normalize(-v_viewPosition);
|
|
221
|
-
vec3 totalScatter = vec3(0.0);
|
|
222
|
-
|
|
223
|
-
#if NUM_DIR_LIGHTS > 0
|
|
224
|
-
for (int i = 0; i < NUM_DIR_LIGHTS; i++) {
|
|
225
|
-
totalScatter += calculateScatter(viewDirection, directionalLights[i].direction, directionalLights[i].color, diffuseColor.a);
|
|
226
|
-
}
|
|
227
|
-
#endif
|
|
228
|
-
|
|
229
|
-
#if NUM_POINT_LIGHTS > 0
|
|
230
|
-
for (int i = 0; i < NUM_POINT_LIGHTS; i++) {
|
|
231
|
-
vec3 toLightDirection = normalize(pointLights[i].position - v_viewPosition);
|
|
232
|
-
float lightDistance = length(pointLights[i].position - v_viewPosition);
|
|
233
|
-
float attenuation = 1.0 / (1.0 + 0.09 * lightDistance + 0.032 * lightDistance * lightDistance);
|
|
234
|
-
totalScatter += calculateScatter(viewDirection, toLightDirection, pointLights[i].color, diffuseColor.a) * attenuation;
|
|
235
|
-
}
|
|
236
|
-
#endif
|
|
237
|
-
|
|
238
|
-
#if NUM_SPOT_LIGHTS > 0
|
|
239
|
-
for (int i = 0; i < NUM_SPOT_LIGHTS; i++) {
|
|
240
|
-
vec3 toLightDirection = normalize(spotLights[i].position - v_viewPosition);
|
|
241
|
-
float lightDistance = length(spotLights[i].position - v_viewPosition);
|
|
242
|
-
float attenuation = 1.0 / (1.0 + 0.09 * lightDistance + 0.032 * lightDistance * lightDistance);
|
|
243
|
-
float spotCosine = dot(normalize(spotLights[i].direction), -toLightDirection);
|
|
244
|
-
float spotFalloff = smoothstep(spotLights[i].coneCos, spotLights[i].penumbraCos, spotCosine);
|
|
245
|
-
totalScatter += calculateScatter(viewDirection, toLightDirection, spotLights[i].color, diffuseColor.a) * attenuation * spotFalloff;
|
|
246
|
-
}
|
|
247
|
-
#endif
|
|
248
|
-
|
|
249
|
-
vec3 albedo = diffuseColor.a > 0.001
|
|
250
|
-
? diffuseColor.rgb / diffuseColor.a
|
|
251
|
-
: vec3(0.0);
|
|
252
|
-
gl_FragColor = vec4(outgoingLight + totalScatter * albedo, diffuseColor.a);
|
|
253
|
-
`);
|
|
254
|
-
}
|
|
255
|
-
if (useShadowSensitivity) {
|
|
256
|
-
fragmentShader = wrapShadowCalls(fragmentShader, "u_shadowSensitivity");
|
|
257
|
-
}
|
|
258
|
-
fragmentShader = fragmentShader.replace("#include <premultiplied_alpha_fragment>", albedoCode.premultChunk);
|
|
259
|
-
shader.fragmentShader = fragmentPreamble + "\n" + fragmentShader;
|
|
260
|
-
};
|
|
261
|
-
const scatterKey = useScatter ? `scatter(${scatterUniforms.u_ScatterPower.value})` : "no-scatter";
|
|
262
|
-
const shadowKey = useShadowSensitivity ? "shadow-sens" : "no-shadow-sens";
|
|
263
|
-
material.customProgramCacheKey = () => [
|
|
264
|
-
"fx",
|
|
265
|
-
albedoNodes.map((node) => node.cacheKey).join("-") || "none",
|
|
266
|
-
normalNodes.map((node) => node.cacheKey).join("-") || "none",
|
|
267
|
-
emissionNodes.map((node) => node.cacheKey).join("-") || "none",
|
|
268
|
-
FXBlending[blending],
|
|
269
|
-
scatterKey,
|
|
270
|
-
shadowKey,
|
|
271
|
-
].join("_");
|
|
272
|
-
return material;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
export { buildFXDiffuseMaterial };
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { ColorRepresentation } from "three";
|
|
2
|
-
import type { FXNodeColor } from "../../nodes/color/FXNodeColor";
|
|
3
|
-
import type { FXNodeNormal } from "../../nodes/normal/FXNodeNormal";
|
|
4
|
-
import type { FXNodeTexture } from "../../nodes/texture/FXNodeTexture";
|
|
5
|
-
import type { FXMaterialOptions } from "../FXMaterial/FXMaterial";
|
|
6
|
-
import { FXMaterial } from "../FXMaterial/FXMaterial";
|
|
7
|
-
/**
|
|
8
|
-
* Configuration options for {@link FXDiffuseMaterial}
|
|
9
|
-
*/
|
|
10
|
-
export interface FXDiffuseMaterialOptions extends FXMaterialOptions {
|
|
11
|
-
/**
|
|
12
|
-
* Normal nodes for lighting; multiple nodes are blended together
|
|
13
|
-
*
|
|
14
|
-
* @defaultValue `[new FXNodeSphericalNormal()]`
|
|
15
|
-
*/
|
|
16
|
-
normalNodes: (FXNodeTexture | FXNodeNormal)[];
|
|
17
|
-
/**
|
|
18
|
-
* Emission color nodes composited for emissive output
|
|
19
|
-
*
|
|
20
|
-
* @defaultValue `[]`
|
|
21
|
-
*/
|
|
22
|
-
emissionNodes: (FXNodeColor | FXNodeTexture)[];
|
|
23
|
-
/**
|
|
24
|
-
* Enable subsurface scattering approximation
|
|
25
|
-
*
|
|
26
|
-
* @defaultValue `false`
|
|
27
|
-
*/
|
|
28
|
-
enableScatter: boolean;
|
|
29
|
-
/**
|
|
30
|
-
* Tint color applied to the scatter contribution
|
|
31
|
-
*
|
|
32
|
-
* @defaultValue `0xffd999`
|
|
33
|
-
*/
|
|
34
|
-
scatterTint: ColorRepresentation;
|
|
35
|
-
/**
|
|
36
|
-
* Scatter lobe sharpness; higher values produce a tighter highlight
|
|
37
|
-
*
|
|
38
|
-
* @defaultValue `10`
|
|
39
|
-
*/
|
|
40
|
-
scatterPower: number;
|
|
41
|
-
/**
|
|
42
|
-
* Forward scatter intensity (light-facing side)
|
|
43
|
-
*
|
|
44
|
-
* @defaultValue `1`
|
|
45
|
-
*/
|
|
46
|
-
forwardScatterStrength: number;
|
|
47
|
-
/**
|
|
48
|
-
* Back scatter intensity (back-lit side)
|
|
49
|
-
*
|
|
50
|
-
* @defaultValue `1`
|
|
51
|
-
*/
|
|
52
|
-
backScatterStrength: number;
|
|
53
|
-
/**
|
|
54
|
-
* Shadow influence (`0` = no shadows, `1` = full shadows)
|
|
55
|
-
*
|
|
56
|
-
* @defaultValue `1`
|
|
57
|
-
*/
|
|
58
|
-
shadowSensitivity: number;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Diffuse particle material with lighting, normals, emission, and optional subsurface scattering
|
|
62
|
-
*/
|
|
63
|
-
export declare class FXDiffuseMaterial extends FXMaterial {
|
|
64
|
-
private readonly normalNodes;
|
|
65
|
-
private readonly emissionNodes;
|
|
66
|
-
private readonly scatterUniforms;
|
|
67
|
-
private readonly shadowSensitivity;
|
|
68
|
-
/**
|
|
69
|
-
* @param options - Material configuration
|
|
70
|
-
*/
|
|
71
|
-
constructor(options?: Partial<FXDiffuseMaterialOptions>);
|
|
72
|
-
/** Releases resources held by all albedo, normal, and emission nodes */
|
|
73
|
-
destroy(): void;
|
|
74
|
-
prepare(): void;
|
|
75
|
-
}
|