├── Threejs ├── types │ ├── module │ │ ├── sceneRoam.ts │ │ ├── animate.ts │ │ ├── fog.ts │ │ ├── sprite.ts │ │ ├── camera.ts │ │ ├── render.ts │ │ ├── ambient.ts │ │ ├── source.ts │ │ ├── environment.ts │ │ ├── skyLight.ts │ │ ├── directional.ts │ │ ├── point.ts │ │ ├── control.ts │ │ ├── spot.ts │ │ ├── sky.ts │ │ ├── event.ts │ │ ├── particle.ts │ │ ├── rectArea.ts │ │ ├── parade.ts │ │ ├── model.ts │ │ ├── water.ts │ │ └── viewer.ts │ ├── types.ts │ └── global.d.ts ├── plugins │ ├── object.ts │ ├── source.ts │ ├── fog.ts │ ├── animate.ts │ ├── sprite.ts │ ├── lights │ │ ├── ambient.ts │ │ ├── skyLight.ts │ │ ├── point.ts │ │ ├── spot.ts │ │ ├── directional.ts │ │ └── rectArea.ts │ ├── particleTween.ts │ ├── render.ts │ ├── particle.ts │ ├── event.ts │ ├── water.ts │ ├── control.ts │ ├── environment.ts │ ├── params.ts │ ├── camera.ts │ ├── skybox.ts │ ├── parade.ts │ ├── model.ts │ ├── particleExamples.ts │ ├── particleEngine.ts │ └── sceneRoam.ts ├── threelibex │ ├── LoaderBase.js │ └── GLTFExtensionLoader.js ├── shader │ ├── particle.ts │ ├── improved.ts │ ├── sky.ts │ └── water.ts └── index.ts ├── lib ├── types │ ├── module │ │ ├── sceneRoam.d.ts │ │ ├── animate.d.ts │ │ ├── fog.d.ts │ │ ├── sprite.d.ts │ │ ├── camera.d.ts │ │ ├── render.d.ts │ │ ├── ambient.d.ts │ │ ├── point.d.ts │ │ ├── source.d.ts │ │ ├── skyLight.d.ts │ │ ├── directional.d.ts │ │ ├── spot.d.ts │ │ ├── environment.d.ts │ │ ├── control.d.ts │ │ ├── rectArea.d.ts │ │ ├── sky.d.ts │ │ ├── event.d.ts │ │ ├── particle.d.ts │ │ ├── model.d.ts │ │ ├── parade.d.ts │ │ ├── water.d.ts │ │ └── viewer.d.ts │ └── types.d.ts ├── shader │ ├── improved.d.ts │ ├── particle.d.ts │ ├── sky.d.ts │ ├── water.d.ts │ └── effect.d.ts ├── plugins │ ├── object.d.ts │ ├── particleTween.d.ts │ ├── render.d.ts │ ├── animate.d.ts │ ├── sprite.d.ts │ ├── fog.d.ts │ ├── camera.d.ts │ ├── lights │ │ ├── ambient.d.ts │ │ ├── skyLight.d.ts │ │ ├── spot.d.ts │ │ ├── point.d.ts │ │ ├── directional.d.ts │ │ └── rectArea.d.ts │ ├── source.d.ts │ ├── skybox.d.ts │ ├── environment.d.ts │ ├── control.d.ts │ ├── event.d.ts │ ├── water.d.ts │ ├── particle.d.ts │ ├── parade.d.ts │ ├── model.d.ts │ ├── params.d.ts │ ├── sceneRoam.d.ts │ ├── particleEngine.d.ts │ └── particleExamples.d.ts └── index.d.ts └── package.json /Threejs/types/module/sceneRoam.ts: -------------------------------------------------------------------------------- 1 | export interface RoamType {} 2 | -------------------------------------------------------------------------------- /lib/types/module/sceneRoam.d.ts: -------------------------------------------------------------------------------- 1 | export interface RoamType { 2 | } 3 | -------------------------------------------------------------------------------- /lib/shader/improved.d.ts: -------------------------------------------------------------------------------- 1 | declare class ImprovedNoise { 2 | noise(x: any, y: any, z: any): any; 3 | } 4 | export { ImprovedNoise }; 5 | -------------------------------------------------------------------------------- /Threejs/types/module/animate.ts: -------------------------------------------------------------------------------- 1 | export interface AnimateType { 2 | frameId: any; 3 | animateFuntion: Array>; 4 | } 5 | export type ViewerAnimate = AnimateType; 6 | -------------------------------------------------------------------------------- /lib/plugins/object.d.ts: -------------------------------------------------------------------------------- 1 | import { Object3D as TObject3D } from "three"; 2 | export declare class Object3D extends TObject3D implements Object3D { 3 | constructor(); 4 | } 5 | -------------------------------------------------------------------------------- /lib/shader/particle.d.ts: -------------------------------------------------------------------------------- 1 | declare const particleVertexShader: string; 2 | declare const particleFragmentShader: string; 3 | export { particleVertexShader, particleFragmentShader }; 4 | -------------------------------------------------------------------------------- /lib/types/module/animate.d.ts: -------------------------------------------------------------------------------- 1 | export interface AnimateType { 2 | frameId: any; 3 | animateFuntion: Array>; 4 | } 5 | export type ViewerAnimate = AnimateType; 6 | -------------------------------------------------------------------------------- /Threejs/plugins/object.ts: -------------------------------------------------------------------------------- 1 | import { Object3D as TObject3D } from "three"; 2 | 3 | export class Object3D extends TObject3D implements Object3D { 4 | constructor() { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Threejs/types/module/fog.ts: -------------------------------------------------------------------------------- 1 | export interface FogType { 2 | initFog: FnThreeParams; 3 | initFogExp: FnTwoParams; 4 | } 5 | 6 | export type ViewerFog = FogType; 7 | -------------------------------------------------------------------------------- /lib/types/module/fog.d.ts: -------------------------------------------------------------------------------- 1 | export interface FogType { 2 | initFog: FnThreeParams; 3 | initFogExp: FnTwoParams; 4 | } 5 | export type ViewerFog = FogType; 6 | -------------------------------------------------------------------------------- /Threejs/types/module/sprite.ts: -------------------------------------------------------------------------------- 1 | export interface SpriteType { 2 | sprite: THREE.Sprite; 3 | init: Fn; 4 | } 5 | 6 | export interface SpriteParams { 7 | texture: THREE.Texture; 8 | name: string; 9 | } 10 | -------------------------------------------------------------------------------- /lib/types/module/sprite.d.ts: -------------------------------------------------------------------------------- 1 | export interface SpriteType { 2 | sprite: THREE.Sprite; 3 | init: Fn; 4 | } 5 | export interface SpriteParams { 6 | texture: THREE.Texture; 7 | name: string; 8 | } 9 | -------------------------------------------------------------------------------- /lib/plugins/particleTween.d.ts: -------------------------------------------------------------------------------- 1 | export declare class Tween implements ParticleTween { 2 | times: number[]; 3 | values: THREE.Vector3 | number[]; 4 | constructor(timeArray?: any[], valueArray?: any[]); 5 | lerp(t: number): any; 6 | } 7 | -------------------------------------------------------------------------------- /lib/plugins/render.d.ts: -------------------------------------------------------------------------------- 1 | import { RenderType } from "../types/types"; 2 | export declare class Renderer implements RenderType { 3 | renderer: THREE.WebGLRenderer; 4 | private el; 5 | constructor(el: HTMLElement); 6 | private init; 7 | } 8 | -------------------------------------------------------------------------------- /Threejs/types/module/camera.ts: -------------------------------------------------------------------------------- 1 | import { ControlType } from "./control"; 2 | export interface CameraType { 3 | camera: THREE.Camera; 4 | flyTo: (tween: any, controls: ControlType, option: FlyToParams) => any; 5 | } 6 | 7 | export type ViewerCamera = CameraType; 8 | -------------------------------------------------------------------------------- /lib/types/module/camera.d.ts: -------------------------------------------------------------------------------- 1 | import { ControlType } from "./control"; 2 | export interface CameraType { 3 | camera: THREE.Camera; 4 | flyTo: (tween: any, controls: ControlType, option: FlyToParams) => any; 5 | } 6 | export type ViewerCamera = CameraType; 7 | -------------------------------------------------------------------------------- /Threejs/types/module/render.ts: -------------------------------------------------------------------------------- 1 | export interface RenderType { 2 | renderer: THREE.Renderer; 3 | } 4 | 5 | export interface ViewerRender { 6 | domElement: HTMLElement; 7 | render: (scene: THREE.Scene, camera: THREE.Scene) => void; 8 | [key: string]: any; 9 | } 10 | -------------------------------------------------------------------------------- /lib/types/module/render.d.ts: -------------------------------------------------------------------------------- 1 | export interface RenderType { 2 | renderer: THREE.Renderer; 3 | } 4 | export interface ViewerRender { 5 | domElement: HTMLElement; 6 | render: (scene: THREE.Scene, camera: THREE.Scene) => void; 7 | [key: string]: any; 8 | } 9 | -------------------------------------------------------------------------------- /lib/plugins/animate.d.ts: -------------------------------------------------------------------------------- 1 | import { AnimateType } from "../types/types"; 2 | export declare class Animate implements AnimateType { 3 | frameId: any; 4 | animateFuntion: Array; 5 | private clock; 6 | constructor(options: any); 7 | private init; 8 | } 9 | -------------------------------------------------------------------------------- /lib/types/module/ambient.d.ts: -------------------------------------------------------------------------------- 1 | export interface AmbientType { 2 | setLight: (exposure: number, intensity: number) => void; 3 | } 4 | export interface AmbientParams { 5 | scene: THREE.Scene; 6 | renderer: THREE.WebGLRenderer; 7 | } 8 | export type ViewerAmbient = AmbientType; 9 | -------------------------------------------------------------------------------- /Threejs/types/module/ambient.ts: -------------------------------------------------------------------------------- 1 | export interface AmbientType { 2 | setLight: (exposure: number, intensity: number) => void; 3 | } 4 | export interface AmbientParams { 5 | scene: THREE.Scene; 6 | renderer: THREE.WebGLRenderer; 7 | } 8 | 9 | export type ViewerAmbient = AmbientType; 10 | -------------------------------------------------------------------------------- /lib/plugins/sprite.d.ts: -------------------------------------------------------------------------------- 1 | import { SpriteType, SpriteParams } from "../types/types"; 2 | import { Object3D } from "./object"; 3 | export declare class Sprite extends Object3D implements SpriteType { 4 | sprite: THREE.Sprite; 5 | constructor(); 6 | init(options: SpriteParams): void; 7 | } 8 | -------------------------------------------------------------------------------- /lib/plugins/fog.d.ts: -------------------------------------------------------------------------------- 1 | import { FogType } from "../types/types"; 2 | export declare class Fog implements FogType { 3 | private scene; 4 | constructor(scene: THREE.Scene); 5 | initFog(color: string, near: number, far: number): void; 6 | initFogExp(color: string, density: number): void; 7 | } 8 | -------------------------------------------------------------------------------- /lib/plugins/camera.d.ts: -------------------------------------------------------------------------------- 1 | import { CameraType } from "../types/types"; 2 | export declare class Camera implements CameraType { 3 | camera: THREE.Camera; 4 | private el; 5 | constructor(el: HTMLElement); 6 | private init; 7 | flyTo(TWEEN: any, controls: any, option: FlyToParams): any; 8 | } 9 | -------------------------------------------------------------------------------- /lib/plugins/lights/ambient.d.ts: -------------------------------------------------------------------------------- 1 | import { AmbientParams, AmbientType } from "../../types/types"; 2 | export declare class Ambient implements AmbientType { 3 | private scene; 4 | private renderer; 5 | constructor(options: AmbientParams); 6 | setLight(exposure: number, intensity: number): void; 7 | } 8 | -------------------------------------------------------------------------------- /Threejs/types/module/source.ts: -------------------------------------------------------------------------------- 1 | interface loadTextureParams { 2 | path: string; 3 | onLoad?: Fn; 4 | onProgress?: Fn; 5 | onError?: Fn; 6 | } 7 | 8 | export interface SourceType { 9 | loadTexture: FnParamsReturn; 10 | } 11 | 12 | export type ViewerSource = SourceType; 13 | -------------------------------------------------------------------------------- /lib/types/module/point.d.ts: -------------------------------------------------------------------------------- 1 | export interface PointLightType { 2 | light: THREE.PointLight; 3 | helper: THREE.PointLightHelper; 4 | init: (color: string, intensity: number, distance: number, decay?: number) => THREE.PointLight; 5 | initHelper: FnParamsReturn; 6 | destory: Fn; 7 | } 8 | -------------------------------------------------------------------------------- /Threejs/types/module/environment.ts: -------------------------------------------------------------------------------- 1 | export interface EnvtType { 2 | environment: EnvironmentType; 3 | init: Fn; 4 | } 5 | export interface EnvironmentParams { 6 | renderer: THREE.WebGLRenderer; 7 | path: string; 8 | scene: THREE.Scene; 9 | environment: EnvironmentType; 10 | } 11 | export type ViewerEnvironment = EnvtType; 12 | -------------------------------------------------------------------------------- /lib/types/module/source.d.ts: -------------------------------------------------------------------------------- 1 | interface loadTextureParams { 2 | path: string; 3 | onLoad?: Fn; 4 | onProgress?: Fn; 5 | onError?: Fn; 6 | } 7 | export interface SourceType { 8 | loadTexture: FnParamsReturn; 9 | } 10 | export type ViewerSource = SourceType; 11 | export {}; 12 | -------------------------------------------------------------------------------- /Threejs/types/module/skyLight.ts: -------------------------------------------------------------------------------- 1 | export interface SkyLightType { 2 | light: THREE.HemisphereLight; 3 | helper: THREE.HemisphereLightHelper; 4 | init: FnThreeParams; 5 | initHelper: FnParamsReturn; 6 | destory: Fn; 7 | } 8 | 9 | export type ViewerSkyLight = SkyLightType; 10 | -------------------------------------------------------------------------------- /lib/types/module/skyLight.d.ts: -------------------------------------------------------------------------------- 1 | export interface SkyLightType { 2 | light: THREE.HemisphereLight; 3 | helper: THREE.HemisphereLightHelper; 4 | init: FnThreeParams; 5 | initHelper: FnParamsReturn; 6 | destory: Fn; 7 | } 8 | export type ViewerSkyLight = SkyLightType; 9 | -------------------------------------------------------------------------------- /Threejs/types/module/directional.ts: -------------------------------------------------------------------------------- 1 | export interface DirectionalType { 2 | light: THREE.DirectionalLight; 3 | helper: THREE.DirectionalLightHelper; 4 | init: FnTwoParams; 5 | initHelper: FnParamsReturn; 6 | destory: Fn; 7 | } 8 | 9 | export type ViewerDirectional = DirectionalType; 10 | -------------------------------------------------------------------------------- /Threejs/types/module/point.ts: -------------------------------------------------------------------------------- 1 | export interface PointLightType { 2 | light: THREE.PointLight; 3 | helper: THREE.PointLightHelper; 4 | init: ( 5 | color: string, 6 | intensity: number, 7 | distance: number, 8 | decay?: number 9 | ) => THREE.PointLight; 10 | initHelper: FnParamsReturn; 11 | destory: Fn; 12 | } 13 | -------------------------------------------------------------------------------- /lib/types/module/directional.d.ts: -------------------------------------------------------------------------------- 1 | export interface DirectionalType { 2 | light: THREE.DirectionalLight; 3 | helper: THREE.DirectionalLightHelper; 4 | init: FnTwoParams; 5 | initHelper: FnParamsReturn; 6 | destory: Fn; 7 | } 8 | export type ViewerDirectional = DirectionalType; 9 | -------------------------------------------------------------------------------- /lib/types/module/spot.d.ts: -------------------------------------------------------------------------------- 1 | export interface SpotType { 2 | light: THREE.SpotLight; 3 | helper: THREE.SpotLightHelper; 4 | init: (color: string, intensity: number, distance: number, target?: THREE.Vector3) => THREE.SpotLight; 5 | initHelper: FnParamsReturn; 6 | destory: Fn; 7 | } 8 | export type ViewerSpot = SpotType; 9 | -------------------------------------------------------------------------------- /lib/types/module/environment.d.ts: -------------------------------------------------------------------------------- 1 | export interface EnvtType { 2 | environment: EnvironmentType; 3 | init: Fn; 4 | } 5 | export interface EnvironmentParams { 6 | renderer: THREE.WebGLRenderer; 7 | path: string; 8 | scene: THREE.Scene; 9 | environment: EnvironmentType; 10 | } 11 | export type ViewerEnvironment = EnvtType; 12 | -------------------------------------------------------------------------------- /lib/plugins/source.d.ts: -------------------------------------------------------------------------------- 1 | import { SourceType } from "../types/types"; 2 | export declare class Source implements SourceType { 3 | private textureLoader; 4 | constructor(); 5 | loadTexture({ path, onLoad, onProgress, onError }: { 6 | path: any; 7 | onLoad: any; 8 | onProgress: any; 9 | onError: any; 10 | }): any; 11 | } 12 | -------------------------------------------------------------------------------- /Threejs/types/module/control.ts: -------------------------------------------------------------------------------- 1 | export interface ControlType { 2 | orbitControls: any; 3 | transformControls: any; 4 | initTransform: FnParamsReturn; 5 | initDrag: Fn; 6 | } 7 | export interface ControlParams { 8 | camera: THREE.Camera; 9 | renderer: THREE.WebGLRenderer; 10 | scene: THREE.Scene[]; 11 | } 12 | 13 | export type ViewerControl = ControlType; 14 | -------------------------------------------------------------------------------- /Threejs/types/module/spot.ts: -------------------------------------------------------------------------------- 1 | export interface SpotType { 2 | light: THREE.SpotLight; 3 | helper: THREE.SpotLightHelper; 4 | init: ( 5 | color: string, 6 | intensity: number, 7 | distance: number, 8 | target?: THREE.Vector3 9 | ) => THREE.SpotLight; 10 | initHelper: FnParamsReturn; 11 | destory: Fn; 12 | } 13 | 14 | export type ViewerSpot = SpotType; 15 | -------------------------------------------------------------------------------- /lib/types/module/control.d.ts: -------------------------------------------------------------------------------- 1 | export interface ControlType { 2 | orbitControls: any; 3 | transformControls: any; 4 | initTransform: FnParamsReturn; 5 | initDrag: Fn; 6 | } 7 | export interface ControlParams { 8 | camera: THREE.Camera; 9 | renderer: THREE.WebGLRenderer; 10 | scene: THREE.Scene[]; 11 | } 12 | export type ViewerControl = ControlType; 13 | -------------------------------------------------------------------------------- /lib/plugins/skybox.d.ts: -------------------------------------------------------------------------------- 1 | import { SkyParams, SkyType, ShaderSkyParams } from "../types/types"; 2 | export declare class Sky implements SkyType { 3 | private path; 4 | private sceneidx; 5 | private gSkyBox; 6 | private gScenes; 7 | sky: THREE.Object3D; 8 | constructor(options: SkyParams); 9 | setSkyBox(skydir: string): void; 10 | initShaderSky(option: ShaderSkyParams): void; 11 | } 12 | -------------------------------------------------------------------------------- /lib/plugins/environment.d.ts: -------------------------------------------------------------------------------- 1 | import { EnvironmentParams, EnvtType } from "../types/types"; 2 | export declare class Environment implements EnvtType { 3 | private pmremGenerator; 4 | private path; 5 | private scene; 6 | environment: EnvironmentType; 7 | constructor(options: EnvironmentParams); 8 | init(): void; 9 | private loadHdr; 10 | private loadExr; 11 | private getCubeMapTexture; 12 | } 13 | -------------------------------------------------------------------------------- /Threejs/plugins/source.ts: -------------------------------------------------------------------------------- 1 | import { TextureLoader } from "three"; 2 | import { SourceType } from "../types/types"; 3 | export class Source implements SourceType { 4 | private textureLoader: THREE.TextureLoader; 5 | constructor() { 6 | this.textureLoader = new TextureLoader(); 7 | } 8 | loadTexture({ path, onLoad, onProgress, onError }): any { 9 | return this.textureLoader.load(path, onLoad, onProgress, onError); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/plugins/lights/skyLight.d.ts: -------------------------------------------------------------------------------- 1 | import { SkyLightType } from "../../types/types"; 2 | export declare class SkyLight implements SkyLightType { 3 | private scene; 4 | light: THREE.HemisphereLight; 5 | helper: THREE.HemisphereLightHelper; 6 | constructor(scene: THREE.Scene); 7 | init(skyColor: string, earthColor: string, intensity: number): THREE.HemisphereLight; 8 | initHelper(size: number): void; 9 | destory(): void; 10 | } 11 | -------------------------------------------------------------------------------- /lib/plugins/control.d.ts: -------------------------------------------------------------------------------- 1 | import { ControlParams, ControlType } from "../types/types"; 2 | export declare class Control implements ControlType { 3 | orbitControls: any; 4 | transformControls: any; 5 | private camera; 6 | private renderer; 7 | private scene; 8 | constructor(options: ControlParams); 9 | private init; 10 | private initOrbit; 11 | initTransform(index: number): void; 12 | initDrag(objects: any): void; 13 | } 14 | -------------------------------------------------------------------------------- /lib/types/module/rectArea.d.ts: -------------------------------------------------------------------------------- 1 | export interface RectAreaType { 2 | light: THREE.RectAreaLight; 3 | areaLight: THREE.Group; 4 | init: (color: string, width: number, height: number, intensity: number) => void; 5 | initArea: (color: string, width: number, intensity: number, position: [number, number, number]) => void; 6 | initHelper: Fn; 7 | initBoxHelper: Fn; 8 | destory: Fn; 9 | } 10 | export type ViewerRectArea = RectAreaType; 11 | -------------------------------------------------------------------------------- /lib/plugins/lights/spot.d.ts: -------------------------------------------------------------------------------- 1 | import { SpotType } from "../../types/types"; 2 | export declare class SpotLight implements SpotType { 3 | private scene; 4 | light: THREE.SpotLight; 5 | helper: THREE.SpotLightHelper; 6 | shadowMass: number; 7 | constructor(scene: THREE.Scene); 8 | init(color: string, intensity: number, distance: number, target?: THREE.Vector3): THREE.SpotLight; 9 | initHelper(size: number): void; 10 | destory(): void; 11 | } 12 | -------------------------------------------------------------------------------- /Threejs/types/module/sky.ts: -------------------------------------------------------------------------------- 1 | export interface SkyType { 2 | sky: THREE.Object3D; 3 | setSkyBox: (skydir: string) => void; 4 | initShaderSky: (params: ShaderSkyParams) => void; 5 | } 6 | export interface SkyParams { 7 | path: string; 8 | sceneidx: number; 9 | gScenes: THREE.Scene[]; 10 | } 11 | export interface ShaderSkyParams { 12 | scale: number; 13 | turbidity: number; 14 | rayleigh: number; 15 | postion: number[]; 16 | } 17 | 18 | export type ViewerSky = SkyType; 19 | -------------------------------------------------------------------------------- /lib/plugins/lights/point.d.ts: -------------------------------------------------------------------------------- 1 | import { PointLightType } from "../../types/types"; 2 | export declare class PointLight implements PointLightType { 3 | private scene; 4 | light: THREE.PointLight; 5 | helper: THREE.PointLightHelper; 6 | shadowMass: number; 7 | constructor(scene: THREE.Scene); 8 | init(color: string, intensity: number, distance: number, decay?: number): THREE.PointLight; 9 | initHelper(size: number): void; 10 | destory(): void; 11 | } 12 | -------------------------------------------------------------------------------- /lib/plugins/event.d.ts: -------------------------------------------------------------------------------- 1 | import { EventType, EventParams } from "../types/types"; 2 | export declare class Event implements EventType { 3 | types: EventTypes[]; 4 | typesFn: { 5 | [P in EventTypes]?: Fn[]; 6 | }; 7 | private el; 8 | private mouse; 9 | private camera; 10 | private scene; 11 | private raycaster; 12 | constructor(options: EventParams); 13 | init(): void; 14 | private getIntersectObject; 15 | } 16 | -------------------------------------------------------------------------------- /Threejs/plugins/fog.ts: -------------------------------------------------------------------------------- 1 | import { FogExp2, Fog as TFog } from "three"; 2 | import { FogType } from "../types/types"; 3 | export class Fog implements FogType { 4 | private scene: THREE.Scene; 5 | constructor(scene: THREE.Scene) { 6 | this.scene = scene; 7 | } 8 | initFog(color: string, near: number, far: number) { 9 | this.scene.fog = new TFog(color, near, far); 10 | } 11 | initFogExp(color: string, density: number) { 12 | this.scene.fog = new FogExp2(color, density); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Threejs/types/module/event.ts: -------------------------------------------------------------------------------- 1 | export interface EventType { 2 | init: Fn; 3 | } 4 | 5 | export interface EventParams { 6 | types: EventTypes[]; 7 | typesFn?: { 8 | [P in EventTypes]?: Fn[]; 9 | }; 10 | el: HTMLElement; 11 | scene: THREE.Group; 12 | camera: THREE.Camera; 13 | } 14 | 15 | export interface ViewerEvent { 16 | types: EventTypes[]; 17 | typesFn?: { 18 | [P in EventTypes]?: Fn[]; 19 | }; 20 | init: Fn; 21 | } 22 | -------------------------------------------------------------------------------- /Threejs/types/module/particle.ts: -------------------------------------------------------------------------------- 1 | export interface ParticleType { 2 | position: THREE.Vector3; 3 | velocity: THREE.Vector3; 4 | acceleration: THREE.Vector3; 5 | angle: number; 6 | angleVelocity: number; 7 | angleAcceleration: number; 8 | size: number; 9 | color: THREE.Color; 10 | opacity: number; 11 | age: number; 12 | alive: number; 13 | update: FnParamsReturn; 14 | } 15 | export interface ParticleParams { 16 | mugen: boolean; 17 | scene: THREE.Scene; 18 | } 19 | -------------------------------------------------------------------------------- /lib/plugins/lights/directional.d.ts: -------------------------------------------------------------------------------- 1 | import { DirectionalType } from "../../types/types"; 2 | export declare class Directional implements DirectionalType { 3 | private scene; 4 | light: THREE.DirectionalLight; 5 | helper: THREE.DirectionalLightHelper; 6 | scope: number; 7 | shadowMass: number; 8 | constructor(scene: THREE.Scene); 9 | init(color: string, intensity: number): THREE.DirectionalLight; 10 | initHelper(size: number): void; 11 | destory(): void; 12 | } 13 | -------------------------------------------------------------------------------- /lib/types/module/sky.d.ts: -------------------------------------------------------------------------------- 1 | export interface SkyType { 2 | sky: THREE.Object3D; 3 | setSkyBox: (skydir: string) => void; 4 | initShaderSky: (params: ShaderSkyParams) => void; 5 | } 6 | export interface SkyParams { 7 | path: string; 8 | sceneidx: number; 9 | gScenes: THREE.Scene[]; 10 | } 11 | export interface ShaderSkyParams { 12 | scale: number; 13 | turbidity: number; 14 | rayleigh: number; 15 | postion: number[]; 16 | } 17 | export type ViewerSky = SkyType; 18 | -------------------------------------------------------------------------------- /lib/types/module/event.d.ts: -------------------------------------------------------------------------------- 1 | export interface EventType { 2 | init: Fn; 3 | } 4 | export interface EventParams { 5 | types: EventTypes[]; 6 | typesFn?: { 7 | [P in EventTypes]?: Fn[]; 8 | }; 9 | el: HTMLElement; 10 | scene: THREE.Group; 11 | camera: THREE.Camera; 12 | } 13 | export interface ViewerEvent { 14 | types: EventTypes[]; 15 | typesFn?: { 16 | [P in EventTypes]?: Fn[]; 17 | }; 18 | init: Fn; 19 | } 20 | -------------------------------------------------------------------------------- /lib/types/module/particle.d.ts: -------------------------------------------------------------------------------- 1 | export interface ParticleType { 2 | position: THREE.Vector3; 3 | velocity: THREE.Vector3; 4 | acceleration: THREE.Vector3; 5 | angle: number; 6 | angleVelocity: number; 7 | angleAcceleration: number; 8 | size: number; 9 | color: THREE.Color; 10 | opacity: number; 11 | age: number; 12 | alive: number; 13 | update: FnParamsReturn; 14 | } 15 | export interface ParticleParams { 16 | mugen: boolean; 17 | scene: THREE.Scene; 18 | } 19 | -------------------------------------------------------------------------------- /Threejs/plugins/animate.ts: -------------------------------------------------------------------------------- 1 | import { AnimateType } from "../types/types"; 2 | 3 | export class Animate implements AnimateType { 4 | frameId: any; 5 | animateFuntion: Array; 6 | private clock: THREE.Clock; 7 | constructor(options) { 8 | this.clock = options.clock; 9 | this.animateFuntion = []; 10 | this.init(); 11 | } 12 | private init() { 13 | this.frameId = requestAnimationFrame(this.init.bind(this)); 14 | const delta = this.clock.getDelta(); 15 | this.animateFuntion.forEach((fn) => fn(delta)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Threejs/types/module/rectArea.ts: -------------------------------------------------------------------------------- 1 | export interface RectAreaType { 2 | light: THREE.RectAreaLight; 3 | areaLight: THREE.Group; 4 | init: ( 5 | color: string, 6 | width: number, 7 | height: number, 8 | intensity: number 9 | ) => void; 10 | initArea: ( 11 | color: string, 12 | width: number, 13 | intensity: number, 14 | position: [number, number, number] 15 | ) => void; 16 | initHelper: Fn; 17 | initBoxHelper: Fn; 18 | destory: Fn; 19 | } 20 | 21 | export type ViewerRectArea = RectAreaType; 22 | -------------------------------------------------------------------------------- /lib/plugins/lights/rectArea.d.ts: -------------------------------------------------------------------------------- 1 | import { RectAreaType } from "../../types/types"; 2 | export declare class RectArea implements RectAreaType { 3 | private scene; 4 | light: THREE.RectAreaLight; 5 | areaLight: THREE.Group; 6 | helper: any; 7 | constructor(scene: THREE.Scene); 8 | init(color: string, width: number, height: number, intensity: number): void; 9 | initArea(color: string, width: number, intensity: number, position: [number, number, number]): void; 10 | initHelper(): void; 11 | initBoxHelper(): void; 12 | destory(): void; 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mool3d", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "main": "lib/index.js", 7 | "types": "./lib/index.d.ts", 8 | "scripts": { 9 | "build": "babel src -d lib --bundleConfigAsCjs", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "@types/three": "^0.149.0", 17 | "axios": "^0.26.1", 18 | "three": "^0.148.0", 19 | "typescript": "^4.6.3" 20 | }, 21 | "dependencies": {} 22 | } 23 | -------------------------------------------------------------------------------- /lib/plugins/water.d.ts: -------------------------------------------------------------------------------- 1 | import { WaterParams, WaterType, WaterShaderParams } from "../types/types"; 2 | export declare class Water implements WaterType { 3 | private texture; 4 | private scene; 5 | private animate; 6 | water: WaterShaderParams; 7 | private radius; 8 | private textureWidth; 9 | private textureHeight; 10 | private sunPosition; 11 | private sunColor; 12 | private waterColor; 13 | private distortionScale; 14 | private waterPosition; 15 | time: number; 16 | constructor(options: WaterParams); 17 | init(): void; 18 | destroy(): void; 19 | } 20 | -------------------------------------------------------------------------------- /lib/plugins/particle.d.ts: -------------------------------------------------------------------------------- 1 | import { ParticleType } from "../types/types"; 2 | export declare class Particle implements ParticleType { 3 | position: THREE.Vector3; 4 | velocity: THREE.Vector3; 5 | acceleration: THREE.Vector3; 6 | angle: number; 7 | angleVelocity: number; 8 | angleAcceleration: number; 9 | size: number; 10 | color: THREE.Color; 11 | opacity: number; 12 | age: number; 13 | alive: number; 14 | sizeTween: ParticleTween; 15 | colorTween: ParticleTween; 16 | opacityTween: ParticleTween; 17 | constructor(); 18 | update(dt: number): void; 19 | } 20 | -------------------------------------------------------------------------------- /lib/shader/sky.d.ts: -------------------------------------------------------------------------------- 1 | import { Mesh } from "three"; 2 | /** 3 | * Based on "A Practical Analytic Model for Daylight" 4 | * aka The Preetham Model, the de facto standard analytic skydome model 5 | * https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight 6 | * 7 | * First implemented by Simon Wallner 8 | * http://simonwallner.at/project/atmospheric-scattering/ 9 | * 10 | * Improved by Martin Upitis 11 | * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR 12 | * 13 | * Three.js integration by zz85 http://twitter.com/blurspline 14 | */ 15 | declare class Sky extends Mesh { 16 | isSky: boolean; 17 | constructor(); 18 | } 19 | export { Sky }; 20 | -------------------------------------------------------------------------------- /lib/shader/water.d.ts: -------------------------------------------------------------------------------- 1 | import { Mesh, Vector3 } from "three"; 2 | /** 3 | * Work based on : 4 | * https://github.com/Slayvin: Flat mirror for three.js 5 | * https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror 6 | * http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL 7 | */ 8 | declare class Water extends Mesh { 9 | isWater: boolean; 10 | material: THREE.ShaderMaterial; 11 | constructor(geometry: any, options?: any); 12 | } 13 | declare const City: { 14 | uniforms: { 15 | iTime: { 16 | value: number; 17 | }; 18 | iResolution: { 19 | value: Vector3; 20 | }; 21 | }; 22 | vertexShader: string; 23 | fragmentShader: string; 24 | }; 25 | export { Water, City }; 26 | -------------------------------------------------------------------------------- /Threejs/plugins/sprite.ts: -------------------------------------------------------------------------------- 1 | import { Sprite as TSprite, SpriteMaterial, FrontSide } from "three"; 2 | import { SpriteType, SpriteParams } from "../types/types"; 3 | import { Object3D } from "./object"; 4 | export class Sprite extends Object3D implements SpriteType { 5 | sprite: THREE.Sprite; 6 | constructor() { 7 | super(); 8 | } 9 | init(options: SpriteParams) { 10 | this.sprite = new TSprite( 11 | new SpriteMaterial({ 12 | map: options.texture, 13 | side: FrontSide, 14 | transparent: true, 15 | depthWrite: false, 16 | sizeAttenuation: false, 17 | toneMapped: false, 18 | }) 19 | ); 20 | this.sprite.name = options.name; 21 | this.sprite.renderOrder = 10000; 22 | this.sprite.geometry.computeBoundingBox(); 23 | this.sprite.geometry.center(); 24 | this.attach(this.sprite); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/plugins/parade.d.ts: -------------------------------------------------------------------------------- 1 | import { ParadeType, ParadeParams } from "../types/types"; 2 | export declare class Parade implements ParadeType { 3 | private pipeTexture; 4 | private pipeParams; 5 | private scene; 6 | private animate; 7 | private callback; 8 | curve: THREE.CatmullRomCurve3; 9 | pipeLine: THREE.Mesh; 10 | stop: boolean; 11 | progress: number; 12 | speed: number; 13 | direction: string; 14 | loop: boolean; 15 | object: THREE.Object3D; 16 | constructor(options: ParadeParams); 17 | drawPipeLine(pipeLineArr: THREE.Vector3[]): void; 18 | private initCurve; 19 | private initPipe; 20 | clear(): void; 21 | autoParade(callback: (type: string, value: { 22 | point: THREE.Vector3; 23 | pointLook: THREE.Vector3; 24 | }) => void): void; 25 | private run; 26 | } 27 | -------------------------------------------------------------------------------- /Threejs/plugins/lights/ambient.ts: -------------------------------------------------------------------------------- 1 | import { AmbientLight } from "three"; 2 | import { AmbientParams, AmbientType } from "../../types/types"; 3 | export class Ambient implements AmbientType { 4 | private scene: THREE.Scene; 5 | private renderer: THREE.WebGLRenderer; 6 | constructor(options: AmbientParams) { 7 | this.scene = options.scene; 8 | this.renderer = options.renderer; 9 | } 10 | setLight(exposure: number, intensity: number) { 11 | this.renderer.toneMappingExposure = exposure; 12 | const obj3d = this.scene.getObjectByName("ambient_light"); 13 | 14 | if (obj3d === undefined) { 15 | console.log(obj3d); 16 | const light = new AmbientLight(0xffffff, exposure); 17 | light.name = "ambient_light"; 18 | this.scene.add(light); 19 | } else { 20 | if (obj3d instanceof AmbientLight) { 21 | obj3d.intensity = intensity; 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Threejs/plugins/lights/skyLight.ts: -------------------------------------------------------------------------------- 1 | import { HemisphereLight, HemisphereLightHelper } from "three"; 2 | import { SkyLightType } from "../../types/types"; 3 | export class SkyLight implements SkyLightType { 4 | private scene: THREE.Scene; 5 | light: THREE.HemisphereLight; 6 | helper: THREE.HemisphereLightHelper; 7 | constructor(scene: THREE.Scene) { 8 | this.scene = scene; 9 | } 10 | init( 11 | skyColor: string, 12 | earthColor: string, 13 | intensity: number 14 | ): THREE.HemisphereLight { 15 | this.light = new HemisphereLight(skyColor, earthColor, intensity); 16 | this.scene.add(this.light); 17 | return this.light; 18 | } 19 | initHelper(size: number) { 20 | this.helper = new HemisphereLightHelper(this.light, size); 21 | this.scene.add(this.helper); 22 | } 23 | destory() { 24 | this.scene.remove(this.helper); 25 | this.scene.remove(this.light); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Threejs/plugins/particleTween.ts: -------------------------------------------------------------------------------- 1 | import { Vector3 } from "three"; 2 | export class Tween implements ParticleTween { 3 | times: number[]; 4 | values: THREE.Vector3 | number[]; 5 | constructor(timeArray = [], valueArray = []) { 6 | this.times = timeArray || []; 7 | this.values = valueArray || []; 8 | } 9 | lerp(t: number) { 10 | var i = 0; 11 | var n = this.times.length; 12 | while (i < n && t > this.times[i]) { 13 | i++; 14 | } 15 | if (i == 0) { 16 | return this.values[0]; 17 | } 18 | if (i == n) { 19 | return this.values[n - 1]; 20 | } 21 | var p = (t - this.times[i - 1]) / (this.times[i] - this.times[i - 1]); 22 | if (this.values[0] instanceof Vector3) { 23 | return this.values[i - 1].clone().lerp(this.values[i], p); 24 | } // its a float 25 | else { 26 | return this.values[i - 1] + p * (this.values[i] - this.values[i - 1]); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/types/module/model.d.ts: -------------------------------------------------------------------------------- 1 | export interface ModelType { 2 | mixer: THREE.AnimationMixer; 3 | animate: boolean; 4 | deepFunction: Fn<{ 5 | e: THREE.Mesh; 6 | item: ModelConfig; 7 | }>[]; 8 | load: (idx: number, callback?: Fn) => void; 9 | loadModel: (url: string, sceneidx: number, callback: FnTwoParams) => void; 10 | loadFbxModel: (url: string, sceneidx: number, callback: FnTwoParams) => void; 11 | playAllClipes: (idx: number) => void; 12 | playNameClipes: (idx: number, clipName: string) => void; 13 | } 14 | export interface ModelParams { 15 | gScenes: THREE.Scene[]; 16 | gStatus: boolean[]; 17 | gAmGroup: THREE.Group[]; 18 | gRayGroup: THREE.Group[]; 19 | baseURL: string; 20 | bus: any; 21 | animateFuntion: Fn[]; 22 | } 23 | export type ViewerModel = ModelType; 24 | -------------------------------------------------------------------------------- /Threejs/types/module/parade.ts: -------------------------------------------------------------------------------- 1 | export interface ParadeType { 2 | curve: THREE.CatmullRomCurve3; //曲线 3 | pipeLine: THREE.Mesh; //管道实例 4 | stop: boolean; //暂停 5 | progress: number; //进度 6 | speed: number; //速度 7 | direction: string; //方向 8 | loop: boolean; //是否循环 9 | object: THREE.Object3D; //物体 10 | drawPipeLine: Fn; 11 | clear: Fn; 12 | autoParade: Fn< 13 | ( 14 | type: string, 15 | value: { point: THREE.Vector3; pointLook: THREE.Vector3 } 16 | ) => void 17 | >; 18 | } 19 | 20 | export interface ParadeParams { 21 | pipeParams: PipeParams; 22 | loop?: boolean; 23 | pipeTexture: THREE.Texture; 24 | scene: THREE.Scene; 25 | animate: Fn[]; 26 | speed: number; 27 | object: THREE.Object3D; 28 | } 29 | export interface PipeParams { 30 | tubularSegments: number; 31 | radius: number; 32 | radialSegments: number; 33 | closed: boolean; 34 | } 35 | 36 | export type ViewerParade = ParadeType; 37 | -------------------------------------------------------------------------------- /lib/types/module/parade.d.ts: -------------------------------------------------------------------------------- 1 | export interface ParadeType { 2 | curve: THREE.CatmullRomCurve3; 3 | pipeLine: THREE.Mesh; 4 | stop: boolean; 5 | progress: number; 6 | speed: number; 7 | direction: string; 8 | loop: boolean; 9 | object: THREE.Object3D; 10 | drawPipeLine: Fn; 11 | clear: Fn; 12 | autoParade: Fn<(type: string, value: { 13 | point: THREE.Vector3; 14 | pointLook: THREE.Vector3; 15 | }) => void>; 16 | } 17 | export interface ParadeParams { 18 | pipeParams: PipeParams; 19 | loop?: boolean; 20 | pipeTexture: THREE.Texture; 21 | scene: THREE.Scene; 22 | animate: Fn[]; 23 | speed: number; 24 | object: THREE.Object3D; 25 | } 26 | export interface PipeParams { 27 | tubularSegments: number; 28 | radius: number; 29 | radialSegments: number; 30 | closed: boolean; 31 | } 32 | export type ViewerParade = ParadeType; 33 | -------------------------------------------------------------------------------- /Threejs/types/module/model.ts: -------------------------------------------------------------------------------- 1 | export interface ModelType { 2 | mixer: THREE.AnimationMixer; 3 | animate: boolean; 4 | deepFunction: Fn<{ 5 | e: THREE.Mesh; 6 | item: ModelConfig; 7 | }>[]; 8 | load: (idx: number, callback?: Fn) => void; 9 | loadModel: ( 10 | url: string, 11 | sceneidx: number, 12 | callback: FnTwoParams 13 | ) => void; 14 | loadFbxModel: ( 15 | url: string, 16 | sceneidx: number, 17 | callback: FnTwoParams 18 | ) => void; 19 | playAllClipes: (idx: number) => void; 20 | playNameClipes: (idx: number, clipName: string) => void; 21 | } 22 | 23 | export interface ModelParams { 24 | gScenes: THREE.Scene[]; 25 | gStatus: boolean[]; 26 | gAmGroup: THREE.Group[]; 27 | gRayGroup: THREE.Group[]; 28 | baseURL: string; 29 | bus: any; 30 | animateFuntion: Fn[]; 31 | } 32 | 33 | export type ViewerModel = ModelType; 34 | -------------------------------------------------------------------------------- /lib/plugins/model.d.ts: -------------------------------------------------------------------------------- 1 | import { ModelType, ModelParams } from "../types/types"; 2 | export declare class Model implements ModelType { 3 | mixer: THREE.AnimationMixer; 4 | private gScenes; 5 | private gStatus; 6 | private gRayGroup; 7 | private gAmGroup; 8 | private baseURL; 9 | private bus; 10 | animate: boolean; 11 | deepFunction: Fn<{ 12 | e: THREE.Mesh; 13 | item: ModelConfig; 14 | }>[]; 15 | constructor(options: ModelParams); 16 | private getConfig; 17 | load(sceneidx: number, callback: Fn): void; 18 | private loadConfigModel; 19 | loadModel(url: string, sceneidx: number, callback: FnTwoParams): void; 20 | loadFbxModel(url: string, sceneidx: number, callback: FnTwoParams): void; 21 | private decodeSence; 22 | private addclips; 23 | playAllClipes(sceneidx: number): void; 24 | playNameClipes(sceneidx: number, clipName: string): void; 25 | } 26 | -------------------------------------------------------------------------------- /Threejs/types/module/water.ts: -------------------------------------------------------------------------------- 1 | export interface WaterType { 2 | time: number; 3 | water: WaterShaderParams; 4 | init: Fn; 5 | destroy: Fn; 6 | } 7 | export type WaterShaderParams = { 8 | material: THREE.ShaderMaterial; 9 | } & THREE.Mesh; 10 | 11 | export type ViewerWater = WaterType; 12 | export interface WaterParams { 13 | radius: number; 14 | textureWidth: number; 15 | textureHeight: number; 16 | sunPosition?: THREE.Vector3; 17 | sunColor?: string; 18 | waterColor?: string; 19 | distortionScale?: number; 20 | waterPosition?: THREE.Vector3; 21 | time: number; 22 | texture: THREE.TextureLoader; 23 | scene: THREE.Scene | THREE.Group; 24 | animate: Fn[]; 25 | } 26 | 27 | export interface InitWaterParams { 28 | radius: number; 29 | textureWidth: number; 30 | textureHeight: number; 31 | sunPosition?: THREE.Vector3; 32 | sunColor?: string; 33 | scene: THREE.Scene | THREE.Group; 34 | waterColor?: string; 35 | distortionScale?: number; 36 | waterPosition?: THREE.Vector3; 37 | time: number; 38 | texture: THREE.TextureLoader; 39 | } 40 | -------------------------------------------------------------------------------- /lib/types/module/water.d.ts: -------------------------------------------------------------------------------- 1 | export interface WaterType { 2 | time: number; 3 | water: WaterShaderParams; 4 | init: Fn; 5 | destroy: Fn; 6 | } 7 | export type WaterShaderParams = { 8 | material: THREE.ShaderMaterial; 9 | } & THREE.Mesh; 10 | export type ViewerWater = WaterType; 11 | export interface WaterParams { 12 | radius: number; 13 | textureWidth: number; 14 | textureHeight: number; 15 | sunPosition?: THREE.Vector3; 16 | sunColor?: string; 17 | waterColor?: string; 18 | distortionScale?: number; 19 | waterPosition?: THREE.Vector3; 20 | time: number; 21 | texture: THREE.TextureLoader; 22 | scene: THREE.Scene | THREE.Group; 23 | animate: Fn[]; 24 | } 25 | export interface InitWaterParams { 26 | radius: number; 27 | textureWidth: number; 28 | textureHeight: number; 29 | sunPosition?: THREE.Vector3; 30 | sunColor?: string; 31 | scene: THREE.Scene | THREE.Group; 32 | waterColor?: string; 33 | distortionScale?: number; 34 | waterPosition?: THREE.Vector3; 35 | time: number; 36 | texture: THREE.TextureLoader; 37 | } 38 | -------------------------------------------------------------------------------- /Threejs/plugins/render.ts: -------------------------------------------------------------------------------- 1 | import { 2 | WebGLRenderer, 3 | sRGBEncoding, 4 | ReinhardToneMapping, 5 | PCFSoftShadowMap, 6 | } from "three"; 7 | import { RenderType } from "../types/types"; 8 | export class Renderer implements RenderType { 9 | renderer: THREE.WebGLRenderer; 10 | private el: HTMLElement; 11 | constructor(el: HTMLElement) { 12 | this.renderer = null; 13 | this.el = el; 14 | this.init(); 15 | } 16 | private init() { 17 | this.renderer = new WebGLRenderer({ antialias: true }); 18 | this.renderer.physicallyCorrectLights = false; 19 | this.renderer.outputEncoding = sRGBEncoding; 20 | this.renderer.setClearColor(0x000000); 21 | this.renderer.setPixelRatio(window.devicePixelRatio); 22 | this.renderer.setSize(this.el.clientWidth, this.el.clientHeight); 23 | this.renderer.toneMapping = ReinhardToneMapping; 24 | //按序渲染 25 | this.renderer.sortObjects = true; 26 | this.renderer.shadowMap.enabled = true; 27 | this.renderer.shadowMap.type = PCFSoftShadowMap; //提高阴影的柔和度 28 | (this.renderer as any).gammaInput = true; 29 | (this.renderer as any).gammaOutput = true; //inear转gamma 30 | (this.renderer as any).gammaFactor = 2.2; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Threejs/threelibex/LoaderBase.js: -------------------------------------------------------------------------------- 1 | export class LoaderBase { 2 | constructor() { 3 | this.fetchOptions = {}; 4 | this.workingPath = ''; 5 | } 6 | 7 | load(url) { 8 | return fetch(url, this.fetchOptions) 9 | .then(res => { 10 | if (!res.ok) { 11 | throw new Error( 12 | `Failed to load file "${url}" with status ${res.status} : ${res.statusText}` 13 | ); 14 | } 15 | return res.arrayBuffer(); 16 | }) 17 | .then(buffer => { 18 | if (this.workingPath === '') { 19 | this.workingPath = this.workingPathForURL(url); 20 | } 21 | 22 | try { 23 | return this.parse(buffer); 24 | } catch (error) { 25 | console.log('buffer', error, url); 26 | } 27 | }); 28 | } 29 | 30 | resolveExternalURL(url) { 31 | if (/^[^\\/]/.test(url)) { 32 | return this.workingPath + '/' + url; 33 | } else { 34 | return url; 35 | } 36 | } 37 | 38 | workingPathForURL(url) { 39 | const splits = url.split(/[\\/]/g); 40 | splits.pop(); 41 | const workingPath = splits.join('/'); 42 | return workingPath + '/'; 43 | } 44 | 45 | parse(buffer) { 46 | throw new Error('LoaderBase: Parse not implemented.'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Threejs/plugins/lights/point.ts: -------------------------------------------------------------------------------- 1 | import { PointLight as Point, PointLightHelper } from "three"; 2 | import { PointLightType } from "../../types/types"; 3 | export class PointLight implements PointLightType { 4 | private scene: THREE.Scene; 5 | light: THREE.PointLight; 6 | helper: THREE.PointLightHelper; 7 | shadowMass: number; 8 | constructor(scene: THREE.Scene) { 9 | this.scene = scene; 10 | this.shadowMass = 2048; 11 | } 12 | init( 13 | color: string, 14 | intensity: number, 15 | distance: number, 16 | decay?: number 17 | ): THREE.PointLight { 18 | this.light = new Point(color, intensity, distance, decay); 19 | this.light.castShadow = true; 20 | this.light.shadow.camera.near = 10; 21 | this.light.shadow.camera.far = 8000; 22 | this.light.shadow.mapSize.x = this.shadowMass; // 定义阴影贴图的宽度和高度,必须为2的整数此幂 23 | this.light.shadow.mapSize.y = this.shadowMass; // 较高的值会以计算时间为代价提供更好的阴影质量 24 | // this.light.shadow.bias = -0.0005; //解决条纹阴影的出现 25 | this.scene.add(this.light); 26 | return this.light; 27 | } 28 | initHelper(size: number) { 29 | this.helper = new PointLightHelper(this.light, size); 30 | this.scene.add(this.helper); 31 | } 32 | destory() { 33 | this.scene.remove(this.helper); 34 | this.scene.remove(this.light); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/plugins/params.d.ts: -------------------------------------------------------------------------------- 1 | import { ViewerParams, ViewerAnimate, ViewerCamera, ViewerAmbient, ViewerEvent, ViewerModel, ViewerFog, ViewerControl, ViewerSky, ViewerEnvironment, ViewerSource, ViewerParade, ViewerWater, ViewerSkyLight, ViewerDirectional, PointLightType, ViewerSpot, ViewerRectArea } from "../types/types"; 2 | export declare class Params { 3 | clock: THREE.Clock; 4 | animate: ViewerAnimate; 5 | gAmGroup: THREE.Group[]; 6 | gRayGroup: THREE.Group[]; 7 | gScenes: THREE.Scene[]; 8 | gStatus: boolean[]; 9 | scene: THREE.Scene; 10 | model: ViewerModel; 11 | sceneidx: number; 12 | cameraClass: ViewerCamera; 13 | activeCamera: THREE.Camera; 14 | renderer: THREE.WebGLRenderer; 15 | controls: ViewerControl; 16 | ambient: ViewerAmbient; 17 | hemisphereLight: ViewerSkyLight; 18 | directional: ViewerDirectional; 19 | pointGroup: PointLightType[]; 20 | spotLight: ViewerSpot; 21 | rectAreaLight: ViewerRectArea; 22 | sky: ViewerSky; 23 | environment: ViewerEnvironment; 24 | event: ViewerEvent; 25 | souce: ViewerSource; 26 | parade: ViewerParade; 27 | spriteGroup: THREE.Object3D[]; 28 | fog: ViewerFog; 29 | water: ViewerWater; 30 | options: ViewerParams; 31 | constructor(options: ViewerParams); 32 | } 33 | -------------------------------------------------------------------------------- /lib/plugins/sceneRoam.d.ts: -------------------------------------------------------------------------------- 1 | import { RoamType } from "../types/types"; 2 | export declare class Roam implements RoamType { 3 | collider: THREE.Mesh; 4 | visualizer: any; 5 | player: THREE.Mesh; 6 | controls: any; 7 | camera: THREE.Camera; 8 | object: THREE.Object3D; 9 | environment: THREE.Group; 10 | scene: THREE.Scene; 11 | animate: Fn[]; 12 | playerIsOnGround: boolean; 13 | fwdPressed: boolean; 14 | bkdPressed: boolean; 15 | lftPressed: boolean; 16 | rgtPressed: boolean; 17 | playerVelocity: THREE.Vector3; 18 | upVector: THREE.Vector3; 19 | tempVector: THREE.Vector3; 20 | tempVector2: THREE.Vector3; 21 | tempBox: THREE.Box3; 22 | tempMat: THREE.Matrix4; 23 | tempSegment: THREE.Line3; 24 | clock: THREE.Clock; 25 | params: any; 26 | isRun: boolean; 27 | runCallback: Fn; 28 | angle: number; 29 | constructor(options: any); 30 | init(): void; 31 | loadColliderEnvironment(): void; 32 | loadplayer(): void; 33 | /** 34 | * @description 35 | * @author: yangj (yangjia@fjxhx.cc) 36 | * @createDate: 2022/3/1 37 | */ 38 | windowEvent(): void; 39 | /** 40 | * @description 重置 41 | * @author: yangj (yangjia@fjxhx.cc) 42 | * @createDate: 2022/3/1 43 | */ 44 | reset(): void; 45 | render(): void; 46 | updatePlayer(delta: any): void; 47 | } 48 | -------------------------------------------------------------------------------- /Threejs/plugins/lights/spot.ts: -------------------------------------------------------------------------------- 1 | import { SpotLight as Spot, SpotLightHelper, Object3D } from "three"; 2 | import { SpotType } from "../../types/types"; 3 | export class SpotLight implements SpotType { 4 | private scene: THREE.Scene; 5 | light: THREE.SpotLight; 6 | helper: THREE.SpotLightHelper; 7 | shadowMass: number; 8 | constructor(scene: THREE.Scene) { 9 | this.scene = scene; 10 | this.shadowMass = 2048; 11 | } 12 | init( 13 | color: string, 14 | intensity: number, 15 | distance: number, 16 | target?: THREE.Vector3 17 | ): THREE.SpotLight { 18 | this.light = new Spot(color, intensity, distance); 19 | this.light.castShadow = true; 20 | this.light.shadow.mapSize.width = 1024; 21 | this.light.shadow.mapSize.height = 1024; 22 | this.light.shadow.camera.near = 10; 23 | this.light.shadow.camera.fov = 10; 24 | this.light.shadow.camera.far = 8000; 25 | this.light.shadow.focus = 1; 26 | if (target) { 27 | const targetObject = new Object3D(); 28 | targetObject.position.copy(target); 29 | this.scene.add(targetObject); 30 | this.light.target = targetObject; 31 | } 32 | this.scene.add(this.light); 33 | return this.light; 34 | } 35 | initHelper(size: number) { 36 | this.helper = new SpotLightHelper(this.light, size); 37 | this.scene.add(this.helper); 38 | } 39 | destory() { 40 | this.scene.remove(this.helper); 41 | this.scene.remove(this.light); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/types/module/viewer.d.ts: -------------------------------------------------------------------------------- 1 | import { ParadeParams } from "./parade"; 2 | import { SpriteParams } from "./sprite"; 3 | import { WaterParams } from "./water"; 4 | export interface ViewerType { 5 | setScene: FnTwoParams, unknown>; 6 | initSky: Fn; 7 | initEnvironment: FnParamsReturn; 8 | initEvent: FnParamsReturn; 9 | initModel: Fn; 10 | flyTo: FnParamsReturn; 11 | initSource: Fn; 12 | initSkyLight: FnThreeParams; 13 | initDirectional: FnTwoParams; 14 | initPointLight: (color: string, intensity: number, distance: number, decay?: number) => number; 15 | initSpotLight: (color: string, intensity: number, distance: number, target: THREE.Vector3) => void; 16 | loadSprite: FnParamsReturn; 17 | initParade: FnParamsReturn; 18 | initParticleEngine: FnTwoParams; 19 | setParticleMode: FnThreeParams; 20 | getParticleTween: FnTwoParams; 21 | initWater: FnParamsReturn; 22 | destroy: Fn; 23 | } 24 | export interface ViewerParams { 25 | el: HTMLElement; 26 | tween: any; 27 | path: string; 28 | bus: any; 29 | } 30 | -------------------------------------------------------------------------------- /Threejs/types/module/viewer.ts: -------------------------------------------------------------------------------- 1 | import { ParadeParams } from "./parade"; 2 | import { SpriteParams } from "./sprite"; 3 | import { WaterParams } from "./water"; 4 | export interface ViewerType { 5 | setScene: FnTwoParams, unknown>; 6 | initSky: Fn; 7 | initEnvironment: FnParamsReturn; 8 | initEvent: FnParamsReturn; 9 | initModel: Fn; 10 | flyTo: FnParamsReturn; 11 | initSource: Fn; 12 | initSkyLight: FnThreeParams; 13 | initDirectional: FnTwoParams; 14 | initPointLight: ( 15 | color: string, 16 | intensity: number, 17 | distance: number, 18 | decay?: number 19 | ) => number; 20 | initSpotLight: ( 21 | color: string, 22 | intensity: number, 23 | distance: number, 24 | target: THREE.Vector3 25 | ) => void; 26 | loadSprite: FnParamsReturn; 27 | initParade: FnParamsReturn; 28 | initParticleEngine: FnTwoParams< 29 | ParticleEngineType, 30 | boolean, 31 | ParticleEngineType 32 | >; 33 | setParticleMode: FnThreeParams< 34 | ParticleEngineType, 35 | ParticleKeys, 36 | ParticleExamplesParams, 37 | unknown 38 | >; 39 | getParticleTween: FnTwoParams; 40 | initWater: FnParamsReturn; 41 | destroy: Fn; 42 | } 43 | 44 | export interface ViewerParams { 45 | el: HTMLElement; 46 | tween: any; 47 | path: string; 48 | bus: any; 49 | } 50 | -------------------------------------------------------------------------------- /Threejs/plugins/lights/directional.ts: -------------------------------------------------------------------------------- 1 | import { DirectionalType } from "../../types/types"; 2 | import { DirectionalLight, DirectionalLightHelper } from "three"; 3 | export class Directional implements DirectionalType { 4 | private scene: THREE.Scene; 5 | light: THREE.DirectionalLight; 6 | helper: THREE.DirectionalLightHelper; 7 | scope: number; 8 | shadowMass: number; 9 | constructor(scene: THREE.Scene) { 10 | this.scene = scene; 11 | this.scope = 100; 12 | this.shadowMass = 2048; 13 | } 14 | init(color: string, intensity: number): THREE.DirectionalLight { 15 | this.light = new DirectionalLight(color, intensity); 16 | this.light.castShadow = true; // 将此平行光源产生阴影的属性打开 17 | // 设置平行光的的阴影属性,即一个长方体的长宽高,在设定值的范围内的物体才会产生阴影 18 | const d = this.scope; 19 | this.light.shadow.camera.left = -d; 20 | this.light.shadow.camera.right = d; 21 | this.light.shadow.camera.top = d; 22 | this.light.shadow.camera.bottom = -d; 23 | this.light.shadow.camera.near = 10; 24 | this.light.shadow.camera.far = 8000; 25 | this.light.shadow.mapSize.x = this.shadowMass; // 定义阴影贴图的宽度和高度,必须为2的整数此幂 26 | this.light.shadow.mapSize.y = this.shadowMass; // 较高的值会以计算时间为代价提供更好的阴影质量 27 | // this.light.shadow.bias = -0.0005; //解决条纹阴影的出现 28 | this.scene.add(this.light); 29 | return this.light; 30 | } 31 | initHelper(size: number) { 32 | this.helper = new DirectionalLightHelper(this.light, size); 33 | this.scene.add(this.helper); 34 | } 35 | destory() { 36 | this.scene.remove(this.helper); 37 | this.scene.remove(this.light); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Threejs/shader/particle.ts: -------------------------------------------------------------------------------- 1 | const particleVertexShader = [ 2 | "attribute vec3 customColor;", 3 | "attribute float customOpacity;", 4 | "attribute float customSize;", 5 | "attribute float customAngle;", 6 | "attribute float customVisible;", // float used as boolean (0 = false, 1 = true) 7 | "varying vec4 vColor;", 8 | "varying float vAngle;", 9 | "void main()", 10 | "{", 11 | "if ( customVisible > 0.5 )", // true 12 | "vColor = vec4( customColor, customOpacity );", // set color associated to vertex; use later in fragment shader. 13 | "else", // false 14 | "vColor = vec4(0,0,0,0);", // make particle invisible. 15 | 16 | "vAngle = customAngle;", 17 | 18 | "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", 19 | "gl_PointSize = customSize * ( 300.0 / length( mvPosition.xyz ) );", // scale particles as objects in 3D space 20 | "gl_Position = projectionMatrix * mvPosition;", 21 | "}", 22 | ].join("\n"); 23 | 24 | const particleFragmentShader = [ 25 | "uniform sampler2D mytexture;", 26 | "varying vec4 vColor;", 27 | "varying float vAngle;", 28 | "void main()", 29 | "{", 30 | "gl_FragColor = vColor;", 31 | 32 | "float c = cos(vAngle);", 33 | "float s = sin(vAngle);", 34 | "vec2 rotatedUV = vec2(c * (gl_PointCoord.x - 0.5) + s * (gl_PointCoord.y - 0.5) + 0.5,", 35 | "c * (gl_PointCoord.y - 0.5) - s * (gl_PointCoord.x - 0.5) + 0.5);", // rotate UV coordinates to rotate texture 36 | "vec4 rotatedTexture = texture2D( mytexture, rotatedUV );", 37 | "gl_FragColor = gl_FragColor * rotatedTexture;", // sets an otherwise white particle texture to desired color 38 | "}", 39 | ].join("\n"); 40 | 41 | export { particleVertexShader, particleFragmentShader }; 42 | -------------------------------------------------------------------------------- /Threejs/threelibex/GLTFExtensionLoader.js: -------------------------------------------------------------------------------- 1 | import { DefaultLoadingManager } from "three"; 2 | import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; 3 | import { LoaderBase } from "./LoaderBase.js"; 4 | 5 | export class GLTFExtensionLoader extends LoaderBase { 6 | constructor(manager = DefaultLoadingManager) { 7 | super(); 8 | this.manager = manager; 9 | } 10 | 11 | parse(buffer) { 12 | return new Promise((resolve, reject) => { 13 | const manager = this.manager; 14 | const fetchOptions = this.fetchOptions; 15 | let loader = 16 | manager.getHandler("path.gltf") || manager.getHandler("path.glb"); 17 | 18 | if (!loader) { 19 | loader = new GLTFLoader(manager); 20 | if ( 21 | fetchOptions.credentials === "include" && 22 | fetchOptions.mode === "cors" 23 | ) { 24 | loader.setCrossOrigin("use-credentials"); 25 | } 26 | 27 | if ("credentials" in fetchOptions) { 28 | loader.setWithCredentials(fetchOptions.credentials === "include"); 29 | } 30 | 31 | if (fetchOptions.headers) { 32 | loader.setRequestHeader(fetchOptions.headers); 33 | } 34 | } 35 | 36 | // assume any pre-registered loader has paths configured as the user desires, but if we're making 37 | // a new loader, use the working path during parse to support relative uris on other hosts 38 | const resourcePath = 39 | loader.resourcePath || loader.path || this.workingPath; 40 | 41 | loader.parse( 42 | buffer, 43 | resourcePath, 44 | (model) => { 45 | resolve(model); 46 | }, 47 | reject 48 | ); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/shader/effect.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 预览模型 3 | */ 4 | import * as THREE from "three"; 5 | declare const _default: { 6 | effect1(): THREE.ShaderMaterial; 7 | effect2(): THREE.ShaderMaterial; 8 | effect3(): THREE.ShaderMaterial; 9 | effect4(): THREE.ShaderMaterial; 10 | effect5(): THREE.ShaderMaterial; 11 | effect6(): THREE.ShaderMaterial; 12 | effect7(): THREE.ShaderMaterial; 13 | effect8(): THREE.ShaderMaterial; 14 | effect9(): THREE.ShaderMaterial; 15 | effect10(): THREE.ShaderMaterial; 16 | effect11(): THREE.ShaderMaterial; 17 | effect12(): THREE.ShaderMaterial; 18 | effect13(): THREE.ShaderMaterial; 19 | effect14(): THREE.ShaderMaterial; 20 | effect15(): THREE.ShaderMaterial; 21 | effect16(): THREE.ShaderMaterial; 22 | effect17(): THREE.ShaderMaterial; 23 | effect18(): THREE.ShaderMaterial; 24 | effect118(): THREE.ShaderMaterial; 25 | effect19(): THREE.ShaderMaterial; 26 | effect20(): THREE.ShaderMaterial; 27 | effect21(): THREE.ShaderMaterial; 28 | effect22(): THREE.ShaderMaterial; 29 | effect23(): THREE.ShaderMaterial; 30 | effect24(): THREE.ShaderMaterial; 31 | effect25(): THREE.ShaderMaterial; 32 | effect26(): THREE.ShaderMaterial; 33 | effect27(): THREE.ShaderMaterial; 34 | effect28(): THREE.ShaderMaterial; 35 | effect29(): THREE.ShaderMaterial; 36 | effect30(): THREE.ShaderMaterial; 37 | effect31(): THREE.ShaderMaterial; 38 | effect32(): THREE.ShaderMaterial; 39 | effect33(): THREE.ShaderMaterial; 40 | effect34(): THREE.ShaderMaterial; 41 | effect35(): THREE.ShaderMaterial; 42 | effect36(): THREE.ShaderMaterial; 43 | }; 44 | export default _default; 45 | -------------------------------------------------------------------------------- /lib/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ViewerType, ViewerParams, SpriteParams, ParadeParams, InitWaterParams } from "./types/types"; 2 | import { Params } from "./plugins/params"; 3 | export declare class Viewer extends Params implements ViewerType { 4 | constructor(options: ViewerParams); 5 | private createScene; 6 | private initAnimate; 7 | initSky(): void; 8 | initEnvironment(environment: EnvironmentType): void; 9 | initEvent(types: EventTypes[]): void; 10 | private initRender; 11 | private initControls; 12 | initModel(): void; 13 | private initAmbient; 14 | initSkyLight(skyColor: string, earthColor: string, intensity: number): void; 15 | initDirectional(color: string, intensity: number): void; 16 | initPointLight(color: string, intensity: number, distance: number, decay?: number): number; 17 | initSpotLight(color: string, intensity: number, distance: number, target?: THREE.Vector3): void; 18 | initRectArea(color: string, width: number, height: number, intensity: number): void; 19 | initRectAreaBox(color: string, width: number, intensity: number, position: [number, number, number]): void; 20 | initFog(): void; 21 | initWater(options: InitWaterParams): void; 22 | initSource(): void; 23 | loadSprite({ texture, name }: SpriteParams): THREE.Object3D; 24 | initParade(params: ParadeParams): void; 25 | initParticleEngine(particle: ParticleEngineType, mugen: boolean): ParticleEngineType; 26 | getParticleTween(times: number[], values: number[]): ParticleTween; 27 | setParticleMode(particle: ParticleEngineType, key: ParticleKeys, ParticleExamplesParams: ParticleExamplesParams): void; 28 | setScene(index: number, callback: Fn): void; 29 | flyTo(option: FlyToParams): void; 30 | destroy(): void; 31 | } 32 | -------------------------------------------------------------------------------- /Threejs/plugins/particle.ts: -------------------------------------------------------------------------------- 1 | import { Vector3, Color } from "three"; 2 | import { ParticleType } from "../types/types"; 3 | export class Particle implements ParticleType { 4 | position: THREE.Vector3; 5 | velocity: THREE.Vector3; 6 | acceleration: THREE.Vector3; 7 | angle: number; 8 | angleVelocity: number; 9 | angleAcceleration: number; 10 | size: number; 11 | color: THREE.Color; 12 | opacity: number; 13 | age: number; 14 | alive: number; 15 | sizeTween: ParticleTween; 16 | colorTween: ParticleTween; 17 | opacityTween: ParticleTween; 18 | constructor() { 19 | this.position = new Vector3(); //位置 20 | this.velocity = new Vector3(); //位移向量(移动方向和距离) 21 | this.acceleration = new Vector3(); //位移向量的增量(每次产生位移后改变位移向量) 22 | this.angle = 0; //角度 23 | this.angleVelocity = 0; //角度增量 24 | this.angleAcceleration = 0; //改变角度增量的增量 25 | this.size = 16.0; //大小 26 | this.color = new Color(); //颜色 27 | this.opacity = 1.0; //透明度 28 | this.age = 0; //时间 29 | this.alive = 0; //存活 30 | } 31 | update(dt: number) { 32 | this.position.add(this.velocity.clone().multiplyScalar(dt)); //位置在位移方向上的运动 33 | this.velocity.add(this.acceleration.clone().multiplyScalar(dt)); //位移向量的改变 34 | this.angle += this.angleVelocity * 0.01745329251 * dt; // 角度在角度偏移量上的改变 35 | this.angleVelocity += this.angleAcceleration * 0.01745329251 * dt; // 角度偏移量自身的改变 36 | this.age += dt; 37 | 38 | if (this.sizeTween.times.length > 0) { 39 | this.size = this.sizeTween.lerp(this.age); 40 | } 41 | 42 | if (this.colorTween.times.length > 0) { 43 | var colorHSL = this.colorTween.lerp(this.age); 44 | this.color = new Color().setHSL(colorHSL.x, colorHSL.y, colorHSL.z); 45 | } 46 | 47 | if (this.opacityTween.times.length > 0) { 48 | this.opacity = this.opacityTween.lerp(this.age); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Threejs/plugins/event.ts: -------------------------------------------------------------------------------- 1 | import { EventType, EventParams } from "../types/types"; 2 | import { Vector2, Raycaster } from "three"; 3 | 4 | export class Event implements EventType { 5 | types: EventTypes[]; //事件类型 6 | typesFn: { 7 | //各类事件函数解藕 8 | [P in EventTypes]?: Fn[]; 9 | }; 10 | private el: HTMLElement; 11 | private mouse: THREE.Vector2; // 用于射线 12 | private camera: THREE.Camera; 13 | private scene: THREE.Group; 14 | private raycaster: THREE.Raycaster; 15 | constructor(options: EventParams) { 16 | this.types = options.types ?? []; 17 | this.el = options.el; 18 | this.mouse = new Vector2(); 19 | this.raycaster = new Raycaster(); 20 | this.camera = options.camera; 21 | this.scene = options.scene; 22 | this.typesFn = options.typesFn ?? { 23 | click: [], 24 | dblclick: [], 25 | mousemove: [], 26 | }; 27 | } 28 | init() { 29 | this.types.forEach((type) => { 30 | this.el.addEventListener(type, (e) => { 31 | const list = this.getIntersectObject(e, true).objectList; 32 | if (list.length > 0) { 33 | (this.typesFn[type] ?? []).forEach((fn) => 34 | fn({ 35 | event: e, 36 | list, 37 | }) 38 | ); 39 | } 40 | }); 41 | }); 42 | } 43 | 44 | private getIntersectObject(event: MouseEvent, recursive: boolean) { 45 | let objectList = []; 46 | try { 47 | this.mouse.x = (event.offsetX / this.el.clientWidth) * 2 - 1; 48 | this.mouse.y = -(event.offsetY / this.el.clientHeight) * 2 + 1; 49 | this.raycaster.setFromCamera(this.mouse, this.camera); 50 | objectList = this.raycaster.intersectObjects( 51 | this.scene.children, 52 | recursive 53 | ); 54 | } catch (e) { 55 | // 鼠标越界 56 | } 57 | return { 58 | raycaster: this.raycaster, 59 | objectList: objectList, 60 | }; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/plugins/particleEngine.d.ts: -------------------------------------------------------------------------------- 1 | import { ParticleParams } from "../types/types"; 2 | export declare class ParticleEngine implements ParticleEngineType { 3 | private positions; 4 | private customVisibles; 5 | private customColor; 6 | private customOpacity; 7 | private customSize; 8 | private customAngle; 9 | private positionStyle; 10 | private positionBase; 11 | private positionSpread; 12 | private positionRadius; 13 | private velocityStyle; 14 | private velocityBase; 15 | private velocitySpread; 16 | private speedBase; 17 | private speedSpread; 18 | private accelerationBase; 19 | private accelerationSpread; 20 | private angleBase; 21 | private angleSpread; 22 | private angleVelocityBase; 23 | private angleVelocitySpread; 24 | private angleAccelerationBase; 25 | private angleAccelerationSpread; 26 | private sizeBase; 27 | private sizeSpread; 28 | private sizeTween; 29 | private colorBase; 30 | private colorSpread; 31 | private colorTween; 32 | private opacityBase; 33 | private opacitySpread; 34 | private opacityTween; 35 | private blendStyle; 36 | private particleArray; 37 | private particlesPerSecond; 38 | private particleDeathAge; 39 | private emitterAge; 40 | private emitterAlive; 41 | private emitterDeathAge; 42 | private particleCount; 43 | private particleGeometry; 44 | private particleTexture; 45 | private particleMaterial; 46 | private particleMesh; 47 | mugen: boolean; 48 | scene: THREE.Scene; 49 | start: boolean; 50 | constructor(options: ParticleParams); 51 | private createParticle; 52 | initialize(): void; 53 | setValues(parameters: any, params: any): void; 54 | private reastValues; 55 | private randomValue; 56 | private randomVector3; 57 | destroy(): void; 58 | update(dt: any): void; 59 | } 60 | -------------------------------------------------------------------------------- /Threejs/plugins/water.ts: -------------------------------------------------------------------------------- 1 | import { WaterParams, WaterType, WaterShaderParams } from "../types/types"; 2 | import { CircleGeometry } from "three"; 3 | import { Water as WaterShader } from "../shader/water"; 4 | 5 | export class Water implements WaterType { 6 | private texture: THREE.TextureLoader; 7 | private scene: THREE.Scene | THREE.Group; 8 | private animate: Fn[]; 9 | water: WaterShaderParams; 10 | private radius: number; 11 | private textureWidth: number; 12 | private textureHeight: number; 13 | private sunPosition: THREE.Vector3; 14 | private sunColor: string; 15 | private waterColor: string; 16 | private distortionScale: number; 17 | private waterPosition: THREE.Vector3; 18 | time: number; 19 | constructor(options: WaterParams) { 20 | this.radius = options.radius; 21 | this.textureWidth = options.textureWidth; 22 | this.textureHeight = options.textureHeight; 23 | this.sunPosition = options.sunPosition; 24 | this.sunColor = options.sunColor; 25 | this.waterColor = options.waterColor; 26 | this.distortionScale = options.distortionScale; 27 | this.waterPosition = options.waterPosition; 28 | this.time = options.time; 29 | this.texture = options.texture; 30 | this.scene = options.scene; 31 | this.animate = options.animate; 32 | } 33 | init() { 34 | this.water = new WaterShader(new CircleGeometry(this.radius, 32), { 35 | textureWidth: this.textureWidth, 36 | textureHeight: this.textureHeight, 37 | waterNormals: this.texture, 38 | sunDirection: this.sunPosition, 39 | sunColor: this.sunColor, 40 | waterColor: this.waterColor, 41 | distortionScale: this.distortionScale, 42 | fog: (this.scene as THREE.Scene).fog !== undefined, 43 | }); 44 | this.water.rotation.x = -Math.PI / 2; 45 | this.water.position.copy(this.waterPosition); 46 | this.scene.add(this.water); 47 | this.animate.push(() => { 48 | (this.water as any).material.uniforms["time"].value += this.time; 49 | }); 50 | } 51 | destroy() { 52 | this.scene.remove(this.water); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Threejs/plugins/control.ts: -------------------------------------------------------------------------------- 1 | import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; 2 | import { TransformControls } from "three/examples/jsm/controls/TransformControls"; 3 | import { ControlParams, ControlType } from "../types/types"; 4 | import { DragControls } from "three/examples/jsm/controls/DragControls"; 5 | export class Control implements ControlType { 6 | orbitControls: any; 7 | transformControls: any; 8 | private camera: THREE.Camera; 9 | private renderer: THREE.WebGLRenderer; 10 | private scene: THREE.Scene[]; 11 | constructor(options: ControlParams) { 12 | this.orbitControls = null; 13 | this.transformControls = null; 14 | this.camera = options.camera; 15 | this.renderer = options.renderer; 16 | this.scene = options.scene; 17 | this.init(); 18 | } 19 | private init() { 20 | this.initOrbit(); 21 | } 22 | private initOrbit() { 23 | this.orbitControls = new OrbitControls( 24 | this.camera, 25 | this.renderer.domElement 26 | ); 27 | // 使动画循环使用时阻尼或自转 意思是否有惯性 28 | this.orbitControls.enableDamping = true; 29 | //动态阻尼系数 就是鼠标拖拽旋转灵敏度 30 | this.orbitControls.dampingFactor = 0.25; 31 | // 控制半球翻转 32 | this.orbitControls.maxPolarAngle = Math.PI / 2; 33 | this.orbitControls.autoRotate = false; 34 | this.orbitControls.autoRotateSpeed = -10; 35 | this.orbitControls.screenSpacePanning = false; 36 | } 37 | 38 | initTransform(index: number) { 39 | //变换控制器 40 | this.transformControls = new TransformControls( 41 | this.camera, 42 | this.renderer.domElement 43 | ); 44 | this.transformControls.setSize(1); 45 | this.scene[index].attach(this.transformControls); 46 | this.transformControls.addEventListener("dragging-changed", (e) => { 47 | this.orbitControls.enabled = !e.value; 48 | }); 49 | } 50 | initDrag(objects) { 51 | const controls = new DragControls( 52 | objects, 53 | this.camera, 54 | this.renderer.domElement 55 | ); 56 | controls.addEventListener("dragstart", function (event) { 57 | console.log("event", event); 58 | }); 59 | 60 | controls.addEventListener("dragend", function (event) { 61 | console.log("event", event); 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/types/types.d.ts: -------------------------------------------------------------------------------- 1 | import { AnimateType, ViewerAnimate } from "./module/animate"; 2 | import { ViewerType, ViewerParams } from "./module/viewer"; 3 | import { CameraType, ViewerCamera } from "./module/camera"; 4 | import { RenderType, ViewerRender } from "./module/render"; 5 | import { ControlParams, ControlType, ViewerControl } from "./module/control"; 6 | import { ModelType, ModelParams, ViewerModel } from "./module/model"; 7 | import { AmbientParams, AmbientType, ViewerAmbient } from "./module/ambient"; 8 | import { ShaderSkyParams, SkyParams, SkyType, ViewerSky } from "./module/sky"; 9 | import { EnvironmentParams, EnvtType, ViewerEnvironment } from "./module/environment"; 10 | import { EventParams, EventType, ViewerEvent } from "./module/event"; 11 | import { SourceType, ViewerSource } from "./module/source"; 12 | import { SpriteType, SpriteParams } from "./module/sprite"; 13 | import { ParadeType, PipeParams, ParadeParams, ViewerParade } from "./module/parade"; 14 | import { ParticleType, ParticleParams } from "./module/particle"; 15 | import { FogType, ViewerFog } from "./module/fog"; 16 | import { WaterParams, WaterType, ViewerWater, InitWaterParams, WaterShaderParams } from "./module/water"; 17 | import { SkyLightType, ViewerSkyLight } from "./module/skyLight"; 18 | import { DirectionalType, ViewerDirectional } from "./module/directional"; 19 | import { PointLightType } from "./module/point"; 20 | import { SpotType, ViewerSpot } from "./module/spot"; 21 | import { RectAreaType, ViewerRectArea } from "./module/rectArea"; 22 | import { RoamType } from "./module/sceneRoam"; 23 | export { AnimateType, ViewerAnimate, ViewerType, ViewerParams, CameraType, ViewerCamera, RenderType, ViewerRender, ControlParams, ControlType, ViewerControl, ModelType, ModelParams, ViewerModel, AmbientParams, AmbientType, ViewerAmbient, ShaderSkyParams, SkyParams, SkyType, ViewerSky, EnvironmentParams, ViewerEnvironment, EnvtType, EventParams, EventType, ViewerEvent, SourceType, ViewerSource, SpriteType, SpriteParams, ParadeType, PipeParams, ParadeParams, ViewerParade, ParticleType, ParticleParams, FogType, ViewerFog, WaterParams, WaterType, ViewerWater, InitWaterParams, WaterShaderParams, SkyLightType, ViewerSkyLight, DirectionalType, ViewerDirectional, PointLightType, SpotType, ViewerSpot, RectAreaType, ViewerRectArea, RoamType, }; 24 | -------------------------------------------------------------------------------- /Threejs/plugins/environment.ts: -------------------------------------------------------------------------------- 1 | import { PMREMGenerator } from "three"; 2 | import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js"; 3 | import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js"; 4 | import { EnvironmentParams, EnvtType } from "../types/types"; 5 | export class Environment implements EnvtType { 6 | private pmremGenerator: THREE.PMREMGenerator; 7 | private path: string; 8 | private scene: THREE.Scene; 9 | environment: EnvironmentType; 10 | constructor(options: EnvironmentParams) { 11 | this.pmremGenerator = new PMREMGenerator(options.renderer); 12 | this.pmremGenerator.compileEquirectangularShader(); 13 | this.path = options.path; 14 | this.scene = options.scene; 15 | this.environment = options.environment ?? { 16 | path: "", 17 | type: "exr", 18 | }; 19 | } 20 | init() { 21 | this.getCubeMapTexture(this.environment).then((envMap) => { 22 | this.scene.environment = envMap; 23 | }); 24 | } 25 | private loadHdr(path: string) { 26 | return new Promise((resolve, reject) => { 27 | new RGBELoader().load( 28 | this.path + path, 29 | (texture) => { 30 | const envMap = 31 | this.pmremGenerator.fromEquirectangular(texture).texture; 32 | this.pmremGenerator.dispose(); 33 | resolve(envMap); 34 | }, 35 | undefined, 36 | reject 37 | ); 38 | }); 39 | } 40 | private loadExr(path: string) { 41 | return new Promise((resolve, reject) => { 42 | new EXRLoader().load( 43 | this.path + path, 44 | (texture) => { 45 | const envMap = 46 | this.pmremGenerator.fromEquirectangular(texture).texture; 47 | this.pmremGenerator.dispose(); 48 | 49 | resolve(envMap); 50 | }, 51 | undefined, 52 | reject 53 | ); 54 | }); 55 | } 56 | //下载环境贴图 57 | private getCubeMapTexture(environment = { path: "", type: "hdr" }) { 58 | const { path, type } = environment; 59 | // no envmap 60 | if (!path) return Promise.resolve(null); 61 | 62 | switch (type) { 63 | case "hdr": 64 | return this.loadHdr(path); 65 | case "exr": 66 | return this.loadExr(path); 67 | default: 68 | return Promise.resolve(null); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Threejs/plugins/params.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ViewerParams, 3 | ViewerAnimate, 4 | ViewerCamera, 5 | ViewerAmbient, 6 | ViewerEvent, 7 | ViewerModel, 8 | ViewerFog, 9 | ViewerControl, 10 | ViewerSky, 11 | ViewerEnvironment, 12 | ViewerSource, 13 | ViewerParade, 14 | ViewerWater, 15 | ViewerSkyLight, 16 | ViewerDirectional, 17 | PointLightType, 18 | ViewerSpot, 19 | ViewerRectArea, 20 | } from "../types/types"; 21 | import { Clock } from "three"; 22 | 23 | /* 24 | *@description: 初始化参数 25 | *@author: yangj 26 | *@date: 2023-03-04 09:08:01 27 | *@return: 28 | */ 29 | export class Params { 30 | clock: THREE.Clock; //时钟 31 | animate: ViewerAnimate; //帧动画执行类 32 | gAmGroup: THREE.Group[]; //环境场景 33 | gRayGroup: THREE.Group[]; //鼠标拾取场景 34 | gScenes: THREE.Scene[]; //主场景 35 | gStatus: boolean[]; //场景是否存于内存 36 | scene: THREE.Scene; //场景容器 37 | model: ViewerModel; //模型类 38 | sceneidx: number; //场景id 39 | cameraClass: ViewerCamera; //相机类 40 | activeCamera: THREE.Camera; //激活相机 41 | renderer: THREE.WebGLRenderer; //渲染 42 | controls: ViewerControl; //控制器类 43 | ambient: ViewerAmbient; //环境光 44 | hemisphereLight: ViewerSkyLight; //半球光 45 | directional: ViewerDirectional; //平行光 46 | pointGroup: PointLightType[]; //点光源组合 47 | spotLight: ViewerSpot; //聚光灯 48 | rectAreaLight: ViewerRectArea; //区域光 49 | sky: ViewerSky; //天空 50 | environment: ViewerEnvironment; //环境贴图 51 | event: ViewerEvent; //事件 52 | souce: ViewerSource; //资源加载类 53 | parade: ViewerParade; 54 | spriteGroup: THREE.Object3D[]; 55 | fog: ViewerFog; //雾 56 | water: ViewerWater; //水 57 | options: ViewerParams; //实例参数 58 | constructor(options: ViewerParams) { 59 | this.options = options; 60 | this.clock = new Clock(); 61 | this.animate = null; 62 | this.gAmGroup = []; 63 | this.gRayGroup = []; 64 | this.gScenes = []; 65 | this.gStatus = []; 66 | this.scene = null; 67 | this.model = null; 68 | this.sceneidx = 1; 69 | this.activeCamera = null; 70 | this.cameraClass = null; 71 | this.renderer = null; 72 | this.ambient = null; 73 | this.hemisphereLight = null; 74 | this.directional = null; 75 | this.pointGroup = []; 76 | this.spotLight = null; 77 | this.environment = null; 78 | this.event = null; 79 | this.souce = null; 80 | this.parade = null; 81 | this.water = null; 82 | this.spriteGroup = []; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Threejs/types/types.ts: -------------------------------------------------------------------------------- 1 | import { AnimateType, ViewerAnimate } from "./module/animate"; 2 | import { ViewerType, ViewerParams } from "./module/viewer"; 3 | import { CameraType, ViewerCamera } from "./module/camera"; 4 | import { RenderType, ViewerRender } from "./module/render"; 5 | import { ControlParams, ControlType, ViewerControl } from "./module/control"; 6 | import { ModelType, ModelParams, ViewerModel } from "./module/model"; 7 | import { AmbientParams, AmbientType, ViewerAmbient } from "./module/ambient"; 8 | import { ShaderSkyParams, SkyParams, SkyType, ViewerSky } from "./module/sky"; 9 | import { 10 | EnvironmentParams, 11 | EnvtType, 12 | ViewerEnvironment, 13 | } from "./module/environment"; 14 | import { EventParams, EventType, ViewerEvent } from "./module/event"; 15 | import { SourceType, ViewerSource } from "./module/source"; 16 | import { SpriteType, SpriteParams } from "./module/sprite"; 17 | import { 18 | ParadeType, 19 | PipeParams, 20 | ParadeParams, 21 | ViewerParade, 22 | } from "./module/parade"; 23 | import { ParticleType, ParticleParams } from "./module/particle"; 24 | import { FogType, ViewerFog } from "./module/fog"; 25 | import { 26 | WaterParams, 27 | WaterType, 28 | ViewerWater, 29 | InitWaterParams, 30 | WaterShaderParams, 31 | } from "./module/water"; 32 | import { SkyLightType, ViewerSkyLight } from "./module/skyLight"; 33 | import { DirectionalType, ViewerDirectional } from "./module/directional"; 34 | import { PointLightType } from "./module/point"; 35 | import { SpotType, ViewerSpot } from "./module/spot"; 36 | import { RectAreaType, ViewerRectArea } from "./module/rectArea"; 37 | import { RoamType } from "./module/sceneRoam"; 38 | export { 39 | AnimateType, 40 | ViewerAnimate, 41 | ViewerType, 42 | ViewerParams, 43 | CameraType, 44 | ViewerCamera, 45 | RenderType, 46 | ViewerRender, 47 | ControlParams, 48 | ControlType, 49 | ViewerControl, 50 | ModelType, 51 | ModelParams, 52 | ViewerModel, 53 | AmbientParams, 54 | AmbientType, 55 | ViewerAmbient, 56 | ShaderSkyParams, 57 | SkyParams, 58 | SkyType, 59 | ViewerSky, 60 | EnvironmentParams, 61 | ViewerEnvironment, 62 | EnvtType, 63 | EventParams, 64 | EventType, 65 | ViewerEvent, 66 | SourceType, 67 | ViewerSource, 68 | SpriteType, 69 | SpriteParams, 70 | ParadeType, 71 | PipeParams, 72 | ParadeParams, 73 | ViewerParade, 74 | ParticleType, 75 | ParticleParams, 76 | FogType, 77 | ViewerFog, 78 | WaterParams, 79 | WaterType, 80 | ViewerWater, 81 | InitWaterParams, 82 | WaterShaderParams, 83 | SkyLightType, 84 | ViewerSkyLight, 85 | DirectionalType, 86 | ViewerDirectional, 87 | PointLightType, 88 | SpotType, 89 | ViewerSpot, 90 | RectAreaType, 91 | ViewerRectArea, 92 | RoamType, 93 | }; 94 | -------------------------------------------------------------------------------- /Threejs/plugins/camera.ts: -------------------------------------------------------------------------------- 1 | import { PerspectiveCamera } from "three"; 2 | import { CameraType } from "../types/types"; 3 | export class Camera implements CameraType { 4 | camera: THREE.Camera; 5 | private el: HTMLElement; 6 | constructor(el: HTMLElement) { 7 | this.camera = null; 8 | this.el = el; 9 | this.init(); 10 | } 11 | private init() { 12 | this.camera = new PerspectiveCamera( 13 | 60, 14 | this.el.clientWidth / this.el.clientHeight, 15 | 1, 16 | 2000000 17 | ); 18 | } 19 | 20 | flyTo(TWEEN: any, controls: any, option: FlyToParams) { 21 | option.position = option.position || []; // 相机新的位置 22 | option.controls = option.controls || []; // 控制器新的中心点位置(围绕此点旋转等) 23 | option.duration = option.duration || 1000; // 飞行时间 24 | option.easing = option.easing || TWEEN.Easing.Linear.None; 25 | TWEEN.removeAll(); 26 | const curPosition = this.camera?.position; 27 | const controlsTar = controls.orbitControls.target; 28 | const tween = new TWEEN.Tween({ 29 | x1: curPosition.x, // 相机当前位置x 30 | y1: curPosition.y, // 相机当前位置y 31 | z1: curPosition.z, // 相机当前位置z 32 | x2: controlsTar.x, // 控制当前的中心点x 33 | y2: controlsTar.y, // 控制当前的中心点y 34 | z2: controlsTar.z, // 控制当前的中心点z 35 | }) 36 | .to( 37 | { 38 | x1: option.position[0], // 新的相机位置x 39 | y1: option.position[1], // 新的相机位置y 40 | z1: option.position[2], // 新的相机位置z 41 | x2: option.controls[0], // 新的控制中心点位置x 42 | y2: option.controls[1], // 新的控制中心点位置x 43 | z2: option.controls[2], // 新的控制中心点位置x 44 | }, 45 | option.duration 46 | ) 47 | .easing(TWEEN.Easing.Linear.None); // TWEEN.Easing.Cubic.InOut //匀速 48 | 49 | tween.onUpdate(() => { 50 | controls.orbitControls.enabled = false; 51 | this.camera?.position.set( 52 | tween._object.x1, 53 | tween._object.y1, 54 | tween._object.z1 55 | ); 56 | controls.orbitControls.target.set( 57 | tween._object.x2, 58 | tween._object.y2, 59 | tween._object.z2 60 | ); 61 | controls.orbitControls.update(); 62 | if (option.update instanceof Function) { 63 | option.update(tween); 64 | } 65 | }); 66 | tween.onStart(() => { 67 | controls.orbitControls.enabled = false; 68 | if (option.start instanceof Function) { 69 | option.start(); 70 | } 71 | }); 72 | tween.onComplete(() => { 73 | controls.orbitControls.enabled = true; 74 | if (option.done instanceof Function) { 75 | option.done(); 76 | } 77 | }); 78 | tween.onStop(() => (option.stop instanceof Function ? option.stop() : "")); 79 | tween.start(); 80 | TWEEN.add(tween); 81 | return tween; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Threejs/shader/improved.ts: -------------------------------------------------------------------------------- 1 | // https://cs.nyu.edu/~perlin/noise/ 2 | 3 | const _p = [ 4 | 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 5 | 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 6 | 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 7 | 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 8 | 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 9 | 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 10 | 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 11 | 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 12 | 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 13 | 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 14 | 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 15 | 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 16 | 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 17 | 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 18 | 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 19 | 61, 156, 180, 20 | ]; 21 | 22 | for (let i = 0; i < 256; i++) { 23 | _p[256 + i] = _p[i]; 24 | } 25 | 26 | function fade(t) { 27 | return t * t * t * (t * (t * 6 - 15) + 10); 28 | } 29 | 30 | function lerp(t, a, b) { 31 | return a + t * (b - a); 32 | } 33 | 34 | function grad(hash, x, y, z) { 35 | const h = hash & 15; 36 | const u = h < 8 ? x : y, 37 | v = h < 4 ? y : h == 12 || h == 14 ? x : z; 38 | return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); 39 | } 40 | 41 | class ImprovedNoise { 42 | noise(x, y, z) { 43 | const floorX = Math.floor(x), 44 | floorY = Math.floor(y), 45 | floorZ = Math.floor(z); 46 | 47 | const X = floorX & 255, 48 | Y = floorY & 255, 49 | Z = floorZ & 255; 50 | 51 | x -= floorX; 52 | y -= floorY; 53 | z -= floorZ; 54 | 55 | const xMinus1 = x - 1, 56 | yMinus1 = y - 1, 57 | zMinus1 = z - 1; 58 | 59 | const u = fade(x), 60 | v = fade(y), 61 | w = fade(z); 62 | 63 | const A = _p[X] + Y, 64 | AA = _p[A] + Z, 65 | AB = _p[A + 1] + Z, 66 | B = _p[X + 1] + Y, 67 | BA = _p[B] + Z, 68 | BB = _p[B + 1] + Z; 69 | 70 | return lerp( 71 | w, 72 | lerp( 73 | v, 74 | lerp(u, grad(_p[AA], x, y, z), grad(_p[BA], xMinus1, y, z)), 75 | lerp(u, grad(_p[AB], x, yMinus1, z), grad(_p[BB], xMinus1, yMinus1, z)) 76 | ), 77 | lerp( 78 | v, 79 | lerp( 80 | u, 81 | grad(_p[AA + 1], x, y, zMinus1), 82 | grad(_p[BA + 1], xMinus1, y, zMinus1) 83 | ), 84 | lerp( 85 | u, 86 | grad(_p[AB + 1], x, yMinus1, zMinus1), 87 | grad(_p[BB + 1], xMinus1, yMinus1, zMinus1) 88 | ) 89 | ) 90 | ); 91 | } 92 | } 93 | 94 | export { ImprovedNoise }; 95 | -------------------------------------------------------------------------------- /Threejs/plugins/lights/rectArea.ts: -------------------------------------------------------------------------------- 1 | import { Group, RectAreaLight } from "three"; 2 | import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper.js"; 3 | import { RectAreaType } from "../../types/types"; 4 | import { RectAreaLightUniformsLib } from "../lights/rectlib"; 5 | export class RectArea implements RectAreaType { 6 | private scene: THREE.Scene; 7 | light: THREE.RectAreaLight; 8 | areaLight: THREE.Group; 9 | helper: any; 10 | constructor(scene: THREE.Scene) { 11 | this.scene = scene; 12 | this.areaLight = new Group(); 13 | RectAreaLightUniformsLib.init(); 14 | } 15 | init(color: string, width: number, height: number, intensity: number) { 16 | this.light = new RectAreaLight(color, intensity, width, height); 17 | this.scene.add(this.light); 18 | } 19 | 20 | initArea( 21 | color: string, 22 | width: number, 23 | intensity: number, 24 | position: [number, number, number] 25 | ) { 26 | const rectLight = new RectAreaLight(color, intensity, width, width); 27 | rectLight.position.set(position[0], width + position[1], position[2]); 28 | rectLight.lookAt(position[0], width / 2, position[2]); 29 | 30 | const rectLight1 = new RectAreaLight(color, intensity, width, width); 31 | rectLight1.position.set( 32 | width / 2 + position[0], 33 | width / 2 + position[1], 34 | position[2] 35 | ); 36 | rectLight1.lookAt(position[0], width / 2 + position[1], position[2]); 37 | const rectLight2 = new RectAreaLight(color, intensity, width, width); 38 | rectLight2.position.set( 39 | -width / 2 + position[0], 40 | width / 2 + position[1], 41 | position[2] 42 | ); 43 | rectLight2.lookAt(position[0], width / 2 + position[1], position[2]); 44 | 45 | const rectLight3 = new RectAreaLight(color, intensity, width, width); 46 | rectLight3.position.set(position[0], position[1], position[2]); 47 | rectLight3.lookAt(position[0], width / 2 + position[1], position[2]); 48 | const rectLight4 = new RectAreaLight(color, intensity, width, width); 49 | rectLight4.position.set( 50 | position[0], 51 | width / 2 + position[1], 52 | width / 2 + position[2] 53 | ); 54 | rectLight4.lookAt(position[0], width / 2 + position[1], position[2]); 55 | 56 | const rectLight5 = new RectAreaLight(color, intensity, width, width); 57 | rectLight5.position.set( 58 | position[0], 59 | width / 2 + position[1], 60 | -width / 2 + position[2] 61 | ); 62 | rectLight5.lookAt(position[0], width / 2 + position[1], position[2]); 63 | 64 | this.areaLight.add( 65 | rectLight, 66 | rectLight1, 67 | rectLight2, 68 | rectLight3, 69 | rectLight4, 70 | rectLight5 71 | ); 72 | this.scene.add(this.areaLight); 73 | } 74 | 75 | initHelper() { 76 | this.helper = new RectAreaLightHelper(this.light, "#fff"); 77 | this.scene.add(this.helper); 78 | } 79 | initBoxHelper() { 80 | this.areaLight.traverse((light) => { 81 | this.areaLight.add( 82 | new RectAreaLightHelper(light as THREE.RectAreaLight, "#fff") 83 | ); 84 | }); 85 | } 86 | destory() { 87 | this.scene.remove(this.helper); 88 | this.areaLight && this.scene.remove(this.areaLight); 89 | this.light && this.scene.remove(this.light); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Threejs/plugins/skybox.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BoxGeometry, 3 | BackSide, 4 | TextureLoader, 5 | MeshBasicMaterial, 6 | Mesh, 7 | Vector3, 8 | } from "three"; 9 | import { Sky as SkyShader } from "../shader/sky"; 10 | import { SkyParams, SkyType, ShaderSkyParams } from "../types/types"; 11 | export class Sky implements SkyType { 12 | private path: string; 13 | private sceneidx: number; 14 | private gSkyBox: THREE.Mesh[]; 15 | private gScenes: THREE.Scene[]; 16 | sky: THREE.Object3D; 17 | constructor(options: SkyParams) { 18 | this.path = options.path; 19 | this.gSkyBox = [null, null]; 20 | this.sceneidx = options.sceneidx; 21 | this.gScenes = options.gScenes; 22 | } 23 | setSkyBox(skydir: string) { 24 | // 创建几何模型 BoxGeometry('x轴', '轴', 'z轴') 25 | const geometry = new BoxGeometry(20000, 20000, 20000); 26 | // 创建纹理贴图 前后 上下 左右 27 | const texture0 = new TextureLoader().load(this.path + `${skydir}/px.jpg`); 28 | const texture1 = new TextureLoader().load(this.path + `${skydir}/nx.jpg`); 29 | const texture2 = new TextureLoader().load(this.path + `${skydir}/py.jpg`); 30 | const texture3 = new TextureLoader().load(this.path + `${skydir}/ny.jpg`); 31 | const texture4 = new TextureLoader().load(this.path + `${skydir}/pz.jpg`); 32 | const texture5 = new TextureLoader().load(this.path + `${skydir}/nz.jpg`); 33 | // 添加材质 34 | const material = [ 35 | new MeshBasicMaterial({ 36 | color: 0xffffff, 37 | map: texture0, 38 | side: BackSide, 39 | }), 40 | new MeshBasicMaterial({ 41 | color: 0xffffff, 42 | map: texture1, 43 | side: BackSide, 44 | }), 45 | new MeshBasicMaterial({ 46 | color: 0xffffff, 47 | map: texture2, 48 | side: BackSide, 49 | }), 50 | new MeshBasicMaterial({ 51 | color: 0xffffff, 52 | map: texture3, 53 | side: BackSide, 54 | }), 55 | new MeshBasicMaterial({ 56 | color: 0xffffff, 57 | map: texture4, 58 | side: BackSide, 59 | }), 60 | new MeshBasicMaterial({ 61 | color: 0xffffff, 62 | map: texture5, 63 | side: BackSide, 64 | }), 65 | ]; 66 | // 创建网格对象 67 | const cube = new Mesh(geometry, material as any); 68 | cube.name = "skybox"; 69 | this.sky = cube; 70 | if (this.gSkyBox[this.sceneidx]) { 71 | this.gScenes[this.sceneidx].remove(this.gSkyBox[this.sceneidx]); 72 | this.gSkyBox[this.sceneidx].geometry.dispose(); 73 | } 74 | 75 | this.gSkyBox[this.sceneidx] = cube; 76 | this.gScenes[this.sceneidx].add(cube); 77 | } 78 | 79 | initShaderSky(option: ShaderSkyParams) { 80 | if (this.gSkyBox[this.sceneidx]) { 81 | this.gScenes[this.sceneidx].remove(this.gSkyBox[this.sceneidx]); 82 | } 83 | const sky = new SkyShader(); 84 | this.sky = sky; 85 | (sky as any).scale.setScalar(option.scale); 86 | this.gScenes[this.sceneidx].add(sky); 87 | const skyUniforms = (sky as any).material.uniforms; 88 | skyUniforms["turbidity"].value = option.turbidity; //浑浊度 89 | skyUniforms["rayleigh"].value = option.rayleigh; //散射 90 | skyUniforms["mieCoefficient"].value = 0.005; 91 | skyUniforms["mieDirectionalG"].value = 0.8; 92 | skyUniforms["sunPosition"].value = new Vector3( 93 | option.postion[0], 94 | option.postion[1], 95 | option.postion[2] 96 | ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Threejs/types/global.d.ts: -------------------------------------------------------------------------------- 1 | declare type Fn = (params?: T) => void; 2 | declare type FnNoParamsReturn = () => T; 3 | declare type FnTwoParams = (a: T, b: P) => R; 4 | declare type FnThreeParams = (a: T, b: P, c: Z) => R; 5 | declare type FnParamsReturn = (params: T) => R; 6 | declare enum EnvironmentEnum { 7 | "hdr", 8 | "exr", 9 | } 10 | declare type environmentType = keyof typeof EnvironmentEnum; 11 | 12 | declare interface EnvironmentType { 13 | path: string; 14 | type: environmentType; 15 | } 16 | interface EventObject { 17 | uv: THREE.Vector3; 18 | point: THREE.Vector3; 19 | object: THREE.Mesh; 20 | faceIndex: number; 21 | face: THREE.Face; 22 | distance: number; 23 | } 24 | declare interface EventCallbackParams { 25 | event: MouseEvent; 26 | list: EventObject[]; 27 | } 28 | 29 | declare enum EventEnum { 30 | "click", 31 | "dblclick", 32 | "mousemove", 33 | } 34 | declare type EventTypes = keyof typeof EventEnum; 35 | declare interface FlyToParams { 36 | position: number[]; 37 | controls?: number[]; 38 | duration?: number; 39 | easing?: number; 40 | start?: Fn; 41 | done?: Fn; 42 | stop?: Fn; 43 | update?: Fn; 44 | } 45 | interface Layers { 46 | name: string; 47 | } 48 | declare interface ModelConfig { 49 | name: string; 50 | target: boolean; 51 | layeridx: number; 52 | scale: number; 53 | positionX: number; 54 | positionY: number; 55 | positionZ: number; 56 | layers: Layers[]; 57 | } 58 | 59 | declare interface ParticleTween { 60 | times: number[]; 61 | values: THREE.Vector3 | number[]; 62 | lerp: FnParamsReturn; 63 | } 64 | declare enum ParticleKey { 65 | "fountain", 66 | "fireball", 67 | "smoke", 68 | "clouds", 69 | "snow", 70 | "rain", 71 | "starfield", 72 | "haze", 73 | "fireflies", 74 | "startunnel", 75 | "firework", 76 | "candle", 77 | } 78 | declare type ParticleKeys = keyof typeof ParticleKey; 79 | declare interface ParticleEngineType { 80 | mugen: boolean; 81 | scene: THREE.Scene; 82 | start: boolean; 83 | initialize: Fn; 84 | setValues: FnTwoParams; 85 | destroy: Fn; 86 | update: FnParamsReturn; 87 | } 88 | declare type ParticleExamplesParams = Partial<{ 89 | positionBase: THREE.Vector3; //初始位置 90 | positionStyle: 1 | 2; //cube or sphere 91 | positionSpread: THREE.Vector3; //初始位置随机累加值(差异化) 92 | positionRadius: number; //sphere类型的粒子扩散范围 93 | velocityStyle: 1 | 2; //cube or sphere 94 | velocityBase: THREE.Vector3; //粒子运动方向以及速度 95 | velocitySpread: THREE.Vector3; //初始化粒子运动方向和速度随机累加值(差异化) 96 | speedBase: number; //sphere类型粒子扩散速度 97 | speedSpread: number; //sphere类型粒子扩散速度随机累加值(差异化) 98 | accelerationBase: THREE.Vector3; //运动初始加速度 99 | accelerationSpread: THREE.Vector3; //运动加速度随机累加值(差异化) 100 | angleBase: number; //角度初始值 101 | angleSpread: number; // 角度初始化随机累计值(差异化) 102 | angleVelocityBase: number; //角度随着运动增量 103 | angleVelocitySpread: number; //角度增量随机累加值(差异化) 104 | sizeBase: number; //大小初始值 105 | sizeSpread: number; //大小初始化随机累加值(差异化) 106 | sizeTween: ParticleTween; //大小随时间变化过渡函数 107 | colorBase: THREE.Vector3; //颜色初始值 108 | colorSpread: THREE.Vector3; //颜色初始化随机累加值(差异化) 109 | colorTween: ParticleTween; //颜色随时间变化过渡函数 110 | opacityBase: number; //透明度初始值 111 | opacitySpread: number; //透明度初始化随机累加值(差异化) 112 | opacityTween: ParticleTween; //透明度随时间变化过渡函数 113 | particlesPerSecond: number; //每秒产生粒子数量 114 | particleDeathAge: number; //粒子存活时间 115 | emitterDeathAge: number; //结束粒子运动时间 116 | particleTexture: THREE.Texture; 117 | }>; 118 | -------------------------------------------------------------------------------- /Threejs/plugins/parade.ts: -------------------------------------------------------------------------------- 1 | import { ParadeType, PipeParams, ParadeParams } from "../types/types"; 2 | import { 3 | CatmullRomCurve3, 4 | TubeGeometry, 5 | MeshBasicMaterial, 6 | RepeatWrapping, 7 | DoubleSide, 8 | Mesh, 9 | } from "three"; 10 | export class Parade implements ParadeType { 11 | private pipeTexture: THREE.Texture; //管道贴图 12 | private pipeParams: PipeParams; //管道参数 13 | private scene: THREE.Scene; //场景 14 | private animate: Fn[]; 15 | private callback: ( 16 | type: string, 17 | value: { point: THREE.Vector3; pointLook: THREE.Vector3 } 18 | ) => void; 19 | curve: THREE.CatmullRomCurve3; //曲线 20 | pipeLine: THREE.Mesh; //管道实例 21 | stop: boolean; //暂停 22 | progress: number; //进度 23 | speed: number; //速度 24 | direction: string; //方向 25 | loop: boolean; //是否循环 26 | object: THREE.Object3D; //物体 27 | constructor(options: ParadeParams) { 28 | this.pipeParams = options.pipeParams; 29 | this.pipeTexture = options.pipeTexture; 30 | this.scene = options.scene; 31 | this.animate = options.animate; 32 | this.speed = options.speed / 1000 ?? 1 / 1000; 33 | this.loop = options.loop ?? false; 34 | this.stop = true; 35 | this.object = options.object; 36 | this.run(); 37 | } 38 | /* 39 | *@description: 绘制管道 40 | *@author: yangj 41 | *@date: 2023-03-10 14:36:45 42 | *@return: 43 | */ 44 | drawPipeLine(pipeLineArr: THREE.Vector3[]) { 45 | if (pipeLineArr.length < 2) { 46 | return; 47 | } 48 | this.initCurve(pipeLineArr); 49 | this.initPipe(this.pipeParams); 50 | } 51 | /* 52 | *@description: 三维平滑曲线 53 | *@author: yangj 54 | *@date: 2023-03-10 14:56:01 55 | *@return: 56 | */ 57 | private initCurve(pipeLineArr: THREE.Vector3[]) { 58 | this.curve = new CatmullRomCurve3(pipeLineArr); 59 | this.curve.arcLengthDivisions = 1000; 60 | } 61 | /* 62 | *@description: 管道 63 | *@author: yangj 64 | *@date: 2023-03-10 14:57:06 65 | *@return: 66 | */ 67 | private initPipe({ 68 | tubularSegments, 69 | radius, 70 | radialSegments, 71 | closed, 72 | }: PipeParams) { 73 | let tubeGeometry = new TubeGeometry( 74 | this.curve, 75 | tubularSegments, 76 | radius, 77 | radialSegments, 78 | closed 79 | ); 80 | this.pipeTexture.wrapS = RepeatWrapping; //每个都重复 81 | this.pipeTexture.wrapT = RepeatWrapping; 82 | this.pipeTexture.repeat.set(1, 1); 83 | this.pipeTexture.needsUpdate = true; 84 | let material = new MeshBasicMaterial({ 85 | map: this.pipeTexture, 86 | side: DoubleSide, 87 | transparent: true, 88 | }); 89 | this.pipeLine = new Mesh(tubeGeometry, material); 90 | this.scene.add(this.pipeLine); 91 | } 92 | /* 93 | *@description: 清除 94 | *@author: yangj 95 | *@date: 2023-03-10 15:21:01 96 | *@return: 97 | */ 98 | clear() { 99 | this.scene.remove(this.pipeLine); 100 | this.pipeLine = null; 101 | } 102 | /* 103 | *@description: 巡检 104 | *@author: yangj 105 | *@date: 2023-03-10 15:23:56 106 | *@return: 107 | */ 108 | autoParade( 109 | callback: ( 110 | type: string, 111 | value: { point: THREE.Vector3; pointLook: THREE.Vector3 } 112 | ) => void 113 | ) { 114 | this.progress = 0; 115 | this.stop = false; 116 | this.callback = callback; 117 | } 118 | private run() { 119 | this.animate.push(() => { 120 | if (!this.stop) { 121 | if (this.direction === "GO") { 122 | if (this.progress > 1.0) { 123 | if (this.loop) { 124 | this.direction = "BACK"; 125 | } else { 126 | this.callback instanceof Function && 127 | this.callback("end", { 128 | point: this.object.position, 129 | pointLook: this.object.position, 130 | }); 131 | } 132 | } else { 133 | this.progress += this.speed; 134 | } 135 | } else { 136 | if (this.progress <= 0) { 137 | this.direction = "GO"; 138 | } else { 139 | this.progress -= this.speed; 140 | } 141 | } 142 | if (this.curve && this.object) { 143 | let point, pointLook; 144 | if (this.direction === "GO") { 145 | point = this.curve.getPoint(this.progress); 146 | pointLook = this.curve.getPoint(this.progress + this.speed * 20); 147 | } else { 148 | point = this.curve.getPoint(this.progress); 149 | pointLook = this.curve.getPoint(this.progress - this.speed * 20); 150 | } 151 | 152 | this.object.position.set(point.x, point.y, point.z); 153 | this.object.lookAt(pointLook); 154 | this.callback instanceof Function && 155 | this.callback("start", { 156 | point, 157 | pointLook, 158 | }); 159 | } 160 | } 161 | }); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Threejs/plugins/model.ts: -------------------------------------------------------------------------------- 1 | import { AnimationMixer, LoadingManager, FrontSide } from "three"; 2 | import { GLTFExtensionLoader } from "../threelibex/GLTFExtensionLoader"; 3 | import { ModelType, ModelParams } from "../types/types"; 4 | import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader"; 5 | 6 | import axios from "axios"; 7 | 8 | export class Model implements ModelType { 9 | mixer: THREE.AnimationMixer; //动画实例 10 | private gScenes: THREE.Scene[]; 11 | private gStatus: boolean[]; 12 | private gRayGroup: THREE.Group[]; 13 | private gAmGroup: THREE.Group[]; 14 | private baseURL: string; 15 | private bus: any; 16 | animate: boolean; 17 | deepFunction: Fn<{ 18 | e: THREE.Mesh; 19 | item: ModelConfig; 20 | }>[]; //深度处理场景业务逻辑 21 | constructor(options: ModelParams) { 22 | this.mixer = null; 23 | this.gScenes = options.gScenes; 24 | this.gStatus = options.gStatus; 25 | this.gRayGroup = options.gRayGroup; 26 | this.gAmGroup = options.gAmGroup; 27 | this.baseURL = options.baseURL; 28 | this.bus = options.bus; 29 | this.deepFunction = []; 30 | this.animate = true; 31 | options.animateFuntion?.push((dt) => { 32 | if (this.animate) { 33 | this.mixer && this.mixer.update(dt); 34 | } 35 | }); 36 | } 37 | /* 38 | *@description: 加载配置文件 39 | *@author: yangj 40 | *@date: 2023-03-04 16:26:55 41 | *@return: 42 | */ 43 | private getConfig() { 44 | return axios.get(this.baseURL + "config.json"); 45 | } 46 | /* 47 | *@description: 加载glb 48 | *@author: yangj 49 | *@date: 2023-03-04 16:27:04 50 | *@return: 51 | */ 52 | load(sceneidx: number, callback: Fn) { 53 | let icount = 0; 54 | let dicount = 0; 55 | this.getConfig() 56 | .then((res) => { 57 | res.data.forEach((configItem: ModelConfig) => { 58 | if (sceneidx !== configItem["layeridx"]) { 59 | return; 60 | } 61 | configItem["layers"].forEach((layers: Layers) => { 62 | icount++; 63 | this.loadConfigModel( 64 | this.baseURL + layers["name"], 65 | configItem, 66 | (scene) => { 67 | this.decodeSence(scene, configItem, layers, () => { 68 | dicount++; 69 | this.bus.emit("scene", { 70 | type: "loading", 71 | progressNum: (dicount / icount) * 100, 72 | value: true, 73 | }); 74 | if (dicount === icount) { 75 | this.gStatus[sceneidx] = true; 76 | callback ? callback() : ""; 77 | } 78 | }); 79 | } 80 | ); 81 | }); 82 | }); 83 | }) 84 | .catch(() => {}); 85 | } 86 | /* 87 | *@description: 加载配置文件glb 88 | *@author: yangj 89 | *@date: 2023-03-04 16:27:26 90 | *@return: 91 | */ 92 | private loadConfigModel( 93 | url: string, 94 | configItem: ModelConfig, 95 | callback: Fn 96 | ) { 97 | const that = this; 98 | const loader = new GLTFExtensionLoader(new LoadingManager()); 99 | loader.load(url).then((gltf) => { 100 | let ascene: THREE.Scene = gltf.scene; 101 | ascene.scale.set(configItem.scale, configItem.scale, configItem.scale); 102 | ascene.animations = gltf.animations; 103 | if (configItem.target) { 104 | that.gRayGroup[configItem.layeridx].add(ascene); 105 | } else { 106 | that.gAmGroup[configItem.layeridx].add(ascene); 107 | } 108 | callback ? callback(ascene) : ""; 109 | }); 110 | } 111 | /* 112 | *@description: 加载glb 113 | *@author: yangj 114 | *@date: 2023-03-19 18:25:38 115 | *@return: 116 | */ 117 | loadModel( 118 | url: string, 119 | sceneidx: number, 120 | callback: FnTwoParams 121 | ) { 122 | const loader = new GLTFExtensionLoader(new LoadingManager()); 123 | loader.load(url).then((glb) => { 124 | this.addclips(glb.animations, sceneidx); 125 | callback(glb.scene, glb.animations); 126 | }); 127 | } 128 | /* 129 | *@description: 加载fbx 130 | *@author: yangj 131 | *@date: 2023-03-28 14:42:51 132 | *@return: 133 | */ 134 | loadFbxModel( 135 | url: string, 136 | sceneidx: number, 137 | callback: FnTwoParams 138 | ) { 139 | const loader = new FBXLoader(); 140 | loader.load(url, (object) => { 141 | this.addclips(object.animations, sceneidx); 142 | callback(object, object.animations); 143 | }); 144 | } 145 | /* 146 | *@description: 处理模型 147 | *@author: yangj 148 | *@date: 2023-03-04 16:26:35 149 | *@return: 150 | */ 151 | private decodeSence( 152 | scene: any, 153 | configItem: ModelConfig, 154 | layers: Layers, 155 | callback: Fn 156 | ) { 157 | const tage = layers["receiveShadow"]; 158 | 159 | if (configItem["positionX"]) { 160 | scene.position.setX(configItem["positionX"]); 161 | } 162 | if (configItem["positionY"]) { 163 | scene.position.setY(configItem["positionY"]); 164 | } 165 | if (configItem["positionZ"]) { 166 | scene.position.setZ(configItem["positionZ"]); 167 | } 168 | scene.traverse((e) => { 169 | if (e.isMesh) { 170 | if (tage) { 171 | e.castShadow = false; 172 | e.receiveShadow = true; 173 | } else { 174 | e.castShadow = true; 175 | e.receiveShadow = true; 176 | } 177 | e.material.shadowSide = FrontSide; 178 | e.material.needsUpdate = true; 179 | this.deepFunction.forEach((fn) => 180 | fn({ 181 | e, 182 | item: configItem, 183 | }) 184 | ); 185 | } 186 | }); 187 | 188 | this.addclips(scene.animations, configItem["layeridx"]); 189 | callback ? callback() : ""; 190 | } 191 | /* 192 | *@description: 添加动画组 193 | *@author: yangj 194 | *@date: 2023-03-04 16:26:24 195 | *@return: 196 | */ 197 | private addclips(clips: any, sidx: number) { 198 | clips.forEach((item) => { 199 | this.gScenes[sidx].animations.push(item); 200 | }); 201 | } 202 | /* 203 | *@description: 执行动画 204 | *@author: yangj 205 | *@date: 2023-03-04 14:01:12 206 | *@return: 207 | */ 208 | playAllClipes(sceneidx: number) { 209 | // 先全部停止 210 | if (this.mixer) { 211 | this.mixer.stopAllAction(); 212 | this.mixer.uncacheRoot(this.mixer.getRoot()); 213 | this.mixer = null; 214 | this.mixer = new AnimationMixer(this.gScenes[sceneidx]); 215 | } else { 216 | this.mixer = new AnimationMixer(this.gScenes[sceneidx]); 217 | } 218 | this.gScenes[sceneidx].animations.forEach((clip) => { 219 | this.mixer.clipAction(clip).reset().play(); 220 | }); 221 | } 222 | /* 223 | *@description: 执行名称动画 224 | *@author: yangj 225 | *@date: 2023-03-19 18:48:08 226 | *@return: 227 | */ 228 | playNameClipes(sceneidx: number, clipName: string) { 229 | // 先全部停止 230 | if (this.mixer) { 231 | this.mixer.stopAllAction(); 232 | this.mixer.uncacheRoot(this.mixer.getRoot()); 233 | this.mixer = null; 234 | this.mixer = new AnimationMixer(this.gScenes[sceneidx]); 235 | } else { 236 | this.mixer = new AnimationMixer(this.gScenes[sceneidx]); 237 | } 238 | this.gScenes[sceneidx].animations.forEach((clip) => { 239 | if (clip.name === clipName) { 240 | this.mixer.clipAction(clip).reset().play(); 241 | } 242 | }); 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /Threejs/shader/sky.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BackSide, 3 | BoxGeometry, 4 | Mesh, 5 | ShaderMaterial, 6 | UniformsUtils, 7 | Vector3, 8 | } from "three"; 9 | 10 | /** 11 | * Based on "A Practical Analytic Model for Daylight" 12 | * aka The Preetham Model, the de facto standard analytic skydome model 13 | * https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight 14 | * 15 | * First implemented by Simon Wallner 16 | * http://simonwallner.at/project/atmospheric-scattering/ 17 | * 18 | * Improved by Martin Upitis 19 | * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR 20 | * 21 | * Three.js integration by zz85 http://twitter.com/blurspline 22 | */ 23 | 24 | class Sky extends Mesh { 25 | isSky: boolean; 26 | constructor() { 27 | const shader = (Sky as any).SkyShader; 28 | 29 | const material = new ShaderMaterial({ 30 | name: "SkyShader", 31 | fragmentShader: shader.fragmentShader, 32 | vertexShader: shader.vertexShader, 33 | uniforms: UniformsUtils.clone(shader.uniforms), 34 | side: BackSide, 35 | depthWrite: false, 36 | }); 37 | 38 | super(new BoxGeometry(1, 1, 1), material); 39 | 40 | this.isSky = true; 41 | } 42 | } 43 | 44 | (Sky as any).SkyShader = { 45 | uniforms: { 46 | turbidity: { value: 2 }, 47 | rayleigh: { value: 1 }, 48 | mieCoefficient: { value: 0.005 }, 49 | mieDirectionalG: { value: 0.8 }, 50 | sunPosition: { value: new Vector3() }, 51 | up: { value: new Vector3(0, 1, 0) }, 52 | }, 53 | 54 | vertexShader: /* glsl */ ` 55 | uniform vec3 sunPosition; 56 | uniform float rayleigh; 57 | uniform float turbidity; 58 | uniform float mieCoefficient; 59 | uniform vec3 up; 60 | 61 | varying vec3 vWorldPosition; 62 | varying vec3 vSunDirection; 63 | varying float vSunfade; 64 | varying vec3 vBetaR; 65 | varying vec3 vBetaM; 66 | varying float vSunE; 67 | 68 | // constants for atmospheric scattering 69 | const float e = 2.71828182845904523536028747135266249775724709369995957; 70 | const float pi = 3.141592653589793238462643383279502884197169; 71 | 72 | // wavelength of used primaries, according to preetham 73 | const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 ); 74 | // this pre-calcuation replaces older TotalRayleigh(vec3 lambda) function: 75 | // (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn)) 76 | const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 ); 77 | 78 | // mie stuff 79 | // K coefficient for the primaries 80 | const float v = 4.0; 81 | const vec3 K = vec3( 0.686, 0.678, 0.666 ); 82 | // MieConst = pi * pow( ( 2.0 * pi ) / lambda, vec3( v - 2.0 ) ) * K 83 | const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 ); 84 | 85 | // earth shadow hack 86 | // cutoffAngle = pi / 1.95; 87 | const float cutoffAngle = 1.6110731556870734; 88 | const float steepness = 1.5; 89 | const float EE = 1000.0; 90 | 91 | float sunIntensity( float zenithAngleCos ) { 92 | zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 ); 93 | return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) ); 94 | } 95 | 96 | vec3 totalMie( float T ) { 97 | float c = ( 0.2 * T ) * 10E-18; 98 | return 0.434 * c * MieConst; 99 | } 100 | 101 | void main() { 102 | 103 | vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); 104 | vWorldPosition = worldPosition.xyz; 105 | 106 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); 107 | gl_Position.z = gl_Position.w; // set z to camera.far 108 | 109 | vSunDirection = normalize( sunPosition ); 110 | 111 | vSunE = sunIntensity( dot( vSunDirection, up ) ); 112 | 113 | vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 ); 114 | 115 | float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) ); 116 | 117 | // extinction (absorbtion + out scattering) 118 | // rayleigh coefficients 119 | vBetaR = totalRayleigh * rayleighCoefficient; 120 | 121 | // mie coefficients 122 | vBetaM = totalMie( turbidity ) * mieCoefficient; 123 | 124 | }`, 125 | 126 | fragmentShader: /* glsl */ ` 127 | varying vec3 vWorldPosition; 128 | varying vec3 vSunDirection; 129 | varying float vSunfade; 130 | varying vec3 vBetaR; 131 | varying vec3 vBetaM; 132 | varying float vSunE; 133 | 134 | uniform float mieDirectionalG; 135 | uniform vec3 up; 136 | 137 | const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 ); 138 | 139 | // constants for atmospheric scattering 140 | const float pi = 3.141592653589793238462643383279502884197169; 141 | 142 | const float n = 1.0003; // refractive index of air 143 | const float N = 2.545E25; // number of molecules per unit volume for air at 288.15K and 1013mb (sea level -45 celsius) 144 | 145 | // optical length at zenith for molecules 146 | const float rayleighZenithLength = 8.4E3; 147 | const float mieZenithLength = 1.25E3; 148 | // 66 arc seconds -> degrees, and the cosine of that 149 | const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324; 150 | 151 | // 3.0 / ( 16.0 * pi ) 152 | const float THREE_OVER_SIXTEENPI = 0.05968310365946075; 153 | // 1.0 / ( 4.0 * pi ) 154 | const float ONE_OVER_FOURPI = 0.07957747154594767; 155 | 156 | float rayleighPhase( float cosTheta ) { 157 | return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) ); 158 | } 159 | 160 | float hgPhase( float cosTheta, float g ) { 161 | float g2 = pow( g, 2.0 ); 162 | float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 ); 163 | return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse ); 164 | } 165 | 166 | void main() { 167 | 168 | vec3 direction = normalize( vWorldPosition - cameraPos ); 169 | 170 | // optical length 171 | // cutoff angle at 90 to avoid singularity in next formula. 172 | float zenithAngle = acos( max( 0.0, dot( up, direction ) ) ); 173 | float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) ); 174 | float sR = rayleighZenithLength * inverse; 175 | float sM = mieZenithLength * inverse; 176 | 177 | // combined extinction factor 178 | vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) ); 179 | 180 | // in scattering 181 | float cosTheta = dot( direction, vSunDirection ); 182 | 183 | float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 ); 184 | vec3 betaRTheta = vBetaR * rPhase; 185 | 186 | float mPhase = hgPhase( cosTheta, mieDirectionalG ); 187 | vec3 betaMTheta = vBetaM * mPhase; 188 | 189 | vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) ); 190 | Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - dot( up, vSunDirection ), 5.0 ), 0.0, 1.0 ) ); 191 | 192 | // nightsky 193 | float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2] 194 | float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2] 195 | vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 ); 196 | vec3 L0 = vec3( 0.1 ) * Fex; 197 | 198 | // composition + solar disc 199 | float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta ); 200 | L0 += ( vSunE * 19000.0 * Fex ) * sundisk; 201 | 202 | vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 ); 203 | 204 | vec3 retColor = pow( texColor, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) ); 205 | 206 | gl_FragColor = vec4( retColor, 1.0 ); 207 | 208 | #include 209 | #include 210 | 211 | }`, 212 | }; 213 | 214 | export { Sky }; 215 | -------------------------------------------------------------------------------- /lib/plugins/particleExamples.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @file: zhdParticleExamples. 3 | * @authors: yangj (yangjia@fjxhx.cc). 4 | * @createDate: 2022/3/4. 5 | * @version: 1.0. 6 | * @copyright © 2021 新和兴 All rights reserved. 7 | */ 8 | import * as THREE from "three"; 9 | import { Tween } from "./particleTween"; 10 | declare let Examples: { 11 | fountain: { 12 | positionStyle: 1; 13 | positionBase: THREE.Vector3; 14 | positionSpread: THREE.Vector3; 15 | velocityStyle: 1; 16 | velocityBase: THREE.Vector3; 17 | velocitySpread: THREE.Vector3; 18 | accelerationBase: THREE.Vector3; 19 | particleTexture: THREE.Texture; 20 | angleBase: number; 21 | angleSpread: number; 22 | angleVelocityBase: number; 23 | angleVelocitySpread: number; 24 | sizeTween: Tween; 25 | opacityTween: Tween; 26 | colorTween: Tween; 27 | particlesPerSecond: number; 28 | particleDeathAge: number; 29 | emitterDeathAge: number; 30 | }; 31 | fireball: { 32 | positionStyle: 2; 33 | positionBase: THREE.Vector3; 34 | positionRadius: number; 35 | velocityStyle: 2; 36 | speedBase: number; 37 | speedSpread: number; 38 | particleTexture: THREE.Texture; 39 | sizeTween: Tween; 40 | opacityTween: Tween; 41 | colorBase: THREE.Vector3; 42 | blendStyle: THREE.Blending; 43 | particlesPerSecond: number; 44 | particleDeathAge: number; 45 | emitterDeathAge: number; 46 | }; 47 | smoke: { 48 | positionStyle: 1; 49 | positionBase: THREE.Vector3; 50 | positionSpread: THREE.Vector3; 51 | velocityStyle: 1; 52 | velocityBase: THREE.Vector3; 53 | velocitySpread: THREE.Vector3; 54 | accelerationBase: THREE.Vector3; 55 | particleTexture: THREE.Texture; 56 | speedBase: number; 57 | speedSpread: number; 58 | angleBase: number; 59 | angleSpread: number; 60 | angleVelocityBase: number; 61 | angleVelocitySpread: number; 62 | sizeTween: Tween; 63 | opacityTween: Tween; 64 | colorTween: Tween; 65 | particlesPerSecond: number; 66 | particleDeathAge: number; 67 | emitterDeathAge: number; 68 | }; 69 | clouds: { 70 | positionStyle: 1; 71 | positionBase: THREE.Vector3; 72 | positionSpread: THREE.Vector3; 73 | velocityStyle: 1; 74 | velocityBase: THREE.Vector3; 75 | velocitySpread: THREE.Vector3; 76 | particleTexture: THREE.Texture; 77 | sizeBase: number; 78 | sizeSpread: number; 79 | colorBase: THREE.Vector3; 80 | opacityTween: Tween; 81 | particlesPerSecond: number; 82 | particleDeathAge: number; 83 | emitterDeathAge: number; 84 | }; 85 | snow: { 86 | positionStyle: 1; 87 | positionBase: THREE.Vector3; 88 | positionSpread: THREE.Vector3; 89 | velocityStyle: 1; 90 | velocityBase: THREE.Vector3; 91 | velocitySpread: THREE.Vector3; 92 | accelerationBase: THREE.Vector3; 93 | angleBase: number; 94 | angleSpread: number; 95 | angleVelocityBase: number; 96 | angleVelocitySpread: number; 97 | particleTexture: THREE.Texture; 98 | sizeTween: Tween; 99 | colorBase: THREE.Vector3; 100 | opacityTween: Tween; 101 | particlesPerSecond: number; 102 | particleDeathAge: number; 103 | emitterDeathAge: number; 104 | }; 105 | rain: { 106 | positionStyle: 1; 107 | positionBase: THREE.Vector3; 108 | positionSpread: THREE.Vector3; 109 | velocityStyle: 1; 110 | velocityBase: THREE.Vector3; 111 | velocitySpread: THREE.Vector3; 112 | accelerationBase: THREE.Vector3; 113 | particleTexture: THREE.Texture; 114 | sizeBase: number; 115 | sizeSpread: number; 116 | colorBase: THREE.Vector3; 117 | colorSpread: THREE.Vector3; 118 | opacityBase: number; 119 | particlesPerSecond: number; 120 | particleDeathAge: number; 121 | emitterDeathAge: number; 122 | }; 123 | starfield: { 124 | positionStyle: 1; 125 | positionBase: THREE.Vector3; 126 | positionSpread: THREE.Vector3; 127 | velocityStyle: 1; 128 | velocityBase: THREE.Vector3; 129 | velocitySpread: THREE.Vector3; 130 | angleBase: number; 131 | angleSpread: number; 132 | angleVelocityBase: number; 133 | angleVelocitySpread: number; 134 | particleTexture: THREE.Texture; 135 | sizeBase: number; 136 | sizeSpread: number; 137 | colorBase: THREE.Vector3; 138 | colorSpread: THREE.Vector3; 139 | opacityBase: number; 140 | particlesPerSecond: number; 141 | particleDeathAge: number; 142 | emitterDeathAge: number; 143 | }; 144 | haze: { 145 | positionStyle: 1; 146 | positionBase: THREE.Vector3; 147 | positionSpread: THREE.Vector3; 148 | velocityStyle: 1; 149 | velocityBase: THREE.Vector3; 150 | velocitySpread: THREE.Vector3; 151 | angleBase: number; 152 | angleSpread: number; 153 | angleVelocityBase: number; 154 | angleVelocitySpread: number; 155 | particleTexture: THREE.Texture; 156 | sizeBase: number; 157 | sizeSpread: number; 158 | colorBase: THREE.Vector3; 159 | colorSpread: THREE.Vector3; 160 | opacityBase: number; 161 | particlesPerSecond: number; 162 | particleDeathAge: number; 163 | emitterDeathAge: number; 164 | }; 165 | fireflies: { 166 | positionStyle: 1; 167 | positionBase: THREE.Vector3; 168 | positionSpread: THREE.Vector3; 169 | velocityStyle: 1; 170 | velocityBase: THREE.Vector3; 171 | velocitySpread: THREE.Vector3; 172 | particleTexture: THREE.Texture; 173 | sizeBase: number; 174 | sizeSpread: number; 175 | opacityTween: Tween; 176 | colorBase: THREE.Vector3; 177 | colorSpread: THREE.Vector3; 178 | particlesPerSecond: number; 179 | particleDeathAge: number; 180 | emitterDeathAge: number; 181 | }; 182 | startunnel: { 183 | positionStyle: 1; 184 | positionBase: THREE.Vector3; 185 | positionSpread: THREE.Vector3; 186 | velocityStyle: 1; 187 | velocityBase: THREE.Vector3; 188 | velocitySpread: THREE.Vector3; 189 | angleBase: number; 190 | angleSpread: number; 191 | angleVelocityBase: number; 192 | angleVelocitySpread: number; 193 | particleTexture: THREE.Texture; 194 | sizeBase: number; 195 | sizeSpread: number; 196 | colorBase: THREE.Vector3; 197 | opacityBase: number; 198 | blendStyle: THREE.Blending; 199 | particlesPerSecond: number; 200 | particleDeathAge: number; 201 | emitterDeathAge: number; 202 | }; 203 | firework: { 204 | positionStyle: 2; 205 | positionBase: THREE.Vector3; 206 | positionRadius: number; 207 | velocityStyle: 2; 208 | speedBase: number; 209 | speedSpread: number; 210 | accelerationBase: THREE.Vector3; 211 | particleTexture: THREE.Texture; 212 | sizeTween: Tween; 213 | opacityTween: Tween; 214 | colorTween: Tween; 215 | blendStyle: THREE.Blending; 216 | particlesPerSecond: number; 217 | particleDeathAge: number; 218 | emitterDeathAge: number; 219 | }; 220 | candle: { 221 | positionStyle: 2; 222 | positionBase: THREE.Vector3; 223 | positionRadius: number; 224 | velocityStyle: 1; 225 | velocityBase: THREE.Vector3; 226 | velocitySpread: THREE.Vector3; 227 | speedBase: number; 228 | speedSpread: number; 229 | particleTexture: THREE.Texture; 230 | sizeTween: Tween; 231 | opacityTween: Tween; 232 | colorTween: Tween; 233 | blendStyle: THREE.Blending; 234 | particlesPerSecond: number; 235 | particleDeathAge: number; 236 | emitterDeathAge: number; 237 | }; 238 | }; 239 | export default Examples; 240 | -------------------------------------------------------------------------------- /Threejs/plugins/particleExamples.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @file: zhdParticleExamples. 3 | * @authors: yangj (yangjia@fjxhx.cc). 4 | * @createDate: 2022/3/4. 5 | * @version: 1.0. 6 | * @copyright © 2021 新和兴 All rights reserved. 7 | */ 8 | import * as THREE from "three"; 9 | import { Tween } from "./particleTween"; 10 | 11 | let gAppPath = "../public/lizi/"; 12 | var Type = Object.freeze({ CUBE: 1, SPHERE: 2 }); 13 | const textureLoader = new THREE.TextureLoader(); 14 | let Examples = { 15 | fountain: { 16 | positionStyle: Type.CUBE, 17 | positionBase: new THREE.Vector3(0, 105, 0), 18 | positionSpread: new THREE.Vector3(10, 0, 10), 19 | 20 | velocityStyle: Type.CUBE, 21 | velocityBase: new THREE.Vector3(0, 60, 0), 22 | velocitySpread: new THREE.Vector3(100, 20, 100), 23 | 24 | accelerationBase: new THREE.Vector3(0, -100, 0), 25 | 26 | particleTexture: textureLoader.load(gAppPath + "star.png"), 27 | 28 | angleBase: 0, 29 | angleSpread: 180, 30 | angleVelocityBase: 0, 31 | angleVelocitySpread: 360 * 4, 32 | 33 | sizeTween: new Tween([0, 1], [1, 10]), 34 | opacityTween: new Tween([2, 3], [1, 0]), 35 | colorTween: new Tween( 36 | [0.5, 2], 37 | [new THREE.Vector3(0, 1, 0.5), new THREE.Vector3(0.8, 1, 0.5)] 38 | ), 39 | 40 | particlesPerSecond: 200, 41 | particleDeathAge: 3.0, 42 | emitterDeathAge: 60, 43 | }, 44 | 45 | fireball: { 46 | positionStyle: Type.SPHERE, 47 | positionBase: new THREE.Vector3(0, 50, 0), 48 | positionRadius: 2, 49 | 50 | velocityStyle: Type.SPHERE, 51 | speedBase: 2, 52 | speedSpread: 10, 53 | 54 | particleTexture: textureLoader.load(gAppPath + "smokeparticle.png"), 55 | 56 | sizeTween: new Tween([0, 0.1], [1, 50]), 57 | opacityTween: new Tween([0.7, 1], [1, 0]), 58 | colorBase: new THREE.Vector3(0.02, 1, 0.4), 59 | blendStyle: THREE.AdditiveBlending, 60 | 61 | particlesPerSecond: 600, 62 | particleDeathAge: 0.5, 63 | emitterDeathAge: 60, 64 | }, 65 | 66 | smoke: { 67 | positionStyle: Type.CUBE, 68 | positionBase: new THREE.Vector3(0, 0, 0), 69 | positionSpread: new THREE.Vector3(2, 0, 2), 70 | 71 | velocityStyle: Type.CUBE, 72 | velocityBase: new THREE.Vector3(0, 30, 0), 73 | velocitySpread: new THREE.Vector3(20, 30, 20), 74 | accelerationBase: new THREE.Vector3(0, -10, 0), 75 | 76 | particleTexture: textureLoader.load(gAppPath + "smokeparticle.png"), 77 | speedBase: 10, 78 | speedSpread: 10, 79 | angleBase: 0, 80 | angleSpread: 120, 81 | angleVelocityBase: 0, 82 | angleVelocitySpread: 720, 83 | 84 | sizeTween: new Tween([0, 1], [32, 128]), 85 | opacityTween: new Tween([0.8, 2], [0.5, 0]), 86 | colorTween: new Tween( 87 | [0.4, 1], 88 | [new THREE.Vector3(0, 0, 0.2), new THREE.Vector3(0, 0, 0.5)] 89 | ), 90 | 91 | particlesPerSecond: 100, 92 | particleDeathAge: 1.0, 93 | emitterDeathAge: 5, 94 | }, 95 | 96 | clouds: { 97 | positionStyle: Type.CUBE, 98 | positionBase: new THREE.Vector3(-100, 100, 0), 99 | positionSpread: new THREE.Vector3(300, 20, 300), 100 | 101 | velocityStyle: Type.CUBE, 102 | velocityBase: new THREE.Vector3(100, 0, 0), 103 | velocitySpread: new THREE.Vector3(100, 0, 0), 104 | 105 | particleTexture: textureLoader.load(gAppPath + "cloud_baseColor.png"), 106 | 107 | sizeBase: 200.0, 108 | sizeSpread: 100.0, 109 | colorBase: new THREE.Vector3(0.0, 0.0, 1), // H,S,L 110 | opacityTween: new Tween([0, 1, 4, 5], [0, 1, 1, 0]), 111 | 112 | particlesPerSecond: 200, 113 | particleDeathAge: 10.0, 114 | emitterDeathAge: 60, 115 | }, 116 | 117 | snow: { 118 | positionStyle: Type.CUBE, 119 | positionBase: new THREE.Vector3(0, 200, 0), 120 | positionSpread: new THREE.Vector3(200, 0, 200), 121 | 122 | velocityStyle: Type.CUBE, 123 | velocityBase: new THREE.Vector3(40, -100, 0), 124 | velocitySpread: new THREE.Vector3(-30, 200, 10), 125 | accelerationBase: new THREE.Vector3(0, -10, 0), 126 | 127 | angleBase: 0, 128 | angleSpread: 720, 129 | angleVelocityBase: 0, 130 | angleVelocitySpread: 60, 131 | 132 | particleTexture: textureLoader.load(gAppPath + "snowflake.png"), 133 | 134 | sizeTween: new Tween([0, 0.25], [4, 5]), 135 | colorBase: new THREE.Vector3(0.66, 1.0, 0.9), // H,S,L 136 | opacityTween: new Tween([2, 3], [0.8, 0]), 137 | 138 | particlesPerSecond: 500, 139 | particleDeathAge: 1.0, 140 | emitterDeathAge: 60, 141 | }, 142 | 143 | rain: { 144 | positionStyle: Type.CUBE, 145 | positionBase: new THREE.Vector3(0, 200, 0), 146 | positionSpread: new THREE.Vector3(200, 0, 200), 147 | 148 | velocityStyle: Type.CUBE, 149 | velocityBase: new THREE.Vector3(0, -200, 0), 150 | velocitySpread: new THREE.Vector3(50, 70, 50), 151 | accelerationBase: new THREE.Vector3(0, -10, 0), 152 | 153 | particleTexture: textureLoader.load(gAppPath + "rain.png"), 154 | sizeBase: 30, 155 | sizeSpread: 40.0, 156 | colorBase: new THREE.Vector3(0.66, 1.0, 0.9), // H,S,L 157 | colorSpread: new THREE.Vector3(0.0, 0, 0.1), 158 | opacityBase: 0.4, 159 | 160 | particlesPerSecond: 500, 161 | particleDeathAge: 1.0, 162 | emitterDeathAge: 60, 163 | }, 164 | 165 | starfield: { 166 | positionStyle: Type.CUBE, 167 | positionBase: new THREE.Vector3(0, 200, 0), 168 | positionSpread: new THREE.Vector3(400, 50, 400), 169 | 170 | velocityStyle: Type.CUBE, 171 | velocityBase: new THREE.Vector3(0, 0, 0), 172 | velocitySpread: new THREE.Vector3(0.5, 0.5, 0.5), 173 | 174 | angleBase: 0, 175 | angleSpread: 720, 176 | angleVelocityBase: 0, 177 | angleVelocitySpread: 4, 178 | 179 | particleTexture: textureLoader.load(gAppPath + "spikey.png"), 180 | 181 | sizeBase: 10.0, 182 | sizeSpread: 2.0, 183 | colorBase: new THREE.Vector3(0.15, 1.0, 0.9), // H,S,L 184 | colorSpread: new THREE.Vector3(0.0, 0.0, 0.2), 185 | opacityBase: 1, 186 | 187 | particlesPerSecond: 1000, 188 | particleDeathAge: 60.0, 189 | emitterDeathAge: 0.1, 190 | }, 191 | //雾霾 192 | haze: { 193 | positionStyle: Type.CUBE, 194 | positionBase: new THREE.Vector3(0, 50, 0), 195 | positionSpread: new THREE.Vector3(400, 100, 400), 196 | 197 | velocityStyle: Type.CUBE, 198 | velocityBase: new THREE.Vector3(0, 0, 0), 199 | velocitySpread: new THREE.Vector3(100.5, 0.5, 100.5), 200 | 201 | angleBase: 0, 202 | angleSpread: 0, 203 | angleVelocityBase: 0, 204 | angleVelocitySpread: 4, 205 | 206 | particleTexture: textureLoader.load(gAppPath + "smoke512.png"), 207 | 208 | sizeBase: 1000.0, 209 | sizeSpread: 2.0, 210 | colorBase: new THREE.Vector3(0.15, 1.0, 0), // H,S,L 211 | colorSpread: new THREE.Vector3(0.0, 0.0, 0.2), 212 | opacityBase: 0.15, 213 | 214 | particlesPerSecond: 1000, 215 | particleDeathAge: 60.0, 216 | emitterDeathAge: 0.1, 217 | }, 218 | fireflies: { 219 | positionStyle: Type.CUBE, 220 | positionBase: new THREE.Vector3(0, 100, 0), 221 | positionSpread: new THREE.Vector3(400, 200, 400), 222 | 223 | velocityStyle: Type.CUBE, 224 | velocityBase: new THREE.Vector3(0, 0, 0), 225 | velocitySpread: new THREE.Vector3(60, 20, 60), 226 | 227 | particleTexture: textureLoader.load(gAppPath + "spark.png"), 228 | 229 | sizeBase: 30.0, 230 | sizeSpread: 10.0, 231 | opacityTween: new Tween( 232 | [0.0, 1.0, 1.1, 2.0, 2.1, 3.0, 3.1, 4.0, 4.1, 5.0, 5.1, 6.0, 6.1], 233 | [0.2, 0.2, 1.0, 1.0, 0.2, 0.2, 1.0, 1.0, 0.2, 0.2, 1.0, 1.0, 0.2] 234 | ), 235 | colorBase: new THREE.Vector3(0.3, 1.0, 0.6), // H,S,L 236 | colorSpread: new THREE.Vector3(0.3, 0.0, 0.0), 237 | 238 | particlesPerSecond: 20, 239 | particleDeathAge: 6.1, 240 | emitterDeathAge: 600, 241 | }, 242 | 243 | startunnel: { 244 | positionStyle: Type.CUBE, 245 | positionBase: new THREE.Vector3(0, 0, 0), 246 | positionSpread: new THREE.Vector3(10, 10, 10), 247 | 248 | velocityStyle: Type.CUBE, 249 | velocityBase: new THREE.Vector3(0, 100, 200), 250 | velocitySpread: new THREE.Vector3(40, 40, 80), 251 | 252 | angleBase: 0, 253 | angleSpread: 720, 254 | angleVelocityBase: 10, 255 | angleVelocitySpread: 0, 256 | 257 | particleTexture: textureLoader.load(gAppPath + "spikey.png"), 258 | 259 | sizeBase: 4.0, 260 | sizeSpread: 2.0, 261 | colorBase: new THREE.Vector3(0.15, 1.0, 0.8), // H,S,L 262 | opacityBase: 1, 263 | blendStyle: THREE.AdditiveBlending, 264 | 265 | particlesPerSecond: 500, 266 | particleDeathAge: 4.0, 267 | emitterDeathAge: 60, 268 | }, 269 | 270 | firework: { 271 | positionStyle: Type.SPHERE, 272 | positionBase: new THREE.Vector3(0, 100, 0), 273 | positionRadius: 10, 274 | 275 | velocityStyle: Type.SPHERE, 276 | speedBase: 90, 277 | speedSpread: 10, 278 | 279 | accelerationBase: new THREE.Vector3(0, -80, 0), 280 | 281 | particleTexture: textureLoader.load(gAppPath + "spark.png"), 282 | 283 | sizeTween: new Tween([0.5, 0.7, 1.3], [5, 40, 1]), 284 | opacityTween: new Tween([0.2, 0.7, 2.5], [0.75, 1, 0]), 285 | colorTween: new Tween( 286 | [0.4, 0.8, 1.0], 287 | [ 288 | new THREE.Vector3(0, 1, 1), 289 | new THREE.Vector3(0, 1, 0.6), 290 | new THREE.Vector3(0.8, 1, 0.6), 291 | ] 292 | ), 293 | blendStyle: THREE.AdditiveBlending, 294 | 295 | particlesPerSecond: 3000, 296 | particleDeathAge: 2.5, 297 | emitterDeathAge: 0.2, 298 | }, 299 | 300 | candle: { 301 | positionStyle: Type.SPHERE, 302 | positionBase: new THREE.Vector3(0, 50, 0), 303 | positionRadius: 2, 304 | 305 | velocityStyle: Type.CUBE, 306 | velocityBase: new THREE.Vector3(0, 30, 0), 307 | velocitySpread: new THREE.Vector3(15, 30, 15), 308 | speedBase: 10, 309 | speedSpread: 10, 310 | 311 | particleTexture: textureLoader.load(gAppPath + "smokeparticle.png"), 312 | 313 | sizeTween: new Tween([10, 10.3, 10.2], [30, 15, 10]), 314 | opacityTween: new Tween([0.9, 1.5], [1, 0]), 315 | colorTween: new Tween( 316 | [0.5, 1.0], 317 | [new THREE.Vector3(0.02, 1, 0.5), new THREE.Vector3(0.05, 1, 0)] 318 | ), 319 | blendStyle: THREE.AdditiveBlending, 320 | 321 | particlesPerSecond: 150, 322 | particleDeathAge: 1, 323 | emitterDeathAge: 10, 324 | }, 325 | }; 326 | export default Examples; 327 | -------------------------------------------------------------------------------- /Threejs/index.ts: -------------------------------------------------------------------------------- 1 | import { Scene, Group, Cache } from "three"; 2 | import { 3 | ViewerType, 4 | ViewerParams, 5 | SpriteParams, 6 | ParadeParams, 7 | InitWaterParams, 8 | } from "./types/types"; 9 | import { Params } from "./plugins/params"; 10 | import { Camera } from "./plugins/camera"; 11 | import { Renderer } from "./plugins/render"; 12 | import { Control } from "./plugins/control"; 13 | import { Animate } from "./plugins/animate"; 14 | import { Model } from "./plugins/model"; 15 | import { Sky } from "./plugins/skybox"; 16 | import { Ambient } from "./plugins/lights/ambient"; 17 | import { SkyLight } from "./plugins/lights/skyLight"; 18 | import { Directional } from "./plugins/lights/directional"; 19 | import { PointLight } from "./plugins/lights/point"; 20 | import { SpotLight } from "./plugins/lights/spot"; 21 | import { RectArea } from "./plugins/lights/rectArea"; 22 | import { Environment } from "./plugins/environment"; 23 | import { Event } from "./plugins/event"; 24 | import { Source } from "./plugins/source"; 25 | import { Sprite } from "./plugins/sprite"; 26 | import { Parade } from "./plugins/parade"; 27 | import { ParticleEngine } from "./plugins/particleEngine"; 28 | import ParticleEngineExamples from "./plugins/particleExamples"; 29 | import { Tween } from "./plugins/particleTween"; 30 | import { Fog } from "./plugins/fog"; 31 | import { Water } from "./plugins/water"; 32 | 33 | const MAP_NAMES = [ 34 | "map", 35 | "aoMap", 36 | "emissiveMap", 37 | "glossinessMap", 38 | "metalnessMap", 39 | "normalMap", 40 | "roughnessMap", 41 | "specularMap", 42 | ]; 43 | function traverseMaterials(object, callback) { 44 | object.traverse((node) => { 45 | if (!node.isMesh) return; 46 | const materials = Array.isArray(node.material) 47 | ? node.material 48 | : [node.material]; 49 | materials.forEach(callback); 50 | }); 51 | } 52 | 53 | export class Viewer extends Params implements ViewerType { 54 | constructor(options: ViewerParams) { 55 | super(options); 56 | this.createScene(); 57 | this.initAnimate(); 58 | this.initRender(); 59 | this.initControls(); 60 | this.initAmbient(); 61 | } 62 | /* 63 | *@description: 创建场景 64 | *@author: yangj 65 | *@date: 2023-03-04 09:34:41 66 | *@return: 67 | */ 68 | private createScene() { 69 | for (let i = 0; i < 15; i++) { 70 | this.gStatus[i] = false; 71 | const scene = new Scene(); 72 | const mainGroup = new Group(); 73 | //环境对象群 74 | const AMGroup = new Group(); 75 | //Ray拾取对象群 76 | const RayGrop = new Group(); 77 | mainGroup.add(AMGroup, RayGrop); 78 | scene.add(mainGroup); 79 | this.gScenes.push(scene); 80 | this.gAmGroup.push(AMGroup); 81 | this.gRayGroup.push(RayGrop); 82 | } 83 | this.scene = this.gScenes[this.sceneidx]; //当前场景 84 | this.cameraClass = new Camera(this.options.el); 85 | this.activeCamera = this.cameraClass.camera; //激活相机 86 | this.scene.add(this.activeCamera); 87 | } 88 | /* 89 | *@description: 初始化帧动画 90 | *@author: yangj 91 | *@date: 2023-03-04 12:56:30 92 | *@return: 93 | */ 94 | private initAnimate() { 95 | this.animate = new Animate({ 96 | clock: this.clock, 97 | }); 98 | } 99 | /* 100 | *@description: 天空盒子 101 | *@author: yangj 102 | *@date: 2023-03-04 17:23:13 103 | *@return: 104 | */ 105 | initSky() { 106 | this.sky = new Sky({ 107 | gScenes: this.gScenes, 108 | path: this.options.path, 109 | sceneidx: this.sceneidx, 110 | }); 111 | } 112 | /* 113 | *@description: 环境贴图 114 | *@author: yangj 115 | *@date: 2023-03-04 20:43:33 116 | *@return: 117 | */ 118 | initEnvironment(environment: EnvironmentType) { 119 | this.environment = new Environment({ 120 | renderer: this.renderer, 121 | path: this.options.path, 122 | scene: this.gScenes[this.sceneidx], 123 | environment: environment, 124 | }); 125 | this.environment.init(); 126 | } 127 | /* 128 | *@description: 事件 129 | *@author: yangj 130 | *@date: 2023-03-04 21:03:26 131 | *@return: 132 | */ 133 | initEvent(types: EventTypes[]) { 134 | this.event = new Event({ 135 | types: types, 136 | el: this.options.el, 137 | camera: this.activeCamera, 138 | scene: this.gRayGroup[this.sceneidx], 139 | }); 140 | this.event.init(); 141 | } 142 | /* 143 | *@description:渲染 144 | *@author: yangj 145 | *@date: 2023-03-04 10:53:31 146 | *@return: 147 | */ 148 | private initRender() { 149 | this.renderer = new Renderer(this.options.el).renderer; 150 | this.options.el.appendChild(this.renderer.domElement); 151 | this.animate?.animateFuntion.push(() => { 152 | this.options.tween.update(); 153 | this.renderer.render(this.scene, this.activeCamera); 154 | }); 155 | } 156 | /* 157 | *@description: 控制器 158 | *@author: yangj 159 | *@date: 2023-03-04 12:36:24 160 | *@return: 161 | */ 162 | private initControls() { 163 | this.controls = new Control({ 164 | camera: this.activeCamera, 165 | renderer: this.renderer, 166 | scene: this.gScenes, 167 | }); 168 | this.animate?.animateFuntion.push((delta) => { 169 | !this.controls.orbitControls.enabled && 170 | this.controls.orbitControls.update(delta); 171 | }); 172 | } 173 | /* 174 | *@description: 初始化场景 175 | *@author: yangj 176 | *@date: 2023-03-04 13:52:01 177 | *@return: 178 | */ 179 | initModel() { 180 | this.model = new Model({ 181 | gScenes: this.gScenes, 182 | gStatus: this.gStatus, 183 | gAmGroup: this.gAmGroup, 184 | gRayGroup: this.gRayGroup, 185 | baseURL: this.options.path, 186 | bus: this.options.bus, 187 | animateFuntion: this.animate.animateFuntion, 188 | }); 189 | } 190 | /* 191 | *@description: 环境光 192 | *@author: yangj 193 | *@date: 2023-03-04 16:53:53 194 | *@return: 195 | */ 196 | private initAmbient() { 197 | this.ambient = new Ambient({ 198 | scene: this.gScenes[this.sceneidx], 199 | renderer: this.renderer, 200 | }); 201 | this.ambient.setLight(1.5, 1); 202 | } 203 | /* 204 | *@description: 半球光 205 | *@author: yangj 206 | *@date: 2023-03-18 13:40:17 207 | *@return: 208 | */ 209 | initSkyLight(skyColor: string, earthColor: string, intensity: number) { 210 | this.hemisphereLight = new SkyLight(this.scene); 211 | this.hemisphereLight.init(skyColor, earthColor, intensity); 212 | } 213 | /* 214 | *@description: 平行光 215 | *@author: yangj 216 | *@date: 2023-03-18 16:07:02 217 | *@return: 218 | */ 219 | initDirectional(color: string, intensity: number) { 220 | this.directional = new Directional(this.scene); 221 | this.directional.init(color, intensity); 222 | } 223 | /* 224 | *@description: 点光源 225 | *@author: yangj 226 | *@date: 2023-03-18 16:39:38 227 | *@return: 228 | */ 229 | initPointLight( 230 | color: string, 231 | intensity: number, 232 | distance: number, 233 | decay?: number 234 | ): number { 235 | const pointLight = new PointLight(this.scene); 236 | pointLight.init(color, intensity, distance, decay); 237 | this.pointGroup.push(pointLight); 238 | return this.pointGroup.length - 1; 239 | } 240 | /* 241 | *@description: 聚光 242 | *@author: yangj 243 | *@date: 2023-03-18 17:13:57 244 | *@return: 245 | */ 246 | initSpotLight( 247 | color: string, 248 | intensity: number, 249 | distance: number, 250 | target?: THREE.Vector3 251 | ) { 252 | this.spotLight = new SpotLight(this.scene); 253 | this.spotLight.init(color, intensity, distance, target); 254 | } 255 | /* 256 | *@description: 单个区域光 257 | *@author: yangj 258 | *@date: 2023-03-18 18:50:36 259 | *@return: 260 | */ 261 | initRectArea( 262 | color: string, 263 | width: number, 264 | height: number, 265 | intensity: number 266 | ) { 267 | this.rectAreaLight = new RectArea(this.scene); 268 | this.rectAreaLight.init(color, width, height, intensity); 269 | } 270 | /* 271 | *@description: 矩形区域光 272 | *@author: yangj 273 | *@date: 2023-03-18 18:54:21 274 | *@return: 275 | */ 276 | initRectAreaBox( 277 | color: string, 278 | width: number, 279 | intensity: number, 280 | position: [number, number, number] 281 | ) { 282 | this.rectAreaLight = new RectArea(this.scene); 283 | this.rectAreaLight.initArea(color, width, intensity, position); 284 | } 285 | /* 286 | *@description: 雾 287 | *@author: yangj 288 | *@date: 2023-03-16 20:48:43 289 | *@return: 290 | */ 291 | initFog() { 292 | this.fog = new Fog(this.scene); 293 | } 294 | /* 295 | *@description: water 296 | *@author: yangj 297 | *@date: 2023-03-17 15:37:39 298 | *@return: 299 | */ 300 | initWater(options: InitWaterParams) { 301 | this.water = new Water({ 302 | ...options, 303 | animate: this.animate.animateFuntion, 304 | }); 305 | this.water.init(); 306 | } 307 | /* 308 | *@description: 资源加载类 309 | *@author: yangj 310 | *@date: 2023-03-09 17:14:40 311 | *@return: 312 | */ 313 | initSource() { 314 | this.souce = new Source(); 315 | } 316 | /* 317 | *@description: 粒子 318 | *@author: yangj 319 | *@date: 2023-03-09 20:34:11 320 | *@return: 321 | */ 322 | loadSprite({ texture, name }: SpriteParams): THREE.Object3D { 323 | let sprite = new Sprite(); 324 | sprite.init({ 325 | texture, 326 | name, 327 | }); 328 | this.spriteGroup.push(sprite); 329 | return sprite; 330 | } 331 | /* 332 | *@description: 巡检 333 | *@author: yangj 334 | *@date: 2023-03-10 15:42:52 335 | *@return: 336 | */ 337 | initParade(params: ParadeParams) { 338 | this.parade = new Parade(params); 339 | } 340 | /* 341 | *@description: 粒子系统 342 | *@author: yangj 343 | *@date: 2023-03-15 15:58:00 344 | *@return: 345 | */ 346 | initParticleEngine( 347 | particle: ParticleEngineType, 348 | mugen: boolean 349 | ): ParticleEngineType { 350 | particle = new ParticleEngine({ 351 | scene: this.gScenes[this.sceneidx], 352 | mugen, 353 | }); 354 | this.animate.animateFuntion.push((dt) => { 355 | if (particle.start) particle.update(dt); 356 | }); 357 | return particle; 358 | } 359 | /* 360 | *@description: 粒子过渡函数 361 | *@author: yangj 362 | *@date: 2023-03-15 22:11:54 363 | *@return: 364 | */ 365 | getParticleTween(times: number[], values: number[]): ParticleTween { 366 | return new Tween(times, values); 367 | } 368 | /* 369 | *@description: 设置粒子模式 370 | *@author: yangj 371 | *@date: 2023-03-15 16:07:32 372 | *@return: 373 | */ 374 | setParticleMode( 375 | particle: ParticleEngineType, 376 | key: ParticleKeys, 377 | ParticleExamplesParams: ParticleExamplesParams 378 | ) { 379 | particle.setValues(ParticleEngineExamples[key], ParticleExamplesParams); 380 | particle.initialize(this.scene); 381 | } 382 | /* 383 | *@description: 加载场景 384 | *@author: yangj 385 | *@date: 2023-03-04 13:37:42 386 | *@return: 387 | */ 388 | setScene(index: number, callback: Fn) { 389 | this.sceneidx = index; 390 | this.scene = this.gScenes[index]; 391 | this.controls.transformControls && this.controls.transformControls.detach(); // 先释放持有物 392 | this.scene.updateMatrix(); 393 | if (!this.gStatus[index]) { 394 | this.model && 395 | this.model.load(index, () => { 396 | callback instanceof Function && callback(); 397 | }); 398 | this.controls.transformControls && 399 | this.scene.add(this.controls.transformControls); 400 | this.initAmbient(); 401 | } else { 402 | this.options.bus.emit("scene", { 403 | type: "transition", 404 | value: true, 405 | }); 406 | setTimeout(() => { 407 | this.options.bus.emit("scene", { 408 | type: "transition", 409 | value: false, 410 | }); 411 | callback instanceof Function && callback(); 412 | }, 1500); 413 | } 414 | } 415 | 416 | /* 417 | *@description: 相机飞行 418 | *@author: yangj 419 | *@date: 2023-03-04 13:44:00 420 | *@return: 421 | */ 422 | flyTo(option: FlyToParams) { 423 | this.cameraClass?.flyTo(this.options.tween, this.controls, option); 424 | } 425 | /* 426 | *@description: 销毁场景 427 | *@author: yangj 428 | *@date: 2023-03-05 14:08:07 429 | *@return: 430 | */ 431 | destroy() { 432 | if (this.animate?.frameId) cancelAnimationFrame(this.animate?.frameId); //销毁requestAnimationFrame 433 | this.scene.traverse((child) => { 434 | child.userData = {}; 435 | if ( 436 | (child as any).material?.dispose && 437 | typeof (child as any).material.dispose === "function" 438 | ) { 439 | (child as any).material.dispose(); 440 | } 441 | if ((child as any).geometry) { 442 | (child as any).geometry.dispose(); 443 | } 444 | child = null; 445 | }); 446 | this.options.tween.removeAll(); 447 | this.renderer.forceContextLoss(); //销毁context 448 | traverseMaterials(this.scene, (material) => { 449 | MAP_NAMES.forEach((map) => { 450 | if (material[map]) material[map].dispose(); 451 | }); 452 | }); 453 | console.log("gapp.scene:", this.renderer.info); 454 | 455 | this.renderer = null; 456 | this.scene = null; 457 | this.activeCamera = null; 458 | 459 | Cache.clear(); 460 | } 461 | } 462 | -------------------------------------------------------------------------------- /Threejs/plugins/particleEngine.ts: -------------------------------------------------------------------------------- 1 | import { ParticleType, ParticleParams } from "../types/types"; 2 | import { 3 | Vector3, 4 | NormalBlending, 5 | Color, 6 | Float32BufferAttribute, 7 | Points, 8 | AdditiveBlending, 9 | BufferGeometry, 10 | ShaderMaterial, 11 | } from "three"; 12 | import { Particle } from "./particle"; 13 | import { 14 | particleFragmentShader, 15 | particleVertexShader, 16 | } from "../shader/particle"; 17 | import { Tween } from "./particleTween"; 18 | var Type = Object.freeze({ CUBE: 1, SPHERE: 2 }); 19 | export class ParticleEngine implements ParticleEngineType { 20 | private positions: number[]; 21 | private customVisibles: number[]; 22 | private customColor: number[]; 23 | private customOpacity: number[]; 24 | private customSize: number[]; 25 | private customAngle: number[]; 26 | private positionStyle: number; 27 | private positionBase: THREE.Vector3; 28 | private positionSpread: THREE.Vector3; 29 | private positionRadius: number; 30 | private velocityStyle: number; 31 | private velocityBase: THREE.Vector3; 32 | private velocitySpread: THREE.Vector3; 33 | private speedBase: number; 34 | private speedSpread: number; 35 | private accelerationBase: THREE.Vector3; 36 | private accelerationSpread: THREE.Vector3; 37 | private angleBase: number; 38 | private angleSpread: number; 39 | private angleVelocityBase: number; 40 | private angleVelocitySpread: number; 41 | private angleAccelerationBase: number; 42 | private angleAccelerationSpread: number; 43 | private sizeBase: number; 44 | private sizeSpread: number; 45 | private sizeTween: ParticleTween; 46 | private colorBase: THREE.Vector3; 47 | private colorSpread: THREE.Vector3; 48 | private colorTween: ParticleTween; 49 | private opacityBase: number; 50 | private opacitySpread: number; 51 | private opacityTween: ParticleTween; 52 | private blendStyle: any; 53 | private particleArray: ParticleType[]; 54 | private particlesPerSecond: number; 55 | private particleDeathAge: number; 56 | private emitterAge: number; 57 | private emitterAlive: boolean; 58 | private emitterDeathAge: number; 59 | private particleCount: number; 60 | private particleGeometry: THREE.BufferGeometry; 61 | private particleTexture: THREE.TextureLoader; 62 | private particleMaterial: THREE.ShaderMaterial; 63 | private particleMesh: THREE.Points; 64 | mugen: boolean; 65 | scene: THREE.Scene; 66 | start: boolean; 67 | constructor(options: ParticleParams) { 68 | this.positions = []; 69 | this.customVisibles = []; 70 | this.customColor = []; 71 | this.customOpacity = []; 72 | this.customSize = []; 73 | this.customAngle = []; 74 | this.positionStyle = Type.CUBE; 75 | this.positionBase = new Vector3(); 76 | this.positionSpread = new Vector3(); 77 | this.positionRadius = 0; 78 | this.velocityStyle = Type.CUBE; 79 | this.velocityBase = new Vector3(); 80 | this.velocitySpread = new Vector3(); 81 | this.speedBase = 0; 82 | this.speedSpread = 0; 83 | this.accelerationBase = new Vector3(); 84 | this.accelerationSpread = new Vector3(); 85 | this.angleBase = 0; 86 | this.angleSpread = 0; 87 | this.angleVelocityBase = 0; 88 | this.angleVelocitySpread = 0; 89 | this.angleAccelerationBase = 0; 90 | this.angleAccelerationSpread = 0; 91 | this.sizeBase = 0.0; 92 | this.sizeSpread = 0.0; 93 | this.sizeTween = new Tween(); 94 | this.colorBase = new Vector3(0.0, 0, 0); 95 | this.colorSpread = new Vector3(0.0, 0.0, 0.0); 96 | this.colorTween = new Tween(); 97 | this.opacityBase = 1.0; 98 | this.opacitySpread = 0.0; 99 | this.opacityTween = new Tween(); 100 | this.blendStyle = NormalBlending; // false; 101 | this.particleArray = []; 102 | this.particlesPerSecond = 100; 103 | this.particleDeathAge = 1.0; 104 | this.emitterAge = 0.0; 105 | this.emitterAlive = true; 106 | this.emitterDeathAge = 60; 107 | this.particleCount = 108 | this.particlesPerSecond * 109 | Math.min(this.particleDeathAge, this.emitterDeathAge); 110 | this.particleGeometry = null; 111 | this.particleTexture = null; 112 | this.particleMaterial = null; 113 | this.particleMesh = null; 114 | 115 | this.mugen = options.mugen || false; 116 | this.scene = options.scene; 117 | this.start = false; 118 | } 119 | /* 120 | *@description: 创建粒子 121 | *@author: yangj 122 | *@date: 2023-03-15 15:42:15 123 | *@return: 124 | */ 125 | private createParticle() { 126 | var particle = new Particle(); 127 | if (this.positionStyle == Type.CUBE) { 128 | particle.position = this.randomVector3( 129 | this.positionBase, 130 | this.positionSpread 131 | ); 132 | } 133 | if (this.positionStyle == Type.SPHERE) { 134 | var z = 2 * Math.random() - 1; 135 | var t = 6.2832 * Math.random(); 136 | var r = Math.sqrt(1 - z * z); 137 | var vec3 = new Vector3(r * Math.cos(t), r * Math.sin(t), z); 138 | particle.position = new Vector3().addVectors( 139 | this.positionBase, 140 | vec3.multiplyScalar(this.positionRadius) 141 | ); 142 | } 143 | 144 | if (this.velocityStyle == Type.CUBE) { 145 | particle.velocity = this.randomVector3( 146 | this.velocityBase, 147 | this.velocitySpread 148 | ); 149 | } 150 | if (this.velocityStyle == Type.SPHERE) { 151 | var direction = new Vector3().subVectors( 152 | particle.position, 153 | this.positionBase 154 | ); 155 | var speed = this.randomValue(this.speedBase, this.speedSpread); 156 | particle.velocity = direction.normalize().multiplyScalar(speed); 157 | } 158 | particle.acceleration = this.randomVector3( 159 | this.accelerationBase, 160 | this.accelerationSpread 161 | ); 162 | particle.angle = this.randomValue(this.angleBase, this.angleSpread); 163 | particle.angleVelocity = this.randomValue( 164 | this.angleVelocityBase, 165 | this.angleVelocitySpread 166 | ); 167 | particle.angleAcceleration = this.randomValue( 168 | this.angleAccelerationBase, 169 | this.angleAccelerationSpread 170 | ); 171 | particle.size = this.randomValue(this.sizeBase, this.sizeSpread); 172 | var color = this.randomVector3(this.colorBase, this.colorSpread); 173 | particle.color = new Color().setHSL(color.x, color.y, color.z); 174 | particle.opacity = this.randomValue(this.opacityBase, this.opacitySpread); 175 | particle.age = 0; 176 | particle.alive = 0; 177 | return particle; 178 | } 179 | 180 | initialize() { 181 | var positions = []; 182 | var customVisibles = []; 183 | var customColor = []; 184 | var customOpacity = []; 185 | var customSize = []; 186 | var customAngle = []; 187 | for (var i = 0; i < this.particleCount; i++) { 188 | this.particleArray[i] = this.createParticle(); 189 | positions.push(this.particleArray[i].position.x); 190 | positions.push(this.particleArray[i].position.y); 191 | positions.push(this.particleArray[i].position.z); 192 | customVisibles.push(this.particleArray[i].alive); 193 | customColor.push(this.particleArray[i].color.r); 194 | customColor.push(this.particleArray[i].color.g); 195 | customColor.push(this.particleArray[i].color.b); 196 | customOpacity.push(this.particleArray[i].opacity); 197 | customSize.push(this.particleArray[i].size); 198 | customAngle.push(this.particleArray[i].angle); 199 | } 200 | this.positions = positions; 201 | this.customVisibles = customVisibles; 202 | this.customColor = customColor; 203 | this.customOpacity = customOpacity; 204 | this.customSize = customSize; 205 | this.customAngle = customAngle; 206 | this.particleGeometry.setAttribute( 207 | "position", 208 | new Float32BufferAttribute(this.positions, 3) 209 | ); 210 | this.particleGeometry.setAttribute( 211 | "customVisible", 212 | new Float32BufferAttribute(this.customVisibles, 1) 213 | ); 214 | this.particleGeometry.setAttribute( 215 | "customColor", 216 | new Float32BufferAttribute(this.customColor, 3) 217 | ); 218 | this.particleGeometry.setAttribute( 219 | "customOpacity", 220 | new Float32BufferAttribute(this.customOpacity, 1) 221 | ); 222 | this.particleGeometry.setAttribute( 223 | "customSize", 224 | new Float32BufferAttribute(this.customSize, 1) 225 | ); 226 | this.particleGeometry.setAttribute( 227 | "customAngle", 228 | new Float32BufferAttribute(this.customAngle, 1) 229 | ); 230 | 231 | this.particleMaterial.blending = this.blendStyle; 232 | if (this.blendStyle !== NormalBlending) { 233 | this.particleMaterial.depthTest = false; 234 | } 235 | 236 | this.particleMesh = new Points( 237 | this.particleGeometry, 238 | this.particleMaterial 239 | ); 240 | // this.particleMesh.dynamic = true; 241 | // this.particleMesh.sortParticles = true; 242 | this.scene.add(this.particleMesh); 243 | this.start = true; 244 | } 245 | 246 | setValues(parameters, params) { 247 | if (parameters === undefined) { 248 | return; 249 | } 250 | let obj = Object.assign(parameters, params); 251 | this.sizeTween = new Tween(); 252 | this.colorTween = new Tween(); 253 | this.opacityTween = new Tween(); 254 | for (var key in obj) { 255 | this[key] = obj[key]; 256 | } 257 | Particle.prototype.sizeTween = this.sizeTween; 258 | Particle.prototype.colorTween = this.colorTween; 259 | Particle.prototype.opacityTween = this.opacityTween; 260 | this.particleArray = []; 261 | this.emitterAge = 0.0; 262 | this.emitterAlive = true; 263 | this.particleCount = 264 | this.particlesPerSecond * 265 | Math.min(this.particleDeathAge, this.emitterDeathAge); 266 | this.particleGeometry = new BufferGeometry(); 267 | this.particleMaterial = new ShaderMaterial({ 268 | uniforms: { 269 | mytexture: { value: this.particleTexture }, 270 | }, 271 | vertexShader: particleVertexShader, 272 | fragmentShader: particleFragmentShader, 273 | blending: AdditiveBlending, 274 | depthTest: false, 275 | transparent: true, 276 | vertexColors: true, 277 | }); 278 | this.particleMesh = new Points(); 279 | } 280 | private reastValues(parameters) { 281 | this.sizeTween = new Tween(); 282 | this.colorTween = new Tween(); 283 | this.opacityTween = new Tween(); 284 | for (var key in parameters) { 285 | this[key] = parameters[key]; 286 | } 287 | } 288 | private randomValue(base: number, spread: number) { 289 | return base + spread * (Math.random() - 0.5); 290 | } 291 | 292 | private randomVector3(base: THREE.Vector3, spread: THREE.Vector3) { 293 | var rand3 = new Vector3( 294 | Math.random() - 0.5, 295 | Math.random() - 0.5, 296 | Math.random() - 0.5 297 | ); 298 | return new Vector3().addVectors( 299 | base, 300 | new Vector3().multiplyVectors(spread, rand3) 301 | ); 302 | } 303 | destroy() { 304 | this.start = false; 305 | this.reastValues({ 306 | positionBase: new Vector3(), 307 | positionStyle: Type.CUBE, 308 | positionSpread: new Vector3(), 309 | positionRadius: 0, 310 | velocityStyle: Type.CUBE, 311 | velocityBase: new Vector3(), 312 | velocitySpread: new Vector3(), 313 | speedBase: 0, 314 | speedSpread: 0, 315 | accelerationBase: new Vector3(), 316 | accelerationSpread: new Vector3(), 317 | particleTexture: null, 318 | angleBase: 0, 319 | angleSpread: 0, 320 | angleVelocityBase: 0, 321 | angleVelocitySpread: 0, 322 | angleAccelerationBase: 0, 323 | angleAccelerationSpread: 0, 324 | sizeBase: 0.0, 325 | sizeSpread: 0.0, 326 | sizeTween: null, 327 | colorBase: new Vector3(0.0, 0.0, 0.0), 328 | colorSpread: new Vector3(0, 0, 0), 329 | colorTween: null, 330 | opacityBase: 0, 331 | opacitySpread: 0, 332 | opacityTween: null, 333 | blendStyle: NormalBlending, 334 | particlesPerSecond: 0, 335 | particleDeathAge: 0, 336 | emitterDeathAge: 0, 337 | }); 338 | this.scene.remove(this.particleMesh); 339 | } 340 | 341 | update(dt) { 342 | var recycleIndices = []; 343 | 344 | for (var i = 0; i < this.particleCount; i++) { 345 | if (this.particleArray[i].alive) { 346 | this.particleArray[i].update(dt); 347 | if (this.particleArray[i].age > this.particleDeathAge) { 348 | this.particleArray[i].alive = 0.0; 349 | recycleIndices.push(i); 350 | } 351 | 352 | this.customVisibles[i] = this.particleArray[i].alive; 353 | this.customColor[i * 3] = this.particleArray[i].color.r; 354 | this.customColor[i * 3 + 1] = this.particleArray[i].color.g; 355 | this.customColor[i * 3 + 2] = this.particleArray[i].color.b; 356 | this.customOpacity[i] = this.particleArray[i].opacity; 357 | this.customSize[i] = this.particleArray[i].size; 358 | this.customAngle[i] = this.particleArray[i].angle; 359 | } 360 | } 361 | 362 | this.particleGeometry.setAttribute( 363 | "customVisible", 364 | new Float32BufferAttribute(this.customVisibles, 1) 365 | ); 366 | this.particleGeometry.setAttribute( 367 | "customColor", 368 | new Float32BufferAttribute(this.customColor, 3) 369 | ); 370 | this.particleGeometry.setAttribute( 371 | "customOpacity", 372 | new Float32BufferAttribute(this.customOpacity, 1) 373 | ); 374 | this.particleGeometry.setAttribute( 375 | "customSize", 376 | new Float32BufferAttribute(this.customSize, 1) 377 | ); 378 | this.particleGeometry.setAttribute( 379 | "customAngle", 380 | new Float32BufferAttribute(this.customAngle, 1) 381 | ); 382 | 383 | this.particleGeometry.attributes.customVisible.needsUpdate = true; 384 | this.particleGeometry.attributes.customColor.needsUpdate = true; 385 | this.particleGeometry.attributes.customOpacity.needsUpdate = true; 386 | this.particleGeometry.attributes.customSize.needsUpdate = true; 387 | this.particleGeometry.attributes.customAngle.needsUpdate = true; 388 | 389 | if (!this.emitterAlive) return; 390 | 391 | if (this.emitterAge < this.particleDeathAge) { 392 | var startIndex = Math.round( 393 | this.particlesPerSecond * (this.emitterAge + 0) 394 | ); 395 | var endIndex = Math.round( 396 | this.particlesPerSecond * (this.emitterAge + dt) 397 | ); 398 | if (endIndex > this.particleCount) { 399 | endIndex = this.particleCount; 400 | } 401 | 402 | for (var i = startIndex; i < endIndex; i++) { 403 | this.particleArray[i].alive = 1.0; 404 | } 405 | } 406 | 407 | for ( 408 | var j = 0; 409 | j < recycleIndices.length; 410 | j++ // 无限循环 411 | ) { 412 | var i: number = recycleIndices[j]; 413 | this.particleArray[i] = this.createParticle(); 414 | this.particleArray[i].alive = 1.0; // activate right away 415 | this.positions[i * 3] = 416 | this.particleArray[i].position.x + 0.1 * Math.sin(0.1 * i + 0.1 * dt); 417 | this.positions[i * 3 + 1] = 418 | this.particleArray[i].position.y + 0.1 * Math.sin(0.1 * i + 0.1 * dt); 419 | this.positions[i * 3 + 2] = 420 | this.particleArray[i].position.z + 0.1 * Math.sin(0.1 * i + 0.1 * dt); 421 | } 422 | for (var j = 0; j < this.particleCount; j++) { 423 | this.positions[j * 3] = this.particleArray[j].position.x; 424 | this.positions[j * 3 + 1] = this.particleArray[j].position.y; 425 | this.positions[j * 3 + 2] = this.particleArray[j].position.z; 426 | } 427 | 428 | this.particleGeometry.setAttribute( 429 | "position", 430 | new Float32BufferAttribute(this.positions, 3) 431 | ); 432 | this.emitterAge += dt; 433 | if (!this.mugen) { 434 | if (this.emitterAge > this.emitterDeathAge) this.emitterAlive = false; 435 | } 436 | } 437 | } 438 | -------------------------------------------------------------------------------- /Threejs/plugins/sceneRoam.ts: -------------------------------------------------------------------------------- 1 | import { RoamType } from "../types/types"; 2 | import { 3 | Vector3, 4 | Box3, 5 | Matrix4, 6 | Line3, 7 | Group, 8 | Mesh, 9 | Clock, 10 | MeshStandardMaterial, 11 | } from "three"; 12 | import { RoundedBoxGeometry } from "three/examples/jsm/geometries/RoundedBoxGeometry.js"; 13 | import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils"; 14 | import { MeshBVH, MeshBVHVisualizer } from "../threelibex/three-mesh-bvh.js"; 15 | export class Roam implements RoamType { 16 | collider: THREE.Mesh; 17 | visualizer: any; 18 | player: THREE.Mesh; 19 | controls: any; 20 | camera: THREE.Camera; 21 | object: THREE.Object3D; 22 | environment: THREE.Group; 23 | scene: THREE.Scene; 24 | animate: Fn[]; 25 | playerIsOnGround: boolean; 26 | fwdPressed: boolean; 27 | bkdPressed: boolean; 28 | lftPressed: boolean; 29 | rgtPressed: boolean; 30 | playerVelocity: THREE.Vector3; 31 | upVector: THREE.Vector3; 32 | tempVector: THREE.Vector3; 33 | tempVector2: THREE.Vector3; 34 | tempBox: THREE.Box3; 35 | tempMat: THREE.Matrix4; 36 | tempSegment: THREE.Line3; 37 | clock: THREE.Clock; 38 | params: any; 39 | isRun: boolean; 40 | runCallback: Fn; 41 | angle: number; 42 | constructor(options) { 43 | this.collider = null; 44 | this.visualizer = null; 45 | this.player = null; // 参照物圆柱体 46 | this.controls = options.controls; // 控制器 47 | this.object = null; //人物模型 48 | this.environment = null; 49 | this.scene = options.scene; //场景 50 | this.camera = options.camera; //相机 51 | this.animate = options.animate; 52 | this.object = options.object; 53 | this.runCallback = options.runCallback; 54 | this.playerIsOnGround = false; 55 | this.fwdPressed = false; // W 56 | this.bkdPressed = false; // S 57 | this.lftPressed = false; // A 58 | this.rgtPressed = false; // D 59 | this.playerVelocity = new Vector3(); 60 | this.upVector = new Vector3(0, 1, 0); 61 | this.tempVector = new Vector3(); 62 | this.tempVector2 = new Vector3(); 63 | this.tempBox = new Box3(); 64 | this.tempMat = new Matrix4(); 65 | this.tempSegment = new Line3(); 66 | this.clock = new Clock(); 67 | this.isRun = false; 68 | this.angle = 0; 69 | this.params = { 70 | // gui配置对对象 71 | firstPerson: false, 72 | displayCollider: false, 73 | displayBVH: false, 74 | visualizeDepth: 10, 75 | gravity: -2, 76 | playerSpeed: 0.3, //移动速度 77 | physicsSteps: 12, 78 | playerVelocity: 5, 79 | reset: this.reset, 80 | }; 81 | } 82 | 83 | init() { 84 | this.loadColliderEnvironment(); 85 | this.windowEvent(); 86 | this.animate.push(() => { 87 | this.render(); 88 | }); 89 | } 90 | 91 | /* 92 | *@description: 生存碰撞面 93 | *@author: yangj 94 | *@date: 2023-03-22 13:46:03 95 | *@return: 96 | */ 97 | loadColliderEnvironment() { 98 | new Box3().setFromObject(this.scene); 99 | this.scene.updateMatrixWorld(true); 100 | const toMerge = {}; 101 | this.scene.traverse((c) => { 102 | if ((c as THREE.Mesh).isMesh && (c as any).material.color !== undefined) { 103 | const hex = (c as any).material.color.getHex(); 104 | toMerge[hex] = toMerge[hex] || []; 105 | toMerge[hex].push(c); 106 | } 107 | }); 108 | this.environment = new Group(); 109 | for (const hex in toMerge) { 110 | const arr = toMerge[hex]; 111 | const visualGeometries = []; 112 | arr.forEach((mesh) => { 113 | if (mesh.material.emissive) { 114 | this.environment.attach(mesh); 115 | } else { 116 | const geom = mesh.geometry.clone(); 117 | console.log(geom); 118 | geom.applyMatrix4(mesh.matrixWorld); 119 | if (!geom.attributes.uv2 && geom.index) { 120 | visualGeometries.push(geom); 121 | } 122 | } 123 | }); 124 | 125 | if (visualGeometries.length > 0) { 126 | const newGeom = 127 | BufferGeometryUtils.mergeBufferGeometries(visualGeometries); 128 | const newMesh = new Mesh( 129 | newGeom, 130 | new MeshStandardMaterial({ 131 | color: parseInt(hex), 132 | }) 133 | ); 134 | newMesh.material.transparent = true; 135 | newMesh.material.opacity = 0; 136 | newMesh.name = "mool"; 137 | this.environment.add(newMesh); 138 | } 139 | } 140 | 141 | // collect all geometries to merge 142 | const geometries = []; 143 | this.environment.updateMatrixWorld(true); 144 | this.environment.traverse((c) => { 145 | if ((c as THREE.Mesh).geometry) { 146 | const cloned = (c as THREE.Mesh).geometry.clone(); 147 | cloned.applyMatrix4(c.matrixWorld); 148 | for (const key in cloned.attributes) { 149 | if (key !== "position") { 150 | cloned.deleteAttribute(key); 151 | } 152 | } 153 | 154 | geometries.push(cloned); 155 | } 156 | }); 157 | 158 | // create the merged geometry 159 | const mergedGeometry = BufferGeometryUtils.mergeBufferGeometries( 160 | geometries, 161 | false 162 | ); 163 | (mergedGeometry as any).boundsTree = new MeshBVH(mergedGeometry, { 164 | lazyGeneration: false, 165 | }); 166 | 167 | this.collider = new Mesh(mergedGeometry); 168 | (this.collider.material as any).wireframe = true; 169 | (this.collider.material as any).opacity = 0.5; 170 | (this.collider.material as any).transparent = true; 171 | this.visualizer = new MeshBVHVisualizer( 172 | this.collider, 173 | this.params.visualizeDepth 174 | ); 175 | this.scene.add(this.visualizer); 176 | this.scene.add(this.collider); 177 | this.scene.add(this.environment); 178 | this.loadplayer(); 179 | } 180 | /* 181 | *@description: 加载移动模型 182 | *@author: yangj 183 | *@date: 2023-03-22 13:46:20 184 | *@return: 185 | */ 186 | loadplayer() { 187 | this.player = new Mesh( 188 | new RoundedBoxGeometry(0.5, 5.5, 0.5, 17, 0.5), 189 | new MeshStandardMaterial() 190 | ); 191 | this.player.geometry.translate(0, -0.5, 0); 192 | (this.player as any).capsuleInfo = { 193 | radius: 0.7, 194 | segment: new Line3(new Vector3(), new Vector3(0, -1, 0.0)), 195 | }; 196 | this.player.name = "player"; 197 | this.player.castShadow = true; 198 | this.player.receiveShadow = true; 199 | (this.player.material as any).shadowSide = 2; 200 | this.player.visible = false; 201 | console.log(this.object); 202 | 203 | this.scene.add(this.player, this.object); 204 | this.reset(); 205 | } 206 | /** 207 | * @description 208 | * @author: yangj (yangjia@fjxhx.cc) 209 | * @createDate: 2022/3/1 210 | */ 211 | windowEvent() { 212 | const that = this; 213 | // window.addEventListener( 214 | // 'resize', 215 | // function() { 216 | // that.camera.aspect = window.innerWidth / window.innerHeight 217 | // camera.updateProjectionMatrix() 218 | 219 | // renderer.setSize(window.innerWidth, window.innerHeight) 220 | // }, 221 | // false 222 | // ) 223 | 224 | document.addEventListener("keydown", function (e) { 225 | switch (e.code) { 226 | case "KeyW": 227 | that.fwdPressed = true; 228 | break; 229 | case "KeyS": 230 | that.bkdPressed = true; 231 | break; 232 | case "KeyD": 233 | that.rgtPressed = true; 234 | break; 235 | case "KeyA": 236 | that.lftPressed = true; 237 | break; 238 | case "KeyZ": 239 | if (that.playerIsOnGround) { 240 | that.playerVelocity.y = that.params.playerVelocity; 241 | } 242 | break; 243 | case "ShiftLeft": 244 | that.params.playerSpeed = 0.6; 245 | that.params.playerVelocity = 7; 246 | break; 247 | case "KeyV": 248 | that.params.firstPerson = !that.params.firstPerson; 249 | if (!that.params.firstPerson) { 250 | that.camera.position 251 | .sub(that.controls.target) 252 | .normalize() 253 | .multiplyScalar(5) 254 | .add(that.controls.target); 255 | that.camera.updateMatrixWorld(); 256 | that.object.visible = true; 257 | } else { 258 | that.camera.updateMatrixWorld(); 259 | that.object.visible = false; 260 | that.controls.reset(); 261 | } 262 | break; 263 | } 264 | if (!that.isRun) { 265 | that.isRun = true; 266 | that.runCallback instanceof Function && that.runCallback(true); 267 | } 268 | }); 269 | 270 | document.addEventListener("keyup", function (e) { 271 | switch (e.code) { 272 | case "KeyW": 273 | that.fwdPressed = false; 274 | break; 275 | case "KeyS": 276 | that.bkdPressed = false; 277 | break; 278 | case "KeyD": 279 | that.rgtPressed = false; 280 | break; 281 | case "KeyA": 282 | that.lftPressed = false; 283 | break; 284 | case "ShiftLeft": 285 | that.params.playerSpeed = 0.3; 286 | that.params.playerVelocity = 5; 287 | break; 288 | } 289 | if ( 290 | that.isRun && 291 | !that.fwdPressed && 292 | !that.bkdPressed && 293 | !that.rgtPressed && 294 | !that.lftPressed 295 | ) { 296 | that.isRun = false; 297 | that.runCallback instanceof Function && that.runCallback(false); 298 | } 299 | }); 300 | } 301 | /** 302 | * @description 重置 303 | * @author: yangj (yangjia@fjxhx.cc) 304 | * @createDate: 2022/3/1 305 | */ 306 | reset() { 307 | this.playerVelocity.set(0, 0, 0); 308 | this.player.position.set(0, 80, 50); 309 | this.camera.position.sub(this.controls.target); 310 | this.controls.target.copy(this.player.position); 311 | this.camera.position.add(this.player.position); 312 | this.controls.update(); 313 | } 314 | /* 315 | *@description: 316 | *@author: yangj 317 | *@date: 2023-03-22 13:58:01 318 | *@return: 319 | */ 320 | render() { 321 | const delta = Math.min(this.clock.getDelta(), 0.1); 322 | if ( 323 | (this.rgtPressed || 324 | this.lftPressed || 325 | this.bkdPressed || 326 | this.fwdPressed) && 327 | !this.params.firstPerson 328 | ) { 329 | } 330 | if (this.params.firstPerson) { 331 | this.controls.maxPolarAngle = Math.PI / 2; 332 | this.controls.minDistance = 1e-4; 333 | this.controls.maxDistance = 1e-3; 334 | } else { 335 | this.controls.maxPolarAngle = Math.PI / 2; 336 | this.controls.minDistance = 4; 337 | this.controls.maxDistance = 10; 338 | } 339 | 340 | if (this.collider && this.player) { 341 | this.collider.visible = this.params.displayCollider; 342 | this.visualizer.visible = this.params.displayBVH; 343 | 344 | const physicsSteps = this.params.physicsSteps; 345 | for (let i = 0; i < physicsSteps; i++) { 346 | this.updatePlayer(delta); 347 | } 348 | } 349 | } 350 | /* 351 | *@description: 更新检测碰撞 352 | *@author: yangj 353 | *@date: 2023-03-22 13:56:29 354 | *@return: 355 | */ 356 | updatePlayer(delta) { 357 | this.playerVelocity.y += this.playerIsOnGround 358 | ? 0 359 | : delta * this.params.gravity; 360 | this.player.position.addScaledVector(this.playerVelocity, delta); 361 | // move the player 362 | const angle = this.controls.getAzimuthalAngle(); 363 | if (this.fwdPressed) { 364 | this.tempVector 365 | .set(0, 0, -1) 366 | .applyAxisAngle(this.upVector, this.angle + angle); 367 | this.player.position.addScaledVector( 368 | this.tempVector, 369 | this.params.playerSpeed * delta 370 | ); 371 | } 372 | 373 | if (this.bkdPressed) { 374 | this.tempVector.set(0, 0, 1).applyAxisAngle(this.upVector, angle); 375 | this.player.position.addScaledVector( 376 | this.tempVector, 377 | this.params.playerSpeed * delta 378 | ); 379 | } 380 | 381 | if (this.lftPressed) { 382 | this.tempVector.set(-1, 0, 0).applyAxisAngle(this.upVector, angle); 383 | this.player.position.addScaledVector( 384 | this.tempVector, 385 | this.params.playerSpeed * delta 386 | ); 387 | } 388 | 389 | if (this.rgtPressed) { 390 | this.tempVector.set(1, 0, 0).applyAxisAngle(this.upVector, angle); 391 | this.player.position.addScaledVector( 392 | this.tempVector, 393 | this.params.playerSpeed * delta 394 | ); 395 | } 396 | this.player.updateMatrixWorld(); 397 | 398 | // adjust player position based on collisions 399 | const capsuleInfo = (this.player as any).capsuleInfo; 400 | this.tempBox.makeEmpty(); 401 | this.tempMat.copy(this.collider.matrixWorld).invert(); 402 | this.tempSegment.copy(capsuleInfo.segment); 403 | 404 | // get the position of the capsule in the local space of the collider 405 | this.tempSegment.start 406 | .applyMatrix4(this.player.matrixWorld) 407 | .applyMatrix4(this.tempMat); 408 | this.tempSegment.end 409 | .applyMatrix4(this.player.matrixWorld) 410 | .applyMatrix4(this.tempMat); 411 | 412 | // get the axis aligned bounding box of the capsule 413 | this.tempBox.expandByPoint(this.tempSegment.start); 414 | this.tempBox.expandByPoint(this.tempSegment.end); 415 | 416 | this.tempBox.min.addScalar(-capsuleInfo.radius); 417 | this.tempBox.max.addScalar(capsuleInfo.radius); 418 | 419 | (this.collider.geometry as any).boundsTree.shapecast({ 420 | intersectsBounds: (box) => box.intersectsBox(this.tempBox), 421 | 422 | intersectsTriangle: (tri) => { 423 | // check if the triangle is intersecting the capsule and adjust the 424 | // capsule position if it is. 425 | const triPoint = this.tempVector; 426 | const capsulePoint = this.tempVector2; 427 | 428 | const distance = tri.closestPointToSegment( 429 | this.tempSegment, 430 | triPoint, 431 | capsulePoint 432 | ); 433 | if (distance < capsuleInfo.radius) { 434 | const depth = capsuleInfo.radius - distance; 435 | const direction = capsulePoint.sub(triPoint).normalize(); 436 | 437 | this.tempSegment.start.addScaledVector(direction, depth); 438 | this.tempSegment.end.addScaledVector(direction, depth); 439 | } 440 | }, 441 | }); 442 | 443 | const newPosition = this.tempVector; 444 | newPosition 445 | .copy(this.tempSegment.start) 446 | .applyMatrix4(this.collider.matrixWorld); 447 | 448 | // check how much the collider was moved 449 | const deltaVector = this.tempVector2; 450 | deltaVector.subVectors(newPosition, this.player.position); 451 | // if the player was primarily adjusted vertically we assume it's on something we should consider ground 452 | this.playerIsOnGround = 453 | deltaVector.y > Math.abs(delta * this.playerVelocity.y * 0.25); 454 | 455 | const offset = Math.max(0.0, deltaVector.length() - 1e-5); 456 | deltaVector.normalize().multiplyScalar(offset); 457 | 458 | // adjust the player model 459 | this.player.position.add(deltaVector); 460 | if (!this.playerIsOnGround) { 461 | deltaVector.normalize(); 462 | this.playerVelocity.addScaledVector( 463 | deltaVector, 464 | -deltaVector.dot(this.playerVelocity) 465 | ); 466 | } else { 467 | this.playerVelocity.set(0, 0, 0); 468 | } 469 | 470 | // adjust the camera 471 | this.camera.position.sub(this.controls.target); 472 | this.controls.target.copy(this.player.position); 473 | this.camera.position.add(this.player.position); 474 | this.camera.updateMatrixWorld(); 475 | let position0 = this.player.position.clone(); 476 | this.controls.position0.copy( 477 | position0.addScaledVector( 478 | new Vector3(0, 0, 1).applyAxisAngle(this.upVector, angle), 479 | 0.01 480 | ) 481 | ); 482 | this.controls.target0.copy(this.player.position); 483 | this.player.rotation.y = this.controls.getAzimuthalAngle() + 3 + this.angle; 484 | if (this.object) { 485 | this.object.rotation.y = 486 | this.controls.getAzimuthalAngle() + 3 + this.angle; 487 | this.object.position.set( 488 | this.player.position.clone().x, 489 | this.player.position.clone().y, 490 | this.player.position.clone().z 491 | ); 492 | this.object.position.y -= 1.5; 493 | } 494 | // if the player has fallen too far below the level reset their position to the start 495 | if (this.player.position.y < -25) { 496 | this.reset(); 497 | } 498 | } 499 | } 500 | -------------------------------------------------------------------------------- /Threejs/shader/water.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Color, 3 | FrontSide, 4 | Matrix4, 5 | Mesh, 6 | PerspectiveCamera, 7 | Plane, 8 | ShaderMaterial, 9 | UniformsLib, 10 | UniformsUtils, 11 | Vector3, 12 | Vector4, 13 | WebGLRenderTarget, 14 | } from "three"; 15 | 16 | /** 17 | * Work based on : 18 | * https://github.com/Slayvin: Flat mirror for three.js 19 | * https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror 20 | * http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL 21 | */ 22 | 23 | class Water extends Mesh { 24 | isWater: boolean; 25 | material: THREE.ShaderMaterial; 26 | constructor(geometry, options: any = {}) { 27 | super(geometry); 28 | 29 | this.isWater = true; 30 | 31 | const scope = this; 32 | 33 | const textureWidth = 34 | options.textureWidth !== undefined ? options.textureWidth : 512; 35 | const textureHeight = 36 | options.textureHeight !== undefined ? options.textureHeight : 512; 37 | 38 | const clipBias = options.clipBias !== undefined ? options.clipBias : 0.0; 39 | const alpha = options.alpha !== undefined ? options.alpha : 1; 40 | const time = options.time !== undefined ? options.time : 0.0; 41 | const normalSampler = 42 | options.waterNormals !== undefined ? options.waterNormals : null; 43 | const sunDirection = 44 | options.sunDirection !== undefined 45 | ? options.sunDirection 46 | : new Vector3(0.70707, 0.70707, 0.0); 47 | const sunColor = new Color( 48 | options.sunColor !== undefined ? options.sunColor : 0xffffff 49 | ); 50 | const waterColor = new Color( 51 | options.waterColor !== undefined ? options.waterColor : 0x7f7f7f 52 | ); 53 | const eye = options.eye !== undefined ? options.eye : new Vector3(0, 0, 0); 54 | const distortionScale = 55 | options.distortionScale !== undefined ? options.distortionScale : 20.0; 56 | const side = options.side !== undefined ? options.side : FrontSide; 57 | const fog = options.fog !== undefined ? options.fog : false; 58 | 59 | // 60 | 61 | const mirrorPlane = new Plane(); 62 | const normal = new Vector3(); 63 | const mirrorWorldPosition = new Vector3(); 64 | const cameraWorldPosition = new Vector3(); 65 | const rotationMatrix = new Matrix4(); 66 | const lookAtPosition = new Vector3(0, 0, -1); 67 | const clipPlane = new Vector4(); 68 | 69 | const view = new Vector3(); 70 | const target = new Vector3(); 71 | const q = new Vector4(); 72 | 73 | const textureMatrix = new Matrix4(); 74 | 75 | const mirrorCamera = new PerspectiveCamera(); 76 | 77 | const renderTarget = new WebGLRenderTarget(textureWidth, textureHeight); 78 | 79 | const mirrorShader = { 80 | uniforms: UniformsUtils.merge([ 81 | UniformsLib["fog"], 82 | UniformsLib["lights"], 83 | { 84 | normalSampler: { value: null }, 85 | mirrorSampler: { value: null }, 86 | alpha: { value: 1.0 }, 87 | time: { value: 0.0 }, 88 | size: { value: 2.0 }, 89 | distortionScale: { value: 20.0 }, 90 | textureMatrix: { value: new Matrix4() }, 91 | sunColor: { value: new Color(0xffffff) }, 92 | sunDirection: { value: new Vector3(0.70707, 0.70707, 0) }, 93 | eye: { value: new Vector3() }, 94 | waterColor: { value: new Color(0x555555) }, 95 | }, 96 | ]), 97 | 98 | vertexShader: /* glsl */ ` 99 | uniform mat4 textureMatrix; 100 | uniform float time; 101 | 102 | varying vec4 mirrorCoord; 103 | varying vec4 worldPosition; 104 | 105 | #include 106 | #include 107 | #include 108 | #include 109 | 110 | void main() { 111 | mirrorCoord = modelMatrix * vec4( position, 1.0 ); 112 | worldPosition = mirrorCoord.xyzw; 113 | mirrorCoord = textureMatrix * mirrorCoord; 114 | vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); 115 | gl_Position = projectionMatrix * mvPosition; 116 | 117 | #include 118 | #include 119 | #include 120 | #include 121 | #include 122 | }`, 123 | 124 | fragmentShader: /* glsl */ ` 125 | uniform sampler2D mirrorSampler; 126 | uniform float alpha; 127 | uniform float time; 128 | uniform float size; 129 | uniform float distortionScale; 130 | uniform sampler2D normalSampler; 131 | uniform vec3 sunColor; 132 | uniform vec3 sunDirection; 133 | uniform vec3 eye; 134 | uniform vec3 waterColor; 135 | 136 | varying vec4 mirrorCoord; 137 | varying vec4 worldPosition; 138 | 139 | vec4 getNoise( vec2 uv ) { 140 | vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0); 141 | vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 ); 142 | vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 ); 143 | vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 ); 144 | vec4 noise = texture2D( normalSampler, uv0 ) + 145 | texture2D( normalSampler, uv1 ) + 146 | texture2D( normalSampler, uv2 ) + 147 | texture2D( normalSampler, uv3 ); 148 | return noise * 0.5 - 1.0; 149 | } 150 | 151 | void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor ) { 152 | vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) ); 153 | float direction = max( 0.0, dot( eyeDirection, reflection ) ); 154 | specularColor += pow( direction, shiny ) * sunColor * spec; 155 | diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse; 156 | } 157 | 158 | #include 159 | #include 160 | #include 161 | #include 162 | #include 163 | #include 164 | #include 165 | #include 166 | 167 | void main() { 168 | 169 | #include 170 | vec4 noise = getNoise( worldPosition.xz * size ); 171 | vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) ); 172 | 173 | vec3 diffuseLight = vec3(0.0); 174 | vec3 specularLight = vec3(0.0); 175 | 176 | vec3 worldToEye = eye-worldPosition.xyz; 177 | vec3 eyeDirection = normalize( worldToEye ); 178 | sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight ); 179 | 180 | float distance = length(worldToEye); 181 | 182 | vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale; 183 | vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.w + distortion ) ); 184 | 185 | float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 ); 186 | float rf0 = 0.3; 187 | float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 ); 188 | vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor; 189 | vec3 albedo = mix( ( sunColor * diffuseLight * 0.3 + scatter ) * getShadowMask(), ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance); 190 | vec3 outgoingLight = albedo; 191 | gl_FragColor = vec4( outgoingLight, alpha ); 192 | 193 | #include 194 | #include 195 | }`, 196 | }; 197 | 198 | const material = new ShaderMaterial({ 199 | fragmentShader: mirrorShader.fragmentShader, 200 | vertexShader: mirrorShader.vertexShader, 201 | uniforms: UniformsUtils.clone(mirrorShader.uniforms), 202 | lights: true, 203 | side: side, 204 | fog: fog, 205 | }); 206 | 207 | material.uniforms["mirrorSampler"].value = renderTarget.texture; 208 | material.uniforms["textureMatrix"].value = textureMatrix; 209 | material.uniforms["alpha"].value = alpha; 210 | material.uniforms["time"].value = time; 211 | material.uniforms["normalSampler"].value = normalSampler; 212 | material.uniforms["sunColor"].value = sunColor; 213 | material.uniforms["waterColor"].value = waterColor; 214 | material.uniforms["sunDirection"].value = sunDirection; 215 | material.uniforms["distortionScale"].value = distortionScale; 216 | 217 | material.uniforms["eye"].value = eye; 218 | this.material = material; 219 | scope.material = material; 220 | 221 | scope.onBeforeRender = function (renderer, scene, camera) { 222 | mirrorWorldPosition.setFromMatrixPosition(scope.matrixWorld); 223 | cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld); 224 | 225 | rotationMatrix.extractRotation(scope.matrixWorld); 226 | 227 | normal.set(0, 0, 1); 228 | normal.applyMatrix4(rotationMatrix); 229 | 230 | view.subVectors(mirrorWorldPosition, cameraWorldPosition); 231 | 232 | // Avoid rendering when mirror is facing away 233 | 234 | if (view.dot(normal) > 0) return; 235 | 236 | view.reflect(normal).negate(); 237 | view.add(mirrorWorldPosition); 238 | 239 | rotationMatrix.extractRotation(camera.matrixWorld); 240 | 241 | lookAtPosition.set(0, 0, -1); 242 | lookAtPosition.applyMatrix4(rotationMatrix); 243 | lookAtPosition.add(cameraWorldPosition); 244 | 245 | target.subVectors(mirrorWorldPosition, lookAtPosition); 246 | target.reflect(normal).negate(); 247 | target.add(mirrorWorldPosition); 248 | 249 | mirrorCamera.position.copy(view); 250 | mirrorCamera.up.set(0, 1, 0); 251 | mirrorCamera.up.applyMatrix4(rotationMatrix); 252 | mirrorCamera.up.reflect(normal); 253 | mirrorCamera.lookAt(target); 254 | 255 | mirrorCamera.far = (camera as any).far; // Used in WebGLBackground 256 | 257 | mirrorCamera.updateMatrixWorld(); 258 | mirrorCamera.projectionMatrix.copy(camera.projectionMatrix); 259 | 260 | // Update the texture matrix 261 | textureMatrix.set( 262 | 0.5, 263 | 0.0, 264 | 0.0, 265 | 0.5, 266 | 0.0, 267 | 0.5, 268 | 0.0, 269 | 0.5, 270 | 0.0, 271 | 0.0, 272 | 0.5, 273 | 0.5, 274 | 0.0, 275 | 0.0, 276 | 0.0, 277 | 1.0 278 | ); 279 | textureMatrix.multiply(mirrorCamera.projectionMatrix); 280 | textureMatrix.multiply(mirrorCamera.matrixWorldInverse); 281 | 282 | // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html 283 | // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf 284 | mirrorPlane.setFromNormalAndCoplanarPoint(normal, mirrorWorldPosition); 285 | mirrorPlane.applyMatrix4(mirrorCamera.matrixWorldInverse); 286 | 287 | clipPlane.set( 288 | mirrorPlane.normal.x, 289 | mirrorPlane.normal.y, 290 | mirrorPlane.normal.z, 291 | mirrorPlane.constant 292 | ); 293 | 294 | const projectionMatrix = mirrorCamera.projectionMatrix; 295 | 296 | q.x = 297 | (Math.sign(clipPlane.x) + projectionMatrix.elements[8]) / 298 | projectionMatrix.elements[0]; 299 | q.y = 300 | (Math.sign(clipPlane.y) + projectionMatrix.elements[9]) / 301 | projectionMatrix.elements[5]; 302 | q.z = -1.0; 303 | q.w = 304 | (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14]; 305 | 306 | // Calculate the scaled plane vector 307 | clipPlane.multiplyScalar(2.0 / clipPlane.dot(q)); 308 | 309 | // Replacing the third row of the projection matrix 310 | projectionMatrix.elements[2] = clipPlane.x; 311 | projectionMatrix.elements[6] = clipPlane.y; 312 | projectionMatrix.elements[10] = clipPlane.z + 1.0 - clipBias; 313 | projectionMatrix.elements[14] = clipPlane.w; 314 | 315 | eye.setFromMatrixPosition(camera.matrixWorld); 316 | 317 | // Render 318 | 319 | const currentRenderTarget = renderer.getRenderTarget(); 320 | 321 | const currentXrEnabled = renderer.xr.enabled; 322 | const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate; 323 | 324 | scope.visible = false; 325 | 326 | renderer.xr.enabled = false; // Avoid camera modification and recursion 327 | renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows 328 | 329 | renderer.setRenderTarget(renderTarget); 330 | 331 | renderer.state.buffers.depth.setMask(true); // make sure the depth buffer is writable so it can be properly cleared, see #18897 332 | 333 | if (renderer.autoClear === false) renderer.clear(); 334 | renderer.render(scene, mirrorCamera); 335 | 336 | scope.visible = true; 337 | 338 | renderer.xr.enabled = currentXrEnabled; 339 | renderer.shadowMap.autoUpdate = currentShadowAutoUpdate; 340 | 341 | renderer.setRenderTarget(currentRenderTarget); 342 | 343 | // Restore viewport 344 | 345 | const viewport = (camera as any).viewport; 346 | 347 | if (viewport !== undefined) { 348 | renderer.state.viewport(viewport); 349 | } 350 | }; 351 | } 352 | } 353 | 354 | const City = { 355 | uniforms: { 356 | iTime: { 357 | value: 0, 358 | }, 359 | iResolution: { 360 | value: new Vector3(1, 1, 1), 361 | }, 362 | }, 363 | 364 | vertexShader: ` 365 | varying vec2 vUv; 366 | void main() { 367 | vUv = uv; 368 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); 369 | } 370 | 371 | `, 372 | 373 | fragmentShader: ` 374 | varying vec2 vUv; 375 | uniform vec3 iResolution; // viewport iResolution (in pixels) 376 | uniform float iTime; 377 | float det=.001, br=0., tub=0., hit=0.; 378 | vec3 pos, sphpos; 379 | mat3 lookat(vec3 dir, vec3 up) { 380 | vec3 rt=normalize(cross(dir,up)); 381 | return mat3(rt,cross(rt,dir),dir); 382 | } 383 | vec3 path(float t) { 384 | return vec3(sin(t+cos(t)*.5)*.5,cos(t*.5),t); 385 | } 386 | mat2 rot(float a) { 387 | float s=sin(a); 388 | float c=cos(a); 389 | return mat2(c,s,-s,c); 390 | } 391 | vec3 fractal(vec2 p) { 392 | p=fract(p*.1); 393 | float m=1000.; 394 | for (int i=0; i<7; i++) { 395 | p=abs(p)/clamp(abs(p.x*p.y),.25,2.)-1.2; 396 | m=min(m,abs(p.y)+fract(p.x*.3+iTime*.5+float(i)*.25)); 397 | } 398 | m=exp(-6.*m); 399 | return m*vec3(abs(p.x),m,abs(p.y)); 400 | } 401 | 402 | float coso(vec3 pp) { 403 | pp*=.7; 404 | pp.xy*=rot(pp.z*2.); 405 | pp.xz*=rot(iTime*2.); 406 | pp.yz*=rot(iTime); 407 | float sph=length(pp)-.04; 408 | sph-=length(sin(pp*40.))*.05; 409 | sph=max(sph,-length(pp)+.11); 410 | float br2=length(pp)-.03; 411 | br2=min(br2,length(pp.xy)+.005); 412 | br2=min(br2,length(pp.xz)+.005); 413 | br2=min(br2,length(pp.yz)+.005); 414 | br2=max(br2,length(pp)-1.); 415 | br=min(br2,br); 416 | float d=min(br,sph); 417 | return d; 418 | } 419 | 420 | 421 | float de(vec3 p) { 422 | hit=0.; 423 | br=1000.; 424 | vec3 pp=p-sphpos; 425 | p.xy-=path(p.z).xy; 426 | p.xy*=rot(p.z+iTime*.5); 427 | float s=sin(p.z*.5+iTime*.5); 428 | p.xy*=1.3-s*s*.7; 429 | 430 | for(int i=0; i<6; i++) { 431 | p=abs(p)-.4; 432 | } 433 | pos=p; 434 | tub=-length(p.xy)+.45+sin(p.z*10.)*.1*smoothstep(.4,.5,abs(.5-fract(p.z*.05))*2.); 435 | float co=coso(pp); 436 | co=min(co,coso(pp+.7)); 437 | co=min(co,coso(pp-.7)); 438 | float d=min(tub,co); 439 | if (d==tub) hit=step(fract(.1*length(sin(p*10.))),.05); 440 | return d*.3; 441 | } 442 | 443 | vec3 march(vec3 from, vec3 dir) { 444 | vec2 uv=vec2(atan(dir.x,dir.y)+iTime*.5,length(dir.xy)+sin(iTime*.2)); 445 | vec3 col=fractal(uv); 446 | float d=0.,td=0.,g=0., ref=0., ltd=0., li=0.; 447 | vec3 p=from; 448 | for (int i=0; i<200; i++) { 449 | p+=dir*d; 450 | d=de(p); 451 | if (d5.) break; 462 | td+=d; 463 | g+=.1/(.1+br*13.); 464 | li+=.1/(.1+tub*5.); 465 | } 466 | g=max(g,li*.15); 467 | float f=1.-td/3.; 468 | if (ref==1.) f=1.-ltd/3.; 469 | if (d<.01) { 470 | col=vec3(1.); 471 | vec2 e=vec2(0.,det); 472 | vec3 n=normalize(vec3(de(p+e.yxx),de(p+e.xyx),de(p+e.xxy))-de(p)); 473 | col=vec3(n.x)*.7; 474 | col+=fract(pos.z*5.)*vec3(.2,.1,.5); 475 | col+=fractal(pos.xz*2.); 476 | if (tub>.01) col=vec3(0.); 477 | } 478 | col*=f; 479 | vec3 glo=g*.1*vec3(2.,1.,2.)*(.5+fract(sin(iTime)*123.456)*1.5)*.5; 480 | glo.rb*=rot(dir.y*1.5); 481 | col+=glo; 482 | col*=vec3(.8,.7,.7); 483 | col=mix(col,vec3(1.),ref*.3); 484 | return col; 485 | } 486 | 487 | void main( ) 488 | { 489 | vec2 uv = vec2(vUv.x / iResolution.x, vUv.y / iResolution.y); 490 | uv -= 0.5; 491 | uv /= vec2(iResolution.y / iResolution.x, 1); 492 | float t=iTime; 493 | vec3 from= path(t); 494 | if (mod(iTime,10.)>5.) from=path(floor(t/4.+.5)*4.); 495 | sphpos=path(t+.5); 496 | from.x+=.2; 497 | vec3 fw=normalize(path(t+.5)-from); 498 | vec3 dir=normalize(vec3(uv,.5)); 499 | dir=lookat(fw,vec3(fw.x*2.,1.,0.))*dir; 500 | dir.xz+=sin(iTime)*.3; 501 | vec3 col=march(from,dir); 502 | col=mix(vec3(.5)*length(col),col,.8); 503 | gl_FragColor =vec4(col,1.); 504 | } 505 | `, 506 | }; 507 | 508 | export { Water, City }; 509 | --------------------------------------------------------------------------------