From 43f2f2ad620bfef3cfd88e3469ab758dcf5ecc1c Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Fri, 8 Sep 2023 18:05:03 +0800 Subject: [PATCH 01/14] chore(effect): build & publish npm package --- packages/effect/README.md | 15 +++++++++++++++ packages/effect/package.json | 4 ++-- packages/effect/vite.config.js | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 packages/effect/README.md create mode 100644 packages/effect/vite.config.js diff --git a/packages/effect/README.md b/packages/effect/README.md new file mode 100644 index 00000000..2dadee67 --- /dev/null +++ b/packages/effect/README.md @@ -0,0 +1,15 @@ +Add effect components for [Orillusion](https://www.orillusion.com) + +## Install +```bash +npm install @orillusion/core --save +npm install @orillusion/effect --save +``` + +Or access Global build from CDN +```html + + +``` + +More doc from [Orillusion](https://www.orillusion.com/guide/effect/Readme.html) \ No newline at end of file diff --git a/packages/effect/package.json b/packages/effect/package.json index 2c6a073d..0df0c639 100644 --- a/packages/effect/package.json +++ b/packages/effect/package.json @@ -2,7 +2,7 @@ "name": "@orillusion/effect", "version": "0.1.0", "author": "Orillusion", - "description": "Orillusion effect Effects", + "description": "Orillusion Effects Plugin", "main": "./dist/effect.umd.js", "module": "./dist/effect.es.js", "module:dev": "./index.ts", @@ -19,6 +19,6 @@ "url": "git+https://github.com/Orillusion/orillusion.git" }, "dependencies": { - "@orillusion/core": "^0.6.3" + "@orillusion/core": "^0.6.9" } } diff --git a/packages/effect/vite.config.js b/packages/effect/vite.config.js new file mode 100644 index 00000000..82373366 --- /dev/null +++ b/packages/effect/vite.config.js @@ -0,0 +1,25 @@ +import { defineConfig } from 'vite' +const path = require('path') +export default defineConfig({ + resolve: { + alias: { + '@orillusion/core': path.resolve(__dirname, '../../src'), + '@orillusion': path.resolve(__dirname, '../') + } + }, + build: { + lib: { + entry: path.resolve('index.ts'), + name: 'Effect', + fileName: (format) => `effect.${format}.js` + }, + rollupOptions: { + external: ['@orillusion/core'], + output: { + globals: { + '@orillusion/core': 'Orillusion' + } + } + } + } +}) \ No newline at end of file From 21a8e70aa390975514ae205206b589d1446abc47 Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Sat, 9 Sep 2023 03:50:00 +0800 Subject: [PATCH 02/14] chore(changelog): update breaking changes --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2622f57a..29ee75e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,11 @@ * add transform depth order ([bf40831](https://github.com/Orillusion/orillusion/commit/bf40831cb9637f7d7b18e4c4cf650ddb5c0b2e13)) * fadeout csm shadow far away ([bf30fe7](https://github.com/Orillusion/orillusion/commit/bf30fe71f6ccba71ebb3e3406f4f248d28e7615d)) +### BREAKING CHANGES +* **material:** `MaterialBase` has beed renamed to `Material`, also need to implement `get/set` for `baseMap` for custom materials +* **shadow:** drop `shadowBias`, `shadowNear`, `shadowFar` options in shadow settings, values will be calculated automatically +* **Bloom:** add new `exposure` option in Bloom settings + ## [0.6.8](https://github.com/Orillusion/orillusion/compare/v0.6.7...v0.6.8) (2023-08-10) ### Bug Fixes From e59bd9f4d43e98941ef634aff5c4e525a02cc6f1 Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Fri, 15 Sep 2023 15:29:10 +0800 Subject: [PATCH 03/14] fix(particle): add get baseMap --- packages/particle/material/ParticleMaterial.ts | 4 ++++ packages/particle/package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/particle/material/ParticleMaterial.ts b/packages/particle/material/ParticleMaterial.ts index 7b5ffd23..4931f844 100644 --- a/packages/particle/material/ParticleMaterial.ts +++ b/packages/particle/material/ParticleMaterial.ts @@ -42,6 +42,10 @@ export class ParticleMaterial extends Material { this.defaultPass.setTexture(`baseMap`, texture); } + public get baseMap() { + return this.defaultPass.getTexture(`baseMap`); + } + public set envMap(texture: Texture) { //not need env texture } diff --git a/packages/particle/package.json b/packages/particle/package.json index 2338f3c7..fa8da685 100644 --- a/packages/particle/package.json +++ b/packages/particle/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/particle", - "version": "0.0.2", + "version": "0.0.3", "author": "Orillusion", "description": "Orillusion Particle Plugin", "main": "./dist/particle.umd.js", From 166d2866b3e427339082f6bbdc7d391d4b91e784 Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Fri, 15 Sep 2023 21:46:29 +0800 Subject: [PATCH 04/14] feat(audio): move audio to @orillusion/media-extension add audio samples --- .../media-extention}/AudioListener.ts | 6 +- .../media-extention}/PositionAudio.ts | 21 +-- .../media-extention}/StaticAudio.ts | 7 +- packages/media-extention/index.ts | 5 +- packages/media-extention/package.json | 2 +- samples/audio/Sample_DynamicAudio.ts | 139 ++++++++++++++++++ samples/audio/Sample_StaticAudio.ts | 105 +++++++++++++ src/index.ts | 3 - 8 files changed, 260 insertions(+), 28 deletions(-) rename {src/components/audio => packages/media-extention}/AudioListener.ts (95%) rename {src/components/audio => packages/media-extention}/PositionAudio.ts (91%) rename {src/components/audio => packages/media-extention}/StaticAudio.ts (95%) create mode 100644 samples/audio/Sample_DynamicAudio.ts create mode 100644 samples/audio/Sample_StaticAudio.ts diff --git a/src/components/audio/AudioListener.ts b/packages/media-extention/AudioListener.ts similarity index 95% rename from src/components/audio/AudioListener.ts rename to packages/media-extention/AudioListener.ts index 0148945b..bc02ffd9 100644 --- a/src/components/audio/AudioListener.ts +++ b/packages/media-extention/AudioListener.ts @@ -1,4 +1,4 @@ -import { ComponentBase } from '../ComponentBase'; +import { ComponentBase } from '@orillusion/core'; /** * Audio Listener @@ -14,9 +14,6 @@ export class AudioListener extends ComponentBase { this.context = new AudioContext(); this.gain = this.context.createGain(); this.gain.connect(this.context.destination); - } - public start() { - } public onUpdate() { if (!this.context) { @@ -45,7 +42,6 @@ export class AudioListener extends ComponentBase { listener.setOrientation(_orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z); } } - destroy() { this.gain.disconnect(); this.context.close(); diff --git a/src/components/audio/PositionAudio.ts b/packages/media-extention/PositionAudio.ts similarity index 91% rename from src/components/audio/PositionAudio.ts rename to packages/media-extention/PositionAudio.ts index 6b48cbc2..f42f3942 100644 --- a/src/components/audio/PositionAudio.ts +++ b/packages/media-extention/PositionAudio.ts @@ -1,9 +1,4 @@ -import { Object3D } from '../../core/entities/Object3D'; -import { UnLitMaterial } from '../../materials/UnLitMaterial'; -import { Color } from '../../math/Color'; -import { Vector3 } from '../../math/Vector3'; -import { BoxGeometry } from '../../shape/BoxGeometry'; -import { MeshRenderer } from '../renderer/MeshRenderer'; +import { BoxGeometry, Color, MeshRenderer, Object3D, UnLitMaterial, Vector3 } from '@orillusion/core'; import { AudioListener } from './AudioListener'; import { StaticAudio } from './StaticAudio'; /** @@ -20,8 +15,8 @@ export class PositionAudio extends StaticAudio { constructor() { super(); } - public setLister(listener: AudioListener): this { - super.setLister(listener); + public setLisenter(listener: AudioListener): this { + super.setLisenter(listener); this.panner = this.context?.createPanner() as PannerNode; this.panner.panningModel = 'HRTF'; this.panner.connect(this.gainNode as GainNode); @@ -41,7 +36,6 @@ export class PositionAudio extends StaticAudio { let refLength = this.panner.refDistance; let maxLength = this.panner.maxDistance; let box = new BoxGeometry(1, 1, 1); - let m1 = new UnLitMaterial(); m1.baseColor = new Color(1, 0, 0); let m2 = new UnLitMaterial(); @@ -50,6 +44,7 @@ export class PositionAudio extends StaticAudio { m3.baseColor = new Color(0, 1, 0); let m4 = new UnLitMaterial(); m4.baseColor = new Color(1, 1, 0); + for (let i = 0; i < this._step; i++) { let group = new Object3D(); let angle = (i * outerAngle) / (this._step - 1); @@ -83,10 +78,10 @@ export class PositionAudio extends StaticAudio { } public hideHelper() { this._helper = false; - for (let l of this._lines) { - l.removeAllChild(); - l.removeFromParent(); - l.destroy(); + for(let g of this._lines){ + while(g.entityChildren.length > 0) + g.entityChildren[0].destroy() + g.destroy() } this._lines.length = 0; } diff --git a/src/components/audio/StaticAudio.ts b/packages/media-extention/StaticAudio.ts similarity index 95% rename from src/components/audio/StaticAudio.ts rename to packages/media-extention/StaticAudio.ts index 1b5f5010..a5eb2efa 100644 --- a/src/components/audio/StaticAudio.ts +++ b/packages/media-extention/StaticAudio.ts @@ -1,4 +1,4 @@ -import { ComponentBase } from '../ComponentBase'; +import { ComponentBase } from '@orillusion/core'; import { AudioListener } from './AudioListener'; /** * Static audio component, volume level does not vary depending on the position of the monitor @@ -20,7 +20,7 @@ export class StaticAudio extends ComponentBase { constructor() { super(); } - public setLister(listener: AudioListener): this { + public setLisenter(listener: AudioListener): this { this.listener = listener; this.context = listener.context as AudioContext; this.gainNode = this.context.createGain(); @@ -103,9 +103,6 @@ export class StaticAudio extends ComponentBase { protected connect() { this.source?.connect(this.gainNode as GainNode); } - public onUpdate() { - super.onUpdate(); - } public destroy(force?: boolean) { this.stop(); this.gainNode?.disconnect(); diff --git a/packages/media-extention/index.ts b/packages/media-extention/index.ts index f031cc34..89f8d3da 100644 --- a/packages/media-extention/index.ts +++ b/packages/media-extention/index.ts @@ -2,5 +2,8 @@ import { ChromaKeyMaterial } from './ChromaKeyMaterial' import { ImageMaterial } from './ImageMaterial' import { VideoMaterial } from './VideoMaterial' import { VideoTexture } from './VideoTexture' +import { AudioListener } from './AudioListener' +import { PositionAudio } from './PositionAudio' +import { StaticAudio } from './StaticAudio' -export {ChromaKeyMaterial, ImageMaterial, VideoMaterial, VideoTexture} \ No newline at end of file +export {ChromaKeyMaterial, ImageMaterial, VideoMaterial, VideoTexture, AudioListener, StaticAudio, PositionAudio} \ No newline at end of file diff --git a/packages/media-extention/package.json b/packages/media-extention/package.json index 3b242137..13e92ff0 100644 --- a/packages/media-extention/package.json +++ b/packages/media-extention/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/media-extention", - "version": "0.2.3", + "version": "0.3.1", "author": "Orillusion", "description": "Orillusion Media Material Extention", "main": "./dist/media.umd.js", diff --git a/samples/audio/Sample_DynamicAudio.ts b/samples/audio/Sample_DynamicAudio.ts new file mode 100644 index 00000000..73efc9ae --- /dev/null +++ b/samples/audio/Sample_DynamicAudio.ts @@ -0,0 +1,139 @@ +import { BoxGeometry, Camera3D, DirectLight, Engine3D, LitMaterial, KelvinUtil, MeshRenderer, Object3D, Scene3D, Vector3, Color, OrbitController, View3D, AtmosphericComponent } from '@orillusion/core'; +import { PositionAudio, AudioListener } from '@orillusion/media-extention' +import { GUIHelp } from '@orillusion/debug/GUIHelp'; + +export class Static_Audio { + lightObj: Object3D; + scene: Scene3D; + camera: Object3D + mats: any[]; + audio: PositionAudio + private a = 40 + private b = 80 + private angle = 0 + constructor() {} + + async run() { + Engine3D.setting.shadow.autoUpdate = true; + Engine3D.setting.shadow.updateFrameRate = 1; + Engine3D.setting.shadow.type = 'HARD'; + Engine3D.setting.shadow.shadowBound = 100; + + await Engine3D.init({ + renderLoop: this.loop.bind(this) + }); + this.scene = new Scene3D(); + this.scene.addComponent(AtmosphericComponent); + + this.camera = new Object3D() + this.camera.localPosition = new Vector3(0, 20, 50) + let mainCamera = this.camera.addComponent(Camera3D) + this.scene.addChild(this.camera) + + mainCamera.perspective(60, Engine3D.aspect, 0.1, 20000.0); + let orbit = this.camera.addComponent(OrbitController) + orbit.target = new Vector3(0, 4, 0) + orbit.minDistance = 10 + orbit.maxDistance = 200 + + let view = new View3D(); + view.scene = this.scene; + view.camera = mainCamera; + + Engine3D.startRenderView(view); + await this.initScene(); + } + + async initScene() { + { + let [speaker, man, music] = await Promise.all([ + Engine3D.res.loadGltf('gltfs/speaker/scene.gltf'), + Engine3D.res.loadGltf('gltfs/glb/CesiumMan.glb'), + fetch('https://cdn.orillusion.com/audio.ogg').then(res=>res.arrayBuffer()) + ]) + speaker.localScale.set(4,4,4) + speaker.rotationX = -120 + speaker.y = 0.5 + let group = new Object3D() + group.addChild(speaker) + group.y = 2 + this.scene.addChild(group) + + man.name = 'man' + man.scaleX = 10; + man.scaleY = 10; + man.scaleZ = 10; + man.rotationX = -90; + man.rotationY = -90 + man.localPosition.set(0, 0.5, 30) + this.scene.addChild(man) + + let listener = man.addComponent(AudioListener) + let audio = group.addComponent(PositionAudio) + audio.setLisenter(listener) + await audio.loadBuffer(music) + audio.refDistance = 10; + audio.maxDistance = 100; + audio.setDirectionalCone( 180, 230, 0.1 ); + audio.showHelper() + + GUIHelp.init(); + GUIHelp.addButton('play', ()=>{ + audio.play() + }) + GUIHelp.addButton('pause', ()=>{ + audio.pause() + }) + GUIHelp.addButton('stop', ()=>{ + audio.stop() + }) + GUIHelp.add({volume:1}, 'volume', 0, 1, 0.01).onChange( (v:number) =>{ + audio.setVolume(v) + }) + GUIHelp.addButton('Toggle Helper', ()=>{ + audio.toggleHelper() + }) + GUIHelp.open() + } + { + let wall = new Object3D() + let mr = wall.addComponent(MeshRenderer) + mr.geometry = new BoxGeometry(40, 30, 1) + let mat = new LitMaterial() + mat.baseColor = new Color(1,0,0) + mr.material = mat + this.scene.addChild(wall) + wall.z = -5 + } + { + let floor = new Object3D(); + let mr = floor.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(3000, 1, 3000); + let mat = new LitMaterial(); + mr.material = mat; + this.scene.addChild(floor); + } + + /******** light *******/ + { + this.lightObj = new Object3D(); + this.lightObj.rotationX = 35; + this.lightObj.rotationY = 110; + this.lightObj.rotationZ = 0; + let directLight = this.lightObj.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = true; + directLight.intensity = 30; + this.scene.addChild(this.lightObj); + } + } + loop(){ + let man = this.scene.getChildByName('man') as Object3D + if(man){ + this.angle += 0.005 + man.x = this.a * Math.cos(this.angle) + man.z = this.b * Math.sin(this.angle) + 30 + man.rotationY -= 0.005 * 180 / Math.PI + } + } +} \ No newline at end of file diff --git a/samples/audio/Sample_StaticAudio.ts b/samples/audio/Sample_StaticAudio.ts new file mode 100644 index 00000000..9797c66d --- /dev/null +++ b/samples/audio/Sample_StaticAudio.ts @@ -0,0 +1,105 @@ +import { BoxGeometry, Camera3D, DirectLight, Engine3D, LitMaterial, KelvinUtil, MeshRenderer, Object3D, Scene3D, Vector3, Color, OrbitController, View3D, AtmosphericComponent } from '@orillusion/core'; +import { StaticAudio, AudioListener } from '@orillusion/media-extention' +import { GUIHelp } from '@orillusion/debug/GUIHelp'; + +export class Static_Audio { + lightObj: Object3D; + scene: Scene3D; + camera: Object3D + mats: any[]; + audio: StaticAudio + constructor() {} + + async run() { + Engine3D.setting.shadow.autoUpdate = true; + Engine3D.setting.shadow.updateFrameRate = 1; + Engine3D.setting.shadow.type = 'HARD'; + Engine3D.setting.shadow.shadowBound = 100; + + await Engine3D.init(); + this.scene = new Scene3D(); + this.scene.addComponent(AtmosphericComponent); + + this.camera = new Object3D() + this.camera.localPosition = new Vector3(0, 20, 50) + let mainCamera = this.camera.addComponent(Camera3D) + this.scene.addChild(this.camera) + + mainCamera.perspective(60, Engine3D.aspect, 0.1, 20000.0); + let orbit = this.camera.addComponent(OrbitController) + orbit.target = new Vector3(0, 4, 0) + orbit.minDistance = 10 + orbit.maxDistance = 200 + + let view = new View3D(); + view.scene = this.scene; + view.camera = mainCamera; + + Engine3D.startRenderView(view); + await this.initScene(); + } + + async initScene() { + { + let group = new Object3D() + let speaker = await Engine3D.res.loadGltf('gltfs/speaker/scene.gltf') + speaker.localScale.set(4,4,4) + speaker.rotationX = -120 + //speaker.y = 1.5 + group.addChild(speaker) + group.y = 2 + this.scene.addChild(group) + + let listener = this.camera.addComponent(AudioListener) + let audio = group.addComponent(StaticAudio) + audio.setLisenter(listener) + + await audio.load('https://cdn.orillusion.com/audio.ogg') + GUIHelp.init(); + GUIHelp.addButton('play', ()=>{ + audio.play() + }) + GUIHelp.addButton('pause', ()=>{ + audio.pause() + }) + GUIHelp.addButton('stop', ()=>{ + audio.stop() + }) + GUIHelp.add({volume:1}, 'volume', 0, 1, 0.01).onChange( (v:number) =>{ + audio.setVolume(v) + }) + GUIHelp.open() + } + { + let wall = new Object3D() + let mr = wall.addComponent(MeshRenderer) + mr.geometry = new BoxGeometry(40, 30, 1) + let mat = new LitMaterial() + mat.baseColor = new Color(1,0,0) + mr.material = mat + this.scene.addChild(wall) + wall.z = -5 + } + { + let floor = new Object3D(); + let mr = floor.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(3000, 1, 3000); + let mat = new LitMaterial(); + mr.material = mat; + this.scene.addChild(floor); + } + + /******** light *******/ + { + this.lightObj = new Object3D(); + this.lightObj.rotationX = 35; + this.lightObj.rotationY = 110; + this.lightObj.rotationZ = 0; + let directLight = this.lightObj.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = true; + directLight.intensity = 30; + this.scene.addChild(this.lightObj); + } + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 9fd30b1e..845da1b6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -121,9 +121,6 @@ export * from "./components/anim/skeletonAnim/buffer/SkeletonBlendComputeArgs" export * from "./components/anim/skeletonAnim/buffer/SkeletonTransformComputeArgs" export * from "./components/anim/skeletonAnim/shader/compute_skeleton_blend" export * from "./components/anim/skeletonAnim/shader/compute_skeleton_transform" -export * from "./components/audio/AudioListener" -export * from "./components/audio/PositionAudio" -export * from "./components/audio/StaticAudio" export * from "./components/controller/CameraControllerBase" export * from "./components/controller/FirstPersonCameraController" export * from "./components/controller/FlyCameraController" From d1b79be579a6e2ad48abe3b6f24efad51756edf3 Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Fri, 15 Sep 2023 23:56:06 +0800 Subject: [PATCH 05/14] docs(audio): expose audio api doc --- packages/media-extention/AudioListener.ts | 1 - packages/media-extention/PositionAudio.ts | 1 - packages/media-extention/StaticAudio.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/packages/media-extention/AudioListener.ts b/packages/media-extention/AudioListener.ts index bc02ffd9..1b608089 100644 --- a/packages/media-extention/AudioListener.ts +++ b/packages/media-extention/AudioListener.ts @@ -3,7 +3,6 @@ import { ComponentBase } from '@orillusion/core'; /** * Audio Listener * Used in conjunction {@link PositionAudio} or {@link StaticAudio} - * @internal * @group Audio */ export class AudioListener extends ComponentBase { diff --git a/packages/media-extention/PositionAudio.ts b/packages/media-extention/PositionAudio.ts index f42f3942..47f0f61f 100644 --- a/packages/media-extention/PositionAudio.ts +++ b/packages/media-extention/PositionAudio.ts @@ -3,7 +3,6 @@ import { AudioListener } from './AudioListener'; import { StaticAudio } from './StaticAudio'; /** * Dynamic audio component, with volume varying based on the relative position of the monitor - * @internal * @group Audio */ export class PositionAudio extends StaticAudio { diff --git a/packages/media-extention/StaticAudio.ts b/packages/media-extention/StaticAudio.ts index a5eb2efa..995bb278 100644 --- a/packages/media-extention/StaticAudio.ts +++ b/packages/media-extention/StaticAudio.ts @@ -2,7 +2,6 @@ import { ComponentBase } from '@orillusion/core'; import { AudioListener } from './AudioListener'; /** * Static audio component, volume level does not vary depending on the position of the monitor - * @internal * @group Audio */ export class StaticAudio extends ComponentBase { From 7df4f95c9bfa85dc2aae121a64916121c2741988 Mon Sep 17 00:00:00 2001 From: OldGentleMan Date: Tue, 31 Oct 2023 16:08:48 +0800 Subject: [PATCH 06/14] feat: add graphic bath mesh (#319) add new prefab data load and parser add prefab component add prefab morph animation close sample prefab debug add blend shape anim add animtor split blendShape and skeleton anim fix animator add skeleton setting Add feature of new Bloom Post. add BitMap add OrderMap new Bloom Post remove repeat field 'format' fix skeleton world position fix apath components fix value parser to comdata fix graphic update fix prefab node name HoverCameraController add flowTarget Replace old Bloom. fix blendShape add new material shader add LitSSSShader add navigation mesh path finder. adapt Navi3DConst value exclude zero direction of calc navi mesh Add navi mesh parse action. add new material framework add new shader and material pass fix new skin component clone fix sample renderer error add graphic mesh fix pointlight shadow fix sphere geometry uv --- index.html | 4 +- index.ts | 1 + packages/debug/GUIHelp.ts | 2 + .../effect/grass/geometry/GrassGeometry.ts | 3 + .../effect/grass/material/GrassMaterial.ts | 113 ++-- .../grass/shader/GrassCastShadowShader.ts | 1 + packages/effect/grass/shader/GrassShader.ts | 1 + packages/media-extention/ChromaKeyMaterial.ts | 4 +- packages/media-extention/ImageMaterial.ts | 4 +- packages/media-extention/VideoMaterial.ts | 42 +- packages/particle/ParticleSystem.ts | 4 +- .../particle/material/ParticleMaterial.ts | 39 +- packages/particle/shader/FastMath.ts | 40 ++ .../particle/shader/ParticleRenderShader.ts | 2 +- public | 2 +- samples/animation/Sample_CurveAnimation.ts | 6 + samples/animation/Sample_MorphTarget.ts | 4 +- samples/animation/Sample_PropertyAnimation.ts | 1 + samples/base/Sample_InitEngine.ts | 4 +- samples/ext/Sample_Boxes.ts | 4 +- samples/ext/Sample_Grass.ts | 72 +-- samples/ext/Sample_Terrain.ts | 3 +- samples/geometry/Sample_ConduitGeometry2.ts | 7 +- samples/gi/Sample_GI.ts | 29 +- samples/gi/Sample_GICornellBox.ts | 13 +- samples/graphic/Sample_GraphicLine.ts | 12 +- samples/index.ts | 16 - samples/lights/Sample_PointLightShadow.ts | 10 +- samples/lights/Sample_ShadowAlpha.ts | 85 --- samples/loader/Sample_FlightHelmet.ts | 12 +- samples/loader/Sample_LoadGLB.ts | 4 +- samples/loader/Sample_LoadGLB2.ts | 7 +- samples/loader/Sample_LoadGLTF.ts | 13 +- samples/material/Sample_ChangeMaterial.ts | 13 +- samples/material/Sample_ClearCoat.ts | 11 - samples/material/Sample_GraphicMeshWave.ts | 146 ++++++ samples/material/Sample_GraphicMesh_0.ts | 201 ++++++++ samples/material/Sample_GraphicMesh_1.ts | 200 ++++++++ samples/material/Sample_GraphicMesh_2.ts | 207 ++++++++ samples/material/Sample_GraphicMesh_3.ts | 158 ++++++ samples/material/Sample_GraphicMesh_4.ts | 147 ++++++ samples/material/Sample_PBR.ts | 3 + samples/material/Sample_PBRMaterial.ts | 12 +- samples/material/Sample_UVMove.ts | 10 - samples/material/script/UVMoveComponent.ts | 4 +- samples/pick/Sample_OutlineEffectPick.ts | 3 +- samples/pick/Sample_PixelPick.ts | 9 +- samples/post/Sample_Bloom.ts | 24 +- samples/post/Sample_Fog.ts | 7 +- samples/post/Sample_GTAO.ts | 9 +- samples/post/Sample_GodRay.ts | 13 +- samples/post/Sample_TAA.ts | 11 - samples/render/Sample_BlendMode.ts | 9 - samples/sky/Sample_AtmosphericSky.ts | 2 +- samples/utils/GUIUtil.ts | 202 ++++++-- src/Engine3D.ts | 91 +++- src/assets/Res.ts | 88 +++- src/assets/shader/ShaderLib.ts | 26 +- .../shader/{utils => compute}/BRDFLUT.ts | 0 src/assets/shader/compute/BloomEffect_cs.ts | 214 ++++++++ .../shader/compute/DDGIIrradiance_Cs.ts | 3 +- .../shader/compute/DDGILighting_CSShader.ts | 1 + src/assets/shader/compute/GTAO_cs.ts | 19 +- .../shader/compute/MultiBouncePass_cs.ts | 2 +- src/assets/shader/compute/PreIntegratedLut.ts | 70 +++ src/assets/shader/core/base/Common_frag.ts | 10 +- .../shader/core/common/GlobalUniform.ts | 14 +- .../shader/core/pass/CastShadow_pass.ts | 166 ++++-- .../shader/core/pass/SkyGBuffer_pass.ts | 13 +- .../shader/core/struct/FragmentVarying.ts | 19 +- src/assets/shader/core/struct/ShadingInput.ts | 10 +- .../core/struct/VertexAttributeIndexShader.ts | 86 ++++ .../shader/core/struct/VertexAttributes.ts | 153 ++++-- src/assets/shader/lighting/BRDF_frag.ts | 76 ++- src/assets/shader/lighting/BsDF_frag.ts | 154 ++++++ src/assets/shader/lighting/BxDF_frag.ts | 87 ++-- src/assets/shader/lighting/Hair_frag.ts | 326 ++++++++++++ src/assets/shader/lighting/Irradiance_frag.ts | 7 +- .../shader/lighting/LightingFunction_frag.ts | 59 ++- src/assets/shader/materials/ColorLitShader.ts | 8 +- src/assets/shader/materials/Hair_shader.ts | 247 +++++++++ .../{LambertShader.ts => Lambert_shader.ts} | 2 +- .../materials/{LitShader.ts => Lit_shader.ts} | 4 +- src/assets/shader/materials/PBRLItShader.ts | 148 ++++-- .../shader/materials/PBRLitSSSShader.ts | 218 ++++++++ src/assets/shader/materials/PavementShader.ts | 4 +- src/assets/shader/materials/UnLit.ts | 12 + .../shader/materials/UnLitTextureArray.ts | 77 +++ .../materials/program/BxdfDebug_frag.ts | 6 +- .../materials/program/NormalMap_frag.ts | 20 +- .../materials/program/ShadowMapping_frag.ts | 129 ++--- .../uniforms/PhysicMaterialUniform_frag.ts | 50 +- .../uniforms/UnLitMaterialUniform_frag.ts | 18 +- src/assets/shader/math/FastMathShader.ts | 82 ++- src/assets/shader/math/MathShader.ts | 10 +- src/assets/shader/post/Bloom_shader.ts | 248 --------- src/assets/shader/post/GlobalFog_shader.ts | 2 + src/assets/shader/utils/ColorUtil.ts | 8 + src/components/SkeletonAnimationComponent.ts | 2 + src/components/anim/AnimatorComponent.ts | 286 +++++++++++ .../anim/morphAnim/MorphTargetBlender.ts | 23 +- .../anim/morphAnim/MorphTargetData.ts | 23 +- .../anim/morphAnim/MorphTargetKey.ts | 55 ++ src/components/anim/skeletonAnim/Joint.ts | 7 +- .../anim/skeletonAnim/SkeletonPose.ts | 188 +++---- .../controller/HoverCameraController.ts | 18 + src/components/gui/core/GUIGeometry.ts | 3 + src/components/gui/core/GUIMaterial.ts | 43 +- src/components/gui/core/GUIRenderer.ts | 4 +- src/components/lights/DirectLight.ts | 2 + src/components/lights/Light.ts | 141 +++++ src/components/lights/LightBase.ts | 19 + src/components/lights/PointLight.ts | 3 +- src/components/lights/SpotLight.ts | 2 + .../post/PostProcessingComponent.ts | 30 +- .../renderer/InstanceDrawComponent.ts | 10 +- src/components/renderer/MeshFilter.ts | 36 ++ src/components/renderer/MeshRenderer.ts | 24 +- src/components/renderer/RenderNode.ts | 87 ++-- .../renderer/SkinnedMeshRenderer.ts | 189 +++---- .../renderer/SkinnedMeshRenderer2.ts | 154 ++++++ src/components/renderer/SkyRenderer.ts | 4 +- src/core/Camera3D.ts | 2 +- src/core/View3D.ts | 3 +- src/core/ViewQuad.ts | 84 +-- src/core/entities/Entity.ts | 3 +- src/core/entities/Object3D.ts | 6 +- src/core/geometry/ExtrudeGeometry.ts | 3 + src/core/geometry/GeometryBase.ts | 95 +++- src/core/geometry/GeometryVertexBuffer.ts | 77 ++- src/core/geometry/GeometryVertexType.ts | 1 + src/core/geometry/VertexAttributeName.ts | 8 + src/core/pool/memory/MemoryInfo.ts | 6 - src/core/tree/quad/IQuadNode.ts | 16 + src/core/tree/quad/QuadAABB.ts | 147 ++++++ src/core/tree/quad/QuadRoot.ts | 92 ++++ src/core/tree/quad/QuadTree.ts | 293 +++++++++++ src/core/tree/quad/QuadTreeCell.ts | 48 ++ src/gfx/generate/BrdfLUTGenerate.ts | 2 +- src/gfx/generate/PassGenerate.ts | 116 ++--- src/gfx/graphics/webGpu/Context3D.ts | 39 +- src/gfx/graphics/webGpu/PipelinePool.ts | 2 +- .../webGpu/compute/PreIntegratedLutCompute.ts | 40 ++ .../webGpu/compute/RenderShaderCompute.ts | 35 ++ .../core/bindGroups/GlobalUniformGroup.ts | 39 +- .../webGpu/core/buffer/ComputeGPUBuffer.ts | 2 +- .../webGpu/core/buffer/GPUBufferBase.ts | 8 +- .../webGpu/core/buffer/IndicesGPUBuffer.ts | 1 + .../buffer/MaterialDataUniformGPUBuffer.ts | 7 +- .../webGpu/core/buffer/MatrixGPUBuffer.ts | 2 +- .../webGpu/core/buffer/StorageGPUBuffer.ts | 2 +- .../webGpu/core/buffer/UniformGPUBuffer.ts | 2 +- .../webGpu/core/buffer/VertexGPUBuffer.ts | 1 + .../graphics/webGpu/core/texture/Texture.ts | 35 +- .../core/texture/TextureMipmapGenerator.ts | 14 +- .../descriptor/WebGPUDescriptorCreator.ts | 21 +- .../graphics/webGpu/shader/ComputeShader.ts | 4 +- .../{RenderShader.ts => RenderShaderPass.ts} | 82 ++- src/gfx/graphics/webGpu/shader/Shader.ts | 245 +++++++++ .../{ShaderBase.ts => ShaderPassBase.ts} | 38 +- .../graphics/webGpu/shader/util/ShaderUtil.ts | 6 +- .../shader/value/ShaderReflectionInfo.ts | 14 +- .../webGpu/shader/value/ShaderState.ts | 1 + src/gfx/renderJob/GPUContext.ts | 8 +- .../renderJob/collect/EntityBatchCollect.ts | 6 +- src/gfx/renderJob/collect/EntityCollect.ts | 6 +- src/gfx/renderJob/collect/RenderGroup.ts | 4 +- .../renderJob/collect/RenderShaderCollect.ts | 5 - .../renderJob/collect/ShadowLightsCollect.ts | 55 +- src/gfx/renderJob/frame/GBufferFrame.ts | 39 +- src/gfx/renderJob/frame/ProbeGBufferFrame.ts | 2 +- src/gfx/renderJob/frame/RTFrame.ts | 6 +- src/gfx/renderJob/frame/RTResourceMap.ts | 4 +- src/gfx/renderJob/jobs/ForwardRenderJob.ts | 10 + src/gfx/renderJob/jobs/RenderMap.ts | 10 +- src/gfx/renderJob/jobs/RendererJob.ts | 11 +- .../renderJob/passRenderer/RenderContext.ts | 22 +- .../renderJob/passRenderer/RendererBase.ts | 12 +- .../cluster/ClusterLightingRender.ts | 72 +-- .../passRenderer/color/ColorPassRenderer.ts | 21 +- .../ddgi/DDGIIrradianceComputePass.ts | 2 +- .../passRenderer/ddgi/DDGIIrradianceVolume.ts | 5 +- .../passRenderer/ddgi/DDGIMultiBouncePass.ts | 2 +- .../passRenderer/ddgi/DDGIProbeRenderer.ts | 12 +- .../graphic/Graphic3DBatchRenderer.ts | 6 +- .../graphic/Graphic3DFixedRenderPipeline.ts | 9 +- .../passRenderer/graphic/Graphic3DRender.ts | 11 +- .../passRenderer/graphic/Graphics3DShape.ts | 40 +- .../passRenderer/graphic/new/Graphic3DMesh.ts | 20 + .../graphic/new/Graphic3DMeshRenderer.ts | 55 ++ .../passRenderer/post/PostRenderer.ts | 6 +- .../preDepth/PreDepthPassRenderer.ts | 4 +- .../shadow/PointLightShadowRenderer.ts | 14 +- .../shadow/ShadowMapPassRenderer.ts | 7 +- .../passRenderer/state/RendererPassState.ts | 7 +- .../passRenderer/state/RendererType.ts | 2 +- src/gfx/renderJob/post/BloomPost.ts | 280 ++++++++++ src/gfx/renderJob/post/DepthOfFieldPost.ts | 4 +- src/gfx/renderJob/post/FXAAPost.ts | 12 +- src/gfx/renderJob/post/GTAOPost.ts | 6 +- src/gfx/renderJob/post/GlobalFog.ts | 78 +-- src/gfx/renderJob/post/GodRayPost.ts | 4 +- src/gfx/renderJob/post/HDRBloomPost.ts | 189 ------- src/gfx/renderJob/post/PostBase.ts | 5 +- src/gfx/renderJob/post/SSRPost.ts | 4 +- src/index.ts | 95 +++- src/loader/FileLoader.ts | 16 +- src/loader/parser/AtlasParser.ts | 3 +- src/loader/parser/B3DMParser.ts | 3 +- src/loader/parser/FontParser.ts | 3 +- src/loader/parser/I3DMParser.ts | 4 +- src/loader/parser/OBJParser.ts | 6 +- src/loader/parser/ParserBase.ts | 3 +- src/loader/parser/ParserFormat.ts | 5 + src/loader/parser/RGBEParser.ts | 2 +- src/loader/parser/gltf/GLBParser.ts | 3 +- src/loader/parser/gltf/GLTFParser.ts | 3 +- .../parser/gltf/GLTFSubParserConverter.ts | 61 +-- .../parser/gltf/GLTFSubParserSkeleton.ts | 73 +-- .../gltf/extends/KHR_materials_clearcoat.ts | 2 +- .../parser/prefab/PrefabAvatarParser.ts | 56 ++ .../parser/prefab/PrefabMaterialParser.ts | 171 ++++++ src/loader/parser/prefab/PrefabMeshParser.ts | 182 +++++++ src/loader/parser/prefab/PrefabParser.ts | 98 ++++ src/loader/parser/prefab/PrefabStringUtil.ts | 63 +++ .../parser/prefab/PrefabTextureParser.ts | 46 ++ .../parser/prefab/mats/MaterialUtilities.ts | 139 +++++ .../prefab/mats/shader/LitHairShader.ts | 220 ++++++++ .../parser/prefab/mats/shader/LitSSSShader.ts | 178 +++++++ .../parser/prefab/mats/shader/LitShader.ts | 121 +++++ .../parser/prefab/mats/shader/QuadShader.ts | 34 ++ .../parser/prefab/mats/shader/SkyShader.ts | 30 ++ .../parser/prefab/mats/shader/StandShader.ts | 485 ++++++++++++++++++ .../parser/prefab/mats/shader/UnLitShader.ts | 98 ++++ .../prefab/mats/shader/UnLitTexArrayShader.ts | 103 ++++ src/loader/parser/prefab/prefabData/APatch.ts | 34 ++ .../prefab/prefabData/BlendShapeData.ts | 44 ++ .../prefab/prefabData/BlendShapeFrameData.ts | 27 + .../prefabData/BlendShapePropertyData.ts | 24 + src/loader/parser/prefab/prefabData/KVData.ts | 24 + .../prefab/prefabData/PrefabAvatarData.ts | 23 + .../prefab/prefabData/PrefabBoneData.ts | 32 ++ .../prefab/prefabData/PrefabMeshData.ts | 18 + .../parser/prefab/prefabData/PrefabNode.ts | 67 +++ .../prefab/prefabData/PrefabTextureData.ts | 16 + .../parser/prefab/prefabData/ValueParser.ts | 135 +++++ .../parser/prefab/prefabData/ValueType.ts | 37 ++ src/materials/BlendMode.ts | 6 +- src/materials/ColorLitMaterial.ts | 13 +- src/materials/GIProbeMaterial.ts | 35 +- src/materials/GlassMaterial.ts | 97 ++-- src/materials/LambertMaterial.ts | 39 +- src/materials/LitMaterial.ts | 195 +++++-- src/materials/Material.ts | 238 +++++---- src/materials/PhysicMaterial.ts | 177 ++++--- src/materials/PointMaterial.ts | 66 --- src/materials/SkyMaterial.ts | 38 +- src/materials/UnLitMaterial.ts | 39 +- src/materials/UnLitTexArrayMaterial.ts | 61 +++ .../multiPass/CastPointShadowMaterialPass.ts | 6 +- .../multiPass/CastShadowMaterialPass.ts | 11 +- src/materials/multiPass/DepthMaterialPass.ts | 5 +- src/materials/multiPass/GBufferPass.ts | 8 +- src/materials/multiPass/SkyGBufferPass.ts | 9 +- src/math/AnimationCurve.ts | 67 +-- src/math/AnimationCurveClip.ts | 65 +++ src/math/AnimationCurveT.ts | 151 ++++++ src/math/BiMap.ts | 43 ++ src/math/OrderMap.ts | 63 +++ src/math/ParticleSystemCurves.ts | 3 +- src/math/Plane3D.ts | 248 +++++++++ src/math/PlaneClassification.ts | 36 ++ src/math/PolynomialCurve.ts | 3 +- src/math/Quaternion.ts | 6 + src/math/Vector3.ts | 35 ++ src/math/enum/FrameCache.ts | 10 + src/math/enum/Keyframe.ts | 41 ++ src/math/enum/T/KeyframeT.ts | 136 +++++ src/math/enum/T/ValueOp.ts | 39 ++ src/math/enum/WrapTimeMode.ts | 11 + src/math/navigation/DoubleArray.ts | 52 ++ src/math/navigation/Navi3DAstar.ts | 108 ++++ src/math/navigation/Navi3DConst.ts | 10 + src/math/navigation/Navi3DEdge.ts | 147 ++++++ src/math/navigation/Navi3DFunnel.ts | 312 +++++++++++ src/math/navigation/Navi3DMaskType.ts | 3 + src/math/navigation/Navi3DMergeVertex.ts | 63 +++ src/math/navigation/Navi3DMesh.ts | 167 ++++++ src/math/navigation/Navi3DPoint.ts | 36 ++ src/math/navigation/Navi3DPoint2D.ts | 36 ++ src/math/navigation/Navi3DPointFat.ts | 36 ++ src/math/navigation/Navi3DRouter.ts | 218 ++++++++ src/math/navigation/Navi3DTriangle.ts | 222 ++++++++ src/setting/EngineSetting.ts | 6 + src/setting/LoaderSetting.ts | 11 + src/setting/RenderSetting.ts | 4 +- src/setting/ShadowSetting.ts | 4 + src/setting/post/BloomSetting.ts | 41 +- src/shape/BoxGeometry.ts | 3 + src/shape/CylinderGeometry.ts | 3 + src/shape/PlaneGeometry.ts | 3 + src/shape/SphereGeometry.ts | 5 +- src/shape/StripeGeometry.ts | 83 +++ src/shape/TorusGeometry.ts | 3 + src/textures/BitmapTexture2D.ts | 46 +- src/textures/BitmapTexture2DArray.ts | 10 +- src/textures/ShadowTexture.ts | 186 +++++++ src/textures/VirtualTexture.ts | 48 +- src/util/BytesArray.ts | 290 +++++++++++ src/util/BytesStream.ts | 12 - src/util/GeometryUtil.ts | 49 +- src/util/Global.ts | 9 + src/util/Object3DUtil.ts | 2 + src/util/SerializeDecoration.ts | 24 + src/util/StorageUtil.ts | 19 + test/components/PostEffects_HDRBloom.test.ts | 6 +- test/shader/RenderShader.test.ts | 4 +- vite.config.js | 14 +- 318 files changed, 13198 insertions(+), 2908 deletions(-) create mode 100644 index.ts delete mode 100644 samples/lights/Sample_ShadowAlpha.ts create mode 100644 samples/material/Sample_GraphicMeshWave.ts create mode 100644 samples/material/Sample_GraphicMesh_0.ts create mode 100644 samples/material/Sample_GraphicMesh_1.ts create mode 100644 samples/material/Sample_GraphicMesh_2.ts create mode 100644 samples/material/Sample_GraphicMesh_3.ts create mode 100644 samples/material/Sample_GraphicMesh_4.ts rename src/assets/shader/{utils => compute}/BRDFLUT.ts (100%) create mode 100644 src/assets/shader/compute/BloomEffect_cs.ts create mode 100644 src/assets/shader/compute/PreIntegratedLut.ts create mode 100644 src/assets/shader/core/struct/VertexAttributeIndexShader.ts create mode 100644 src/assets/shader/lighting/BsDF_frag.ts create mode 100644 src/assets/shader/lighting/Hair_frag.ts create mode 100644 src/assets/shader/materials/Hair_shader.ts rename src/assets/shader/materials/{LambertShader.ts => Lambert_shader.ts} (97%) rename src/assets/shader/materials/{LitShader.ts => Lit_shader.ts} (85%) create mode 100644 src/assets/shader/materials/PBRLitSSSShader.ts create mode 100644 src/assets/shader/materials/UnLitTextureArray.ts delete mode 100644 src/assets/shader/post/Bloom_shader.ts create mode 100644 src/components/anim/AnimatorComponent.ts create mode 100644 src/components/lights/Light.ts create mode 100644 src/components/renderer/MeshFilter.ts create mode 100644 src/components/renderer/SkinnedMeshRenderer2.ts create mode 100644 src/core/tree/quad/IQuadNode.ts create mode 100644 src/core/tree/quad/QuadAABB.ts create mode 100644 src/core/tree/quad/QuadRoot.ts create mode 100644 src/core/tree/quad/QuadTree.ts create mode 100644 src/core/tree/quad/QuadTreeCell.ts create mode 100644 src/gfx/graphics/webGpu/compute/PreIntegratedLutCompute.ts create mode 100644 src/gfx/graphics/webGpu/compute/RenderShaderCompute.ts rename src/gfx/graphics/webGpu/shader/{RenderShader.ts => RenderShaderPass.ts} (94%) create mode 100644 src/gfx/graphics/webGpu/shader/Shader.ts rename src/gfx/graphics/webGpu/shader/{ShaderBase.ts => ShaderPassBase.ts} (87%) create mode 100644 src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh.ts create mode 100644 src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts create mode 100644 src/gfx/renderJob/post/BloomPost.ts delete mode 100644 src/gfx/renderJob/post/HDRBloomPost.ts create mode 100644 src/loader/parser/ParserFormat.ts create mode 100644 src/loader/parser/prefab/PrefabAvatarParser.ts create mode 100644 src/loader/parser/prefab/PrefabMaterialParser.ts create mode 100644 src/loader/parser/prefab/PrefabMeshParser.ts create mode 100644 src/loader/parser/prefab/PrefabParser.ts create mode 100644 src/loader/parser/prefab/PrefabStringUtil.ts create mode 100644 src/loader/parser/prefab/PrefabTextureParser.ts create mode 100644 src/loader/parser/prefab/mats/MaterialUtilities.ts create mode 100644 src/loader/parser/prefab/mats/shader/LitHairShader.ts create mode 100644 src/loader/parser/prefab/mats/shader/LitSSSShader.ts create mode 100644 src/loader/parser/prefab/mats/shader/LitShader.ts create mode 100644 src/loader/parser/prefab/mats/shader/QuadShader.ts create mode 100644 src/loader/parser/prefab/mats/shader/SkyShader.ts create mode 100644 src/loader/parser/prefab/mats/shader/StandShader.ts create mode 100644 src/loader/parser/prefab/mats/shader/UnLitShader.ts create mode 100644 src/loader/parser/prefab/mats/shader/UnLitTexArrayShader.ts create mode 100644 src/loader/parser/prefab/prefabData/APatch.ts create mode 100644 src/loader/parser/prefab/prefabData/BlendShapeData.ts create mode 100644 src/loader/parser/prefab/prefabData/BlendShapeFrameData.ts create mode 100644 src/loader/parser/prefab/prefabData/BlendShapePropertyData.ts create mode 100644 src/loader/parser/prefab/prefabData/KVData.ts create mode 100644 src/loader/parser/prefab/prefabData/PrefabAvatarData.ts create mode 100644 src/loader/parser/prefab/prefabData/PrefabBoneData.ts create mode 100644 src/loader/parser/prefab/prefabData/PrefabMeshData.ts create mode 100644 src/loader/parser/prefab/prefabData/PrefabNode.ts create mode 100644 src/loader/parser/prefab/prefabData/PrefabTextureData.ts create mode 100644 src/loader/parser/prefab/prefabData/ValueParser.ts create mode 100644 src/loader/parser/prefab/prefabData/ValueType.ts delete mode 100644 src/materials/PointMaterial.ts create mode 100644 src/materials/UnLitTexArrayMaterial.ts create mode 100644 src/math/AnimationCurveClip.ts create mode 100644 src/math/AnimationCurveT.ts create mode 100644 src/math/BiMap.ts create mode 100644 src/math/OrderMap.ts create mode 100644 src/math/Plane3D.ts create mode 100644 src/math/PlaneClassification.ts create mode 100644 src/math/enum/FrameCache.ts create mode 100644 src/math/enum/Keyframe.ts create mode 100644 src/math/enum/T/KeyframeT.ts create mode 100644 src/math/enum/T/ValueOp.ts create mode 100644 src/math/enum/WrapTimeMode.ts create mode 100644 src/math/navigation/DoubleArray.ts create mode 100644 src/math/navigation/Navi3DAstar.ts create mode 100644 src/math/navigation/Navi3DConst.ts create mode 100644 src/math/navigation/Navi3DEdge.ts create mode 100644 src/math/navigation/Navi3DFunnel.ts create mode 100644 src/math/navigation/Navi3DMaskType.ts create mode 100644 src/math/navigation/Navi3DMergeVertex.ts create mode 100644 src/math/navigation/Navi3DMesh.ts create mode 100644 src/math/navigation/Navi3DPoint.ts create mode 100644 src/math/navigation/Navi3DPoint2D.ts create mode 100644 src/math/navigation/Navi3DPointFat.ts create mode 100644 src/math/navigation/Navi3DRouter.ts create mode 100644 src/math/navigation/Navi3DTriangle.ts create mode 100644 src/setting/LoaderSetting.ts create mode 100644 src/shape/StripeGeometry.ts create mode 100644 src/textures/ShadowTexture.ts create mode 100644 src/util/BytesArray.ts delete mode 100644 src/util/BytesStream.ts create mode 100644 src/util/StorageUtil.ts diff --git a/index.html b/index.html index 696e69b5..ff36f92d 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Orillusion | Samples + Graphic3D | Samples - + \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 00000000..3b86b522 --- /dev/null +++ b/index.ts @@ -0,0 +1 @@ +export * from "./src/index" diff --git a/packages/debug/GUIHelp.ts b/packages/debug/GUIHelp.ts index 12b24969..324b4320 100644 --- a/packages/debug/GUIHelp.ts +++ b/packages/debug/GUIHelp.ts @@ -1,9 +1,11 @@ +import { GTAOPost } from '../../src/index.js'; import { GUI } from './dat.gui.module.js' /** * @internal */ class _GUIHelp { + public debug: boolean = false; public data: any; public gui: GUI; diff --git a/packages/effect/grass/geometry/GrassGeometry.ts b/packages/effect/grass/geometry/GrassGeometry.ts index fe8c89d7..0289b3b5 100644 --- a/packages/effect/grass/geometry/GrassGeometry.ts +++ b/packages/effect/grass/geometry/GrassGeometry.ts @@ -110,6 +110,9 @@ export class GrassGeometry extends GeometryBase { indexCount: indexes.length, vertexStart: 0, index: 0, + vertexCount: 0, + firstStart: 0, + topology: 0 }); this.bounds = new BoundingBox(Vector3.ZERO, new Vector3(9999, 9999, 9999)); diff --git a/packages/effect/grass/material/GrassMaterial.ts b/packages/effect/grass/material/GrassMaterial.ts index 3d3920a8..0974e034 100644 --- a/packages/effect/grass/material/GrassMaterial.ts +++ b/packages/effect/grass/material/GrassMaterial.ts @@ -1,4 +1,4 @@ -import { BlendMode, Color, GPUAddressMode, Material, RenderShader, RendererType, ShaderLib, Texture, Vector2, Vector3, Vector4 } from "@orillusion/core"; +import { BlendMode, Color, GPUAddressMode, Material, RenderShaderPass, PassType, Shader, ShaderLib, Texture, Vector2, Vector3, Vector4 } from "@orillusion/core"; import { GrassShader } from "../shader/GrassShader"; import { GrassVertexAttributeShader } from "../shader/GrassVertexAttributeShader"; import { GrassCastShadowShader } from "../shader/GrassCastShadowShader"; @@ -7,11 +7,12 @@ export class GrassMaterial extends Material { constructor() { super(); + let newShader = new Shader(); ShaderLib.register("GrassVertexAttributeShader", GrassVertexAttributeShader); ShaderLib.register("GrassShader", GrassShader); - let colorPass = new RenderShader(`GrassShader`, `GrassShader`); - this.defaultPass = colorPass; + let colorPass = new RenderShaderPass(`GrassShader`, `GrassShader`); + colorPass.passType = PassType.COLOR; colorPass.setShaderEntry(`VertMain`, `FragMain`) colorPass.setDefine("TRANSFORMVERTEX", true); let shaderState = colorPass.shaderState; @@ -21,17 +22,18 @@ export class GrassMaterial extends Material { shaderState.useLight = true; shaderState.castShadow = false; shaderState.blendMode = BlendMode.NONE; + newShader.addRenderPass(colorPass); ShaderLib.register("GrassCastShadowShader", GrassCastShadowShader); - let shadowPass = new RenderShader(`GrassCastShadowShader`, `GrassCastShadowShader`); + let shadowPass = new RenderShaderPass(`GrassCastShadowShader`, `GrassCastShadowShader`); + shadowPass.passType = PassType.SHADOW shadowPass.setDefine("USE_ALPHACUT", true); shadowPass.setDefine("TRANSFORMVERTEX", true); shadowPass.setShaderEntry(`VertMain`) shadowPass.shaderState.blendMode = BlendMode.NONE; shadowPass.shaderState.receiveEnv = false; - this.addPass(RendererType.SHADOW, shadowPass); - + newShader.addRenderPass(shadowPass); colorPass.setUniformColor("baseColor", new Color(0.0, 1.0, 0.0, 1.0)); colorPass.setUniformColor("grassBottomColor", new Color(3 / 255, 16 / 255, 3 / 255)); @@ -67,159 +69,118 @@ export class GrassMaterial extends Material { // this.baseMap = Engine3D.res.whiteTexture; colorPass.doubleSide = true; shadowPass.doubleSide = true; + + this.shader = newShader; } public set baseMap(texture: Texture) { - // texture.visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - this.defaultPass.setTexture(`baseMap`, texture); - shadowPass.setTexture(`baseMap`, texture); + this.shader.setTexture(`baseMap`, texture); } public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } public set windMap(texture: Texture) { // texture.visibility = GPUShaderStage.VERTEX; texture.addressModeU = GPUAddressMode.repeat; texture.addressModeV = GPUAddressMode.repeat; - this.defaultPass.setTexture("windMap", texture); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setTexture("windMap", texture); + this.shader.setTexture("windMap", texture); } public set windBound(v: Vector4) { - this.defaultPass.setUniformVector4("windBound", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - this.defaultPass.setUniformVector4("windBound", v); - shadowPass.setUniformVector4("windBound", v); + this.shader.setUniformVector4("windBound", v); } public get windBound(): Vector4 { - return this.defaultPass.uniforms["windBound"].vector4; + return this.shader.getUniform("windBound").data; } public set grassBaseColor(v: Color) { - this.defaultPass.setUniformColor("grassBottomColor", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - shadowPass.setUniformColor("grassBottomColor", v); + this.shader.setUniformColor("grassBottomColor", v); } public get grassBaseColor(): Color { - return this.defaultPass.uniforms["grassBottomColor"].color; + return this.shader.getUniformColor("grassBottomColor"); } public set grassTopColor(v: Color) { - this.defaultPass.setUniformColor("grassTopColor", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformColor("grassTopColor", v); + this.shader.setUniformColor("grassTopColor", v); } public get grassTopColor(): Color { - return this.defaultPass.uniforms["grassTopColor"].color; + return this.shader.getUniformColor("grassTopColor"); } public set windDirection(v: Vector2) { - this.defaultPass.setUniformVector2("windDirection", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformVector2("windDirection", v); + this.shader.setUniformVector2("windDirection", v); } public get windDirection(): Vector2 { - return this.defaultPass.uniforms["windDirection"].vector2; + return this.shader.getUniform("windDirection").data; } public set windPower(v: number) { - this.defaultPass.setUniformFloat("windPower", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("windPower", v); + this.shader.setUniformFloat("windPower", v); } public get windPower(): number { - return this.defaultPass.uniforms["windPower"].data; + return this.shader.getUniform("windPower").data; } public set windSpeed(v: number) { - this.defaultPass.setUniformFloat("windSpeed", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("windSpeed", v); + this.shader.setUniformFloat("windSpeed", v); } public get windSpeed(): number { - return this.defaultPass.uniforms["windSpeed"].data; + return this.shader.getUniform("windSpeed").data; } public set grassHeight(v: number) { - this.defaultPass.setUniformFloat("grassHeight", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("grassHeight", v); + this.shader.setUniformFloat("grassHeight", v); } public get grassHeight(): number { - return this.defaultPass.uniforms["grassHeight"].data; + return this.shader.getUniform("grassHeight").data; } public set curvature(v: number) { - this.defaultPass.setUniformFloat("curvature", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("curvature", v); + this.shader.setUniformFloat("curvature", v); } public get curvature(): number { - return this.defaultPass.uniforms["curvature"].data; + return this.shader.getUniform("curvature").data; } public set roughness(v: number) { - this.defaultPass.setUniformFloat("roughness", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("roughness", v); + this.shader.setUniformFloat("roughness", v); } public get roughness(): number { - return this.defaultPass.uniforms["roughness"].data; + return this.shader.getUniform("roughness").data; } public set translucent(v: number) { - this.defaultPass.setUniformFloat("translucent", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("translucent", v); + this.shader.setUniformFloat("translucent", v); } public get translucent(): number { - return this.defaultPass.uniforms["translucent"].data; + return this.shader.getUniform("translucent").data; } public set soft(v: number) { - this.defaultPass.setUniformFloat("soft", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("soft", v); + this.shader.setUniformFloat("soft", v); } public get soft(): number { - return this.defaultPass.uniforms["soft"].data; + return this.shader.getUniform("soft").data; } public set specular(v: number) { - this.defaultPass.setUniformFloat("specular", v); - let shadowPass = this.getPass(RendererType.SHADOW)[0]; - - shadowPass.setUniformFloat("specular", v); + this.shader.setUniformFloat("specular", v); } public get specular(): number { - return this.defaultPass.uniforms["specular"].data; + return this.shader.getUniform("specular").data; } } \ No newline at end of file diff --git a/packages/effect/grass/shader/GrassCastShadowShader.ts b/packages/effect/grass/shader/GrassCastShadowShader.ts index 57eeb1db..9446fa85 100644 --- a/packages/effect/grass/shader/GrassCastShadowShader.ts +++ b/packages/effect/grass/shader/GrassCastShadowShader.ts @@ -36,6 +36,7 @@ export let GrassCastShadowShader = /* wgsl */` var windMap: texture_2d; const DEGREES_TO_RADIANS : f32 = 3.1415926 / 180.0 ; + const PI : f32 = 3.1415926 ; @vertex fn VertMain( vertex:VertexAttributes ) -> VertexOutput { diff --git a/packages/effect/grass/shader/GrassShader.ts b/packages/effect/grass/shader/GrassShader.ts index 36f6bf5d..9b401019 100644 --- a/packages/effect/grass/shader/GrassShader.ts +++ b/packages/effect/grass/shader/GrassShader.ts @@ -42,6 +42,7 @@ export let GrassShader = /* wgsl */` var windMap: texture_2d; const DEGREES_TO_RADIANS : f32 = 3.1415926 / 180.0 ; + const PI : f32 = 3.1415926 ; @vertex fn VertMain( vertex:VertexAttributes ) -> VertexOutput { diff --git a/packages/media-extention/ChromaKeyMaterial.ts b/packages/media-extention/ChromaKeyMaterial.ts index d2c0fe23..c22c7e80 100644 --- a/packages/media-extention/ChromaKeyMaterial.ts +++ b/packages/media-extention/ChromaKeyMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Vector4, Color, BlendMode, registerMaterial, Material, RenderShader, Texture } from "@orillusion/core"; +import { Engine3D, ShaderLib, Vector4, Color, BlendMode, registerMaterial, Material, RenderShaderPass, Texture } from "@orillusion/core"; import { ChromaKeyShader } from "./ChromaKeyShader"; /** @@ -14,7 +14,7 @@ export class ChromaKeyMaterial extends Material { super(); ShaderLib.register("ChromaKeyShader", ChromaKeyShader); - this.defaultPass = new RenderShader( + this.defaultPass = new RenderShaderPass( `ChromaKeyShader`, `ChromaKeyShader` ); diff --git a/packages/media-extention/ImageMaterial.ts b/packages/media-extention/ImageMaterial.ts index bba37b19..7c396d18 100644 --- a/packages/media-extention/ImageMaterial.ts +++ b/packages/media-extention/ImageMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Vector4, Color, Texture, Material, RenderShader } from "@orillusion/core"; +import { Engine3D, ShaderLib, Vector4, Color, Texture, Material, RenderShaderPass } from "@orillusion/core"; import ImageMaterialShader from "./ImageMaterialShader.wgsl?raw"; @@ -15,7 +15,7 @@ export class ImageMaterial extends Material { constructor() { super(); ShaderLib.register("ImageMaterialShader", ImageMaterialShader); - this.defaultPass = new RenderShader(`ImageMaterialShader`, `ImageMaterialShader`); + this.defaultPass = new RenderShaderPass(`ImageMaterialShader`, `ImageMaterialShader`); this.defaultPass.setShaderEntry(`VertMain`, `FragMain`) this.defaultPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); this.defaultPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); diff --git a/packages/media-extention/VideoMaterial.ts b/packages/media-extention/VideoMaterial.ts index cba9ae88..acc01e85 100644 --- a/packages/media-extention/VideoMaterial.ts +++ b/packages/media-extention/VideoMaterial.ts @@ -1,5 +1,5 @@ -import { Color, Engine3D, Material, RenderShader, ShaderLib, Texture, Vector4, registerMaterial } from '@orillusion/core'; +import { Color, Engine3D, Material, PassType, RenderShaderPass, Shader, ShaderLib, Texture, Vector4 } from '@orillusion/core'; import { VideoShader } from './VideoShader'; /** @@ -16,18 +16,19 @@ export class VideoMaterial extends Material { super(); ShaderLib.register('VideoShader', VideoShader); - ShaderLib.register("VideoShader", VideoShader); + let newShader = new Shader(); - this.defaultPass = new RenderShader(`VideoShader`, `VideoShader`); - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`) + let colorPass = new RenderShaderPass(`VideoShader`, `VideoShader`); + colorPass.passType = PassType.COLOR; + colorPass.setShaderEntry(`VertMain`, `FragMain`) - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`) - this.defaultPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); - this.defaultPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); - this.defaultPass.setUniformColor(`baseColor`, new Color()); - this.defaultPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); - this.defaultPass.setUniformFloat(`alphaCutoff`, 0.5); - let shaderState = this.defaultPass.shaderState; + colorPass.setShaderEntry(`VertMain`, `FragMain`) + colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + colorPass.setUniformColor(`baseColor`, new Color()); + colorPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); + colorPass.setUniformFloat(`alphaCutoff`, 0.5); + let shaderState = colorPass.shaderState; shaderState.acceptShadow = false; shaderState.receiveEnv = false; shaderState.acceptGI = false; @@ -35,30 +36,32 @@ export class VideoMaterial extends Material { shaderState.castShadow = false; shaderState.useZ = false; + newShader.addRenderPass(colorPass); + this.shader = newShader; // default value - this.defaultPass.setTexture(`baseMap`, Engine3D.res.whiteTexture); + colorPass.setTexture(`baseMap`, Engine3D.res.whiteTexture); } /** * Set the clip rect area */ public set rectClip(value: Vector4) { - this.defaultPass.uniforms[`rectClip`].vector4 = value; + this.shader.setUniformVector4("rectClip", value); } /** * Get the clip rect area */ public get rectClip(): Vector4 { - return this.defaultPass.uniforms[`rectClip`].vector4; + return this.shader.getUniform("rectClip").data; } public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } public set baseMap(value: Texture) { - this.defaultPass.setTexture(`baseMap`, value); + this.shader.setTexture(`baseMap`, value); } /** @@ -74,11 +77,4 @@ export class VideoMaterial extends Material { public set shadowMap(texture: Texture) { //not need shadowMap texture } - - /** - * Start debug GUI - */ - debug() { - - } } \ No newline at end of file diff --git a/packages/particle/ParticleSystem.ts b/packages/particle/ParticleSystem.ts index a03334cc..b566267a 100644 --- a/packages/particle/ParticleSystem.ts +++ b/packages/particle/ParticleSystem.ts @@ -1,4 +1,4 @@ -import { ShaderLib, RenderNode, RendererMask, GeometryBase, Ctor, PlaneGeometry, Vector3, View3D, Time, Material, RendererType } from "@orillusion/core"; +import { ShaderLib, RenderNode, RendererMask, GeometryBase, Ctor, PlaneGeometry, Vector3, View3D, Time, Material, PassType } from "@orillusion/core"; import { ParticleMaterial } from "./material/ParticleMaterial"; import { ParticleSimulator } from "./simulator/ParticleSimulator"; import { ParticleDataStructShader } from "./shader/ParticleDataStruct"; @@ -136,7 +136,7 @@ export class ParticleSystem extends RenderNode { this.playing = true; } - let renderShader = this.material.getPass(RendererType.COLOR)[0]; + let renderShader = this.material.getPass(PassType.COLOR)[0]; renderShader.setStorageBuffer(`particleGlobalData`, this.particleSimulator.particleGlobalMemory); renderShader.setStorageBuffer(`particleLocalDatas`, this.particleSimulator.particleLocalMemory); this.instanceCount = this.particleSimulator.maxParticle; diff --git a/packages/particle/material/ParticleMaterial.ts b/packages/particle/material/ParticleMaterial.ts index 4931f844..ea52bae8 100644 --- a/packages/particle/material/ParticleMaterial.ts +++ b/packages/particle/material/ParticleMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Texture, GPUCompareFunction, BlendMode, Color, Vector4, RenderShader, Material, RendererType } from "@orillusion/core"; +import { Engine3D, ShaderLib, Texture, GPUCompareFunction, BlendMode, Color, Vector4, RenderShaderPass, Material, PassType, Shader } from "@orillusion/core"; import { ParticleRenderShader } from "../shader/ParticleRenderShader"; /** @@ -10,42 +10,43 @@ export class ParticleMaterial extends Material { super(); ShaderLib.register("ParticleRenderShader", ParticleRenderShader); - let colorPass = new RenderShader(`ParticleRenderShader`, `ParticleRenderShader`); - this.defaultPass = colorPass; + let newShader = new Shader(); + + let colorPass = new RenderShaderPass(`ParticleRenderShader`, `ParticleRenderShader`); + colorPass.passType = PassType.COLOR; colorPass.setShaderEntry(`VertMain`, `FragMain`) + newShader.addRenderPass(colorPass); colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); colorPass.setUniformColor(`baseColor`, new Color()); colorPass.setUniformFloat(`alphaCutoff`, 0.5); - - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = false; - shaderState.receiveEnv = false; - shaderState.acceptGI = false; - shaderState.useLight = false; - shaderState.castShadow = false; - shaderState.depthWriteEnabled = true; + colorPass.renderOrder = 3001; + colorPass.shaderState.transparent = true; + colorPass.shaderState.depthWriteEnabled = false; + colorPass.shaderState.depthCompare = GPUCompareFunction.less; + colorPass.shaderState.acceptShadow = false; + colorPass.shaderState.receiveEnv = false; + colorPass.shaderState.acceptGI = false; + colorPass.shaderState.useLight = false; + colorPass.shaderState.castShadow = false; + + this.shader = newShader; // default value this.baseMap = Engine3D.res.whiteTexture; this.blendMode = BlendMode.ADD; - this.defaultPass.renderOrder = 3001; - this.defaultPass.shaderState.transparent = true; - this.defaultPass.shaderState.depthWriteEnabled = false; - this.defaultPass.shaderState.depthCompare = GPUCompareFunction.less; - } public set baseMap(texture: Texture) { //not need env texture - this.defaultPass.setTexture(`baseMap`, texture); + this.shader.setTexture(`baseMap`, texture); } public get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } - + public set envMap(texture: Texture) { //not need env texture } diff --git a/packages/particle/shader/FastMath.ts b/packages/particle/shader/FastMath.ts index bbcfc4b8..38dd3c11 100644 --- a/packages/particle/shader/FastMath.ts +++ b/packages/particle/shader/FastMath.ts @@ -14,4 +14,44 @@ fn lengthFast( v :vec3 ) -> f32 var LengthSqr = dot(v,v); return sqrtFast( LengthSqr ); } + +fn asinFast( x:f32 )-> f32 +{ + return (0.5 * PI) - acosFast(x); +} + +fn acosFast( inX: f32 ) -> f32 +{ + var x = abs(inX); + var res = -0.156583 * x + (0.5 * PI); + res *= sqrt(1.0 - x); + + if(inX >= 0.0){ + return res ; + }else{ + return PI - res ; + } +} + +fn acosFast4( inX : f32 ) +{ + var x1 = abs(inX); + var x2 = x1 * x1; + var x3 = x2 * x1; + var s; + + s = -0.2121144 * x1 + 1.5707288; + s = 0.0742610 * x2 + s; + s = -0.0187293 * x3 + s; + s = sqrt(1.0 - x1) * s; + + // acos function mirroring + // check per platform if compiles to a selector - no branch neeeded + if(inX >= 0.0){ + return s ; + }else{ + return PI - s ; + } +} + `; diff --git a/packages/particle/shader/ParticleRenderShader.ts b/packages/particle/shader/ParticleRenderShader.ts index 06a167a0..eddfd362 100644 --- a/packages/particle/shader/ParticleRenderShader.ts +++ b/packages/particle/shader/ParticleRenderShader.ts @@ -112,7 +112,7 @@ export let ParticleRenderShader = /* wgsl */ ` let v3Right: vec3 = normalize(cross(vec3( 0.0 , 1.0 , 0.0 ) * mat3, v3Look)); let v3Up: vec3 = cross(v3Look, v3Right); return mat3x3(v3Right, v3Up, v3Look); - } + } fn makeAxleRotationMatrix(axis: vec3, angle: f32) -> mat4x4 { var x = axis.x; diff --git a/public b/public index fcd386df..1e9b664b 160000 --- a/public +++ b/public @@ -1 +1 @@ -Subproject commit fcd386dff4f93f6e4d5de69ac6d0160a06dae799 +Subproject commit 1e9b664bf6b6fc2985cfa5608463b57eed1324e5 diff --git a/samples/animation/Sample_CurveAnimation.ts b/samples/animation/Sample_CurveAnimation.ts index c02ead0e..bd84a543 100644 --- a/samples/animation/Sample_CurveAnimation.ts +++ b/samples/animation/Sample_CurveAnimation.ts @@ -1,5 +1,6 @@ import { Object3D, Scene3D, AnimationCurve, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, Keyframe, Object3DUtil, Time } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { GUIUtil } from "@samples/utils/GUIUtil"; class Sample_AnimCurve { lightObj3D: Object3D; @@ -13,6 +14,7 @@ class Sample_AnimCurve { async run() { await Engine3D.init({ beforeRender: () => this.renderUpdate() }); + Engine3D.setting.render.debug = true; Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; Engine3D.setting.shadow.type = `HARD`; @@ -36,6 +38,8 @@ class Sample_AnimCurve { await this.initScene(); sky.relativeTransform = this.lightObj3D.transform; + + GUIUtil.renderDebug(); } async initScene() { @@ -51,6 +55,8 @@ class Sample_AnimCurve { directLight.intensity = 30; this.scene.addChild(this.lightObj3D); + GUIUtil.renderDirLight(directLight); + //create animation curve 1 this.curve1 = new AnimationCurve(); this.curve1.addKeyFrame(new Keyframe(0, 1)); diff --git a/samples/animation/Sample_MorphTarget.ts b/samples/animation/Sample_MorphTarget.ts index 3f876564..bfab5393 100644 --- a/samples/animation/Sample_MorphTarget.ts +++ b/samples/animation/Sample_MorphTarget.ts @@ -3,7 +3,7 @@ import { Object3D, Scene3D, Engine3D, AtmosphericComponent, webGPUContext, Hover import { GUIUtil } from "@samples/utils/GUIUtil"; // Sample of how to control the morphtarget animation -class Sample_MorphTarget { +export class Sample_MorphTarget { lightObj3D: Object3D; scene: Scene3D; influenceData: { [key: string]: number } = {}; @@ -91,4 +91,4 @@ class Sample_MorphTarget { } -new Sample_MorphTarget().run(); \ No newline at end of file +// new Sample_MorphTarget().run(); \ No newline at end of file diff --git a/samples/animation/Sample_PropertyAnimation.ts b/samples/animation/Sample_PropertyAnimation.ts index 87277b02..9606cc89 100644 --- a/samples/animation/Sample_PropertyAnimation.ts +++ b/samples/animation/Sample_PropertyAnimation.ts @@ -67,6 +67,7 @@ class Sample_PropertyAnimation { } private displayGUI() { + GUIUtil.renderShadowSetting(true); // restart the animation clip GUIHelp.addFolder('Property Animation'); GUIHelp.addButton('Restart', () => { diff --git a/samples/base/Sample_InitEngine.ts b/samples/base/Sample_InitEngine.ts index b30c9382..b06dd80c 100644 --- a/samples/base/Sample_InitEngine.ts +++ b/samples/base/Sample_InitEngine.ts @@ -1,4 +1,4 @@ -import { AtmosphericComponent, BoxGeometry, CameraUtil, DirectLight, Engine3D, GTAOPost, HDRBloomPost, HoverCameraController, KelvinUtil, LambertMaterial, LitMaterial, MeshRenderer, Object3D, OcclusionSystem, PlaneGeometry, PostProcessingComponent, Quaternion, Scene3D, SphereGeometry, UnLitMaterial, Vector3, Vector3Ex, View3D } from '@orillusion/core'; +import { AtmosphericComponent, BloomPost, BoxGeometry, CameraUtil, DirectLight, Engine3D, GTAOPost, HoverCameraController, KelvinUtil, LambertMaterial, LitMaterial, MeshRenderer, Object3D, OcclusionSystem, PlaneGeometry, PostProcessingComponent, Quaternion, Scene3D, SphereGeometry, UnLitMaterial, Vector3, Vector3Ex, View3D } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { Stats } from '@orillusion/stats'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -37,7 +37,7 @@ export class Sample_InitEngine { Engine3D.startRenderView(this.view); let postCom = scene.addComponent(PostProcessingComponent); - let post = postCom.addPost(HDRBloomPost) as HDRBloomPost; + let post = postCom.addPost(BloomPost) as BloomPost; let post2 = postCom.addPost(GTAOPost) as GTAOPost; GUIUtil.renderBloom(post); diff --git a/samples/ext/Sample_Boxes.ts b/samples/ext/Sample_Boxes.ts index 2b628d9d..8907a5c7 100644 --- a/samples/ext/Sample_Boxes.ts +++ b/samples/ext/Sample_Boxes.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, BoxGeometry, UnLitMaterial, PointLight, GTAOPost, HDRBloomPost } from "@orillusion/core"; +import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, BoxGeometry, UnLitMaterial, PointLight, GTAOPost, BloomPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GrassComponent, TerrainGeometry } from "@orillusion/effect"; @@ -32,7 +32,7 @@ class Sample_Boxes { this.post = this.view.scene.addComponent(PostProcessingComponent); this.post.addPost(GTAOPost); - this.post.addPost(HDRBloomPost); + this.post.addPost(BloomPost); let fog = this.post.addPost(GlobalFog); fog.start = 91.0862; fog.end = 487.5528; diff --git a/samples/ext/Sample_Grass.ts b/samples/ext/Sample_Grass.ts index f5a486d5..b85e6d3f 100644 --- a/samples/ext/Sample_Grass.ts +++ b/samples/ext/Sample_Grass.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color } from "@orillusion/core"; +import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GrassComponent, TerrainGeometry } from "@orillusion/effect"; import { Stats } from "@orillusion/stats"; @@ -32,6 +32,7 @@ export class Sample_Grass { Engine3D.startRenderView(this.view); this.post = this.view.scene.addComponent(PostProcessingComponent); + let fxaa = this.post.addPost(FXAAPost); let fog = this.post.addPost(GlobalFog); fog.fogColor = new Color(136 / 255, 215 / 255, 236 / 255, 1); fog.start = 0; @@ -121,53 +122,32 @@ export class Sample_Grass { scene.addChild(grass); } - GUIHelp.addFolder("grass-wind"); - // GUIHelp.add(grassCom.grassMaterial.windBound, "x", -terrainSize * 0.5, terrainSize * 0.5, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.x = v; - // grassCom.grassMaterial.windBound = bound; + // GUIHelp.addFolder("grass-wind"); + // GUIHelp.addColor(grassCom.grassMaterial, "grassBaseColor"); + // GUIHelp.addColor(grassCom.grassMaterial, "grassTopColor"); + // GUIHelp.add(grassCom.grassMaterial.windDirection, "x", -1.0, 1, 0.0001).onChange((v) => { + // let tv = grassCom.grassMaterial.windDirection; + // tv.x = v; + // grassCom.grassMaterial.windDirection = tv; // }); - // GUIHelp.add(grassCom.grassMaterial.windBound, "y", -terrainSize * 0.5, terrainSize * 0.5, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.y = v; - // grassCom.grassMaterial.windBound = bound; + // GUIHelp.add(grassCom.grassMaterial.windDirection, "y", -1.0, 1, 0.0001).onChange((v) => { + // let tv = grassCom.grassMaterial.windDirection; + // tv.y = v; + // grassCom.grassMaterial.windDirection = tv; // }); - // GUIHelp.add(grassCom.grassMaterial.windBound, "z", 0, terrainSize, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.z = v; - // grassCom.grassMaterial.windBound = bound; - // }); - // GUIHelp.add(grassCom.grassMaterial.windBound, "w", 0, terrainSize, 0.0001).onChange((v) => { - // let bound = grassCom.grassMaterial.windBound; - // bound.w = v; - // grassCom.grassMaterial.windBound = bound; - // }); - - GUIHelp.addColor(grassCom.grassMaterial, "grassBaseColor"); - GUIHelp.addColor(grassCom.grassMaterial, "grassTopColor"); - GUIHelp.add(grassCom.grassMaterial.windDirection, "x", -1.0, 1, 0.0001).onChange((v) => { - let tv = grassCom.grassMaterial.windDirection; - tv.x = v; - grassCom.grassMaterial.windDirection = tv; - }); - GUIHelp.add(grassCom.grassMaterial.windDirection, "y", -1.0, 1, 0.0001).onChange((v) => { - let tv = grassCom.grassMaterial.windDirection; - tv.y = v; - grassCom.grassMaterial.windDirection = tv; - }); - GUIHelp.add(grassCom.grassMaterial, "windPower", 0.0, 20, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "windSpeed", 0.0, 20, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "curvature", 0.0, 1, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "grassHeight", 0.0, 100, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "roughness", 0.0, 1, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "translucent", 0.0, 1, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "soft", 0.0, 10, 0.0001); - GUIHelp.add(grassCom.grassMaterial, "specular", 0.0, 10, 0.0001); - GUIHelp.endFolder(); - - GUIHelp.addFolder("shadow"); - GUIHelp.add(Engine3D.setting.shadow, "shadowBound", 0.0, 3000, 0.0001); - GUIHelp.endFolder(); + // GUIHelp.add(grassCom.grassMaterial, "windPower", 0.0, 20, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "windSpeed", 0.0, 20, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "curvature", 0.0, 1, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "grassHeight", 0.0, 100, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "roughness", 0.0, 1, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "translucent", 0.0, 1, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "soft", 0.0, 10, 0.0001); + // GUIHelp.add(grassCom.grassMaterial, "specular", 0.0, 10, 0.0001); + // GUIHelp.endFolder(); + + // GUIHelp.addFolder("shadow"); + // GUIHelp.add(Engine3D.setting.shadow, "shadowBound", 0.0, 3000, 0.0001); + // GUIHelp.endFolder(); let globalFog = this.post.getPost(GlobalFog); // GUIUtil.renderFog(globalFog); diff --git a/samples/ext/Sample_Terrain.ts b/samples/ext/Sample_Terrain.ts index 0e73b4b4..eb21cceb 100644 --- a/samples/ext/Sample_Terrain.ts +++ b/samples/ext/Sample_Terrain.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color } from "@orillusion/core"; +import { Engine3D, View3D, Scene3D, CameraUtil, AtmosphericComponent, webGPUContext, HoverCameraController, Object3D, DirectLight, KelvinUtil, PlaneGeometry, VertexAttributeName, LitMaterial, MeshRenderer, Vector4, Vector3, Matrix3, PostProcessingComponent, TAAPost, BitmapTexture2D, GlobalFog, Color, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GrassComponent, TerrainGeometry } from "@orillusion/effect"; @@ -29,6 +29,7 @@ class Sample_Terrain { Engine3D.startRenderView(this.view); this.post = this.view.scene.addComponent(PostProcessingComponent); + let fxaa = this.post.addPost(FXAAPost); let fog = this.post.addPost(GlobalFog); fog.start = 2000; fog.end = 0; diff --git a/samples/geometry/Sample_ConduitGeometry2.ts b/samples/geometry/Sample_ConduitGeometry2.ts index ca4d07f2..9bed6d7f 100644 --- a/samples/geometry/Sample_ConduitGeometry2.ts +++ b/samples/geometry/Sample_ConduitGeometry2.ts @@ -1,4 +1,4 @@ -import { AttributeAnimCurve, BitmapTexture2D, BlendMode, Color, Engine3D, ExtrudeGeometry, LitMaterial, MeshRenderer, Object3D, Object3DUtil, PropertyAnimClip, PropertyAnimation, Scene3D, Vector3, WrapMode } from "@orillusion/core"; +import { AttributeAnimCurve, BitmapTexture2D, BlendMode, BloomPost, Color, Engine3D, ExtrudeGeometry, LitMaterial, MeshRenderer, Object3D, Object3DUtil, PropertyAnimClip, PropertyAnimation, Scene3D, Vector3, WrapMode } from "@orillusion/core"; import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; import { UVMoveComponent } from "@samples/material/script/UVMoveComponent"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; @@ -25,7 +25,8 @@ class Sample_ConduitGeometry2 { let exampleScene = createExampleScene(param); exampleScene.camera.enableCSM = true; this.scene = exampleScene.scene; - Engine3D.startRenderView(exampleScene.view); + let job = Engine3D.startRenderView(exampleScene.view); + job.addPost(new BloomPost()); await this.createMaterial(); await this.loadCurveData(); @@ -53,6 +54,7 @@ class Sample_ConduitGeometry2 { animation.speed = 0.5; animation.appendClip(this.animClip); } + async loadCurveData() { // load external curve data let json: any = await Engine3D.res.loadJSON('json/anim_0.json'); @@ -76,6 +78,7 @@ class Sample_ConduitGeometry2 { let texture = new BitmapTexture2D(); texture.addressModeU = "repeat"; texture.addressModeV = "repeat"; + // await texture.load('textures/grid.jpg'); await texture.load('textures/cell.png'); this.material.baseMap = texture; } diff --git a/samples/gi/Sample_GI.ts b/samples/gi/Sample_GI.ts index 96730343..c5959152 100644 --- a/samples/gi/Sample_GI.ts +++ b/samples/gi/Sample_GI.ts @@ -1,5 +1,5 @@ import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, HDRBloomPost, PostProcessingComponent, TAAPost } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, PostProcessingComponent, TAAPost, BloomPost, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; @@ -12,6 +12,7 @@ class Sample_GI { Engine3D.setting.gi.enable = true; Engine3D.setting.gi.debug = true; + Engine3D.setting.render.debug = true; Engine3D.setting.gi.probeYCount = 3; Engine3D.setting.gi.probeXCount = 6; @@ -33,16 +34,6 @@ class Sample_GI { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - debug: false, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.9, - radius: 4, - strength: 1.2 - }; - await Engine3D.init({ renderLoop: () => { if (this.giComponent?.isStart) { @@ -60,16 +51,20 @@ class Sample_GI { exampleScene.camera.enableCSM = true; Engine3D.startRenderViews([exampleScene.view]); let job = Engine3D.getRenderJob(exampleScene.view); + + let postProcessing = this.scene.addComponent(PostProcessingComponent); + // postProcessing.addPost(FXAAPost); + // postProcessing.addPost(TAAPost); + // postProcessing.addPost(GTAOPost); + postProcessing.addPost(BloomPost); await this.initScene(); this.addGIProbes(); // GUIUtil.renderAtomosphericSky(exampleScene.atmosphericSky); - GUIUtil.renderDirLight(exampleScene.light); + GUIUtil.renderDirLight(exampleScene.light, false); - let postProcessing = this.scene.addComponent(PostProcessingComponent); - postProcessing.addPost(TAAPost); - postProcessing.addPost(GTAOPost); - postProcessing.addPost(HDRBloomPost); + GUIUtil.renderDebug(); + GUIUtil.renderAtmosphericSky(exampleScene.atmosphericSky); } private giComponent: GlobalIlluminationComponent; @@ -83,7 +78,7 @@ class Sample_GI { async initScene() { { let floorHeight = 20; - let floor = Object3DUtil.GetSingleCube(1000, floorHeight, 1000, 0.6, 0.6, 0.6); + let floor = Object3DUtil.GetSingleCube(1000, floorHeight, 1000, 0.5, 0.5, 0.5); floor.y = -floorHeight; this.scene.addChild(floor); } diff --git a/samples/gi/Sample_GICornellBox.ts b/samples/gi/Sample_GICornellBox.ts index 6286e26b..d2fbd84a 100644 --- a/samples/gi/Sample_GICornellBox.ts +++ b/samples/gi/Sample_GICornellBox.ts @@ -1,5 +1,5 @@ import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Vector3, GTAOPost, PostProcessingComponent, HDRBloomPost } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Vector3, GTAOPost, PostProcessingComponent, BloomPost } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { GUIUtil } from "@samples/utils/GUIUtil"; @@ -36,15 +36,6 @@ class Sample_GICornellBox { Engine3D.setting.shadow.updateFrameRate = 1; Engine3D.setting.render.debug = true; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - debug: false, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.9, - radius: 4, - strength: 1.2 - }; await Engine3D.init({ renderLoop: () => { @@ -66,7 +57,7 @@ class Sample_GICornellBox { let postProcessing = this.scene.addComponent(PostProcessingComponent); postProcessing.addPost(GTAOPost); - postProcessing.addPost(HDRBloomPost); + postProcessing.addPost(BloomPost); Engine3D.setting.shadow.csmScatteringExp = 0.8; GUIHelp.add(Engine3D.setting.shadow, 'csmScatteringExp', 0.5, 1, 0.001); diff --git a/samples/graphic/Sample_GraphicLine.ts b/samples/graphic/Sample_GraphicLine.ts index 7907b96d..436abe52 100644 --- a/samples/graphic/Sample_GraphicLine.ts +++ b/samples/graphic/Sample_GraphicLine.ts @@ -1,5 +1,5 @@ import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, HDRBloomPost, PostProcessingComponent, TAAPost, Vector3, Color, AnimationCurve, Keyframe } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, GlobalIlluminationComponent, Object3DUtil, GTAOPost, PostProcessingComponent, TAAPost, Vector3, Color, AnimationCurve, Keyframe } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; @@ -11,16 +11,6 @@ class Sample_GraphicLine { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.material.materialDebug = false; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - debug: false, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.9, - radius: 4, - strength: 1.2 - }; - await Engine3D.init({}); GUIHelp.init(); let param = createSceneParam(); diff --git a/samples/index.ts b/samples/index.ts index d05c6510..7558858f 100644 --- a/samples/index.ts +++ b/samples/index.ts @@ -68,19 +68,3 @@ document.body.appendChild(iframe) } } - -// new Sample_PointLight().run(); -// new Sample_LoadGLB4().run(); - -// import { Sample_Grass } from "./ext/Sample_Grass"; -// console.log("a"); -// new Sample_Grass().run(); - -// new Sample_drawCallShareGeometry().run(); - -// import { Sample_InitEngine } from "./base/Sample_InitEngine"; -// import { Sample_PointLight } from "./lights/Sample_PointLight"; -// new Sample_InitEngine().run(); -// // new Sample_PointLight().run(); - - diff --git a/samples/lights/Sample_PointLightShadow.ts b/samples/lights/Sample_PointLightShadow.ts index 3baabe03..d4f3dd0c 100644 --- a/samples/lights/Sample_PointLightShadow.ts +++ b/samples/lights/Sample_PointLightShadow.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, Vector3, View3D, SphereGeometry, Object3D, MeshRenderer, LitMaterial, PointLight, BoxGeometry, Object3DUtil } from "@orillusion/core"; +import { Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, Vector3, View3D, SphereGeometry, Object3D, MeshRenderer, LitMaterial, PointLight, BoxGeometry, Object3DUtil, PostProcessingComponent, FXAAPost } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; // sample of point light shadow @@ -10,6 +10,7 @@ class Sample_PointLightShadow { Engine3D.setting.shadow.enable = true; Engine3D.setting.shadow.debug = true; + Engine3D.setting.render.debug = true; Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.material.materialDebug = true; @@ -32,6 +33,13 @@ class Sample_PointLightShadow { view.camera = mainCamera; Engine3D.startRenderView(view); + + let post = this.scene.addComponent(PostProcessingComponent); + post.addPost(FXAAPost); + + setTimeout(() => { + GUIUtil.renderDebug(); + }, 1000); } async initScene(scene: Scene3D) { diff --git a/samples/lights/Sample_ShadowAlpha.ts b/samples/lights/Sample_ShadowAlpha.ts deleted file mode 100644 index e1f364e5..00000000 --- a/samples/lights/Sample_ShadowAlpha.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Scene3D, HoverCameraController, Engine3D, AtmosphericComponent, Object3D, Camera3D, Vector3, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, CameraUtil, SphereGeometry, Color, Object3DUtil, BlendMode, Vector4 } from "@orillusion/core"; -import { GUIUtil } from "@samples/utils/GUIUtil"; - -//sample of direction light -class Sample_ShadowAlpha { - scene: Scene3D; - async run() { - Engine3D.setting.shadow.enable = true; - // Engine3D.setting.render.zPrePass = true; - Engine3D.setting.shadow.autoUpdate = true; - Engine3D.setting.shadow.shadowSize = 1024; - Engine3D.setting.render.debug = true; - Engine3D.setting.render.useLogDepth = false; - Engine3D.setting.occlusionQuery.octree = { width: 1000, height: 1000, depth: 1000, x: 0, y: 0, z: 0 } - await Engine3D.init({}); - - GUIHelp.init(); - - this.scene = new Scene3D(); - let sky = this.scene.addComponent(AtmosphericComponent); - - // init camera3D - let mainCamera = CameraUtil.createCamera3D(null, this.scene); - // mainCamera.enableCSM = true; - mainCamera.perspective(60, Engine3D.aspect, 1, 5000.0); - //set camera data - mainCamera.object3D.z = -15; - mainCamera.object3D.addComponent(HoverCameraController).setCamera(-15, -35, 200); - - sky.relativeTransform = this.initLight(); - await this.initScene(); - - let view = new View3D(); - view.scene = this.scene; - view.camera = mainCamera; - - Engine3D.startRenderView(view); - GUIUtil.renderDebug(); - } - - // create direction light - private initLight() { - // add a direction light - let lightObj3D = new Object3D(); - lightObj3D.rotationX = 46; - lightObj3D.rotationY = 62; - lightObj3D.rotationZ = 0; - let sunLight = lightObj3D.addComponent(DirectLight); - sunLight.intensity = 15; - sunLight.lightColor = KelvinUtil.color_temperature_to_rgb(6553); - sunLight.castShadow = true; - - GUIUtil.renderDirLight(sunLight); - this.scene.addChild(lightObj3D); - return sunLight.transform; - } - - async initScene() { - let tex = await Engine3D.res.loadTexture("textures/grid.jpg"); - - { - let geometry = new SphereGeometry(20, 100, 20); - let material = new LitMaterial(); - let obj = new Object3D(); - let mr = obj.addComponent(MeshRenderer); - mr.geometry = geometry; - mr.material = material; - this.scene.addChild(obj); - } - { - let mat = new LitMaterial(); - // mat.baseMap = Engine3D.res.grayTexture; - mat.uvTransform_1 = new Vector4(0, 0, 100, 100); - let floor = new Object3D(); - let mr = floor.addComponent(MeshRenderer); - mr.geometry = new BoxGeometry(10000, 1, 10000); - mr.material = mat; - mat.baseMap = tex; - this.scene.addChild(floor); - } - } -} - -new Sample_ShadowAlpha().run(); diff --git a/samples/loader/Sample_FlightHelmet.ts b/samples/loader/Sample_FlightHelmet.ts index f2a67da9..10473a05 100644 --- a/samples/loader/Sample_FlightHelmet.ts +++ b/samples/loader/Sample_FlightHelmet.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Object3D, Scene3D, HoverCameraController, Engine3D, CameraUtil, View3D, SSRPost, HDRBloomPost, AtmosphericComponent, DirectLight, KelvinUtil, Time } from "@orillusion/core"; +import { Object3D, Scene3D, HoverCameraController, Engine3D, CameraUtil, View3D, SSRPost, AtmosphericComponent, DirectLight, KelvinUtil, Time } from "@orillusion/core"; import { GUIUtil as GUIUtil } from "@samples/utils/GUIUtil"; class Sample_FlightHelmet { @@ -22,16 +22,6 @@ class Sample_FlightHelmet { Engine3D.setting.shadow.shadowBound = 10; Engine3D.setting.render.postProcessing.ssao.radius = 0.018; Engine3D.setting.render.postProcessing.ssao.aoPower = 1; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - strength: 1.5, - luminosityThreshold: 0.1, - radius: 4, - debug: false - }; - this.scene = new Scene3D(); let camera = CameraUtil.createCamera3DObject(this.scene); diff --git a/samples/loader/Sample_LoadGLB.ts b/samples/loader/Sample_LoadGLB.ts index 780a0f83..2ef82b3b 100644 --- a/samples/loader/Sample_LoadGLB.ts +++ b/samples/loader/Sample_LoadGLB.ts @@ -1,4 +1,4 @@ -import { AtmosphericComponent, Engine3D, GTAOPost, HDRBloomPost, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, SkyRenderer, TAAPost } from "@orillusion/core"; +import { AtmosphericComponent, BloomPost, Engine3D, GTAOPost, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, SkyRenderer, TAAPost } from "@orillusion/core"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene } from "@samples/utils/ExampleScene"; import { GUIUtil } from "@samples/utils/GUIUtil"; @@ -27,7 +27,7 @@ export class Sample_LoadGLB { let post = this.scene.addComponent(PostProcessingComponent); let gtao = post.addPost(GTAOPost); // let taa = post.addPost(TAAPost); - let hdr = post.addPost(HDRBloomPost); + let hdr = post.addPost(BloomPost); GUIUtil.renderBloom(hdr); GUIUtil.renderDirLight(ex.light); diff --git a/samples/loader/Sample_LoadGLB2.ts b/samples/loader/Sample_LoadGLB2.ts index 8a951fe0..f6701594 100644 --- a/samples/loader/Sample_LoadGLB2.ts +++ b/samples/loader/Sample_LoadGLB2.ts @@ -9,8 +9,10 @@ export class Sample_LoadGLB2 { scene: Scene3D; async run() { - await Engine3D.init(); + Engine3D.setting.render.debug = true; Engine3D.setting.shadow.autoUpdate = true; + + await Engine3D.init(); let exampleScene = createExampleScene(); exampleScene.atmosphericSky.displaySun = false; exampleScene.atmosphericSky.sunRadiance = 1; @@ -22,7 +24,8 @@ export class Sample_LoadGLB2 { await this.initScene(); GUIHelp.init(); - GUIUtil.renderAtomosphericSky(exampleScene.atmosphericSky); + GUIUtil.renderAtmosphericSky(exampleScene.atmosphericSky); + GUIUtil.renderDebug(); } async initScene() { diff --git a/samples/loader/Sample_LoadGLTF.ts b/samples/loader/Sample_LoadGLTF.ts index 10364f32..a8b96b4b 100644 --- a/samples/loader/Sample_LoadGLTF.ts +++ b/samples/loader/Sample_LoadGLTF.ts @@ -9,16 +9,9 @@ class Sample_LoadGLTF { async run() { //config settings Engine3D.setting.material.materialChannelDebug = true; - Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; + Engine3D.setting.shadow.shadowBound = 100; + Engine3D.setting.shadow.shadowSize = 2048; + //init engine await Engine3D.init(); diff --git a/samples/material/Sample_ChangeMaterial.ts b/samples/material/Sample_ChangeMaterial.ts index 7bcae940..020acd3f 100644 --- a/samples/material/Sample_ChangeMaterial.ts +++ b/samples/material/Sample_ChangeMaterial.ts @@ -12,17 +12,6 @@ class Sample_ChangeMaterial { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - exposure: 1, - strength: 0.86, - radius: 4, - debug: false - }; - this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); @@ -107,6 +96,8 @@ class Sample_ChangeMaterial { GUIHelp.addButton("change-mat3", () => { mr.material = mat3; }); + + GUIHelp.open(); } } diff --git a/samples/material/Sample_ClearCoat.ts b/samples/material/Sample_ClearCoat.ts index 3d9ec9fc..dedc92c5 100644 --- a/samples/material/Sample_ClearCoat.ts +++ b/samples/material/Sample_ClearCoat.ts @@ -16,17 +16,6 @@ class Sample_ClearCoat { //config settings Engine3D.setting.shadow.shadowBound = 300; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - exposure: 1, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; - this.scene = new Scene3D(); let camera = CameraUtil.createCamera3DObject(this.scene); diff --git a/samples/material/Sample_GraphicMeshWave.ts b/samples/material/Sample_GraphicMeshWave.ts new file mode 100644 index 00000000..d0bc573f --- /dev/null +++ b/samples/material/Sample_GraphicMeshWave.ts @@ -0,0 +1,146 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, PrefabParser } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMeshWave { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 100; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + // mr.setTextureID(i, 35); + mr.setTextureID(i, 0); + // mr.setTextureID(i, 18); + + let size = 1.0; + element.transform.scaleX = size; + element.transform.scaleY = size; + element.transform.scaleZ = size; + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + this.wave(i, pos); + + element.transform.localPosition = pos; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_0.ts b/samples/material/Sample_GraphicMesh_0.ts new file mode 100644 index 00000000..c836e4d8 --- /dev/null +++ b/samples/material/Sample_GraphicMesh_0.ts @@ -0,0 +1,201 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_0 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0026.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0001.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0009.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0017.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0022.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0025.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0012.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0016.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0018.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0023.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0027.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0028.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0035.png") as BitmapTexture2D); + + // texts.push(Engine3D.res.grayTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + { + this.width = 200; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 35); + + + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + tmp.scaleBy(Math.sin((i + Time.frame * 0.01)) * 50); + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_1.ts b/samples/material/Sample_GraphicMesh_1.ts new file mode 100644 index 00000000..81a70d9f --- /dev/null +++ b/samples/material/Sample_GraphicMesh_1.ts @@ -0,0 +1,200 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_1 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0026.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0001.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0009.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0017.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0022.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0025.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0012.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0016.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0018.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0023.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0027.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0028.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0035.png") as BitmapTexture2D); + + // texts.push(Engine3D.res.grayTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 200; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 35); + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + tmp.scaleBy(Math.sin((i + Time.frame * 0.01 * this.frame * 0.01)) * this.cafe); + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_2.ts b/samples/material/Sample_GraphicMesh_2.ts new file mode 100644 index 00000000..a6c7945e --- /dev/null +++ b/samples/material/Sample_GraphicMesh_2.ts @@ -0,0 +1,207 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_2 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0026.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0001.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0009.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0017.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0022.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0025.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0012.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0016.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0018.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0023.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0027.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0028.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0035.png") as BitmapTexture2D); + + // texts.push(Engine3D.res.grayTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 200; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 35); + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + let r = Math.sin((i + Time.frame * 0.01 * this.frame * 0.01)) * this.cafe; + tmp.scaleBy(r); + + let tr = 1.0 - (r / this.cafe); + + element.transform.scaleX = tr; + element.transform.scaleY = tr; + element.transform.scaleZ = tr; + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_3.ts b/samples/material/Sample_GraphicMesh_3.ts new file mode 100644 index 00000000..4890c6b7 --- /dev/null +++ b/samples/material/Sample_GraphicMesh_3.ts @@ -0,0 +1,158 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, PrefabParser } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_3 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + PrefabParser.useWebp = false; + let node = await Engine3D.res.loadGltf("gltfs/glb/beer.glb") as Object3D; + let geo = node.getComponents(MeshRenderer)[0].geometry; + + // texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(Engine3D.res.yellowTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 100; + this.height = 20; + // let geometry = new BoxGeometry(1, 1, 1); + // let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geo, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + // mr.material.blendMode = BlendMode.ADD; + // mr.material.transparent = true; + // mr.material.depthWriteEnabled = false; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + // mr.setTextureID(i, 35); + mr.setTextureID(i, 0); + // mr.setTextureID(i, 18); + + let size = Math.random() * 5.0 + 1.0; + element.transform.scaleX = size; + element.transform.scaleY = size; + element.transform.scaleZ = size; + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + let r = this.cafe; + tmp.scaleBy(r); + + let tr = Math.sin(i * (Time.frame * 0.0001) * this.frame * 0.01) + 1.0; + tr *= 0.1; + element.transform.scaleX = tr; + element.transform.scaleY = tr; + element.transform.scaleZ = tr; + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_GraphicMesh_4.ts b/samples/material/Sample_GraphicMesh_4.ts new file mode 100644 index 00000000..ae7424d1 --- /dev/null +++ b/samples/material/Sample_GraphicMesh_4.ts @@ -0,0 +1,147 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, PrefabParser } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_4 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + let view = new View3D(); + view.scene = this.scene; + view.camera = camera; + + Engine3D.startRenderView(view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + // texts.push(Engine3D.res.yellowTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 80; + this.height = 80; + // let geometry = new BoxGeometry(1, 1, 1); + let geo = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geo, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.useBillboard = true; + mr.material.blendMode = BlendMode.ADD; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + mr.setTextureID(i, 0); + + let size = Math.random() * 5.0 + 1.0; + element.transform.scaleX = size; + element.transform.scaleY = size; + element.transform.scaleZ = size; + } + } + } + + update() { + if (this.parts) { + let pos = new Vector3(); + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + let r = this.cafe; + + // let tr = Math.sin((i * (Time.frame % 3600 * 0.0001 / 5) * this.frame * 0.01)) + 1.0; + let tr = Math.sin((tmp.x * (Time.frame * 0.001)) % 1000) * 3 + 1.0; + element.transform.scaleX = tr; + element.transform.scaleY = tr; + element.transform.scaleZ = tr; + tmp.scaleBy(r + tr * 2); + + element.transform.localPosition = tmp; + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/material/Sample_PBR.ts b/samples/material/Sample_PBR.ts index 0901950d..4259ffbc 100644 --- a/samples/material/Sample_PBR.ts +++ b/samples/material/Sample_PBR.ts @@ -11,6 +11,7 @@ class Sample_PBR { async run() { await Engine3D.init({}); + Engine3D.setting.render.debug = true; Engine3D.setting.shadow.shadowBound = 5; GUIHelp.init(); @@ -28,6 +29,8 @@ class Sample_PBR { Engine3D.startRenderView(view); + GUIUtil.renderDebug(); + await this.initScene(); sky.relativeTransform = this.lightObj3D.transform; } diff --git a/samples/material/Sample_PBRMaterial.ts b/samples/material/Sample_PBRMaterial.ts index 8a4c6b18..40eeba35 100644 --- a/samples/material/Sample_PBRMaterial.ts +++ b/samples/material/Sample_PBRMaterial.ts @@ -11,16 +11,6 @@ class Sample_PBRMaterial { //config settings Engine3D.setting.render.debug = true; Engine3D.setting.shadow.shadowBound = 50; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - strength: 0.86, - exposure: 1, - radius: 4, - debug: false - }; await Engine3D.init({ canvasConfig: { alpha: true, zIndex: 11, backgroundImage: '/logo/bg.webp' } }); @@ -73,7 +63,7 @@ class Sample_PBRMaterial { if (material instanceof LitMaterial) { material.metallic = 1; material.roughness = 0.35; - material.defaultPass.setDefine("USE_TANGENT", false); + material.setDefine("USE_TANGENT", false); } } model.transform.scaleX = 10; diff --git a/samples/material/Sample_UVMove.ts b/samples/material/Sample_UVMove.ts index 05308fd2..77b36736 100644 --- a/samples/material/Sample_UVMove.ts +++ b/samples/material/Sample_UVMove.ts @@ -12,16 +12,6 @@ class Sample_UVMove { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - exposure: 1, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); diff --git a/samples/material/script/UVMoveComponent.ts b/samples/material/script/UVMoveComponent.ts index ce8ab2ac..f083e222 100644 --- a/samples/material/script/UVMoveComponent.ts +++ b/samples/material/script/UVMoveComponent.ts @@ -22,12 +22,12 @@ export class UVMoveComponent extends ComponentBase { onUpdate(): void { if (this._material) { - let value = this._material.defaultPass.getUniform(`transformUV1`); + let value = this._material.getUniformV4(`transformUV1`); value.x += Time.delta * this._speed.x * 0.001; value.y += Time.delta * this._speed.y * 0.001; value.z = this._speed.z; value.w = this._speed.w; - this._material.defaultPass.setUniform(`transformUV1`, value); + this._material.setUniformVector4(`transformUV1`, value); } } } \ No newline at end of file diff --git a/samples/pick/Sample_OutlineEffectPick.ts b/samples/pick/Sample_OutlineEffectPick.ts index 400e4148..4264e65c 100644 --- a/samples/pick/Sample_OutlineEffectPick.ts +++ b/samples/pick/Sample_OutlineEffectPick.ts @@ -1,7 +1,7 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { createExampleScene } from "@samples/utils/ExampleScene"; -import { Object3D, Scene3D, Color, Engine3D, OutlinePost, SphereGeometry, LitMaterial, MeshRenderer, ColliderComponent, PointerEvent3D, outlinePostManager } from "@orillusion/core"; +import { Object3D, Scene3D, Color, Engine3D, OutlinePost, SphereGeometry, LitMaterial, MeshRenderer, ColliderComponent, PointerEvent3D, outlinePostManager, FXAAPost } from "@orillusion/core"; class Sample_OutlineEffectPick { lightObj: Object3D; @@ -32,6 +32,7 @@ class Sample_OutlineEffectPick { GUIUtil.renderDirLight(exampleScene.light, false); let job = Engine3D.startRenderView(exampleScene.view); + // job.addPost(new FXAAPost()); job.addPost(new OutlinePost()); this.initPickObject(this.scene); diff --git a/samples/pick/Sample_PixelPick.ts b/samples/pick/Sample_PixelPick.ts index 910d74b0..5c23a384 100644 --- a/samples/pick/Sample_PixelPick.ts +++ b/samples/pick/Sample_PixelPick.ts @@ -2,7 +2,7 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { MaterialStateComponent } from "@samples/pick/MaterialStateComponent"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { createExampleScene } from "@samples/utils/ExampleScene"; -import { Scene3D, Engine3D, MeshRenderer, ColliderComponent, PointerEvent3D, SphereGeometry, Object3D, LitMaterial, Color } from "@orillusion/core"; +import { Scene3D, Engine3D, MeshRenderer, ColliderComponent, PointerEvent3D, SphereGeometry, Object3D, LitMaterial, Color, FXAAPost, PostProcessingComponent, BloomPost } from "@orillusion/core"; class Sample_PixelPick { scene: Scene3D; @@ -18,6 +18,9 @@ class Sample_PixelPick { Engine3D.startRenderView(exampleScene.view); + let postProcessing = this.scene.getOrAddComponent(PostProcessingComponent); + let bloomPost = postProcessing.addPost(BloomPost); + GUIHelp.init(); GUIUtil.renderDirLight(exampleScene.light, false); @@ -65,8 +68,8 @@ class Sample_PixelPick { let mat = new LitMaterial(); mat.roughness = i / 10; - mat.metallic_max = 1.0; - mat.metallic_min = 0.0; + // mat.metallic_max = 1.0; + // mat.metallic_min = 0.0; mat.metallic = 0.6; let renderer = obj.addComponent(MeshRenderer); diff --git a/samples/post/Sample_Bloom.ts b/samples/post/Sample_Bloom.ts index ef231f7e..e52ca91f 100644 --- a/samples/post/Sample_Bloom.ts +++ b/samples/post/Sample_Bloom.ts @@ -2,7 +2,7 @@ import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, - CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, HDRBloomPost + CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, BloomPost } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUI } from '@orillusion/debug/dat.gui.module'; @@ -36,12 +36,7 @@ class Sample_Bloom { Engine3D.startRenderView(view); let postProcessing = this.scene.addComponent(PostProcessingComponent); - let post = postProcessing.addPost(HDRBloomPost); - post.blurX = 5; - post.blurY = 5; - post.luminosityThreshold = 1.1; - post.strength = 1.0; - + let post = postProcessing.addPost(BloomPost); GUIHelp.init(); GUIUtil.renderBloom(post, true); } @@ -61,13 +56,8 @@ class Sample_Bloom { { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.grayTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; - mat.roughness = 1.5; - mat.metallic = 0.0; + mat.roughness = 1.0; + mat.metallic = 0.1; let floor = new Object3D(); let mr = floor.addComponent(MeshRenderer); @@ -105,9 +95,8 @@ class Sample_Bloom { { { let litMat = new LitMaterial(); - litMat.emissiveMap = Engine3D.res.whiteTexture; litMat.emissiveColor = new Color(0.0, 0.0, 1.0); - litMat.emissiveIntensity = 5.0; + litMat.emissiveIntensity = 1.8; let sp = new Object3D(); let mr = sp.addComponent(MeshRenderer); mr.geometry = new SphereGeometry(15, 30, 30); @@ -120,9 +109,8 @@ class Sample_Bloom { { let litMat = new LitMaterial(); - litMat.emissiveMap = Engine3D.res.whiteTexture; litMat.emissiveColor = new Color(1.0, 1.0, 0.0); - litMat.emissiveIntensity = 5; + litMat.emissiveIntensity = 1.2; let sp = new Object3D(); let mr = sp.addComponent(MeshRenderer); mr.geometry = new SphereGeometry(15, 30, 30); diff --git a/samples/post/Sample_Fog.ts b/samples/post/Sample_Fog.ts index 3285c043..144bc509 100644 --- a/samples/post/Sample_Fog.ts +++ b/samples/post/Sample_Fog.ts @@ -1,4 +1,4 @@ -import { AtmosphericComponent, BoxGeometry, CameraUtil, CylinderGeometry, DirectLight, Engine3D, GlobalFog, HoverCameraController, KelvinUtil, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, View3D, webGPUContext } from '@orillusion/core'; +import { AtmosphericComponent, BoxGeometry, CameraUtil, CylinderGeometry, DirectLight, Engine3D, FXAAPost, GlobalFog, HoverCameraController, KelvinUtil, LitMaterial, MeshRenderer, Object3D, PlaneGeometry, PostProcessingComponent, Scene3D, View3D, webGPUContext } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -28,8 +28,9 @@ class Sample_Fog { Engine3D.startRenderView(view); GUIHelp.init(); - GUIUtil.renderAtomosphericSky(sky, false); + GUIUtil.renderAtmosphericSky(sky, false); let postProcessing = this.scene.addComponent(PostProcessingComponent); + let fXAAPost = postProcessing.addPost(FXAAPost); let fog = postProcessing.addPost(GlobalFog); GUIUtil.renderGlobalFog(fog, true); } @@ -49,7 +50,6 @@ class Sample_Fog { { let mat = new LitMaterial(); - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); mat.roughness = 0.5; mat.metallic = 0.5; @@ -65,7 +65,6 @@ class Sample_Fog { private createPlane(scene: Scene3D) { let mat = new LitMaterial(); - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); mat.roughness = 1.0; mat.metallic = 0.0; diff --git a/samples/post/Sample_GTAO.ts b/samples/post/Sample_GTAO.ts index bc16409f..1402dbc8 100644 --- a/samples/post/Sample_GTAO.ts +++ b/samples/post/Sample_GTAO.ts @@ -2,7 +2,7 @@ import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, - CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color, HDRBloomPost + CameraUtil, webGPUContext, BoxGeometry, TAAPost, AtmosphericComponent, GTAOPost, Color } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -59,11 +59,6 @@ class Sample_GTAO { async initScene() { { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.whiteTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 1.0; mat.metallic = 0.0; @@ -107,8 +102,6 @@ class Sample_GTAO { mat.baseColor = new Color(1.0, 0.464, 0.0); mat.normalMap = Engine3D.res.normalTexture; mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 1.0; mat.metallic = 0.0; diff --git a/samples/post/Sample_GodRay.ts b/samples/post/Sample_GodRay.ts index ad6e5b2c..fc920bec 100644 --- a/samples/post/Sample_GodRay.ts +++ b/samples/post/Sample_GodRay.ts @@ -2,8 +2,7 @@ import { View3D, DirectLight, Engine3D, PostProcessingComponent, LitMaterial, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, PlaneGeometry, Scene3D, SphereGeometry, - CameraUtil, webGPUContext, BoxGeometry, AtmosphericComponent, Time, - HDRBloomPost, GodRayPost + CameraUtil, webGPUContext, BoxGeometry, AtmosphericComponent, Time, GodRayPost, BloomPost } from '@orillusion/core'; import { GUIHelp } from '@orillusion/debug/GUIHelp'; import { GUIUtil } from '@samples/utils/GUIUtil'; @@ -38,9 +37,9 @@ class Sample_GodRay { let postProcessing = this.scene.addComponent(PostProcessingComponent); postProcessing.addPost(GodRayPost); - postProcessing.addPost(HDRBloomPost); + postProcessing.addPost(BloomPost); - GUIUtil.renderAtomosphericSky(sky, false); + GUIUtil.renderAtmosphericSky(sky, false); } async initScene() { { @@ -72,13 +71,7 @@ class Sample_GodRay { private ball: Object3D; private createPlane(scene: Scene3D) { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.whiteTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 10.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 0.5; - mat.roughness_max = 0.1; mat.metallic = 0.2; { let sphereGeometry = new SphereGeometry(20, 50, 50); diff --git a/samples/post/Sample_TAA.ts b/samples/post/Sample_TAA.ts index 66df356b..08a4abb1 100644 --- a/samples/post/Sample_TAA.ts +++ b/samples/post/Sample_TAA.ts @@ -53,11 +53,6 @@ class Sample_TAA { { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.grayTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 255.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 1.0; mat.metallic = 0.0; @@ -74,13 +69,7 @@ class Sample_TAA { private createPlane(scene: Scene3D) { let mat = new LitMaterial(); - mat.baseMap = Engine3D.res.whiteTexture; - mat.normalMap = Engine3D.res.normalTexture; - mat.aoMap = Engine3D.res.whiteTexture; - mat.maskMap = Engine3D.res.createTexture(32, 32, 255.0, 10.0, 0.0, 1); - mat.emissiveMap = Engine3D.res.blackTexture; mat.roughness = 0.5; - mat.roughness_max = 0.1; mat.metallic = 0.2; { let sphereGeometry = new SphereGeometry(1, 50, 50); diff --git a/samples/render/Sample_BlendMode.ts b/samples/render/Sample_BlendMode.ts index 5f273e88..8840313e 100644 --- a/samples/render/Sample_BlendMode.ts +++ b/samples/render/Sample_BlendMode.ts @@ -9,15 +9,6 @@ class Sample_BlendMode2 { Engine3D.setting.material.materialChannelDebug = true; Engine3D.setting.shadow.shadowBound = 5; - Engine3D.setting.render.postProcessing.bloom = { - enable: true, - blurX: 4, - blurY: 4, - luminosityThreshold: 0.8, - strength: 0.86, - radius: 4, - debug: false - }; this.scene = new Scene3D(); let sky = this.scene.addComponent(AtmosphericComponent); diff --git a/samples/sky/Sample_AtmosphericSky.ts b/samples/sky/Sample_AtmosphericSky.ts index 927abefb..883845a4 100644 --- a/samples/sky/Sample_AtmosphericSky.ts +++ b/samples/sky/Sample_AtmosphericSky.ts @@ -28,7 +28,7 @@ class Sample_AtmosphericSky { // gui GUIHelp.init(); - GUIUtil.renderAtomosphericSky(sky); + GUIUtil.renderAtmosphericSky(sky); } } diff --git a/samples/utils/GUIUtil.ts b/samples/utils/GUIUtil.ts index ca4b4060..64afaa3d 100644 --- a/samples/utils/GUIUtil.ts +++ b/samples/utils/GUIUtil.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { AtmosphericComponent, BillboardType, BlendMode, Color, DirectLight, Engine3D, GPUCullMode, GlobalFog, GlobalIlluminationComponent, HDRBloomPost, LitMaterial, Material, PointLight, SpotLight, Transform, UIImage, UIPanel, UIShadow, View3D } from "@orillusion/core"; +import { AnimatorComponent, AtmosphericComponent, BillboardType, BlendMode, BloomPost, Color, DirectLight, Engine3D, GPUCullMode, GTAOPost, GlobalFog, GlobalIlluminationComponent, LitMaterial, Material, MorphTargetBlender, Object3D, PointLight, SkinnedMeshRenderer2, SpotLight, Transform, UIImage, UIPanel, UIShadow, View3D } from "@orillusion/core"; import { UVMoveComponent } from "@samples/material/script/UVMoveComponent"; export class GUIUtil { @@ -8,13 +8,15 @@ export class GUIUtil { public static renderShadowSetting(open: boolean = true) { GUIHelp.addFolder('ShadowSetting'); let setting = Engine3D.setting.shadow; + GUIHelp.add(setting, 'shadowBound', 0, 2048, 1); + GUIHelp.add(setting, 'shadowBias', 0.0001, 0.2, 0.00001); open && GUIHelp.open(); GUIHelp.endFolder(); } //render AtmosphericComponent - public static renderAtomosphericSky(component: AtmosphericComponent, open: boolean = true, name?: string) { + public static renderAtmosphericSky(component: AtmosphericComponent, open: boolean = true, name?: string) { name ||= 'AtmosphericSky'; GUIHelp.addFolder(name); GUIHelp.add(component, 'sunX', 0, 1, 0.01); @@ -66,27 +68,37 @@ export class GUIUtil { GUIHelp.add(transform, 'rotationX', 0.0, 360.0, 0.01); GUIHelp.add(transform, 'rotationY', 0.0, 360.0, 0.01); GUIHelp.add(transform, 'rotationZ', 0.0, 360.0, 0.01); - GUIHelp.add(transform, 'scaleX', 0.0, 2.0, 0.01); - GUIHelp.add(transform, 'scaleY', 0.0, 2.0, 0.01); - GUIHelp.add(transform, 'scaleZ', 0.0, 2.0, 0.01); + GUIHelp.add(transform, 'scaleX', -2.0, 2.0, 0.01); + GUIHelp.add(transform, 'scaleY', -2.0, 2.0, 0.01); + GUIHelp.add(transform, 'scaleZ', -2.0, 2.0, 0.01); open && GUIHelp.open(); GUIHelp.endFolder(); } + public static renderBloom(bloom: BloomPost, open: boolean = true, name?: string) { + name ||= 'Bloom'; + GUIHelp.addFolder(name); + GUIHelp.add(bloom, 'downSampleBlurSize', 3, 15, 1); + GUIHelp.add(bloom, 'downSampleBlurSigma', 0.01, 1, 0.001); + GUIHelp.add(bloom, 'upSampleBlurSize', 3, 15, 1); + GUIHelp.add(bloom, 'upSampleBlurSigma', 0.01, 1, 0.001); + GUIHelp.add(bloom, 'luminanceThreshole', 0.001, 10.0, 0.001); + GUIHelp.add(bloom, 'bloomIntensity', 0.001, 10.0, 0.001); + open && GUIHelp.open(); + GUIHelp.endFolder(); + } - //render bloom gui panel - public static renderBloom(bloom: HDRBloomPost, open: boolean = true, name?: string) { - name ||= 'HDRBloom'; + public static renderVector3(obj: Object3D, open: boolean = true, name?: string) { + name ||= 'Vector3'; GUIHelp.addFolder(name); - GUIHelp.add(bloom, 'enable'); - GUIHelp.addColor(bloom, 'tintColor'); - GUIHelp.add(bloom, 'luminosityThreshold'); - GUIHelp.add(bloom, 'strength', 0, 3, 0.001); - GUIHelp.add(bloom, 'exposure'); - GUIHelp.add(bloom, 'radius', 0, 1.0, 0.001); - GUIHelp.add(bloom, 'blurX'); - GUIHelp.add(bloom, 'blurY'); + GUIHelp.add(obj, 'x', -10.0, 10.0, 0.01); + GUIHelp.add(obj, 'y', -10.0, 10.0, 0.01); + GUIHelp.add(obj, 'z', -10.0, 10.0, 0.01); + + GUIHelp.add(obj.transform, 'rotationX', 0.0, 360.0, 0.01); + GUIHelp.add(obj.transform, 'rotationY', 0.0, 360.0, 0.01); + GUIHelp.add(obj.transform, 'rotationZ', 0.0, 360.0, 0.01); open && GUIHelp.open(); GUIHelp.endFolder(); } @@ -362,18 +374,20 @@ export class GUIUtil { static renderDebug() { // if (Engine3D.setting.render.debug) { - let debugTextures = Engine3D.getRenderJob(Engine3D.views[0]).postRenderer.debugTextures; - let debugTextureObj = { normalRender: -1 }; - for (let i = 0; i < debugTextures.length; i++) { - const tex = debugTextures[i]; - debugTextureObj[tex.name] = i; - } GUIHelp.removeFolder(`RenderPerformance`); //debug let f = GUIHelp.addFolder('RenderPerformance'); f.open(); - GUIHelp.add(Engine3D.setting.render, 'debugQuad', debugTextureObj); + if (Engine3D.getRenderJob(Engine3D.views[0]).postRenderer) { + let debugTextures = Engine3D.getRenderJob(Engine3D.views[0]).postRenderer.debugTextures; + let debugTextureObj = { normalRender: -1 }; + for (let i = 0; i < debugTextures.length; i++) { + const tex = debugTextures[i]; + debugTextureObj[tex.name] = i; + } + GUIHelp.add(Engine3D.setting.render, 'debugQuad', debugTextureObj); + } let debugChanel = { PositionView: 0, ColorView: 1, @@ -400,50 +414,126 @@ export class GUIUtil { GUIHelp.add(Engine3D.setting.render, 'drawOpMax', 0.0, 10000, 1); GUIHelp.endFolder(); } - // } - public static renderMaterial(mat: Material, open: boolean = true, name?: string) { - name ||= 'Material'; - GUIHelp.addFolder(name); + static renderLitMaterial(mat: LitMaterial) { + GUIHelp.addFolder(mat.name); + GUIHelp.addColor(mat, 'baseColor').onChange((v) => { + let color = mat.baseColor; + color.copyFromArray(v); + mat.baseColor = color; + }); - if (mat instanceof LitMaterial) { - GUIHelp.addColor(mat, 'baseColor').onChange((v) => { - mat.defaultPass.baseColor = v; - }); + let blendMode = { + NONE: BlendMode.NONE, + NORMAL: BlendMode.NORMAL, + ADD: BlendMode.ADD, + ALPHA: BlendMode.ALPHA, + } + // change blend mode by click dropdown box + GUIHelp.add({ blendMode: mat.blendMode }, 'blendMode', blendMode).onChange((v) => { + mat.blendMode = BlendMode[BlendMode[parseInt(v)]]; + }); - let blendMode = { - NONE: BlendMode.NONE, - NORMAL: BlendMode.NORMAL, - ADD: BlendMode.ADD, - ALPHA: BlendMode.ALPHA, - } - // change blend mode by click dropdown box - GUIHelp.add({ blendMode: mat.blendMode }, 'blendMode', blendMode).onChange((v) => { - mat.blendMode = BlendMode[BlendMode[parseInt(v)]]; - }); + GUIHelp.add(mat, 'alphaCutoff', 0.0, 1.0, 0.0001).onChange((v) => { + mat.alphaCutoff = v; + }); - GUIHelp.add(mat, 'alphaCutoff', 0.0, 1.0, 0.0001).onChange((v) => { - mat.alphaCutoff = v; - }); + GUIHelp.add(mat, 'doubleSide').onChange((v) => { + mat.doubleSide = v; + }); - GUIHelp.add(mat, 'doubleSide').onChange((v) => { - mat.doubleSide = v; - }); + GUIHelp.add(mat, 'roughness', 0.0, 1.0, 0.0001).onChange((v) => { + mat.roughness = v; + }); - GUIHelp.add(mat, 'roughness').onChange((v) => { - mat.roughness = v; - }); + GUIHelp.add(mat, 'metallic', 0.0, 1.0, 0.0001).onChange((v) => { + mat.metallic = v; + }); - GUIHelp.add(mat, 'metallic').onChange((v) => { - mat.metallic = v; - }); + GUIHelp.endFolder(); + } - GUIHelp.add(mat, 'envIntensity').onChange((v) => { - mat.envIntensity = v; + public static blendShape(obj: Object3D) { + GUIHelp.addFolder('morph controller'); + // register MorphTargetBlender component + let blendShapeComponent = obj.addComponent(MorphTargetBlender); + let targetRenderers = blendShapeComponent.cloneMorphRenderers(); + + let influenceData = {}; + // bind influenceData to gui + for (let key in targetRenderers) { + influenceData[key] = 0.0; + GUIHelp.add(influenceData, key, 0, 1, 0.01).onChange((v) => { + influenceData[key] = v; + let list = blendShapeComponent.getMorphRenderersByKey(key); + for (let renderer of list) { + renderer.setMorphInfluence(key, v); + } }); } - open && GUIHelp.open(); + GUIHelp.open(); + GUIHelp.endFolder(); + } + + public static renderBlendShape(obj: Object3D) { + GUIHelp.addFolder('morph controller'); + // register MorphTargetBlender component + let blendShapeComponents = obj.getComponents(SkinnedMeshRenderer2); + let targetRenderers = null; + for (let ii = 0; ii < blendShapeComponents.length; ii++) { + if (blendShapeComponents[ii].geometry.blendShapeData) { + targetRenderers = blendShapeComponents[ii].geometry.blendShapeData.shapeNames; + } + } + + if (targetRenderers) { + let influenceData = {}; + // bind influenceData to gui + for (let i in targetRenderers) { + let key = targetRenderers[i]; + influenceData[key] = 0.0; + GUIHelp.add(influenceData, key, 0, 1, 0.01).onChange((v) => { + influenceData[key] = v; + for (let index = 0; index < blendShapeComponents.length; index++) { + for (let renderer of blendShapeComponents) { + renderer.setMorphInfluence(key, v); + } + } + }); + } + } + + GUIHelp.open(); + GUIHelp.endFolder(); + } + + static renderAnimator(com: AnimatorComponent) { + let anim = {} + for (let i = 0; i < com.clips.length; i++) { + const clip = com.clips[i]; + anim[clip.clipName] = clip.clipName; + } + + GUIHelp.addFolder('morph controller'); + + GUIHelp.add({ anim: anim }, 'anim', anim).onChange((v) => { + com.playAnim(v); + com.playBlendShape(v); + }); + GUIHelp.endFolder(); + + } + + + public static renderGTAO(post: GTAOPost) { + GUIHelp.addFolder("GTAO"); + GUIHelp.add(post, "maxDistance", 0.0, 149, 1); + GUIHelp.add(post, "maxPixel", 0.0, 150, 1); + GUIHelp.add(post, "rayMarchSegment", 0.0, 50, 0.001); + GUIHelp.add(post, "darkFactor", 0.0, 5, 0.001); + GUIHelp.add(post, "blendColor"); + GUIHelp.add(post, "multiBounce"); GUIHelp.endFolder(); } } \ No newline at end of file diff --git a/src/Engine3D.ts b/src/Engine3D.ts index 9b39d96a..609c9878 100644 --- a/src/Engine3D.ts +++ b/src/Engine3D.ts @@ -5,12 +5,15 @@ import { Time } from './util/Time'; import { InputSystem } from './io/InputSystem'; import { View3D } from './core/View3D'; import { version } from '../package.json'; + +import { GPUTextureFormat } from './gfx/graphics/webGpu/WebGPUConst'; import { webGPUContext } from './gfx/graphics/webGpu/Context3D'; -import { FXAAPost } from './gfx/renderJob/post/FXAAPost'; +import { RTResourceConfig } from './gfx/renderJob/config/RTResourceConfig'; +import { RTResourceMap } from './gfx/renderJob/frame/RTResourceMap'; + import { ForwardRenderJob } from './gfx/renderJob/jobs/ForwardRenderJob'; import { GlobalBindGroup } from './gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup'; import { Interpolator } from './math/TimeInterpolator'; -import { RTResourceMap } from './gfx/renderJob/frame/RTResourceMap'; import { RendererJob } from './gfx/renderJob/jobs/RendererJob'; import { Res } from './assets/Res'; import { ShaderLib } from './assets/shader/ShaderLib'; @@ -19,7 +22,10 @@ import { ComponentCollect } from './gfx/renderJob/collect/ComponentCollect'; import { ShadowLightsCollect } from './gfx/renderJob/collect/ShadowLightsCollect'; import { GUIConfig } from './components/gui/GUIConfig'; import { WasmMatrix } from '@orillusion/wasm-matrix/WasmMatrix'; -import { Matrix4 } from '.'; +import { Matrix4 } from './math/Matrix4'; +import { FXAAPost } from './gfx/renderJob/post/FXAAPost'; +import { PostProcessingComponent } from './components/post/PostProcessingComponent'; +import { Texture } from './gfx/graphics/webGpu/core/texture/Texture'; /** * Orillusion 3D Engine @@ -136,6 +142,15 @@ export class Engine3D { useLogDepth: false, gi: false, postProcessing: { + bloom: { + downSampleStep: 5, + downSampleBlurSize: 5, + downSampleBlurSigma: 1.0, + upSampleBlurSize: 5, + upSampleBlurSigma: 1.0, + luminanceThreshole: 1.0, + bloomIntensity: 1.0, + }, globalFog: { debug: false, enable: false, @@ -148,7 +163,7 @@ export class Engine3D { skyFactor: 0.5, skyRoughness: 0.4, overrideSkyFactor: 0.8, - fogColor: new Color(112 / 255, 61 / 255, 139 / 255, 1), + fogColor: new Color(96 / 255, 117 / 255, 133 / 255, 1), falloff: 0.7, rayLength: 200.0, scatteringExponent: 2.7, @@ -203,16 +218,6 @@ export class Engine3D { mixThreshold: 0.1, debug: true, }, - bloom: { - enable: false, - blurX: 4, - blurY: 4, - strength: 0.25, - exposure: 1, - radius: 1.3, - luminosityThreshold: 0.98, - debug: false, - }, fxaa: { enable: false, }, @@ -229,12 +234,10 @@ export class Engine3D { enable: true, type: 'HARD', pointShadowBias: 0.002, - // shadowQuality: 2.5, shadowSize: 1024, pointShadowSize: 1024, shadowSoft: 0.005, - // shadowNear: 1, - // shadowFar: 2000, + shadowBias: 0.0001, needUpdate: true, autoUpdate: true, updateFrameRate: 2, @@ -286,6 +289,9 @@ export class Engine3D { materialChannelDebug: false, materialDebug: false }, + loader: { + numConcurrent: 20, + } }; @@ -327,6 +333,8 @@ export class Engine3D { this.res = new Res(); + this.res.initDefault(); + this._beforeRender = descriptor.beforeRender; this._renderLoop = descriptor.renderLoop; this._lateRender = descriptor.lateRender; @@ -345,8 +353,20 @@ export class Engine3D { this.views = [view]; let renderJob = new ForwardRenderJob(view); this.renderJobs.set(view, renderJob); - renderJob.addPost(new FXAAPost()); - renderJob.start(); + let presentationSize = webGPUContext.presentationSize; + // RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); + + if (this.setting.pick.mode == `pixel`) { + let postProcessing = view.scene.getOrAddComponent(PostProcessingComponent); + postProcessing.addPost(FXAAPost); + + } else { + } + + if (this.setting.pick.mode == `pixel` || this.setting.pick.mode == `bound`) { + view.enablePick = true; + } + this.resume(); return renderJob; } @@ -364,8 +384,18 @@ export class Engine3D { const view = views[i]; let renderJob = new ForwardRenderJob(view); this.renderJobs.set(view, renderJob); - renderJob.addPost(new FXAAPost()); - renderJob.start(); + let presentationSize = webGPUContext.presentationSize; + + if (this.setting.pick.mode == `pixel`) { + let postProcessing = view.scene.addComponent(PostProcessingComponent); + postProcessing.addPost(FXAAPost); + } else { + RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); + } + + if (this.setting.pick.mode == `pixel` || this.setting.pick.mode == `bound`) { + view.enablePick = true; + } } this.resume(); } @@ -401,6 +431,9 @@ export class Engine3D { * @internal */ private static render(time) { + webGPUContext.updateSize(); + Texture.destroyTexture(); + this._deltaTime = time - this._time; this._time = time; @@ -489,6 +522,18 @@ export class Engine3D { } } + for (const iterator of ComponentCollect.graphicComponent) { + let k = iterator[0]; + let v = iterator[1]; + for (const iterator2 of v) { + let f = iterator2[0]; + let c = iterator2[1]; + if (k && f.enable) { + c(k); + }; + } + } + if (this._renderLoop) { this._renderLoop(); } @@ -503,6 +548,9 @@ export class Engine3D { globalMatrixBindGroup.writeBuffer(Matrix4.useCount * 16); this.renderJobs.forEach((v, k) => { + if (!v.renderState) { + v.start(); + } v.renderFrame(); }); @@ -520,6 +568,7 @@ export class Engine3D { } if (this._lateRender) this._lateRender(); + } diff --git a/src/assets/Res.ts b/src/assets/Res.ts index 05a1e06e..8e2b768c 100644 --- a/src/assets/Res.ts +++ b/src/assets/Res.ts @@ -23,20 +23,26 @@ import { FontParser, FontInfo } from '../loader/parser/FontParser'; import { fonts } from './Fonts'; import { AtlasParser } from '../loader/parser/AtlasParser'; import { Reference } from '../util/Reference'; -import { Material } from '..'; +import { Material } from '../materials/Material'; +import { Ctor, Parser } from '../util/Global'; +import { ParserBase } from '../loader/parser/ParserBase'; +import { GeometryBase } from '../core/geometry/GeometryBase'; +import { LitMaterial } from '../materials/LitMaterial'; /** * Resource management classes for textures, materials, models, and preset bodies. * @group Assets */ export class Res { + private _texturePool: Map; private _materialPool: Map; private _prefabPool: Map; // private _prefabLoaderPool: Map; private _gltfPool: Map; + private _geometryPool: Map; private _atlasList: Map; - + private _obj: Map; /** * @constructor @@ -45,17 +51,36 @@ export class Res { this._texturePool = new Map(); this._materialPool = new Map(); this._prefabPool = new Map(); + this._geometryPool = new Map(); // this._prefabLoaderPool = new Map; this._gltfPool = new Map; this._atlasList = new Map(); - - this.initDefault(); + this._obj = new Map(); + // this.initDefault(); } public getGltf(url: string): GLTF_Info { return this._gltfPool.get(url); } + /** + * add a obj with reference of url + * @param url file path + * @param texture source obj + */ + public addObj(url: string, obj: any) { + this._obj.set(url, obj); + } + + /** + * get obj by url + * @param url file path + * @returns + */ + public getObj(url: string): any { + return this._obj.get(url); + } + /** * add a texture with reference of url * @param url file path @@ -74,6 +99,14 @@ export class Res { return this._texturePool.get(url); } + public addGeometry(url: string, geo: GeometryBase) { + this._geometryPool.set(url, geo); + } + + public getGeometry(url: string): GeometryBase { + return this._geometryPool.get(url); + } + /** * add a material with reference of name * @param name material name @@ -129,6 +162,13 @@ export class Res { return null; } + public async load(url: string, c: Parser, loaderFunctions?: LoaderFunctions) { + let loader = new FileLoader(); + let parser = await loader.load(url, c, loaderFunctions); + let ret = parser.data; + return ret; + } + /** * load a gltf file * @param url the url of file @@ -231,6 +271,39 @@ export class Res { return texture; } + private async loadTextureCount(urls: string[], count: number, loaderFunctions?: LoaderFunctions, flipY?: boolean) { + return new Promise( + async (suc, fail) => { + let total = 0; + let loadTexture = []; + if (count == 0) { + suc(loadTexture); + } + for (let j = 0; j < count; j++) { + const url = urls.shift(); + this.loadTexture(url, loaderFunctions, flipY).then((t) => { + loadTexture.push(t); + total++; + if (total == count) { + suc(loadTexture); + } + }); + } + } + ); + } + + public async loadBitmapTextures(urls: string[], count: number = 5, loaderFunctions?: LoaderFunctions, flipY?: boolean) { + let loadTexture: BitmapTexture2D[] = []; + let loadCount = Math.floor(urls.length / count) + 1; + let last = Math.floor(urls.length % count) + for (let i = 0; i < loadCount; i++) { + let list = await this.loadTextureCount(urls, i == loadCount - 1 ? last : count, loaderFunctions, flipY); + loadTexture.push(...list); + } + return loadTexture; + } + /** * load a hdr texture * @param url texture url @@ -373,6 +446,7 @@ export class Res { public defaultGUITexture: GUITexture; public defaultGUISprite: GUISprite; + public defaultMaterial: LitMaterial; /** * create a texture @@ -424,9 +498,9 @@ export class Res { /** * Initialize a common texture object. Provide a universal solid color texture object. */ - private initDefault() { + public initDefault() { this.normalTexture = this.createTexture(32, 32, 255 * 0.5, 255 * 0.5, 255.0, 255.0, 'default-normalTexture'); - this.maskTexture = this.createTexture(32, 32, 255, 255 * 0.5, 0.0, 255.0, 'default-maskTexture'); + this.maskTexture = this.createTexture(32, 32, 255, 255 * 0.5, 255.0, 255.0, 'default-maskTexture'); this.whiteTexture = this.createTexture(32, 32, 255, 255, 255, 255, 'default-whiteTexture'); this.blackTexture = this.createTexture(32, 32, 0, 0, 0, 255.0, 'default-blackTexture'); this.redTexture = this.createTexture(32, 32, 255, 0, 0, 255.0, 'default-redTexture'); @@ -458,5 +532,7 @@ export class Res { this.defaultGUITexture = new GUITexture(this.whiteTexture); this.defaultGUISprite = new GUISprite(this.defaultGUITexture); this.defaultGUISprite.trimSize.set(4, 4) + + this.defaultMaterial = new LitMaterial(); } } diff --git a/src/assets/shader/ShaderLib.ts b/src/assets/shader/ShaderLib.ts index 94575115..612dfc6d 100644 --- a/src/assets/shader/ShaderLib.ts +++ b/src/assets/shader/ShaderLib.ts @@ -1,4 +1,3 @@ -import { Bloom_shader } from './post/Bloom_shader'; import { ClusterDebug_frag } from './materials/program/ClusterDebug_frag'; import { CubeSky_Shader } from './sky/CubeSky_Shader'; import { LightingFunction_frag } from './lighting/LightingFunction_frag'; @@ -28,13 +27,24 @@ import { Irradiance_frag } from './lighting/Irradiance_frag'; import { BRDF_frag } from './lighting/BRDF_frag'; import { BxDF_frag } from './lighting/BxDF_frag'; import { Clearcoat_frag } from './materials/program/Clearcoat_frag'; -import { LitShader } from './materials/LitShader'; +import { Lit_shader } from './materials/Lit_shader'; import { PBRLItShader } from './materials/PBRLItShader'; import { BxdfDebug_frag } from './materials/program/BxdfDebug_frag'; import { Quad_depth2d_frag_wgsl, Quad_depthCube_frag_wgsl, Quad_frag_wgsl, Quad_vert_wgsl } from './quad/Quad_shader'; import { ColorUtil } from './utils/ColorUtil'; import { GenerayRandomDir } from './utils/GenerayRandomDir'; -import { ClusterLight, GBuffer_pass, LambertShader, MatrixShader, QuadGlsl_fs, QuadGlsl_vs, SkyGBuffer_pass, UnLit, ZPassShader_fs, ZPassShader_vs, castPointShadowMap_vert, directionShadowCastMap_frag, shadowCastMap_frag, shadowCastMap_vert } from '../..'; +import { MatrixShader } from './math/MatrixShader'; +import { ClusterLight } from './core/struct/ClusterLight'; +import { Hair_frag } from './lighting/Hair_frag'; +import { BsDF_frag } from './lighting/BsDF_frag'; +import { UnLit } from './materials/UnLit'; +import { Lambert_shader } from './materials/Lambert_shader'; +import { QuadGlsl_fs, QuadGlsl_vs } from './glsl/Quad_glsl'; +import { SkyGBuffer_pass } from './core/pass/SkyGBuffer_pass'; +import { GBuffer_pass } from './core/pass/GBuffer_pass'; +import { castPointShadowMap_vert, directionShadowCastMap_frag, shadowCastMap_frag, shadowCastMap_vert } from './core/pass/CastShadow_pass'; +import { ZPassShader_vs } from './core/pass/ZPassShader_vs'; +import { ZPassShader_fs } from './core/pass/ZPassShader_fs'; /** * @internal @@ -44,6 +54,7 @@ export class ShaderLib { public static init() { ShaderLib.register('MathShader', MathShader); ShaderLib.register('FastMathShader', FastMathShader); + ShaderLib.register('MatrixShader', MatrixShader); ShaderLib.register('GlobalUniform', GlobalUniform); @@ -78,11 +89,13 @@ export class ShaderLib { ShaderLib.register('ColorUtil_frag', ColorUtil); ShaderLib.register('ColorUtil', ColorUtil); ShaderLib.register('BRDF_frag', BRDF_frag); + ShaderLib.register('Hair_frag', Hair_frag); ShaderLib.register('BxDF_frag', BxDF_frag); + ShaderLib.register('BsDF_frag', BsDF_frag); ShaderLib.register('UnLit_frag', UnLit_frag); ShaderLib.register('UnLit', UnLit); ShaderLib.register('Clearcoat_frag', Clearcoat_frag); - ShaderLib.register('LitShader', LitShader); + ShaderLib.register('LitShader', Lit_shader); ShaderLib.register('PBRLItShader', PBRLItShader); ShaderLib.register('ClusterDebug_frag', ClusterDebug_frag); @@ -94,11 +107,8 @@ export class ShaderLib { ShaderLib.register('Quad_depthCube_frag_wgsl', Quad_depthCube_frag_wgsl); ShaderLib.register('sky_vs_frag_wgsl', CubeSky_Shader.sky_vs_frag_wgsl); ShaderLib.register('sky_fs_frag_wgsl', CubeSky_Shader.sky_fs_frag_wgsl); - ShaderLib.register('Bloom_Brightness_frag_wgsl', Bloom_shader.Bloom_Brightness_frag_wgsl); - ShaderLib.register('Bloom_blur_frag_wgsl', Bloom_shader.Bloom_blur_frag_wgsl); - ShaderLib.register('Bloom_composite_frag_wgsl', Bloom_shader.Bloom_composite_frag_wgsl); - ShaderLib.register("LambertShader", LambertShader); + ShaderLib.register("LambertShader", Lambert_shader); ShaderLib.register("QuadGlsl_vs", QuadGlsl_vs); ShaderLib.register("QuadGlsl_fs", QuadGlsl_fs); diff --git a/src/assets/shader/utils/BRDFLUT.ts b/src/assets/shader/compute/BRDFLUT.ts similarity index 100% rename from src/assets/shader/utils/BRDFLUT.ts rename to src/assets/shader/compute/BRDFLUT.ts diff --git a/src/assets/shader/compute/BloomEffect_cs.ts b/src/assets/shader/compute/BloomEffect_cs.ts new file mode 100644 index 00000000..36b4e3d7 --- /dev/null +++ b/src/assets/shader/compute/BloomEffect_cs.ts @@ -0,0 +1,214 @@ + +let BloomCfg = /*wgsl*/ ` +struct BloomCfg{ + downSampleStep: f32, + downSampleBlurSize: f32, + downSampleBlurSigma: f32, + upSampleBlurSize: f32, + upSampleBlurSigma: f32, + luminanceThreshole: f32, + bloomIntensity: f32, + slot: f32, +} +@group(0) @binding(0) var bloomCfg: BloomCfg; +` +//_______________calc weight + +let GaussWeight2D: string = /*wgsl*/ ` +fn GaussWeight2D(x:f32, y:f32, sigma:f32) -> f32 + { + let PI = 3.14159265358; + let E = 2.71828182846; + let sigma_2 = pow(sigma, 2); + + let a = -(x*x + y*y) / (2.0 * sigma_2); + return pow(E, a) / (2.0 * PI * sigma_2); + } +` + +let GaussBlur = function (GaussNxN: string, inTex: string, inTexSampler: string) { + var code: string = /*wgsl*/ ` + + + fn ${GaussNxN}(uv:vec2, n:i32, stride:vec2, sigma:f32) -> vec3 + { + var color = vec3(0.0); + let r:i32 = n / 2; + var weight:f32 = 0.0; + + for(var i:i32=-r; i<=r; i+=1) + { + for(var j=-r; j<=r; j+=1) + { + let w = GaussWeight2D(f32(i), f32(j), sigma); + var coord:vec2 = uv + vec2(f32(i), f32(j)) * stride; + // color += tex2D(tex, coord).rgb * w; + color += textureSampleLevel(${inTex}, ${inTexSampler}, coord, 0.0).xyz * w; + weight += w; + } + } + + color /= weight; + return color; + }`; + return code; + +} + + + +//________________________pixel filter + +export let threshold: string = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var inTex : texture_2d; +@group(0) @binding(2) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(inTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = textureLoad(inTex, fragCoord, 0); + let lum = dot(vec3(0.2126, 0.7152, 0.0722), color.rgb); + + // if(lum<=bloomCfg.luminanceThreshole) { + // color = vec4(0,0,0,color.w); + // } + var ret = color.xyz; + var brightness = lum; + var contribution = max(0, brightness - bloomCfg.luminanceThreshole); + contribution /=max(brightness, 0.00001); + ret = ret * contribution; + + textureStore(outTex, fragCoord, vec4(ret, color.w)); +} +` + +//________________________down sample + +export let downSample: string = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var inTex : texture_2d; +@group(0) @binding(2) var inTexSampler: sampler; +@group(0) @binding(3) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +${GaussWeight2D} +${GaussBlur('GaussNxN', 'inTex', 'inTexSampler')} + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(outTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = vec4(0.0, 0.0, 0.0, 1.0); + var uv = vec2(f32(fragCoord.x), f32(fragCoord.y)) / vec2(f32(texSize.x - 1), f32(texSize.y -1)); + let stride = vec2(1.0) / vec2(f32(texSize.x), f32(texSize.y)); // texel size of last level + let rgb = GaussNxN(uv, i32(bloomCfg.downSampleBlurSize), stride, bloomCfg.downSampleBlurSigma); + color = vec4(rgb, color.w); + textureStore(outTex, fragCoord, color); +} +` + + +//__________________________up sample +export let upSample = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var _MainTex : texture_2d; +@group(0) @binding(2) var _MainTexSampler: sampler; +@group(0) @binding(3) var _PrevMip : texture_2d; +@group(0) @binding(4) var _PrevMipSampler: sampler; +@group(0) @binding(5) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +${GaussWeight2D} +${GaussBlur('GaussNxN_0', '_MainTex', '_MainTexSampler')} +${GaussBlur('GaussNxN_1', '_PrevMip', '_PrevMipSampler')} + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(outTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = vec4(0.0, 0.0, 0.0, 1.0); + var uv = vec2(f32(fragCoord.x), f32(fragCoord.y)) / vec2(f32(texSize.x - 1), f32(texSize.y -1)); + // half stride + let prev_stride = vec2(0.5) / vec2(f32(texSize.x), f32(texSize.y)); + let curr_stride = vec2(1.0) / vec2(f32(texSize.x), f32(texSize.y)); + + let rgb1 = GaussNxN_0(uv, i32(bloomCfg.upSampleBlurSize), prev_stride, bloomCfg.upSampleBlurSigma); + let rgb2 = GaussNxN_1(uv, i32(bloomCfg.upSampleBlurSize), curr_stride, bloomCfg.upSampleBlurSigma); + color = vec4(rgb1+rgb2, color.w); + textureStore(outTex, fragCoord, color); +} +` + + +//__________________________blend +export let post = /*wgsl*/ ` +${BloomCfg} + +@group(0) @binding(1) var _MainTex : texture_2d; +@group(0) @binding(2) var _BloomTex : texture_2d; +@group(0) @binding(3) var _BloomTexSampler : sampler; +@group(0) @binding(4) var outTex : texture_storage_2d; + +var texSize: vec2; +var fragCoord: vec2; + +fn ACESToneMapping(color: vec3, adapted_lum: f32) -> vec3 +{ + let A = 2.51; + let B = 0.03; + let C = 2.43; + let D = 0.59; + let E = 0.14; + + var color2 = color * adapted_lum; + color2 = (color2 * (A * color2 + B)) / (color2 * (C * color2 + D) + E); + return color2; +} + +@compute @workgroup_size( 8 , 8 , 1 ) +fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(global_invocation_id) globalInvocation_id : vec3) +{ + fragCoord = vec2( globalInvocation_id.xy ); + texSize = textureDimensions(outTex).xy; + if(fragCoord.x >= i32(texSize.x) || fragCoord.y >= i32(texSize.y)){ + return; + } + var color = textureLoad(_MainTex, fragCoord, 0); + let uv = vec2(f32(fragCoord.x), f32(fragCoord.y)) / vec2(f32(texSize.x - 1), f32(texSize.y - 1)); + + // var bloom = textureLoad(_BloomTex, fragCoord, 0).xyz; + var bloom = textureSampleLevel(_BloomTex, _BloomTexSampler, uv, 0.0).xyz * bloomCfg.bloomIntensity; + + // tone map + bloom = ACESToneMapping(bloom, 1.0); + let g = 1.0 / 2.2; + bloom = saturate(pow(bloom, vec3(g))); + + color = vec4(color.xyz + bloom.xyz, color.w); + textureStore(outTex, fragCoord, color); +} +` \ No newline at end of file diff --git a/src/assets/shader/compute/DDGIIrradiance_Cs.ts b/src/assets/shader/compute/DDGIIrradiance_Cs.ts index 2ca6d611..ae97f6c1 100644 --- a/src/assets/shader/compute/DDGIIrradiance_Cs.ts +++ b/src/assets/shader/compute/DDGIIrradiance_Cs.ts @@ -2,6 +2,7 @@ export let DDGIIrradiance_shader = /*wgsl*/` #include "GenerayRandomDir" #include "MathShader" #include "IrradianceVolumeData_frag" +var PI: f32 = 3.14159265359; struct ProbeData{ offsetX:f32, @@ -32,7 +33,7 @@ struct CacheHitData{ @group(0) @binding(0) var probes : array; @group(0) @binding(1) var irradianceBuffer : array>; @group(0) @binding(2) var depthBuffer : array>; -@group(0) @binding(3) var uniformData : IrradianceVolumeData ; +@group(0) @binding(3) var uniformData : IrradianceVolumeData ; @group(0) @binding(4) var probeIrradianceMap : texture_storage_2d; @group(0) @binding(5) var probeDepthMap : texture_storage_2d; @group(0) @binding(6) var depthRaysBuffer : array>; diff --git a/src/assets/shader/compute/DDGILighting_CSShader.ts b/src/assets/shader/compute/DDGILighting_CSShader.ts index 98fe584d..e650ee67 100644 --- a/src/assets/shader/compute/DDGILighting_CSShader.ts +++ b/src/assets/shader/compute/DDGILighting_CSShader.ts @@ -1,6 +1,7 @@ import { CSM } from "../../../core/csm/CSM"; export let DDGILighting_shader = /*wgsl*/` +var PI: f32 = 3.14159265359; #include "GlobalUniform" #include "MathShader" diff --git a/src/assets/shader/compute/GTAO_cs.ts b/src/assets/shader/compute/GTAO_cs.ts index 35ef5351..683d2f9d 100644 --- a/src/assets/shader/compute/GTAO_cs.ts +++ b/src/assets/shader/compute/GTAO_cs.ts @@ -63,6 +63,7 @@ export let GTAO_cs: string = /*wgsl*/ ` if(gtaoData.blendColor > 0.5){ outColor = oc.xyz * gtao; } + // textureStore(outTex, fragCoord , vec4(vec3f(newFactor), oc.w)); textureStore(outTex, fragCoord , vec4(outColor, oc.w)); } @@ -115,14 +116,16 @@ export let GTAO_cs: string = /*wgsl*/ ` && sampleCoord.y < i32(texSize.y) ) { totalWeight += 1.0; - let samplePosition = textureLoad(posTex, sampleCoord, 0).xyz; - let distanceVec2 = samplePosition - wPosition; - let distance = length(distanceVec2); - if(distance < gtaoData.maxDistance && distance > 1.0){ - let sampleDir = normalize(distanceVec2); - var factor = saturate(dot(sampleDir, originNormal) - 0.1); - factor *= 1.0 - distance / gtaoData.maxDistance; - weight += factor; + let samplePosition = textureLoad(posTex, sampleCoord, 0).xyzw; + if(samplePosition.w>0.0){ + let distanceVec2 = samplePosition.xyz - wPosition; + let distance = length(distanceVec2); + if(distance < gtaoData.maxDistance ){ + let sampleDir = normalize(distanceVec2); + var factor = saturate( dot(sampleDir, originNormal)); + factor *= 1.0 - distance / gtaoData.maxDistance; + weight += factor; + } } } } diff --git a/src/assets/shader/compute/MultiBouncePass_cs.ts b/src/assets/shader/compute/MultiBouncePass_cs.ts index 55ba48c4..bf44b2db 100644 --- a/src/assets/shader/compute/MultiBouncePass_cs.ts +++ b/src/assets/shader/compute/MultiBouncePass_cs.ts @@ -13,7 +13,7 @@ export let MultiBouncePass_cs: string = /*wgsl*/ ` }; @group(0) @binding(0) var outputBuffer : texture_storage_2d; - @group(0) @binding(1) var uniformData : IrradianceVolumeData ; + @group(0) @binding(1) var uniformData : IrradianceVolumeData ; @group(1) @binding(0) var normalMapSampler : sampler; @group(1) @binding(1) var normalMap : texture_2d; diff --git a/src/assets/shader/compute/PreIntegratedLut.ts b/src/assets/shader/compute/PreIntegratedLut.ts new file mode 100644 index 00000000..e3676e29 --- /dev/null +++ b/src/assets/shader/compute/PreIntegratedLut.ts @@ -0,0 +1,70 @@ + +export let PreIntegratedLut: string = /*wgsl*/ ` +varPI: f32 = 3.141592653589793; + +fn Scatter( r:f32) -> vec3f +{ + return Gaussian(0.0064 * 1.414, r) * vec3f(0.233, 0.455, 0.649) + + Gaussian(0.0484 * 1.414, r) * vec3f(0.100, 0.336, 0.344) + + Gaussian(0.1870 * 1.414, r) * vec3f(0.118, 0.198, 0.000) + + Gaussian(0.5670 * 1.414, r) * vec3f(0.113, 0.007, 0.007) + + Gaussian(1.9900 * 1.414, r) * vec3f(0.358, 0.004, 0.00001) + + Gaussian(7.4100 * 1.414, r) * vec3f(0.078, 0.00001, 0.00001); +} + +fn Gaussian( v:f32 , r:f32 ) -> f32 +{ + return 1.0 / sqrt(2.0 * PI * v) * exp(-(r * r) / (2.0 * v)); +} + +fn Integrate( cosTheta : f32 , skinRadius: f32 ) -> vec3f +{ + var theta = acos(cosTheta); // theta -> the angle from lighting direction + var totalWeights = vec3f(0.0); + var totalLight = vec3f(0.0); + + var a = -(PI / 2.0); + let inc = 0.05; + + while ( a <= (PI / 2.0) ) { + var sampleAngle = theta + a; + var diffuse = clamp(cos(sampleAngle),0.0,1.0); + + // calc distance + var sampleDist = abs(2.0 * skinRadius * sin(a * 0.5)); + + // estimated by Gaussian pdf + var weights = Scatter(sampleDist); + + totalWeights += weights; + totalLight += diffuse * weights; + a += inc; + } + + var result = vec3f(totalLight.x / totalWeights.x, totalLight.y / totalWeights.y, totalLight.z / totalWeights.z); + return result; +} + +@group(0) @binding(0) var sssMap: texture_storage_2d; + +@compute @workgroup_size(8, 8, 1) +// fn CsMain( @builtin(workgroup_id) workgroup_id : vec3 , @builtin(local_invocation_id) local_invocation_id : vec3 ){ +fn CsMain(@builtin(global_invocation_id) global_invocation_id : vec3){ + var fragCoord = vec2(global_invocation_id.x, global_invocation_id.y); + + var fragColor = vec4(1.0,1.0,0.0,1.0); + // // Output to screen + // var res = integrateBRDF(f32(fragCoord.y + 1u) / 256.0, f32(fragCoord.x + 1u) / 256.0); + // fragColor = vec4(res.x, res.y, 0.0, 1.0); + + var NDotL = mix(-1.0, 1.0, f32(fragCoord.x) / 256.0) ; + var oneOverR = 2.0 * 1.0 / (f32((fragCoord.y + 1u)) / 256.0); + + //Integrate Diffuse Scattering + var diff = Integrate(NDotL, oneOverR); + // fragColor = vec4f(diff,1.0); + fragColor = vec4f(vec3f(diff),1.0); + textureStore(sssMap, vec2(fragCoord.xy), fragColor); +} +` + diff --git a/src/assets/shader/core/base/Common_frag.ts b/src/assets/shader/core/base/Common_frag.ts index 58ca186d..b793b400 100644 --- a/src/assets/shader/core/base/Common_frag.ts +++ b/src/assets/shader/core/base/Common_frag.ts @@ -8,8 +8,11 @@ export let Common_frag: string = /*wgsl*/ ` var ORI_VertexVarying: FragmentVarying; var ORI_ShadingInput: ShadingInput; var viewDir:vec3; + var modelIndex:u32; @fragment fn FragMain( vertex_varying:FragmentVarying ) -> FragmentOutput { + modelIndex = u32(round(vertex_varying.index)) ; + ORI_VertexVarying = vertex_varying; ORI_FragmentOutput.color = vec4(1.0, 0.0, 0.0, 1.0); viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; @@ -26,9 +29,6 @@ export let Common_frag: string = /*wgsl*/ ` debugFragmentOut(); #endif - // var d1 = logDepth( ORI_VertexVarying.fragCoord.w , globalUniform.far); - // ORI_FragmentOutput.out_depth = d1 ; - #if USE_OUTDEPTH #if USE_LOGDEPTH ORI_FragmentOutput.out_depth = log2Depth(ORI_VertexVarying.fragCoord.z,globalUniform.near,globalUniform.far) ; @@ -37,10 +37,6 @@ export let Common_frag: string = /*wgsl*/ ` #endif #endif - // var d1 = log2(ORI_VertexVarying.fragCoord.w + 1.0) * 2.0 / (log(f + 1.0) / 0.6931471805599453) * 0.5 ; - // 2.0 / (Math.log(camera.far + 1.0) / Math.LN2) - // ORI_FragmentOutput.out_depth = d1 ; - return ORI_FragmentOutput ; } diff --git a/src/assets/shader/core/common/GlobalUniform.ts b/src/assets/shader/core/common/GlobalUniform.ts index 954e679e..89750c83 100644 --- a/src/assets/shader/core/common/GlobalUniform.ts +++ b/src/assets/shader/core/common/GlobalUniform.ts @@ -40,10 +40,16 @@ export let GlobalUniform: string = /*wgsl*/ ` enableCSM:f32, csmMargin:f32, - notUsed1:f32, - notUsed2:f32, - notUsed3:f32 - + nDirShadowStart: i32, + nDirShadowEnd: i32, + nPointShadowStart: i32, + + nPointShadowEnd: i32, + empty1: i32, + empty2: i32, + empty3: i32, + + shadowLights:mat4x4 }; @group(0) @binding(0) diff --git a/src/assets/shader/core/pass/CastShadow_pass.ts b/src/assets/shader/core/pass/CastShadow_pass.ts index cd43c7bb..38087140 100644 --- a/src/assets/shader/core/pass/CastShadow_pass.ts +++ b/src/assets/shader/core/pass/CastShadow_pass.ts @@ -20,37 +20,68 @@ struct VertexOutput { var worldMatrix: mat4x4; struct VertexAttributes{ - @builtin(instance_index) index : u32, - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) uv: vec2, - @location(3) TEXCOORD_1: vec2, + @builtin(instance_index) index : u32, + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) TEXCOORD_1: vec2, + + #if USE_METAHUMAN + #if USE_TANGENT + @location(4) TANGENT: vec4, + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(9)} + #else + ${MorphTarget_shader.getMorphTargetAttr(7)} + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(8)} + #else + ${MorphTarget_shader.getMorphTargetAttr(6)} + #endif + #endif + #else + #if USE_TANGENT + @location(4) TANGENT: vec4, + #endif - #if USE_TANGENT - @location(4) TANGENT: vec4, - #if USE_SKELETON - @location(5) joints0: vec4, - @location(6) weights0: vec4, - #if USE_JOINT_VEC8 - @location(7) joints1: vec4, - @location(8) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(5)} - #endif - #elseif USE_SKELETON - @location(4) joints0: vec4, - @location(5) weights0: vec4, - #if USE_JOINT_VEC8 - @location(6) joints1: vec4, - @location(7) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(4)} - #endif -} + #if USE_SKELETON + #if USE_TANGENT + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + #endif + #endif + #endif + #if USE_MORPHTARGETS + #if USE_TANGENT + ${MorphTarget_shader.getMorphTargetAttr(5)} + #else + ${MorphTarget_shader.getMorphTargetAttr(4)} + #endif + #endif + #endif +} @vertex fn main(vertex:VertexAttributes) -> VertexOutput { @@ -105,28 +136,54 @@ struct VertexAttributes{ @location(2) uv: vec2, @location(3) TEXCOORD_1: vec2, - #if USE_TANGENT - @location(4) TANGENT: vec4, - #if USE_SKELETON - @location(5) joints0: vec4, - @location(6) weights0: vec4, - #if USE_JOINT_VEC8 - @location(7) joints1: vec4, - @location(8) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(5)} - #endif - #elseif USE_SKELETON - @location(4) joints0: vec4, - @location(5) weights0: vec4, - #if USE_JOINT_VEC8 - @location(6) joints1: vec4, - @location(7) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(4)} - #endif + + #if USE_METAHUMAN + #if USE_TANGENT + @location(4) TANGENT: vec4, + @location(5) joints0: vec4, + @location(6) weights0: vec4, + @location(7) joints1: vec4, + @location(8) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(9)} + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + @location(6) joints1: vec4, + @location(7) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(8)} + #endif + #else + #if USE_TANGENT + @location(4) TANGENT: vec4, + #endif + + #if USE_SKELETON + #if USE_TANGENT + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + #endif + #endif + #endif + + #if USE_MORPHTARGETS + #if USE_TANGENT + ${MorphTarget_shader.getMorphTargetAttr(5)} + #else + ${MorphTarget_shader.getMorphTargetAttr(4)} + #endif + #endif + + #endif } @vertex @@ -135,6 +192,15 @@ fn main(vertex:VertexAttributes) -> VertexOutput { let shadowMatrix: mat4x4 = globalUniform.projMat * globalUniform.viewMat ; var vertexPosition = vertex.position.xyz; + #if USE_METAHUMAN + ${MorphTarget_shader.getMorphTargetCalcVertex()} + #if USE_JOINT_VEC8 + worldMatrix *= getSkeletonWorldMatrix_8(vertex.joints0, vertex.weights0, vertex.joints1, vertex.weights1); + #else + worldMatrix *= getSkeletonWorldMatrix_4(vertex.joints0, vertex.weights0); + #endif + #endif + #if USE_MORPHTARGETS ${MorphTarget_shader.getMorphTargetCalcVertex()} #endif diff --git a/src/assets/shader/core/pass/SkyGBuffer_pass.ts b/src/assets/shader/core/pass/SkyGBuffer_pass.ts index 72add096..a7166de1 100644 --- a/src/assets/shader/core/pass/SkyGBuffer_pass.ts +++ b/src/assets/shader/core/pass/SkyGBuffer_pass.ts @@ -2,8 +2,9 @@ export let SkyGBuffer_pass: string = /*wgsl*/ ` #include "GlobalUniform" struct uniformData { + eyesPos: vec3, exposure: f32, - roughness: f32 + roughness: f32, }; struct FragmentOutput { @@ -21,14 +22,10 @@ var baseMap: texture_cube; var global: uniformData; fn LinearToGammaSpace(linRGB: vec3) -> vec3 { - var linRGB1: vec3; - linRGB1 = linRGB; - linRGB1 = max(linRGB1, vec3(0.0, 0.0, 0.0)); - linRGB1.x = pow(linRGB1.x, 0.4166666567325592); - linRGB1.y = pow(linRGB1.y, 0.4166666567325592); - linRGB1.z = pow(linRGB1.z, 0.4166666567325592); + var linRGB1 = max(linRGB, vec3(0.0)); + linRGB1 = pow(linRGB1, vec3(0.4166666567325592)); return max(((1.0549999475479126 * linRGB1) - vec3(0.054999999701976776)), vec3(0.0)); -} + } @fragment fn main(@location(0) fragUV: vec2, @location(1) vWorldPos: vec4, @location(2) vWorldNormal: vec3) -> FragmentOutput { diff --git a/src/assets/shader/core/struct/FragmentVarying.ts b/src/assets/shader/core/struct/FragmentVarying.ts index b3f36f66..8a0ccc99 100644 --- a/src/assets/shader/core/struct/FragmentVarying.ts +++ b/src/assets/shader/core/struct/FragmentVarying.ts @@ -1,20 +1,21 @@ export let FragmentVarying: string = /*wgsl*/ ` struct FragmentVarying { - @location(0) fragUV0: vec2, - @location(1) fragUV1: vec2, - @location(2) viewPosition: vec4, - @location(3) fragPosition: vec4, - @location(4) vWorldPos: vec4, - @location(5) vWorldNormal: vec3, - @location(6) vColor: vec4, + @location(0) index: f32, + @location(1) fragUV0: vec2, + @location(2) fragUV1: vec2, + @location(3) viewPosition: vec4, + @location(4) fragPosition: vec4, + @location(5) vWorldPos: vec4, + @location(6) vWorldNormal: vec3, + @location(7) vColor: vec4, #if USE_SHADOWMAPING - @location(7) vShadowPos: vec4, + @location(8) vShadowPos: vec4, #endif #if USE_TANGENT - @location(8) TANGENT: vec4, + @location(9) TANGENT: vec4, #endif @builtin(front_facing) face: bool, diff --git a/src/assets/shader/core/struct/ShadingInput.ts b/src/assets/shader/core/struct/ShadingInput.ts index 4d626624..77f76427 100644 --- a/src/assets/shader/core/struct/ShadingInput.ts +++ b/src/assets/shader/core/struct/ShadingInput.ts @@ -1,21 +1,29 @@ export let ShadingInput: string = /*wgsl*/ ` struct ShadingInput{ BaseColor:vec4, + Roughness:f32, Metallic:f32, Specular:f32, + EmissiveColor:vec4, SurfaceColor:vec4, + Normal:vec3, + HairNormal:vec3, Tangent:vec4, + WorldPositionOffset:vec3, AmbientOcclusion:f32, + PixelDepthOffset:f32, Opacity:f32, OpacityMask:f32, Refraction:f32, - FragDepth:f32 + FragDepth:f32, + + SSS:vec3f, } ` diff --git a/src/assets/shader/core/struct/VertexAttributeIndexShader.ts b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts new file mode 100644 index 00000000..99821333 --- /dev/null +++ b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts @@ -0,0 +1,86 @@ + +export let VertexAttributeIndexShader: string = /*wgsl*/ ` + #include "WorldMatrixUniform" + struct VertexAttributes{ + @builtin(instance_index) index : u32, + + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) TEXCOORD_1: vec2, + @location(4) vIndex: f32, + } + + struct VertexOutput { + @location(0) index: f32, + @location(1) varying_UV0: vec2, + @location(2) varying_UV1: vec2, + @location(3) varying_ViewPos: vec4, + @location(4) varying_Clip: vec4, + @location(5) varying_WPos: vec4, + @location(6) varying_WNormal: vec3, + @location(7) varying_Color: vec4, + #if USE_SHADOWMAPING + @location(8) varying_ShadowPos: vec4, + #endif + @builtin(position) member: vec4 + }; + + struct TransformVertex{ + position:vec3, + normal:vec3, + } + + struct GraphicNodeStruct{ + matrixIndex:f32, + texIndex:f32, + } + + var ORI_VertexOut: VertexOutput ; + var worldMatrix: mat4x4 ; + var graphicNode: GraphicNodeStruct ; + + fn ORI_Vert(vertex:VertexAttributes){ + var vertexPosition = vertex.position; + var vertexNormal = vertex.normal; + + ORI_VertexOut.index = f32(vertex.vIndex) ; + graphicNode = graphicBuffer[u32(round(vertex.vIndex))]; + let node_Matrix_M = models.matrix[u32(round(graphicNode.matrixIndex))]; + + #if USE_TANGENT + ORI_VertexOut.varying_Tangent = vertex.TANGENT ; + #endif + + ORI_MATRIX_M = node_Matrix_M * ORI_MATRIX_M ; + + #if USE_BILLBOARD + let billboardMatrix: mat3x3 = calculateBillboardMatrix2(globalUniform.CameraPos.xyz,ORI_MATRIX_M[3].xyz,globalUniform.cameraWorldMatrix[1].xyz); + vertexPosition = billboardMatrix * vertexPosition.xyz; + #endif + + worldMatrix = ORI_MATRIX_M ; + + let nMat = mat3x3(ORI_MATRIX_M[0].xyz,ORI_MATRIX_M[1].xyz,ORI_MATRIX_M[2].xyz) ; + ORI_NORMALMATRIX = transpose(inverse( nMat )); + + var worldPos = (ORI_MATRIX_M * vec4(vertexPosition.xyz, 1.0)); + + #if TRANSFORMVERTEX + var transformVertex = transformVertex(worldPos.xyz,vertexNormal,vertex); + worldPos = vec4(transformVertex.position ,worldPos.w); + vertexNormal = transformVertex.normal ; + #endif + + var viewPosition = ORI_MATRIX_V * worldPos; + var clipPosition = ORI_MATRIX_P * viewPosition ; + + ORI_VertexOut.varying_UV0 = vertex.uv.xy ; + ORI_VertexOut.varying_UV1 = vertex.TEXCOORD_1.xy; + ORI_VertexOut.varying_ViewPos = viewPosition / viewPosition.w; + ORI_VertexOut.varying_Clip = clipPosition; + ORI_VertexOut.varying_WPos = worldPos; + ORI_VertexOut.varying_WNormal = normalize( vertexNormal.xyz); + ORI_VertexOut.member = clipPosition ; + } +` \ No newline at end of file diff --git a/src/assets/shader/core/struct/VertexAttributes.ts b/src/assets/shader/core/struct/VertexAttributes.ts index 5ed5f5da..74031a90 100644 --- a/src/assets/shader/core/struct/VertexAttributes.ts +++ b/src/assets/shader/core/struct/VertexAttributes.ts @@ -2,60 +2,100 @@ import { SkeletonAnimation_shader } from "../../anim/SkeletonAnimation_shader"; import { MorphTarget_shader } from "../../../../components/anim/morphAnim/MorphTarget_shader"; export let VertexAttributes: string = /*wgsl*/ ` - #if USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetShaderBinding(3, 0)} - #endif + var PI: f32 = 3.14159265359; + #if USE_METAHUMAN + ${MorphTarget_shader.getMorphTargetShaderBinding(3, 0)} + ${SkeletonAnimation_shader.groupBindingAndFunctions(3, 2)} + #else + #if USE_MORPHTARGETS + ${MorphTarget_shader.getMorphTargetShaderBinding(3, 0)} + #endif - #if USE_SKELETON - ${SkeletonAnimation_shader.groupBindingAndFunctions(3, 0)} + #if USE_SKELETON + ${SkeletonAnimation_shader.groupBindingAndFunctions(3, 0)} + #endif #endif struct VertexAttributes{ - @builtin(instance_index) index : u32, - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) uv: vec2, - @location(3) TEXCOORD_1: vec2, + @builtin(instance_index) index : u32, + @location(0) position: vec3, + @location(1) normal: vec3, + @location(2) uv: vec2, + @location(3) TEXCOORD_1: vec2, + + #if USE_METAHUMAN + #if USE_TANGENT + @location(4) TANGENT: vec4, + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(9)} + #else + ${MorphTarget_shader.getMorphTargetAttr(7)} + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + ${MorphTarget_shader.getMorphTargetAttr(8)} + #else + ${MorphTarget_shader.getMorphTargetAttr(6)} + #endif + #endif + #else + #if USE_TANGENT + @location(4) TANGENT: vec4, + #endif + + #if USE_SKELETON + #if USE_TANGENT + @location(5) joints0: vec4, + @location(6) weights0: vec4, + #if USE_JOINT_VEC8 + @location(7) joints1: vec4, + @location(8) weights1: vec4, + #endif + #else + @location(4) joints0: vec4, + @location(5) weights0: vec4, + #if USE_JOINT_VEC8 + @location(6) joints1: vec4, + @location(7) weights1: vec4, + #endif + #endif + #endif + + #if USE_MORPHTARGETS + #if USE_TANGENT + ${MorphTarget_shader.getMorphTargetAttr(5)} + #else + ${MorphTarget_shader.getMorphTargetAttr(4)} + #endif + #endif - #if USE_TANGENT - @location(4) TANGENT: vec4, - #if USE_SKELETON - @location(5) joints0: vec4, - @location(6) weights0: vec4, - #if USE_JOINT_VEC8 - @location(7) joints1: vec4, - @location(8) weights1: vec4, - #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(5)} - #endif - #elseif USE_SKELETON - @location(4) joints0: vec4, - @location(5) weights0: vec4, - #if USE_JOINT_VEC8 - @location(6) joints1: vec4, - @location(7) weights1: vec4, #endif - #elseif USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetAttr(4)} - #endif } struct VertexOutput { - @location(0) varying_UV0: vec2, - @location(1) varying_UV1: vec2, - @location(2) varying_ViewPos: vec4, - @location(3) varying_Clip: vec4, - @location(4) varying_WPos: vec4, - @location(5) varying_WNormal: vec3, - @location(6) varying_Color: vec4, + @location(0) index: f32, + @location(1) varying_UV0: vec2, + @location(2) varying_UV1: vec2, + @location(3) varying_ViewPos: vec4, + @location(4) varying_Clip: vec4, + @location(5) varying_WPos: vec4, + @location(6) varying_WNormal: vec3, + @location(7) varying_Color: vec4, #if USE_SHADOWMAPING - @location(7) varying_ShadowPos: vec4, + @location(8) varying_ShadowPos: vec4, #endif #if USE_TANGENT - @location(8) varying_Tangent: vec4, + @location(9) varying_Tangent: vec4, #endif @builtin(position) member: vec4 @@ -67,11 +107,8 @@ export let VertexAttributes: string = /*wgsl*/ ` var vertexPosition = vertex.position; var vertexNormal = vertex.normal; - #if USE_MORPHTARGETS - ${MorphTarget_shader.getMorphTargetCalcVertex()} - #endif - - #if USE_SKELETON + #if USE_METAHUMAN + ${MorphTarget_shader.getMorphTargetCalcVertex()} #if USE_JOINT_VEC8 let skeletonNormal = getSkeletonWorldMatrix_8(vertex.joints0, vertex.weights0, vertex.joints1, vertex.weights1); ORI_MATRIX_M *= skeletonNormal ; @@ -79,13 +116,27 @@ export let VertexAttributes: string = /*wgsl*/ ` let skeletonNormal = getSkeletonWorldMatrix_4(vertex.joints0, vertex.weights0); ORI_MATRIX_M *= skeletonNormal ; #endif - #endif + #else + #if USE_MORPHTARGETS + ${MorphTarget_shader.getMorphTargetCalcVertex()} + #endif - #if USE_TANGENT - ORI_VertexOut.varying_Tangent = vertex.TANGENT ; + #if USE_SKELETON + #if USE_JOINT_VEC8 + let skeletonNormal = getSkeletonWorldMatrix_8(vertex.joints0, vertex.weights0, vertex.joints1, vertex.weights1); + ORI_MATRIX_M *= skeletonNormal ; + #else + let skeletonNormal = getSkeletonWorldMatrix_4(vertex.joints0, vertex.weights0); + ORI_MATRIX_M *= skeletonNormal ; + #endif + #endif #endif - + ORI_NORMALMATRIX = transpose(inverse( mat3x3(ORI_MATRIX_M[0].xyz,ORI_MATRIX_M[1].xyz,ORI_MATRIX_M[2].xyz) )); + + #if USE_TANGENT + ORI_VertexOut.varying_Tangent = vec4f(normalize(ORI_NORMALMATRIX * vertex.TANGENT.xyz),vertex.TANGENT.w) ; + #endif var worldPos = (ORI_MATRIX_M * vec4(vertexPosition.xyz, 1.0)); var viewPosition = ORI_MATRIX_V * worldPos; @@ -93,8 +144,12 @@ export let VertexAttributes: string = /*wgsl*/ ` ORI_CameraWorldDir = normalize(ORI_CAMERAMATRIX[3].xyz - worldPos.xyz) ; + ORI_VertexOut.index = f32(vertex.index) ; + ORI_VertexOut.varying_UV0 = vertex.uv.xy ; + ORI_VertexOut.varying_UV1 = vertex.TEXCOORD_1.xy; + ORI_VertexOut.varying_ViewPos = viewPosition ; ORI_VertexOut.varying_Clip = clipPosition ; ORI_VertexOut.varying_WPos = worldPos ; diff --git a/src/assets/shader/lighting/BRDF_frag.ts b/src/assets/shader/lighting/BRDF_frag.ts index 99f04012..20154d19 100644 --- a/src/assets/shader/lighting/BRDF_frag.ts +++ b/src/assets/shader/lighting/BRDF_frag.ts @@ -11,15 +11,19 @@ export let BRDF_frag: string = /*wgsl*/ ` Albedo: vec4, Emissive: vec3, + Specular: vec3, N: vec3, V: vec3, R: vec3, + T: vec3, F0: vec3, F: vec3, KS: vec3, KD: vec3, + + Alpha: f32, Shadow: f32, Indirect: f32, Reflectance: f32, @@ -31,8 +35,7 @@ export let BRDF_frag: string = /*wgsl*/ ` EnvColor: vec3, Irradiance: vec3, - LightChannel: vec3, - TangentChannel: vec3, + LightChannel: vec3 }; var fragData: FragData; @@ -43,23 +46,19 @@ export let BRDF_frag: string = /*wgsl*/ ` NoL : f32 , VoL : f32 , NoH : f32 , + HoL : f32 , VoH : f32 }; fn getContext( N:vec3, V:vec3, H:vec3, L:vec3 ) -> BxDFContext { var Context:BxDFContext ; - Context.NoL = saturate(dot(N, L)) ; - Context.NoV = saturate(dot(N, V)) ; - Context.VoL = saturate(dot(V, L)) ; + Context.NoL = saturate(dot(N, L)); + Context.NoV = saturate(dot(N, V)); + Context.VoL = saturate(dot(V, L)); Context.NoH = saturate(dot(N, H)); Context.VoH = saturate(dot(V, H)); - - // Context.NoL = max(dot(N, L),0.0); - // Context.NoV = max(dot(N, V),0.0); - // Context.VoL = max(dot(V, L),0.0) ; - // Context.NoH = saturate(dot(N, H)); - // Context.VoH = max(dot(V, H),0.0); + Context.HoL = saturate(dot(H, L)); return Context ; } @@ -219,24 +218,30 @@ export let BRDF_frag: string = /*wgsl*/ ` fn simpleBRDF( albedo:vec3, N:vec3, V:vec3,L:vec3,att:f32,lightColor:vec3,roughness:f32 ,metallic:f32)-> vec3{ let H = normalize(V + L); let Context:BxDFContext = getContext(N,V,H,L); - + let alpha = roughness ;//pow(roughness,5.0) ; let F0 = mix(vec3(materialUniform.materialF0.rgb), albedo , metallic); - let D = DistributionGGX( Context.NoH , roughness); - let G = GeometrySmith(Context.NoV,Context.NoL, roughness ); + let D = DistributionGGX( Context.NoH , alpha); + let G = GeometrySmith(Context.NoV,Context.NoL, alpha ); let F = FresnelSchlick(Context.VoH, vec3(F0)); let specular = ( D * G * F ) / (4.0 * Context.NoV * Context.NoL + 0.001); - let kS = F; + + // let kS = exp2( (-5.55473 * Context.HoL - 6.98316) * Context.HoL ); + let kS = F ; var kd = 1.0 - kS ; kd *= 1.0 - metallic ; - var diffuse = kd * (albedo.rgb / PI ) ; - let ambient = specular.rgb ; - fragData.KD += kd; - fragData.KS += F; + #if USE_SRGB_ALBEDO + var diffuse = kd ; + #else + var diffuse = kd * (albedo.rgb / PI ) ; + #endif - var col = (diffuse + ambient) * Context.NoL * lightColor * att ; - // var col = (diffuse + ambient) * Context.NoL * lightColor ; - return (col.rgb ) ; + let lightAtt = Context.NoL * lightColor * att ; + var diffuseColor = diffuse * lightAtt; + // diffuseColor = vec3f(0.0) ; + var specularColor = specular * lightAtt; + var col = (diffuseColor + specularColor ) ; + return (col.rgb) ; } fn getSpecularDominantDir ( N : vec3 , R : vec3 , roughness : f32 ) -> vec3 @@ -251,10 +256,11 @@ export let BRDF_frag: string = /*wgsl*/ ` let MAX_REFLECTION_LOD = i32(textureNumLevels(prefilterMap)) ; let mip = roughnessToMipmapLevel(roughness,MAX_REFLECTION_LOD); - var prefilteredColor: vec3 = (textureSampleLevel(prefilterMap, prefilterMapSampler, getSpecularDominantDir(fragData.N,R,roughness) , mip ).rgb); - prefilteredColor = globalUniform.skyExposure * (prefilteredColor); + fragData.EnvColor = (textureSampleLevel(prefilterMap, prefilterMapSampler, getSpecularDominantDir(fragData.N,R,roughness) , mip ).rgb); + // var prefilteredColor: vec3 = (textureSampleLevel(prefilterMap, prefilterMapSampler, getSpecularDominantDir(fragData.N,R,roughness) , mip ).rgb); + fragData.EnvColor = globalUniform.skyExposure * (fragData.EnvColor); var envBRDF = textureSampleLevel(brdflutMap, brdflutMapSampler, vec2(NoV, roughness) , 0.0 ) ; - return prefilteredColor * (specularColor.rgb * envBRDF.x + saturate( 50.0 * specularColor.g ) * envBRDF.y) ; + return fragData.EnvColor * (specularColor.rgb * envBRDF.x + saturate( 50.0 * specularColor.g ) * envBRDF.y) ; } fn fresnel_coat(n:vec3,v:vec3,ior:f32) -> f32 { @@ -347,5 +353,25 @@ export let BRDF_frag: string = /*wgsl*/ ` } #endif + + fn EnvBRDF( SpecularColor : vec3f , Roughness : f32 , NoV : f32) -> vec3f + { + // brdflutMap, brdflutMapSampler + var AB = textureSampleLevel( brdflutMap, brdflutMapSampler, vec2f( NoV, Roughness ), 0.0 ).rg; + var GF = SpecularColor * AB.x + saturate( 50.0 * SpecularColor.g ) * AB.y; + return GF; + } + + fn IBLEnv( V:vec3f , N:vec3f , Roughness : f32) -> vec3f + { + let NdotV = max(dot(N,V),0.0); + let MAX_REFLECTION_LOD = i32(textureNumLevels(prefilterMap)); + + let mip = roughnessToMipmapLevel(Roughness,MAX_REFLECTION_LOD); + + let R = 2.0 * dot( V , N ) * N - V ; + var envIBL: vec3 = textureSampleLevel(prefilterMap, prefilterMapSampler, R , mip ).rgb ; + return envIBL; + } ` diff --git a/src/assets/shader/lighting/BsDF_frag.ts b/src/assets/shader/lighting/BsDF_frag.ts new file mode 100644 index 00000000..5cab6294 --- /dev/null +++ b/src/assets/shader/lighting/BsDF_frag.ts @@ -0,0 +1,154 @@ +export let BsDF_frag: string = /*wgsl*/ ` + #include "Clearcoat_frag" + #include "BRDF_frag" + #include "MathShader" + #include "FastMathShader" + #include "Common_frag" + #include "GlobalUniform" + + #include "PhysicMaterialUniform_frag" + #include "NormalMap_frag" + #include "LightingFunction_frag" + #include "Irradiance_frag" + #include "ColorUtil_frag" + #include "BxdfDebug_frag" + + + + //ORI_ShadingInput + fn initFragData() { + fragData.Albedo = ORI_ShadingInput.BaseColor ; + fragData.Ao = clamp( pow(ORI_ShadingInput.AmbientOcclusion,materialUniform.ao) , 0.0 , 1.0 ) ; + fragData.Roughness = clamp((ORI_ShadingInput.Roughness),0.003,1.0) ; + fragData.Metallic = ORI_ShadingInput.Metallic ; + fragData.Emissive = ORI_ShadingInput.EmissiveColor.rgb ; + fragData.N = ORI_ShadingInput.Normal; + let viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; + fragData.V = viewDir ; + #if USE_TANGENT + fragData.T = ORI_VertexVarying.TANGENT.xyz ; + #endif + + let R = 2.0 * dot( fragData.V , fragData.N ) * fragData.N - fragData.V ; + fragData.R = R ;//reflect( fragData.V , fragData.N ) ; + + fragData.NoV = saturate(dot(fragData.N, fragData.V)) ; + + fragData.F0 = mix(vec3(materialUniform.specularColor.rgb), fragData.Albedo.rgb, fragData.Metallic); + + fragData.F = computeFresnelSchlick(fragData.NoV, fragData.F0); + fragData.KD = vec3(fragData.F) ; + fragData.KS = vec3(0.0) ; + + fragData.Indirect = 0.0 ; + fragData.Reflectance = 1.0 ; + + fragData.ClearcoatRoughness = materialUniform.clearcoatRoughnessFactor ; + #if USE_CLEARCOAT_ROUGHNESS + fragData.ClearcoatRoughness = getClearcoatRoughness() * materialUniform.clearcoatRoughnessFactor; + #endif + } + + fn BsDFShading(){ + initFragData(); + + var irradiance = vec3(0.0) ; + #if USEGI + irradiance += getIrradiance().rgb ; + #else + let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + irradiance += (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, fragData.N.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); + #endif + irradiance = ORI_ShadingInput.SSS + LinearToGammaSpace(irradiance.rgb); + fragData.Irradiance = irradiance.rgb ; + + + + //***********lighting-PBR part********* + var specColor = vec3(0.0) ; + let lightIndex = getCluster(); + let start = max(lightIndex.start, 0.0); + let count = max(lightIndex.count, 0.0); + let end = max(start + count , 0.0); + for(var i:i32 = i32(start) ; i < i32(end); i += 1 ) + { + let light = getLight(i32(i)); + switch (light.lightType) { + case PointLightType: { + specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + } + case DirectLightType: { + specColor += directDulLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; + } + case SpotLightType: { + specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; + } + default: { + } + } + } + + + fragData.LightChannel = specColor ; + + let sunLight = lightBuffer[0] ; + //***********lighting-PBR part********* + var F = FresnelSchlickRoughness(fragData.NoV, fragData.F0, fragData.Roughness); + var kS = F; + var kD = vec3(1.0) - kS; + kD = kD * (1.0 - fragData.Metallic); + let envIBL = materialUniform.envIntensity * approximateSpecularIBL( F , fragData.Roughness , fragData.R , fragData.NoV ) ; + fragData.EnvColor = envIBL ; + //***********indirect-specular part********* + + var surfaceReduction = 1.0/(fragData.Roughness*fragData.Roughness+1.0); + var oneMinusReflectivity = oneMinusReflectivity(fragData.Metallic , materialUniform.materialF0.r ); + var grazingTerm = clamp((1.0 - fragData.Roughness ) + (1.0 - oneMinusReflectivity),0.0,1.0); + var t = pow5(fragData.NoV); + var fresnelLerp = FresnelLerp(fragData.NoV,fragData.F0.rgb,vec3(grazingTerm)) ; + var iblSpecularResult = surfaceReduction * fragData.EnvColor * fresnelLerp + envIBL; + iblSpecularResult *= max(sunLight.quadratic,0.05) ; + //***********indirect-specular part********* + + //***********indirect-ambient part********* + var kdLast = (1.0 - fragData.F0.r) * (1.0 - fragData.Metallic); + // Dim the edges, there should be more specular reflection at the edges + var iblDiffuseResult = irradiance * 2.0 * kdLast * fragData.Albedo.rgb * (vec3(1.0) - kS) ; + //irradiance + //***********indirect-ambient part********* + var indirectResult = (iblSpecularResult + iblDiffuseResult) * fragData.Ao * max(sunLight.quadratic,0.05); + // debugOut = vec4f(iblDiffuseResult,1.0); + + ORI_FragmentOutput.color = vec4(0.0); + + // Using stripped down, 'pure log', formula. Parameterized by grey points and dynamic range covered. + #if USEGBUFFER + var normal_rgba8unorm = (ORI_VertexVarying.vWorldNormal + 1.0) * 0.5; + normal_rgba8unorm = clamp(normal_rgba8unorm, vec3(0.0), vec3(1.0)); + ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); + ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); + #endif + + #if USE_WORLDPOS + ORI_FragmentOutput.worldPos = vec4(ORI_VertexVarying.vWorldPos.xyzw); + #endif + + var color = specColor + indirectResult ; + color += fragData.Emissive.xyz ; + + var clearCoatColor = vec3(0.0); + #if USE_CLEARCOAT + let clearCoatBaseColor = vec3(1.0) * materialUniform.baseColor.rgb ; + let clearNormal = fragData.N ; + let clearcoatRoughness = fragData.ClearcoatRoughness ; + let att = sunLight.intensity / LUMEN ; + let clearCoatLayer = ClearCoat_BRDF( color , materialUniform.clearcoatColor.rgb , materialUniform.ior , clearNormal , -sunLight.direction ,-fragData.V , materialUniform.clearcoatWeight , clearcoatRoughness , att ); + color = vec3(clearCoatLayer.rgb/fragData.Albedo.a) ; + #endif + + let retColor = (LinearToGammaSpace(color.rgb)); + ORI_FragmentOutput.color = vec4( retColor ,fragData.Albedo.a) ; + } + + ` + diff --git a/src/assets/shader/lighting/BxDF_frag.ts b/src/assets/shader/lighting/BxDF_frag.ts index 33e98c2e..d2d39a73 100644 --- a/src/assets/shader/lighting/BxDF_frag.ts +++ b/src/assets/shader/lighting/BxDF_frag.ts @@ -17,22 +17,25 @@ export let BxDF_frag: string = /*wgsl*/ ` //ORI_ShadingInput fn initFragData() { - fragData.Albedo = ORI_ShadingInput.BaseColor * ORI_ShadingInput.BaseColor.a ; - fragData.Ao = ORI_ShadingInput.AmbientOcclusion ; - fragData.Roughness = clamp(ORI_ShadingInput.Roughness,0.003,1.0) ; + fragData.Albedo = ORI_ShadingInput.BaseColor ; + fragData.Ao = clamp( pow(ORI_ShadingInput.AmbientOcclusion,materialUniform.ao) , 0.0 , 1.0 ) ; + fragData.Roughness = clamp((ORI_ShadingInput.Roughness),0.003,1.0) ; fragData.Metallic = ORI_ShadingInput.Metallic ; fragData.Emissive = ORI_ShadingInput.EmissiveColor.rgb ; fragData.N = ORI_ShadingInput.Normal; let viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz) ; fragData.V = viewDir ; - // fragData.V = normalize(globalUniform.cameraWorldMatrix[3].xyz - ORI_VertexVarying.vWorldPos.xyz) ; + #if USE_TANGENT + fragData.T = ORI_VertexVarying.TANGENT.xyz * ORI_VertexVarying.TANGENT.w ; + #endif + let R = 2.0 * dot( fragData.V , fragData.N ) * fragData.N - fragData.V ; fragData.R = R ;//reflect( fragData.V , fragData.N ) ; fragData.NoV = saturate(dot(fragData.N, fragData.V)) ; - fragData.F0 = mix(vec3(materialUniform.materialF0.rgb), fragData.Albedo.rgb, fragData.Metallic); + fragData.F0 = mix(vec3(materialUniform.specularColor.rgb), fragData.Albedo.rgb, fragData.Metallic); fragData.F = computeFresnelSchlick(fragData.NoV, fragData.F0); fragData.KD = vec3(fragData.F) ; @@ -60,9 +63,6 @@ export let BxDF_frag: string = /*wgsl*/ ` irradiance = LinearToGammaSpace(irradiance.rgb); fragData.Irradiance = irradiance.rgb ; - #if USE_TANGENT - fragData.TangentChannel = vec3(ORI_VertexVarying.TANGENT.w);// ORI_VertexVarying.TANGENT.xyz * ORI_VertexVarying.TANGENT.w ; - #endif //***********lighting-PBR part********* var specColor = vec3(0.0) ; @@ -72,66 +72,65 @@ export let BxDF_frag: string = /*wgsl*/ ` let end = max(start + count , 0.0); for(var i:i32 = i32(start) ; i < i32(end); i += 1 ) { - let light = getLight(i32(i)); - - switch (light.lightType) { - case PointLightType: { - specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + let light = getLight(i32(i)); + switch (light.lightType) { + case PointLightType: { + specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + } + case DirectLightType: { + specColor += directLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; + } + case SpotLightType: { + specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; + } + default: { + } } - case DirectLightType: { - specColor += directLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; - } - case SpotLightType: { - specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; - } - default: { - } - } } - fragData.LightChannel = specColor ; + fragData.LightChannel = specColor ; + let sunLight = lightBuffer[0] ; //***********lighting-PBR part********* var F = FresnelSchlickRoughness(fragData.NoV, fragData.F0, fragData.Roughness); var kS = F; var kD = vec3(1.0) - kS; kD = kD * (1.0 - fragData.Metallic); - let env = materialUniform.envIntensity * approximateSpecularIBL( F , fragData.Roughness , fragData.R , fragData.NoV ) ; - fragData.EnvColor = env ; + let envIBL = materialUniform.envIntensity * approximateSpecularIBL( F , fragData.Roughness , fragData.R , fragData.NoV ) ; + fragData.EnvColor = envIBL ; //***********indirect-specular part********* - var surfaceReduction = 1.0/(fragData.Roughness*fragData.Roughness+1.0); //Reduce the reflection coefficient of non-metallic materials - var oneMinusReflectivity = oneMinusReflectivity(fragData.Metallic , materialUniform.materialF0.r );// materialUniform.materialF0.a - materialUniform.materialF0.a * fragData.Metallic ; + var surfaceReduction = 1.0/(fragData.Roughness*fragData.Roughness+1.0); + var oneMinusReflectivity = oneMinusReflectivity(fragData.Metallic , materialUniform.materialF0.r ); var grazingTerm = clamp((1.0 - fragData.Roughness ) + (1.0 - oneMinusReflectivity),0.0,1.0); var t = pow5(fragData.NoV); - var fresnelLerp = FresnelLerp(fragData.NoV,fragData.F0.rgb,vec3(grazingTerm)) ; //Controlling Fresnel and metallic reflections - var iblSpecularResult = surfaceReduction*env*fresnelLerp ; + var fresnelLerp = FresnelLerp(fragData.NoV,fragData.F0.rgb,vec3(grazingTerm)) ; + var iblSpecularResult = surfaceReduction * fragData.EnvColor * fresnelLerp + envIBL; + iblSpecularResult *= max(sunLight.quadratic,0.05) ; //***********indirect-specular part********* //***********indirect-ambient part********* - var kdLast = (1.0 - fragData.F0.r) * (1.0 - fragData.Metallic); //Dim the edges, there should be more specular reflection at the edges - var iblDiffuseResult = irradiance * kdLast * fragData.Albedo.rgb ; + var kdLast = (1.0 - 0.04) * (1.0 - fragData.Metallic); + // Dim the edges, there should be more specular reflection at the edges + var iblDiffuseResult = irradiance * vec3f(kdLast) * fragData.Albedo.rgb ; + //irradiance //***********indirect-ambient part********* - let sunLight = lightBuffer[0] ; - var indirectResult = (iblSpecularResult + iblDiffuseResult) * fragData.Ao * max(sunLight.quadratic,0.05) ; - // let test = indirectResult ; + var indirectResult = (iblSpecularResult + iblDiffuseResult) * fragData.Ao * max(sunLight.quadratic,0.05); + // debugOut = vec4f(iblDiffuseResult,1.0); ORI_FragmentOutput.color = vec4(0.0); // Using stripped down, 'pure log', formula. Parameterized by grey points and dynamic range covered. #if USEGBUFFER var normal_rgba8unorm = (ORI_VertexVarying.vWorldNormal + 1.0) * 0.5; - normal_rgba8unorm = clamp(normal_rgba8unorm, vec3(0.0), vec3(1.0)); + ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); + ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); #endif // ORI_FragmentOutput.color = vec4(ORI_FragmentOutput.color.xyz,fragData.Albedo.a) ; #if USE_WORLDPOS ORI_FragmentOutput.worldPos = vec4(ORI_VertexVarying.vWorldPos.xyzw); - #endif - - #if USEGBUFFER - ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); - ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); + // ORI_FragmentOutput.worldPos = vec4(0.0,0.0,1.0,1.0); #endif var color = specColor + indirectResult ; @@ -147,10 +146,10 @@ export let BxDF_frag: string = /*wgsl*/ ` color = vec3(clearCoatLayer.rgb/fragData.Albedo.a) ; #endif - ORI_FragmentOutput.color = vec4(LinearToGammaSpace(color.rgb),fragData.Albedo.a) ; - - // var iblSpecularResult = surfaceReduction*env*fresnelLerp ; - // ORI_FragmentOutput.color = vec4(vec3(test),fragData.Albedo.a) ; + var retColor = (LinearToGammaSpace(color.rgb)); + // retColor += fragData.Emissive.xyz ; + // ORI_FragmentOutput.color = vec4( irradiance * min(fragData.Albedo.rgb,vec3f(1.0)) ,fragData.Albedo.a) ; + ORI_FragmentOutput.color = vec4( retColor.rgb * fragData.Albedo.a ,fragData.Albedo.a) ; } ` diff --git a/src/assets/shader/lighting/Hair_frag.ts b/src/assets/shader/lighting/Hair_frag.ts new file mode 100644 index 00000000..42b116d5 --- /dev/null +++ b/src/assets/shader/lighting/Hair_frag.ts @@ -0,0 +1,326 @@ +export let Hair_frag: string = /*wgsl*/ ` + #include "BRDF_frag" + #include "MathShader" + #include "FastMathShader" + #include "Common_frag" + #include "GlobalUniform" + + #include "PhysicMaterialUniform_frag" + #include "NormalMap_frag" + #include "LightingFunction_frag" + #include "Irradiance_frag" + #include "ColorUtil_frag" + #include "BxdfDebug_frag" + + struct FHairTransmittanceData{ + bUseBacklit:bool, + bUseSeparableR:bool, + bUseLegacyAbsorption:bool + }; + + //ORI_ShadingInput + fn initFragData() { + fragData.Albedo = ORI_ShadingInput.BaseColor ; + fragData.Ao = clamp( pow(ORI_ShadingInput.AmbientOcclusion,materialUniform.ao) , 0.0 , 1.0 ) ; + fragData.Roughness = ORI_ShadingInput.Roughness ; + fragData.Metallic = ORI_ShadingInput.Metallic ; + fragData.Emissive = ORI_ShadingInput.EmissiveColor.rgb ; + fragData.Specular = vec3f(materialUniform.specularColor.rgb) ; + fragData.N = ORI_ShadingInput.Normal; + let viewDir = normalize(globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz ) ; + fragData.V = viewDir ; + fragData.Ao = materialUniform.ao ; + #if USE_TANGENT + fragData.T = ORI_VertexVarying.TANGENT.xyz * ORI_VertexVarying.TANGENT.w ; + #endif + + let R = 2.0 * dot( fragData.V , fragData.N ) * fragData.N - fragData.V ; + fragData.R = R ;//reflect( fragData.V , fragData.N ) ; + + fragData.NoV = saturate(dot(fragData.N, fragData.V)) ; + + fragData.F0 = mix(vec3(materialUniform.specularColor.rgb), fragData.Albedo.rgb, fragData.Metallic); + + fragData.F = computeFresnelSchlick(fragData.NoV, fragData.F0); + fragData.KD = vec3(fragData.F) ; + fragData.KS = vec3(0.0) ; + + fragData.Indirect = 0.0 ; + fragData.Reflectance = 1.0 ; + } + + + + fn transformHairNormal(normal : vec3) -> vec3{ + var face = 1.0 ; + if(ORI_VertexVarying.face){ + face = 1.0 ; + }else{ + face = -1.0 ; + } + #if USE_TANGENT + let T = ORI_VertexVarying.TANGENT.xyz; + let N = ORI_VertexVarying.vWorldNormal ; + let B = cross(T,N) * ORI_VertexVarying.TANGENT.w * face; + let mat3 = mat3x3(T,B,N); + let n = mat3 * normal; + return n ; + #else + return normal ; + #endif + } + + + fn Hair_g( B:f32 , Theta:f32 ) -> f32 + { + return exp(-0.5 * pow2(Theta) / (B * B)) / (sqrt(2 * PI) * B); + } + + fn Hair_F( CosTheta:f32 )-> f32 + { + let n = 1.55; + let F0 = pow2((1.0 - n) / (1.0 + n)); + return F0 + (1.0 - F0) * pow5(1.0 - CosTheta); + } + + fn HairColorToAbsorption( C:vec3f , B:f32 ) -> vec3f + { + let b2 = B * B; + let b3 = B * b2; + let b4 = b2 * b2; + let b5 = B * b4; + let D = (5.969 - 0.215 * B + 2.532 * b2 - 10.73 * b3 + 5.574 * b4 + 0.245 * b5); + return pow2v3(log(C) / D); + } + + fn Luminance( LinearColor : vec3f ) -> f32 + { + return dot( LinearColor, vec3f( 0.3, 0.59, 0.11 ) ); + } + + fn KajiyaKayDiffuseAttenuation( L:vec3f, V:vec3f, N:vec3f, Shadow:f32 ) -> vec3f + { + // Use soft Kajiya Kay diffuse attenuation + var KajiyaDiffuse = 1.0 - abs(dot(N, L)); + + var FakeNormal = normalize(V - N * dot(V, N)); + //N = normalize( DiffuseN + FakeNormal * 2 ); + let nN = FakeNormal; + + let BaseColor = fragData.Albedo.rgb / PI ; + // Hack approximation for multiple scattering. + var Wrap = 1.0; + var NoL = saturate((dot(nN, L) + Wrap) / squareF(1.0 + Wrap)); + var DiffuseScatter = (1.0 / PI) * mix(NoL, KajiyaDiffuse, 0.33) * fragData.Metallic; + var Luma = Luminance(BaseColor); + var ScatterTint = pow(BaseColor / Luma, vec3f(1.0 - Shadow)); + return sqrt(BaseColor) * DiffuseScatter * ScatterTint; + } + + fn HairNormal( ID : f32 ) -> vec4f { + let tangentA = vec4f(0.0,0.0,0.3,1.0); + let tangentB = vec4f(0.0,0.0,-0.3,1.0); + + let iTangent = mix(tangentA,tangentB,vec4f(ID)); + var tangent = vec4f(0.0); + #if USE_FLOWER + + #else + let tt = vec4f(0.0,-1.0,0.0,1.0); + tangent = tt + iTangent; + #endif + + return normalize(tangent) ; + } + + fn hairShading( light:LightData , sV:vec3f, N:vec3f, Shadow:f32 , HairTransmittance : FHairTransmittanceData , InBacklit:f32 , Area:f32 , Random:vec2f ) -> vec3f{ + var ClampedRoughness = clamp(fragData.Roughness, 1/255.0, 1.0); + let Backlit = min(InBacklit, materialUniform.backlit); + let HairColor = fragData.Albedo.rgb ; + let lightCC = pow( light.lightColor.rgb,vec3(2.2)); + var lightColor = getHDRColor( lightCC.rgb , light.linear ) ; + var lightAtt = light.intensity ; + + let V = normalize(sV) ; + let L = normalize(-light.direction) ; + let H = normalize(N+L) ; + var S : vec3f= vec3f(0.0) ; + + var KajiyaKayDiffuseFactor = 1.0; + + let VoL = dot(V,L); + let SinThetaL = clamp(dot(N,L), -1.0, 1.0); + let SinThetaV = clamp(dot(N,V), -1.0, 1.0); + + var CosThetaD = cos( 0.5 * abs( asinFast( SinThetaV ) - asinFast( SinThetaL ) ) ); + // var CosThetaD = cos( 0.5 * abs( asin( SinThetaV ) - asin( SinThetaL ) ) ); + + var Lp = L - SinThetaL * N; + var Vp = V - SinThetaV * N; + var CosPhi = dot(Lp,Vp) * rsqrt( dot(Lp,Lp) * dot(Vp,Vp) + 1e-4 ); + var CosHalfPhi = sqrt( saturate( 0.5 + 0.5 * CosPhi ) ); + + let n = 1.55; + let n_prime = 1.19 / CosThetaD + 0.36 * CosThetaD; + + let Shift = 0.035; + var Alpha:array = array( + -Shift * 2.0, + Shift, + Shift * 4.0, + ); + + var B:array =array( + Area + pow2(ClampedRoughness), + (Area + pow2(ClampedRoughness) / 2.0), + Area + pow2(ClampedRoughness) * 2.0, + ); + + //S SR + let sa = sin(Alpha[0]); + let ca = cos(Alpha[0]); + var ShiftA = 2.0 * sa * (ca * CosHalfPhi * sqrt(1.0 - SinThetaV * SinThetaV) + sa * SinThetaV); + var BScale = 1.0; + if(HairTransmittance.bUseSeparableR){ + BScale = sqrt(2.0) * CosHalfPhi ; + } + var Mp_R = Hair_g(B[0] * BScale, SinThetaL + SinThetaV - ShiftA); + var Np_R = 0.25 * CosHalfPhi; + var Fp_R = Hair_F(sqrt(saturate(0.5 + 0.5 * (VoL)))); + S += vec3f(Mp_R* Np_R * Fp_R * (fragData.F0 * 2.0)) * mix(1.0, 0.0, saturate(-VoL)); + KajiyaKayDiffuseFactor -= Fp_R; + + //S ST + var Mp_ST = Hair_g( B[1], SinThetaL + SinThetaV - Alpha[1] ); + var a_ST = 1.0 / n_prime; + var h_ST = CosHalfPhi * ( 1.0 + a_ST * ( 0.6 - 0.8 * CosPhi ) ); + var f_ST = Hair_F( CosThetaD * sqrt( saturate( 1.0 - h_ST * h_ST ) ) ); + var Fp_ST = pow2(1.0 - f_ST); + var Tp_ST : vec3f = vec3f( 0.0 ); + if (HairTransmittance.bUseLegacyAbsorption) + { + Tp_ST = pow(HairColor.rgb, vec3f(0.5 * sqrt(1.0 - pow2(h_ST * a_ST)) / CosThetaD)); + } + else + { + let AbsorptionColor = HairColorToAbsorption(HairColor.rgb,0.3); + Tp_ST = exp(-AbsorptionColor * 2.0 * abs(1.0 - pow2(h_ST * a_ST) / CosThetaD)); + } + + var Np_ST = exp( -3.65 * CosPhi - 3.98 ); + + S += Mp_ST * Np_ST * Fp_ST * Tp_ST * Backlit; + KajiyaKayDiffuseFactor -= Fp_ST; + + //S TRT + var Mp_TRT = Hair_g( B[2], SinThetaL + SinThetaV - Alpha[2] ); + + //float h = 0.75; + var f_TRT = Hair_F( CosThetaD * 0.5 ); + var Fp_TRT = pow2(1.0 - f_TRT) * f_TRT; + var Tp_TRT = pow( HairColor.rgb , vec3f(0.8 / CosThetaD) ); + var Np_TRT = exp( 17.0 * CosPhi - 16.78 ); + + S += Mp_TRT * Np_TRT * Fp_TRT * Tp_TRT; + KajiyaKayDiffuseFactor -= Fp_TRT; + // S = vec3f((KajiyaKayDiffuseFactor)); + + S += KajiyaKayDiffuseAttenuation(L,V,N,Shadow) ;//* saturate(KajiyaKayDiffuseFactor); + // S = vec3f((KajiyaKayDiffuseFactor)); + S = -min(-S, vec3f(0.0)); + return 2.0 * PI *vec3f(S) * (lightAtt / LUMEN) ; + } + + fn BSSSRDFShading(){ + initFragData(); + + var irradiance = vec3(0.0) ; + #if USEGI + irradiance += getIrradiance().rgb ; + #else + let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + irradiance += (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, fragData.N.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); + #endif + irradiance = ORI_ShadingInput.SSS + (irradiance.rgb); + fragData.Irradiance = irradiance.rgb ; + + //***********lighting-PBR part********* + var specColor = vec3(0.0) ; + let lightIndex = getCluster(); + let start = max(lightIndex.start, 0.0); + let count = max(lightIndex.count, 0.0); + let end = max(start + count , 0.0); + for(var i:i32 = i32(start) ; i < i32(end); i += 1 ) + { + let light = getLight(i32(i)); + switch (light.lightType) { + case PointLightType: { + // specColor += pointLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic,light) ; + } + case DirectLightType: { + // specColor += directHairLighting( fragData.Albedo.rgb ,fragData.N,fragData.V,fragData.Roughness ,fragData.Metallic, light , globalUniform.shadowBias) ; + var fHairTransmittanceData : FHairTransmittanceData ; + fHairTransmittanceData.bUseBacklit = true ; + fHairTransmittanceData.bUseSeparableR = true ; + fHairTransmittanceData.bUseLegacyAbsorption = false ; + + //use shadow visible backlit + // var shadow = 0.0 ; + // if(light.castShadow>=0){ + // #if USE_SHADOWMAPING + // shadow = shadowStrut.directShadowVisibility[i32(light.castShadow)] ; + // #endif + // } + + specColor = hairShading(light,fragData.V, ORI_ShadingInput.HairNormal , 1.0 ,fHairTransmittanceData,1.0,materialUniform.area,vec2f(0.0)); + } + case SpotLightType: { + // specColor += spotLighting( fragData.Albedo.rgb,ORI_VertexVarying.vWorldPos.xyz,fragData.N,fragData.V,fragData.Roughness,fragData.Metallic , light ) ; + } + default: { + } + } + } + + + let sunLight = lightBuffer[0] ; + //***********lighting-PBR part********* + var F = FresnelSchlickRoughness(fragData.NoV, fragData.F0.rgb , fragData.Roughness); + var kS = F; + // var kD = vec3(1.0) - kS; + // kD = kD * (1.0 - fragData.Metallic); + let envIBL = materialUniform.envIntensity * IBLEnv(fragData.V ,fragData.N ,fragData.Roughness ) ; + fragData.EnvColor = envIBL ; + // fragData.Specular = envIBL ; + //***********indirect-specular part********* + + var iblSpecularResult = fragData.Metallic * fragData.EnvColor * materialUniform.specularColor.rgb ; + //***********indirect-specular part********* + + //***********indirect-ambient part********* + var kdLast = (1.0 - fragData.F0.r) * (1.0 - fragData.Metallic); + var iblDiffuseResult = irradiance * kdLast * fragData.Albedo.rgb * (vec3(1.0) - kS) ; + //irradiance + //***********indirect-ambient part********* + var indirectResult = (iblSpecularResult + iblDiffuseResult * max(sunLight.quadratic,0.05) ) * fragData.Ao ; + fragData.LightChannel = specColor ; + + // Using stripped down, 'pure log', formula. Parameterized by grey points and dynamic range covered. + #if USEGBUFFER + var normal_rgba8unorm = (ORI_VertexVarying.vWorldNormal + 1.0) * 0.5; + normal_rgba8unorm = clamp(normal_rgba8unorm, vec3(0.0), vec3(1.0)); + ORI_FragmentOutput.worldNormal = vec4(normal_rgba8unorm,1.0); + ORI_FragmentOutput.material = vec4(1.0,fragData.Roughness,fragData.Metallic,1.0); + #endif + + #if USE_WORLDPOS + ORI_FragmentOutput.worldPos = vec4(ORI_VertexVarying.vWorldPos.xyzw); + #endif + + let finalColor = LinearToGammaSpace(vec3f(specColor + indirectResult) ) ; + ORI_FragmentOutput.color = vec4( finalColor ,fragData.Albedo.a) ; + // ORI_FragmentOutput.color = vec4( vec3f(specColor) ,fragData.Albedo.a) ; +} + + ` + diff --git a/src/assets/shader/lighting/Irradiance_frag.ts b/src/assets/shader/lighting/Irradiance_frag.ts index 8ce3a883..477348d0 100644 --- a/src/assets/shader/lighting/Irradiance_frag.ts +++ b/src/assets/shader/lighting/Irradiance_frag.ts @@ -1,10 +1,5 @@ export let Irradiance_frag: string = /*wgsl*/ ` #include "IrradianceVolumeData_frag" - fn pow3( x : f32 ) -> f32 - { - return x*x*x; - } - struct IrradianceField { probeStartPosition: vec4, probeCounts:vec4, @@ -23,7 +18,7 @@ export let Irradiance_frag: string = /*wgsl*/ ` @group(1) @binding(auto) var irradianceDepthMap: texture_2d; @group(2) @binding(7) - var irradianceData : IrradianceVolumeData ; + var irradianceData : IrradianceVolumeData ; var irradianceFieldSurface: IrradianceField; var energyPreservation: f32 = 0.85; diff --git a/src/assets/shader/lighting/LightingFunction_frag.ts b/src/assets/shader/lighting/LightingFunction_frag.ts index 0682ed26..e1eb44dd 100644 --- a/src/assets/shader/lighting/LightingFunction_frag.ts +++ b/src/assets/shader/lighting/LightingFunction_frag.ts @@ -39,7 +39,7 @@ fn directLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , #if USE_LAMBERT color = vec3(1.0,1.0,1.0) ; #endif - + #if USE_BRDF color = simpleBRDF(albedo,N,V,L,att,lightColor,roughness,metallic) ; #endif @@ -47,6 +47,63 @@ fn directLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , return color; } +fn directDulLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 , light:LightData , shadowBias:f32 ) -> vec3 { + var color = vec3(0.0) ; + #if USE_LIGHT + var L = -normalize(light.direction.xyz) ; + let lightCC = pow( light.lightColor.rgb,vec3(2.2)); + var lightColor = getHDRColor( lightCC.rgb , light.linear ) ; + var att = light.intensity / LUMEN ; + if(light.castShadow>=0){ + #if USE_SHADOWMAPING + for (var j: i32 = 0; j < 8; j += 1) { + if(j == light.castShadow){ + att *= shadowStrut.directShadowVisibility[j] ; + } + } + #endif + } + #if USE_LAMBERT + color = vec3(1.0,1.0,1.0) ; + #endif + + #if USE_BRDF + color = 0.85 * simpleBRDF(albedo,N,V,L,att,lightColor,0.85 * roughness,metallic) ; + color += 0.15 * simpleBRDF(albedo,N,V,L,att,lightColor,0.15 * roughness,metallic) ; + #endif + #endif + return color; +} + +fn directHairLighting( albedo:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 , light:LightData , shadowBias:f32 ) -> vec3 { + var color = vec3(0.0) ; + #if USE_LIGHT + var L = -normalize(light.direction.xyz) ; + let lightCC = pow( light.lightColor.rgb,vec3(2.2)); + var lightColor = getHDRColor( lightCC.rgb , light.linear ) ; + var att = light.intensity / LUMEN ; + if(light.castShadow>=0){ + #if USE_SHADOWMAPING + for (var j: i32 = 0; j < 8; j += 1) { + if(j == light.castShadow){ + att *= shadowStrut.directShadowVisibility[j] ; + } + } + #endif + } + #if USE_LAMBERT + color = vec3(1.0,1.0,1.0) ; + #endif + + #if USE_BRDF + color = 0.5 * simpleBRDF(albedo,N,V,L,att,lightColor,0.85 ,metallic) ; + color += 0.5 * simpleBRDF(albedo,N,V,L,att,lightColor,0.15 ,metallic) ; + #endif + #endif + return color; +} + + fn pointLighting( albedo:vec3,WP:vec3, N:vec3, V:vec3, roughness:f32 , metallic:f32 ,light:LightData ) -> vec3 { var color = vec3(0.0) ; let lightPos = light.position.xyz; diff --git a/src/assets/shader/materials/ColorLitShader.ts b/src/assets/shader/materials/ColorLitShader.ts index a2ea1ed2..b5aa1638 100644 --- a/src/assets/shader/materials/ColorLitShader.ts +++ b/src/assets/shader/materials/ColorLitShader.ts @@ -1,5 +1,4 @@ -export class ColorLitShader { - public static Ori_AllShader: string = /*wgsl*/` +export let ColorLitShader: string = /*wgsl*/` #include "Common_vert" #include "Common_frag" #include "BxDF_frag" @@ -14,7 +13,7 @@ export class ColorLitShader { ORI_ShadingInput.Roughness = materialUniform.roughness ; ORI_ShadingInput.Metallic = materialUniform.metallic ; ORI_ShadingInput.Specular = 0.5 ; - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; + ORI_ShadingInput.AmbientOcclusion = 1.0 ; ORI_ShadingInput.EmissiveColor = vec4(0.0); ORI_ShadingInput.Normal = ORI_VertexVarying.vWorldNormal.rgb ; @@ -25,5 +24,4 @@ export class ColorLitShader { BxDFShading(); } - ` -} + ` \ No newline at end of file diff --git a/src/assets/shader/materials/Hair_shader.ts b/src/assets/shader/materials/Hair_shader.ts new file mode 100644 index 00000000..3e5f59d4 --- /dev/null +++ b/src/assets/shader/materials/Hair_shader.ts @@ -0,0 +1,247 @@ +export let Hair_shader_op: string = /*wgsl*/ ` + #include "Common_vert" + #include "Common_frag" + #include "Hair_frag" + + @group(1) @binding(auto) + var baseMapSampler: sampler; + @group(1) @binding(auto) + var baseMap: texture_2d; + + @group(1) @binding(auto) + var idMapSampler: sampler; + @group(1) @binding(auto) + var idMap: texture_2d; + + @group(1) @binding(auto) + var depthMapSampler: sampler; + @group(1) @binding(auto) + var depthMap: texture_2d; + + @group(1) @binding(auto) + var rootMapSampler: sampler; + @group(1) @binding(auto) + var rootMap: texture_2d; + + @group(1) @binding(auto) + var alphaMapSampler: sampler; + @group(1) @binding(auto) + var alphaMap: texture_2d; + + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + + baseColor0: vec4, + baseColor1: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + + ao: f32, + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + + backlit: f32, + area: f32, + }; +#endif + + var debugOut : vec4f = vec4f(0.0) ; + var uv : vec2f = vec2f(0.0) ; + + fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; + } + + fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + + ORI_ShadingInput.Roughness = materialUniform.roughness; + ORI_ShadingInput.Metallic = materialUniform.metallic; + + + #if USE_HAIRCOLOR + let root = textureSample(rootMap, rootMapSampler, uv ).r ; + ORI_ShadingInput.BaseColor = mix(materialUniform.baseColor0,materialUniform.baseColor1,root) ; + #else + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #endif + #endif + + fragData.Alpha = 1.0 ; + #if USE_ALPHA_A + // fragData.Alpha = textureSampleLevel(alphaMap, alphaMapSampler, uv , 0.0 ).r ; + // let shake = (globalUniform.frame % 5.0) / 5.0 * 2.0 ; + fragData.Alpha = textureSample(alphaMap, alphaMapSampler, uv ).r ; + #endif + + #if USE_ALPHACUT + if( (fragData.Alpha - materialUniform.alphaCutoff) < 0.0 ){ + #if USEGBUFFER + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + #endif + discard; + } + #endif + + #if USE_SHADOWMAPING + useShadow(); + #endif + + ORI_ShadingInput.Specular = 1.0 ; + + let idMap = textureSampleLevel(idMap, idMapSampler, uv , 0.0 ); + var hairNormal = HairNormal(idMap.r).rgb ; + hairNormal = transformHairNormal( hairNormal) ; + ORI_ShadingInput.HairNormal = hairNormal ; + + ORI_ShadingInput.Normal = unPackRGNormal(vec3f(0.5,0.5,1.0),1.0,1.0) ; + + ORI_ShadingInput.BaseColor.a = fragData.Alpha; + + BSSSRDFShading(); + } +` + +export let Hair_shader_tr: string = /*wgsl*/ ` +#include "Common_vert" +#include "Common_frag" +#include "Hair_frag" + +@group(1) @binding(auto) +var baseMapSampler: sampler; +@group(1) @binding(auto) +var baseMap: texture_2d; + +@group(1) @binding(auto) +var idMapSampler: sampler; +@group(1) @binding(auto) +var idMap: texture_2d; + +@group(1) @binding(auto) +var depthMapSampler: sampler; +@group(1) @binding(auto) +var depthMap: texture_2d; + +@group(1) @binding(auto) +var rootMapSampler: sampler; +@group(1) @binding(auto) +var rootMap: texture_2d; + +@group(1) @binding(auto) +var alphaMapSampler: sampler; +@group(1) @binding(auto) +var alphaMap: texture_2d; + +#if USE_CUSTOMUNIFORM +struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + + baseColor0: vec4, + baseColor1: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + + ao: f32, + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + + backlit: f32, + area: f32, +}; +#endif + +var debugOut : vec4f = vec4f(0.0) ; +var uv : vec2f = vec2f(0.0) ; + +fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; +} + +fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + + ORI_ShadingInput.Roughness = materialUniform.roughness; + ORI_ShadingInput.Metallic = materialUniform.metallic; + + #if USE_HAIRCOLOR + let root = textureSample(rootMap, rootMapSampler, uv ).r ; + ORI_ShadingInput.BaseColor = mix(materialUniform.baseColor0,materialUniform.baseColor1,root) ; + #else + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + #endif + #endif + + fragData.Alpha = 1.0 ; + #if USE_ALPHA_A + fragData.Alpha = textureSampleLevel(alphaMap, alphaMapSampler, uv , 0.0 ).r ; + #endif + + #if USE_ALPHACUT + if( (((1.0 - fragData.Alpha) - (1.0 - materialUniform.alphaCutoff))) < 0.0 ){ + #if USEGBUFFER + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + #endif + discard; + } + #endif + + #if USE_SHADOWMAPING + useShadow(); + #endif + + ORI_ShadingInput.Specular = 1.0 ; + + let idMap = textureSampleLevel(idMap, idMapSampler, uv , 0.0 ); + var hairNormal = HairNormal(idMap.r).rgb ; + hairNormal = transformHairNormal( hairNormal) ; + ORI_ShadingInput.HairNormal = hairNormal ; + + ORI_ShadingInput.Normal = unPackRGNormal(vec3f(0.5,0.5,1.0),1.0,1.0) ; + + ORI_ShadingInput.BaseColor.a = fragData.Alpha; + + BSSSRDFShading(); +} +` + diff --git a/src/assets/shader/materials/LambertShader.ts b/src/assets/shader/materials/Lambert_shader.ts similarity index 97% rename from src/assets/shader/materials/LambertShader.ts rename to src/assets/shader/materials/Lambert_shader.ts index a78a4ce6..83795ea0 100644 --- a/src/assets/shader/materials/LambertShader.ts +++ b/src/assets/shader/materials/Lambert_shader.ts @@ -1,4 +1,4 @@ -export let LambertShader: string = /*wgsl*/ ` +export let Lambert_shader: string = /*wgsl*/ ` #include "Common_vert" #include "Common_frag" #include "ClusterLight" diff --git a/src/assets/shader/materials/LitShader.ts b/src/assets/shader/materials/Lit_shader.ts similarity index 85% rename from src/assets/shader/materials/LitShader.ts rename to src/assets/shader/materials/Lit_shader.ts index 4dae19b4..ceca8bbd 100644 --- a/src/assets/shader/materials/LitShader.ts +++ b/src/assets/shader/materials/Lit_shader.ts @@ -1,4 +1,4 @@ -export let LitShader: string = /*wgsl*/ ` +export let Lit_shader: string = /*wgsl*/ ` #include "Common_vert" #include "Common_frag" #include "BxDF_frag" @@ -13,7 +13,7 @@ export let LitShader: string = /*wgsl*/ ` ORI_ShadingInput.Roughness = materialUniform.roughness ; ORI_ShadingInput.Metallic = materialUniform.metallic ; ORI_ShadingInput.Specular = 0.5 ; - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; + ORI_ShadingInput.AmbientOcclusion = 1.0 ; ORI_ShadingInput.EmissiveColor = vec4(0.0); ORI_ShadingInput.Normal = ORI_VertexVarying.vWorldNormal.rgb ; diff --git a/src/assets/shader/materials/PBRLItShader.ts b/src/assets/shader/materials/PBRLItShader.ts index ba3ac3c2..df611066 100644 --- a/src/assets/shader/materials/PBRLItShader.ts +++ b/src/assets/shader/materials/PBRLItShader.ts @@ -13,25 +13,25 @@ export let PBRLItShader: string = /*wgsl*/ ` @group(1) @binding(auto) var normalMap: texture_2d; - #if USE_ARMC + // #if USE_ARMC + // @group(1) @binding(auto) + // var maskMapSampler: sampler; + // @group(1) @binding(auto) + // var maskMap: texture_2d; + // #endif + + // #if USE_MR @group(1) @binding(auto) var maskMapSampler: sampler; @group(1) @binding(auto) var maskMap: texture_2d; - #endif - - #if USE_MR - @group(1) @binding(auto) - var maskMapSampler: sampler; - @group(1) @binding(auto) - var maskMap: texture_2d; - #endif + // #endif #if USE_AOTEX @group(1) @binding(auto) var aoMapSampler: sampler; @group(1) @binding(auto) - var aomapMap: texture_2d; + var aoMap: texture_2d; #endif @group(1) @binding(auto) @@ -39,6 +39,8 @@ export let PBRLItShader: string = /*wgsl*/ ` @group(1) @binding(auto) var emissiveMap: texture_2d; + var debugOut : vec4f = vec4f(0.0) ; + fn vert(inputData:VertexAttributes) -> VertexOutput { ORI_Vert(inputData) ; return ORI_VertexOut ; @@ -50,14 +52,31 @@ export let PBRLItShader: string = /*wgsl*/ ` var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; - ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; - ORI_ShadingInput.BaseColor = vec4(gammaToLiner(ORI_ShadingInput.BaseColor.rgb*ORI_ShadingInput.BaseColor.w ) * materialUniform.baseColor.rgb,ORI_ShadingInput.BaseColor.w*materialUniform.baseColor.a) ; - #if USE_ALPHACUT + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = gammaToLiner(ORI_ShadingInput.BaseColor.rgb) ; + ORI_ShadingInput.BaseColor = vec4( ORI_ShadingInput.BaseColor * materialUniform.baseColor.rgb, ORI_ShadingInput.BaseColor.w * materialUniform.baseColor.a) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = vec4f(gammaToLiner(ORI_ShadingInput.BaseColor.rgb) * materialUniform.baseColor.rgb,ORI_ShadingInput.BaseColor.a) ; + #endif + + var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; + + #if USE_ALPHA_A + ORI_ShadingInput.BaseColor.a = ORI_ShadingInput.BaseColor.a * (maskTex.a) ; + #endif + + #if USE_ALPHACUT if( (ORI_ShadingInput.BaseColor.a - materialUniform.alphaCutoff) <= 0.0 ){ ORI_FragmentOutput.color = vec4(0.0,0.0,0.0,1.0); - ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); - ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); - ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + + #if USEGBUFFER + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + #endif + discard; } #endif @@ -66,54 +85,75 @@ export let PBRLItShader: string = /*wgsl*/ ` useShadow(); #endif - #if USE_ARMC - var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; - - ORI_ShadingInput.AmbientOcclusion = maskTex.r * materialUniform.ao ; - - #if USE_AOTEX - var aoMap = textureSample(aomapMap, aoMapSampler, uv ); - ORI_ShadingInput.AmbientOcclusion = mix(0.0,aoMap.r,materialUniform.ao) ; - #endif - - ORI_ShadingInput.Roughness = maskTex.g * materialUniform.roughness ; - ORI_ShadingInput.Metallic = maskTex.b * materialUniform.metallic ; + var roughnessChannel:f32 = 1.0 ; + #if USE_ROUGHNESS_A + roughnessChannel = maskTex.a ; + #else if USE_ROUGHNESS_R + roughnessChannel = maskTex.r ; + #else if USE_ROUGHNESS_G + roughnessChannel = maskTex.g ; + #else if USE_ROUGHNESS_B + roughnessChannel = maskTex.b ; + #else if USE_ALBEDO_A + roughnessChannel = ORI_ShadingInput.BaseColor.a ; + #endif + + #if USE_SMOOTH + var roughness = ( 1.0 - roughnessChannel ) * materialUniform.roughness; + ORI_ShadingInput.Roughness = clamp(roughness , 0.0001 , 1.0); + #else + ORI_ShadingInput.Roughness = clamp(roughnessChannel * materialUniform.roughness ,0.0001,1.0); + #endif + + var metallicChannel:f32 = 1.0 ; + #if USE_METALLIC_A + metallicChannel = maskTex.a ; + #else if USE_METALLIC_R + metallicChannel = maskTex.r ; + #else if USE_METALLIC_G + metallicChannel = maskTex.g ; + #else if USE_METALLIC_B + metallicChannel = maskTex.b ; + #endif + + ORI_ShadingInput.Metallic = metallicChannel * materialUniform.metallic ; + + var aoChannel:f32 = 1.0 ; + #if USE_AOTEX + var aoMap = textureSample(aoMap, aoMapSampler, uv ); + aoChannel = aoMap.g ; + #else + #if USE_AO_A + aoChannel = maskTex.a ; + #else if USE_AO_R + aoChannel = maskTex.r ; + #else if USE_AO_G + aoChannel = maskTex.g ; + #else if USE_AO_B + aoChannel = maskTex.b ; + #endif + #endif - #elseif USE_MR - var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; - #if USE_AOTEX - var aoMap = textureSample(aomapMap, aoMapSampler, uv ); - ORI_ShadingInput.AmbientOcclusion = mix(0.0,aoMap.r,materialUniform.ao) ; - #else - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; - #endif + ORI_ShadingInput.AmbientOcclusion = aoChannel ; + ORI_ShadingInput.Specular = 1.0 ; - ORI_ShadingInput.Roughness = maskTex.g * materialUniform.roughness ; - ORI_ShadingInput.Metallic = maskTex.b * materialUniform.metallic; + #if USE_EMISSIVEMAP + var emissiveMapColor = textureSample(emissiveMap, emissiveMapSampler , ORI_VertexVarying.fragUV0.xy) ; + let emissiveColor = materialUniform.emissiveColor.rgb * emissiveMapColor.rgb * materialUniform.emissiveIntensity ; + ORI_ShadingInput.EmissiveColor = vec4(emissiveColor.rgb,1.0); #else - ORI_ShadingInput.Roughness = materialUniform.roughness ; - ORI_ShadingInput.Metallic = materialUniform.metallic ; - ORI_ShadingInput.AmbientOcclusion = materialUniform.ao ; - #if USE_AOTEX - var aoMap = textureSample(aomapMap, aoMapSampler, uv ); - ORI_ShadingInput.AmbientOcclusion = mix(0.0,aoMap.r,materialUniform.ao) ; - #endif + let emissiveColor = materialUniform.emissiveColor.rgb * materialUniform.emissiveIntensity ; + ORI_ShadingInput.EmissiveColor = vec4(emissiveColor,1.0); #endif - ORI_ShadingInput.Roughness = clamp(ORI_ShadingInput.Roughness,0.084,1.0); - ORI_ShadingInput.Specular = 0.5 ; - - var emissiveColor = textureSample(emissiveMap, emissiveMapSampler , ORI_VertexVarying.fragUV0.xy) ; - emissiveColor = vec4(gammaToLiner(emissiveColor.rgb),emissiveColor.w); - ORI_ShadingInput.EmissiveColor = vec4(materialUniform.emissiveColor.rgb * emissiveColor.rgb * materialUniform.emissiveIntensity,1.0); var Normal = textureSample(normalMap,normalMapSampler,uv).rgb ; - // Normal.y = 1.0 - Normal.y ; - // let normal = unPackNormal(Normal,1.0,materialUniform.normalScale) ; - let normal = unPackNormal(Normal,materialUniform.normalScale) ; + let normal = unPackRGNormal(Normal,1.0,1.0) ; ORI_ShadingInput.Normal = normal ; BxDFShading(); + + // ORI_FragmentOutput.color = vec4(vec3(normal.rgb),1.0) ; } ` diff --git a/src/assets/shader/materials/PBRLitSSSShader.ts b/src/assets/shader/materials/PBRLitSSSShader.ts new file mode 100644 index 00000000..3a8ee687 --- /dev/null +++ b/src/assets/shader/materials/PBRLitSSSShader.ts @@ -0,0 +1,218 @@ +export let PBRLitSSSShader: string = /*wgsl*/ ` + #include "Common_vert" + #include "Common_frag" + #include "BsDF_frag" + + @group(1) @binding(auto) + var baseMapSampler: sampler; + @group(1) @binding(auto) + var baseMap: texture_2d; + + @group(1) @binding(auto) + var normalMapSampler: sampler; + @group(1) @binding(auto) + var normalMap: texture_2d; + + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + + baseColor: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + + ao: f32, + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + + clearcoatColor: vec4, + + clearcoatWeight: f32, + clearcoatFactor: f32, + clearcoatRoughnessFactor: f32, + skinPower: f32, + + skinColor: vec4, + skinColorIns: f32, + curveFactor: f32, + }; + #endif + // #if USE_ARMC + // @group(1) @binding(auto) + // var maskMapSampler: sampler; + // @group(1) @binding(auto) + // var maskMap: texture_2d; + // #endif + + // #if USE_MR + @group(1) @binding(auto) + var maskMapSampler: sampler; + @group(1) @binding(auto) + var maskMap: texture_2d; + // #endif + + #if USE_AOTEX + @group(1) @binding(auto) + var aoMapSampler: sampler; + @group(1) @binding(auto) + var aoMap: texture_2d; + #endif + + @group(1) @binding(auto) + var emissiveMapSampler: sampler; + @group(1) @binding(auto) + var emissiveMap: texture_2d; + + @group(1) @binding(auto) + var sssMapSampler: sampler; + @group(1) @binding(auto) + var sssMap: texture_2d; + + @group(1) @binding(auto) + var lutMapSampler: sampler; + @group(1) @binding(auto) + var lutMap: texture_2d; + + var debugOut : vec4f = vec4f(0.0) ; + + fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; + } + + fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + + var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + + #if USE_SRGB_ALBEDO + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = vec4f(ORI_ShadingInput.BaseColor.rgb/ORI_ShadingInput.BaseColor.a,ORI_ShadingInput.BaseColor.a) ; + ORI_ShadingInput.BaseColor = vec4(gammaToLiner(ORI_ShadingInput.BaseColor.rgb) * materialUniform.baseColor.rgb, ORI_ShadingInput.BaseColor.w * materialUniform.baseColor.a) ; + #else + ORI_ShadingInput.BaseColor = textureSample(baseMap, baseMapSampler, uv ) ; + ORI_ShadingInput.BaseColor = vec4f(ORI_ShadingInput.BaseColor.rgb/ORI_ShadingInput.BaseColor.a,ORI_ShadingInput.BaseColor.a) ; + ORI_ShadingInput.BaseColor = vec4(gammaToLiner(ORI_ShadingInput.BaseColor.rgb) * materialUniform.baseColor.rgb, ORI_ShadingInput.BaseColor.w * materialUniform.baseColor.a) ; + #endif + + var maskTex = textureSample(maskMap, maskMapSampler, uv ) ; + + #if USE_ALPHA_A + ORI_ShadingInput.BaseColor.a = ORI_ShadingInput.BaseColor.a * (maskTex.a) ; + ORI_ShadingInput.BaseColor = vec4f(ORI_ShadingInput.BaseColor.rgb/ORI_ShadingInput.BaseColor.a,ORI_ShadingInput.BaseColor.a) ; + #endif + + #if USE_ALPHACUT + if( (ORI_ShadingInput.BaseColor.a - materialUniform.alphaCutoff) <= 0.0 ){ + ORI_FragmentOutput.color = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldPos = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.worldNormal = vec4(0.0,0.0,0.0,1.0); + ORI_FragmentOutput.material = vec4(0.0,0.0,0.0,1.0); + discard; + } + #endif + + #if USE_SHADOWMAPING + useShadow(); + #endif + + // maskTex =vec4f( gammaToLiner(maskTex.rgb), maskTex.a ); + + var roughnessChannel:f32 = 1.0 ; + #if USE_ROUGHNESS_A + roughnessChannel = maskTex.a ; + #else if USE_ROUGHNESS_R + roughnessChannel = maskTex.r ; + #else if USE_ROUGHNESS_G + roughnessChannel = maskTex.g ; + #else if USE_ROUGHNESS_B + roughnessChannel = maskTex.b ; + #else if USE_ALBEDO_A + roughnessChannel = ORI_ShadingInput.BaseColor.a ; + #endif + + #if USE_SMOOTH + var roughness = ( 1.0 - roughnessChannel ) * materialUniform.roughness; + ORI_ShadingInput.Roughness = clamp(roughness , 0.0001 , 1.0); + #else + ORI_ShadingInput.Roughness = clamp(roughnessChannel * materialUniform.roughness ,0.0001,1.0); + #endif + + var metallicChannel:f32 = 1.0 ; + #if USE_METALLIC_A + metallicChannel = maskTex.a ; + #else if USE_METALLIC_R + metallicChannel = maskTex.r ; + #else if USE_METALLIC_G + metallicChannel = maskTex.g ; + #else if USE_METALLIC_B + metallicChannel = maskTex.b ; + #endif + ORI_ShadingInput.Metallic = metallicChannel * metallicChannel * materialUniform.metallic ; + + var aoChannel:f32 = 1.0 ; + #if USE_AOTEX + var aoMap = textureSample(aoMap, aoMapSampler, uv ); + aoChannel = aoMap.g ; + #else + #if USE_AO_A + aoChannel = maskTex.a ; + #else if USE_AO_R + aoChannel = maskTex.r ; + #else if USE_AO_G + aoChannel = maskTex.g ; + #else if USE_AO_B + aoChannel = maskTex.b ; + #endif + #endif + + // ORI_ShadingInput.BaseColor.a = maskTex.a ; + + ORI_ShadingInput.AmbientOcclusion = aoChannel ; + + ORI_ShadingInput.Specular = 1.0 ; + + var emissiveColor = textureSample(emissiveMap, emissiveMapSampler , ORI_VertexVarying.fragUV0.xy) ; + + emissiveColor = vec4(gammaToLiner(emissiveColor.rgb),emissiveColor.w); + + ORI_ShadingInput.EmissiveColor = vec4(materialUniform.emissiveColor.rgb * emissiveColor.rgb * materialUniform.emissiveIntensity,1.0); + + + + var Normal = textureSample(normalMap,normalMapSampler,uv).rgb ; + + let normal = unPackRGNormal(Normal,1.0,1.0) ; + + ORI_ShadingInput.Normal = normal ; + + var sssColor = vec3f(pow(textureSample(sssMap, sssMapSampler, uv ).r,materialUniform.skinPower)) * materialUniform.skinColor.rgb ; + let sunLight = lightBuffer[0] ; + let sunLightIntensity = (sunLight.intensity / LUMEN) ; + let ndl = 1.0 - clamp(dot(normalize(normal),-normalize(sunLight.direction)),0.0,1.0) * 0.5 + 0.5 ;//1.0 - saturate( dot(normalize(normal),normalize(sunLight.direction)) ) * 0.5 + 0.5 ; + ORI_ShadingInput.SSS += 0.5 * vec3f(sssColor * sunLightIntensity * materialUniform.skinColorIns * ndl * sunLight.lightColor.rgb ) ; + + var curve = clamp(materialUniform.curveFactor * (length(fwidth(ORI_ShadingInput.Normal.xyz)) / length(fwidth(ORI_VertexVarying.vWorldPos.xyz*100.0))),0.0,1.0); + var NDotL = dot(ORI_ShadingInput.Normal, -sunLight.direction ); + var sssColor2 = textureSample(lutMap, lutMapSampler ,vec2f(NDotL * 0.5 + 0.5, materialUniform.curveFactor * sssColor.r)).rgb * sunLight.lightColor.rgb * sunLightIntensity ; + ORI_ShadingInput.SSS = sssColor2.rgb * ORI_ShadingInput.BaseColor.rgb ; + + BsDFShading(); + + // ORI_FragmentOutput.color = vec4f(vec3f(0.5*ORI_ShadingInput.SSS),1.0) ; + } +` + diff --git a/src/assets/shader/materials/PavementShader.ts b/src/assets/shader/materials/PavementShader.ts index 6a1f306b..a3a8b752 100644 --- a/src/assets/shader/materials/PavementShader.ts +++ b/src/assets/shader/materials/PavementShader.ts @@ -1,4 +1,4 @@ -export let PavementShader:string = /*wgsl*/` +export let PavementShader: string = /*wgsl*/` #include "Common_vert" #include "Common_frag" #include "BxDF_frag" @@ -57,7 +57,7 @@ export let PavementShader:string = /*wgsl*/` ORI_ShadingInput.Roughness = ReflectMap * materialUniform.roughness ; ORI_ShadingInput.Metallic = materialUniform.metallic ; ORI_ShadingInput.Specular = 0.5 ; - ORI_ShadingInput.AmbientOcclusion = Ao * materialUniform.ao ; + ORI_ShadingInput.AmbientOcclusion = Ao; ORI_ShadingInput.EmissiveColor = vec4(0.0); let normal = unPackRGNormal(Normal,Displace.r*materialUniform.normalScale,1.0) ; diff --git a/src/assets/shader/materials/UnLit.ts b/src/assets/shader/materials/UnLit.ts index 4e8e439b..52a4ea89 100644 --- a/src/assets/shader/materials/UnLit.ts +++ b/src/assets/shader/materials/UnLit.ts @@ -4,6 +4,15 @@ export let UnLit: string = /*wgsl*/ ` #include "UnLit_frag" #include "UnLitMaterialUniform_frag" + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + baseColor: vec4, + alphaCutoff: f32, + }; + #endif + @group(1) @binding(0) var baseMapSampler: sampler; @group(1) @binding(1) @@ -25,7 +34,10 @@ export let UnLit: string = /*wgsl*/ ` } ORI_ShadingInput.BaseColor = color * materialUniform.baseColor ; + UnLit(); + + // ORI_FragmentOutput.color = vec4( 1.0,0.0,0.0,1.0) ; } ` diff --git a/src/assets/shader/materials/UnLitTextureArray.ts b/src/assets/shader/materials/UnLitTextureArray.ts new file mode 100644 index 00000000..ad161668 --- /dev/null +++ b/src/assets/shader/materials/UnLitTextureArray.ts @@ -0,0 +1,77 @@ +export let UnLitTextureArray: string = /*wgsl*/ ` + // #include "Common_vert" + #include "Common_frag" + #include "UnLit_frag" + #include "UnLitMaterialUniform_frag" + + #include "WorldMatrixUniform" + #include "VertexAttributeIndexShader" + #include "GlobalUniform" + #include "Inline_vert" + #include "EnvMap_frag" + #include "ColorUtil_frag" + + const DEGREES_TO_RADIANS : f32 = 3.1415926 / 180.0 ; + const PI : f32 = 3.1415926 ; + + #if USE_CUSTOMUNIFORM + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + baseColor: vec4, + alphaCutoff: f32, + }; + #endif + + @group(1) @binding(0) + var baseMapSampler: sampler; + @group(1) @binding(1) + var baseMap: texture_2d_array; + + @group(2) @binding(5) + var graphicBuffer : array; + + @vertex + fn VertMain( vertex:VertexAttributes ) -> VertexOutput { + vertex_inline(vertex); + vert(vertex); + return ORI_VertexOut ; + } + + fn vert(inputData:VertexAttributes) -> VertexOutput { + ORI_Vert(inputData) ; + return ORI_VertexOut ; + } + + fn frag(){ + var transformUV1 = materialUniform.transformUV1; + var transformUV2 = materialUniform.transformUV2; + + // var irradiance = vec3(0.0) ; + // let MAX_REFLECTION_LOD = f32(textureNumLevels(prefilterMap)) ; + // irradiance += (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, ORI_VertexVarying.vWorldNormal.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); + + graphicNode = graphicBuffer[u32(round(ORI_VertexVarying.index))]; + + var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; + let color = textureSample(baseMap,baseMapSampler,uv, u32(round(graphicNode.texIndex)) ); + // let color = textureSample(baseMap,baseMapSampler,uv, u32(round(ORI_VertexVarying.index))); + + // ORI_ViewDir = normalize( globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz); + // let att = dot( ORI_ViewDir , ORI_VertexVarying.vWorldNormal.xyz ); + + // irradiance = LinearToGammaSpace(irradiance.rgb) * color.rgb ;//* att ; + + if(color.w < 0.5){ + discard ; + } + + // let outColor = vec4f( color.rgb * (att * 0.5 + 0.5 ) , 1.0 ) * materialUniform.baseColor ; + let outColor = vec4f( color.rgb , 1.0 ) * materialUniform.baseColor ; + + // ORI_ShadingInput.BaseColor = color ; + ORI_ShadingInput.BaseColor = vec4f(outColor.xyz,1.0) ; + UnLit(); + } +` + diff --git a/src/assets/shader/materials/program/BxdfDebug_frag.ts b/src/assets/shader/materials/program/BxdfDebug_frag.ts index 12c42382..3b94deed 100644 --- a/src/assets/shader/materials/program/BxdfDebug_frag.ts +++ b/src/assets/shader/materials/program/BxdfDebug_frag.ts @@ -6,7 +6,7 @@ export let BxdfDebug_frag: string = /*wgsl*/ ` } fn debugMeshID(){ - let meshIDColor = u32(ORI_VertexVarying.vWorldPos.w ) ; + let meshIDColor = u32(round(ORI_VertexVarying.vWorldPos.w) ) ; let color = colorSet[ meshIDColor % 9u] ; ORI_FragmentOutput.color = vec4(vec3(color.rgb),1.0); } @@ -29,7 +29,7 @@ export let BxdfDebug_frag: string = /*wgsl*/ ` } fn debugAmbient(){ - ORI_FragmentOutput.color = vec4(fragData.Irradiance * fragData.Albedo.rgb,1.0); + ORI_FragmentOutput.color = vec4(vec3f(fragData.Alpha) ,1.0); } fn debugEmissive(){ @@ -57,7 +57,7 @@ export let BxdfDebug_frag: string = /*wgsl*/ ` } fn debugTangent(){ - ORI_FragmentOutput.color = vec4(vec3(fragData.TangentChannel),1.0); + ORI_FragmentOutput.color = vec4(vec3(fragData.T),1.0); } fn debugFragmentOut(){ diff --git a/src/assets/shader/materials/program/NormalMap_frag.ts b/src/assets/shader/materials/program/NormalMap_frag.ts index 374ba7eb..d8795563 100644 --- a/src/assets/shader/materials/program/NormalMap_frag.ts +++ b/src/assets/shader/materials/program/NormalMap_frag.ts @@ -1,18 +1,19 @@ export let NormalMap_frag: string = /*wgsl*/ ` + fn perturbNormal( worldPos:vec3, surf_norm:vec3, mapN:vec3 , normalScale:f32 , face:f32 ) -> vec3 { var q0 = vec3( dpdx( worldPos.x ), dpdx( worldPos.y ), dpdx( worldPos.z ) ); var q1 = vec3( dpdy( worldPos.x ), dpdy( worldPos.y ), dpdy( worldPos.z ) ); var st0 = dpdx( ORI_VertexVarying.fragUV0.xy ); var st1 = dpdy( ORI_VertexVarying.fragUV0.xy ); var N = surf_norm; - var q1perp = cross( q1, N ); var q0perp = cross( N, q0 ); + var q1perp = cross( q1, N ); - #if USE_TANGENT - var T = ORI_VertexVarying.TANGENT.xyz ; - #else + // #if USE_TANGENT + // var T = ORI_VertexVarying.TANGENT.xyz ; + // #else var T = q1perp * st0.x + q0perp * st1.x; - #endif + // #endif var B = q1perp * st0.y + q0perp * st1.y; @@ -21,9 +22,10 @@ export let NormalMap_frag: string = /*wgsl*/ ` if( det != 0.0 ){ scale = inverseSqrt( det ) ; } - #if USE_TANGENT - scale = scale * ORI_VertexVarying.TANGENT.w ; - #endif + + // #if USE_TANGENT + // scale = scale * ORI_VertexVarying.TANGENT.w ; + // #endif scale *= normalScale; return normalize( (T * ( -mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z ) * face ) ; @@ -51,7 +53,7 @@ export let NormalMap_frag: string = /*wgsl*/ ` n.y = 1.0 - n.y ; #endif - var mapNormal: vec3 = unpackNormalMap(n) ; + var mapNormal: vec3 = n ;//unpackNormalMap(n) ; return perturbNormal(ORI_VertexVarying.vWorldPos.xyz , ORI_VertexVarying.vWorldNormal.xyz , mapNormal , height , face ) ; #endif } diff --git a/src/assets/shader/materials/program/ShadowMapping_frag.ts b/src/assets/shader/materials/program/ShadowMapping_frag.ts index 457a5562..62a839ad 100644 --- a/src/assets/shader/materials/program/ShadowMapping_frag.ts +++ b/src/assets/shader/materials/program/ShadowMapping_frag.ts @@ -13,22 +13,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` directShadowVisibility: array, pointShadows: array, } - - varshadowStrut: ShadowStruct; - - struct ShadowBuffer{ - nDirShadowStart: i32, - nDirShadowEnd: i32, - nPointShadowStart: i32, - nPointShadowEnd: i32, - shadowLights:array - } - - #if DEBUG_CLUSTER - @group(2) @binding(6) var shadowBuffer: ShadowBuffer; - #else - @group(2) @binding(5) var shadowBuffer: ShadowBuffer; - #endif + var shadowStrut: ShadowStruct ; fn useShadow(){ shadowStrut.directShadowVisibility = array( 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0) ; @@ -51,9 +36,9 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` #if USE_SHADOWMAPING let enableCSM:bool = globalUniform.enableCSM > 0.5; for (var i: i32 = 0; i < dirCount ; i = i + 1) { - if( i >= shadowBuffer.nDirShadowStart && i < shadowBuffer.nDirShadowEnd ){ - let ldx = shadowBuffer.shadowLights[i]; - var light = lightBuffer[ldx]; + if( i >= globalUniform.nDirShadowStart && i < globalUniform.nDirShadowEnd ){ + let ldx = globalUniform.shadowLights[u32(i) / 4u][u32(i) % 4u]; + let light = lightBuffer[u32(ldx)] ; var shadowIndex = i32(light.castShadow); var visibility = 1.0; var shadowMatrix:mat4x4; @@ -96,7 +81,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` if(validCount == 0){ visibility = 1.0; }else{ - visibility = visibility / totalWeight; + visibility = visibility / totalWeight ; } }else{ shadowMatrix = globalUniform.shadowMatrix[shadowIndex]; @@ -135,8 +120,9 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` isOutSideArea = 0.0; var uvOnePixel = 1.0 / vec2(globalUniform.shadowMapSize); var totalWeight = 0.0; - var NoL = abs(dot(normalize(ORI_VertexVarying.vWorldNormal), normalize(light.direction))); - var bias = shadowBias / max(NoL, 0.000001); + var NoL = (dot(normalize(ORI_VertexVarying.vWorldNormal), normalize(-light.direction))); + let v = max(NoL, 0.0) ; + var bias = shadowBias / v; for (var y = -1; y <= 1; y++) { for (var x = -1; x <= 1; x++) { var offset = vec2(f32(x), f32(y)) * uvOnePixel; @@ -144,7 +130,7 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` // visibility += textureSampleCompare(shadowMap, shadowMapSampler, varying_shadowUV + offset, depthTexIndex, shadowPos.z - bias); var depth = textureSampleLevel(shadowMap, shadowMapSampler, varying_shadowUV + offset, depthTexIndex, 0); if ((shadowPos.z - bias ) < depth) { - visibility += 1.0 ;//* dot(offsetDir, dir.xyz); + visibility += 1.0 ; } totalWeight += 1.0; } @@ -161,76 +147,75 @@ export let ShadowMapping_frag: string = /*wgsl*/ ` let offset = 0.1; for (var i: i32 = 0; i < pointCount ; i = i + 1) { - if( i >= shadowBuffer.nPointShadowStart && i < shadowBuffer.nPointShadowEnd ){ - let ldx = shadowBuffer.shadowLights[i]; - let light = lightBuffer[ldx] ; + if( i >= globalUniform.nPointShadowStart && i < globalUniform.nPointShadowEnd ){ + let ldx = globalUniform.shadowLights[u32(i) / 4u][u32(i) % 4u]; + let light = lightBuffer[u32(ldx)] ; #if USE_SHADOWMAPING - let lightPos = light.position.xyz; - var shadow = 0.0; - let frgToLight = worldPos - lightPos.xyz; - var dir: vec3 = normalize(frgToLight); - var len = length(frgToLight); - var bias = max(shadowBias * globalUniform.far * (1.0 - dot(ORI_ShadingInput.Normal, dir)), 0.005); + let lightPos = light.position.xyz; + var shadow = 0.0; + let frgToLight = worldPos - lightPos.xyz; + var dir: vec3 = normalize(frgToLight); + var len = length(frgToLight); + var bias = max(shadowBias * globalUniform.far * (1.0 - dot(ORI_ShadingInput.Normal, dir)), 0.005); #if USE_PCF_SHADOW - let samples = 4.0; - for (var x: f32 = -offset; x < offset; x += offset / (samples * 0.5)) { - for (var y: f32 = -offset; y < offset; y += offset / (samples * 0.5)) { - for (var z: f32 = -offset; z < offset; z += offset / (samples * 0.5)) { - let offsetDir = normalize(dir.xyz + vec3(x, y, z)); + let samples = 4.0; + for (var x: f32 = -offset; x < offset; x += offset / (samples * 0.5)) { + for (var y: f32 = -offset; y < offset; y += offset / (samples * 0.5)) { + for (var z: f32 = -offset; z < offset; z += offset / (samples * 0.5)) { + let offsetDir = normalize(dir.xyz + vec3(x, y, z)); + var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, offsetDir, light.castShadow, 0); + depth *= globalUniform.far; + if ((len - bias) > depth) { + shadow += 1.0 * dot(offsetDir, dir.xyz); + } + } + } + } + shadow = min(max(shadow / (samples * samples * samples), 0.0), 1.0); + #endif + + #if USE_SOFT_SHADOW + let vDis = length(globalUniform.CameraPos.xyz - worldPos.xyz); + let sampleRadies = globalUniform.shadowSoft; + let samples = 20; + for (var j: i32 = 0; j < samples; j += 1) { + let offsetDir = normalize(dir.xyz + sampleOffsetDir[j] * sampleRadies); var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, offsetDir, light.castShadow, 0); depth *= globalUniform.far; if ((len - bias) > depth) { shadow += 1.0 * dot(offsetDir, dir.xyz); } } - } - } - shadow = min(max(shadow / (samples * samples * samples), 0.0), 1.0); - #endif - - #if USE_SOFT_SHADOW - let vDis = length(globalUniform.CameraPos.xyz - worldPos.xyz); - let sampleRadies = globalUniform.shadowSoft; - let samples = 20; - for (var j: i32 = 0; j < samples; j += 1) { - let offsetDir = normalize(dir.xyz + sampleOffsetDir[j] * sampleRadies); - var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, offsetDir, light.castShadow, 0); - depth *= globalUniform.far; - if ((len - bias) > depth) { - shadow += 1.0 * dot(offsetDir, dir.xyz); - } - } - shadow = min(max(shadow / f32(samples), 0.0), 1.0); + shadow = min(max(shadow / f32(samples), 0.0), 1.0); #endif #if USE_HARD_SHADOW - var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, dir.xyz, light.castShadow, 0); - depth *= globalUniform.far; - if ((len - bias) > depth) { - shadow = 1.0; - } + var depth = textureSampleLevel(pointShadowMap, pointShadowMapSampler, dir.xyz, light.castShadow, 0); + depth *= globalUniform.far; + if ((len - bias) > depth) { + shadow = 1.0; + } #endif - - for (var j = 0; j < pointCount ; j+=1 ) { - if(i32(light.castShadow) == j){ - shadowStrut.pointShadows[j] = 1.0 - shadow ; + for (var j = 0; j < pointCount ; j+=1 ) { + if(i32(light.castShadow) == j){ + shadowStrut.pointShadows[j] = 1.0 - shadow ; + } } - } #endif } } } #if USE_SOFT_SHADOW - varsampleOffsetDir : array, 20> = array, 20>( - vec3(1.0, 1.0, 1.0), vec3(1.0, -1.0, 1.0), vec3(-1.0, -1.0, 1.0), vec3(-1.0, 1.0, 1.0), - vec3(1.0, 1.0, -1.0), vec3(1.0, -1.0, -1.0), vec3(-1.0, -1.0, -1.0), vec3(-1.0, 1.0, -1.0), - vec3(1.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0), vec3(-1.0, -1.0, 0.0), vec3(-1.0, 1.0, 0.0), - vec3(1.0, 0.0, 1.0), vec3(-1.0, 0.0, 1.0), vec3(1.0, 0.0, -1.0), vec3(-1.0, 0.0, -1.0), - vec3(0.0, 1.0, 1.0), vec3(0.0, -1.0, 1.0), vec3(0.0, -1.0, -1.0), vec3(0.0, 1.0, -1.0), - ); + varsampleOffsetDir : array, 20> = array, 20>( + vec3(1.0, 1.0, 1.0), vec3(1.0, -1.0, 1.0), vec3(-1.0, -1.0, 1.0), vec3(-1.0, 1.0, 1.0), + vec3(1.0, 1.0, -1.0), vec3(1.0, -1.0, -1.0), vec3(-1.0, -1.0, -1.0), vec3(-1.0, 1.0, -1.0), + vec3(1.0, 1.0, 0.0), vec3(1.0, -1.0, 0.0), vec3(-1.0, -1.0, 0.0), vec3(-1.0, 1.0, 0.0), + vec3(1.0, 0.0, 1.0), vec3(-1.0, 0.0, 1.0), vec3(1.0, 0.0, -1.0), vec3(-1.0, 0.0, -1.0), + vec3(0.0, 1.0, 1.0), vec3(0.0, -1.0, 1.0), vec3(0.0, -1.0, -1.0), vec3(0.0, 1.0, -1.0), + ); #endif ` diff --git a/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts b/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts index a92cddcb..6aab2ff0 100644 --- a/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts +++ b/src/assets/shader/materials/uniforms/PhysicMaterialUniform_frag.ts @@ -1,29 +1,33 @@ export let PhysicMaterialUniform_frag = /* wgsl */` - struct MaterialUniform { - transformUV1:vec4, - transformUV2:vec4, + #if USE_CUSTOMUNIFORM + #else + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, - baseColor: vec4, - emissiveColor: vec4, - materialF0: vec4, - envIntensity: f32, - normalScale: f32, - roughness: f32, - metallic: f32, - ao: f32, + baseColor: vec4, + emissiveColor: vec4, + materialF0: vec4, + specularColor: vec4, + envIntensity: f32, + normalScale: f32, + roughness: f32, + metallic: f32, + ao: f32, - roughness_min: f32, - roughness_max: f32, - metallic_min: f32, - metallic_max: f32, - emissiveIntensity: f32, - alphaCutoff: f32, - ior: f32, - clearcoatColor: vec4, - clearcoatWeight: f32, - clearcoatFactor: f32, - clearcoatRoughnessFactor: f32, - }; + roughness_min: f32, + roughness_max: f32, + metallic_min: f32, + metallic_max: f32, + emissiveIntensity: f32, + alphaCutoff: f32, + ior: f32, + clearcoatColor: vec4, + clearcoatWeight: f32, + clearcoatFactor: f32, + clearcoatRoughnessFactor: f32, + }; + #endif @group(2) @binding(0) var materialUniform: MaterialUniform; diff --git a/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts b/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts index 07f05673..5847578f 100644 --- a/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts +++ b/src/assets/shader/materials/uniforms/UnLitMaterialUniform_frag.ts @@ -1,10 +1,16 @@ export let UnLitMaterialUniform_frag = /* wgsl */` -struct MaterialUniform { - transformUV1:vec4, - transformUV2:vec4, - baseColor: vec4, - alphaCutoff: f32, -}; + + +#if USE_CUSTOMUNIFORM +#else + struct MaterialUniform { + transformUV1:vec4, + transformUV2:vec4, + baseColor: vec4, + alphaCutoff: f32, + }; +#endif + @group(2) @binding(0) var materialUniform: MaterialUniform; diff --git a/src/assets/shader/math/FastMathShader.ts b/src/assets/shader/math/FastMathShader.ts index 4a4eb495..c3ae62f8 100644 --- a/src/assets/shader/math/FastMathShader.ts +++ b/src/assets/shader/math/FastMathShader.ts @@ -1,11 +1,22 @@ export let FastMathShader: string = /*wgsl*/ ` - fn Pow3( x : f32 ) -> f32 + fn pow2( x : f32 ) -> f32 + { + return x * x; + } + + fn pow2v3( x : vec3f ) -> vec3f + { + return x * x; + } + + + fn pow3( x : f32 ) -> f32 { var xx = x*x; return x * xx; } - fn Pow4( x : f32 ) -> f32 + fn pow4( x : f32 ) -> f32 { var xx = x*x; return xx * xx; @@ -30,5 +41,72 @@ export let FastMathShader: string = /*wgsl*/ ` { return pow(a, -0.5); } + + fn squareF( a : f32 ) -> f32 + { + return a * a; + } + + fn squareV2( a : vec2f ) -> vec2f + { + return a * a; + } + + fn squareV3( a : vec3f ) -> vec3f + { + return a * a; + } + + fn sqrtFast( x : f32 ) -> f32 + { + var i = i32(x); + i = 0x1FBD1DF5 + (i / 2 ); + return f32(i); + } + + fn lengthFast( v :vec3 ) -> f32 + { + var LengthSqr = dot(v,v); + return sqrtFast( LengthSqr ); + } + + fn asinFast( x:f32 )-> f32 + { + return (0.5 * PI) - acosFast(x); + } + + fn acosFast( inX: f32 ) -> f32 + { + var x = abs(inX); + var res = -0.156583 * x + (0.5 * PI); + res *= sqrt(1.0 - x); + + if(inX >= 0.0){ + return res ; + }else{ + return PI - res ; + } + } + + fn acosFast4( inX : f32 )-> f32 + { + var x1 = abs(inX); + var x2 = x1 * x1; + var x3 = x2 * x1; + var s = 0.0 ; + + s = -0.2121144 * x1 + 1.5707288; + s = 0.0742610 * x2 + s; + s = -0.0187293 * x3 + s; + s = sqrt(1.0 - x1) * s; + + // acos function mirroring + // check per platform if compiles to a selector - no branch neeeded + if(inX >= 0.0){ + return s ; + }else{ + return PI - s ; + } + } ` diff --git a/src/assets/shader/math/MathShader.ts b/src/assets/shader/math/MathShader.ts index 665522d0..20d3e8b4 100644 --- a/src/assets/shader/math/MathShader.ts +++ b/src/assets/shader/math/MathShader.ts @@ -2,7 +2,6 @@ * @internal */ export let MathShader = /* wgsl */ ` -var PI: f32 = 3.14159265359; fn applyQuaternion(position:vec3, q:vec4) -> vec3{ @@ -302,4 +301,13 @@ fn dir_to_faceId(pt:vec3) -> i32 { comp -= comp.xxyz * bitMsk; return comp; } + + fn calculateBillboardMatrix2(eye:vec3f,pos:vec3f,up:vec3f) -> mat3x3 { + + let zAxis: vec3f = -normalize(pos.xyz - eye); + var xAxis: vec3f = cross(up,zAxis); + xAxis = normalize(cross(zAxis,xAxis)); + let yAxis = normalize(cross(zAxis, xAxis)); + return mat3x3(xAxis, yAxis, zAxis); + } `; diff --git a/src/assets/shader/post/Bloom_shader.ts b/src/assets/shader/post/Bloom_shader.ts deleted file mode 100644 index d573d925..00000000 --- a/src/assets/shader/post/Bloom_shader.ts +++ /dev/null @@ -1,248 +0,0 @@ -export class Bloom_shader { - public static Bloom_Brightness_frag_wgsl: string = /* wgsl */ ` - struct uniformData { - luminosityThreshold: f32 - }; - - struct FragmentOutput { - @location(0) o_Target: vec4 - }; - - var fragUV1: vec2; - var o_Target: vec4; - @group(1) @binding(0) - var baseMapSampler: sampler; - @group(1) @binding(1) - var baseMap: texture_2d; - @group(2) @binding(0) - var global: uniformData; - - fn Brightness(c: vec3) -> f32 { - var c1: vec3; - - c1 = c; - let e8: vec3 = c1; - let e10: vec3 = c1; - let e12: vec3 = c1; - let e14: vec3 = c1; - let e17: vec3 = c1; - let e19: vec3 = c1; - let e21: vec3 = c1; - let e23: vec3 = c1; - let e25: vec3 = c1; - let e28: vec3 = c1; - return max(max(e23.x, e25.y), e28.z); - } - - fn main1() { - var uv: vec2; - var LinearColor: vec4; - var TotalLuminance: f32; - var BloomLuminance: f32; - var BloomAmount: f32; - - let e6: vec2 = fragUV1; - uv = e6.xy; - let e11: vec2 = uv; - uv.y = (1.0 - e11.y); - let e15: vec2 = uv; - let e16: vec4 = textureSample(baseMap, baseMapSampler, e15); - LinearColor = e16; - let e18: vec4 = LinearColor; - let e27: vec4 = LinearColor; - let e36: vec4 = LinearColor; - let e38: vec3 = min(vec3(f32(65000), f32(65000), f32(65000)), e36.xyz); - LinearColor.x = e38.x; - LinearColor.y = e38.y; - LinearColor.z = e38.z; - let e45: vec4 = LinearColor; - let e47: vec4 = LinearColor; - let e49: f32 = Brightness(e47.xyz); - TotalLuminance = e49; - let e51: f32 = TotalLuminance; - let e52: f32 = global.luminosityThreshold; - BloomLuminance = (e51 - e52); - let e55: f32 = BloomLuminance; - let e60: f32 = BloomLuminance; - BloomAmount = clamp((e60 * 0.5), 0.0, 1.0); - let e67: f32 = BloomAmount; - let e68: vec4 = LinearColor; - o_Target = vec4((e67 * e68.xyz), f32(0)); - return; - } - - @fragment - fn main(@location(0) fragUV: vec2) -> FragmentOutput { - fragUV1 = fragUV; - main1(); - let e13: vec4 = o_Target; - return FragmentOutput(e13); - } - `; - - - public static Bloom_blur_frag_wgsl: string = /* wgsl */ ` - struct uniformData { - texSize: vec2, - hScale: f32, - vScale: f32, - horizontal: f32 - }; - - struct FragmentOutput { - @location(0) o_Target: vec4 - }; - - var fragUV1: vec2; - var o_Target: vec4; - @group(1) @binding(0) - var baseMapSampler: sampler; - @group(1) @binding(1) - var baseMap: texture_2d; - @group(2) @binding(0) - var global: uniformData; - - fn main1() { - - return; - } - - const buffer1: array = array(0.22702699899673462, 0.194594606757164, 0.12162160128355026, 0.05405399948358536, 0.01621600054204464); - - @fragment - fn main(@location(0) fragUV: vec2) -> FragmentOutput { - var result: vec3; - var i: i32 = 1; - var j: i32 = 1; - var uv: vec2 = fragUV; - uv.y = (1.0 - uv.y); - var tex_offset: vec2 = (vec2(1.0) / vec2(global.texSize)); - let color: vec4 = textureSample(baseMap, baseMapSampler, uv); - result = (color.xyz * buffer1[0]); - - if ((global.horizontal > 1.0)) { - { - loop { - if (!((i < 5))) { - break; - } - { - let c1: vec4 = textureSample(baseMap, baseMapSampler, (uv + vec2(((tex_offset.x * f32(i)) * global.hScale), 0.0))); - result = (result + (c1.xyz * buffer1[i])); - let e101: vec4 = textureSample(baseMap, baseMapSampler, (uv - vec2(((tex_offset.x * f32(i)) * global.hScale), 0.0))); - result = (result + (e101.xyz * buffer1[i])); - } - continuing { - i = (i + 1); - } - } - } - } - if ((global.horizontal < 1.0)) { - { - loop { - let e114: i32 = j; - if (!((e114 < 5))) { - break; - } - { - let e144: vec4 = textureSample(baseMap, baseMapSampler, (uv + vec2(0.0, ((tex_offset.y * f32(j)) * global.vScale)))); - result = (result + (e144.xyz * buffer1[j])); - let e175: vec4 = textureSample(baseMap, baseMapSampler, (uv - vec2(0.0, ((tex_offset.y * f32(j)) * global.vScale)))); - result = (result + (e175.xyz * buffer1[j])); - } - continuing { - j = (j + 1); - } - } - } - } - o_Target = vec4(result, 1.0); - return FragmentOutput(o_Target); - } - `; - - public static Bloom_composite_frag_wgsl: string = /* wgsl */ ` - #include "ColorUtil" - struct UniformData { - tintColor:vec4, - bloomStrength: f32, - exposure: f32, - bloomRadius: f32, - }; - - struct FragmentOutput { - @location(0) o_Target: vec4 - }; - - var fragUV1: vec2; - var o_Target: vec4; - @group(1) @binding(0) - var baseMapSampler: sampler; - @group(1) @binding(1) - var baseMap: texture_2d; - @group(1) @binding(2) - var blurTex1Sampler: sampler; - @group(1) @binding(3) - var blurTex1: texture_2d; - @group(1) @binding(4) - var blurTex2Sampler: sampler; - @group(1) @binding(5) - var blurTex2: texture_2d; - @group(1) @binding(6) - var blurTex3Sampler: sampler; - @group(1) @binding(7) - var blurTex3: texture_2d; - @group(1) @binding(8) - var blurTex4Sampler: sampler; - @group(1) @binding(9) - var blurTex4: texture_2d; - @group(1) @binding(10) - var blurTex5Sampler: sampler; - @group(1) @binding(11) - var blurTex5: texture_2d; - @group(2) @binding(0) - var global: UniformData; - - const bloomFactors = array(1.0, 0.800000011920929, 0.6000000238418579, 0.4000000059604645, 0.20000000298023224); - - fn lerpBloomFactor(factor: f32) -> f32 { - var mirrorFactor: f32 = (1.2000000476837158 - factor); - return mix(factor, mirrorFactor, global.bloomRadius); - } - - fn main1() { - - return; - } - - @fragment - fn main(@location(0) fragUV: vec2) -> FragmentOutput { - var uv: vec2 = fragUV; - uv.y = (1.0 - uv.y); - - let e38: f32 = lerpBloomFactor(bloomFactors[0]); - let e46: vec4 = textureSample(blurTex1, blurTex1Sampler, uv); - let e52: f32 = lerpBloomFactor(bloomFactors[1]); - let e60: vec4 = textureSample(blurTex2, blurTex2Sampler, uv); - let e67: f32 = lerpBloomFactor(bloomFactors[2]); - let e75: vec4 = textureSample(blurTex3, blurTex3Sampler, uv); - let e82: f32 = lerpBloomFactor(bloomFactors[3]); - let e90: vec4 = textureSample(blurTex4, blurTex4Sampler, uv); - let e97: f32 = lerpBloomFactor(bloomFactors[4]); - let e105: vec4 = textureSample(blurTex5, blurTex5Sampler, uv); - o_Target = ((((((((e38 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[0], 1.0)) * e46) + ((e52 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[1], 1.0)) * e60)) + ((e67 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[2], 1.0)) * e75)) + ((e82 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[3], 1.0)) * e90)) + ((e97 * vec4(array,5>(vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0))[4], 1.0)) * e105)))); - - let baseColor: vec4 = textureSample(baseMap, baseMapSampler, uv); - - var bloomLight = global.bloomStrength * o_Target.rgb; - - bloomLight = getHDRColor(bloomLight.rgb,global.exposure); - bloomLight = LinearToGammaSpace(bloomLight); - - o_Target = baseColor + vec4(bloomLight * global.tintColor.rgb, baseColor.a) ; - o_Target.a = min(o_Target.a,1.0); - return FragmentOutput(o_Target); - } - `; -} \ No newline at end of file diff --git a/src/assets/shader/post/GlobalFog_shader.ts b/src/assets/shader/post/GlobalFog_shader.ts index d3a4da3e..7b38703e 100644 --- a/src/assets/shader/post/GlobalFog_shader.ts +++ b/src/assets/shader/post/GlobalFog_shader.ts @@ -4,6 +4,8 @@ import { GlobalUniform } from "../core/common/GlobalUniform"; * @internal */ export let GlobalFog_shader = /* wgsl */ ` +var PI: f32 = 3.14159265359; + struct FragmentOutput { @location(0) o_Target: vec4 }; diff --git a/src/assets/shader/utils/ColorUtil.ts b/src/assets/shader/utils/ColorUtil.ts index 719b8229..b2fc1803 100644 --- a/src/assets/shader/utils/ColorUtil.ts +++ b/src/assets/shader/utils/ColorUtil.ts @@ -97,6 +97,14 @@ export let ColorUtil: string = /*wgsl*/ ` } } + fn BlendNormalRNM( n1:vec3f, n2:vec3f) -> vec3f + { + let t = n1.xyz + vec3f(0.0, 0.0, 1.0); + let u = n2.xyz * vec3f(-1.0, -1.0, 1.0); + let r = (t / t.z) * dot(t, u) - u; + return r; + } + // fn ReorientedBlendNormal(){ // vec3 t = texture(baseMap, uv).xyz * vec3( 2.0, 2.0, 2.0) + vec3(-1.0, -1.0, 0.0); // vec3 u = texture(detailMap, uv).xyz * vec3(-2.0, -2.0, 2.0) + vec3( 1.0, 1.0, -1.0); diff --git a/src/components/SkeletonAnimationComponent.ts b/src/components/SkeletonAnimationComponent.ts index b94cfcca..d30e6b5f 100644 --- a/src/components/SkeletonAnimationComponent.ts +++ b/src/components/SkeletonAnimationComponent.ts @@ -1,3 +1,4 @@ +import { RegisterComponent } from ".."; import { Object3D } from "../core/entities/Object3D"; import { StorageGPUBuffer } from "../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; import { Time } from "../util/Time"; @@ -11,6 +12,7 @@ import { SkeletonPose } from "./anim/skeletonAnim/SkeletonPose"; * skeleton animation * @group Animation */ +@RegisterComponent export class SkeletonAnimationComponent extends ComponentBase { /** * Whether it is playing diff --git a/src/components/anim/AnimatorComponent.ts b/src/components/anim/AnimatorComponent.ts new file mode 100644 index 00000000..d03ae871 --- /dev/null +++ b/src/components/anim/AnimatorComponent.ts @@ -0,0 +1,286 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { BoxGeometry, DEGREES_TO_RADIANS, Engine3D, LitMaterial, Matrix4, MeshFilter, MeshRenderer, Object3D, PrefabAvatarData, Quaternion, RenderNode, RendererBase, Skeleton, SkeletonPose, SkinnedMeshRenderer2, StorageGPUBuffer, Time, Vector2, Vector3, Vector4, View3D, makeMatrix44 } from "../.."; +import { PropertyAnimationClip } from "../../math/AnimationCurveClip"; +import { RegisterComponent } from "../../util/SerializeDecoration"; +import { ComponentBase } from "../ComponentBase"; + +@RegisterComponent +export class AnimatorComponent extends ComponentBase { + public jointMatrixIndexTableBuffer: StorageGPUBuffer; + public playBlendShapeLoop: boolean = false; + protected inverseBindMatrices: Float32Array[]; + protected _avatar: PrefabAvatarData; + protected _rendererList: SkinnedMeshRenderer2[]; + protected propertyCache: Map + + protected _clips: PropertyAnimationClip[]; + protected _clipsMap: Map; + protected _currentSkeletonClip: PropertyAnimationClip; + protected _currentBlendAnimClip: PropertyAnimationClip; + + private _skeletonTime: number = 0; + private _blendShapeTime: number = 0; + private _skeletonSpeed: number = 1; + private _blendShapeSpeed: number = 1; + private _skeletonStart: boolean = true; + private _blendShapeStart: boolean = true; + root: Object3D; + private _avatarName: string; + + public init(param?: any): void { + this.propertyCache = new Map(); + this._clipsMap = new Map(); + this._clips = []; + } + + public start(): void { + this._rendererList = this.object3D.getComponentsInChild(SkinnedMeshRenderer2); + } + + private debug() { + } + + playAnim(anim: string, time: number = 0, speed: number = 1) { + if (this._clipsMap.has(anim)) { + this._currentSkeletonClip = this._clipsMap.get(anim); + this._skeletonTime = time; + this._skeletonSpeed = speed; + this._skeletonStart = true; + } else { + console.warn(`not has anim ${anim}`); + } + } + + playBlendShape(shapeName: string, time: number = 0, speed: number = 1) { + if (this._clipsMap.has(shapeName)) { + this._currentBlendAnimClip = this._clipsMap.get(shapeName); + this._blendShapeTime = time; + this._blendShapeSpeed = speed; + this._blendShapeStart = true; + } else { + console.warn(`not has blendShape ${shapeName}`); + } + } + + public set avatar(name: string) { + this._avatarName = name; + this.inverseBindMatrices = []; + + this._avatar = Engine3D.res.getObj(name) as PrefabAvatarData; + + let jointMapping = this.buildSkeletonPose(); + const jointMatrixIndexTable = new Float32Array(jointMapping); + this.jointMatrixIndexTableBuffer = new StorageGPUBuffer(this._avatar.count, 0, jointMatrixIndexTable); + } + + public getJointIndexTable(skinJointsName: Array) { + let result = new Array(); + for (let i = 0; i < skinJointsName.length; i++) { + let joint = this._avatar.boneMap.get(skinJointsName[i]); + result[i] = joint ? joint.boneID : -1; + } + return result; + } + + private skeltonPoseObject3D: { [name: string]: Object3D } = {}; + private skeltonTPoseObject3D: { [name: string]: Object3D } = {}; + private buildSkeletonPose(): number[] { + let list = []; + for (const joint of this._avatar.boneData) { + let obj = new Object3D(); + + Matrix4.getEuler(Vector3.HELP_6, joint.q, true, 'ZYX'); + obj.localPosition = joint.t.clone(); + obj.localRotation = Vector3.HELP_6.clone(); + obj.localScale = Vector3.ONE; joint.s.clone(); + + this.skeltonPoseObject3D[joint.boneName] = obj; + this.skeltonTPoseObject3D[joint.bonePath] = obj.clone(); + + if (joint.parentBoneName && joint.parentBoneName != "") { + this.skeltonPoseObject3D[joint.parentBoneName].addChild(obj); + } else { + // this.object3D.addChild(obj); + if (this.object3D.transform.scene3D) { + this.object3D.transform.scene3D.addChild(obj); + } + this.root = obj; + } + + list.push(obj.transform.worldMatrix.index); + let local = new Matrix4(); + local.copyFrom(obj.transform.worldMatrix); + local.invert(); + this.inverseBindMatrices.push(local.rawData); + } + + // GUIHelp.endFolder(); + + return list; + } + + public set clips(clips: PropertyAnimationClip[]) { + this._clips = clips; + for (const clip of clips) { + this._clipsMap.set(clip.clipName, clip); + } + // this.playAnim(clips[0].clipName); + } + + public get clips(): PropertyAnimationClip[] { + return this._clips; + } + + public cloneTo(obj: Object3D): void { + let animatorComponent = obj.addComponent(AnimatorComponent); + animatorComponent.avatar = this._avatarName; + animatorComponent.clips = this._clips; + } + + private updateTime() { + if (this._skeletonStart) { + this._skeletonTime += Time.delta * 0.001 * this._skeletonSpeed; + if (this._currentSkeletonClip && this._currentSkeletonClip.loopTime) { + this._skeletonTime = this._skeletonTime % this._currentSkeletonClip.stopTime; + } + } + + if (this._blendShapeStart) { + this._blendShapeTime += Time.delta * 0.001 * this._blendShapeSpeed; + if (this._currentBlendAnimClip) { + if (this._currentBlendAnimClip.loopTime && this.playBlendShapeLoop) { + this._blendShapeTime = this._blendShapeTime % this._currentBlendAnimClip.stopTime; + } else { + this._blendShapeTime = Math.min(this._blendShapeTime, this._currentBlendAnimClip.stopTime) - 0.0001; + } + } + } + } + + public onUpdate(view?: View3D) { + let worldMatrix = this.transform.worldMatrix; + // this.root.x = -worldMatrix.position.x ; + // this.root.y = -worldMatrix.position.y ; + // this.root.z = -worldMatrix.position.z ; + + this.updateTime(); + this.updateSkeletonAnim(); + this.updateMorphAnim(); + } + + private updateSkeletonAnim() { + if (this._currentSkeletonClip) { + let joints = this._avatar.boneData; + let i = 0; + let len = joints.length; + for (i = 0; i < len; i++) { + const joint = joints[i]; + let obj = this.skeltonPoseObject3D[joint.boneName]; + + if (this._currentSkeletonClip.useSkeletonPos) { + let pos = this.getPosition(joint.bonePath, this._skeletonTime); + obj.transform.localPosition = pos; + } + + let rot = this.getRotation(joint.bonePath, this._skeletonTime); + obj.transform.localRotation = rot; + + if (this._currentSkeletonClip.useSkeletonScale) { + let scale = this.getScale(joint.bonePath, this._skeletonTime); + obj.transform.localScale = scale; + } + } + } + } + + private updateMorphAnim() { + if (this._currentBlendAnimClip && this._currentBlendAnimClip.floatCurves) { + if (this._currentBlendAnimClip.floatCurves.size > 0 && this._rendererList) { + for (const iterator of this._currentBlendAnimClip.floatCurves) { + let key = iterator[0]; + let curve = iterator[1]; + let attributes = curve.propertys; + + let x = this._currentBlendAnimClip.floatCurves.get(key).getValue(this._blendShapeTime) as number; + let value = x / 100; + for (const renderer of this._rendererList) { + if (renderer.blendShape) { + let property: any = this.propertyCache.get(renderer); + if (property && key in property) { + property[key](value); + } else { + property = renderer; + for (const att of attributes) { + if (!property[att]) + break; + property = property[att]; + } + if (!property || property == renderer) break; + + if (!this.propertyCache.get(renderer)) + this.propertyCache.set(renderer, {}) + this.propertyCache.get(renderer)[key] = property; + property(value); + } + } + } + } + } + } + } + + public updateBlendShape(attributes: string[], key: string, value: number) { + for (const renderer of this._rendererList) { + if (renderer.blendShape) { + let property: any = this.propertyCache.get(renderer); + if (property && key in property) { + property[key](value); + } else { + property = renderer; + for (const att of attributes) { + if (!property[att]) + break; + property = property[att]; + } + if (!property || property == renderer) break; + + if (!this.propertyCache.get(renderer)) + this.propertyCache.set(renderer, {}) + this.propertyCache.get(renderer)[key] = property; + property(value); + } + } + } + } + + private getPosition(boneName: string, time: number) { + if (this._currentSkeletonClip.positionCurves.has(boneName)) { + let t = this._currentSkeletonClip.positionCurves.get(boneName).getValue(time) as Vector3; + return t; + } + return this.skeltonTPoseObject3D[boneName].localPosition; + } + + private getRotation(boneName: string, time: number) { + if (this._currentSkeletonClip.rotationCurves.has(boneName)) { + let v4 = this._currentSkeletonClip.rotationCurves.get(boneName).getValue(time) as Vector4; + Quaternion.HELP_2.set(v4.x, v4.y, v4.z, v4.w); + Matrix4.getEuler(Vector3.HELP_6, Quaternion.HELP_2, true, 'ZYX'); + return Vector3.HELP_6; + } + return this.skeltonTPoseObject3D[boneName].localRotation; + } + + private getScale(boneName: string, time: number) { + if (this._currentSkeletonClip.scaleCurves.has(boneName)) { + let x = this._currentSkeletonClip.scaleCurves.get(boneName).getValue(time) as Vector3; + return x; + } + return this.skeltonTPoseObject3D[boneName].localScale; + } + + private getFloat(propertyName: string, time: number) { + let x = this._currentSkeletonClip.floatCurves.get(propertyName).getValue(time) as number; + return x; + } +} \ No newline at end of file diff --git a/src/components/anim/morphAnim/MorphTargetBlender.ts b/src/components/anim/morphAnim/MorphTargetBlender.ts index 7e1af99a..ec0e05fd 100644 --- a/src/components/anim/morphAnim/MorphTargetBlender.ts +++ b/src/components/anim/morphAnim/MorphTargetBlender.ts @@ -5,17 +5,22 @@ import { Quaternion } from "../../../math/Quaternion"; import { Vector3 } from "../../../math/Vector3"; import { ComponentBase } from "../../ComponentBase"; import { MorphTargetFrame } from "./MorphTargetFrame"; -import { MeshRenderer } from "../../renderer/MeshRenderer"; +import { SkinnedMeshRenderer2 } from "../../renderer/SkinnedMeshRenderer2"; import { RendererMask, RendererMaskUtil } from "../../../gfx/renderJob/passRenderer/state/RendererMask"; +import { Ctor } from "../../../util/Global"; +import { MeshRenderer } from "../../renderer/MeshRenderer"; export class MorphTargetBlender extends ComponentBase { - private _targetRenderers: { [key: string]: MeshRenderer[] } = {}; + private _targetRenderers: { [key: string]: SkinnedMeshRenderer2[] } = {}; private _vec3 = new Vector3(); private _matrix4: Matrix4 = new Matrix4(); private _quaternion: Quaternion = new Quaternion(); public init(param?: any): void { - let meshRenders: MeshRenderer[] = this.fetchMorphRenderers(this.object3D); + let meshRenders: SkinnedMeshRenderer2[] = this.fetchMorphRenderers(this.object3D, SkinnedMeshRenderer2); + let meshRenders2: MeshRenderer[] = this.fetchMorphRenderers(this.object3D, MeshRenderer); + meshRenders.push(...meshRenders2 as any); + for (const renderer of meshRenders) { let hasMorphTarget = RendererMaskUtil.hasMask(renderer.rendererMask, RendererMask.MorphTarget); if (hasMorphTarget) { @@ -30,11 +35,11 @@ export class MorphTargetBlender extends ComponentBase { } - public getMorphRenderersByKey(key: string): MeshRenderer[] { + public getMorphRenderersByKey(key: string): SkinnedMeshRenderer2[] { return this._targetRenderers[key]; } - public cloneMorphRenderers(): { [key: string]: MeshRenderer[] } { + public cloneMorphRenderers(): { [key: string]: SkinnedMeshRenderer2[] } { let dst = {} as any; for (let key in this._targetRenderers) { dst[key] = this._targetRenderers[key]; @@ -79,15 +84,15 @@ export class MorphTargetBlender extends ComponentBase { } } - private applyMorphTargetInfluence(key: string, influence: number, rendererList: MeshRenderer[]): void { + private applyMorphTargetInfluence(key: string, influence: number, rendererList: SkinnedMeshRenderer2[]): void { for (let renderer of rendererList) { renderer.setMorphInfluence(key, influence); } } - private fetchMorphRenderers(obj: Object3D): MeshRenderer[] { - let sourceRenders: MeshRenderer[] = obj.getComponentsInChild(MeshRenderer); - let result: MeshRenderer[] = []; + private fetchMorphRenderers(obj: Object3D, c: Ctor): T[] { + let sourceRenders: T[] = obj.getComponentsInChild(c); + let result: T[] = []; for (let renderer of sourceRenders) { if (renderer.hasMask(RendererMask.MorphTarget)) { result.push(renderer); diff --git a/src/components/anim/morphAnim/MorphTargetData.ts b/src/components/anim/morphAnim/MorphTargetData.ts index af274400..e82d4e8b 100644 --- a/src/components/anim/morphAnim/MorphTargetData.ts +++ b/src/components/anim/morphAnim/MorphTargetData.ts @@ -3,7 +3,7 @@ import { UniformGPUBuffer } from '../../../gfx/graphics/webGpu/core/buffer/Unifo import { MorphTarget_shader } from '../../../components/anim/morphAnim/MorphTarget_shader'; import { ComputeShader } from '../../../gfx/graphics/webGpu/shader/ComputeShader'; import { GPUContext } from '../../../gfx/renderJob/GPUContext'; -import { RenderShader } from '../../../gfx/graphics/webGpu/shader/RenderShader'; +import { RenderShaderPass } from '../../../gfx/graphics/webGpu/shader/RenderShaderPass'; import { GeometryBase } from '../../../core/geometry/GeometryBase'; import { VertexAttributeData } from '../../../core/geometry/VertexAttributeData'; @@ -67,6 +67,9 @@ export class MorphTargetData { protected _collectMorphTargetData: MorphTargetCollectData; + private _blendTarget: { [key: string]: any } + + constructor() { this._isInfluenceDirty = true; this.generateGPUBuffer(); @@ -97,7 +100,7 @@ export class MorphTargetData { this._normalAttrDataGroup.reset(this._collectMorphTargetData.mergedNormal); } - public applyRenderShader(renderShader: RenderShader) { + public applyRenderShader(renderShader: RenderShaderPass) { this.uploadMorphTargetBuffer(); this.uploadConfigGBuffer(); // @@ -125,7 +128,9 @@ export class MorphTargetData { this._computeShader.workerSizeY = this._computeWorkGroupXY; this._computeShader.workerSizeZ = 1; + // if (false) { GPUContext.computeCommand(command, this._computeShaders); + // } } public updateInfluence(index: number, value: number) { @@ -133,11 +138,25 @@ export class MorphTargetData { this._morphInfluenceArray[index] = value; } + public get blendShape() { + return this._blendTarget; + } + private collectMorphTargetList(geometry: GeometryBase): MorphTargetCollectData { let posAttrList = this.collectAttribute('a_morphPositions_', geometry); let morphTargetCount = posAttrList.length; let vertexCount: number = posAttrList[0].data.length / 3; + this._blendTarget = {}; + if (geometry.blendShapeData) { + for (let i = 0; i < geometry.blendShapeData.shapeIndexs.length; i++) { + let index = geometry.blendShapeData.shapeIndexs[i]; + let shapeNames = geometry.blendShapeData.shapeNames[i].split("."); + let shapeName = shapeNames[shapeNames.length - 1]; + this._blendTarget[shapeName] = (value) => this.updateInfluence(index, value); + } + } + //position let posArray: Float32Array = new Float32Array(vertexCount * morphTargetCount * 3); { diff --git a/src/components/anim/morphAnim/MorphTargetKey.ts b/src/components/anim/morphAnim/MorphTargetKey.ts index 25807687..fcc9443c 100644 --- a/src/components/anim/morphAnim/MorphTargetKey.ts +++ b/src/components/anim/morphAnim/MorphTargetKey.ts @@ -52,3 +52,58 @@ export type MorphTargetStandardKey = 'cheekPuff' | 'mouthPress_R' | 'mouthSmile_R'; + +export enum MorphTargetTransformKey { + 'mouthRollLower' = "mouthRollLower", + 'browOuterUp_L' = "browOuterUpLeft", + 'mouthSmile_L' = "mouthSmileLeft", + 'jawRight' = "jawRight", + 'eyeLookOut_L' = "eyeLookOutLeft", + 'mouthFunnel' = "mouthFunnel", + 'mouthUpperUp_R' = "mouthUpperUpRight", + 'browDown_L' = "browDownLeft", + 'jawLeft' = "jawLeft", + 'mouthLowerDown_L' = "mouthLowerDownLeft", + 'noseSneer_R' = "noseSneerRight", + 'jawForward' = "jawForward", + 'mouthLowerDown_R' = "mouthLowerDownRight", + 'browInnerUp' = "browInnerUp", + 'mouthRollUpper' = "mouthRollUpper", + 'mouthStretch_R' = "mouthStretchRight", + 'mouthPucker' = "mouthPucker", + 'eyeBlink_L' = "eyeBlinkLeft", + 'mouthUpperUp_L' = "mouthUpperUpLeft", + 'mouthShrugUpper' = "mouthShrugUpper", + 'eyeLookIn_R' = "eyeLookInRight", + 'noseSneer_L' = "noseSneerLeft", + 'mouthFrown_L' = "mouthFrownLeft", + 'cheekSquint_L' = "cheekSquintLeft", + 'eyeLookDown_L' = "eyeLookDownLeft", + 'mouthDimple_L' = "mouthDimpleLeft", + 'mouthFrown_R' = "mouthFrownRight", + 'eyeLookIn_L' = "eyeLookInLeft", + 'eyeLookOut_R' = "eyeLookOutRight", + 'mouthLeft' = "mouthLeft", + 'mouthStretch_L' = "mouthStretchLeft", + 'mouthPress_L' = "mouthPressLeft", + 'mouthDimple_R' = "mouthDimpleRight", + 'eyeWide_R' = "eyeWideRight", + 'browDown_R' = "browDownRight", + 'eyeLookUp_R' = "eyeLookUpRight", + 'eyeBlink_R' = "eyeBlinkRight", + 'cheekSquint_R' = "cheekSquintRight", + 'mouthRight' = "mouthDimpleRight", + 'eyeLookDown_R' = "eyeLookDownRight", + 'eyeLookUp_L' = "eyeLookUpLeft", + 'eyeSquint_L' = "eyeSquintLeft", + 'jawOpen' = "jawOpen", + 'browOuterUp_R' = "browOuterUpRight", + 'mouthClose' = "mouthClose", + 'mouthShrugLower' = "mouthShrugLower", + 'eyeWide_L' = "eyeWideLeft", + 'tongueOut' = "tongueOut", + 'eyeSquint_R' = "eyeSquintRight", + 'cheekPuff' = "cheekPuff", + 'mouthPress_R' = "mouthPressRight", + 'mouthSmile_R' = "mouthSmileRight", +} \ No newline at end of file diff --git a/src/components/anim/skeletonAnim/Joint.ts b/src/components/anim/skeletonAnim/Joint.ts index 4a08a0af..170da8fc 100644 --- a/src/components/anim/skeletonAnim/Joint.ts +++ b/src/components/anim/skeletonAnim/Joint.ts @@ -17,6 +17,11 @@ export class Joint { */ public index: number = 0; + /** + * Bone instanceID + */ + public instanceID: string = ""; + /** * The parent of a bone joint */ @@ -25,7 +30,7 @@ export class Joint { /** * Bone joint child object */ - public children: Array = []; + // public children: Array = []; /** * The scaling value of the bone joint diff --git a/src/components/anim/skeletonAnim/SkeletonPose.ts b/src/components/anim/skeletonAnim/SkeletonPose.ts index f398a292..f439e690 100644 --- a/src/components/anim/skeletonAnim/SkeletonPose.ts +++ b/src/components/anim/skeletonAnim/SkeletonPose.ts @@ -10,109 +10,117 @@ import { Skeleton } from './Skeleton'; * @group Animation */ export class SkeletonPose { - /** - * time of this pose in owner animation clip - */ - public time: number; - protected _skeleton: Skeleton; - protected _jointsPose: Array; - protected mJointMatrixIndexTable: Array; + /** + * time of this pose in owner animation clip + */ + public time: number; + protected _skeleton: Skeleton; + protected _jointsPose: Array; + protected mJointMatrixIndexTable: Array; - constructor(skeleton: Skeleton, useGlobalMatrix: boolean = false) { - this._skeleton = skeleton; - this._jointsPose = new Array(skeleton.numJoint); - this.mJointMatrixIndexTable = new Array(skeleton.numJoint); - for (let index = 0; index < skeleton.numJoint; index++) { - let joint = new JointPose(index, useGlobalMatrix); - this._jointsPose[index] = joint; - this.mJointMatrixIndexTable[index] = joint.worldMatrix.index; + constructor(skeleton: Skeleton, useGlobalMatrix: boolean = false) { + this._skeleton = skeleton; + this._jointsPose = new Array(skeleton.numJoint); + this.mJointMatrixIndexTable = new Array(skeleton.numJoint); + for (let index = 0; index < skeleton.numJoint; index++) { + let joint = new JointPose(index, useGlobalMatrix); + this._jointsPose[index] = joint; + this.mJointMatrixIndexTable[index] = joint.worldMatrix.index; + } } - } - /** - * build this pose from float32 array data - */ - public buildSkeletonPose(poseData: Float32Array) { - let scale = new Vector3(); - let rotation = new Quaternion(); - let translation = new Vector3(); - let jointLocalMatrix = new Array(this._skeleton.numJoint); - this.time = poseData[11] > 0 ? poseData[11] : poseData[24]; - for (let jointIndex = 0; jointIndex < this._skeleton.numJoint; jointIndex++) { - let byteOffset = 12 * jointIndex * 4; - let jointData = new Float32Array(poseData.buffer, poseData.byteOffset + byteOffset, 12); + /** + * build this pose from float32 array data + */ + public buildSkeletonPose(poseData: Float32Array) { + let scale = new Vector3(); + let rotation = new Quaternion(); + let translation = new Vector3(); + let jointLocalMatrix = new Array(this._skeleton.numJoint); + this.time = poseData[11] > 0 ? poseData[11] : poseData[24]; + for (let jointIndex = 0; jointIndex < this._skeleton.numJoint; jointIndex++) { + let byteOffset = 12 * jointIndex * 4; + let jointData = new Float32Array(poseData.buffer, poseData.byteOffset + byteOffset, 12); - let localMatrix = new Matrix4(); - scale.set(jointData[0], jointData[1], jointData[2]); - rotation.set(jointData[4], jointData[5], jointData[6], jointData[7]); - translation.set(jointData[8], jointData[9], jointData[10]); - makeMatrix44(rotation.getEulerAngles(), translation, scale, localMatrix); - jointLocalMatrix[jointIndex] = localMatrix; + let localMatrix = new Matrix4(); + scale.set(jointData[0], jointData[1], jointData[2]); + rotation.set(jointData[4], jointData[5], jointData[6], jointData[7]); + translation.set(jointData[8], jointData[9], jointData[10]); + makeMatrix44(rotation.getEulerAngles(), translation, scale, localMatrix); + jointLocalMatrix[jointIndex] = localMatrix; - let joint = new JointPose(jointIndex); - const nParentIndex = this._skeleton.getJointParentIndex(jointIndex); - if (nParentIndex < 0) { - joint.worldMatrix.copyFrom(localMatrix); - } else { - let parentJoint = this._jointsPose[nParentIndex]; - multiplyMatrices4x4REF(parentJoint.worldMatrix, localMatrix, joint.worldMatrix); - } - this._jointsPose[jointIndex] = joint; + let joint = new JointPose(jointIndex); + const nParentIndex = this._skeleton.getJointParentIndex(jointIndex); + if (nParentIndex < 0) { + joint.worldMatrix.copyFrom(localMatrix); + } else { + let parentJoint = this._jointsPose[nParentIndex]; + multiplyMatrices4x4REF(parentJoint.worldMatrix, localMatrix, joint.worldMatrix); + } + this._jointsPose[jointIndex] = joint; + } } - } - /** - * Returns joints count of owner skeleton - */ - public get numJoint(): number { - return this._skeleton.numJoint; - } + /** + * Returns joints count of owner skeleton + */ + public get numJoint(): number { + return this._skeleton.numJoint; + } - /** - * Returns all joint pose - */ - public get joints(): Array { - return this._jointsPose; - } + /** + * Returns all joint pose + */ + public get joints(): Array { + return this._jointsPose; + } - /** - * Returns list of matrix's index - */ - public get jointMatrixIndexTable(): Array { - return this.mJointMatrixIndexTable; - } + /** + * Returns list of matrix's index + */ + public get jointMatrixIndexTable(): Array { + return this.mJointMatrixIndexTable; + } - /** - * Returns lerped skeletonPose from pose a to pose b - * @param a selected pose No.1 - * @param b selected pose No.2 - * @param weight number - */ - public lerp(a: SkeletonPose, b: SkeletonPose, weight: number) { - for (let index = 0; index < this._jointsPose.length; index++) { - let jointA = a._jointsPose[index]; - let jointB = b._jointsPose[index]; - let jointDst = this._jointsPose[index]; - jointDst.worldMatrix.lerp(jointA.worldMatrix, jointB.worldMatrix, weight); + /** + * Returns lerped skeletonPose from pose a to pose b + * @param a selected pose No.1 + * @param b selected pose No.2 + * @param weight number + */ + public lerp(a: SkeletonPose, b: SkeletonPose, weight: number) { + if (a && b) { + for (let index = 0; index < this._jointsPose.length; index++) { + let jointA = a._jointsPose[index]; + let jointB = b._jointsPose[index]; + let jointDst = this._jointsPose[index]; + jointDst.worldMatrix.lerp(jointA.worldMatrix, jointB.worldMatrix, weight); + } + } else { + for (let index = 0; index < this._jointsPose.length; index++) { + let jointA = a._jointsPose[index]; + let jointDst = this._jointsPose[index]; + jointDst.worldMatrix.copyFrom(jointA.worldMatrix); + } + } } - } - /** - * Copy skeleton pose from other skeleton pose - * @param other source skeleton pose - */ - public copyFrom(other: SkeletonPose) { - for (let index = 0; index < this._jointsPose.length; index++) { - this._jointsPose[index].worldMatrix.copyFrom(other._jointsPose[index].worldMatrix) + /** + * Copy skeleton pose from other skeleton pose + * @param other source skeleton pose + */ + public copyFrom(other: SkeletonPose) { + for (let index = 0; index < this._jointsPose.length; index++) { + this._jointsPose[index].worldMatrix.copyFrom(other._jointsPose[index].worldMatrix) + } } - } - /** - * Reset this skeleton pose - */ - public reset() { - for (let index = 0; index < this._jointsPose.length; index++) { - this._jointsPose[index].worldMatrix.identity(); + /** + * Reset this skeleton pose + */ + public reset() { + for (let index = 0; index < this._jointsPose.length; index++) { + this._jointsPose[index].worldMatrix.identity(); + } } - } } diff --git a/src/components/controller/HoverCameraController.ts b/src/components/controller/HoverCameraController.ts index cae7ab7d..468a972c 100644 --- a/src/components/controller/HoverCameraController.ts +++ b/src/components/controller/HoverCameraController.ts @@ -96,6 +96,8 @@ export class HoverCameraController extends ComponentBase { * @internal */ private _targetPos: Object3D; + private _flowTarget: Object3D; + private _flowOffset: Vector3; private _mouseLeftDown: boolean = false; private _mouseRightDown: boolean = false; @@ -122,7 +124,16 @@ export class HoverCameraController extends ComponentBase { Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_MOVE, this.onMouseMove, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_UP, this.onMouseUp, this); Engine3D.inputSystem.addEventListener(PointerEvent3D.POINTER_WHEEL, this.onMouseWheel, this); + } + + public flowTarget(target: Object3D, offset: Vector3 = Vector3.ZERO) { + this._flowTarget = target; + this._flowOffset ||= new Vector3(); + this._flowOffset.copyFrom(offset); + } + public getFlowTarget(): Object3D { + return this._flowTarget; } /** @@ -227,6 +238,12 @@ export class HoverCameraController extends ComponentBase { if (!this.enable) return; + if (this._flowTarget) { + Vector3.HELP_0.copyFrom(this._flowTarget.transform.worldPosition); + Vector3.HELP_0.add(this._flowOffset, Vector3.HELP_0); + this.target = Vector3.HELP_0; + } + let dt = clamp(Time.delta, 0.0, 0.016); if (this.smooth) { this._currentPos.x += (this._targetPos.x - this._currentPos.x) * dt * this.dragSmooth; @@ -271,5 +288,6 @@ export class HoverCameraController extends ComponentBase { Engine3D.inputSystem.removeEventListener(PointerEvent3D.POINTER_WHEEL, this.onMouseWheel, this); super.destroy(force); this.camera = null; + this._flowTarget = null; } } diff --git a/src/components/gui/core/GUIGeometry.ts b/src/components/gui/core/GUIGeometry.ts index 0fbcf71d..f8bec48a 100644 --- a/src/components/gui/core/GUIGeometry.ts +++ b/src/components/gui/core/GUIGeometry.ts @@ -124,7 +124,10 @@ export class GUIGeometry extends GeometryBase { indexStart: 0, indexCount: this._faceIndexes.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); return this; } diff --git a/src/components/gui/core/GUIMaterial.ts b/src/components/gui/core/GUIMaterial.ts index 10e20c2c..ecf81945 100644 --- a/src/components/gui/core/GUIMaterial.ts +++ b/src/components/gui/core/GUIMaterial.ts @@ -1,12 +1,11 @@ -import { RendererType } from "../../.."; +import { PassType, Shader } from "../../.."; import { Engine3D } from "../../../Engine3D"; import { ShaderLib } from "../../../assets/shader/ShaderLib"; import { GPUCompareFunction, GPUCullMode } from "../../../gfx/graphics/webGpu/WebGPUConst"; import { Texture } from "../../../gfx/graphics/webGpu/core/texture/Texture"; -import { RenderShader } from "../../../gfx/graphics/webGpu/shader/RenderShader"; +import { RenderShaderPass } from "../../../gfx/graphics/webGpu/shader/RenderShaderPass"; import { BlendMode } from "../../../materials/BlendMode"; import { Material } from "../../../materials/Material"; -import { registerMaterial } from "../../../materials/MaterialRegister"; import { Vector2 } from "../../../math/Vector2"; import { Vector4 } from "../../../math/Vector4"; import { GUISpace } from "../GUIConfig"; @@ -26,8 +25,11 @@ export class GUIMaterial extends Material { ShaderLib.register('GUI_shader_view', GUIShader.GUI_shader_view); ShaderLib.register('GUI_shader_world', GUIShader.GUI_shader_world); + let newShader = new Shader(); + let shaderKey: string = space == GUISpace.View ? 'GUI_shader_view' : 'GUI_shader_world'; - let colorPass = new RenderShader(shaderKey, shaderKey); + let colorPass = new RenderShaderPass(shaderKey, shaderKey); + colorPass.passType = PassType.COLOR; colorPass.setShaderEntry(`VertMain`, `FragMain`); colorPass.setUniformVector2('screenSize', this._screenSize); @@ -44,47 +46,46 @@ export class GUIMaterial extends Material { colorPass.blendMode = BlendMode.ALPHA; colorPass.depthCompare = space == GUISpace.View ? GPUCompareFunction.always : GPUCompareFunction.less_equal; colorPass.cullMode = GPUCullMode.back; - + newShader.addRenderPass(colorPass); // colorPass.transparent = true; // colorPass.receiveEnv = false; - this.defaultPass = colorPass; - + this.shader = newShader; } /** * Write effective vertex count (vertex index < vertexCount) */ public setLimitVertex(vertexCount: number) { - this.defaultPass.setUniformFloat('limitVertex', vertexCount); + this.shader.setUniformFloat('limitVertex', vertexCount); } public setGUISolution(value: Vector2, pixelRatio: number) { - this.defaultPass.setUniformVector2('guiSolution', value); - this.defaultPass.setUniformFloat('pixelRatio', pixelRatio); + this.shader.setUniformVector2('guiSolution', value); + this.shader.setUniformFloat('pixelRatio', pixelRatio); } public setScissorRect(left: number, bottom: number, right: number, top: number) { this._scissorRect ||= new Vector4(); this._scissorRect.set(left, bottom, right, top); - this.defaultPass.setUniformVector4('scissorRect', this._scissorRect); + this.shader.setUniformVector4('scissorRect', this._scissorRect); } public setScissorEnable(value: boolean) { if (this._scissorEnable != value) { this._scissorEnable = value; if (value) { - this.defaultPass.setDefine("SCISSOR_ENABLE", true); + this.shader.setDefine("SCISSOR_ENABLE", true); } else { - this.defaultPass.deleteDefine('SCISSOR_ENABLE'); + this.shader.deleteDefine('SCISSOR_ENABLE'); } - this.defaultPass.noticeValueChange(); + this.shader.noticeValueChange(); } } public setScissorCorner(radius: number, fadeOut: number) { - this.defaultPass.setUniformFloat('scissorCornerRadius', radius); - this.defaultPass.setUniformFloat('scissorFadeOutSize', fadeOut); + this.shader.setUniformFloat('scissorCornerRadius', radius); + this.shader.setUniformFloat('scissorFadeOutSize', fadeOut); } /** @@ -92,7 +93,7 @@ export class GUIMaterial extends Material { */ public setScreenSize(width: number, height: number): this { this._screenSize.set(width, height); - this.defaultPass.setUniformVector2('screenSize', this._screenSize); + this.shader.setUniformVector2('screenSize', this._screenSize); return this; } @@ -102,7 +103,7 @@ export class GUIMaterial extends Material { public setTextures(list: Texture[]) { for (let i = 0; i < 7; i++) { let texture = list[i] || Engine3D.res.whiteTexture; - this.defaultPass.setTexture(`tex_${i}`, texture); + this.shader.setTexture(`tex_${i}`, texture); this.setVideoTextureDefine(i, texture.isVideoTexture); } } @@ -112,16 +113,16 @@ export class GUIMaterial extends Material { let changed = false; if (isVideoTexture != this._videoTextureFlags[i]) { if (isVideoTexture) { - this.defaultPass.setDefine(`VideoTexture${i}`, true); + this.shader.setDefine(`VideoTexture${i}`, true); } else { - this.defaultPass.deleteDefine(`VideoTexture${i}`); + this.shader.deleteDefine(`VideoTexture${i}`); } this._videoTextureFlags[i] = isVideoTexture; changed = true; } if (changed) { - this.defaultPass.noticeValueChange(); + this.shader.noticeValueChange(); } } diff --git a/src/components/gui/core/GUIRenderer.ts b/src/components/gui/core/GUIRenderer.ts index fa7af163..b53c5ca0 100644 --- a/src/components/gui/core/GUIRenderer.ts +++ b/src/components/gui/core/GUIRenderer.ts @@ -3,7 +3,7 @@ import { View3D } from "../../../core/View3D"; import { ClusterLightingBuffer } from "../../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; import { RendererMask } from "../../../gfx/renderJob/passRenderer/state/RendererMask"; import { RendererPassState } from "../../../gfx/renderJob/passRenderer/state/RendererPassState"; -import { RendererType } from "../../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../../gfx/renderJob/passRenderer/state/RendererType"; import { MeshRenderer } from "../../renderer/MeshRenderer"; import { GUIGeometry } from "./GUIGeometry"; @@ -48,7 +48,7 @@ export class GUIRenderer extends MeshRenderer { * @param renderPassState * @param clusterLightingBuffer */ - public nodeUpdate(view: View3D, rendererType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, rendererType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { for (let i = 0; i < this.materials.length; i++) { const material = this.materials[i]; let passes = material.getPass(rendererType); diff --git a/src/components/lights/DirectLight.ts b/src/components/lights/DirectLight.ts index d81c6ad2..848cb8e2 100644 --- a/src/components/lights/DirectLight.ts +++ b/src/components/lights/DirectLight.ts @@ -1,5 +1,6 @@ import { Camera3D } from '../../core/Camera3D'; import { UUID } from '../../util/Global'; +import { RegisterComponent } from '../../util/SerializeDecoration'; import { LightBase } from './LightBase'; import { LightType } from './LightData'; /** @@ -8,6 +9,7 @@ import { LightType } from './LightData'; *The light of this light source is parallel, for example, sunlight. This light source can generate shadows. * @group Lights */ +@RegisterComponent export class DirectLight extends LightBase { public shadowCamera: Camera3D; diff --git a/src/components/lights/Light.ts b/src/components/lights/Light.ts new file mode 100644 index 00000000..f1d1c1e4 --- /dev/null +++ b/src/components/lights/Light.ts @@ -0,0 +1,141 @@ +import { RegisterComponent } from '../..'; +import { Engine3D } from '../../Engine3D'; +import { View3D } from '../../core/View3D'; +import { Vector3 } from '../../math/Vector3'; +import { UUID } from '../../util/Global'; +import { LightBase } from './LightBase'; +import { LightType } from './LightData'; +/** + *Point light source. + *A single point light source that illuminates all directions. + *A common example is to simulate the light emitted by a light bulb, where a point light source cannot create shadows. + * @group Lights + */ +@RegisterComponent +export class Light extends LightBase { + + constructor() { + super(); + } + + public init(): void { + super.init(); + this.lightData.lightType = LightType.PointLight; + if (this.object3D.name == "") { + this.object3D.name = "PointLight" + UUID(); + } + } + + + /** + * + * Get the range of the light source + * @return {number} + */ + public get range(): number { + return this.lightData.range as number; + } + /** + * + * Set the range of the light source + * @param {number} + */ + public set range(value: number) { + this.lightData.range = value; + this.onChange(); + } + + /** + * + * Get the illumination distance of the light source + * @type {number} + * @memberof PointLight + */ + public get at(): number { + return this.lightData.linear as number; + } + + /** + * + * Set the illumination distance of the light source + * @param {value} It will decay linearly from the maximum value to the current light position at a distance of 0, + * with a default value of 0. This means that the intensity of the light will not decrease due to distance + * @memberof PointLight + */ + public set at(value: number) { + this.lightData.linear = value; + this.onChange(); + } + + /** + * Get the radius to control the light + */ + public get radius(): number { + return this.lightData.radius as number; + } + + /** + * Set the radius of the control light + */ + public set radius(value: number) { + this.lightData.radius = value; + this.onChange(); + } + + /** + * Get the radius to control the light + */ + public get quadratic(): number { + return this.lightData.quadratic as number; + } + + /** + * Set the radius of the control light + */ + public set quadratic(value: number) { + this.lightData.quadratic = value; + this.onChange(); + } + + + + public start(): void { + this.transform.rotationX = 90; + super.start(); + } + + public onUpdate(): void { + // this.transform.updateWorldMatrix(true); + } + + public onGraphic(view?: View3D): void { + let custom = view.graphic3D.createCustomShape( + `PointLight_${this.object3D.instanceID}`, + this.transform, + ); + custom.buildAxis(); + custom.buildCircle(Vector3.ZERO, this.range, 32, Vector3.X_AXIS); + custom.buildCircle(Vector3.ZERO, this.range, 32, Vector3.Y_AXIS); + custom.buildCircle(Vector3.ZERO, this.range, 32, Vector3.Z_AXIS); + } + + /** + * enable GUI debug + */ + public debug() { + } + + public debugDraw(show: boolean) { + // if (this.mShowDebugLine != show) { + // if (show) { + // this.drawDebugLine(); + // } else { + // let view = this.transform.view3D; + // view.graphic3D.Clear(`PointLight_${this.object3D.uuid}`); + // } + // this.mShowDebugLine = show; + // } + } + +} + diff --git a/src/components/lights/LightBase.ts b/src/components/lights/LightBase.ts index a5d942e1..48bc4f25 100644 --- a/src/components/lights/LightBase.ts +++ b/src/components/lights/LightBase.ts @@ -183,6 +183,24 @@ export class LightBase extends ComponentBase implements ILight { this.lightData.lightColor = value; this.onChange(); } + + /** + * Get light source color + * @return Color + */ + public get color(): Color { + return this.lightData.lightColor; + } + + /** + * Set light source color + * @param Color + */ + public set color(value: Color) { + this.lightData.lightColor = value; + this.onChange(); + } + /** * Get Illumination intensity of light source * @return number @@ -190,6 +208,7 @@ export class LightBase extends ComponentBase implements ILight { public get intensity(): number { return this.lightData.intensity as number; } + /** * Set Illumination intensity of light source * @param value diff --git a/src/components/lights/PointLight.ts b/src/components/lights/PointLight.ts index f6fd1f31..5e3cfe81 100644 --- a/src/components/lights/PointLight.ts +++ b/src/components/lights/PointLight.ts @@ -1,7 +1,7 @@ -import { Engine3D } from '../../Engine3D'; import { View3D } from '../../core/View3D'; import { Vector3 } from '../../math/Vector3'; import { UUID } from '../../util/Global'; +import { RegisterComponent } from '../../util/SerializeDecoration'; import { LightBase } from './LightBase'; import { LightType } from './LightData'; /** @@ -10,6 +10,7 @@ import { LightType } from './LightData'; *A common example is to simulate the light emitted by a light bulb, where a point light source cannot create shadows. * @group Lights */ +@RegisterComponent export class PointLight extends LightBase { constructor() { diff --git a/src/components/lights/SpotLight.ts b/src/components/lights/SpotLight.ts index 9f688031..a8060dc2 100644 --- a/src/components/lights/SpotLight.ts +++ b/src/components/lights/SpotLight.ts @@ -3,6 +3,7 @@ import { View3D } from '../../core/View3D'; import { clamp, DEGREES_TO_RADIANS, RADIANS_TO_DEGREES } from '../../math/MathUtil'; import { Vector3 } from '../../math/Vector3'; import { UUID } from '../../util/Global'; +import { RegisterComponent } from '../../util/SerializeDecoration'; import { LightBase } from './LightBase'; import { LightType } from './LightData'; @@ -12,6 +13,7 @@ import { LightType } from './LightData'; * Similar to a desk lamp, chandelier, or flashlight, this light source can produce shadows. * @group Lights */ +@RegisterComponent export class SpotLight extends LightBase { constructor() { super(); diff --git a/src/components/post/PostProcessingComponent.ts b/src/components/post/PostProcessingComponent.ts index 21c716e1..adc63477 100644 --- a/src/components/post/PostProcessingComponent.ts +++ b/src/components/post/PostProcessingComponent.ts @@ -1,3 +1,4 @@ +import { FXAAPost, webGPUContext } from "../.."; import { Engine3D } from "../../Engine3D"; import { PostBase } from "../../gfx/renderJob/post/PostBase"; import { Ctor } from "../../util/Global"; @@ -5,6 +6,8 @@ import { ComponentBase } from "../ComponentBase"; export class PostProcessingComponent extends ComponentBase { private _postList: Map; + + public init(param?: any): void { this._postList = new Map(); } @@ -26,6 +29,7 @@ export class PostProcessingComponent extends ComponentBase { } private activePost() { + webGPUContext.canResize = false; let view = this.transform.view3D; let job = Engine3D.getRenderJob(view); this._postList.forEach((v) => { @@ -34,6 +38,7 @@ export class PostProcessingComponent extends ComponentBase { } private unActivePost() { + webGPUContext.canResize = true; let view = this.transform.view3D; let job = Engine3D.getRenderJob(view); this._postList.forEach((v) => { @@ -42,20 +47,27 @@ export class PostProcessingComponent extends ComponentBase { } public addPost(c: Ctor): T { - if (this._postList.has(c.prototype)) return; + if (this._postList.has(c.name)) return; + if (!this._postList.has("FXAAPost")) { + let post = new FXAAPost(); + this._postList.set(post.constructor.name, post); + if (this._enable) + this.activePost(); + if (c.name == "FXAAPost") { + return post as T; + } + } let post = new c(); - this._postList.set(c.prototype, post); + this._postList.set(c.name, post); if (this._enable) this.activePost(); - // post.onAttach(this.transform.view3D); - // Engine3D.getRenderJob(this.transform.view3D).addPost(post); return post; } public removePost(c: Ctor) { - if (!this._postList.has(c.prototype)) return; - let post = this._postList.get(c.prototype); - this._postList.delete(c.prototype); + if (!this._postList.has(c.name)) return; + let post = this._postList.get(c.name); + this._postList.delete(c.name); let view = this.transform.view3D; let job = Engine3D.getRenderJob(view); @@ -63,7 +75,7 @@ export class PostProcessingComponent extends ComponentBase { } public getPost(c: Ctor): T { - if (!this._postList.has(c.prototype)) return null; - return this._postList.get(c.prototype) as T; + if (!this._postList.has(c.name)) return null; + return this._postList.get(c.name) as T; } } \ No newline at end of file diff --git a/src/components/renderer/InstanceDrawComponent.ts b/src/components/renderer/InstanceDrawComponent.ts index 450acb5f..b34f005e 100644 --- a/src/components/renderer/InstanceDrawComponent.ts +++ b/src/components/renderer/InstanceDrawComponent.ts @@ -7,7 +7,7 @@ import { RenderNode } from "./RenderNode"; import { StorageGPUBuffer } from "../../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; import { View3D } from "../../core/View3D"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; -import { RendererType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; export class InstanceDrawComponent extends RenderNode { @@ -63,7 +63,7 @@ export class InstanceDrawComponent extends RenderNode { } - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer): void { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer): void { this._keyRenderGroup.forEach((v, k) => { let instanceMatrixBuffer = this._keyBufferGroup.get(k); let renderNode = v[0]; @@ -84,7 +84,7 @@ export class InstanceDrawComponent extends RenderNode { } - public renderPass(view: View3D, passType: RendererType, renderContext: RenderContext) { + public renderPass(view: View3D, passType: PassType, renderContext: RenderContext) { this._keyRenderGroup.forEach((v, k) => { let renderNode = v[0]; renderNode.instanceCount = v.length; @@ -92,7 +92,7 @@ export class InstanceDrawComponent extends RenderNode { }) } - public renderItem(view: View3D, passType: RendererType, renderNode: RenderNode, renderContext: RenderContext) { + public renderItem(view: View3D, passType: PassType, renderNode: RenderNode, renderContext: RenderContext) { let worldMatrix = renderNode.transform._worldMatrix; for (let i = 0; i < renderNode.materials.length; i++) { @@ -114,7 +114,7 @@ export class InstanceDrawComponent extends RenderNode { if (renderShader.shaderState.splitTexture) { renderContext.endRenderPass(); RTResourceMap.WriteSplitColorTexture(renderNode.instanceID); - renderContext.beginRenderPass(); + renderContext.beginOpaqueRenderPass(); GPUContext.bindCamera(renderContext.encoder, view.camera); GPUContext.bindGeometryBuffer(renderContext.encoder, renderNode.geometry); diff --git a/src/components/renderer/MeshFilter.ts b/src/components/renderer/MeshFilter.ts new file mode 100644 index 00000000..56e067af --- /dev/null +++ b/src/components/renderer/MeshFilter.ts @@ -0,0 +1,36 @@ +import { GeometryBase, Object3D } from '../..'; +import { Engine3D } from '../../Engine3D'; +import { RegisterComponent } from '../../util/SerializeDecoration'; +import { MeshRenderer } from './MeshRenderer'; + +/** + * The mesh renderer component is a component used to render the mesh + * @group Components + */ +@RegisterComponent +export class MeshFilter extends MeshRenderer { + constructor() { + super(); + } + + public get geometry(): GeometryBase { + return null; + } + public set geometry(value: GeometryBase) { + + } + + public cloneTo(obj: Object3D): void { + + } + + public set meshURL(value: string) { + let geometry = Engine3D.res.getGeometry(value); + if (geometry) { + this.geometry = geometry; + } else { + console.error("no geometry set", value); + } + // this.material = Engine3D.res.defaltMaterial; + } +} diff --git a/src/components/renderer/MeshRenderer.ts b/src/components/renderer/MeshRenderer.ts index 1779f617..b028fe6f 100644 --- a/src/components/renderer/MeshRenderer.ts +++ b/src/components/renderer/MeshRenderer.ts @@ -4,16 +4,17 @@ import { ClusterLightingBuffer } from '../../gfx/renderJob/passRenderer/cluster/ import { GeometryBase } from '../../core/geometry/GeometryBase'; import { RendererMask } from '../../gfx/renderJob/passRenderer/state/RendererMask'; import { RendererPassState } from '../../gfx/renderJob/passRenderer/state/RendererPassState'; -import { RendererType } from '../../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; import { MorphTargetData } from '../anim/morphAnim/MorphTargetData'; import { RenderNode } from './RenderNode'; -import { EditorInspector } from '../../util/SerializeDecoration'; -import { Material } from '../..'; +import { EditorInspector, RegisterComponent } from '../../util/SerializeDecoration'; +import { Color, Material, mergeFunctions } from '../..'; /** * The mesh renderer component is a component used to render the mesh * @group Components */ +@RegisterComponent export class MeshRenderer extends RenderNode { /** * Enabling this option allows the grid to display any shadows cast on the grid. @@ -71,8 +72,17 @@ export class MeshRenderer extends RenderNode { } this.object3D.bound = this._geometry.bounds.clone(); - if (this._readyPipeline) { + if (!this._readyPipeline) { this.initPipeline(); + + if (this._computes && this._computes) { + this.onCompute = mergeFunctions(this.onCompute, () => { + for (let i = 0; i < this._computes.length; i++) { + const compute = this._computes[i]; + compute.onUpdate(); + } + }); + } } } @@ -124,7 +134,7 @@ export class MeshRenderer extends RenderNode { * @param clusterLightingRender * @param probes */ - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { if (this.morphData && this.morphData.enable) { for (let i = 0; i < this.materials.length; i++) { const material = this.materials[i]; @@ -143,4 +153,8 @@ export class MeshRenderer extends RenderNode { super.destroy(force); } + // public onGraphic(view?: View3D) { + // if (this._geometry) + // view.graphic3D.drawMeshWireframe(this._geometry.instanceID, this._geometry, this.transform, Color.COLOR_RED); + // } } diff --git a/src/components/renderer/RenderNode.ts b/src/components/renderer/RenderNode.ts index e4ff1797..8e7b519f 100644 --- a/src/components/renderer/RenderNode.ts +++ b/src/components/renderer/RenderNode.ts @@ -13,7 +13,7 @@ import { RenderContext } from "../../gfx/renderJob/passRenderer/RenderContext"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; import { RendererMask, RendererMaskUtil } from "../../gfx/renderJob/passRenderer/state/RendererMask"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; -import { RendererType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { GetCountInstanceID, UUID } from "../../util/Global"; import { Reference } from "../../util/Reference"; import { ComponentBase } from "../ComponentBase"; @@ -23,6 +23,7 @@ import { OctreeEntity } from "../../core/tree/octree/OctreeEntity"; import { Transform } from "../Transform"; import { Material } from "../../materials/Material"; import { RenderLayer } from "../../gfx/renderJob/config/RenderLayer"; +import { RenderShaderCompute, ComputeShader } from "../.."; /** @@ -51,7 +52,7 @@ export class RenderNode extends ComponentBase { protected _renderOrder: number = 0; public isRenderOrderChange?: boolean; public needSortOnCameraZ?: boolean; - private _octreeBinder: { octree: Octree, entity: OctreeEntity }; + protected _octreeBinder: { octree: Octree, entity: OctreeEntity }; public preInit: boolean = false; /** @@ -60,13 +61,16 @@ export class RenderNode extends ComponentBase { * The object is only visible when it has at least one common layer with the camera in use. * When using a ray projector, this attribute can also be used to filter out unwanted objects in ray intersection testing. */ - private _renderLayer: RenderLayer = RenderLayer.None; + protected _renderLayer: RenderLayer = RenderLayer.None; + protected _computes: RenderShaderCompute[]; public init() { this.renderOrder = 0; this.rendererMask = RendererMask.Default; this.instanceID = GetCountInstanceID().toString(); + + this._computes = []; } public attachSceneOctree(octree: Octree) { @@ -169,10 +173,15 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < this._materials.length; i++) { let mat = this._materials[i]; Reference.getInstance().detached(mat, this) + if (mat.shader && mat.shader.computes) + this.removeComputes(mat.shader.computes); } + for (let i = 0; i < value.length; i++) { let mat = value[i]; Reference.getInstance().attached(mat, this) + if (mat.shader && mat.shader.computes) + this.addComputes(mat.shader.computes); } this._materials = value; @@ -181,7 +190,7 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < value.length; i++) { const element = value[i]; - const passArray = element.getPass(RendererType.COLOR); + const passArray = element.getPass(PassType.COLOR); const pass = passArray[0]; if (pass.shaderState.transparent) { transparent = true; @@ -196,7 +205,18 @@ export class RenderNode extends ComponentBase { } } + private addComputes(computes: RenderShaderCompute[]) { + this._computes.push(...computes); + } + private removeComputes(computes: RenderShaderCompute[]) { + for (const com of computes) { + let index = this._computes.indexOf(com); + if (index != -1) { + this._computes.splice(index, 1); + } + } + } public addRendererMask(tag: RendererMask) { this._rendererMask = RendererMaskUtil.addMask(this._rendererMask, tag); @@ -210,7 +230,9 @@ export class RenderNode extends ComponentBase { if (!this._readyPipeline) { this.initPipeline(); } + EntityCollect.instance.addRenderNode(this.transform.scene3D, this); + this.updateOctreeEntity(); } @@ -236,7 +258,7 @@ export class RenderNode extends ComponentBase { let index = 0; for (let j = 0; j < this._materials.length; j++) { const material = this._materials[j]; - let passList = material.getPass(RendererType.COLOR); + let passList = material.getPass(PassType.COLOR); for (let i = 0; i < passList.length; i++) { const pass = passList[i]; // let shader = RenderShader.getShader(pass.instanceID); @@ -253,7 +275,7 @@ export class RenderNode extends ComponentBase { let sort = 0; for (let i = 0; i < this.materials.length; i++) { const element = this.materials[i]; - const passArray = element.getPass(RendererType.COLOR); + const passArray = element.getPass(PassType.COLOR); const pass = passArray[0]; if (pass.renderOrder >= 3000) { sort = sort > pass.renderOrder ? sort : pass.renderOrder; @@ -275,7 +297,7 @@ export class RenderNode extends ComponentBase { if (this.castGI) { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; - PassGenerate.createGIPass(this, mat); + PassGenerate.createGIPass(this, mat.shader); } } @@ -283,7 +305,7 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; if (mat.castShadow) { - PassGenerate.createShadowPass(this, mat); + PassGenerate.createShadowPass(this, mat.shader); } } // } @@ -292,7 +314,7 @@ export class RenderNode extends ComponentBase { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; if (mat.castShadow) { - PassGenerate.createShadowPass(this, mat); + PassGenerate.createShadowPass(this, mat.shader); } } } @@ -302,12 +324,12 @@ export class RenderNode extends ComponentBase { if (!ignoreDepthPass && Engine3D.setting.render.zPrePass) { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; - PassGenerate.createDepthPass(this, mat); + PassGenerate.createDepthPass(this, mat.shader); } } else { for (let i = 0; i < this.materials.length; i++) { const mat = this.materials[i]; - mat.removePass(RendererType.DEPTH, 0); + mat.shader.removeShaderByIndex(PassType.DEPTH, 0); } } } @@ -340,7 +362,7 @@ export class RenderNode extends ComponentBase { this._castReflection = value; } - public renderPass(view: View3D, passType: RendererType, renderContext: RenderContext) { + public renderPass(view: View3D, passType: PassType, renderContext: RenderContext) { let renderNode = this; let worldMatrix = renderNode.transform._worldMatrix; for (let i = 0; i < renderNode.materials.length; i++) { @@ -368,22 +390,23 @@ export class RenderNode extends ComponentBase { if (renderShader.shaderState.splitTexture) { renderContext.endRenderPass(); RTResourceMap.WriteSplitColorTexture(renderNode.instanceID); - renderContext.beginRenderPass(); + renderContext.beginOpaqueRenderPass(); GPUContext.bindCamera(renderContext.encoder, view.camera); GPUContext.bindGeometryBuffer(renderContext.encoder, renderNode._geometry); } GPUContext.bindPipeline(renderContext.encoder, renderShader); let subGeometries = renderNode._geometry.subGeometries; - // for (let k = 0; k < subGeometries.length; k++) { - const subGeometry = subGeometries[i]; - let lodInfos = subGeometry.lodLevels; - let lodInfo = lodInfos[renderNode.lodLevel]; - - if (renderNode.instanceCount > 0) { - GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, renderNode.instanceCount, lodInfo.indexStart, 0, 0); - } else { - GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + for (let k = 0; k < subGeometries.length; k++) { + const subGeometry = subGeometries[k]; + let lodInfos = subGeometry.lodLevels; + let lodInfo = lodInfos[renderNode.lodLevel]; + + if (renderNode.instanceCount > 0) { + GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, renderNode.instanceCount, lodInfo.indexStart, 0, 0); + } else { + GPUContext.drawIndexed(renderContext.encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + } } } } @@ -396,7 +419,7 @@ export class RenderNode extends ComponentBase { * @param encoder * @returns */ - public renderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { if (!this.enable) return; // this.nodeUpdate(view, passType, rendererPassState, clusterLightingBuffer); @@ -405,6 +428,7 @@ export class RenderNode extends ComponentBase { let worldMatrix = node.object3D.transform._worldMatrix; for (let i = 0; i < this.materials.length; i++) { const material = this.materials[i]; + // material.applyUniform(); let passes = material.getPass(passType); if (!passes || passes.length == 0) return; @@ -428,10 +452,12 @@ export class RenderNode extends ComponentBase { if (matPass.pipeline) { GPUContext.bindPipeline(encoder, matPass); let subGeometries = node._geometry.subGeometries; - const subGeometry = subGeometries[i]; - let lodInfos = subGeometry.lodLevels; - let lodInfo = lodInfos[node.lodLevel]; - GPUContext.drawIndexed(encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + for (let k = 0; k < subGeometries.length; k++) { + const subGeometry = subGeometries[k]; + let lodInfos = subGeometry.lodLevels; + let lodInfo = lodInfos[node.lodLevel]; + GPUContext.drawIndexed(encoder, lodInfo.indexCount, 1, lodInfo.indexStart, 0, worldMatrix.index); + } } } } @@ -441,7 +467,7 @@ export class RenderNode extends ComponentBase { } - public recordRenderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public recordRenderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { if (!this.enable) return; // this.nodeUpdate(view, passType, rendererPassState, clusterLightingBuffer); @@ -472,7 +498,7 @@ export class RenderNode extends ComponentBase { } } - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { this.preInit = true; let node = this; let envMap = view.scene.envMap; @@ -510,7 +536,6 @@ export class RenderNode extends ComponentBase { let shadowRenderer = Engine3D.getRenderJob(view).shadowMapPassRenderer; if (shadowRenderer && shadowRenderer.depth2DArrayTexture) { renderShader.setTexture(`shadowMap`, Engine3D.getRenderJob(view).shadowMapPassRenderer.depth2DArrayTexture); - renderShader.setStorageBuffer(`shadowBuffer`, ShadowLightsCollect.shadowBuffer.get(view.scene)); } // let shadowLight = ShadowLights.list; // if (shadowLight.length) { @@ -534,7 +559,7 @@ export class RenderNode extends ComponentBase { if (lightUniformEntries) { renderShader.setStorageBuffer(`lightBuffer`, lightUniformEntries.storageGPUBuffer); if (lightUniformEntries.irradianceVolume) { - renderShader.setStructStorageBuffer(`irradianceData`, lightUniformEntries.irradianceVolume.irradianceVolumeBuffer); + renderShader.setUniformBuffer(`irradianceData`, lightUniformEntries.irradianceVolume.irradianceVolumeBuffer); } } diff --git a/src/components/renderer/SkinnedMeshRenderer.ts b/src/components/renderer/SkinnedMeshRenderer.ts index 21344dad..704fc397 100644 --- a/src/components/renderer/SkinnedMeshRenderer.ts +++ b/src/components/renderer/SkinnedMeshRenderer.ts @@ -3,10 +3,11 @@ import { Object3D } from "../../core/entities/Object3D"; import { MeshRenderer } from "./MeshRenderer"; import { RendererMask } from "../../gfx/renderJob/passRenderer/state/RendererMask"; import { StorageGPUBuffer } from "../../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; -import { RendererType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; import { SkeletonAnimationComponent } from "../SkeletonAnimationComponent"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; +import { GeometryBase, Matrix4, RegisterComponent } from "../.."; /** * Skin Mesh Renderer Component @@ -15,112 +16,116 @@ import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ * meshes with mixed shapes, and meshes running cloth simulations. * @group Components */ +@RegisterComponent export class SkinnedMeshRenderer extends MeshRenderer { - public skinJointsName: Array; - protected mInverseBindMatrixData: Array; - protected mInverseBindMatrixBuffer: StorageGPUBuffer; - protected mSkeletonAnimation: SkeletonAnimationComponent; - protected mJointIndexTableBuffer: StorageGPUBuffer; + public skinJointsName: Array; + protected mInverseBindMatrixData: Array; + protected mInverseBindMatrixBuffer: StorageGPUBuffer; + protected mSkeletonAnimation: SkeletonAnimationComponent; + protected mJointIndexTableBuffer: StorageGPUBuffer; - constructor() { - super(); - this.addRendererMask(RendererMask.SkinnedMesh); - } - - public start() { - super.start(); - this.skeletonAnimation = this.object3D.getComponent(SkeletonAnimationComponent); - if (!this.skeletonAnimation) { - let comps = this.object3D.parentObject.parentObject.getComponentsInChild(SkeletonAnimationComponent); - if (comps.length > 0) { - this.skeletonAnimation = comps[0]; - } - if (!this.skeletonAnimation) { - this.skeletonAnimation = this.object3D.getComponentFromParent(SkeletonAnimationComponent); - } + constructor() { + super(); + this.addRendererMask(RendererMask.SkinnedMesh); } - } - public onEnable(): void { - super.onEnable(); - } + public start() { + super.start(); + this.skeletonAnimation = this.object3D.getComponent(SkeletonAnimationComponent); + if (!this.skeletonAnimation) { + let comps = this.object3D.parentObject.parentObject.getComponentsInChild(SkeletonAnimationComponent); + if (comps.length > 0) { + this.skeletonAnimation = comps[0]; + } + let parentObj = this.object3D; + while (!this.skeletonAnimation && parentObj) { + this.skeletonAnimation = parentObj.getComponentFromParent(SkeletonAnimationComponent); + if (parentObj.parent) { + parentObj = parentObj.parent.object3D; + } + } + } + } - public get skeletonAnimation(): SkeletonAnimationComponent { - return this.mSkeletonAnimation; - } + public onEnable(): void { + super.onEnable(); + } - public set skeletonAnimation(value: SkeletonAnimationComponent) { - this.mSkeletonAnimation = value; - if (!value) { - return; + public get skeletonAnimation(): SkeletonAnimationComponent { + return this.mSkeletonAnimation; } - if (!this.mJointIndexTableBuffer) { - let skinJointIndexData = this.mSkeletonAnimation.getJointIndexTable(this.skinJointsName); - this.mJointIndexTableBuffer = new StorageGPUBuffer(skinJointIndexData.length * 4, 0, new Float32Array(skinJointIndexData)); - this.mJointIndexTableBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + public set skeletonAnimation(value: SkeletonAnimationComponent) { + this.mSkeletonAnimation = value; + if (!value) { + return; + } + + if (!this.mJointIndexTableBuffer) { + let skinJointIndexData = this.mSkeletonAnimation.getJointIndexTable(this.skinJointsName); + this.mJointIndexTableBuffer = new StorageGPUBuffer(skinJointIndexData.length * 4, 0, new Float32Array(skinJointIndexData)); + this.mJointIndexTableBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + } } - } - public get skinInverseBindMatrices(): Array { - return this.mInverseBindMatrixData; - } + public get skinInverseBindMatrices(): Array { + return this.mInverseBindMatrixData; + } - public set skinInverseBindMatrices(inverseBindMatrices: Array) { - this.mInverseBindMatrixData = inverseBindMatrices; - var inverseBindMatricesData = new Float32Array(inverseBindMatrices.length * 16); - for (let i = 0; i < inverseBindMatrices.length; i++) { - let index = i * 16; - let mat4x4 = inverseBindMatrices[i]; - inverseBindMatricesData.set(mat4x4, index); + public set skinInverseBindMatrices(inverseBindMatrices: Array) { + this.mInverseBindMatrixData = inverseBindMatrices; + var inverseBindMatricesData = new Float32Array(inverseBindMatrices.length * 16); + for (let i = 0; i < inverseBindMatrices.length; i++) { + let index = i * 16; + let mat4x4 = inverseBindMatrices[i]; + inverseBindMatricesData.set(mat4x4, index); + } + this.mInverseBindMatrixBuffer = new StorageGPUBuffer(inverseBindMatricesData.byteLength, 0, inverseBindMatricesData); + this.mInverseBindMatrixBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; } - this.mInverseBindMatrixBuffer = new StorageGPUBuffer(inverseBindMatricesData.byteLength, 0, inverseBindMatricesData); - this.mInverseBindMatrixBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; - } - public get inverseBindMatrixBuffer(): StorageGPUBuffer { - return this.mInverseBindMatrixBuffer; - } + public get inverseBindMatrixBuffer(): StorageGPUBuffer { + return this.mInverseBindMatrixBuffer; + } - public get jointIndexTableBuffer(): GPUBuffer { - return this.mJointIndexTableBuffer.buffer; - } + public get jointIndexTableBuffer(): GPUBuffer { + return this.mJointIndexTableBuffer.buffer; + } - public cloneTo(obj: Object3D) { - let skinnedMesh = obj.addComponent(SkinnedMeshRenderer); - skinnedMesh.geometry = this.geometry; - skinnedMesh.material = this.material.clone(); - skinnedMesh.castShadow = this.castShadow; - skinnedMesh.castGI = this.castGI; - skinnedMesh.receiveShadow = this.receiveShadow; - skinnedMesh.rendererMask = this.rendererMask; - skinnedMesh.skinJointsName = this.skinJointsName; - skinnedMesh.skinInverseBindMatrices = this.skinInverseBindMatrices; - skinnedMesh.mJointIndexTableBuffer = this.mJointIndexTableBuffer; - } + public cloneTo(obj: Object3D) { + let skinnedMesh = obj.addComponent(SkinnedMeshRenderer); + skinnedMesh.geometry = this.geometry; + skinnedMesh.material = this.material.clone(); + skinnedMesh.castShadow = this.castShadow; + skinnedMesh.castGI = this.castGI; + skinnedMesh.receiveShadow = this.receiveShadow; + skinnedMesh.rendererMask = this.rendererMask; + skinnedMesh.skinJointsName = this.skinJointsName; + skinnedMesh.skinInverseBindMatrices = this.skinInverseBindMatrices; + skinnedMesh.mJointIndexTableBuffer = this.mJointIndexTableBuffer; + } - /** - * @internal - * @param passType - * @param renderPassState - * @param scene3D - * @param clusterLightingRender - * @param probes - */ - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { - for (let i = 0; i < this.materials.length; i++) { - const material = this.materials[i]; - let passes = material.getPass(passType); - if (passes) for (let i = 0; i < passes.length; i++) { - const renderShader = passes[i]; - if (!renderShader.pipeline) { - renderShader.setStorageBuffer('jointsMatrixIndexTable', this.mSkeletonAnimation.jointMatrixIndexTableBuffer); - renderShader.setStorageBuffer('jointsInverseMatrix', this.mInverseBindMatrixBuffer); - renderShader.setStorageBuffer('jointsIndexMapingTable', this.mJointIndexTableBuffer); + /** + * @internal + * @param passType + * @param renderPassState + * @param scene3D + * @param clusterLightingRender + * @param probes + */ + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + for (let i = 0; i < this.materials.length; i++) { + const material = this.materials[i]; + let passes = material.getPass(passType); + if (passes) for (let i = 0; i < passes.length; i++) { + const renderShader = passes[i]; + if (!renderShader.pipeline && this.mSkeletonAnimation) { + renderShader.setStorageBuffer('jointsMatrixIndexTable', this.mSkeletonAnimation.jointMatrixIndexTableBuffer); + renderShader.setStorageBuffer('jointsInverseMatrix', this.mInverseBindMatrixBuffer); + renderShader.setStorageBuffer('jointsIndexMapingTable', this.mJointIndexTableBuffer); + } + } } - } + super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); } - super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); - } - -} +} \ No newline at end of file diff --git a/src/components/renderer/SkinnedMeshRenderer2.ts b/src/components/renderer/SkinnedMeshRenderer2.ts new file mode 100644 index 00000000..469fcbde --- /dev/null +++ b/src/components/renderer/SkinnedMeshRenderer2.ts @@ -0,0 +1,154 @@ +import { View3D } from "../../core/View3D"; +import { Object3D } from "../../core/entities/Object3D"; +import { MeshRenderer } from "./MeshRenderer"; +import { RendererMask } from "../../gfx/renderJob/passRenderer/state/RendererMask"; +import { StorageGPUBuffer } from "../../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; +import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/RendererPassState"; +import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; +import { AnimatorComponent, GeometryBase, LitMaterial, Matrix4, RegisterComponent } from "../.."; + +/** + * Skin Mesh Renderer Component + * Renders a deformable mesh. + * Deformable meshes include skin meshes (meshes with bones and bound poses), + * meshes with mixed shapes, and meshes running cloth simulations. + * @group Components + */ +@RegisterComponent +export class SkinnedMeshRenderer2 extends MeshRenderer { + public skinJointsName: Array; + protected mInverseBindMatrixData: Array; + protected mInverseBindMatrixBuffer: StorageGPUBuffer; + protected mSkeletonAnimation: AnimatorComponent; + protected mJointIndexTableBuffer: StorageGPUBuffer; + + constructor() { + super(); + this.addRendererMask(RendererMask.SkinnedMesh); + } + + public get geometry(): GeometryBase { + return this._geometry; + } + + public set geometry(value: GeometryBase) { + this.skinJointsName = value.skinNames; + let matrixList: Float32Array[] = []; + for (let i = 0; i < value.bindPose.length; i++) { + matrixList.push(value.bindPose[i].rawData.slice(0, 16)); + } + this.skinInverseBindMatrices = matrixList; + super.geometry = value; + } + + public start() { + super.start(); + this.skeletonAnimation = this.object3D.getComponent(AnimatorComponent); + if (!this.skeletonAnimation) { + let comps = this.object3D.parentObject.parentObject.getComponentsInChild(AnimatorComponent); + if (comps.length > 0) { + this.skeletonAnimation = comps[0]; + } + let parentObj = this.object3D; + while (!this.skeletonAnimation && parentObj) { + this.skeletonAnimation = parentObj.getComponentFromParent(AnimatorComponent); + if (parentObj.parent) { + parentObj = parentObj.parent.object3D; + } + } + } + // this.skinInverseBindMatrices = this.skeletonAnimation.inverseBindMatrices; + } + + public get blendShape() { + // key: string, value: number + return this.morphData + } + + public onEnable(): void { + super.onEnable(); + } + + public get skeletonAnimation(): AnimatorComponent { + return this.mSkeletonAnimation; + } + + public set skeletonAnimation(value: AnimatorComponent) { + this.mSkeletonAnimation = value; + if (!value) { + return; + } + + if (!this.mJointIndexTableBuffer) { + let skinJointIndexData = this.mSkeletonAnimation.getJointIndexTable(this.skinJointsName); + this.mJointIndexTableBuffer = new StorageGPUBuffer(skinJointIndexData.length, 0, new Float32Array(skinJointIndexData)); + this.mJointIndexTableBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + } + } + + public get skinInverseBindMatrices(): Array { + return this.mInverseBindMatrixData; + } + + public set skinInverseBindMatrices(inverseBindMatrices: Array) { + this.mInverseBindMatrixData = inverseBindMatrices; + var inverseBindMatricesData = new Float32Array(inverseBindMatrices.length * 16); + for (let i = 0; i < inverseBindMatrices.length; i++) { + let index = i * 16; + let mat4x4 = inverseBindMatrices[i]; + inverseBindMatricesData.set(mat4x4, index); + } + this.mInverseBindMatrixBuffer = new StorageGPUBuffer(inverseBindMatricesData.byteLength, 0, inverseBindMatricesData); + this.mInverseBindMatrixBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.COMPUTE; + } + + public get inverseBindMatrixBuffer(): StorageGPUBuffer { + return this.mInverseBindMatrixBuffer; + } + + public get jointIndexTableBuffer(): GPUBuffer { + return this.mJointIndexTableBuffer.buffer; + } + + public cloneTo(obj: Object3D) { + let skinnedMesh = obj.addComponent(SkinnedMeshRenderer2); + let newMats = []; + for (const mat of this.materials) { + newMats.push(mat.clone()); + } + skinnedMesh.materials = newMats; + skinnedMesh.geometry = this.geometry; + skinnedMesh.castShadow = this.castShadow; + skinnedMesh.castGI = this.castGI; + skinnedMesh.receiveShadow = this.receiveShadow; + skinnedMesh.rendererMask = this.rendererMask; + skinnedMesh.skinJointsName = this.skinJointsName; + skinnedMesh.skinInverseBindMatrices = this.skinInverseBindMatrices; + skinnedMesh.mJointIndexTableBuffer = this.mJointIndexTableBuffer; + } + + /** + * @internal + * @param passType + * @param renderPassState + * @param scene3D + * @param clusterLightingRender + * @param probes + */ + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer) { + for (let i = 0; i < this.materials.length; i++) { + const material = this.materials[i]; + let passes = material.getPass(passType); + if (passes) for (let i = 0; i < passes.length; i++) { + const renderShader = passes[i]; + if (!renderShader.pipeline && this.mSkeletonAnimation) { + renderShader.setStorageBuffer('jointsMatrixIndexTable', this.mSkeletonAnimation.jointMatrixIndexTableBuffer); + renderShader.setStorageBuffer('jointsInverseMatrix', this.mInverseBindMatrixBuffer); + renderShader.setStorageBuffer('jointsIndexMapingTable', this.mJointIndexTableBuffer); + } + } + } + super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); + } +} \ No newline at end of file diff --git a/src/components/renderer/SkyRenderer.ts b/src/components/renderer/SkyRenderer.ts index 550422da..d20505dc 100644 --- a/src/components/renderer/SkyRenderer.ts +++ b/src/components/renderer/SkyRenderer.ts @@ -8,7 +8,7 @@ import { EntityCollect } from '../../gfx/renderJob/collect/EntityCollect'; import { ClusterLightingBuffer } from '../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer'; import { RendererMask } from '../../gfx/renderJob/passRenderer/state/RendererMask'; import { RendererPassState } from '../../gfx/renderJob/passRenderer/state/RendererPassState'; -import { RendererType } from '../../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; import { SkyMaterial } from '../../materials/SkyMaterial'; import { Vector3 } from '../../math/Vector3'; import { SphereGeometry } from '../../shape/SphereGeometry'; @@ -57,7 +57,7 @@ export class SkyRenderer extends MeshRenderer { } } - public renderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { // this.transform.updateWorldMatrix(); super.renderPass2(view, passType, rendererPassState, clusterLightingBuffer, encoder, useBundle); // this.transform.localPosition = Camera3D.mainCamera.transform.localPosition ; diff --git a/src/core/Camera3D.ts b/src/core/Camera3D.ts index 3bd81349..10d20559 100644 --- a/src/core/Camera3D.ts +++ b/src/core/Camera3D.ts @@ -127,7 +127,7 @@ export class Camera3D extends ComponentBase { public getShadowBias(depthTexSize: number): number { let sizeOnePixel = 2.0 * this.getShadowWorldExtents() / depthTexSize; let depth = this.far - this.near; - return sizeOnePixel / depth; + return sizeOnePixel / depth - Engine3D.setting.shadow.shadowBias * 0.01; } public getShadowWorldExtents(): number { diff --git a/src/core/View3D.ts b/src/core/View3D.ts index 7f334f66..c90ec262 100644 --- a/src/core/View3D.ts +++ b/src/core/View3D.ts @@ -28,7 +28,6 @@ export class View3D extends CEventListener { super(); this.canvasList = []; this._viewPort = new Vector4(x, y, width, height); - this.enablePick = true; this.graphic3D = new Graphic3D(); } @@ -60,7 +59,7 @@ export class View3D extends CEventListener { this._scene = value; value.view = this; - ShadowLightsCollect.createBuffer(value); + ShadowLightsCollect.createBuffer(this); if (this.graphic3D) value.addChild(this.graphic3D); diff --git a/src/core/ViewQuad.ts b/src/core/ViewQuad.ts index 8f8ea625..0f4db71b 100644 --- a/src/core/ViewQuad.ts +++ b/src/core/ViewQuad.ts @@ -2,20 +2,16 @@ import { MeshRenderer } from '../components/renderer/MeshRenderer'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; import { UniformNode } from '../gfx/graphics/webGpu/core/uniforms/UniformNode'; import { WebGPUDescriptorCreator } from '../gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator'; -import { GPUCompareFunction } from '../gfx/graphics/webGpu/WebGPUConst'; import { webGPUContext } from '../gfx/graphics/webGpu/Context3D'; import { RTFrame } from '../gfx/renderJob/frame/RTFrame'; -import { BlendMode } from '../materials/BlendMode'; -import { Color } from '../math/Color'; import { PlaneGeometry } from '../shape/PlaneGeometry'; - import { Object3D } from './entities/Object3D'; import { RendererPassState } from '../gfx/renderJob/passRenderer/state/RendererPassState'; -import { Engine3D } from '../Engine3D'; import { GPUContext } from '../gfx/renderJob/GPUContext'; -import { RendererType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; import { View3D } from './View3D'; -import { Material, RenderShader } from '..'; +import { Material } from '../materials/Material'; +import { QuadShader } from '../loader/parser/prefab/mats/shader/QuadShader'; /** * @internal * @group Entity @@ -25,27 +21,18 @@ export class ViewQuad extends Object3D { height: number = 128; quadRenderer: MeshRenderer; material: Material; - uniforms: { [key: string]: UniformNode }; + // uniforms: { [key: string]: UniformNode }; rendererPassState: RendererPassState; - pass: RenderShader; + quadShader: QuadShader; - constructor(vs: string = 'QuadGlsl_vs', fs: string = 'QuadGlsl_fs', rtFrame: RTFrame, shaderUniforms?: { [uniName: string]: UniformNode }, multisample: number = 0, f: boolean = false) { + constructor(vs: string = 'QuadGlsl_vs', fs: string = 'QuadGlsl_fs', rtFrame: RTFrame, multisample: number = 0, f: boolean = false) { super(); - let renderTexture = rtFrame ? rtFrame.attachments : []; + let renderTexture = rtFrame ? rtFrame.renderTargets : []; this.material = new Material(); - this.pass = new RenderShader(vs, fs); - this.material.addPass(RendererType.COLOR, this.pass); - - this.pass.blendMode = BlendMode.NONE; - let shaderState = this.pass.shaderState; - shaderState.frontFace = `cw`; - // shaderState.cullMode = `back`; - shaderState.depthWriteEnabled = false; - shaderState.depthCompare = GPUCompareFunction.always; - shaderState.multisample = multisample; - this.uniforms = this.pass.uniforms = shaderUniforms ? shaderUniforms : { color: new UniformNode(new Color()) }; + this.quadShader = new QuadShader(vs, fs); + this.material.shader = this.quadShader; this.quadRenderer = this.addComponent(MeshRenderer); this.quadRenderer.material = this.material; @@ -55,13 +42,6 @@ export class ViewQuad extends Object3D { // this.quadRenderer.renderOrder = 99999; this.quadRenderer.geometry = new PlaneGeometry(100, 100, 1, 1); - this.colorTexture = Engine3D.res.blackTexture; - - this.pass.setUniformFloat(`x`, 0); - this.pass.setUniformFloat(`y`, 0); - this.pass.setUniformFloat(`width`, 100); - this.pass.setUniformFloat(`height`, 100); - this.quadRenderer.material = this.material; this.quadRenderer[`__start`](); this.quadRenderer[`_enable`] = true; @@ -69,24 +49,20 @@ export class ViewQuad extends Object3D { // this.createRendererPassState(renderTargets, depth); // this.rendererPassState = WebGPUDescriptorPool.createRendererPassState(renderTargets, shaderState.multisample>0 ? false : true); this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(rtFrame, `load`); - if (shaderState.multisample > 0) { - this.rendererPassState.multisample = shaderState.multisample; + if (multisample > 0) { + this.rendererPassState.multisample = this.quadShader.getDefaultColorShader().shaderState.multisample; this.rendererPassState.multiTexture = webGPUContext.device.createTexture({ size: { width: webGPUContext.presentationSize[0], height: webGPUContext.presentationSize[1], }, - sampleCount: shaderState.multisample, + sampleCount: multisample, format: renderTexture.length > 0 ? renderTexture[0].format : webGPUContext.presentationFormat, usage: GPUTextureUsage.RENDER_ATTACHMENT, }) } } - public set colorTexture(tex: Texture) { - this.material.getPass(RendererType.COLOR)[0].setTexture(`baseMap`, tex); - } - /** * By inputting a map to viewQuad and setting corresponding * processing shaders, the corresponding results are output for off-screen rendering @@ -101,8 +77,8 @@ export class ViewQuad extends Object3D { let camera = view.camera; let encoder = GPUContext.beginRenderPass(command, viewQuad.rendererPassState); GPUContext.bindCamera(encoder, camera); - viewQuad.quadRenderer.nodeUpdate(view, RendererType.COLOR, viewQuad.rendererPassState, null); - viewQuad.quadRenderer.renderPass2(view, RendererType.COLOR, viewQuad.rendererPassState, null, encoder); + viewQuad.quadRenderer.nodeUpdate(view, PassType.COLOR, viewQuad.rendererPassState, null); + viewQuad.quadRenderer.renderPass2(view, PassType.COLOR, viewQuad.rendererPassState, null, encoder); GPUContext.endPass(encoder); } @@ -117,37 +93,13 @@ export class ViewQuad extends Object3D { */ public renderToViewQuad(view: View3D, viewQuad: ViewQuad, command: GPUCommandEncoder, colorTexture: Texture) { let camera = view.camera; - viewQuad.colorTexture = colorTexture; + + viewQuad.quadShader.setTexture('baseMap', colorTexture); let encoder = GPUContext.beginRenderPass(command, viewQuad.rendererPassState); GPUContext.bindCamera(encoder, camera); - // viewQuad.x = view.viewPort.x; - // viewQuad.y = view.viewPort.y; - // viewQuad.scaleX = view.viewPort.width; - // viewQuad.scaleY = view.viewPort.height; - // viewQuad.transform.updateWorldMatrix(true); - // encoder.setViewport( - // view.viewPort.x * webGPUContext.presentationSize[0], - // view.viewPort.y * webGPUContext.presentationSize[1], - // view.viewPort.width * webGPUContext.presentationSize[0], - // view.viewPort.height * webGPUContext.presentationSize[1], - // 0.0, 1.0); - // encoder.setScissorRect( - // view.viewPort.x * webGPUContext.presentationSize[0], - // view.viewPort.y * webGPUContext.presentationSize[0], - // view.viewPort.width * webGPUContext.presentationSize[0], - // view.viewPort.height * webGPUContext.presentationSize[1], - // ); - - // encoder.setScissorRect(view.viewPort.x, view.viewPort.y, 300, 150); - // encoder.setViewport(view.viewPort.x, view.viewPort.y, view.viewPort.width / (view.viewPort.width / view.viewPort.height), view.viewPort.height, 0.0, 1.0); - // encoder.setScissorRect(view.viewPort.x, view.viewPort.y, view.viewPort.width, view.viewPort.height); - - // encoder.setViewport(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height, 0.0, 1.0); - // encoder.setScissorRect(camera.viewPort.x, camera.viewPort.y, camera.viewPort.width, camera.viewPort.height); - - viewQuad.quadRenderer.nodeUpdate(view, RendererType.COLOR, viewQuad.rendererPassState, null); - viewQuad.quadRenderer.renderPass2(view, RendererType.COLOR, viewQuad.rendererPassState, null, encoder); + viewQuad.quadRenderer.nodeUpdate(view, PassType.COLOR, viewQuad.rendererPassState, null); + viewQuad.quadRenderer.renderPass2(view, PassType.COLOR, viewQuad.rendererPassState, null, encoder); GPUContext.endPass(encoder); } } diff --git a/src/core/entities/Entity.ts b/src/core/entities/Entity.ts index f8c80d5a..ff6df208 100644 --- a/src/core/entities/Entity.ts +++ b/src/core/entities/Entity.ts @@ -308,6 +308,7 @@ export class Entity extends CEventDispatcher { } this.components.forEach((v, k) => { v.enable = false; + v.beforeDestroy(); v.destroy(); }); this.components.clear(); @@ -319,8 +320,8 @@ export class Entity extends CEventDispatcher { while (v.length > 0) { const element = v.shift(); element[`__start`](); + ComponentCollect.waitStartComponent.delete(element.object3D); } - ComponentCollect.waitStartComponent.delete(k); }); } } diff --git a/src/core/entities/Object3D.ts b/src/core/entities/Object3D.ts index 444be1be..c700111b 100644 --- a/src/core/entities/Object3D.ts +++ b/src/core/entities/Object3D.ts @@ -549,17 +549,17 @@ function DecorateObject3D(ctor: any, _?: any) { public get materialColor(): Color { let component = this.getComponent(MeshRenderer); - return component?.material?.defaultPass.baseColor; + return component?.material?.shader.getDefaultColorShader().baseColor; } public set materialColor(color: Color) { let material = this.getComponent(MeshRenderer)?.material; - material && (material.defaultPass.baseColor = color); + material && (material.shader.getDefaultColorShader().baseColor = color); } public notifyMaterialColorChange(materialIndex: number, key: string) { let materials = this.getComponent(MeshRenderer).materials; - materials?.[materialIndex]?.defaultPass.uniforms[key].onChange(); + materials?.[materialIndex]?.shader.getDefaultColorShader().uniforms[key].onChange(); } }; } \ No newline at end of file diff --git a/src/core/geometry/ExtrudeGeometry.ts b/src/core/geometry/ExtrudeGeometry.ts index c3a65c4a..05bff8a8 100644 --- a/src/core/geometry/ExtrudeGeometry.ts +++ b/src/core/geometry/ExtrudeGeometry.ts @@ -180,7 +180,10 @@ export class ExtrudeGeometry extends GeometryBase { indexStart: 0, indexCount: indices_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); this.computeNormals(); diff --git a/src/core/geometry/GeometryBase.ts b/src/core/geometry/GeometryBase.ts index 385029c2..54962f05 100644 --- a/src/core/geometry/GeometryBase.ts +++ b/src/core/geometry/GeometryBase.ts @@ -8,12 +8,17 @@ import { GeometryIndicesBuffer } from "./GeometryIndicesBuffer"; import { GeometryVertexType } from "./GeometryVertexType"; import { VertexAttributeData } from "./VertexAttributeData"; import { ArrayBufferData } from "../../gfx/graphics/webGpu/core/buffer/ArrayBufferData"; +import { BlendShapeData } from "../../loader/parser/prefab/prefabData/BlendShapeData"; +import { Matrix4 } from "../../math/Matrix4"; -export type LodLevel = { +export type LODDescriptor = { indexStart: number; indexCount: number; vertexStart: number; + vertexCount: number; + firstStart: number; index: number; + topology: number; } @@ -22,7 +27,7 @@ export type LodLevel = { * @group Geometry */ export class SubGeometry { - public lodLevels: LodLevel[]; + public lodLevels: LODDescriptor[]; } @@ -35,14 +40,19 @@ export class GeometryBase { public name: string; public subGeometries: SubGeometry[] = []; public morphTargetsRelative: boolean; - public morphTargetDictionary: { value: string; key: number }; - private _bounds: BoundingBox; + public morphTargetDictionary: { [blenderName: string]: number }; + public skinNames: string[]; + public bindPose: Matrix4[]; + public blendShapeData: BlendShapeData; + public vertexDim: number; + private _bounds: BoundingBox; private _attributeMap: Map; private _attributes: string[]; private _indicesBuffer: GeometryIndicesBuffer; private _vertexBuffer: GeometryVertexBuffer; private _onChange: boolean = true; + private _wireframeLines: Vector3[]; constructor() { this.instanceID = UUID(); @@ -90,7 +100,7 @@ export class GeometryBase { this._bounds.max.z = -Number.MAX_VALUE; let attributes = this.getAttribute(VertexAttributeName.position); - if (attributes) { + if (attributes && attributes.data) { for (let i = 0; i < attributes.data.length / 3; i++) { const px = attributes.data[i * 3 + 0]; const py = attributes.data[i * 3 + 1]; @@ -127,9 +137,9 @@ export class GeometryBase { /** * add subGeometry from lod level - * @param lodLevels @see LodLevel + * @param lodLevels @see LODDescriptor */ - public addSubGeometry(...lodLevels: LodLevel[]) { + public addSubGeometry(...lodLevels: LODDescriptor[]) { let sub = new SubGeometry(); sub.lodLevels = lodLevels; this.subGeometries.push(sub); @@ -160,7 +170,7 @@ export class GeometryBase { } } - public setAttribute(attribute: string, data: ArrayBufferData) { + public setAttribute(attribute: VertexAttributeName | string, data: ArrayBufferData) { if (attribute == VertexAttributeName.indices) { this.setIndices(data); } else { @@ -173,35 +183,64 @@ export class GeometryBase { } } - public getAttribute(attribute: string): VertexAttributeData { + public getAttribute(attribute: VertexAttributeName | string): VertexAttributeData { return this._attributeMap.get(attribute) as VertexAttributeData; } - public hasAttribute(attribute: string): boolean { + public hasAttribute(attribute: VertexAttributeName | string): boolean { return this._attributeMap.has(attribute); } public genWireframe(): Vector3[] { - let positionAttribute = this.getAttribute(`position`); - let indexAttribute = this.getAttribute(`indices`); - if (indexAttribute && positionAttribute && indexAttribute.data.length > 0) { - let vertexData = positionAttribute.data; - let lines = []; - for (let i = 0; i < indexAttribute.data.length / 3; i++) { - const i1 = indexAttribute.data[i * 3 + 0]; - const i2 = indexAttribute.data[i * 3 + 1]; - const i3 = indexAttribute.data[i * 3 + 2]; - - let p1 = new Vector3(vertexData[i1 * 3 + 0], vertexData[i1 * 3 + 1], vertexData[i1 * 3 + 2]); - let p2 = new Vector3(vertexData[i2 * 3 + 0], vertexData[i2 * 3 + 1], vertexData[i2 * 3 + 2]); - let p3 = new Vector3(vertexData[i3 * 3 + 0], vertexData[i3 * 3 + 1], vertexData[i3 * 3 + 2]); - - lines.push(p1, p2); - lines.push(p2, p3); - lines.push(p3, p1); + if (this._wireframeLines) return this._wireframeLines; + if (this.geometryType == GeometryVertexType.split || this.geometryType == GeometryVertexType.compose) { + let positionAttribute = this.getAttribute(VertexAttributeName.position); + let indexAttribute = this.getAttribute(VertexAttributeName.indices); + if (indexAttribute && positionAttribute && indexAttribute.data.length > 0) { + let vertexData = positionAttribute.data; + let lines = []; + for (let i = 0; i < indexAttribute.data.length / 3; i++) { + const i1 = indexAttribute.data[i * 3 + 0]; + const i2 = indexAttribute.data[i * 3 + 1]; + const i3 = indexAttribute.data[i * 3 + 2]; + + let p1 = new Vector3(vertexData[i1 * 3 + 0], vertexData[i1 * 3 + 1], vertexData[i1 * 3 + 2]); + let p2 = new Vector3(vertexData[i2 * 3 + 0], vertexData[i2 * 3 + 1], vertexData[i2 * 3 + 2]); + let p3 = new Vector3(vertexData[i3 * 3 + 0], vertexData[i3 * 3 + 1], vertexData[i3 * 3 + 2]); + + lines.push(p1, p2); + lines.push(p2, p3); + lines.push(p3, p1); + } + this._wireframeLines = lines; + return lines; + } + } else if (this.geometryType == GeometryVertexType.compose_bin) { + let vertexAttribute = this.getAttribute(VertexAttributeName.all); + let strip = this.vertexDim; + + let indexAttribute = this.getAttribute(VertexAttributeName.indices); + if (indexAttribute && vertexAttribute && indexAttribute.data.length > 0) { + let vertexData = vertexAttribute.data; + let lines = []; + for (let i = 0; i < indexAttribute.data.length / 3; i++) { + const i1 = indexAttribute.data[i * 3 + 0]; // start by 0 + const i2 = indexAttribute.data[i * 3 + 1]; // start by 1 + const i3 = indexAttribute.data[i * 3 + 2]; // start by 2 + + let p1 = new Vector3(vertexData[i1 * strip + 0], vertexData[i1 * strip + 1], vertexData[i1 * strip + 2]); + let p2 = new Vector3(vertexData[i2 * strip + 0], vertexData[i2 * strip + 1], vertexData[i2 * strip + 2]); + let p3 = new Vector3(vertexData[i3 * strip + 0], vertexData[i3 * strip + 1], vertexData[i3 * strip + 2]); + + lines.push(p1, p2); + lines.push(p2, p3); + lines.push(p3, p1); + } + this._wireframeLines = lines; + return lines; } - return lines; } + return null; } diff --git a/src/core/geometry/GeometryVertexBuffer.ts b/src/core/geometry/GeometryVertexBuffer.ts index 76005495..23bef450 100644 --- a/src/core/geometry/GeometryVertexBuffer.ts +++ b/src/core/geometry/GeometryVertexBuffer.ts @@ -4,6 +4,7 @@ import { VertexAttributeData } from "./VertexAttributeData"; import { GeometryVertexType } from "./GeometryVertexType"; import { VertexBufferLayout, VertexAttribute } from "./VertexAttribute"; import { VertexAttributeSize } from "./VertexAttributeSize"; +import { VertexAttributeName } from "./VertexAttributeName"; export class GeometryVertexBuffer { @@ -33,6 +34,9 @@ export class GeometryVertexBuffer { case GeometryVertexType.compose: this.createComposeVertexBuffer(vertexDataInfos, shaderReflection); break; + case GeometryVertexType.compose_bin: + this.createComposBinVertexBuffer(vertexDataInfos, shaderReflection); + break; } } @@ -62,6 +66,7 @@ export class GeometryVertexBuffer { } vertexDataInfos.set(attributeInfo.name, vertexInfo); } + let len = vertexInfo.data.length / attributeLayout.stride; if (this.vertexCount != 0 && this.vertexCount != len) { console.error(" vertex count not match attribute count"); @@ -111,15 +116,69 @@ export class GeometryVertexBuffer { } vertexDataInfos.set(attributeInfo.name, vertexInfo); } - let len = vertexInfo.data.length / attributeLayout.stride; - if (this.vertexCount != 0 && this.vertexCount != len) { - console.error(" vertex count not match attribute count"); + if (vertexInfo.data) { + let len = vertexInfo.data.length / attributeLayout.stride; + if (this.vertexCount != 0 && this.vertexCount != len) { + console.error(" vertex count not match attribute count"); + } + this.vertexCount = len; } - this.vertexCount = len; + attributeOffset += attributeInfo.size; + } + + this._vertexBufferLayouts[0] = { + name: `composeStruct`, + arrayStride: attributeOffset * 4, + stepMode: `vertex`, + attributes: this._attributeSlotLayouts[0], + offset: 0, + size: this.vertexCount * attributeOffset * 4 + } + + this.vertexGPUBuffer = new VertexGPUBuffer(this.vertexCount * attributeOffset); + } + private createComposBinVertexBuffer(vertexDataInfos: Map, shaderReflection: ShaderReflection) { + this._attributeSlotLayouts[0] = []; + + let attributeOffset = 0; + for (let i = 0; i < shaderReflection.attributes.length; i++) { + const attributeInfo = shaderReflection.attributes[i]; + if (attributeInfo.name == `index`) continue; + if (attributeInfo.type == `builtin`) continue; + this._attributeLocation[attributeInfo.name] = attributeInfo.location; + + let attributeLayout: VertexAttribute = { + name: attributeInfo.name, + format: attributeInfo.format, + offset: attributeOffset * 4, + shaderLocation: attributeInfo.location, + stride: VertexAttributeSize[attributeInfo.format] + } + this._attributeSlotLayouts[0][attributeInfo.location] = attributeLayout; + + let vertexInfo = vertexDataInfos.get(attributeInfo.name); + if (!vertexInfo) { + vertexInfo = { + attribute: attributeInfo.name, + data: new Float32Array(attributeInfo.size * this.vertexCount) + } + vertexDataInfos.set(attributeInfo.name, vertexInfo); + } + if (vertexInfo.data) { + let len = vertexInfo.data.length / attributeLayout.stride; + if (this.vertexCount != 0 && this.vertexCount != len) { + console.error(" vertex count not match attribute count"); + } + this.vertexCount = len; + } attributeOffset += attributeInfo.size; } + let att_all = vertexDataInfos.get(VertexAttributeName.all); + let len = att_all.data.length / attributeOffset; + this.vertexCount = len; + this._vertexBufferLayouts[0] = { name: `composeStruct`, arrayStride: attributeOffset * 4, @@ -154,6 +213,9 @@ export class GeometryVertexBuffer { } } break; + case GeometryVertexType.compose_bin: + this.vertexGPUBuffer.node.setFloat32Array(0, vertexDataInfo.data as Float32Array); + break; } this.vertexGPUBuffer?.apply(); } @@ -186,6 +248,13 @@ export class GeometryVertexBuffer { } } break; + + case GeometryVertexType.compose_bin: + { + let attributeData = vertexDataInfos.get(VertexAttributeName.all); + this.vertexGPUBuffer.node.setFloat32Array(0, attributeData.data as Float32Array); + } + break; } this.vertexGPUBuffer.apply(); } diff --git a/src/core/geometry/GeometryVertexType.ts b/src/core/geometry/GeometryVertexType.ts index 618c36a8..82983336 100644 --- a/src/core/geometry/GeometryVertexType.ts +++ b/src/core/geometry/GeometryVertexType.ts @@ -2,4 +2,5 @@ export enum GeometryVertexType { split, compose, + compose_bin, } \ No newline at end of file diff --git a/src/core/geometry/VertexAttributeName.ts b/src/core/geometry/VertexAttributeName.ts index 43c05ce6..d412303d 100644 --- a/src/core/geometry/VertexAttributeName.ts +++ b/src/core/geometry/VertexAttributeName.ts @@ -8,6 +8,11 @@ export enum VertexAttributeName { TANGENT = 'TANGENT', TEXCOORD_1 = 'TEXCOORD_1', TEXCOORD_2 = 'TEXCOORD_2', + TEXCOORD_3 = 'TEXCOORD_3', + TEXCOORD_4 = 'TEXCOORD_4', + TEXCOORD_5 = 'TEXCOORD_5', + TEXCOORD_6 = 'TEXCOORD_6', + TEXCOORD_7 = 'TEXCOORD_7', color = 'color', joints0 = 'joints0', joints1 = 'joints1', @@ -17,4 +22,7 @@ export enum VertexAttributeName { indices = `indices`, vIndex = 'vIndex', a_morphPositions_0 = 'a_morphPositions_0', + + + all = 'all', } diff --git a/src/core/pool/memory/MemoryInfo.ts b/src/core/pool/memory/MemoryInfo.ts index 8b1bbb35..0dc8a5d3 100644 --- a/src/core/pool/memory/MemoryInfo.ts +++ b/src/core/pool/memory/MemoryInfo.ts @@ -150,8 +150,6 @@ export class MemoryInfo { this.dataBytes.setUint16(index * Uint16Array.BYTES_PER_ELEMENT, v, true); } - - public getUint16(index: number = 0): number { return this.dataBytes.getUint16(index * Uint16Array.BYTES_PER_ELEMENT, true); } @@ -172,10 +170,6 @@ export class MemoryInfo { } public setFloat32Array(index: number, data: Float32Array) { - // let buffer = this.dataBytes.buffer.slice(this.dataBytes.byteOffset, this.dataBytes.byteOffset + data.length * Float32Array.BYTES_PER_ELEMENT); - // let tmp = new Float32Array(buffer, index * Float32Array.BYTES_PER_ELEMENT); - // tmp.set(data); - let tmp = new Float32Array(this.dataBytes.buffer, this.dataBytes.byteOffset + index * Float32Array.BYTES_PER_ELEMENT, data.length); tmp.set(data); } diff --git a/src/core/tree/quad/IQuadNode.ts b/src/core/tree/quad/IQuadNode.ts new file mode 100644 index 00000000..9233e101 --- /dev/null +++ b/src/core/tree/quad/IQuadNode.ts @@ -0,0 +1,16 @@ +import { Plane3D } from "../../../math/Plane3D"; +import { QuadAABB } from "./QuadAABB"; + +export interface IQuadNode { + + initAABB(): void; + + isTriangle: boolean; + + aabb: QuadAABB; + + calcGlobalQuadAABB(): void; + + plane?: Plane3D; + +} diff --git a/src/core/tree/quad/QuadAABB.ts b/src/core/tree/quad/QuadAABB.ts new file mode 100644 index 00000000..aca56990 --- /dev/null +++ b/src/core/tree/quad/QuadAABB.ts @@ -0,0 +1,147 @@ +import { Vector3 } from "../../../math/Vector3"; + +export class QuadAABB { + + public minPosX: number = 0; + + public minPosY: number = 0; + + public maxPosX: number = 0; + + public maxPosY: number = 0; + + public testID: number = 0; + + public points: Array; + + private offsetPosition: Vector3; + + private static TINY: number = 0.000001; + + constructor() { + this.points = new Array(); + this.offsetPosition = new Vector3(0, 0, 0, 0); + this.clear(); + + } + + public setAABox(cx: number, cy: number, sideX: number, sideY: number): void { + this.minPosX = cx - sideX / 2 - QuadAABB.TINY; + this.maxPosX = cx + sideX / 2 + QuadAABB.TINY; + this.minPosY = cy - sideY / 2 - QuadAABB.TINY; + this.maxPosY = cy + sideY / 2 + QuadAABB.TINY; + + this.offsetPosition.setTo(0, 0, 0); + } + + public setOffset(vec: Vector3): void { + + this.maxPosX += vec.x - this.offsetPosition.x; + this.minPosX += vec.x - this.offsetPosition.x; + + this.minPosY += vec.z - this.offsetPosition.z; + this.maxPosY += vec.z - this.offsetPosition.z; + + this.offsetPosition.copyFrom(vec); + } + + public setContainRect(minX: number, minY: number, maxX: number, maxY: number): void { + if (this.minPosX > minX) this.minPosX = minX; + if (this.minPosY > minY) this.minPosY = minY; + if (this.maxPosX < maxX) this.maxPosX = maxX; + if (this.maxPosY < maxY) this.maxPosY = maxY; + } + + public clear(): void { + var huge: number = 1000000000; + this.minPosX = this.minPosY = huge; + this.maxPosX = this.maxPosY = -huge; + this.points.length = 0; + this.testID = 0; + this.offsetPosition.setTo(0, 0, 0); + } + + public addPoint(pos: Vector3): void { + if (this.points.indexOf(pos) == -1) { + if (pos.x < this.minPosX) + this.minPosX = pos.x - QuadAABB.TINY; + if (pos.x > this.maxPosX) + this.maxPosX = pos.x + QuadAABB.TINY; + if (pos.z < this.minPosY) + this.minPosY = pos.z - QuadAABB.TINY; + if (pos.z > this.maxPosY) + this.maxPosY = pos.z + QuadAABB.TINY; + + this.points.push(pos); + } + } + + public clone(): QuadAABB { + var aabb: QuadAABB = new QuadAABB(); + aabb.minPosX = this.minPosX; + aabb.minPosY = this.minPosY; + aabb.maxPosX = this.maxPosX; + aabb.maxPosY = this.maxPosY; + return aabb; + } + public get radius(): number { + return Math.sqrt((this.maxPosY - this.minPosY) * (this.maxPosY - this.minPosY) + (this.maxPosX - this.minPosX) * (this.maxPosX - this.minPosX)); + } + + public get sideX(): number { + return this.maxPosX - this.minPosX; + } + + public get sideY(): number { + return this.maxPosY - this.minPosY; + } + + public get centreX(): number { + return (this.maxPosX - this.minPosX) * 0.5 + this.minPosX; + } + + public get centreY(): number { + return (this.maxPosY - this.minPosY) * 0.5 + this.minPosY; + } + + public overlapTest(box: QuadAABB): boolean { + return ( + (this.minPosY >= box.maxPosY) || + (this.maxPosY <= box.minPosY) || + (this.minPosX >= box.maxPosX) || + (this.maxPosX <= box.minPosX)) ? false : true; + } + + public isPointInside(pos: Vector3): boolean { + return ((pos.x >= this.minPosX) && + (pos.x <= this.maxPosX) && + (pos.z >= this.minPosY) && + (pos.z <= this.maxPosY)); + } + + public isIntersectLineSegment(p1x: number, p1y: number, p2x: number, p2y: number): boolean { + var isIntersect: boolean = false; + // function p1-p2 + var A1: number = p1y - p2y; + var B1: number = p2x - p1x; + var C1: number = p1x * p2y - p2x * p1y; + // + var LineIntersectY: number = (-C1 - A1 * this.minPosX) / B1; + if (LineIntersectY <= this.maxPosY && LineIntersectY >= this.minPosY) + isIntersect = true; + LineIntersectY = (-C1 - A1 * this.maxPosX) / B1; + if (LineIntersectY <= this.maxPosY && LineIntersectY >= this.minPosY) + isIntersect = true; + var LineIntersectX: number = (-C1 - B1 * this.minPosY) / A1; + if (LineIntersectX <= this.maxPosX && LineIntersectX >= this.minPosX) + isIntersect = true; + LineIntersectX = (-C1 - B1 * this.maxPosY) / A1; + if (LineIntersectX <= this.maxPosX && LineIntersectX >= this.minPosX) + isIntersect = true; + return isIntersect; + } + + + + +} \ No newline at end of file diff --git a/src/core/tree/quad/QuadRoot.ts b/src/core/tree/quad/QuadRoot.ts new file mode 100644 index 00000000..2daa7af1 --- /dev/null +++ b/src/core/tree/quad/QuadRoot.ts @@ -0,0 +1,92 @@ +import { Vector3 } from "../../../math/Vector3"; +import { IQuadNode } from "./IQuadNode"; +import { QuadAABB } from "./QuadAABB"; +import { QuadTree } from "./QuadTree"; + +export class QuadRoot { + + private _maxNodesPerCell: number; + + private _minCellSize: number; + + private _quadTree: QuadTree; + + private _collisionNodesIdx: Array; + + private _segBox: QuadAABB; + + private _collisionNodes: Array; + + constructor(maxNodesPerCell: number = 10, minCellSize: number = 500) { + this._maxNodesPerCell = maxNodesPerCell; + this._minCellSize = minCellSize; + this._segBox = new QuadAABB; + this._collisionNodesIdx = new Array(); + this._collisionNodes = new Array(); + } + + public createQuadTree(nodes: Array): void { + + this._quadTree = new QuadTree(); + this._quadTree.initNodes(nodes); + this._quadTree.buildQuadTree(this._maxNodesPerCell, this._minCellSize); + } + + public getNodesByAABB(minX: number, minY: number, maxX: number, maxY: number): Array { + // 创建一个射线的boundingbox + this._segBox.clear(); + this._segBox.maxPosX = maxX; + this._segBox.maxPosY = maxY; + this._segBox.minPosX = minX; + this._segBox.minPosY = minY; + + // 获取Boundingbox中的nodes + this._collisionNodesIdx.length = 0; + this._collisionNodes.length = 0; + var numNodes: number = this._quadTree.getNodesIntersectingtAABox(this._collisionNodesIdx, this._segBox); + var quadNode: IQuadNode; + for (var i: number = 0; i < this._collisionNodesIdx.length; i++) { + quadNode = this._quadTree.getQuadNode(this._collisionNodesIdx[i]); + this._collisionNodes.push(quadNode); + } + return this._collisionNodes; + + } + + public getTriangleAtPoint(point: Vector3, threshold: number = 5): IQuadNode { + // 创建一个射线的boundingbox + this._segBox.clear(); + this._segBox.setAABox(point.x, point.z, 1, 1); + + this._collisionNodesIdx.length = 0; + this._collisionNodes.length = 0; + // 获取Boundingbox中的node的ID + var numTriangles: number = this._quadTree.getNodesIntersectingtAABox(this._collisionNodesIdx, this._segBox); + + // 检查那个三角与点(x,y)相交 + var minDistance: number = 0xffffffff; + var curDistance: number = 0; + var minTriangle: IQuadNode; + var quadNode: IQuadNode; + var triangle: IQuadNode; + var box: QuadAABB; + for (var i: number = 0; i < this._collisionNodesIdx.length; i++) { + quadNode = this._quadTree.getQuadNode(this._collisionNodesIdx[i]); + box = quadNode.aabb; + if (!Vector3.pointInsideTriangle(point, box.points[0], box.points[1], box.points[2])) { + continue; + } + triangle = quadNode; + curDistance = Math.abs(triangle.plane.distance(point)); + if (curDistance > threshold) + continue; + if (quadNode == null || curDistance <= minDistance) { + minTriangle = triangle; + minDistance = curDistance; + } + } + + return minTriangle; + } + +} diff --git a/src/core/tree/quad/QuadTree.ts b/src/core/tree/quad/QuadTree.ts new file mode 100644 index 00000000..b2f492b1 --- /dev/null +++ b/src/core/tree/quad/QuadTree.ts @@ -0,0 +1,293 @@ +import { Vector3 } from "../../../math/Vector3"; +import { IQuadNode } from "./IQuadNode"; +import { QuadAABB } from "./QuadAABB"; +import { QuadTreeCell } from "./QuadTreeCell"; + +export class QuadTree { + + private _cells: Array; + + private _rootCell: QuadTreeCell; + + private _quadNodes: Array; + + private _aabb: QuadAABB; + + private _cellsToTest: Array; + + private _testID: number; + + constructor() { + this._testID = 0; + this._cells = new Array(); + this._quadNodes = new Array(); + this._cellsToTest = new Array(); + this._aabb = new QuadAABB(); + } + + public getQuadNode(idx: number): IQuadNode { + return this._quadNodes[idx]; + } + + public clear(): void { + this._cells.length = 0; + this._quadNodes.length = 0; + } + + public initNodes(nodes: Array): void { + this.clear(); + var i: number = 0; + var count: number = nodes.length; + while (i < count) { + nodes[i].calcGlobalQuadAABB(); + this._quadNodes.push(nodes[i]); + i++; + } + + } + + public buildQuadTree(maxNodesPerCell: number, minCellSize: number): void { + this._aabb.clear(); + + for (var node of this._quadNodes) { + if (node.isTriangle) { + for (var vt of node.aabb.points) { + this._aabb.addPoint(vt); + } + } + else { + this._aabb.setContainRect(node.aabb.minPosX, node.aabb.minPosY, node.aabb.maxPosX, node.aabb.maxPosY); + } + } + + this._cells.length = 0; + this._rootCell = new QuadTreeCell(this._aabb); // 创建根节点 + this._cells.push(this._rootCell); + + var numTriangles: number = this._quadNodes.length; + for (var i: number = 0; i < numTriangles; i++) { + this._cells[0].nodeIndices[i] = i; // 先把所有的三角面放到根节点上 + } + + var cellsToProcess: Array = new Array(); + cellsToProcess.push(0); + + var iTri: number; + var cellIndex: number; + var childCell: QuadTreeCell; + while (cellsToProcess.length != 0) { + cellIndex = cellsToProcess.pop(); + if (this._cells[cellIndex].nodeIndices.length <= maxNodesPerCell + || this._cells[cellIndex].aabb.radius < minCellSize) { + continue; // 该cell中还可以放三角面 + } + + for (i = 0; i < QuadTreeCell.NUM_CHILDREN; i++) { + this._cells[cellIndex].childCellIndices[i] = this._cells.length; + cellsToProcess.push(this._cells.length); + this._cells.push(new QuadTreeCell(this.createAABox(this._cells[cellIndex].aabb, i))); + + childCell = this._cells[this._cells.length - 1]; + + // 父节点上的三角型往子节点中放 + numTriangles = this._cells[cellIndex].nodeIndices.length; + var pushCount: number = 0; + for (var j: number = 0; j < numTriangles; j++) { + iTri = this._cells[cellIndex].nodeIndices[j]; + + if (this.doesNodeIntersectCell(this._quadNodes[iTri], childCell)) { + pushCount++; + childCell.nodeIndices.push(iTri); + } + } + } + this._cells[cellIndex].nodeIndices.length = 0; + } + } + + private createAABox(aabb: QuadAABB, id: number): QuadAABB { + var centerX: number = aabb.centreX; + var centerY: number = aabb.centreY; + var dimX: number = aabb.sideX; + var dimY: number = aabb.sideY; + + var result: QuadAABB = new QuadAABB(); + switch (id) { + case 0: // 1象限 + result.setAABox(centerX + dimX / 4, centerY + dimY / 4, dimX / 2, dimY / 2); + break; + case 1: // 2象限 + result.setAABox(centerX - dimX / 4, centerY + dimY / 4, dimX / 2, dimY / 2); + break; + case 2: // 3象限 + result.setAABox(centerX - dimX / 4, centerY - dimY / 4, dimX / 2, dimY / 2); + break; + case 3: // 4象限 + result.setAABox(centerX + dimX / 4, centerY - dimY / 4, dimX / 2, dimY / 2); + break; + default: + result.setAABox(centerX + dimX / 4, centerY - dimY / 4, dimX / 2, dimY / 2); + break; + } + + return result; + } + + private doesNodeIntersectCell(node: IQuadNode, cell: QuadTreeCell): Boolean { + // boundingbox要重叠 + var box: QuadAABB = node.aabb; + if (!box.overlapTest(cell.aabb)) { + return false; + } + //如果不是三角形,则只需要检测aabb的相交 + if (!node.isTriangle) + return true; + + var points: Array = box.points; + var p1: Vector3 = points[0]; + var p2: Vector3 = points[1]; + var p3: Vector3 = points[2]; + + if (cell.aabb.isPointInside(p1) || + cell.aabb.isPointInside(p2) || + cell.aabb.isPointInside(p3)) { // 三角型有顶点在cell中 + return true; + } + + // cell的顶点在三角型中 + var isIntersect: Boolean = + this.pointInTriangle(cell.aabb.minPosX, cell.aabb.minPosY, p1, p2, p3) || + this.pointInTriangle(cell.aabb.minPosX, cell.aabb.maxPosY, p1, p2, p3) || + this.pointInTriangle(cell.aabb.maxPosX, cell.aabb.maxPosY, p1, p2, p3) || + this.pointInTriangle(cell.aabb.maxPosX, cell.aabb.minPosY, p1, p2, p3); + + if (isIntersect) + return true; + + + // 三角形的边是否与AABB的边相交 + isIntersect = cell.aabb.isIntersectLineSegment(p1.x, p1.z, p2.x, p2.z) || + cell.aabb.isIntersectLineSegment(p1.x, p1.z, p3.x, p3.z) || + cell.aabb.isIntersectLineSegment(p2.x, p2.z, p3.x, p3.z); + + return isIntersect; + } + + public getNodesIntersectingtAABox(result: Array, aabb: QuadAABB): number { + if (this._cells.length == 0) + return 0; + this._cellsToTest.length = 0; + this._cellsToTest.push(0); + + this.incrementTestCounter(); + + var cellIndex: number, nTris: number, cell: QuadTreeCell; + var nodeBox: QuadAABB; + var i: number = 0; + while (this._cellsToTest.length != 0) { + cellIndex = this._cellsToTest.pop(); + + cell = this._cells[cellIndex]; + + if (!aabb.overlapTest(cell.aabb)) { + continue; + } + + if (cell.isLeaf()) { + nTris = cell.nodeIndices.length; + for (i = 0; i < nTris; i++) { + nodeBox = this.getQuadNode(cell.nodeIndices[i]).aabb; + if (nodeBox.testID != this._testID) { + nodeBox.testID = this._testID; + if (aabb.overlapTest(nodeBox)) { + result.push(cell.nodeIndices[i]); + } + } + } + } else { + for (i = 0; i < QuadTreeCell.NUM_CHILDREN; i++) { + this._cellsToTest.push(cell.childCellIndices[i]); + } + } + } + return result.length; + + } + + private pointInTriangle(x: number, y: number, triP1: Vector3, triP2: Vector3, triP3: Vector3): boolean { + var p1: Vector3 = triP1; + var p2: Vector3 = triP2; + var p3: Vector3 = triP3; + + // 直线方程p1-p2 + var A1: number = p1.z - p2.z; + var B1: number = p2.x - p1.x; + var C1: number = p1.x * p2.z - p2.x * p1.z; + // 直线方程p2-p3 + var A2: number = p2.z - p3.z; + var B2: number = p3.x - p2.x; + var C2: number = p2.x * p3.z - p3.x * p2.z; + // 直线方程p3-p1 + var A3: number = p3.z - p1.z; + var B3: number = p1.x - p3.x; + var C3: number = p3.x * p1.z - p1.x * p3.z; + + var isInTri: boolean = false; + var D1: number = A1 * x + B1 * y + C1; + var D2: number = A2 * x + B2 * y + C2; + var D3: number = A3 * x + B3 * y + C3; + + const Tiny: number = 0.01; + if ((D1 >= -Tiny && D2 >= -Tiny && D3 >= -Tiny) || (D1 <= Tiny && D2 <= Tiny && D3 <= Tiny)) + isInTri = true; + + return isInTri; + } + + private incrementTestCounter(): void { + ++this._testID; + if (this._testID == 0) { + var numTriangles: number = this._quadNodes.length; + for (var i: number = 0; i < numTriangles; i++) { + this._quadNodes[i].aabb.testID = 0; + } + this._testID = 1; + } + } + + private logDeep: number = 0; + private logTree(cellIndex: number): void { + if (cellIndex < 0) + return; + + this.logDeep++; + + var cell: QuadTreeCell = this._cells[cellIndex]; + + var spaces: String = ""; + for (var si: number = 0; si < (this.logDeep - 1); si++) + spaces += "-|"; + + console.log(spaces + "i=" + cellIndex + " " + + cell.aabb.minPosX.toFixed(2) + " " + cell.aabb.maxPosX.toFixed(2) + " " + + cell.aabb.minPosY.toFixed(2) + " " + cell.aabb.maxPosY.toFixed(2)); + + var i: number; + for (i = 0; i < cell.nodeIndices.length; i++) { + if (cell.nodeIndices[i] >= 0) { + var tri: IQuadNode = this._quadNodes[cell.nodeIndices[i]]; + console.log(spaces + " t=" + cell.nodeIndices[i] + " " + + tri.aabb.minPosX.toFixed(2) + " " + tri.aabb.maxPosX.toFixed(2) + " " + + tri.aabb.minPosY.toFixed(2) + " " + tri.aabb.maxPosY.toFixed(2)); + + } + } + for (i = 0; i < cell.childCellIndices.length; i++) { + if (cell.childCellIndices[i] >= 0) { + this.logTree(cell.childCellIndices[i]); + } + } + this.logDeep--; + } + +} diff --git a/src/core/tree/quad/QuadTreeCell.ts b/src/core/tree/quad/QuadTreeCell.ts new file mode 100644 index 00000000..083bbcd9 --- /dev/null +++ b/src/core/tree/quad/QuadTreeCell.ts @@ -0,0 +1,48 @@ +import { Vector3 } from "../../../math/Vector3"; +import { QuadAABB } from "./QuadAABB"; + + +export class QuadTreeCell { + + public static NUM_CHILDREN: number = 4; + + public childCellIndices: Array; + + public nodeIndices: Array; + + public aabb: QuadAABB; + + public points: Array; + + constructor(aabox: QuadAABB) { + this.childCellIndices = new Array(); + this.childCellIndices.length = QuadTreeCell.NUM_CHILDREN; + + this.nodeIndices = new Array(); + + this.clear(); + + if (aabox) { + this.aabb = aabox.clone(); + } else { + this.aabb = new QuadAABB(); + } + } + + /** + * @language zh_CN + * Indicates if we contain triangles (if not then we should/might have children) + */ + public isLeaf(): boolean { + return this.childCellIndices[0] == -1; + } + + public clear(): void { + for (var i: number = 0; i < QuadTreeCell.NUM_CHILDREN; i++) { + this.childCellIndices[i] = -1; + } + this.nodeIndices.splice(0, this.nodeIndices.length); + } + + +} \ No newline at end of file diff --git a/src/gfx/generate/BrdfLUTGenerate.ts b/src/gfx/generate/BrdfLUTGenerate.ts index 80b2d2a0..64e2ae9f 100644 --- a/src/gfx/generate/BrdfLUTGenerate.ts +++ b/src/gfx/generate/BrdfLUTGenerate.ts @@ -1,4 +1,4 @@ -import { BRDFLUT } from '../../assets/shader/utils/BRDFLUT'; +import { BRDFLUT } from '../../assets/shader/compute/BRDFLUT'; import { VirtualTexture } from '../../textures/VirtualTexture'; import { ComputeShader } from '../graphics/webGpu/shader/ComputeShader'; import { GPUTextureFormat } from '../graphics/webGpu/WebGPUConst'; diff --git a/src/gfx/generate/PassGenerate.ts b/src/gfx/generate/PassGenerate.ts index 064b2d96..416d7312 100644 --- a/src/gfx/generate/PassGenerate.ts +++ b/src/gfx/generate/PassGenerate.ts @@ -1,44 +1,45 @@ import { RenderNode } from '../../components/renderer/RenderNode'; -// import { CastPointShadowMaterialPass } from '../../materials/multiPass/CastPointShadowMaterialPass'; -// import { CastShadowMaterialPass } from '../../materials/multiPass/CastShadowMaterialPass'; -// import { DepthMaterialPass } from '../../materials/multiPass/DepthMaterialPass'; -// import { GBufferPass } from '../../materials/multiPass/GBufferPass'; -// import { SkyGBufferPass } from '../../materials/multiPass/SkyGBufferPass'; import { RendererMaskUtil, RendererMask } from '../renderJob/passRenderer/state/RendererMask'; -import { RendererType } from '../renderJob/passRenderer/state/RendererType'; +import { PassType } from '../renderJob/passRenderer/state/RendererType'; import { GLTFType } from '../../loader/parser/gltf/GLTFType'; -import { CastPointShadowMaterialPass, CastShadowMaterialPass, DepthMaterialPass, GBufferPass, Material, RendererPassState, SkyGBufferPass } from '../..'; +import { Shader } from '../graphics/webGpu/shader/Shader'; +import { SkyGBufferPass } from '../../materials/multiPass/SkyGBufferPass'; +import { GBufferPass } from '../../materials/multiPass/GBufferPass'; +import { VertexAttributeName } from '../../core/geometry/VertexAttributeName'; +import { CastShadowMaterialPass } from '../../materials/multiPass/CastShadowMaterialPass'; +import { CastPointShadowMaterialPass } from '../../materials/multiPass/CastPointShadowMaterialPass'; +import { DepthMaterialPass } from '../../materials/multiPass/DepthMaterialPass'; /** * @internal * @group GFX */ export class PassGenerate { - public static createGIPass(renderNode: RenderNode, material: Material) { + public static createGIPass(renderNode: RenderNode, shader: Shader) { if (RendererMaskUtil.hasMask(renderNode.rendererMask, RendererMask.Sky)) { - let colorPass = material.getPass(RendererType.COLOR)[0]; - let pass = new SkyGBufferPass(); - pass.setTexture(`baseMap`, colorPass.getTexture('baseMap')); - - pass.cullMode = colorPass.cullMode; - pass.frontFace = colorPass.frontFace; + let pass0 = shader.passShader.get(PassType.GI); + if (!pass0) { + let colorPass = shader.getSubShaders(PassType.COLOR)[0]; + let pass = new SkyGBufferPass(); + pass.setTexture(`baseMap`, colorPass.getTexture('baseMap')); + pass.cullMode = colorPass.cullMode; + pass.frontFace = colorPass.frontFace; + shader.addRenderPass(pass, 0); + pass.preCompile(renderNode.geometry); + } - material.addPass(RendererType.GI, pass, 0); - pass.preCompile(renderNode.geometry); } else { - this.castGBufferPass(renderNode, material); + this.castGBufferPass(renderNode, shader); } } - public static castGBufferPass(renderNode: RenderNode, material: Material) { - // for (let i = 0; i < renderNode.materials.length; i++) { - // const mat = renderNode.materials[i]; - let colorPassList = material.getPass(RendererType.COLOR); + public static castGBufferPass(renderNode: RenderNode, shader: Shader) { + let colorPassList = shader.getDefaultShaders(); for (let jj = 0; jj < colorPassList.length; jj++) { const colorPass = colorPassList[jj]; - let giPassList = material.getPass(RendererType.GI); - if (!giPassList || giPassList.length < jj) { + let giPassList = shader.getSubShaders(PassType.GI); + if (!giPassList || giPassList.length == 0 || giPassList.length < jj) { let pass = new GBufferPass(); pass.setTexture('baseMap', colorPass.getTexture("baseMap")); pass.setTexture('normalMap', colorPass.getTexture("normalMap")); @@ -53,23 +54,22 @@ export class PassGenerate { pass.cullMode = colorPass.cullMode; pass.frontFace = colorPass.frontFace; pass.preCompile(renderNode.geometry); - material.addPass(RendererType.GI, pass); + shader.addRenderPass(pass); } } - // } } - public static createShadowPass(renderNode: RenderNode, material: Material) { + public static createShadowPass(renderNode: RenderNode, shader: Shader) { let use_skeleton = RendererMaskUtil.hasMask(renderNode.rendererMask, RendererMask.SkinnedMesh); - let useTangent = renderNode.geometry.hasAttribute('TANGENT'); + let useTangent = renderNode.geometry.hasAttribute(VertexAttributeName.TANGENT); let useMorphTargets = renderNode.geometry.hasAttribute(GLTFType.MORPH_POSITION_PREFIX + '0'); let useMorphNormals = renderNode.geometry.hasAttribute(GLTFType.MORPH_NORMAL_PREFIX + '0'); - let colorPassList = material.getPass(RendererType.COLOR); + let colorPassList = shader.getSubShaders(PassType.COLOR); for (let i = 0; i < colorPassList.length; i++) { const colorPass = colorPassList[i]; - let shadowPassList = material.getPass(RendererType.SHADOW); - if (!shadowPassList || shadowPassList.length < i) { + let shadowPassList = shader.getSubShaders(PassType.SHADOW); + if (!shadowPassList || shadowPassList.length < (i + 1)) { let shadowPass = new CastShadowMaterialPass(); shadowPass.setTexture(`baseMap`, colorPass.getTexture(`baseMap`)); shadowPass.setUniform(`alphaCutoff`, colorPass.getUniform(`alphaCutoff`)); @@ -95,11 +95,11 @@ export class PassGenerate { shadowPass.shaderState.cullMode = `back`; } shadowPass.preCompile(renderNode.geometry); - material.addPass(RendererType.SHADOW, shadowPass); + shader.addRenderPass(shadowPass); } - let castPointShadowPassList = material.getPass(RendererType.POINT_SHADOW); - if (!castPointShadowPassList) { + let castPointShadowPassList = shader.getSubShaders(PassType.POINT_SHADOW); + if (!castPointShadowPassList || castPointShadowPassList.length < (i + 1)) { let castPointShadowPass = new CastPointShadowMaterialPass(); castPointShadowPass.setTexture(`baseMap`, colorPass.getTexture(`baseMap`)); castPointShadowPass.setUniform(`alphaCutoff`, colorPass.getUniform(`alphaCutoff`)); @@ -121,53 +121,13 @@ export class PassGenerate { castPointShadowPass.shaderState.cullMode = `front`; castPointShadowPass.preCompile(renderNode.geometry); } - material.addPass(RendererType.POINT_SHADOW, castPointShadowPass); + shader.addRenderPass(castPointShadowPass); } } } - public static createReflectionPass(renderNode: RenderNode, material: Material) { - // let reflectionPass = material.renderShader.getPassShader(RendererType.REFLECTION); - // if (!reflectionPass) { - // reflectionPass = new ColorLitMaterial(); - // let baseMat = renderNode.materials[0]; - // reflectionPass.baseMap = baseMat.baseMap; - // let useTangent = renderNode.geometry.hasVertexAttribute('TANGENT'); - // let useMorphTargets = renderNode.geometry.hasVertexAttribute(GLTFType.MORPH_POSITION_PREFIX + '0'); - // let useMorphNormals = renderNode.geometry.hasVertexAttribute(GLTFType.MORPH_NORMAL_PREFIX + '0'); - - // let use_skeleton = RendererMaskUtil.hasMask(renderNode.rendererMask, RendererMask.SkinnedMesh); - - // let shader = reflectionPass.getShader(); - // shader.shaderState.cullMode = baseMat.getShader().cullMode; - // shader.shaderState.frontFace = baseMat.getShader().frontFace; - - // for (let j = 0; j < 1; j++) { - // const renderShader = reflectionPass.getShader(); - - // if (!useTangent) { - // renderShader.setDefine(`USE_TANGENT`, useTangent); - // } - // if (use_skeleton) { - // renderShader.setDefine(`USE_SKELETON`, use_skeleton); - // } - // if (useMorphTargets) { - // renderShader.setDefine(`USE_MORPHTARGETS`, useMorphTargets); - // } - // if (useMorphNormals) { - // renderShader.setDefine(`USE_MORPHNORMALS`, useMorphNormals); - // } - - // renderShader.preCompile(renderNode.geometry, reflectionPass); - // } - - // material.renderShader.setPassShader(RendererType.REFLECTION, reflectionPass); - // } - // material.addPass(RendererType.REFLECTION, reflectionPass, 0); - } - - public static createDepthPass(renderNode: RenderNode, material: Material) { - let colorListPass = material.getPass(RendererType.COLOR); + public static createDepthPass(renderNode: RenderNode, shader: Shader) { + let colorListPass = shader.getSubShaders(PassType.COLOR); let useTangent = renderNode.geometry.hasAttribute('TANGENT'); let useMorphTargets = renderNode.geometry.hasAttribute(GLTFType.MORPH_POSITION_PREFIX + '0'); let useMorphNormals = renderNode.geometry.hasAttribute(GLTFType.MORPH_NORMAL_PREFIX + '0'); @@ -175,7 +135,7 @@ export class PassGenerate { for (let i = 0; i < colorListPass.length; i++) { const colorPass = colorListPass[i]; - let depthPassList = material.getPass(RendererType.DEPTH); + let depthPassList = shader.getSubShaders(PassType.DEPTH); if (!depthPassList && colorPass.shaderState.useZ) { if (!depthPassList || depthPassList.length < i) { let depthPass = new DepthMaterialPass(); @@ -195,7 +155,7 @@ export class PassGenerate { depthPass.cullMode = colorPass.cullMode; depthPass.frontFace = colorPass.frontFace; depthPass.preCompile(renderNode.geometry); - material.addPass(RendererType.DEPTH, depthPass); + shader.addRenderPass(depthPass); } } } diff --git a/src/gfx/graphics/webGpu/Context3D.ts b/src/gfx/graphics/webGpu/Context3D.ts index 628dc6e6..8b0865df 100644 --- a/src/gfx/graphics/webGpu/Context3D.ts +++ b/src/gfx/graphics/webGpu/Context3D.ts @@ -1,8 +1,10 @@ +import { CEventDispatcher } from '../../../event/CEventDispatcher'; +import { CResizeEvent } from '../../../event/CResizeEvent'; import { CanvasConfig } from './CanvasConfig'; /** * @internal */ -class Context3D { +class Context3D extends CEventDispatcher { public adapter: GPUAdapter; public device: GPUDevice; public context: GPUCanvasContext; @@ -15,6 +17,7 @@ class Context3D { public canvasConfig: CanvasConfig; public super: number = 1.0; private _pixelRatio: number = 1.0; + canResize: boolean = true; // initSize: number[]; public get pixelRatio() { return this._pixelRatio; @@ -34,7 +37,6 @@ class Context3D { // check if external canvas has initial with and height style const _width = this.canvas.clientWidth, _height = this.canvas.clientHeight - this.resize(this.canvas.clientWidth, this.canvas.clientHeight) // set a initial style if size changed if (_width != this.canvas.clientWidth) this.canvas.style.width = _width + 'px' @@ -104,28 +106,25 @@ class Context3D { format: this.presentationFormat, usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT, alphaMode: 'premultiplied', - colorSpace: `display-p3`, + colorSpace: `srgb`, }); - - // resize canvas size, aspect - this.resize(this.canvas.clientWidth, this.canvas.clientHeight) - let timer: any - const resizeObserver = new ResizeObserver(() => { - clearTimeout(timer) - timer = setTimeout(() => { - this.resize(this.canvas.clientWidth, this.canvas.clientHeight) - }, 50) - }); - resizeObserver.observe(this.canvas); + this.updateSize(); return true; } - public resize(width: number, height: number) { - this.canvas.width = this.windowWidth = Math.floor(width * this.pixelRatio * this.super) - this.canvas.height = this.windowHeight = Math.floor(height * this.pixelRatio * this.super) - this.presentationSize[0] = this.windowWidth; - this.presentationSize[1] = this.windowHeight; - this.aspect = this.windowWidth / this.windowHeight; + public updateSize() { + let w = Math.floor(this.canvas.clientWidth * this.pixelRatio * this.super); + let h = Math.floor(this.canvas.clientHeight * this.pixelRatio * this.super); + if (w != this.windowWidth || h != this.windowHeight) { + // if (this.canvas.width != this.windowWidth || this.canvas.height != this.windowHeight) { + this.canvas.width = this.windowWidth = w; + this.canvas.height = this.windowHeight = h; + this.presentationSize[0] = this.windowWidth; + this.presentationSize[1] = this.windowHeight; + this.aspect = this.windowWidth / this.windowHeight; + if (this.canResize) + this.dispatchEvent(new CResizeEvent(CResizeEvent.RESIZE, { width: this.windowWidth, height: this.windowHeight })); + } } } diff --git a/src/gfx/graphics/webGpu/PipelinePool.ts b/src/gfx/graphics/webGpu/PipelinePool.ts index 0e0bc733..cbea888e 100644 --- a/src/gfx/graphics/webGpu/PipelinePool.ts +++ b/src/gfx/graphics/webGpu/PipelinePool.ts @@ -1,4 +1,4 @@ -import { PoolNode, RenderShader } from "../../.."; +import { PoolNode, RenderShaderPass } from "../../.."; export class PipelinePool { private static pipelineMap: Map = new Map(); diff --git a/src/gfx/graphics/webGpu/compute/PreIntegratedLutCompute.ts b/src/gfx/graphics/webGpu/compute/PreIntegratedLutCompute.ts new file mode 100644 index 00000000..0262c6c4 --- /dev/null +++ b/src/gfx/graphics/webGpu/compute/PreIntegratedLutCompute.ts @@ -0,0 +1,40 @@ +import { VirtualTexture } from '../../../../textures/VirtualTexture'; +import { GPUTextureFormat } from '../WebGPUConst'; +import { GPUContext } from '../../../renderJob/GPUContext'; +import { RenderShaderCompute } from './RenderShaderCompute'; +import { PreIntegratedLut } from '../../../../assets/shader/compute/PreIntegratedLut'; +import { MaterialDataUniformGPUBuffer } from '../core/buffer/MaterialDataUniformGPUBuffer'; +import { Shader } from '../shader/Shader'; +/** + * @internal + * @group GFX + */ +export class PreIntegratedLutCompute extends RenderShaderCompute { + + constructor(shader: Shader) { + super(PreIntegratedLut, shader); + } + + protected init() { + //create virtual texture + let texture = new VirtualTexture(256, 256, GPUTextureFormat.rgba8unorm, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING); + + //set storageTexture + this.compute.setStorageTexture('sssMap', texture); + this.sourceShader.setTexture("lutMap", texture); + + return texture; + } + + public onFrame() { + + //set worker size + this.compute.workerSizeX = 256 / 8; + this.compute.workerSizeY = 256 / 8; + + //active + let commandEncoder = GPUContext.beginCommandEncoder(); + GPUContext.computeCommand(commandEncoder, [this.compute]); + GPUContext.endCommandEncoder(commandEncoder); + } +} diff --git a/src/gfx/graphics/webGpu/compute/RenderShaderCompute.ts b/src/gfx/graphics/webGpu/compute/RenderShaderCompute.ts new file mode 100644 index 00000000..2b32a6f3 --- /dev/null +++ b/src/gfx/graphics/webGpu/compute/RenderShaderCompute.ts @@ -0,0 +1,35 @@ +import { Shader } from "../../../.."; +import { ComputeShader } from "../shader/ComputeShader"; + +export class RenderShaderCompute { + + protected sourceShader: Shader; + protected compute: ComputeShader; + + protected needUpdate: boolean = true; + + constructor(shaderStr: string, sourceShader: Shader) { + this.sourceShader = sourceShader; + this.compute = new ComputeShader(shaderStr); + this.init(); + } + + protected init() { + + } + + protected onOnce?() + + protected onFrame?() + + public onUpdate() { + if (this.onFrame) { + this.onFrame(); + } + + if (this.onOnce && this.needUpdate) { + this.needUpdate = false; + this.onFrame(); + } + } +} \ No newline at end of file diff --git a/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts b/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts index 03fc39a9..34b5d342 100644 --- a/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts +++ b/src/gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup.ts @@ -24,6 +24,16 @@ export class GlobalUniformGroup { private uniformByteLength: number; private matrixesByteLength: number; + private shadowMatrixRaw = new Float32Array(8 * 16); + private csmMatrixRaw = new Float32Array(CSM.Cascades * 16); + private csmShadowBias = new Float32Array(4); + + public shadowLights = new Float32Array(16); + public dirShadowStart = 0; + public dirShadowEnd = 0; + public pointShadowStart = 0; + public pointShadowEnd = 0; + /** * * @param matrixBindGroup global matrix bindgroup @@ -33,7 +43,8 @@ export class GlobalUniformGroup { this.usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST; // ... + 8(shadow matrix) + 8(csm matrix) + 4(csm bias) + 4(csm scattering exp...) this.uniformGPUBuffer = new UniformGPUBuffer(32 * 4 * 4 + (3 * 4 * 4) + 8 * 16 + CSM.Cascades * 16 + 4 + 4); - this.uniformGPUBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE + this.uniformGPUBuffer.visibility = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE; + this.matrixBindGroup = matrixBindGroup; this.createBindGroup(); @@ -67,9 +78,7 @@ export class GlobalUniformGroup { }); } - private shadowMatrixRaw = new Float32Array(8 * 16); - private csmMatrixRaw = new Float32Array(CSM.Cascades * 16); - private csmShadowBias = new Float32Array(4); + public setCamera(camera: Camera3D) { this.uniformGPUBuffer.setMatrix(`_projectionMatrix`, camera.projectionMatrix); @@ -102,21 +111,19 @@ export class GlobalUniformGroup { } this.uniformGPUBuffer.setFloat32Array(`csmShadowBias`, this.csmShadowBias); this.uniformGPUBuffer.setFloat32Array(`csmMatrix`, this.csmMatrixRaw); - this.uniformGPUBuffer.setVector3(`CameraPos`, camera.transform.worldPosition); this.uniformGPUBuffer.setFloat(`frame`, Time.frame); this.uniformGPUBuffer.setFloat(`time`, Time.frame); this.uniformGPUBuffer.setFloat(`delta`, Time.delta); + // this.uniformGPUBuffer.setFloat(`shadowBias`, Engine3D.setting.shadow.shadowBias); this.uniformGPUBuffer.setFloat(`shadowBias`, camera.getShadowBias(shadowMapSize)); this.uniformGPUBuffer.setFloat(`skyExposure`, Engine3D.setting.sky.skyExposure); this.uniformGPUBuffer.setFloat(`renderPassState`, Engine3D.setting.render.renderPassState); this.uniformGPUBuffer.setFloat(`quadScale`, Engine3D.setting.render.quadScale); this.uniformGPUBuffer.setFloat(`hdrExposure`, Engine3D.setting.render.hdrExposure); - this.uniformGPUBuffer.setInt32(`renderState_left`, Engine3D.setting.render.renderState_left); this.uniformGPUBuffer.setInt32(`renderState_right`, Engine3D.setting.render.renderState_right); this.uniformGPUBuffer.setFloat(`renderState_split`, Engine3D.setting.render.renderState_split); - let mouseX = Engine3D.inputSystem.mouseX * webGPUContext.pixelRatio; let mouseY = Engine3D.inputSystem.mouseY * webGPUContext.pixelRatio; this.uniformGPUBuffer.setFloat(`mouseX`, mouseX); @@ -125,14 +132,16 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setFloat(`windowHeight`, webGPUContext.windowHeight); this.uniformGPUBuffer.setFloat(`near`, camera.near); this.uniformGPUBuffer.setFloat(`far`, camera.far); - this.uniformGPUBuffer.setFloat(`pointShadowBias`, Engine3D.setting.shadow.pointShadowBias); this.uniformGPUBuffer.setFloat(`shadowMapSize`, shadowMapSize); this.uniformGPUBuffer.setFloat(`shadowSoft`, Engine3D.setting.shadow.shadowSoft); this.uniformGPUBuffer.setFloat(`enableCSM`, camera.enableCSM ? 1 : 0); - this.uniformGPUBuffer.setFloat(`csmMargin`, Engine3D.setting.shadow.csmMargin); - + this.uniformGPUBuffer.setInt32(`nDirShadowStart`, this.dirShadowStart); + this.uniformGPUBuffer.setInt32(`nDirShadowEnd`, this.dirShadowEnd); + this.uniformGPUBuffer.setInt32(`nPointShadowStart`, this.pointShadowStart); + this.uniformGPUBuffer.setInt32(`nPointShadowEnd`, this.pointShadowEnd); + this.uniformGPUBuffer.setFloat32Array(`shadowLights`, this.shadowLights); this.uniformGPUBuffer.apply(); } @@ -153,7 +162,7 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setFloat(`frame`, Time.frame); this.uniformGPUBuffer.setFloat(`time`, Time.frame); this.uniformGPUBuffer.setFloat(`delta`, Time.delta); - this.uniformGPUBuffer.setFloat(`shadowBias`, 0.0001); + this.uniformGPUBuffer.setFloat(`shadowBias`, Engine3D.setting.shadow.shadowBias); this.uniformGPUBuffer.setFloat(`skyExposure`, Engine3D.setting.sky.skyExposure); this.uniformGPUBuffer.setFloat(`renderPassState`, Engine3D.setting.render.renderPassState); this.uniformGPUBuffer.setFloat(`quadScale`, Engine3D.setting.render.quadScale); @@ -178,12 +187,16 @@ export class GlobalUniformGroup { this.uniformGPUBuffer.setFloat(`enableCSM`, 0); this.uniformGPUBuffer.setFloat(`csmMargin`, Engine3D.setting.shadow.csmMargin); - + this.uniformGPUBuffer.setInt32(`nDirShadowStart`, this.dirShadowStart); + this.uniformGPUBuffer.setInt32(`nDirShadowEnd`, this.dirShadowEnd); + this.uniformGPUBuffer.setInt32(`nPointShadowStart`, this.pointShadowStart); + this.uniformGPUBuffer.setInt32(`nPointShadowEnd`, this.pointShadowEnd); + this.uniformGPUBuffer.setFloat32Array(`shadowLights`, this.shadowLights); this.uniformGPUBuffer.apply(); } - public addUniformNode() { } + public setShadowLight() { } } diff --git a/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts index f02d3e09..b86680e6 100644 --- a/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/ComputeGPUBuffer.ts @@ -10,6 +10,6 @@ export class ComputeGPUBuffer extends GPUBufferBase { constructor(size: number, data?: Float32Array) { super(); this.bufferType = GPUBufferType.ComputeGPUBuffer; - this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST, size, data); + this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST, size, data, "ComputeGPUBuffer"); } } diff --git a/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts b/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts index d9e98fdb..bb6a6d7c 100644 --- a/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts +++ b/src/gfx/graphics/webGpu/core/buffer/GPUBufferBase.ts @@ -309,10 +309,6 @@ export class GPUBufferBase { // this.applyMapAsync(); } - public applyMapAsync() { - this.mapAsyncWrite(new Float32Array(this.memory.shareDataBuffer), this.memory.shareDataBuffer.byteLength / 4); - } - public mapAsyncWrite(mapAsyncArray: Float32Array, len: number) { // Upload data using mapAsync and a queue of staging buffers. let bytesLen = len; @@ -382,7 +378,7 @@ export class GPUBufferBase { } } - protected createBuffer(usage: GPUBufferUsageFlags, size: number, data?: ArrayBufferData) { + protected createBuffer(usage: GPUBufferUsageFlags, size: number, data?: ArrayBufferData, debugLabel?: string) { let device = webGPUContext.device; this.byteSize = size * 4; this.usage = usage; @@ -390,6 +386,7 @@ export class GPUBufferBase { this.destroy(); } this.buffer = device.createBuffer({ + label: debugLabel, size: this.byteSize, usage: usage, mappedAtCreation: false, @@ -424,6 +421,7 @@ export class GPUBufferBase { let device = webGPUContext.device; this.buffer = device.createBuffer({ + label: "StructStorageGPUBuffer", size: totalLength, // size: totalLength * 4, usage: usage, diff --git a/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts index cde486b4..ab6f0ea0 100644 --- a/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/IndicesGPUBuffer.ts @@ -26,6 +26,7 @@ export class IndicesGPUBuffer extends GPUBufferBase { this.destroy(); } this.buffer = device.createBuffer({ + label: "IndicesGPUBuffer", size: this.byteSize, usage: usage, mappedAtCreation: false, diff --git a/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts index d47ab69c..69ad9332 100644 --- a/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/MaterialDataUniformGPUBuffer.ts @@ -31,7 +31,7 @@ export class MaterialDataUniformGPUBuffer extends GPUBufferBase { } len = Math.floor(len / 256 + 1) * 256; - this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, len / 4); + this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, len / 4, null, "MaterialDataUniformGPUBuffer"); for (const key in uniformNodes) { const node = uniformNodes[key]; if (!node) console.error(key, "is empty"); @@ -52,11 +52,6 @@ export class MaterialDataUniformGPUBuffer extends GPUBufferBase { */ public apply() { if (this.uniformNodes.length == 0) return; - // if (this.uniformNodes.length > 0 && this.uniformNodes[0].type == "IrradianceVolumeData") { - // if (this.uniformNodes[0].data["isVolumeFrameChange"]) { - // this._onChange = true; - // } - // } if (!this._onChange) return; for (const key in this.uniformNodes) { diff --git a/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts index 1054bef1..2ac8ccd6 100644 --- a/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/MatrixGPUBuffer.ts @@ -17,7 +17,7 @@ export class MatrixGPUBuffer extends GPUBufferBase { super(); this.bufferType = GPUBufferType.StorageGPUBuffer; this.size = size; - this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data); + this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data, "MatrixGPUBuffer"); } public writeBufferByHeap(mapAsyncArray: Float32Array, len: number) { diff --git a/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts index d728a408..83cda847 100644 --- a/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/StorageGPUBuffer.ts @@ -11,7 +11,7 @@ export class StorageGPUBuffer extends GPUBufferBase { constructor(size: number, usage: number = 0, data?: ArrayBufferData) { super(); this.bufferType = GPUBufferType.StorageGPUBuffer; - this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data); + this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | usage, size, data, "StorageGPUBuffer"); // this.createBuffer(GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, size, data); } } diff --git a/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts index 1ee4860a..3fe78db0 100644 --- a/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/UniformGPUBuffer.ts @@ -10,7 +10,7 @@ export class UniformGPUBuffer extends GPUBufferBase { constructor(size: number, data?: Float32Array) { super(); this.bufferType = GPUBufferType.UniformGPUBuffer; - this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, size, data); + this.createBuffer(GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, size, data, "UniformGPUBuffer"); } public genUniformNodes() { diff --git a/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts b/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts index 30dcb0f7..c09605e4 100644 --- a/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts +++ b/src/gfx/graphics/webGpu/core/buffer/VertexGPUBuffer.ts @@ -25,6 +25,7 @@ export class VertexGPUBuffer extends GPUBufferBase { this.destroy(); } this.buffer = device.createBuffer({ + label: "VertexGPUBuffer", size: this.byteSize, usage: usage, mappedAtCreation: false, diff --git a/src/gfx/graphics/webGpu/core/texture/Texture.ts b/src/gfx/graphics/webGpu/core/texture/Texture.ts index 8afe6cd1..13534184 100644 --- a/src/gfx/graphics/webGpu/core/texture/Texture.ts +++ b/src/gfx/graphics/webGpu/core/texture/Texture.ts @@ -1,6 +1,7 @@ -import { GPUAddressMode } from '../../WebGPUConst'; +import { GPUAddressMode, GPUFilterMode } from '../../WebGPUConst'; import { TextureMipmapGenerator } from './TextureMipmapGenerator'; import { webGPUContext } from '../../Context3D'; +import { TextureMipmapCompute } from './TextureMipmapCompute'; /** * Texture @@ -51,7 +52,7 @@ export class Texture implements GPUSamplerDescriptor { /** * GPUTextureUsage */ - public usage: number; + public usage: GPUFlagsConstant; /** * texture width @@ -203,9 +204,9 @@ export class Texture implements GPUSamplerDescriptor { this.height = height; this.numberLayer = numberLayer; - this.minFilter = 'linear'; - this.magFilter = 'linear'; - this.mipmapFilter = `linear`; + this.minFilter = GPUFilterMode.linear; + this.magFilter = GPUFilterMode.linear; + this.mipmapFilter = GPUFilterMode.linear; this.addressModeU = GPUAddressMode.repeat; this.addressModeV = GPUAddressMode.repeat; // this.visibility = GPUShaderStage.FRAGMENT; @@ -263,6 +264,8 @@ export class Texture implements GPUSamplerDescriptor { } else { this.viewDescriptor = { dimension: this.textureBindingLayout.viewDimension, + mipLevelCount: mipLevelCount, + baseMipLevel: 0 }; } } @@ -300,6 +303,7 @@ export class Texture implements GPUSamplerDescriptor { if (this.useMipmap) { TextureMipmapGenerator.webGPUGenerateMipmap(this); + // TextureMipmapCompute.createMipmap(this,this.mipmapCount); } } @@ -348,9 +352,16 @@ export class Texture implements GPUSamplerDescriptor { return this._sourceImageData; } + public getMipmapCount() { + let w = this.width; + let h = this.height; + let maxSize = Math.max(w, h); + return 1 + Math.log2(maxSize) | 0; + } + protected updateTextureDescription() { // let mipmapCount = this.useMipmap ? Math.floor(Math.log2(this.width)) : 1; - this.mipmapCount = Math.floor(this.useMipmap ? Math.log2(Math.min(this.width, this.height)) : 1); + this.mipmapCount = Math.floor(this.useMipmap ? this.getMipmapCount() : 1); this.createTextureDescriptor(this.width, this.height, this.mipmapCount, this.format); } @@ -532,4 +543,16 @@ export class Texture implements GPUSamplerDescriptor { } } + private static _texs: GPUTexture[] = []; + public static delayDestroyTexture(tex: GPUTexture) { + this._texs.push(tex); + } + + public static destroyTexture() { + if (this._texs.length > 0) { + while (this._texs.length > 0) { + this._texs.shift().destroy(); + } + } + } } diff --git a/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts b/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts index 1791ea2f..5dc44dd3 100644 --- a/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts +++ b/src/gfx/graphics/webGpu/core/texture/TextureMipmapGenerator.ts @@ -1,5 +1,6 @@ import { GPUContext } from '../../../../renderJob/GPUContext'; import { webGPUContext } from '../../Context3D'; +import { GPUFilterMode } from '../../WebGPUConst'; import { Texture } from './Texture'; /** * @internal @@ -80,6 +81,13 @@ export class TextureMipmapGenerator { return pipeline; } + public static getMipmapCount(texture: Texture) { + let w = texture.width; + let h = texture.height; + let maxSize = Math.max(w, h); + return 1 + Math.log2(maxSize) | 0; + } + // TextureDescriptor should be the descriptor that the texture was created with. // This version only works for basic 2D textures. public static webGPUGenerateMipmap(texture: Texture) { @@ -112,7 +120,7 @@ export class TextureMipmapGenerator { @fragment fn fragmentMain(@location(0) texCoord : vec2) -> @location(0) vec4 { - var outColor: vec4 = textureSample(img, imgSampler, texCoord); + var outColor: vec4 = textureSampleLevel(img, imgSampler, texCoord , 0.0 ); return outColor; } `, @@ -149,8 +157,8 @@ export class TextureMipmapGenerator { }); } else { sampler = gpuDevice.createSampler({ - minFilter: `linear`, - magFilter: `linear`, + minFilter: GPUFilterMode.linear, + magFilter: GPUFilterMode.linear, }); } diff --git a/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts b/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts index 3768d3ce..8f83a9fc 100644 --- a/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts +++ b/src/gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator.ts @@ -3,6 +3,7 @@ import { RTResourceConfig } from '../../../renderJob/config/RTResourceConfig'; import { GPUTextureFormat } from '../WebGPUConst'; import { webGPUContext } from '../Context3D'; import { RendererPassState } from '../../../renderJob/passRenderer/state/RendererPassState'; +import { CResizeEvent } from '../../../../event/CResizeEvent'; /** * @internal * @author sirxu @@ -24,27 +25,29 @@ export class WebGPUDescriptorCreator { rps.isOutTarget = rtFrame.isOutTarget; rps.depthCleanValue = rtFrame.depthCleanValue; rps.depthLoadOp = rtFrame.depthLoadOp; - if (rtFrame && rtFrame.attachments.length > 0) { - rps.renderTargets = rtFrame.attachments; - rps.rtTextureDescripts = rtFrame.rtDescriptors; + + if (rtFrame && rtFrame.renderTargets.length > 0) { + rps.renderTargets = rtFrame.renderTargets; + rps.rtTextureDescriptors = rtFrame.rtDescriptors; rps.renderPassDescriptor = WebGPUDescriptorCreator.getRenderPassDescriptor(rps); rps.renderBundleEncoderDescriptor = WebGPUDescriptorCreator.getRenderBundleDescriptor(rps); - rps.outAttachments = []; - for (let i = 0; i < rtFrame.attachments.length; i++) { - const element = rtFrame.attachments[i]; - rps.outAttachments[i] = { + rps.renderTargetTextures = []; + for (let i = 0; i < rtFrame.renderTargets.length; i++) { + const element = rtFrame.renderTargets[i]; + rps.renderTargetTextures[i] = { format: element.format, }; if (element.name.indexOf(RTResourceConfig.colorBufferTex_NAME) != -1) { rps.outColor = i; } } + } else { rps.renderPassDescriptor = WebGPUDescriptorCreator.getRenderPassDescriptor(rps, loadOp); rps.renderBundleEncoderDescriptor = WebGPUDescriptorCreator.getRenderBundleDescriptor(rps); // if(!rps.customSize){ - rps.outAttachments = [ + rps.renderTargetTextures = [ { format: webGPUContext.presentationFormat, }, @@ -74,7 +77,7 @@ export class WebGPUDescriptorCreator { size = [renderPassState.renderTargets[0].width, renderPassState.renderTargets[0].height]; for (let i = 0; i < renderPassState.renderTargets.length; i++) { const texture = renderPassState.renderTargets[i]; - const rtDesc = renderPassState.rtTextureDescripts[i]; + const rtDesc = renderPassState.rtTextureDescriptors[i]; attachMentTexture.push({ view: texture.getGPUView(), resolveTarget: undefined, diff --git a/src/gfx/graphics/webGpu/shader/ComputeShader.ts b/src/gfx/graphics/webGpu/shader/ComputeShader.ts index 9f5f5b43..88b57776 100644 --- a/src/gfx/graphics/webGpu/shader/ComputeShader.ts +++ b/src/gfx/graphics/webGpu/shader/ComputeShader.ts @@ -1,6 +1,6 @@ import { Texture } from '../core/texture/Texture'; import { webGPUContext } from '../Context3D'; -import { ShaderBase } from './ShaderBase'; +import { ShaderPassBase } from './ShaderPassBase'; import { ShaderReflection, ShaderReflectionVarInfo } from './value/ShaderReflectionInfo'; import { Preprocessor } from './util/Preprocessor'; import { Reference, Struct } from '../../../..'; @@ -13,7 +13,7 @@ import { UniformGPUBuffer } from '../core/buffer/UniformGPUBuffer'; * @author sirxu * compute shader kernel */ -export class ComputeShader extends ShaderBase { +export class ComputeShader extends ShaderPassBase { /** * Compute shader entry point name */ diff --git a/src/gfx/graphics/webGpu/shader/RenderShader.ts b/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts similarity index 94% rename from src/gfx/graphics/webGpu/shader/RenderShader.ts rename to src/gfx/graphics/webGpu/shader/RenderShaderPass.ts index 24e6da9e..9a7c9249 100644 --- a/src/gfx/graphics/webGpu/shader/RenderShader.ts +++ b/src/gfx/graphics/webGpu/shader/RenderShaderPass.ts @@ -12,7 +12,7 @@ import { UniformNode } from "../core/uniforms/UniformNode"; import { Texture } from "../core/texture/Texture"; import { webGPUContext } from "../Context3D"; import { ShaderConverter } from "./converter/ShaderConverter"; -import { ShaderBase } from "./ShaderBase"; +import { ShaderPassBase } from "./ShaderPassBase"; import { ShaderStage } from "./ShaderStage"; import { Preprocessor } from "./util/Preprocessor"; import { ShaderReflection, ShaderReflectionVarInfo } from "./value/ShaderReflectionInfo"; @@ -25,9 +25,13 @@ import { Reference } from "../../../../util/Reference"; import { CSM } from "../../../../core/csm/CSM"; import { GPUCompareFunction, GPUCullMode } from "../WebGPUConst"; import { UniformValue } from "./value/UniformValue"; +import { PassType } from "../../../renderJob/passRenderer/state/RendererType"; +import { Vector4 } from "../../../../math/Vector4"; import { PipelinePool } from "../PipelinePool"; -export class RenderShader extends ShaderBase { +export class RenderShaderPass extends ShaderPassBase { + + public passType: PassType = PassType.COLOR; public useRz: boolean = false; @@ -61,10 +65,7 @@ export class RenderShader extends ShaderBase { */ public bindGroupLayouts: GPUBindGroupLayout[]; - /** - * Uniform data for materials - */ - public materialDataUniformBuffer: MaterialDataUniformGPUBuffer; + public envMap: Texture; @@ -79,6 +80,7 @@ export class RenderShader extends ShaderBase { protected _textureGroup: number = -1; protected _textureChange: boolean = false; protected _groupsShaderReflectionVarInfos: ShaderReflectionVarInfo[][]; + outBufferMask: Vector4; constructor(vs: string, fs: string) { super(); @@ -112,7 +114,6 @@ export class RenderShader extends ShaderBase { this._bufferDic.set(`materialUniform`, this.materialDataUniformBuffer); } - /** * Blend mode */ @@ -142,6 +143,20 @@ export class RenderShader extends ShaderBase { this.shaderState.cullMode = b; } + /** + * depthWriteEnabled mode + */ + public get depthWriteEnabled(): boolean { + return this.shaderState.depthWriteEnabled; + } + + public set depthWriteEnabled(value: boolean) { + if (this.shaderState.depthWriteEnabled != value) { + this._valueChange = true; + } + this.shaderState.depthWriteEnabled = value; + } + /** * get render face cull mode */ @@ -370,7 +385,7 @@ export class RenderShader extends ShaderBase { //*********************************/ //******************/ - if (renderPassState.outAttachments.length > 1) { + if (renderPassState.renderTargetTextures.length > 1) { this.defineValue[`USE_WORLDPOS`] = true; this.defineValue[`USEGBUFFER`] = true; } else { @@ -692,7 +707,22 @@ export class RenderShader extends ShaderBase { let bufferMesh = geometry; let shaderState = this.shaderState; - let targets = renderPassState.outAttachments; + //create color state + let targets: GPUColorTargetState[] = []; + for (const tex of renderPassState.renderTargetTextures) { + targets.push({ + format: tex.format, + }); + } + + //set color state + for (let i = 0; i < targets.length; i++) { + const rtTexState = targets[i]; + if (shaderState.writeMasks && shaderState.writeMasks.length > 0) { + rtTexState.writeMask = shaderState.writeMasks[i]; + } + } + if (renderPassState.outColor != -1) { let target = targets[renderPassState.outColor]; if (shaderState.blendMode != BlendMode.NONE) { @@ -807,6 +837,8 @@ export class RenderShader extends ShaderBase { private preDefine(geometry: GeometryBase) { // this.vertexAttributes = "" ; // check geometry vertex attributes + let useSecondUV = geometry.hasAttribute(VertexAttributeName.TEXCOORD_1); + let isSkeleton = geometry.hasAttribute(VertexAttributeName.joints0); let hasMorphTarget = geometry.hasAttribute(VertexAttributeName.a_morphPositions_0); @@ -819,8 +851,16 @@ export class RenderShader extends ShaderBase { let useLight = this.shaderState.useLight; - this.defineValue[`USE_SKELETON`] = isSkeleton; - this.defineValue[`USE_MORPHTARGETS`] = hasMorphTarget; + if (useSecondUV) { + this.defineValue[`USE_SECONDUV`] = true; + } + + if (isSkeleton && hasMorphTarget) { + this.defineValue[`USE_METAHUMAN`] = true; + } else { + this.defineValue[`USE_SKELETON`] = isSkeleton; + this.defineValue[`USE_MORPHTARGETS`] = hasMorphTarget; + } if (!('USE_TANGENT' in this.defineValue)) { this.defineValue[`USE_TANGENT`] = useTangent; @@ -908,14 +948,16 @@ export class RenderShader extends ShaderBase { } else { texture.destroy(false); let table = Reference.getInstance().getReference(texture); - let list = []; - table.forEach((v, k) => { - if (`name` in v) { - list.push(v[`name`]); - } else { - list.push(`NaN`); - } - }); + if (table) { + let list = []; + table.forEach((v, k) => { + if (`name` in v) { + list.push(v[`name`]); + } else { + list.push(`NaN`); + } + }); + } } } } @@ -963,7 +1005,7 @@ export class RenderShader extends ShaderBase { * @returns Returns the instance ID of the RenderShader */ public static createShader(vs: string, fs: string): string { - let shader = new RenderShader(vs, fs); + let shader = new RenderShaderPass(vs, fs); ShaderUtil.renderShader.set(shader.instanceID, shader); return shader.instanceID; } diff --git a/src/gfx/graphics/webGpu/shader/Shader.ts b/src/gfx/graphics/webGpu/shader/Shader.ts new file mode 100644 index 00000000..6fdb3997 --- /dev/null +++ b/src/gfx/graphics/webGpu/shader/Shader.ts @@ -0,0 +1,245 @@ +import { RenderShaderCompute } from "../compute/RenderShaderCompute"; +import { GPUBufferBase } from "../core/buffer/GPUBufferBase"; +import { StorageGPUBuffer } from "../core/buffer/StorageGPUBuffer"; +import { StructStorageGPUBuffer } from "../core/buffer/StructStorageGPUBuffer"; +import { UniformGPUBuffer } from "../core/buffer/UniformGPUBuffer"; +import { Texture } from "../core/texture/Texture"; +import { RenderShaderPass } from "./RenderShaderPass"; +import { UniformValue } from "./value/UniformValue"; +import { PassType } from "../../../renderJob/passRenderer/state/RendererType"; +import { Color } from "../../../../math/Color"; +import { Vector2 } from "../../../../math/Vector2"; +import { Vector3 } from "../../../../math/Vector3"; +import { Vector4 } from "../../../../math/Vector4"; +import { Struct } from "../../../../util/struct/Struct"; + +export class Shader { + + + public computes: RenderShaderCompute[]; + + public passShader: Map; + + constructor() { + this.computes = []; + this.passShader = new Map(); + } + + public addRenderPass(renderShader: RenderShaderPass, index: number = -1) { + let subShader: RenderShaderPass[] = this.passShader.get(renderShader.passType) || []; + if (index == -1) { + subShader.push(renderShader); + } else { + subShader.splice(index, -1, renderShader); + } + this.passShader.set(renderShader.passType, subShader); + } + + public removeShader(renderShader: RenderShaderPass, index: number = -1) { + let subShader: RenderShaderPass[] = this.passShader.get(renderShader.passType); + if (subShader) { + if (index == -1) { + let index = subShader.indexOf(renderShader); + if (index != -1) { + subShader.splice(index); + } + } else { + subShader.splice(index, 1); + } + } + } + + public removeShaderByIndex(passType: PassType, index: number = -1) { + let subShader: RenderShaderPass[] = this.passShader.get(passType); + if (subShader) { + if (index == -1) { + this.passShader.delete(passType); + } else { + subShader.splice(index, 1); + } + } + } + + public getSubShaders(passType: PassType): RenderShaderPass[] { + return this.passShader.get(passType) || []; + } + + public hasSubShaders(passType: PassType): boolean { + let subs = this.passShader.get(passType); + return subs.length > 0; + } + + public getDefaultShaders(): RenderShaderPass[] { + return this.passShader.get(PassType.COLOR); + } + + public getDefaultColorShader(): RenderShaderPass { + return this.passShader.get(PassType.COLOR)[0]; + } + + public setDefine(arg0: string, arg1: boolean) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setDefine(arg0, arg1); + } + } + } + + public deleteDefine(arg0: string) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.deleteDefine(arg0); + } + } + } + + public setUniform(arg0: string, arg1: UniformValue) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniform(arg0, arg1); + } + } + } + + public setUniformFloat(arg0: string, arg1: number) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformFloat(arg0, arg1); + } + } + } + + public setUniformVector2(arg0: string, arg1: Vector2) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformVector2(arg0, arg1); + } + } + } + + public setUniformVector3(arg0: string, arg1: Vector3) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformVector3(arg0, arg1); + } + } + } + + public setUniformVector4(arg0: string, arg1: Vector4) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformVector4(arg0, arg1); + } + } + } + + public setUniformColor(arg0: string, arg1: Color) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformColor(arg0, arg1); + } + } + } + + public getUniform(arg0: string): any { + return this.getDefaultColorShader().getUniform(arg0); + } + + public getUniformFloat(arg0: string): number { + return this.getDefaultColorShader().getUniformFloat(arg0); + } + + public getUniformVector2(arg0: string): Vector2 { + return this.getDefaultColorShader().getUniformVector2(arg0); + } + + public getUniformVector3(arg0: string): Vector3 { + return this.getDefaultColorShader().getUniformVector3(arg0); + } + + public getUniformVector4(arg0: string): Vector4 { + return this.getDefaultColorShader().getUniformVector4(arg0); + } + + public getUniformColor(arg0: string): Color { + return this.getDefaultColorShader().getUniformColor(arg0); + } + + public setTexture(arg0: string, arg1: Texture) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setTexture(arg0, arg1); + } + } + this.setDefine(`USE_${arg0.toLocaleUpperCase()}`, true); + } + + public getTexture(arg0: string): Texture { + return this.getDefaultColorShader().textures[arg0]; + } + + public setUniformBuffer(arg0: string, arg1: UniformGPUBuffer) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setUniformBuffer(arg0, arg1); + } + } + } + + public getUniformBuffer(arg0: string): GPUBufferBase { + return this.getDefaultColorShader().getBuffer(arg0); + } + + public setStorageBuffer(arg0: string, arg1: StorageGPUBuffer) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setStorageBuffer(arg0, arg1); + } + } + } + + public getStorageBuffer(arg0: string): StorageGPUBuffer { + return this.getDefaultColorShader().getBuffer(arg0); + } + + public setStructStorageBuffer(arg0: string, arg1: StructStorageGPUBuffer) { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.setStructStorageBuffer(arg0, arg1); + } + } + } + + public getStructStorageBuffer(arg0: string): GPUBufferBase { + return this.getDefaultColorShader().getBuffer(arg0); + } + + public noticeValueChange() { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.noticeValueChange(); + } + } + } + + public destroy() { + this.getDefaultColorShader().destroy(); + } + + public clone() { + let newShader = new Shader(); + let sourceShaderPassList = this.getDefaultShaders(); + for (const shadePass of sourceShaderPassList) { + newShader.addRenderPass(shadePass); + } + return newShader; + } + + applyUniform() { + for (const pass of this.passShader) { + for (const rd of pass[1]) { + rd.applyUniform(); + } + } + } +} \ No newline at end of file diff --git a/src/gfx/graphics/webGpu/shader/ShaderBase.ts b/src/gfx/graphics/webGpu/shader/ShaderPassBase.ts similarity index 87% rename from src/gfx/graphics/webGpu/shader/ShaderBase.ts rename to src/gfx/graphics/webGpu/shader/ShaderPassBase.ts index d74313ec..a3a188dc 100644 --- a/src/gfx/graphics/webGpu/shader/ShaderBase.ts +++ b/src/gfx/graphics/webGpu/shader/ShaderPassBase.ts @@ -11,9 +11,10 @@ import { UniformGPUBuffer } from "../core/buffer/UniformGPUBuffer"; import { UniformNode } from "../core/uniforms/UniformNode"; import { ShaderReflection } from "./value/ShaderReflectionInfo"; import { UniformValue } from "./value/UniformValue"; +import { MaterialDataUniformGPUBuffer } from "../core/buffer/MaterialDataUniformGPUBuffer"; -export class ShaderBase { +export class ShaderPassBase { /** * Shader Unique instance id */ @@ -59,6 +60,11 @@ export class ShaderBase { */ public uniforms: { [name: string]: UniformNode }; + /** + * Uniform data for materials + */ + public materialDataUniformBuffer: MaterialDataUniformGPUBuffer; + protected _bufferDic: Map; protected _shaderChange: boolean = true; protected _valueChange: boolean = false; @@ -251,10 +257,40 @@ export class ShaderBase { return this.uniforms[name].data; } + public getUniformFloat(name: string): number { + return this.uniforms[name].data; + } + + public getUniformVector2(name: string): Vector2 { + return this.uniforms[name].data; + } + + public getUniformVector3(name: string): Vector3 { + return this.uniforms[name].data; + } + + public getUniformVector4(name: string): Vector4 { + return this.uniforms[name].data; + } + + public getUniformColor(name: string): Color { + return this.uniforms[name].color; + } + + public getBuffer(name: string): GPUBufferBase { + return this._bufferDic[name].data; + } + protected noticeBufferChange(name: string) { } + public applyUniform() { + if (this.materialDataUniformBuffer && this._valueChange) { + this.materialDataUniformBuffer.apply(); + } + } + /** * destroy */ diff --git a/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts b/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts index eb9aca29..4789055e 100644 --- a/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts +++ b/src/gfx/graphics/webGpu/shader/util/ShaderUtil.ts @@ -1,4 +1,4 @@ -import { RenderShader } from "../RenderShader"; +import { RenderShaderPass } from "../RenderShaderPass"; export type VertexPart = { name: string; @@ -21,10 +21,10 @@ export type FragmentPart = { export class ShaderUtil { public static renderShaderModulePool: Map; - public static renderShader: Map; + public static renderShader: Map; public static init() { this.renderShaderModulePool = new Map(); - this.renderShader = new Map(); + this.renderShader = new Map(); } } diff --git a/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts b/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts index edf88bef..26d4bb62 100644 --- a/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts +++ b/src/gfx/graphics/webGpu/shader/value/ShaderReflectionInfo.ts @@ -1,8 +1,8 @@ import { VertexAttributeSize } from '../../../../../core/geometry/VertexAttributeSize'; import { VertexFormat } from '../../../../../core/geometry/VertexFormat'; import { ComputeShader } from '../ComputeShader'; -import { RenderShader } from '../RenderShader'; -import { ShaderBase } from '../ShaderBase'; +import { RenderShaderPass } from '../RenderShaderPass'; +import { ShaderPassBase } from '../ShaderPassBase'; import { Preprocessor } from '../util/Preprocessor'; import { ShaderValue } from './ShaderValue'; @@ -78,7 +78,7 @@ export class ShaderReflection { } } - public static parser2(wgsl: string, shaderBase: ShaderBase) { + public static parser2(wgsl: string, shaderBase: ShaderPassBase) { if (!shaderBase.shaderReflection) shaderBase.shaderReflection = new ShaderReflection(); let shaderReflection = shaderBase.shaderReflection; if (wgsl.indexOf(`@vertex`) != -1) { @@ -140,14 +140,14 @@ export class ShaderReflection { } } - public static final(shaderBase: ShaderBase) { + public static final(shaderBase: ShaderPassBase) { let shaderReflection = shaderBase.shaderReflection; this._shaderReflectionMap.set(shaderBase.shaderVariant, shaderReflection); this.combineShaderReflectionVarInfo(shaderReflection, shaderReflection.vs_variables); this.combineShaderReflectionVarInfo(shaderReflection, shaderReflection.fs_variables); } - public static getShaderReflection2(code: string, shaderBase: ShaderBase) { + public static getShaderReflection2(code: string, shaderBase: ShaderPassBase) { if (shaderBase.shaderVariant != undefined) { let preShader = Preprocessor.parse(code, shaderBase.defineValue); ShaderReflection.parser2(preShader, shaderBase); @@ -188,7 +188,7 @@ export class ShaderReflection { return shaderVariant; } - public static genShaderVariant(shader: ShaderBase) { + public static genShaderVariant(shader: ShaderPassBase) { let shaderVariant = ''; for (const key in shader.uniforms) { shaderVariant += key + ':'; @@ -209,7 +209,7 @@ export class ShaderReflection { return shaderVariant; } - public static genRenderShaderVariant(renderShader: RenderShader) { + public static genRenderShaderVariant(renderShader: RenderShaderPass) { let shaderVariant = `RenderShader(${renderShader.vsName},${renderShader.fsName})`; shaderVariant += '|'; diff --git a/src/gfx/graphics/webGpu/shader/value/ShaderState.ts b/src/gfx/graphics/webGpu/shader/value/ShaderState.ts index f04413d1..eb301609 100644 --- a/src/gfx/graphics/webGpu/shader/value/ShaderState.ts +++ b/src/gfx/graphics/webGpu/shader/value/ShaderState.ts @@ -32,6 +32,7 @@ export class ShaderState { public splitTexture: boolean = false; public alphaCutoff: number; public useFragDepth: boolean = false; + public writeMasks: GPUColorWriteFlags[] = []; public setFromMapValues(values: Map) { if (values.has('blendMode')) { diff --git a/src/gfx/renderJob/GPUContext.ts b/src/gfx/renderJob/GPUContext.ts index 170fb8fc..4ff2857d 100644 --- a/src/gfx/renderJob/GPUContext.ts +++ b/src/gfx/renderJob/GPUContext.ts @@ -4,7 +4,7 @@ import { ProfilerUtil } from "../../util/ProfilerUtil"; import { webGPUContext } from "../graphics/webGpu/Context3D"; import { GlobalBindGroup } from "../graphics/webGpu/core/bindGroups/GlobalBindGroup"; import { ComputeShader } from "../graphics/webGpu/shader/ComputeShader"; -import { RenderShader } from "../graphics/webGpu/shader/RenderShader"; +import { RenderShaderPass } from "../graphics/webGpu/shader/RenderShaderPass"; import { RendererPassState } from "./passRenderer/state/RendererPassState"; /** @@ -13,7 +13,7 @@ import { RendererPassState } from "./passRenderer/state/RendererPassState"; export class GPUContext { public static lastGeometry: GeometryBase; public static lastPipeline: GPURenderPipeline; - public static lastShader: RenderShader; + public static lastShader: RenderShaderPass; public static drawCount: number = 0; public static renderPassCount: number = 0; public static geometryCount: number = 0; @@ -25,10 +25,10 @@ export class GPUContext { /** * renderPipeline before render need bind pipeline * @param encoder current GPURenderPassEncoder {@link GPURenderPassEncoder } {@link GPURenderBundleEncoder } - * @param renderShader render pass shader {@link RenderShader } + * @param renderShader render pass shader {@link RenderShaderPass } * @returns */ - public static bindPipeline(encoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderShader: RenderShader) { + public static bindPipeline(encoder: GPURenderPassEncoder | GPURenderBundleEncoder, renderShader: RenderShaderPass) { if (GPUContext.lastShader != renderShader) { GPUContext.lastShader = renderShader; } else { diff --git a/src/gfx/renderJob/collect/EntityBatchCollect.ts b/src/gfx/renderJob/collect/EntityBatchCollect.ts index 992d9102..b2c7f6cd 100644 --- a/src/gfx/renderJob/collect/EntityBatchCollect.ts +++ b/src/gfx/renderJob/collect/EntityBatchCollect.ts @@ -1,5 +1,5 @@ import { RenderNode } from '../../../components/renderer/RenderNode'; -import { RendererType } from '../passRenderer/state/RendererType'; +import { PassType } from '../passRenderer/state/RendererType'; import { RenderGroup } from './RenderGroup'; /** * @internal @@ -18,12 +18,12 @@ export class EntityBatchCollect { g_key += node.geometry.instanceID; for (let i = 0; i < node.materials.length; i++) { const mat = node.materials[i]; - s_key += mat.defaultPass.shaderVariant; + s_key += mat.shader.getDefaultColorShader().shaderVariant; } let key = g_key + s_key; if (!this.renderGroup.has(key)) { this.renderGroup.set(key, { - bundleMap: new Map(), + bundleMap: new Map(), key: key, renderNodes: [], }); diff --git a/src/gfx/renderJob/collect/EntityCollect.ts b/src/gfx/renderJob/collect/EntityCollect.ts index 40988012..e1afaa4d 100644 --- a/src/gfx/renderJob/collect/EntityCollect.ts +++ b/src/gfx/renderJob/collect/EntityCollect.ts @@ -1,11 +1,13 @@ -import { Camera3D } from '../../..'; +import { Graphic3DMeshRenderer } from '../../..'; import { Engine3D } from '../../../Engine3D'; import { ILight } from '../../../components/lights/ILight'; import { RenderNode } from '../../../components/renderer/RenderNode'; +import { Camera3D } from '../../../core/Camera3D'; import { Scene3D } from '../../../core/Scene3D'; import { View3D } from '../../../core/View3D'; import { BoundingBox } from '../../../core/bound/BoundingBox'; +import { GeometryBase } from '../../../core/geometry/GeometryBase'; import { Octree } from '../../../core/tree/octree/Octree'; import { Vector3 } from '../../../math/Vector3'; import { zSorterUtil } from '../../../util/ZSorterUtil'; @@ -291,7 +293,7 @@ export class EntityCollect { } public getRenderShaderCollect(view: View3D) { - let viewList = this._renderShaderCollect.renderShaderUpdateList.get(view) || []; + let viewList = this._renderShaderCollect.renderShaderUpdateList.get(view); return viewList; } } diff --git a/src/gfx/renderJob/collect/RenderGroup.ts b/src/gfx/renderJob/collect/RenderGroup.ts index 33ec5b1b..9881c139 100644 --- a/src/gfx/renderJob/collect/RenderGroup.ts +++ b/src/gfx/renderJob/collect/RenderGroup.ts @@ -1,11 +1,11 @@ import { RenderNode } from '../../../components/renderer/RenderNode'; -import { RendererType } from '../passRenderer/state/RendererType'; +import { PassType } from '../passRenderer/state/RendererType'; /** * @internal * @group Post */ export type RenderGroup = { key: string; - bundleMap: Map; + bundleMap: Map; renderNodes: RenderNode[]; }; diff --git a/src/gfx/renderJob/collect/RenderShaderCollect.ts b/src/gfx/renderJob/collect/RenderShaderCollect.ts index 556cfd64..ba488ba9 100644 --- a/src/gfx/renderJob/collect/RenderShaderCollect.ts +++ b/src/gfx/renderJob/collect/RenderShaderCollect.ts @@ -51,11 +51,6 @@ export class RenderShaderCollect { const pass = colorPassList[i]; let key = `${node.geometry.instanceID + pass.instanceID}` rDic.delete(key); - // if (!nodeMap) { - // nodeMap = new Map(); - // rDic.set(key, nodeMap); - // } - // nodeMap.set(node.instanceID, node); } }); } diff --git a/src/gfx/renderJob/collect/ShadowLightsCollect.ts b/src/gfx/renderJob/collect/ShadowLightsCollect.ts index 823f3b44..38e40c50 100644 --- a/src/gfx/renderJob/collect/ShadowLightsCollect.ts +++ b/src/gfx/renderJob/collect/ShadowLightsCollect.ts @@ -1,12 +1,9 @@ -import { StorageGPUBuffer } from '../../..'; -import { Engine3D } from '../../../Engine3D'; import { ILight } from '../../../components/lights/ILight'; - import { LightType } from '../../../components/lights/LightData'; import { Scene3D } from '../../../core/Scene3D'; - +import { View3D } from '../../../core/View3D'; import { CameraUtil } from '../../../util/CameraUtil'; -import { UUID } from '../../../util/Global'; +import { GlobalBindGroup } from '../../graphics/webGpu/core/bindGroups/GlobalBindGroup'; /** * @internal * @group Lights @@ -18,33 +15,18 @@ export class ShadowLightsCollect { public static directionLightList: Map; public static pointLightList: Map; - public static shadowBuffer: Map; - public static shadowLights: Map;//Uint32Array = new Uint32Array(16); + public static shadowLights: Map; public static init() { this.directionLightList = new Map(); this.pointLightList = new Map(); - - this.shadowBuffer = new Map; - this.shadowLights = new Map; + this.shadowLights = new Map; } - public static createBuffer(scene: Scene3D) { - if (!this.shadowBuffer.has(scene)) { - let buffer = new StorageGPUBuffer(4 + 16); - buffer.visibility = GPUShaderStage.FRAGMENT; - this.shadowBuffer.set(scene, buffer); - - buffer.setInt32('nDirShadowStart', 0); - buffer.setInt32('nDirShadowEnd', 1); - buffer.setInt32('nPointShadowStart', 0); - buffer.setInt32('nPointShadowEnd', 0); - - let list = new Uint32Array(16); - this.shadowLights.set(scene, list); - - buffer.setUint32Array('shadowLights', list); - buffer.apply(); + public static createBuffer(view: View3D) { + if (!this.shadowLights.has(view.scene)) { + let list = new Float32Array(16); + this.shadowLights.set(view.scene, list); } } @@ -175,11 +157,11 @@ export class ShadowLightsCollect { } - public static update(scene3D: Scene3D) { - let shadowBuffer = this.shadowBuffer.get(scene3D); - let shadowLights = this.shadowLights.get(scene3D); - let directionLightList = ShadowLightsCollect.directionLightList.get(scene3D); - let pointLightList = ShadowLightsCollect.pointLightList.get(scene3D); + public static update(view: View3D) { + let globalUniform = GlobalBindGroup.getCameraGroup(view.camera); + let shadowLights = this.shadowLights.get(view.scene); + let directionLightList = ShadowLightsCollect.directionLightList.get(view.scene); + let pointLightList = ShadowLightsCollect.pointLightList.get(view.scene); let nDirShadowStart: number = 0; let nDirShadowEnd: number = 0; @@ -195,8 +177,8 @@ export class ShadowLightsCollect { } nDirShadowEnd = directionLightList.length; } - shadowBuffer.setInt32('nDirShadowStart', nDirShadowStart); - shadowBuffer.setInt32('nDirShadowEnd', nDirShadowEnd); + globalUniform.dirShadowStart = nDirShadowStart; + globalUniform.dirShadowEnd = nDirShadowEnd; if (pointLightList) { nPointShadowStart = nDirShadowEnd; @@ -208,10 +190,9 @@ export class ShadowLightsCollect { } nPointShadowEnd = nPointShadowStart + pointLightList.length; } - shadowBuffer.setInt32('nPointShadowStart', nPointShadowStart); - shadowBuffer.setInt32('nPointShadowEnd', nPointShadowEnd); - shadowBuffer.setUint32Array(`shadowLights`, shadowLights); - shadowBuffer.apply(); + globalUniform.pointShadowStart = nPointShadowStart; + globalUniform.pointShadowEnd = nPointShadowEnd; + globalUniform.shadowLights = shadowLights; } } diff --git a/src/gfx/renderJob/frame/GBufferFrame.ts b/src/gfx/renderJob/frame/GBufferFrame.ts index 2c40133f..c6976b3e 100644 --- a/src/gfx/renderJob/frame/GBufferFrame.ts +++ b/src/gfx/renderJob/frame/GBufferFrame.ts @@ -1,3 +1,4 @@ +import { Engine3D } from "../../.."; import { VirtualTexture } from "../../../textures/VirtualTexture"; import { webGPUContext } from "../../graphics/webGpu/Context3D"; import { GPUTextureFormat } from "../../graphics/webGpu/WebGPUConst"; @@ -8,57 +9,57 @@ import { RTResourceMap } from "./RTResourceMap"; export class GBufferFrame extends RTFrame { public static gBufferMap: Map = new Map(); - + public static bufferTexture: boolean = false; constructor() { super([], []); } crateGBuffer(key: string, rtWidth: number, rtHeight: number) { - let attachments = this.attachments; + let attachments = this.renderTargets; let reDescriptors = this.rtDescriptors; - // GPUTextureFormat.rgba16float, GPUTextureFormat.rgba8unorm, GPUTextureFormat.rgba8unorm let colorBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.colorBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba16float, false); let positionBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.positionBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba16float, false); let normalBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.normalBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba8unorm, false); let materialBufferTex = RTResourceMap.createRTTexture(key + RTResourceConfig.materialBufferTex_NAME, rtWidth, rtHeight, GPUTextureFormat.rgba8unorm, false); - attachments.push(colorBufferTex); - attachments.push(positionBufferTex); - attachments.push(normalBufferTex); - attachments.push(materialBufferTex); + if (GBufferFrame.bufferTexture) { + attachments.push(colorBufferTex); + attachments.push(positionBufferTex); + attachments.push(normalBufferTex); + attachments.push(materialBufferTex); + } let colorRTDes = new RTDescriptor(); colorRTDes.loadOp = `clear`; - // colorRTDes.clearValue = [1,0,0,1]; - //depth24plus-stencil8 - let depthTexture = new VirtualTexture(rtWidth, rtHeight, GPUTextureFormat.depth32float, false); - // let depthTexture = new VirtualTexture(rtWidth, rtHeight, `depth24plus`, false); + let depthTexture = new VirtualTexture(rtWidth, rtHeight, GPUTextureFormat.depth24plus, false); depthTexture.name = `depthTexture`; let depthDec = new RTDescriptor(); depthDec.loadOp = `load`; this.depthTexture = depthTexture; - reDescriptors.push(colorRTDes); - reDescriptors.push(new RTDescriptor()); - reDescriptors.push(new RTDescriptor()); - reDescriptors.push(new RTDescriptor()); + if (GBufferFrame.bufferTexture) { + reDescriptors.push(colorRTDes); + reDescriptors.push(new RTDescriptor()); + reDescriptors.push(new RTDescriptor()); + reDescriptors.push(new RTDescriptor()); + } } public getColorMap() { - return this.attachments[0]; + return this.renderTargets[0]; } public getPositionMap() { - return this.attachments[1]; + return this.renderTargets[1]; } public getNormalMap() { - return this.attachments[2]; + return this.renderTargets[2]; } public getMaterialMap() { - return this.attachments[3]; + return this.renderTargets[3]; } /** diff --git a/src/gfx/renderJob/frame/ProbeGBufferFrame.ts b/src/gfx/renderJob/frame/ProbeGBufferFrame.ts index 6ee02c9a..9fa95d81 100644 --- a/src/gfx/renderJob/frame/ProbeGBufferFrame.ts +++ b/src/gfx/renderJob/frame/ProbeGBufferFrame.ts @@ -13,7 +13,7 @@ export class ProbeGBufferFrame extends RTFrame { } crateGBuffer(rtWidth: number, rtHeight: number) { - let attachments = this.attachments; + let attachments = this.renderTargets; let rtDescriptors = this.rtDescriptors; let positionMap = new VirtualTexture(rtWidth, rtHeight, GPUTextureFormat.rgba16float, false); positionMap.name = `positionMap`; diff --git a/src/gfx/renderJob/frame/RTFrame.ts b/src/gfx/renderJob/frame/RTFrame.ts index b0093e02..a06bd644 100644 --- a/src/gfx/renderJob/frame/RTFrame.ts +++ b/src/gfx/renderJob/frame/RTFrame.ts @@ -5,7 +5,7 @@ import { RTDescriptor } from "../../graphics/webGpu/descriptor/RTDescriptor"; export class RTFrame { public label: string; public customSize: boolean = false; - public attachments: VirtualTexture[]; + public renderTargets: VirtualTexture[]; public rtDescriptors: RTDescriptor[]; public zPreTexture: VirtualTexture; @@ -17,7 +17,7 @@ export class RTFrame { public isOutTarget: boolean = true; constructor(attachments: VirtualTexture[], rtDescriptors: RTDescriptor[], depthTexture?: VirtualTexture, zPreTexture?: VirtualTexture, isOutTarget: boolean = true) { - this.attachments = attachments; + this.renderTargets = attachments; this.rtDescriptors = rtDescriptors; this.depthTexture = depthTexture; this.zPreTexture = zPreTexture; @@ -25,7 +25,7 @@ export class RTFrame { } public clone2Frame(rtFrame: RTFrame) { - rtFrame.attachments.push(...this.attachments.concat()); + rtFrame.renderTargets.push(...this.renderTargets.concat()); for (let i = 0; i < this.rtDescriptors.length; i++) { const des = this.rtDescriptors[i]; let rtDes = new RTDescriptor(); diff --git a/src/gfx/renderJob/frame/RTResourceMap.ts b/src/gfx/renderJob/frame/RTResourceMap.ts index 3ed7f278..dbcaed69 100644 --- a/src/gfx/renderJob/frame/RTResourceMap.ts +++ b/src/gfx/renderJob/frame/RTResourceMap.ts @@ -47,14 +47,14 @@ export class RTResourceMap { return rt; } - public static createViewQuad(name: string, shaderVS: string, shaderFS: string, outRtTexture: VirtualTexture, shaderUniforms?: { [uniName: string]: UniformNode }, multisample: number = 0) { + public static createViewQuad(name: string, shaderVS: string, shaderFS: string, outRtTexture: VirtualTexture, multisample: number = 0) { let rtFrame = new RTFrame([ outRtTexture ], [ new RTDescriptor() ]); - let viewQuad = new ViewQuad(shaderVS, shaderFS, rtFrame, shaderUniforms, multisample); + let viewQuad = new ViewQuad(shaderVS, shaderFS, rtFrame, multisample); RTResourceMap.rtViewQuad.set(name, viewQuad); return viewQuad; } diff --git a/src/gfx/renderJob/jobs/ForwardRenderJob.ts b/src/gfx/renderJob/jobs/ForwardRenderJob.ts index f6d48913..99b1aedd 100644 --- a/src/gfx/renderJob/jobs/ForwardRenderJob.ts +++ b/src/gfx/renderJob/jobs/ForwardRenderJob.ts @@ -5,6 +5,10 @@ import { ColorPassRenderer } from '../passRenderer/color/ColorPassRenderer'; import { GBufferFrame } from '../frame/GBufferFrame'; import { RendererJob } from './RendererJob'; import { DDGIProbeRenderer } from '../passRenderer/ddgi/DDGIProbeRenderer'; +import { webGPUContext } from '../../graphics/webGpu/Context3D'; +import { RTResourceConfig } from '../config/RTResourceConfig'; +import { RTResourceMap } from '../frame/RTResourceMap'; +import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; /** * Forward+ * Every time a forward rendering is performed, @@ -21,6 +25,7 @@ export class ForwardRenderJob extends RendererJob { public start(): void { super.start(); + let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); { let debugTextures = []; @@ -32,6 +37,11 @@ export class ForwardRenderJob extends RendererJob { colorPassRenderer.setRenderStates(rtFrame); + for (let i = 0; i < rtFrame.renderTargets.length; i++) { + const tex = rtFrame.renderTargets[i]; + debugTextures.push(tex); + } + if (Engine3D.setting.gi.enable) { let lightEntries = GlobalBindGroup.getLightEntries(this.view.scene); this.ddgiProbeRenderer = new DDGIProbeRenderer(lightEntries.irradianceVolume); diff --git a/src/gfx/renderJob/jobs/RenderMap.ts b/src/gfx/renderJob/jobs/RenderMap.ts index 44a04ea0..b0969e21 100644 --- a/src/gfx/renderJob/jobs/RenderMap.ts +++ b/src/gfx/renderJob/jobs/RenderMap.ts @@ -1,15 +1,15 @@ import { Camera3D } from "../../../core/Camera3D"; import { Scene3D } from "../../../core/Scene3D"; import { RendererBase } from "../passRenderer/RendererBase"; -import { RendererType } from "../passRenderer/state/RendererType"; +import { PassType } from "../passRenderer/state/RendererType"; export class RendererMap { - private map: Map; + private map: Map; private passRendererList: RendererBase[]; constructor() { - this.map = new Map(); + this.map = new Map(); this.passRendererList = []; } @@ -24,7 +24,7 @@ export class RendererMap { } } - public getRenderer(passType: RendererType): RendererBase { + public getRenderer(passType: PassType): RendererBase { return this.map.get(passType); } @@ -32,7 +32,7 @@ export class RendererMap { this.passRendererList.push(renderer); } - public getAllRenderer(): Map { + public getAllRenderer(): Map { return this.map; } diff --git a/src/gfx/renderJob/jobs/RendererJob.ts b/src/gfx/renderJob/jobs/RendererJob.ts index 8cb6a79d..ec8f2fdd 100644 --- a/src/gfx/renderJob/jobs/RendererJob.ts +++ b/src/gfx/renderJob/jobs/RendererJob.ts @@ -17,6 +17,7 @@ import { PostBase } from '../post/PostBase'; import { RendererBase } from '../passRenderer/RendererBase'; import { Ctor } from '../../../util/Global'; import { DDGIProbeRenderer } from '../passRenderer/ddgi/DDGIProbeRenderer'; +import { Texture } from '../../graphics/webGpu/core/texture/Texture'; /** * render jobs @@ -74,6 +75,7 @@ export class RendererJob { */ public pauseRender: boolean = false; public pickFire: PickFire; + public renderState: boolean = false; protected _view: View3D; /** @@ -124,6 +126,7 @@ export class RendererJob { * start render task */ public start() { + this.renderState = true; } // public get guiCanvas(): UICanvas { @@ -162,7 +165,10 @@ export class RendererJob { * @param post */ public addPost(post: PostBase): PostBase | PostBase[] { - if (!this.postRenderer) this.enablePost(GBufferFrame.getGBufferFrame('ColorPassGBuffer')); + if (!this.postRenderer) { + GBufferFrame.bufferTexture = true; + this.enablePost(GBufferFrame.getGBufferFrame('ColorPassGBuffer')); + } if (post instanceof PostBase) { this.postRenderer.attachPost(this.view, post); @@ -198,7 +204,7 @@ export class RendererJob { this.clusterLightingRender.render(view, this.occlusionSystem); if (this.shadowMapPassRenderer) { - ShadowLightsCollect.update(view.scene); + ShadowLightsCollect.update(view); this.shadowMapPassRenderer.render(view, this.occlusionSystem); } @@ -226,6 +232,7 @@ export class RendererJob { if (this.postRenderer && this.postRenderer.postList.length > 0) { this.postRenderer.render(view); } + } public debug() { diff --git a/src/gfx/renderJob/passRenderer/RenderContext.ts b/src/gfx/renderJob/passRenderer/RenderContext.ts index 875e8763..ff25bc0d 100644 --- a/src/gfx/renderJob/passRenderer/RenderContext.ts +++ b/src/gfx/renderJob/passRenderer/RenderContext.ts @@ -24,19 +24,23 @@ export class RenderContext { * continue renderer pass state * @returns */ - public beginContinueRendererPassState() { + public beginContinueRendererPassState(color_loadOp: GPULoadOp = 'load', depth_loadOp: GPULoadOp = 'load') { if (this.rendererPassStates.length > 0) { let splitRtFrame = this.rtFrame.clone(); for (const iterator of splitRtFrame.rtDescriptors) { iterator.loadOp = `load`; // iterator.storeOp = `discard`; } - splitRtFrame.depthLoadOp = "load"; - let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(splitRtFrame); + splitRtFrame.depthLoadOp = depth_loadOp; + let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(splitRtFrame, color_loadOp); this.rendererPassStates.push(splitRendererPassState); return splitRendererPassState; } else { - let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame); + // for (const iterator of this.rtFrame.rtDescriptors) { + // iterator.loadOp = color_loadOp; + // } + this.rtFrame.depthLoadOp = depth_loadOp; + let splitRendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, color_loadOp); this.rendererPassStates.push(splitRendererPassState); return splitRendererPassState; } @@ -46,8 +50,14 @@ export class RenderContext { return this.rendererPassStates[this.rendererPassStates.length - 1]; } - public beginRenderPass() { - this.beginContinueRendererPassState(); + public beginOpaqueRenderPass() { + this.beginContinueRendererPassState('clear', 'clear'); + this.begineNewCommand(); + this.beginNewEncoder(); + } + + public beginTransparentRenderPass() { + this.beginContinueRendererPassState('load', 'load'); this.begineNewCommand(); this.beginNewEncoder(); } diff --git a/src/gfx/renderJob/passRenderer/RendererBase.ts b/src/gfx/renderJob/passRenderer/RendererBase.ts index 5e17c100..ae43b94a 100644 --- a/src/gfx/renderJob/passRenderer/RendererBase.ts +++ b/src/gfx/renderJob/passRenderer/RendererBase.ts @@ -14,10 +14,13 @@ import { EntityCollect } from "../collect/EntityCollect"; import { RTFrame } from "../frame/RTFrame"; import { OcclusionSystem } from "../occlusion/OcclusionSystem"; import { RendererPassState } from "./state/RendererPassState"; -import { RendererType } from "./state/RendererType"; +import { PassType } from "./state/RendererType"; import { RenderContext } from "./RenderContext"; import { ClusterLightingRender } from "./cluster/ClusterLightingRender"; import { ClusterLightingBuffer } from "./cluster/ClusterLightingBuffer"; +import { RTResourceMap } from "../frame/RTResourceMap"; +import { RTResourceConfig } from "../config/RTResourceConfig"; +import { webGPUContext } from "../../graphics/webGpu/Context3D"; /** @@ -33,14 +36,14 @@ export class RendererBase extends CEventDispatcher { protected renderContext: RenderContext; - protected _rendererType: RendererType; + protected _rendererType: PassType; protected _rtFrame: RTFrame; - public get passType(): RendererType { + public get passType(): PassType { return this._rendererType; } - public set passType(value: RendererType) { + public set passType(value: PassType) { this._rendererType = value; } @@ -63,6 +66,7 @@ export class RendererBase extends CEventDispatcher { } this.renderContext = new RenderContext(rtFrame); + } public setIrradiance(probeIrradianceMap: VirtualTexture, probeDepthMap: VirtualTexture) { diff --git a/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts b/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts index 481e5a8b..16ccd831 100644 --- a/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts +++ b/src/gfx/renderJob/passRenderer/cluster/ClusterLightingRender.ts @@ -6,7 +6,7 @@ import { EntityCollect } from '../../collect/EntityCollect'; import { GPUContext } from '../../GPUContext'; import { OcclusionSystem } from '../../occlusion/OcclusionSystem'; import { RendererBase } from '../RendererBase'; -import { RendererType } from '../state/RendererType'; +import { PassType } from '../state/RendererType'; import { ILight } from '../../../../components/lights/ILight'; import { ClusterLightingBuffer } from './ClusterLightingBuffer'; import { ClusterBoundsSource_cs } from '../../../../assets/shader/cluster/ClusterBoundsSource_cs'; @@ -33,7 +33,7 @@ export class ClusterLightingRender extends RendererBase { constructor(view: View3D) { super(); - this.passType = RendererType.Cluster; + this.passType = PassType.Cluster; this.initCompute(view); } @@ -67,40 +67,40 @@ export class ClusterLightingRender extends RendererBase { this.resize = true; - GUIHelp.addButton("clusterBuffer", () => { - let od = this.clusterLightingBuffer.clusterBuffer.readBuffer(); - console.log(od); - let byteLength = 2 * 4; - for (let i = 0; i < numClusters; i++) { - const element = new Float32Array(od.buffer, i * byteLength * 4, byteLength); - let p0 = new Vector3(element[0], element[1], element[2], element[3]); - let p1 = new Vector3(element[4], element[5], element[6], element[7]); - view.graphic3D.drawBox(i + "-box", p0, p1, Color.random()); - } - }); - - GUIHelp.addButton("assignTable", () => { - let od = this.clusterLightingBuffer.assignTableBuffer.readBuffer(); - for (let i = 0; i < od.length / 4; i++) { - const count = od[i * 4 + 0]; - const start = od[i * 4 + 1]; - const e1 = od[i * 4 + 2]; - const e2 = od[i * 4 + 3]; - if (count >= 1) { - console.log(count); - } - - if ((start + count) > start + 1) { - console.log(count, start, e1, e2); - } - } - console.log(od); - }); - - GUIHelp.addButton("clustersUniformBuffer", () => { - let od = this.clusterLightingBuffer.clustersUniformBuffer.readBuffer(); - console.log(od); - }); + // GUIHelp.addButton("clusterBuffer", () => { + // let od = this.clusterLightingBuffer.clusterBuffer.readBuffer(); + // console.log(od); + // let byteLength = 2 * 4; + // for (let i = 0; i < numClusters; i++) { + // const element = new Float32Array(od.buffer, i * byteLength * 4, byteLength); + // let p0 = new Vector3(element[0], element[1], element[2], element[3]); + // let p1 = new Vector3(element[4], element[5], element[6], element[7]); + // view.graphic3D.drawBox(i + "-box", p0, p1, Color.random()); + // } + // }); + + // GUIHelp.addButton("assignTable", () => { + // let od = this.clusterLightingBuffer.assignTableBuffer.readBuffer(); + // for (let i = 0; i < od.length / 4; i++) { + // const count = od[i * 4 + 0]; + // const start = od[i * 4 + 1]; + // const e1 = od[i * 4 + 2]; + // const e2 = od[i * 4 + 3]; + // if (count >= 1) { + // console.log(count); + // } + + // if ((start + count) > start + 1) { + // console.log(count, start, e1, e2); + // } + // } + // console.log(od); + // }); + + // GUIHelp.addButton("clustersUniformBuffer", () => { + // let od = this.clusterLightingBuffer.clustersUniformBuffer.readBuffer(); + // console.log(od); + // }); } render(view: View3D, occlusionSystem: OcclusionSystem) { diff --git a/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts b/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts index b642d547..6d403766 100644 --- a/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/color/ColorPassRenderer.ts @@ -4,11 +4,13 @@ import { View3D } from "../../../../core/View3D"; import { ProfilerUtil } from "../../../../util/ProfilerUtil"; import { GPUContext } from "../../GPUContext"; import { EntityCollect } from "../../collect/EntityCollect"; +import { RTResourceConfig } from "../../config/RTResourceConfig"; +import { RTResourceMap } from "../../frame/RTResourceMap"; import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RenderContext } from "../RenderContext"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; /** * @internal @@ -19,7 +21,7 @@ import { RendererType } from "../state/RendererType"; export class ColorPassRenderer extends RendererBase { constructor() { super(); - this.passType = RendererType.COLOR; + this.passType = PassType.COLOR; } public render(view: View3D, occlusionSystem: OcclusionSystem, clusterLightingBuffer?: ClusterLightingBuffer, maskTr: boolean = false) { @@ -38,7 +40,7 @@ export class ColorPassRenderer extends RendererBase { { ProfilerUtil.start("ColorPass Draw Opaque"); - this.renderContext.beginRenderPass(); + this.renderContext.beginOpaqueRenderPass(); let command = this.renderContext.command; let renderPassEncoder = this.renderContext.encoder; @@ -83,7 +85,7 @@ export class ColorPassRenderer extends RendererBase { { ProfilerUtil.start("ColorPass Draw Transparent"); - this.renderContext.beginRenderPass(); + this.renderContext.beginTransparentRenderPass(); let command = this.renderContext.command; let renderPassEncoder = this.renderContext.encoder; @@ -105,6 +107,13 @@ export class ColorPassRenderer extends RendererBase { graphic3DRenderNode.renderPass2(view, this._rendererType, this.splitRendererPassState, clusterLightingBuffer, renderPassEncoder); } + // let graphicsMesh = EntityCollect.instance.getGraphicMesh(view); + // for (const iterator of graphicsMesh) { + // let meshGroup = iterator; + // meshGroup.nodeUpdate(view, this._rendererType, this.splitRendererPassState, clusterLightingBuffer); + // meshGroup.renderPass2(view, this._rendererType, this.splitRendererPassState, clusterLightingBuffer, renderPassEncoder); + // } + this.renderContext.endRenderPass(); ProfilerUtil.end("ColorPass Draw Transparent"); @@ -114,8 +123,8 @@ export class ColorPassRenderer extends RendererBase { } public drawNodes(view: View3D, renderContext: RenderContext, nodes: RenderNode[], occlusionSystem: OcclusionSystem, clusterLightingBuffer: ClusterLightingBuffer) { - { - let viewRenderList = EntityCollect.instance.getRenderShaderCollect(view); + let viewRenderList = EntityCollect.instance.getRenderShaderCollect(view); + if (viewRenderList) { for (const renderList of viewRenderList) { let nodeMap = renderList[1]; for (const iterator of nodeMap) { diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts index cc58cd42..a69acf5c 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceComputePass.ts @@ -43,7 +43,7 @@ export class DDGIIrradianceComputePass { this.computeShader.setStorageBuffer(`depthRaysBuffer`, this.depthRaysBuffer); this.computeShader.setStorageBuffer(`probes`, this.volume.probesBuffer); - this.computeShader.setStorageBuffer(`uniformData`, this.volume.irradianceVolumeBuffer); + this.computeShader.setUniformBuffer(`uniformData`, this.volume.irradianceVolumeBuffer); this.computeShader.setStorageBuffer("models", GlobalBindGroup.modelMatrixBindGroup.matrixBufferDst); } diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts index 1bab3631..342ba806 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIIrradianceVolume.ts @@ -3,6 +3,7 @@ import { Vector3 } from "../../../../math/Vector3"; import { Probe } from "./Probe"; import { GlobalIlluminationSetting } from "../../../../setting/GlobalIlluminationSetting"; import { StorageGPUBuffer } from "../../../graphics/webGpu/core/buffer/StorageGPUBuffer"; +import { UniformGPUBuffer } from "../../../.."; /** * @internal * @group Post @@ -15,7 +16,7 @@ export class DDGIIrradianceVolume { private randomOrientation: Matrix4; private startPosition: Vector3 = new Vector3(); private isVolumeChange: boolean = true; - public irradianceVolumeBuffer: StorageGPUBuffer; + public irradianceVolumeBuffer: UniformGPUBuffer; //__make random direction private readonly directionDistance: number = 20; @@ -37,7 +38,7 @@ export class DDGIIrradianceVolume { this.setting = setting; this.randomOrientation = new Matrix4(false); this.randomOrientation.identity(); - this.irradianceVolumeBuffer = new StorageGPUBuffer(80); + this.irradianceVolumeBuffer = new UniformGPUBuffer(80); this.createFramesBuffer(); //center this.arroundPositions.push(this.centerDirection.clone()); diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts index eb6bf5c6..f117be71 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIMultiBouncePass.ts @@ -28,7 +28,7 @@ export class DDGIMultiBouncePass { this.computerShader = new ComputeShader(MultiBouncePass_cs); this.computerShader.setStorageTexture("outputBuffer", this.blendTexture); - this.computerShader.setStorageBuffer("uniformData", this.volume.irradianceVolumeBuffer); + this.computerShader.setUniformBuffer("uniformData", this.volume.irradianceVolumeBuffer); } public setInputs(inputs: VirtualTexture[]) { diff --git a/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts b/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts index db921b5d..201abaad 100644 --- a/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts +++ b/src/gfx/renderJob/passRenderer/ddgi/DDGIProbeRenderer.ts @@ -8,7 +8,7 @@ import { GPUContext } from '../../GPUContext'; import { ProbeGBufferFrame } from '../../frame/ProbeGBufferFrame'; import { OcclusionSystem } from '../../occlusion/OcclusionSystem'; import { RendererBase } from '../RendererBase'; -import { RendererType } from '../state/RendererType'; +import { PassType } from '../state/RendererType'; import { DDGIIrradianceComputePass } from './DDGIIrradianceComputePass'; import { DDGIIrradianceVolume } from './DDGIIrradianceVolume'; import { DDGIMultiBouncePass } from './DDGIMultiBouncePass'; @@ -62,7 +62,7 @@ export class DDGIProbeRenderer extends RendererBase { constructor(volume: DDGIIrradianceVolume) { super(); - this.passType = RendererType.GI; + this.passType = PassType.GI; this.volume = volume; let giSetting = volume.setting; @@ -79,9 +79,9 @@ export class DDGIProbeRenderer extends RendererBase { this.probeRenderResult = new ProbeRenderResult(); let probeGBufferFrame = new ProbeGBufferFrame(this.sizeW, this.sizeH); - this.positionMap = probeGBufferFrame.attachments[0]; - this.normalMap = probeGBufferFrame.attachments[1]; - this.colorMap = probeGBufferFrame.attachments[2]; + this.positionMap = probeGBufferFrame.renderTargets[0]; + this.normalMap = probeGBufferFrame.renderTargets[1]; + this.colorMap = probeGBufferFrame.renderTargets[2]; this.setRenderStates(probeGBufferFrame); } @@ -299,7 +299,7 @@ export class DDGIProbeRenderer extends RendererBase { if (execRender) { let probeList = EntityCollect.instance.getProbes(view.scene); this.renderContext.clean(); - this.renderContext.beginRenderPass(); + this.renderContext.beginOpaqueRenderPass(); this.tempProbeList.length = 0; let remainCount = Math.min(this.probeCountPerFrame, probeList.length); this.probeRenderResult.count = remainCount; diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts index efef4ed6..cb109b45 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DBatchRenderer.ts @@ -5,7 +5,7 @@ import { Color } from "../../../../math/Color"; import { Vector3 } from "../../../../math/Vector3"; import { RendererMask } from "../state/RendererMask"; import { RendererPassState } from "../state/RendererPassState"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; import { ClusterLightingRender } from "../cluster/ClusterLightingRender"; import { Graphic3DFixedRenderPipeline } from "./Graphic3DFixedRenderPipeline"; import { GraphicConfig } from "./GraphicConfig"; @@ -82,7 +82,7 @@ export class Graphic3DBatchRenderer extends RenderNode { this._readyPipeline = true; } - public nodeUpdate(view: View3D, passType: RendererType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { + public nodeUpdate(view: View3D, passType: PassType, renderPassState: RendererPassState, clusterLightingBuffer?: ClusterLightingBuffer) { // if(!this.enable || passType != RendererType.COLOR ) return ; if (this.mDirtyData) { this.mRenderPipeline.reset(); @@ -94,7 +94,7 @@ export class Graphic3DBatchRenderer extends RenderNode { return; } - public renderPass2(view: View3D, passType: RendererType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { + public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) { // if(!this.enable || passType != RendererType.COLOR ) return ; this.mRenderPipeline.render(rendererPassState, encoder); } diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts index 084b80ea..70067ffd 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DFixedRenderPipeline.ts @@ -56,7 +56,8 @@ export class Graphic3DFixedRenderPipeline { } let remainLength = this.mDataBuffer.length - this.mOffset; - this.mDataBuffer.set(data.slice(0, remainLength), this.mOffset); + // this.mDataBuffer.set(data.slice(0, remainLength), this.mOffset); + this.mDataBuffer.set(data, this.mOffset,); this.mOffset += remainLength; data = data.slice(remainLength); } @@ -86,10 +87,10 @@ export class Graphic3DFixedRenderPipeline { const device = webGPUContext.device; if (!this.mRenderPipeline) { - let targets = rendererPassState.outAttachments; + let targets = rendererPassState.renderTargetTextures; if (rendererPassState.outColor != -1) { let target = targets[rendererPassState.outColor]; - target.blend = BlendFactor.getBlend(BlendMode.NONE); + target.blend = BlendFactor.getBlend(BlendMode.ALPHA); } this.mRenderPipelineLayout = device.createPipelineLayout({ @@ -111,7 +112,7 @@ export class Graphic3DFixedRenderPipeline { }, primitive: { topology: this.mGPUPrimitiveTopology, - cullMode: GPUCullMode.back, + cullMode: GPUCullMode.none, frontFace: 'ccw', }, }; diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts index 8e9b42ac..686c8eaf 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts @@ -248,9 +248,9 @@ export class Graphic3D extends Object3D { this.mFillRender.fillShapeData(uuid, 'fill', color, [ origin, new Vector3(origin.x + width, origin.y, origin.z), - new Vector3(origin.x + width, origin.y + height, origin.z), - new Vector3(origin.x + width, origin.y + height, origin.z), - new Vector3(origin.x, origin.y + height, origin.z), + new Vector3(origin.x + width, origin.y, origin.z + height), + new Vector3(origin.x + width, origin.y, origin.z + height), + new Vector3(origin.x, origin.y, origin.z + height), origin ]); } @@ -300,10 +300,11 @@ export class Graphic3D extends Object3D { * @param transform The Transform that needs to be bound * @param color The color of the wire frame */ - public drawMeshWireframe(uuid: string, geometry: GeometryBase, transform: Transform, color: Color = Color.COLOR_WHITE) { + public drawMeshWireframe(uuid: string, geometry: GeometryBase, transform: Transform, color: Color = Color.COLOR_WHITE, forceUpdate: boolean = false) { if (geometry) this.createCustomShape(uuid, transform ? transform : this.transform).fillShapeData( geometry.genWireframe(), - color + color, + forceUpdate ); } diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts b/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts index 49e6497f..d075a26f 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphics3DShape.ts @@ -99,7 +99,7 @@ export class Graphics3DShape { this.fillShapeData(points, color); } - public fillShapeData(points: Vector3[], colors: Color | Color[]) { + public fillShapeData(points: Vector3[], colors: Color | Color[], forceUpdate: boolean = false) { if (!this.shapeData) { this.shapeData = new Float32Array(GraphicConfig.ShapeVertexSize * points.length); } else if (this.count + GraphicConfig.ShapeVertexSize * points.length >= this.shapeData.length) { @@ -108,25 +108,27 @@ export class Graphics3DShape { this.shapeData = tmp; } - const shapeData = this.shapeData; - for (let i = 0; i < points.length; ++i) { - const point = points[i]; - shapeData[this.count++] = point.x; - shapeData[this.count++] = point.y; - shapeData[this.count++] = point.z; - shapeData[this.count++] = this.transformIndex; + if (forceUpdate || this.dirtyData == false) { + const shapeData = this.shapeData; + for (let i = 0; i < points.length; ++i) { + const point = points[i]; + shapeData[this.count++] = point.x; + shapeData[this.count++] = point.y; + shapeData[this.count++] = point.z; + shapeData[this.count++] = this.transformIndex; - if (colors instanceof Color) { - shapeData[this.count++] = colors.r; - shapeData[this.count++] = colors.g; - shapeData[this.count++] = colors.b; - shapeData[this.count++] = colors.a; - } else { - const color = colors[i]; - shapeData[this.count++] = color.r; - shapeData[this.count++] = color.g; - shapeData[this.count++] = color.b; - shapeData[this.count++] = color.a; + if (colors instanceof Color) { + shapeData[this.count++] = colors.r; + shapeData[this.count++] = colors.g; + shapeData[this.count++] = colors.b; + shapeData[this.count++] = colors.a; + } else { + const color = colors[i]; + shapeData[this.count++] = color.r; + shapeData[this.count++] = color.g; + shapeData[this.count++] = color.b; + shapeData[this.count++] = color.a; + } } } diff --git a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh.ts b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh.ts new file mode 100644 index 00000000..5f35d318 --- /dev/null +++ b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh.ts @@ -0,0 +1,20 @@ +import { Scene3D } from "../../../../../core/Scene3D"; +import { Object3D } from "../../../../../core/entities/Object3D"; +import { GeometryBase } from "../../../../../core/geometry/GeometryBase"; +import { BitmapTexture2DArray } from "../../../../../textures/BitmapTexture2DArray"; +import { Graphic3DMeshRenderer } from "./Graphic3DMeshRenderer"; + +export class Graphic3DMesh { + public static meshMap: Map = new Map(); + public static meshDrawGroup: Map = new Map(); + public static draw(scene: Scene3D, geo: GeometryBase, texture: BitmapTexture2DArray, count: number): Graphic3DMeshRenderer { + if (!this.meshMap.has(geo)) { + let object = new Object3D(); + let renderNode = object.addComponent(Graphic3DMeshRenderer); + renderNode.create(geo, texture, count); + this.meshMap.set(geo, renderNode); + scene.addChild(object); + return renderNode; + } + } +} \ No newline at end of file diff --git a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts new file mode 100644 index 00000000..82ca2a14 --- /dev/null +++ b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts @@ -0,0 +1,55 @@ +import { MeshRenderer } from "../../../../../components/renderer/MeshRenderer"; +import { View3D } from "../../../../../core/View3D"; +import { Object3D } from "../../../../../core/entities/Object3D"; +import { GeometryBase } from "../../../../../core/geometry/GeometryBase"; +import { UnLitTexArrayMaterial } from "../../../../../materials/UnLitTexArrayMaterial"; +import { BitmapTexture2DArray } from "../../../../../textures/BitmapTexture2DArray"; +import { GeometryUtil } from "../../../../../util/GeometryUtil"; +import { StorageGPUBuffer } from "../../../../graphics/webGpu/core/buffer/StorageGPUBuffer"; + +export class Graphic3DMeshRenderer extends MeshRenderer { + public transformBuffer: StorageGPUBuffer; + public sourceGeometry: GeometryBase; + public texture: BitmapTexture2DArray; + public object3Ds: Object3D[]; + + private _onChange: boolean = false; + public init(): void { + super.init(); + } + + public create(source: GeometryBase, tex: BitmapTexture2DArray, num: number) { + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = tex; + this.material = mat; + + this.transformBuffer = new StorageGPUBuffer(num * 2, 0); + this.material.setStorageBuffer("graphicBuffer", this.transformBuffer); + + this.object3Ds = []; + for (let i = 0; i < num; i++) { + const element = new Object3D(); + this.object3Ds.push(element); + this.object3D.addChild(element); + + this.transformBuffer.setFloat("matrix_" + i, element.transform.worldMatrix.index); + this.transformBuffer.setFloat("texId_" + i, 1); + } + + this.transformBuffer.apply(); + this.geometry = GeometryUtil.mergeNumber(source, num); + } + + public setTextureID(i: number, id: number) { + this.transformBuffer.setFloat("texId_" + i, id); + this._onChange = true; + } + + public onUpdate(view?: View3D) { + if (this._onChange) { + this._onChange = false; + this.transformBuffer.apply(); + } + } + +} \ No newline at end of file diff --git a/src/gfx/renderJob/passRenderer/post/PostRenderer.ts b/src/gfx/renderJob/passRenderer/post/PostRenderer.ts index 8d4bec11..27ecbf35 100644 --- a/src/gfx/renderJob/passRenderer/post/PostRenderer.ts +++ b/src/gfx/renderJob/passRenderer/post/PostRenderer.ts @@ -7,7 +7,7 @@ import { GPUContext } from "../../GPUContext"; import { RTFrame } from "../../frame/RTFrame"; import { PostBase } from "../../post/PostBase"; import { RendererBase } from "../RendererBase"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; /** @@ -20,7 +20,7 @@ export class PostRenderer extends RendererBase { constructor() { super(); - this._rendererType = RendererType.POST; + this._rendererType = PassType.POST; this.postList = []; @@ -29,7 +29,7 @@ export class PostRenderer extends RendererBase { public initRenderer() { ShaderLib.register("FullQuad_vert_wgsl", FullQuad_vert_wgsl); - this.finalQuadView = new ViewQuad(`Quad_vert_wgsl`, `Quad_frag_wgsl`, new RTFrame([], []), null, null, false); + this.finalQuadView = new ViewQuad(`Quad_vert_wgsl`, `Quad_frag_wgsl`, new RTFrame([], []), 0, false); } public attachPost(view: View3D, post: PostBase) { diff --git a/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts b/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts index 633787d1..321c5213 100644 --- a/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer.ts @@ -14,7 +14,7 @@ import { RTResourceMap } from "../../frame/RTResourceMap"; import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; import { ZCullingCompute } from "./ZCullingCompute"; /** @@ -28,7 +28,7 @@ export class PreDepthPassRenderer extends RendererBase { zCullingCompute: ZCullingCompute; constructor() { super(); - this.passType = RendererType.DEPTH; + this.passType = PassType.DEPTH; let size = webGPUContext.presentationSize; let scale = 1; diff --git a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts index 5b349716..8815cbaf 100644 --- a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts @@ -19,9 +19,10 @@ import { Time } from '../../../../util/Time'; import { RTDescriptor } from '../../../graphics/webGpu/descriptor/RTDescriptor'; import { WebGPUDescriptorCreator } from '../../../graphics/webGpu/descriptor/WebGPUDescriptorCreator'; import { RendererPassState } from '../state/RendererPassState'; -import { RendererType } from '../state/RendererType'; +import { PassType } from '../state/RendererType'; import { ILight } from '../../../../components/lights/ILight'; -import { Reference } from '../../../..'; +import { ShadowTexture } from '../../../../textures/ShadowTexture'; +import { Reference } from '../../../../util/Reference'; type CubeShadowMapInfo = { cubeCamera: CubeCamera, @@ -43,7 +44,7 @@ export class PointLightShadowRenderer extends RendererBase { public shadowSize: number = 1024; constructor() { super(); - this.passType = RendererType.POINT_SHADOW; + this.passType = PassType.POINT_SHADOW; // this.shadowSize = Engine3D.setting.shadow.pointShadowSize; this._shadowCameraDic = new Map(); @@ -60,11 +61,11 @@ export class PointLightShadowRenderer extends RendererBase { } else { let camera = new PointShadowCubeCamera(view.camera.near, view.camera.far, 90, true); camera.label = lightBase.name; - let depths: VirtualTexture[] = []; + let depths: ShadowTexture[] = []; let rendererPassStates: RendererPassState[] = []; for (let i = 0; i < 6; i++) { - let depthTexture = new VirtualTexture(this.shadowSize, this.shadowSize, this.cubeArrayTexture.format, false); + let depthTexture = new ShadowTexture(this.shadowSize, this.shadowSize, this.cubeArrayTexture.format, false); let rtFrame = new RTFrame([this.colorTexture], [new RTDescriptor()]); depthTexture.name = `shadowDepthTexture_` + lightBase.name + i + "_face"; rtFrame.depthTexture = depthTexture; @@ -75,8 +76,7 @@ export class PointLightShadowRenderer extends RendererBase { rendererPassStates[i] = rendererPassState; depths[i] = depthTexture; - Engine3D.getRenderJob(view).postRenderer.setDebugTexture([depthTexture]); - Engine3D.getRenderJob(view).debug(); + Engine3D.getRenderJob(view).postRenderer?.setDebugTexture([depthTexture]); } cubeShadowMapInfo = { cubeCamera: camera, diff --git a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts index 6b43dca9..9f2ed6bb 100644 --- a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts @@ -15,12 +15,13 @@ import { ShadowLightsCollect } from "../../collect/ShadowLightsCollect"; import { RTFrame } from "../../frame/RTFrame"; import { OcclusionSystem } from "../../occlusion/OcclusionSystem"; import { RendererPassState } from "../state/RendererPassState"; -import { RendererType } from "../state/RendererType"; +import { PassType } from "../state/RendererType"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; import { Reference } from "../../../../util/Reference"; import { Texture } from "../../../graphics/webGpu/core/texture/Texture"; import { CSM } from "../../../../core/csm/CSM"; +import { ShadowTexture } from "../../../../textures/ShadowTexture"; /** * @internal @@ -35,7 +36,7 @@ export class ShadowMapPassRenderer extends RendererBase { constructor() { super(); this.setShadowMap(Engine3D.setting.shadow.shadowSize, CSM.Cascades); - this.passType = RendererType.SHADOW; + this.passType = PassType.SHADOW; } setShadowMap(size: number, cascades: number) { @@ -45,7 +46,7 @@ export class ShadowMapPassRenderer extends RendererBase { for (let i = 0; i < 8; i++) { let rtFrame = new RTFrame([], []); - const tex = new VirtualTexture(size, size, GPUTextureFormat.depth32float, false); + const tex = new ShadowTexture(size, size, GPUTextureFormat.depth32float, false); tex.name = `shadowDepthTexture_${i}`; rtFrame.depthTexture = tex; rtFrame.label = "shadowRender"; diff --git a/src/gfx/renderJob/passRenderer/state/RendererPassState.ts b/src/gfx/renderJob/passRenderer/state/RendererPassState.ts index 46ee9a45..0a584154 100644 --- a/src/gfx/renderJob/passRenderer/state/RendererPassState.ts +++ b/src/gfx/renderJob/passRenderer/state/RendererPassState.ts @@ -15,13 +15,10 @@ export class RendererPassState { public customSize: boolean = false; public zPreTexture: VirtualTexture = null; public depthTexture: VirtualTexture = null; - public outAttachments: GPUColorTargetState[]; + public renderTargetTextures: GPUColorTargetState[]; public outColor: number = -1; public renderTargets: Texture[]; - public rtTextureDescripts: RTDescriptor[]; - // public depthFormat: GPUTextureFormat = 'depth24plus'; - // public depthFormat: GPUTextureFormat = 'depth32float'; - // public depthTexture: GPUTexture; + public rtTextureDescriptors: RTDescriptor[]; public irradianceBuffer: Texture[]; public multisample: number = 0; public multiTexture: GPUTexture; diff --git a/src/gfx/renderJob/passRenderer/state/RendererType.ts b/src/gfx/renderJob/passRenderer/state/RendererType.ts index 09bb584a..d85c9d92 100644 --- a/src/gfx/renderJob/passRenderer/state/RendererType.ts +++ b/src/gfx/renderJob/passRenderer/state/RendererType.ts @@ -1,7 +1,7 @@ /** * @internal */ -export enum RendererType { +export enum PassType { COLOR = 1 << 0, NORMAL = 1 << 1, POSITION = 1 << 2, diff --git a/src/gfx/renderJob/post/BloomPost.ts b/src/gfx/renderJob/post/BloomPost.ts new file mode 100644 index 00000000..e68aecb9 --- /dev/null +++ b/src/gfx/renderJob/post/BloomPost.ts @@ -0,0 +1,280 @@ +import { VirtualTexture } from '../../../textures/VirtualTexture'; +import { UniformGPUBuffer } from '../../graphics/webGpu/core/buffer/UniformGPUBuffer'; +import { WebGPUDescriptorCreator } from '../../graphics/webGpu/descriptor/WebGPUDescriptorCreator'; +import { ComputeShader } from '../../graphics/webGpu/shader/ComputeShader'; +import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; +import { webGPUContext } from '../../graphics/webGpu/Context3D'; +import { GPUContext } from '../GPUContext'; +import { RendererPassState } from '../passRenderer/state/RendererPassState'; +import { PostBase } from './PostBase'; +import { Engine3D } from '../../../Engine3D'; +import { View3D } from '../../../core/View3D'; +import { RTDescriptor } from '../../graphics/webGpu/descriptor/RTDescriptor'; +import { RTFrame } from '../frame/RTFrame'; +import { downSample, post, threshold, upSample } from '../../../assets/shader/compute/BloomEffect_cs'; + +/** + * Bloom Effects + * ``` + * bloom setting + * let cfg = {@link Engine3D.setting.render.postProcessing.bloom}; + *``` + * @group Post Effects + */ +export class BloomPost extends PostBase { + /** + * @internal + */ + RT_BloomUp: VirtualTexture[]; + RT_BloomDown: VirtualTexture[]; + RT_threshold: VirtualTexture; + /** + * @internal + */ + rendererPassState: RendererPassState; + /** + * @internal + */ + thresholdCompute: ComputeShader; + downSampleComputes: ComputeShader[]; + upSampleComputes: ComputeShader[]; + postCompute: ComputeShader; + /** + * @internal + */ + bloomSetting: UniformGPUBuffer; + /** + * @internal + */ + rtFrame: RTFrame; + + constructor() { + super(); + } + + /** + * @internal + */ + onAttach(view: View3D,) { + Engine3D.setting.render.postProcessing.bloom.enable = true; + this.createGUI(); + } + /** + * @internal + */Render + onDetach(view: View3D,) { + Engine3D.setting.render.postProcessing.bloom.enable = false; + this.removeGUI(); + } + + private createGUI() { + } + + private removeGUI() { + } + + public get downSampleBlurSize(): number { + return Engine3D.setting.render.postProcessing.bloom.downSampleBlurSize; + } + public set downSampleBlurSize(value: number) { + Engine3D.setting.render.postProcessing.bloom.downSampleBlurSize = value; + } + + + public get downSampleBlurSigma(): number { + return Engine3D.setting.render.postProcessing.bloom.downSampleBlurSigma; + } + public set downSampleBlurSigma(value: number) { + Engine3D.setting.render.postProcessing.bloom.downSampleBlurSigma = value; + } + + public get upSampleBlurSize(): number { + return Engine3D.setting.render.postProcessing.bloom.upSampleBlurSize; + } + public set upSampleBlurSize(value: number) { + Engine3D.setting.render.postProcessing.bloom.upSampleBlurSize = value; + } + + public get upSampleBlurSigma(): number { + return Engine3D.setting.render.postProcessing.bloom.upSampleBlurSigma; + } + public set upSampleBlurSigma(value: number) { + Engine3D.setting.render.postProcessing.bloom.upSampleBlurSigma = value; + } + + public get luminanceThreshole(): number { + return Engine3D.setting.render.postProcessing.bloom.luminanceThreshole; + } + public set luminanceThreshole(value: number) { + Engine3D.setting.render.postProcessing.bloom.luminanceThreshole = value; + } + + public get bloomIntensity(): number { + return Engine3D.setting.render.postProcessing.bloom.bloomIntensity; + } + public set bloomIntensity(value: number) { + Engine3D.setting.render.postProcessing.bloom.bloomIntensity = value; + } + + private createThreshouldCompute() { + this.thresholdCompute = new ComputeShader(threshold); + + this.autoSetColorTexture('inTex', this.thresholdCompute); + this.thresholdCompute.setStorageTexture(`outTex`, this.RT_threshold); + this.thresholdCompute.setUniformBuffer('bloomCfg', this.bloomSetting); + this.thresholdCompute.workerSizeX = Math.ceil(this.RT_threshold.width / 8); + this.thresholdCompute.workerSizeY = Math.ceil(this.RT_threshold.height / 8); + this.thresholdCompute.workerSizeZ = 1; + } + + private createDownSampleComputes() { + let setting = Engine3D.setting.render.postProcessing.bloom; + const N = setting.downSampleStep; // 下采样次数 + this.downSampleComputes = []; + + for (let i = 0; i < N; i++) { + let compute = new ComputeShader(downSample); + let dstTexture = this.RT_BloomDown[i]; + let srcTexture = i == 0 ? this.RT_threshold : this.RT_BloomDown[i - 1]; + compute.setSamplerTexture(`inTex`, srcTexture); + compute.setStorageTexture(`outTex`, dstTexture); + compute.setUniformBuffer('bloomCfg', this.bloomSetting); + compute.workerSizeX = Math.ceil(dstTexture.width / 8); + compute.workerSizeY = Math.ceil(dstTexture.height / 8); + compute.workerSizeZ = 1; + + this.downSampleComputes.push(compute); + + // Graphics.Blit(RT_BloomDown[i - 1], RT_BloomDown[i], new Material(Shader.Find("Shaders/downSample"))); + } + } + + private createUpSampleComputes() { + let setting = Engine3D.setting.render.postProcessing.bloom; + const N = setting.downSampleStep; // 下采样次数 + this.upSampleComputes = []; + { + let compute = new ComputeShader(upSample); + let dstTexture = this.RT_BloomUp[0]; + let srcTexture = this.RT_BloomDown[N - 2]; + compute.setSamplerTexture(`_MainTex`, srcTexture); + compute.setSamplerTexture(`_PrevMip`, this.RT_BloomDown[N - 1]); + compute.setStorageTexture(`outTex`, dstTexture); + compute.setUniformBuffer('bloomCfg', this.bloomSetting); + compute.workerSizeX = Math.ceil(dstTexture.width / 8); + compute.workerSizeY = Math.ceil(dstTexture.height / 8); + compute.workerSizeZ = 1; + + this.upSampleComputes.push(compute); + } + for (let i = 1; i < N - 1; i++) { + let compute = new ComputeShader(upSample); + let dstTexture = this.RT_BloomUp[i]; + let srcTexture = this.RT_BloomDown[N - 2 - i]; + compute.setSamplerTexture(`_MainTex`, srcTexture); + compute.setSamplerTexture(`_PrevMip`, this.RT_BloomUp[i - 1]); + compute.setStorageTexture(`outTex`, dstTexture); + compute.setUniformBuffer('bloomCfg', this.bloomSetting); + compute.workerSizeX = Math.ceil(dstTexture.width / 8); + compute.workerSizeY = Math.ceil(dstTexture.height / 8); + compute.workerSizeZ = 1; + + this.upSampleComputes.push(compute); + + // Graphics.Blit(RT_BloomDown[i - 1], RT_BloomDown[i], new Material(Shader.Find("Shaders/downSample"))); + } + } + + private createPostCompute() { + let setting = Engine3D.setting.render.postProcessing.bloom; + const N = setting.downSampleStep; // 融合结果 + + this.postCompute = new ComputeShader(post); + + this.autoSetColorTexture('_MainTex', this.postCompute); + this.postCompute.setSamplerTexture(`_BloomTex`, this.RT_BloomUp[N - 2]); + this.postCompute.setStorageTexture(`outTex`, this.RT_threshold); + this.postCompute.setUniformBuffer('bloomCfg', this.bloomSetting); + + this.postCompute.workerSizeX = Math.ceil(this.RT_threshold.width / 8); + this.postCompute.workerSizeY = Math.ceil(this.RT_threshold.height / 8); + this.postCompute.workerSizeZ = 1; + } + + + private createResource() { + let setting = Engine3D.setting.render.postProcessing.bloom; + + this.bloomSetting = new UniformGPUBuffer(4 * 2); //vector4 * 2 + + let presentationSize = webGPUContext.presentationSize; + let screenWidth = presentationSize[0]; + let screenHeight = presentationSize[1]; + + this.RT_threshold = new VirtualTexture(screenWidth, screenHeight, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + + const N = setting.downSampleStep; // 下采样次数 + { + let downSize = 2; + this.RT_BloomDown = []; + + // 创建下纹理 + for (let i = 0; i < N; i++) { + let w = Math.ceil(screenWidth / downSize); + let h = Math.ceil(screenHeight / downSize); + this.RT_BloomDown[i] = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + downSize *= 2; + } + } + + { + // 创建上采样纹理 + this.RT_BloomUp = []; + for (let i = 0; i < N - 1; i++) { + let w = this.RT_BloomDown[N - 2 - i].width; + let h = this.RT_BloomDown[N - 2 - i].height; + this.RT_BloomUp[i] = new VirtualTexture(w, h, GPUTextureFormat.rgba16float, false, GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.TEXTURE_BINDING); + } + } + + let bloomDesc = new RTDescriptor(); + bloomDesc.loadOp = `load`; + + // this.rtFrame = new RTFrame([this.RT_threshold], [bloomDesc]); + // this.rtFrame = new RTFrame([this.RT_BloomDown[4]], [bloomDesc]); + // this.rtFrame = new RTFrame([this.RT_BloomUp[5]], [bloomDesc]); + this.rtFrame = new RTFrame([this.RT_threshold], [bloomDesc]); + } + + /** + * @internal + */ + render(view: View3D, command: GPUCommandEncoder) { + if (!this.thresholdCompute) { + this.createResource(); + this.createThreshouldCompute(); + + this.createDownSampleComputes(); + this.createUpSampleComputes(); + this.createPostCompute(); + + this.rendererPassState = WebGPUDescriptorCreator.createRendererPassState(this.rtFrame, null); + this.rendererPassState.label = "Bloom"; + } + let cfg = Engine3D.setting.render.postProcessing.bloom; + + this.bloomSetting.setFloat('downSampleStep', cfg.downSampleStep); + this.bloomSetting.setFloat('downSampleBlurSize', cfg.downSampleBlurSize); + this.bloomSetting.setFloat('downSampleBlurSigma', cfg.downSampleBlurSigma); + this.bloomSetting.setFloat('upSampleBlurSize', cfg.upSampleBlurSize); + this.bloomSetting.setFloat('upSampleBlurSigma', cfg.upSampleBlurSigma); + this.bloomSetting.setFloat('luminanceThreshole', cfg.luminanceThreshole); + this.bloomSetting.setFloat('bloomIntensity', cfg.bloomIntensity); + + this.bloomSetting.apply(); + + GPUContext.computeCommand(command, [this.thresholdCompute, ...this.downSampleComputes, ...this.upSampleComputes, this.postCompute]); + GPUContext.lastRenderPassState = this.rendererPassState; + } + +} diff --git a/src/gfx/renderJob/post/DepthOfFieldPost.ts b/src/gfx/renderJob/post/DepthOfFieldPost.ts index 79177990..fc92a435 100644 --- a/src/gfx/renderJob/post/DepthOfFieldPost.ts +++ b/src/gfx/renderJob/post/DepthOfFieldPost.ts @@ -129,8 +129,8 @@ export class DepthOfFieldPost extends PostBase { blurCompute.setUniformBuffer('blurSetting', blurSetting); let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - blurCompute.setSamplerTexture(RTResourceConfig.positionBufferTex_NAME, rtFrame.attachments[1]); - blurCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.attachments[2]); + blurCompute.setSamplerTexture(RTResourceConfig.positionBufferTex_NAME, rtFrame.renderTargets[1]); + blurCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.renderTargets[2]); let input = i % 2 == 0 ? this.blurTexture1 : this.blurTexture2; let output = i % 2 == 1 ? this.blurTexture1 : this.blurTexture2; diff --git a/src/gfx/renderJob/post/FXAAPost.ts b/src/gfx/renderJob/post/FXAAPost.ts index fe2ed8bc..031cf277 100644 --- a/src/gfx/renderJob/post/FXAAPost.ts +++ b/src/gfx/renderJob/post/FXAAPost.ts @@ -4,8 +4,6 @@ import { Vector2 } from '../../../math/Vector2'; import { UniformNode } from '../../graphics/webGpu/core/uniforms/UniformNode'; import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; import { webGPUContext } from '../../graphics/webGpu/Context3D'; -import { RTResourceConfig } from '../config/RTResourceConfig'; -import { RTResourceMap } from '../frame/RTResourceMap'; import { PostBase } from './PostBase'; import { View3D } from '../../../core/View3D'; import { FXAAShader } from '../../..'; @@ -21,17 +19,13 @@ export class FXAAPost extends PostBase { constructor() { super(); let presentationSize = webGPUContext.presentationSize; - RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); ShaderLib.register("FXAA_Shader", FXAAShader); - let shaderUniforms = { - u_texel: new UniformNode(new Vector2(1.0 / presentationSize[0], 1.0 / presentationSize[1])), - u_strength: new UniformNode(4), - }; - let rt = this.createRTTexture(`FXAAPost`, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float); - this.createViewQuad(`fxaa`, 'FXAA_Shader', rt, shaderUniforms); + let quad = this.createViewQuad(`fxaa`, 'FXAA_Shader', rt); + quad.quadShader.setUniform("u_texel", new Vector2(1.0 / presentationSize[0], 1.0 / presentationSize[1])); + quad.quadShader.setUniform("u_strength", 4); } /** * @internal diff --git a/src/gfx/renderJob/post/GTAOPost.ts b/src/gfx/renderJob/post/GTAOPost.ts index 2fddb75e..049cb45e 100644 --- a/src/gfx/renderJob/post/GTAOPost.ts +++ b/src/gfx/renderJob/post/GTAOPost.ts @@ -180,9 +180,9 @@ export class GTAOPost extends PostBase { this.gtaoCompute.setStorageBuffer('aoBuffer', this.aoBuffer); let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); //setting.usePosFloat32 ? RTResourceMap.getTexture(RTResourceConfig.positionBufferTex_NAME): - let posTexture = rtFrame.attachments[1]; + let posTexture = rtFrame.renderTargets[1]; this.gtaoCompute.setSamplerTexture(`posTex`, posTexture); - this.gtaoCompute.setSamplerTexture(`normalTex`, rtFrame.attachments[2]); + this.gtaoCompute.setSamplerTexture(`normalTex`, rtFrame.renderTargets[2]); this.autoSetColorTexture('inTex', this.gtaoCompute); this.gtaoCompute.setStorageTexture(`outTex`, this.gtaoTexture); @@ -265,4 +265,4 @@ export class GTAOPost extends PostBase { GPUContext.computeCommand(command, [this.gtaoCompute]); GPUContext.lastRenderPassState = this.rendererPassState; } -} +} \ No newline at end of file diff --git a/src/gfx/renderJob/post/GlobalFog.ts b/src/gfx/renderJob/post/GlobalFog.ts index 459e8c8e..7c8c163b 100644 --- a/src/gfx/renderJob/post/GlobalFog.ts +++ b/src/gfx/renderJob/post/GlobalFog.ts @@ -39,25 +39,28 @@ export class GlobalFog extends PostBase { ShaderLib.register("GlobalFog_shader", GlobalFog_shader); let shaderUniforms = { - fogColor: new UniformNode(new Color(globalFog.fogColor.r, globalFog.fogColor.g, globalFog.fogColor.b, globalFog.fogColor.a)), - fogType: new UniformNode(globalFog.fogType), - fogHeightScale: new UniformNode(globalFog.fogHeightScale), - start: new UniformNode(globalFog.start), - end: new UniformNode(globalFog.end), - density: new UniformNode(globalFog.density), - ins: new UniformNode(globalFog.ins), - falloff: new UniformNode(globalFog.falloff), - rayLength: new UniformNode(globalFog.rayLength), - scatteringExponent: new UniformNode(globalFog.scatteringExponent), - dirHeightLine: new UniformNode(globalFog.dirHeightLine), - skyFactor: new UniformNode(globalFog.skyFactor), - skyRoughness: new UniformNode(globalFog.skyRoughness), - overrideSkyFactor: new UniformNode(globalFog.overrideSkyFactor), isSkyHDR: new UniformNode(0), }; this.rtTexture = this.createRTTexture(`GlobalFog`, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float); - this.viewQuad = this.createViewQuad(`GlobalFog`, 'GlobalFog_shader', this.rtTexture, shaderUniforms); + this.viewQuad = this.createViewQuad(`GlobalFog`, 'GlobalFog_shader', this.rtTexture); + let shader = this.viewQuad.quadShader; + + shader.setUniformColor("fogColor", new Color(globalFog.fogColor.r, globalFog.fogColor.g, globalFog.fogColor.b, globalFog.fogColor.a)); + shader.setUniform("fogType", globalFog.fogType); + shader.setUniform("fogHeightScale", globalFog.fogHeightScale); + shader.setUniform("start", globalFog.start); + shader.setUniform("end", globalFog.end); + shader.setUniform("density", globalFog.density); + shader.setUniform("ins", globalFog.ins); + shader.setUniform("falloff", globalFog.falloff); + shader.setUniform("rayLength", globalFog.rayLength); + shader.setUniform("scatteringExponent", globalFog.scatteringExponent); + shader.setUniform("dirHeightLine", globalFog.dirHeightLine); + shader.setUniform("skyFactor", globalFog.skyFactor); + shader.setUniform("skyRoughness", globalFog.skyRoughness); + shader.setUniform("overrideSkyFactor", globalFog.overrideSkyFactor); + shader.setUniform("isSkyHDR", 0); let ptex = rtFrame.getPositionMap(); let ntex = rtFrame.getNormalMap(); @@ -79,56 +82,56 @@ export class GlobalFog extends PostBase { public set fogType(v: number) { this._globalFog.fogType = v; - this.viewQuad.uniforms['fogType'].value = v; + this.viewQuad.quadShader.setUniform('fogType', v); } public get fogType() { return this._globalFog.fogType; } public set fogHeightScale(v: number) { this._globalFog.fogHeightScale = v; - this.viewQuad.uniforms['fogHeightScale'].value = v; + this.viewQuad.quadShader.setUniform('fogHeightScale', v); } public get fogHeightScale() { - return this.viewQuad.uniforms['fogHeightScale'].value; + return this.viewQuad.quadShader.getUniform('fogHeightScale'); } public set start(v: number) { this._globalFog.start = v; - this.viewQuad.uniforms['start'].value = v; + this.viewQuad.quadShader.setUniform('start', v); } public get start() { - return this.viewQuad.uniforms['start'].value; + return this.viewQuad.quadShader.getUniform('start'); } public set end(v: number) { this._globalFog.end = v; - this.viewQuad.uniforms['end'].value = v; + this.viewQuad.quadShader.setUniform('end', v); } public get end() { - return this.viewQuad.uniforms['end'].value; + return this.viewQuad.quadShader.getUniform('end'); } public set ins(v: number) { this._globalFog.ins = v; - this.viewQuad.uniforms['ins'].value = v; + this.viewQuad.quadShader.setUniform('ins', v); } public get ins() { - return this.viewQuad.uniforms['ins'].value; + return this.viewQuad.quadShader.getUniform('ins'); } public set density(v: number) { this._globalFog.density = v; - this.viewQuad.uniforms['density'].value = v; + this.viewQuad.quadShader.setUniform('density', v); } public get density() { - return this.viewQuad.uniforms['density'].value; + return this.viewQuad.quadShader.getUniform('density'); } public set skyRoughness(v: number) { this._globalFog.skyRoughness = v; - this.viewQuad.uniforms['skyRoughness'].value = v; + this.viewQuad.quadShader.setUniform('skyRoughness', v); } public get skyRoughness() { return this._globalFog.skyRoughness; } public set skyFactor(v: number) { this._globalFog.skyFactor = v; - this.viewQuad.uniforms['skyFactor'].value = v; + this.viewQuad.quadShader.setUniform('skyFactor', v); } public get skyFactor() { return this._globalFog.skyFactor; @@ -136,7 +139,7 @@ export class GlobalFog extends PostBase { public set overrideSkyFactor(v: number) { this._globalFog.overrideSkyFactor = v; - this.viewQuad.uniforms['overrideSkyFactor'].value = v; + this.viewQuad.quadShader.setUniform('overrideSkyFactor', v); } public get overrideSkyFactor() { return this._globalFog.overrideSkyFactor; @@ -154,22 +157,21 @@ export class GlobalFog extends PostBase { */ public set fogColor(value: Color) { this._globalFog.fogColor.copyFrom(value); - this.viewQuad.uniforms['fogColor'].color = value; - this.viewQuad.uniforms['fogColor'].onChange(); + this.viewQuad.quadShader.setUniformColor('fogColor', value); } public set falloff(v: number) { this._globalFog.falloff = v; - this.viewQuad.uniforms['falloff'].value = v; + this.viewQuad.quadShader.setUniform('falloff', v); } public get falloff() { - return this.viewQuad.uniforms['falloff'].value; + return this.viewQuad.quadShader.getUniform('falloff'); } public set rayLength(v: number) { this._globalFog.rayLength = v; - this.viewQuad.uniforms['rayLength'].value = v; + this.viewQuad.quadShader.setUniform('rayLength', v); } public get rayLength() { @@ -178,7 +180,7 @@ export class GlobalFog extends PostBase { public set scatteringExponent(v: number) { this._globalFog.scatteringExponent = v; - this.viewQuad.uniforms['scatteringExponent'].value = v; + this.viewQuad.quadShader.setUniform('scatteringExponent', v); } public get scatteringExponent() { @@ -187,7 +189,7 @@ export class GlobalFog extends PostBase { public set dirHeightLine(v: number) { this._globalFog.dirHeightLine = v; - this.viewQuad.uniforms['dirHeightLine'].value = v; + this.viewQuad.quadShader.setUniform('dirHeightLine', v); } public get dirHeightLine() { @@ -198,7 +200,7 @@ export class GlobalFog extends PostBase { * @internal */ public setInputTexture(positionMap: VirtualTexture, normalMap: VirtualTexture) { - const pass = this.viewQuad.pass; + const pass = this.viewQuad.quadShader; pass.setTexture('positionMap', positionMap); pass.setTexture('normalMap', normalMap); this._lastSkyTexture = this.getSkyTexture(); @@ -217,7 +219,7 @@ export class GlobalFog extends PostBase { * @internal */ render(view: View3D, command: GPUCommandEncoder) { - const pass = this.viewQuad.pass; + const pass = this.viewQuad.quadShader; let skyTexture = this.getSkyTexture(); if (skyTexture != this._lastSkyTexture) { this._lastSkyTexture = skyTexture; diff --git a/src/gfx/renderJob/post/GodRayPost.ts b/src/gfx/renderJob/post/GodRayPost.ts index 7c3b1f4d..e59cadab 100644 --- a/src/gfx/renderJob/post/GodRayPost.ts +++ b/src/gfx/renderJob/post/GodRayPost.ts @@ -87,8 +87,8 @@ export class GodRayPost extends PostBase { let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); - this.godRayCompute.setSamplerTexture(`posTex`, rtFrame.attachments[1]); - this.godRayCompute.setSamplerTexture(`normalTex`, rtFrame.attachments[2]); + this.godRayCompute.setSamplerTexture(`posTex`, rtFrame.renderTargets[1]); + this.godRayCompute.setSamplerTexture(`normalTex`, rtFrame.renderTargets[2]); this.autoSetColorTexture('inTex', this.godRayCompute); this.godRayCompute.setStorageTexture(`outTex`, this.godRayTexture); diff --git a/src/gfx/renderJob/post/HDRBloomPost.ts b/src/gfx/renderJob/post/HDRBloomPost.ts deleted file mode 100644 index f2762783..00000000 --- a/src/gfx/renderJob/post/HDRBloomPost.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { ViewQuad } from '../../../core/ViewQuad'; -import { Engine3D } from '../../../Engine3D'; -import { Vector2 } from '../../../math/Vector2'; -import { UniformNode } from '../../graphics/webGpu/core/uniforms/UniformNode'; -import { GPUTextureFormat } from '../../graphics/webGpu/WebGPUConst'; -import { webGPUContext } from '../../graphics/webGpu/Context3D'; -import { GPUContext } from '../GPUContext'; -import { RTResourceConfig } from '../config/RTResourceConfig'; -import { RTResourceMap } from '../frame/RTResourceMap'; -import { PostBase } from './PostBase'; -import { View3D } from '../../../core/View3D'; -import { Color, RendererType } from '../../..'; -/** - * HDR Bloom effect - * ``` - * @group Post Effects - */ -export class HDRBloomPost extends PostBase { - private brightnessView: ViewQuad; - private compositeView: ViewQuad; - private blurList: { ql: ViewQuad; qr: ViewQuad }[]; - /** - * @internal - */ - public blurX: number = 1; - /** - * @internal - */ - public blurY: number = 1; - constructor() { - super(); - const bloomSetting = Engine3D.setting.render.postProcessing.bloom; - - bloomSetting.enable = true; - - let presentationSize = webGPUContext.presentationSize; - let outTextures = this.createRTTexture('HDRBloomPost-outTextures', presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); - RTResourceMap.createRTTexture(RTResourceConfig.colorBufferTex_NAME, presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); - - { - let brightnessTextures = this.createRTTexture('brightnessTextures', presentationSize[0], presentationSize[1], GPUTextureFormat.rgba16float, false); - - this.brightnessView = this.createViewQuad(`brightnessView`, `Bloom_Brightness_frag_wgsl`, brightnessTextures, { - luminosityThreshold: new UniformNode(bloomSetting.luminosityThreshold), - }); - } - - let blurMip = 5; - let sizeW = presentationSize[0]; - let sizeH = presentationSize[1]; - this.blurList = []; - for (let i = 0; i < blurMip; i++) { - let tex_l = this.createRTTexture(`tex_l${i}`, sizeW, sizeH, GPUTextureFormat.rgba16float); - let tex_r = this.createRTTexture(`tex_r${i}`, sizeW, sizeH, GPUTextureFormat.rgba16float); - - let ql = this.createViewQuad(`ql${i}`, `Bloom_blur_frag_wgsl`, tex_l, { - texSize: new UniformNode(new Vector2(sizeW * 2, sizeH * 2)), - hScale: new UniformNode(i), - vScale: new UniformNode(i), - horizontal: new UniformNode(0.5), - }); - - let qr = this.createViewQuad(`qr${i}`, `Bloom_blur_frag_wgsl`, tex_r, { - texSize: new UniformNode(new Vector2(sizeW * 2, sizeH * 2)), - hScale: new UniformNode(i), - vScale: new UniformNode(i), - horizontal: new UniformNode(1.0), - }); - - this.blurList.push({ - ql: ql, - qr: qr, - }); - - sizeW /= 2; - sizeH /= 2; - } - - { - this.compositeView = this.createViewQuad(`compositeView`, `Bloom_composite_frag_wgsl`, outTextures, { - tintColor: new UniformNode(new Color(1, 1, 1)), - bloomStrength: new UniformNode(bloomSetting.strength), - exposure: new UniformNode(bloomSetting.exposure), - bloomRadius: new UniformNode(1), - }); - } - - this.blurX = bloomSetting.blurX; - this.blurY = bloomSetting.blurY; - this.luminosityThreshold = bloomSetting.luminosityThreshold; - this.strength = bloomSetting.strength; - this.radius = bloomSetting.radius; - } - - onAttach(view: View3D): void { - this.debug(); - } - - onDetach(view: View3D): void { - } - - public debug() { - } - - public get tintColor(): Color { - return this.compositeView.uniforms['tintColor'].color; - } - - public set tintColor(color: Color) { - this.compositeView.uniforms['tintColor'].color = color; - } - - public get strength() { - return this.compositeView.uniforms['bloomStrength'].value; - } - - public set strength(value: number) { - this.compositeView.uniforms['bloomStrength'].value = value; - } - - public get exposure() { - return this.compositeView.uniforms['exposure'].value; - } - - public set exposure(value: number) { - this.compositeView.uniforms['exposure'].value = value; - } - - - public get radius() { - return this.compositeView.uniforms['bloomRadius'].value; - } - - public set radius(value: number) { - this.compositeView.uniforms['bloomRadius'].value = value; - } - - public get luminosityThreshold(): number { - return this.brightnessView.uniforms['luminosityThreshold'].value; - } - - public set luminosityThreshold(value: number) { - this.brightnessView.uniforms['luminosityThreshold'].value = value; - } - - /** - * @internal - */ - render(view: View3D, command: GPUCommandEncoder) { - // let command = GPUContext.beginCommandEncoder(); - { - let colorTexture = this.getOutTexture(); - { - this.brightnessView.renderToViewQuad(view, this.brightnessView, command, colorTexture); - } - { - let tex = this.brightnessView.rendererPassState.renderTargets[0]; - for (let i = 0; i < this.blurList.length; i++) { - let ql = this.blurList[i].ql; - let qr = this.blurList[i].qr; - - ql.pass.setUniformFloat(`horizontal`, 0.5); - ql.pass.setUniformFloat(`vScale`, i * this.blurX); - - ql.renderToViewQuad(view, ql, command, tex); - tex = ql.rendererPassState.renderTargets[0]; - - qr.pass.setUniformFloat(`horizontal`, 2.0); - qr.pass.setUniformFloat(`hScale`, i * this.blurY); - - qr.renderToViewQuad(view, qr, command, tex); - tex = qr.rendererPassState.renderTargets[0]; - } - } - - { - let pass = this.compositeView.pass; - pass.setTexture(`blurTex1`, this.blurList[0].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex2`, this.blurList[1].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex3`, this.blurList[2].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex4`, this.blurList[3].qr.rendererPassState.renderTargets[0]); - pass.setTexture(`blurTex5`, this.blurList[4].qr.rendererPassState.renderTargets[0]); - - this.compositeView.renderToViewQuad(view, this.compositeView, command, colorTexture); - } - } - // GPUContext.endCommandEncoder(command); - } -} diff --git a/src/gfx/renderJob/post/PostBase.ts b/src/gfx/renderJob/post/PostBase.ts index 10e151f3..7c1b9cba 100644 --- a/src/gfx/renderJob/post/PostBase.ts +++ b/src/gfx/renderJob/post/PostBase.ts @@ -1,4 +1,3 @@ -import { Scene3D } from '../../../core/Scene3D'; import { ViewQuad } from '../../../core/ViewQuad'; import { VirtualTexture } from '../../../textures/VirtualTexture'; import { Texture } from '../../graphics/webGpu/core/texture/Texture'; @@ -34,8 +33,8 @@ export class PostBase { return rt; } - protected createViewQuad(name: string, shaderName: string, outRtTexture: VirtualTexture, shaderUniforms?: { [uniName: string]: UniformNode }, msaa: number = 0) { - let viewQuad = RTResourceMap.createViewQuad(name, 'Quad_vert_wgsl', shaderName, outRtTexture, shaderUniforms, msaa); + protected createViewQuad(name: string, shaderName: string, outRtTexture: VirtualTexture, msaa: number = 0) { + let viewQuad = RTResourceMap.createViewQuad(name, 'Quad_vert_wgsl', shaderName, outRtTexture, msaa); this.rtViewQuad.set(name, viewQuad); return viewQuad; } diff --git a/src/gfx/renderJob/post/SSRPost.ts b/src/gfx/renderJob/post/SSRPost.ts index 5fedce16..2746ccdb 100644 --- a/src/gfx/renderJob/post/SSRPost.ts +++ b/src/gfx/renderJob/post/SSRPost.ts @@ -169,8 +169,8 @@ export class SSRPost extends PostBase { let rtFrame = GBufferFrame.getGBufferFrame("ColorPassGBuffer"); this.SSR_RayTraceCompute.setSamplerTexture("zBufferTexture", rtFrame.getPositionMap()); - this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.attachments[2]); - this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.materialBufferTex_NAME, rtFrame.attachments[3]); + this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.normalBufferTex_NAME, rtFrame.renderTargets[2]); + this.SSR_RayTraceCompute.setSamplerTexture(RTResourceConfig.materialBufferTex_NAME, rtFrame.renderTargets[3]); if (EntityCollect.instance.sky instanceof SkyRenderer) this.SSR_RayTraceCompute.setSamplerTexture(`prefilterMap`, EntityCollect.instance.sky.map); diff --git a/src/index.ts b/src/index.ts index 845da1b6..70fff56e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,8 @@ export * from "./assets/shader/anim/SkeletonAnimation_shader" export * from "./assets/shader/cluster/ClusterBoundsSource_cs" export * from "./assets/shader/cluster/ClusterLighting_cs" export * from "./assets/shader/compute/BLUR_CsShader" +export * from "./assets/shader/compute/BRDFLUT" +export * from "./assets/shader/compute/BloomEffect_cs" export * from "./assets/shader/compute/BlurEffectCreator_cs" export * from "./assets/shader/compute/DDGIIrradiance_Cs" export * from "./assets/shader/compute/DDGILighting_CSShader" @@ -21,6 +23,7 @@ export * from "./assets/shader/compute/OutLineBlendColor_cs" export * from "./assets/shader/compute/OutlineCalcOutline_cs" export * from "./assets/shader/compute/Outline_cs" export * from "./assets/shader/compute/Picker_cs" +export * from "./assets/shader/compute/PreIntegratedLut" export * from "./assets/shader/compute/SSAO_cs" export * from "./assets/shader/compute/SSR_BlendColor_cs" export * from "./assets/shader/compute/SSR_IS_cs" @@ -47,6 +50,7 @@ export * from "./assets/shader/core/struct/ClusterLight" export * from "./assets/shader/core/struct/ColorPassFragmentOutput" export * from "./assets/shader/core/struct/FragmentVarying" export * from "./assets/shader/core/struct/ShadingInput" +export * from "./assets/shader/core/struct/VertexAttributeIndexShader" export * from "./assets/shader/core/struct/VertexAttributes" export * from "./assets/shader/glsl/Quad_glsl" export * from "./assets/shader/glsl/Sky_glsl" @@ -54,7 +58,9 @@ export * from "./assets/shader/glsl/post/LUT_glsl" export * from "./assets/shader/graphic/Graphic3DShader_fs" export * from "./assets/shader/graphic/Graphic3DShader_vs" export * from "./assets/shader/lighting/BRDF_frag" +export * from "./assets/shader/lighting/BsDF_frag" export * from "./assets/shader/lighting/BxDF_frag" +export * from "./assets/shader/lighting/Hair_frag" export * from "./assets/shader/lighting/IESProfiles_frag" export * from "./assets/shader/lighting/IrradianceVolumeData_frag" export * from "./assets/shader/lighting/Irradiance_frag" @@ -63,13 +69,16 @@ export * from "./assets/shader/lighting/UnLit_frag" export * from "./assets/shader/materials/ColorLitShader" export * from "./assets/shader/materials/GIProbeShader" export * from "./assets/shader/materials/GlassShader" -export * from "./assets/shader/materials/LambertShader" -export * from "./assets/shader/materials/LitShader" +export * from "./assets/shader/materials/Hair_shader" +export * from "./assets/shader/materials/Lambert_shader" +export * from "./assets/shader/materials/Lit_shader" export * from "./assets/shader/materials/OutlinePass" export * from "./assets/shader/materials/PBRLItShader" +export * from "./assets/shader/materials/PBRLitSSSShader" export * from "./assets/shader/materials/PavementShader" export * from "./assets/shader/materials/PointShadowDebug" export * from "./assets/shader/materials/UnLit" +export * from "./assets/shader/materials/UnLitTextureArray" export * from "./assets/shader/materials/program/BxdfDebug_frag" export * from "./assets/shader/materials/program/Clearcoat_frag" export * from "./assets/shader/materials/program/ClusterDebug_frag" @@ -82,13 +91,11 @@ export * from "./assets/shader/materials/uniforms/VideoUniform_frag" export * from "./assets/shader/math/FastMathShader" export * from "./assets/shader/math/MathShader" export * from "./assets/shader/math/MatrixShader" -export * from "./assets/shader/post/Bloom_shader" export * from "./assets/shader/post/FXAAShader" export * from "./assets/shader/post/GlobalFog_shader" export * from "./assets/shader/quad/Quad_shader" export * from "./assets/shader/sky/AtmosphericScatteringSky_shader" export * from "./assets/shader/sky/CubeSky_Shader" -export * from "./assets/shader/utils/BRDFLUT" export * from "./assets/shader/utils/ColorUtil" export * from "./assets/shader/utils/GenerayRandomDir" export * from "./components/AtmosphericComponent" @@ -98,6 +105,7 @@ export * from "./components/ComponentBase" export * from "./components/IComponent" export * from "./components/SkeletonAnimationComponent" export * from "./components/Transform" +export * from "./components/anim/AnimatorComponent" export * from "./components/anim/OAnimationEvent" export * from "./components/anim/curveAnim/AnimationMonitor" export * from "./components/anim/curveAnim/AttributeAnimCurve" @@ -160,6 +168,7 @@ export * from "./components/lights/DirectLight" export * from "./components/lights/GILighting" export * from "./components/lights/IESProfiles" export * from "./components/lights/ILight" +export * from "./components/lights/Light" export * from "./components/lights/LightBase" export * from "./components/lights/LightData" export * from "./components/lights/PointLight" @@ -167,9 +176,11 @@ export * from "./components/lights/SpotLight" export * from "./components/post/PostProcessingComponent" export * from "./components/renderer/GlobalIlluminationComponent" export * from "./components/renderer/InstanceDrawComponent" +export * from "./components/renderer/MeshFilter" export * from "./components/renderer/MeshRenderer" export * from "./components/renderer/RenderNode" export * from "./components/renderer/SkinnedMeshRenderer" +export * from "./components/renderer/SkinnedMeshRenderer2" export * from "./components/renderer/SkyRenderer" export * from "./components/shape/BoxColliderShape" export * from "./components/shape/CapsuleColliderShape" @@ -213,6 +224,11 @@ export * from "./core/tree/kdTree/KDTreeNode" export * from "./core/tree/kdTree/KDTreeSpace" export * from "./core/tree/octree/Octree" export * from "./core/tree/octree/OctreeEntity" +export * from "./core/tree/quad/IQuadNode" +export * from "./core/tree/quad/QuadAABB" +export * from "./core/tree/quad/QuadRoot" +export * from "./core/tree/quad/QuadTree" +export * from "./core/tree/quad/QuadTreeCell" export * from "./event/CEvent" export * from "./event/CEventDispatcher" export * from "./event/CEventListener" @@ -236,6 +252,8 @@ export * from "./gfx/graphics/webGpu/CanvasConfig" export * from "./gfx/graphics/webGpu/Context3D" export * from "./gfx/graphics/webGpu/PipelinePool" export * from "./gfx/graphics/webGpu/WebGPUConst" +export * from "./gfx/graphics/webGpu/compute/PreIntegratedLutCompute" +export * from "./gfx/graphics/webGpu/compute/RenderShaderCompute" export * from "./gfx/graphics/webGpu/core/bindGroups/GlobalBindGroup" export * from "./gfx/graphics/webGpu/core/bindGroups/GlobalBindGroupLayout" export * from "./gfx/graphics/webGpu/core/bindGroups/GlobalUniformGroup" @@ -262,8 +280,9 @@ export * from "./gfx/graphics/webGpu/core/uniforms/UniformNode" export * from "./gfx/graphics/webGpu/descriptor/RTDescriptor" export * from "./gfx/graphics/webGpu/descriptor/WebGPUDescriptorCreator" export * from "./gfx/graphics/webGpu/shader/ComputeShader" -export * from "./gfx/graphics/webGpu/shader/RenderShader" -export * from "./gfx/graphics/webGpu/shader/ShaderBase" +export * from "./gfx/graphics/webGpu/shader/RenderShaderPass" +export * from "./gfx/graphics/webGpu/shader/Shader" +export * from "./gfx/graphics/webGpu/shader/ShaderPassBase" export * from "./gfx/graphics/webGpu/shader/ShaderStage" export * from "./gfx/graphics/webGpu/shader/converter/GLSLLexer" export * from "./gfx/graphics/webGpu/shader/converter/GLSLLexerToken" @@ -320,6 +339,8 @@ export * from "./gfx/renderJob/passRenderer/graphic/Graphic3DLineBatchRenderer" export * from "./gfx/renderJob/passRenderer/graphic/Graphic3DRender" export * from "./gfx/renderJob/passRenderer/graphic/GraphicConfig" export * from "./gfx/renderJob/passRenderer/graphic/Graphics3DShape" +export * from "./gfx/renderJob/passRenderer/graphic/new/Graphic3DMesh" +export * from "./gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer" export * from "./gfx/renderJob/passRenderer/post/PostRenderer" export * from "./gfx/renderJob/passRenderer/preDepth/PreDepthPassRenderer" export * from "./gfx/renderJob/passRenderer/preDepth/ZCullingCompute" @@ -328,12 +349,12 @@ export * from "./gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer" export * from "./gfx/renderJob/passRenderer/state/RendererMask" export * from "./gfx/renderJob/passRenderer/state/RendererPassState" export * from "./gfx/renderJob/passRenderer/state/RendererType" +export * from "./gfx/renderJob/post/BloomPost" export * from "./gfx/renderJob/post/DepthOfFieldPost" export * from "./gfx/renderJob/post/FXAAPost" export * from "./gfx/renderJob/post/GTAOPost" export * from "./gfx/renderJob/post/GlobalFog" export * from "./gfx/renderJob/post/GodRayPost" -export * from "./gfx/renderJob/post/HDRBloomPost" export * from "./gfx/renderJob/post/OutlinePost" export * from "./gfx/renderJob/post/PostBase" export * from "./gfx/renderJob/post/SSRPost" @@ -356,6 +377,7 @@ export * from "./loader/parser/FontParser" export * from "./loader/parser/I3DMParser" export * from "./loader/parser/OBJParser" export * from "./loader/parser/ParserBase" +export * from "./loader/parser/ParserFormat" export * from "./loader/parser/RGBEParser" export * from "./loader/parser/b3dm/B3DMLoader" export * from "./loader/parser/b3dm/B3DMLoaderBase" @@ -390,6 +412,33 @@ export * from "./loader/parser/gltf/extends/KHR_texture_basisu" export * from "./loader/parser/gltf/extends/KHR_texture_transform" export * from "./loader/parser/i3dm/I3DMLoader" export * from "./loader/parser/i3dm/I3DMLoaderBase" +export * from "./loader/parser/prefab/PrefabAvatarParser" +export * from "./loader/parser/prefab/PrefabMaterialParser" +export * from "./loader/parser/prefab/PrefabMeshParser" +export * from "./loader/parser/prefab/PrefabParser" +export * from "./loader/parser/prefab/PrefabStringUtil" +export * from "./loader/parser/prefab/PrefabTextureParser" +export * from "./loader/parser/prefab/mats/MaterialUtilities" +export * from "./loader/parser/prefab/mats/shader/LitHairShader" +export * from "./loader/parser/prefab/mats/shader/LitSSSShader" +export * from "./loader/parser/prefab/mats/shader/LitShader" +export * from "./loader/parser/prefab/mats/shader/QuadShader" +export * from "./loader/parser/prefab/mats/shader/SkyShader" +export * from "./loader/parser/prefab/mats/shader/StandShader" +export * from "./loader/parser/prefab/mats/shader/UnLitShader" +export * from "./loader/parser/prefab/mats/shader/UnLitTexArrayShader" +export * from "./loader/parser/prefab/prefabData/APatch" +export * from "./loader/parser/prefab/prefabData/BlendShapeData" +export * from "./loader/parser/prefab/prefabData/BlendShapeFrameData" +export * from "./loader/parser/prefab/prefabData/BlendShapePropertyData" +export * from "./loader/parser/prefab/prefabData/KVData" +export * from "./loader/parser/prefab/prefabData/PrefabAvatarData" +export * from "./loader/parser/prefab/prefabData/PrefabBoneData" +export * from "./loader/parser/prefab/prefabData/PrefabMeshData" +export * from "./loader/parser/prefab/prefabData/PrefabNode" +export * from "./loader/parser/prefab/prefabData/PrefabTextureData" +export * from "./loader/parser/prefab/prefabData/ValueParser" +export * from "./loader/parser/prefab/prefabData/ValueType" export * from "./loader/parser/tileRenderer/TileSet" export * from "./loader/parser/tileRenderer/TilesRenderer" export * from "./materials/BlendMode" @@ -401,17 +450,20 @@ export * from "./materials/LitMaterial" export * from "./materials/Material" export * from "./materials/MaterialRegister" export * from "./materials/PhysicMaterial" -export * from "./materials/PointMaterial" export * from "./materials/SkyMaterial" export * from "./materials/UnLitMaterial" +export * from "./materials/UnLitTexArrayMaterial" export * from "./materials/multiPass/CastPointShadowMaterialPass" export * from "./materials/multiPass/CastShadowMaterialPass" export * from "./materials/multiPass/DepthMaterialPass" export * from "./materials/multiPass/GBufferPass" export * from "./materials/multiPass/SkyGBufferPass" export * from "./math/AnimationCurve" +export * from "./math/AnimationCurveClip" +export * from "./math/AnimationCurveT" export * from "./math/Bezier2D" export * from "./math/Bezier3D" +export * from "./math/BiMap" export * from "./math/Color" export * from "./math/CubicBezierCurve" export * from "./math/CubicBezierPath" @@ -420,10 +472,13 @@ export * from "./math/Line" export * from "./math/MathUtil" export * from "./math/Matrix3" export * from "./math/Matrix4" +export * from "./math/OrderMap" export * from "./math/Orientation3D" export * from "./math/ParticleMath" export * from "./math/ParticleSystemCurves" export * from "./math/Plane" +export * from "./math/Plane3D" +export * from "./math/PlaneClassification" export * from "./math/PolynomialCurve" export * from "./math/Polynomials" export * from "./math/Quaternion" @@ -437,9 +492,28 @@ export * from "./math/UV" export * from "./math/Vector2" export * from "./math/Vector3" export * from "./math/Vector4" +export * from "./math/enum/FrameCache" +export * from "./math/enum/Keyframe" +export * from "./math/enum/T/KeyframeT" +export * from "./math/enum/T/ValueOp" +export * from "./math/enum/WrapTimeMode" +export * from "./math/navigation/DoubleArray" +export * from "./math/navigation/Navi3DAstar" +export * from "./math/navigation/Navi3DConst" +export * from "./math/navigation/Navi3DEdge" +export * from "./math/navigation/Navi3DFunnel" +export * from "./math/navigation/Navi3DMaskType" +export * from "./math/navigation/Navi3DMergeVertex" +export * from "./math/navigation/Navi3DMesh" +export * from "./math/navigation/Navi3DPoint" +export * from "./math/navigation/Navi3DPoint2D" +export * from "./math/navigation/Navi3DPointFat" +export * from "./math/navigation/Navi3DRouter" +export * from "./math/navigation/Navi3DTriangle" export * from "./setting/EngineSetting" export * from "./setting/GlobalIlluminationSetting" export * from "./setting/LightSetting" +export * from "./setting/LoaderSetting" export * from "./setting/MaterialSetting" export * from "./setting/OcclusionQuerySetting" export * from "./setting/PickSetting" @@ -457,6 +531,7 @@ export * from "./shape/BoxGeometry" export * from "./shape/CylinderGeometry" export * from "./shape/PlaneGeometry" export * from "./shape/SphereGeometry" +export * from "./shape/StripeGeometry" export * from "./shape/TorusGeometry" export * from "./textures/AtmosphericScatteringSky" export * from "./textures/BitmapTexture2D" @@ -470,6 +545,7 @@ export * from "./textures/Float32ArrayTexture" export * from "./textures/HDRTexture" export * from "./textures/HDRTextureCube" export * from "./textures/LDRTextureCube" +export * from "./textures/ShadowTexture" export * from "./textures/SolidColorSky" export * from "./textures/TextureCubeFaceData" export * from "./textures/Uint16Texture" @@ -477,7 +553,7 @@ export * from "./textures/Uint8ArrayTexture" export * from "./textures/VirtualTexture" export * from "./util/AxisObject" export * from "./util/BoundUtil" -export * from "./util/BytesStream" +export * from "./util/BytesArray" export * from "./util/CameraUtil" export * from "./util/Convert" export * from "./util/GeometryUtil" @@ -487,6 +563,7 @@ export * from "./util/Object3DUtil" export * from "./util/ProfilerUtil" export * from "./util/Reference" export * from "./util/SerializeDecoration" +export * from "./util/StorageUtil" export * from "./util/StringUtil" export * from "./util/Time" export * from "./util/Vector3Ex" diff --git a/src/loader/FileLoader.ts b/src/loader/FileLoader.ts index c5609b47..52157c9e 100644 --- a/src/loader/FileLoader.ts +++ b/src/loader/FileLoader.ts @@ -1,7 +1,8 @@ import { LoaderBase } from './LoaderBase'; import { LoaderFunctions } from './LoaderFunctions'; import { ParserBase } from './parser/ParserBase'; -import { Ctor } from "../util/Global"; +import { Ctor, Parser } from "../util/Global"; +import { ParserFormat } from './parser/ParserFormat'; /** * @internal @@ -16,9 +17,9 @@ export class FileLoader extends LoaderBase { * @see LoaderFunctions * @returns */ - public async load(url: string, c: Ctor, loaderFunctions?: LoaderFunctions, userData?: any): Promise { - switch (c[`format`]) { - case `bin`: + public async load(url: string, c: Parser, loaderFunctions?: LoaderFunctions, userData?: any): Promise { + switch (c.format) { + case ParserFormat.BIN: { return new Promise(async (succ, fail) => { this.loadBinData(url, loaderFunctions).then(async (data) => { @@ -37,8 +38,7 @@ export class FileLoader extends LoaderBase { }) }); } - break; - case `json`: + case ParserFormat.JSON: { return new Promise((succ, fail) => { this.loadJson(url, loaderFunctions) @@ -56,8 +56,7 @@ export class FileLoader extends LoaderBase { }); }); } - break; - case `text`: + case ParserFormat.TEXT: { return new Promise((succ, fail) => { this.loadTxt(url, loaderFunctions) @@ -79,7 +78,6 @@ export class FileLoader extends LoaderBase { }); }); } - break; default: break; } diff --git a/src/loader/parser/AtlasParser.ts b/src/loader/parser/AtlasParser.ts index e5da83db..606609ba 100644 --- a/src/loader/parser/AtlasParser.ts +++ b/src/loader/parser/AtlasParser.ts @@ -3,9 +3,10 @@ import { GUITexture } from "../../components/gui/core/GUITexture"; import { Engine3D } from "../../Engine3D"; import { Texture } from "../../gfx/graphics/webGpu/core/texture/Texture"; import { ParserBase } from "../../loader/parser/ParserBase"; +import { ParserFormat } from "./ParserFormat"; export class AtlasParser extends ParserBase { - static format: string = 'text'; + static format: ParserFormat = ParserFormat.TEXT; private _json: any; private _texture: Texture; diff --git a/src/loader/parser/B3DMParser.ts b/src/loader/parser/B3DMParser.ts index 2a23e9db..77eacf90 100644 --- a/src/loader/parser/B3DMParser.ts +++ b/src/loader/parser/B3DMParser.ts @@ -1,8 +1,9 @@ import { Object3D } from '../../core/entities/Object3D'; import { ParserBase } from './ParserBase'; +import { ParserFormat } from './ParserFormat'; export class B3DMParser extends ParserBase { - static format: string = 'bin'; + static format: ParserFormat = ParserFormat.JSON; public async parseBuffer(buffer: ArrayBuffer) { let loader = new B3DMLoader(); diff --git a/src/loader/parser/FontParser.ts b/src/loader/parser/FontParser.ts index 80d18038..7a99d448 100644 --- a/src/loader/parser/FontParser.ts +++ b/src/loader/parser/FontParser.ts @@ -3,6 +3,7 @@ import { fonts } from "../../assets/Fonts"; import { GUISprite } from "../../components/gui/core/GUISprite"; import { GUITexture } from "../../components/gui/core/GUITexture"; import { ParserBase } from "./ParserBase"; +import { ParserFormat } from "./ParserFormat"; export class FontInfo { public face: string = ''; @@ -49,7 +50,7 @@ export class FontChar { } export class FontParser extends ParserBase { - static format: string = 'text'; + static format: ParserFormat = ParserFormat.TEXT; public static parseSprite(guiTexture: GUITexture[], fontData: FontInfo) { for (const key in fontData.fontChar) { diff --git a/src/loader/parser/I3DMParser.ts b/src/loader/parser/I3DMParser.ts index f1b402a8..15efafd4 100644 --- a/src/loader/parser/I3DMParser.ts +++ b/src/loader/parser/I3DMParser.ts @@ -1,9 +1,9 @@ import { ParserBase } from './ParserBase'; +import { ParserFormat } from './ParserFormat'; import { I3DMLoader } from "./i3dm/I3DMLoader"; export class I3DMParser extends ParserBase { - static format: string = 'bin'; - + static format: ParserFormat = ParserFormat.BIN; async parseBuffer(buffer: ArrayBuffer) { let loader = new I3DMLoader(); loader.adjustmentTransform = this.userData; diff --git a/src/loader/parser/OBJParser.ts b/src/loader/parser/OBJParser.ts index 3bed3534..6661f108 100644 --- a/src/loader/parser/OBJParser.ts +++ b/src/loader/parser/OBJParser.ts @@ -7,6 +7,7 @@ import { LitMaterial } from '../../materials/LitMaterial'; import { StringUtil } from '../../util/StringUtil'; import { FileLoader } from '../FileLoader'; import { ParserBase } from './ParserBase'; +import { ParserFormat } from './ParserFormat'; type MatData = { @@ -54,7 +55,7 @@ type Face = { * @group Loader */ export class OBJParser extends ParserBase { - static format: string = 'text'; + static format: ParserFormat = ParserFormat.TEXT; private textData: string = ''; private source_vertices: number[][]; @@ -346,7 +347,10 @@ export class OBJParser extends ParserBase { indexStart: 0, indexCount: geoData.indeice_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); let mat = new LitMaterial(); diff --git a/src/loader/parser/ParserBase.ts b/src/loader/parser/ParserBase.ts index 052abaca..63be235b 100644 --- a/src/loader/parser/ParserBase.ts +++ b/src/loader/parser/ParserBase.ts @@ -1,12 +1,13 @@ import { Texture } from '../../gfx/graphics/webGpu/core/texture/Texture'; import { LoaderFunctions } from '../LoaderFunctions'; +import { ParserFormat } from './ParserFormat'; /** * @internal * @group Loader */ export class ParserBase { - static format: string = 'bin'; + static format: ParserFormat = ParserFormat.BIN; public baseUrl: string; public initUrl: string; public loaderFunctions?: LoaderFunctions; diff --git a/src/loader/parser/ParserFormat.ts b/src/loader/parser/ParserFormat.ts new file mode 100644 index 00000000..ba34b29f --- /dev/null +++ b/src/loader/parser/ParserFormat.ts @@ -0,0 +1,5 @@ +export enum ParserFormat { + TEXT, + BIN, + JSON +} \ No newline at end of file diff --git a/src/loader/parser/RGBEParser.ts b/src/loader/parser/RGBEParser.ts index 36c64e6b..b1fed387 100644 --- a/src/loader/parser/RGBEParser.ts +++ b/src/loader/parser/RGBEParser.ts @@ -38,7 +38,7 @@ export class RGBEHeader { * @group Loader */ export class RGBEParser extends ParserBase { - static format: string = 'bin'; + // static format: string = 'bin'; private _rgbeArray: Uint8Array; private _width: number; private _height: number; diff --git a/src/loader/parser/gltf/GLBParser.ts b/src/loader/parser/gltf/GLBParser.ts index 0608b965..b5814a27 100644 --- a/src/loader/parser/gltf/GLBParser.ts +++ b/src/loader/parser/gltf/GLBParser.ts @@ -1,5 +1,6 @@ import { BitmapTexture2D } from '../../../textures/BitmapTexture2D'; import { ParserBase } from '../ParserBase'; +import { ParserFormat } from '../ParserFormat'; import { GLTF_Info } from './GLTFInfo'; import { GLTFSubParser } from './GLTFSubParser'; @@ -29,7 +30,7 @@ export class GLBChunk { * @group Loader */ export class GLBParser extends ParserBase { - static format: string = 'bin'; + static format: ParserFormat = ParserFormat.BIN; private _gltf: GLTF_Info; diff --git a/src/loader/parser/gltf/GLTFParser.ts b/src/loader/parser/gltf/GLTFParser.ts index 73c34281..5a66d884 100644 --- a/src/loader/parser/gltf/GLTFParser.ts +++ b/src/loader/parser/gltf/GLTFParser.ts @@ -1,6 +1,7 @@ import { StringUtil } from '../../../util/StringUtil'; import { FileLoader } from '../../FileLoader'; import { ParserBase } from '../ParserBase'; +import { ParserFormat } from '../ParserFormat'; import { GLTF_Info } from './GLTFInfo'; import { GLTFSubParser } from './GLTFSubParser'; @@ -10,7 +11,7 @@ import { GLTFSubParser } from './GLTFSubParser'; * @group Loader */ export class GLTFParser extends ParserBase { - static format: string = 'json'; + static format: ParserFormat = ParserFormat.JSON; private _gltf: GLTF_Info; public async parseJson(obj: object) { diff --git a/src/loader/parser/gltf/GLTFSubParserConverter.ts b/src/loader/parser/gltf/GLTFSubParserConverter.ts index 24a3d408..07d95f5b 100644 --- a/src/loader/parser/gltf/GLTFSubParserConverter.ts +++ b/src/loader/parser/gltf/GLTFSubParserConverter.ts @@ -177,73 +177,59 @@ export class GLTFSubParserConverter { if (primitive.material) { const { baseColorTexture, baseColorFactor, metallicFactor, roughnessFactor, doubleSided, metallicRoughnessTexture, normalTexture, occlusionTexture, emissiveTexture, emissiveFactor, enableBlend, alphaCutoff } = primitive.material; - let physicMaterial = (newMat = this.applyMaterialExtensions(primitive.material, newMat) as PhysicMaterial); + let physicMaterial = (newMat = this.applyMaterialExtensions(primitive.material, newMat)); if (`enableBlend` in primitive.material) { if (primitive.material[`enableBlend`]) { physicMaterial.blendMode = BlendMode.NORMAL; - physicMaterial.depthWriteEnabled = false; } else { physicMaterial.blendMode = BlendMode.NONE; } - - if (primitive.material.defines) { - if (primitive.material.defines.indexOf(`ALPHA_BLEND`) != -1) { - physicMaterial.blendMode = BlendMode.ALPHA; - physicMaterial.transparent = true; - physicMaterial.depthWriteEnabled = false; - } - } } - if (`alphaCutoff` in primitive.material && alphaCutoff > 0) { - physicMaterial.alphaCutoff = alphaCutoff; + if (`alphaCutoff` in primitive.material && alphaCutoff > 0 && alphaCutoff < 1) { + physicMaterial.setUniformFloat("alphaCutoff", alphaCutoff); physicMaterial.blendMode = BlendMode.NORMAL; physicMaterial.transparent = true; - physicMaterial.depthWriteEnabled = false; + // physicMaterial.depthWriteEnabled = false; } - if (primitive.material.transformUV1) physicMaterial.uvTransform_1 = primitive.material.transformUV1; - if (primitive.material.transformUV2) physicMaterial.uvTransform_2 = primitive.material.transformUV2; - - physicMaterial.baseColor = new Color(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2], baseColorFactor[3]); - - physicMaterial.roughness = roughnessFactor; - - physicMaterial.metallic = metallicFactor; - + if (primitive.material.transformUV1) { + physicMaterial.setUniformVector4("uvTransform_1", primitive.material.transformUV1); + } + if (primitive.material.transformUV2) { + physicMaterial.setUniformVector4("uvTransform_2", primitive.material.transformUV2); + } + physicMaterial.setUniformColor("baseColor", new Color(baseColorFactor[0], baseColorFactor[1], baseColorFactor[2], baseColorFactor[3])); + physicMaterial.setUniformFloat("roughness", roughnessFactor); + physicMaterial.setUniformFloat("metallic", metallicFactor); + physicMaterial.setUniformFloat("ao", 1); physicMaterial.doubleSide = doubleSided; - physicMaterial.ao = 1; - if (baseColorTexture) { - physicMaterial.baseMap = baseColorTexture; + physicMaterial.setTexture("baseMap", baseColorTexture); } if (normalTexture) { - physicMaterial.normalMap = normalTexture; + physicMaterial.setTexture("normalMap", normalTexture); } if (metallicRoughnessTexture) { - physicMaterial.maskMap = metallicRoughnessTexture; + physicMaterial.setTexture("maskMap", metallicRoughnessTexture); } if (occlusionTexture && (metallicRoughnessTexture != occlusionTexture)) { - physicMaterial.aoMap = occlusionTexture; + physicMaterial.setTexture("aoMap", occlusionTexture); } if (emissiveTexture) { - physicMaterial.emissiveMap = emissiveTexture; + physicMaterial.setTexture("emissiveMap", emissiveTexture); } if (emissiveFactor && (emissiveFactor[0] > 0 || emissiveFactor[1] > 0 || emissiveFactor[2] > 0)) { - if (physicMaterial.emissiveMap) { - if (physicMaterial.emissiveMap == Engine3D.res.blackTexture) { - physicMaterial.emissiveMap = Engine3D.res.whiteTexture; - } + if (!physicMaterial.shader.getTexture("emissiveMap")) { + physicMaterial.shader.setTexture("emissiveMap", Engine3D.res.whiteTexture); } - let emissiveFactorA = emissiveFactor[3] ? emissiveFactor[3] : 1.0; - physicMaterial.emissiveColor = new Color(emissiveFactor[0], emissiveFactor[1], emissiveFactor[2], emissiveFactorA); - physicMaterial.emissiveIntensity = 1; + physicMaterial.setUniformColor("emissiveColor", new Color(emissiveFactor[0], emissiveFactor[1], emissiveFactor[2], emissiveFactor[3])); } } } @@ -412,6 +398,9 @@ export class GLTFSubParserConverter { indexCount: indicesAttribute.data.length, vertexStart: 0, index: 0, + vertexCount: 0, + firstStart: 0, + topology: 0 } ) return geometry; diff --git a/src/loader/parser/gltf/GLTFSubParserSkeleton.ts b/src/loader/parser/gltf/GLTFSubParserSkeleton.ts index eb8f0fdc..cd130572 100644 --- a/src/loader/parser/gltf/GLTFSubParserSkeleton.ts +++ b/src/loader/parser/gltf/GLTFSubParserSkeleton.ts @@ -46,37 +46,48 @@ export class GLTFSubParserSkeleton { } count++; let joint = skeleton.getJointByName(node.name); - switch (property) { - case 'scale': - for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { - var srcOffset = nFrame * outputAccessor.numComponents; - var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index; - bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x - bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y - bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z - bufferData[dstOffset + 3] = 1; - } - break; - case 'rotation': - for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { - var srcOffset = nFrame * outputAccessor.numComponents; - var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 4; - bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x - bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y - bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z - bufferData[dstOffset + 3] = outputAccessor.data[srcOffset + 3]; // w - } - break; - case 'translation': - for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { - var srcOffset = nFrame * outputAccessor.numComponents; - var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 8; - bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x - bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y - bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z - bufferData[dstOffset + 3] = inputAccessor.data[nFrame * inputAccessor.numComponents]; - } - break; + if (!joint) { + switch (property) { + case 'scale': + break; + case 'rotation': + break; + case 'translation': + break; + } + } else { + switch (property) { + case 'scale': + for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { + var srcOffset = nFrame * outputAccessor.numComponents; + var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index; + bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x + bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y + bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z + bufferData[dstOffset + 3] = 1; + } + break; + case 'rotation': + for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { + var srcOffset = nFrame * outputAccessor.numComponents; + var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 4; + bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x + bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y + bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z + bufferData[dstOffset + 3] = outputAccessor.data[srcOffset + 3]; // w + } + break; + case 'translation': + for (var nFrame: number = 0; nFrame < numFrame; nFrame++) { + var srcOffset = nFrame * outputAccessor.numComponents; + var dstOffset = skeletonPoseLength * nFrame + 12 * joint.index + 8; + bufferData[dstOffset + 0] = outputAccessor.data[srcOffset + 0]; // x + bufferData[dstOffset + 1] = outputAccessor.data[srcOffset + 1]; // y + bufferData[dstOffset + 2] = outputAccessor.data[srcOffset + 2]; // z + bufferData[dstOffset + 3] = inputAccessor.data[nFrame * inputAccessor.numComponents]; + } + break; + } } } diff --git a/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts b/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts index 3d895738..e8e5aa01 100644 --- a/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts +++ b/src/loader/parser/gltf/extends/KHR_materials_clearcoat.ts @@ -11,7 +11,7 @@ export class KHR_materials_clearcoat { public static apply(gltf: any, dmaterial: any, tMaterial: any) { let extensions = dmaterial.extensions; if (extensions && extensions[`KHR_materials_clearcoat`]) { - (tMaterial as Material).defaultPass.setDefine('USE_CLEARCOAT', true); + (tMaterial as Material).shader.getDefaultColorShader().setDefine('USE_CLEARCOAT', true); let KHR_materials_clearcoat = extensions[`KHR_materials_clearcoat`]; if (`clearcoatFactor` in KHR_materials_clearcoat) { diff --git a/src/loader/parser/prefab/PrefabAvatarParser.ts b/src/loader/parser/prefab/PrefabAvatarParser.ts new file mode 100644 index 00000000..f291feee --- /dev/null +++ b/src/loader/parser/prefab/PrefabAvatarParser.ts @@ -0,0 +1,56 @@ +import { Engine3D } from "../../../Engine3D"; +import { GeometryBase, LODDescriptor } from "../../../core/geometry/GeometryBase"; +import { GeometryVertexType } from "../../../core/geometry/GeometryVertexType"; +import { VertexAttributeName } from "../../../core/geometry/VertexAttributeName"; +import { BytesArray } from "../../../util/BytesArray"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; +import { PrefabAvatarData } from "./prefabData/PrefabAvatarData"; + + +export class PrefabAvatarParser extends ParserBase { + static format: ParserFormat = ParserFormat.BIN; + public static parser(bytesStream: BytesArray, prefabParser: PrefabParser) { + let avatarCount = bytesStream.readInt32(); + for (let j = 0; j < avatarCount; j++) { + let prefabAvatarData = new PrefabAvatarData(); + prefabAvatarData.formBytes(bytesStream.readBytesArray()); + Engine3D.res.addObj(prefabAvatarData.name, prefabAvatarData); + } + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } + +} + +let MeshVertexAttribute = { + "Position": VertexAttributeName.position, + "Normal": VertexAttributeName.normal, + "Color": VertexAttributeName.color, + "Tangent": VertexAttributeName.TANGENT, + "TexCoord0": VertexAttributeName.uv, + "TexCoord1": VertexAttributeName.TEXCOORD_1, + "TexCoord2": VertexAttributeName.TEXCOORD_2, + "TexCoord3": VertexAttributeName.TEXCOORD_2, + "TexCoord4": VertexAttributeName.TEXCOORD_4, + "TexCoord5": VertexAttributeName.TEXCOORD_5, + "TexCoord6": VertexAttributeName.TEXCOORD_6, + "TexCoord7": VertexAttributeName.TEXCOORD_7, + "BlendIndices": VertexAttributeName.joints0, + "BlendWeight": VertexAttributeName.weights0, +} + + + + diff --git a/src/loader/parser/prefab/PrefabMaterialParser.ts b/src/loader/parser/prefab/PrefabMaterialParser.ts new file mode 100644 index 00000000..900e99b5 --- /dev/null +++ b/src/loader/parser/prefab/PrefabMaterialParser.ts @@ -0,0 +1,171 @@ +import { BitmapTexture2D, BlendMode, Engine3D } from "../../.."; +import { LitMaterial } from "../../../materials/LitMaterial"; +import { Material } from "../../../materials/Material"; +import { Color } from "../../../math/Color"; +import { BytesArray } from "../../../util/BytesArray"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; +import { MaterialUtilities } from "./mats/MaterialUtilities"; +import { KV } from "./prefabData/KVData"; +import { PrefabTextureData } from "./prefabData/PrefabTextureData"; + + +export class PrefabMaterialParser extends ParserBase { + static format: ParserFormat = ParserFormat.TEXT; + + public static parserMaterial(bytesStream: BytesArray, prefabParser: PrefabParser) { + let matCount = bytesStream.readInt32(); + for (let i = 0; i < matCount; i++) { + let matBytes = bytesStream.readBytesArray(); + + let matName = matBytes.readUTF(); + let id = matBytes.readUTF(); + let renderType = matBytes.readUTF(); + let defines = matBytes.readStringArray(); + let uvTransform_1 = matBytes.readVector4(); + let uvTransform_2 = matBytes.readVector4(); + let shaderName = matBytes.readUTF(); + let properties: KV[] = []; + let textures: PrefabTextureData[] = []; + let propertyCount = matBytes.readInt32(); + for (let j = 0; j < propertyCount; j++) { + let kv: KV = new KV(); + kv.formBytes(matBytes); + properties.push(kv); + } + + let textureCount = matBytes.readInt32(); + for (let j = 0; j < textureCount; j++) { + let texBytes = matBytes.readBytesArray(); + let textureData = new PrefabTextureData(); + textureData.property = texBytes.readUTF(); + textureData.name = texBytes.readUTF(); + textureData.texture = Engine3D.res.getTexture(textureData.name) as BitmapTexture2D; + textureData.texelSize = texBytes.readVector2(); + textureData.wrapModeU = texBytes.readUnit32(); + textureData.wrapModeV = texBytes.readUnit32(); + textureData.wrapModeW = texBytes.readUnit32(); + textureData.wrapMode = texBytes.readUnit32(); + textureData.anisoLevel = texBytes.readUnit32(); + textureData.dimension = texBytes.readUnit32(); + textureData.filterMode = texBytes.readUnit32(); + textures.push(textureData); + } + + let mat = MaterialUtilities.GetMaterial(shaderName); + mat.name = matName; + // mat.uvTransform_1 = uvTransform_1; + // mat.uvTransform_2 = uvTransform_2; + // mat.roughness = 1; + // mat.metallic = 1; + // mat.alphaCutoff = 0.5; + + // mat.blendMode = renderType == "Opaque" ? BlendMode.NONE : BlendMode.ALPHA; + + for (let i = 0; i < defines.length; i++) { + const define = defines[i]; + mat.shader.setDefine(define, true); + } + + MaterialUtilities.applyMaterialTexture(mat, textures); + MaterialUtilities.applyMaterialProperties(mat, properties); + + // for (let k = 0; k < properties.length; k++) { + // const kv = properties[k]; + + // // mat.setu(texInfo.property, texInfo.texture); + // // if (kv.key in Material_transformer.prototype) { + // // Material_transformer.prototype[kv.key](kv, mat); + // // } + // } + + Engine3D.res.addMat(id, mat); + } + } + + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } +} + + +class Texture_transformer { + public _MainTex(tex: PrefabTextureData, material: Material) { + material.shader.setDefine("USE_SRGB_ALBEDO", true); + return { + property: "baseMap", + value: tex.texture + }; + } + + public _MetallicGlossMap(tex: PrefabTextureData) { + return { + property: "maskMap", + value: tex.texture + }; + } + + public _BumpMap(tex: PrefabTextureData) { + return { + property: "normalMap", + value: tex.texture + }; + } + + public _OcclusionMap(tex: PrefabTextureData, mat: LitMaterial) { + mat.shader.setDefine("USE_AOTEX", true); + mat.ao = 1.0; + return { + property: "aoMap", + value: tex.texture + }; + } +} + +class Material_transformer { + _Color(kv: KV, material: LitMaterial) { + material.baseColor = kv.getValue(); + } + + // _Glossiness(kv: KV, material: LitMaterial) { + // let str = kv.value.replaceAll("[", ""); + // str = str.replaceAll("]", ""); + // let alpha = 1.0 - parseFloat(str); + // let roughness = alpha * alpha * alpha * alpha; + // // material.roughness = roughness; + // } + //return 1 + Math.log2(maxSize) | 0; + + _GlossMapScale(kv: KV, material: LitMaterial) { + material.roughness = kv.getValue()[0]; + } + + _Metallic(kv: KV, material: LitMaterial) { + if (!material.maskMap) { + material.metallic = kv.getValue()[0]; + } else { + material.metallic = 1.0; + } + } + + _SmoothnessTextureChannel(kv: KV, material: LitMaterial) { + let channel = kv.getValue(); + let type = channel == 0 ? `USE_ROUGHNESS_A` : "USE_ALBEDO_A"; + let type2 = `USE_METALLIC_R`; + material.shader.setDefine(type, true); + material.shader.setDefine(type2, true); + } +} + +let TextureChannel = ["A", "R", "G", "B"] + diff --git a/src/loader/parser/prefab/PrefabMeshParser.ts b/src/loader/parser/prefab/PrefabMeshParser.ts new file mode 100644 index 00000000..d78fce4d --- /dev/null +++ b/src/loader/parser/prefab/PrefabMeshParser.ts @@ -0,0 +1,182 @@ +import { Engine3D } from "../../../Engine3D"; +import { GeometryBase, LODDescriptor } from "../../../core/geometry/GeometryBase"; +import { GeometryVertexType } from "../../../core/geometry/GeometryVertexType"; +import { VertexAttributeName } from "../../../core/geometry/VertexAttributeName"; +import { BytesArray } from "../../../util/BytesArray"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; +import { BlendShapeData } from "./prefabData/BlendShapeData"; +import { PrefabMeshData } from "./prefabData/PrefabMeshData"; + + +export class PrefabMeshParser extends ParserBase { + static format: ParserFormat = ParserFormat.BIN; + + public async parseBuffer(buffer: ArrayBuffer) { + } + + public static parserMeshs(bytesStream: BytesArray, prefabParser: PrefabParser) { + + + let meshCount = bytesStream.readInt32(); + for (let j = 0; j < meshCount; j++) { + let prefabMesh = new PrefabMeshData(); + let meshBytesArray = bytesStream.readBytesArray();; + prefabMesh.meshName = meshBytesArray.readUTF(); + prefabMesh.meshID = meshBytesArray.readUTF(); + + let useTangent = meshBytesArray.readFloat32() > 0; + let useColor = meshBytesArray.readFloat32() > 0; + let useSecondUV = meshBytesArray.readFloat32() > 0; + let useSkeleton = meshBytesArray.readFloat32() > 0; + let useBlendShape = meshBytesArray.readFloat32() > 0; + + if (useSkeleton) { + prefabMesh.bones = meshBytesArray.readStringArray(); + prefabMesh.bindPose = meshBytesArray.readMatrix44Array(); + } + + if (useBlendShape) { + prefabMesh.blendShapeData = new BlendShapeData(); + prefabMesh.blendShapeData.formBytes(meshBytesArray); + } + + let vertexBlock = meshBytesArray.readBytesArray(); + let vertexBuffer = meshBytesArray.readBytesArray(); + + let attCount = vertexBlock.readInt32(); + let vertex_dim = 0; + let attributes = []; + for (let i = 0; i < attCount; i++) { + attributes[i] = {}; + attributes[i].att = MeshVertexAttribute[vertexBlock.readUTF()]; + attributes[i].dim = vertexBlock.readInt32(); + vertex_dim += attributes[i].dim; + attributes[i].format = vertexBlock.readUTF(); + } + + prefabMesh.vertexCount = vertexBlock.readInt32(); + prefabMesh.vertexBuffer = vertexBuffer.getFloat32Array(); + + let tmpIndices = meshBytesArray.readInt32Array(); + let subMesh: LODDescriptor[] = []; + let subMeshCount = meshBytesArray.readInt32(); + for (let jj = 0; jj < subMeshCount; jj++) { + let subMesh_topology = meshBytesArray.readInt32(); + let subMesh_indexStart = meshBytesArray.readInt32(); + let subMesh_indexCount = meshBytesArray.readInt32(); + let subMesh_baseVertex = meshBytesArray.readInt32(); + let subMesh_firstVertex = meshBytesArray.readInt32(); + let subMesh_vertexCount = meshBytesArray.readInt32(); + let subMesh_boundMin = meshBytesArray.readVector3(); + let subMesh_boundMax = meshBytesArray.readVector3(); + let subDes: LODDescriptor = { + indexStart: subMesh_indexStart, + indexCount: subMesh_indexCount, + vertexStart: subMesh_baseVertex, + vertexCount: subMesh_vertexCount, + firstStart: subMesh_firstVertex, + topology: subMesh_topology, + index: jj + } + subMesh.push(subDes); + } + + + if (tmpIndices.length > 65535) { + prefabMesh.indices = new Uint32Array(tmpIndices); + } else { + prefabMesh.indices = new Uint16Array(tmpIndices); + } + + let geometry = new GeometryBase(); + geometry.vertexDim = vertex_dim; + geometry.geometryType = GeometryVertexType.compose_bin; + geometry.setIndices(prefabMesh.indices); + geometry.setAttribute(VertexAttributeName.all, prefabMesh.vertexBuffer); + if (useSkeleton) { + geometry.skinNames = prefabMesh.bones; + geometry.bindPose = prefabMesh.bindPose; + } + if (useBlendShape) { + geometry.blendShapeData = prefabMesh.blendShapeData; + geometry.morphTargetsRelative = true; + geometry.morphTargetDictionary = {}; + for (let i = 0; i < prefabMesh.blendShapeData.blendCount; i++) { + // if (i == 0) { + // for (let index = 0; index < prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendPositionList.length; index++) { + // if (prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendPositionList[index] != 0) { + // console.error("has"); + // } + // } + // } + geometry.setAttribute("a_morphPositions_" + i, prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendPositionList); + geometry.setAttribute("a_morphNormals_" + i, prefabMesh.blendShapeData.blendShapePropertyDatas[i].blendNormalList); + for (let i = 0; i < prefabMesh.blendShapeData.blendCount; i++) { + let blendName = prefabMesh.blendShapeData.shapeNames[i]; + let blendIndex = prefabMesh.blendShapeData.shapeIndexs[i]; + geometry.morphTargetDictionary[blendName] = blendIndex; + } + } + + + // geometry.setAttribute("a_morphPositions_0", prefabMesh.blendShapeData.positionList); + // geometry.setAttribute("a_morphNormals_0", prefabMesh.blendShapeData.normalList); + // geometry.morphTargetsRelative = true; + // geometry.morphTargetDictionary = {}; + // for (let i = 0; i < prefabMesh.blendShapeData.blendCount; i++) { + // let blendName = prefabMesh.blendShapeData.shapeNames[i]; + // let blendIndex = prefabMesh.blendShapeData.shapeIndexs[i]; + // geometry.morphTargetDictionary[blendName] = blendIndex; + // } + } + for (let ii = 0; ii < attributes.length; ii++) { + const element = attributes[ii].att; + geometry.setAttribute(element, null);//3 + } + + for (let kk = 0; kk < subMesh.length; kk++) { + const element = subMesh[kk]; + geometry.addSubGeometry(element); + } + + geometry.name = prefabMesh.meshName; + Engine3D.res.addGeometry(prefabMesh.meshID, geometry); + } + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } + +} + +let MeshVertexAttribute = { + "Position": VertexAttributeName.position, + "Normal": VertexAttributeName.normal, + "Color": VertexAttributeName.color, + "Tangent": VertexAttributeName.TANGENT, + "TexCoord0": VertexAttributeName.uv, + "TexCoord1": VertexAttributeName.TEXCOORD_1, + "TexCoord2": VertexAttributeName.TEXCOORD_2, + "TexCoord3": VertexAttributeName.TEXCOORD_2, + "TexCoord4": VertexAttributeName.TEXCOORD_4, + "TexCoord5": VertexAttributeName.TEXCOORD_5, + "TexCoord6": VertexAttributeName.TEXCOORD_6, + "TexCoord7": VertexAttributeName.vIndex, + "BlendIndices": VertexAttributeName.joints0, + "BlendWeight": VertexAttributeName.weights0, +} + + + + diff --git a/src/loader/parser/prefab/PrefabParser.ts b/src/loader/parser/prefab/PrefabParser.ts new file mode 100644 index 00000000..0fb2ce52 --- /dev/null +++ b/src/loader/parser/prefab/PrefabParser.ts @@ -0,0 +1,98 @@ +import { Engine3D } from "../../../Engine3D"; +import { MeshFilter } from "../../../components/renderer/MeshFilter"; +import { SkinnedMeshRenderer } from "../../../components/renderer/SkinnedMeshRenderer"; +import { Object3D } from "../../../core/entities/Object3D"; +import { GeometryBase } from "../../../core/geometry/GeometryBase"; +import { Material } from "../../../materials/Material"; +import { Quaternion } from "../../../math/Quaternion"; +import { Vector3 } from "../../../math/Vector3"; +import { BitmapTexture2D } from "../../../textures/BitmapTexture2D"; +import { BytesArray } from "../../../util/BytesArray"; +import { GetComponentClass } from "../../../util/SerializeDecoration"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabAvatarParser } from "./PrefabAvatarParser"; +import { PrefabMaterialParser } from "./PrefabMaterialParser"; +import { PrefabMeshParser } from "./PrefabMeshParser"; +import { PrefabTextureParser } from "./PrefabTextureParser"; +import { LitSSSShader } from "./mats/shader/LitSSSShader"; +import { LitShader } from "./mats/shader/LitShader"; +import { PrefabAvatarData } from "./prefabData/PrefabAvatarData"; +import { PrefabNode } from "./prefabData/PrefabNode"; + +LitShader; +LitSSSShader; +export class PrefabParser extends ParserBase { + public static useWebp: boolean = true; + static format: ParserFormat = ParserFormat.BIN; + public avatarDic: { [name: string]: PrefabAvatarData }; + public nodeData: PrefabNode; + public async parseBuffer(buffer: ArrayBuffer) { + this.avatarDic = {}; + + let bytesStream = new BytesArray(buffer, 0); + + await PrefabTextureParser.parserTexture(bytesStream, this, this.loaderFunctions); + + PrefabAvatarParser.parser(bytesStream, this); + + PrefabMeshParser.parserMeshs(bytesStream, this); + + PrefabMaterialParser.parserMaterial(bytesStream, this); + + this.nodeData = this.parserPrefabNode(bytesStream); + + this.data = this.data = this.parserNodeTree(this.nodeData); + } + + private parserPrefabNode(bytesStream: BytesArray) { + let rootNodeData = PrefabNode.parser(bytesStream); + return rootNodeData; + } + + private parserNodeTree(nodeData: PrefabNode) { + let root = new Object3D(); + root.localPosition = Vector3.serialize(nodeData.position); + root.localQuaternion = Quaternion.serialize(nodeData.rotation); + root.localScale = Vector3.serialize(nodeData.scale); + root.name = nodeData.name; + if (nodeData.comDatas) { + for (let i = 0; i < nodeData.comDatas.length; i++) { + const comData = nodeData.comDatas[i]; + let com = null; + let comClass = GetComponentClass(comData.comName); + if (comClass) { + com = root.getOrAddComponent(comClass); + for (let j = 0; j < comData.data.length; j++) { + const kv = comData.data[j]; + if (kv.key in com) { + com[kv.key] = kv.getValue(); + } + } + } else { + // console.warn("no component", comData.comName); + } + } + } + + if (nodeData.child && nodeData.child.length > 0) { + for (let j = 0; j < nodeData.child.length; j++) { + let child = this.parserNodeTree(nodeData.child[j]); + root.addChild(child); + } + } + return root; + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } +} diff --git a/src/loader/parser/prefab/PrefabStringUtil.ts b/src/loader/parser/prefab/PrefabStringUtil.ts new file mode 100644 index 00000000..140f2db9 --- /dev/null +++ b/src/loader/parser/prefab/PrefabStringUtil.ts @@ -0,0 +1,63 @@ +import { Quaternion } from "../../.."; + +export class PrefabStringUtil { + + public static getNumber(st: string) { + let v = parseFloat(st); + return v; + } + + public static getInt(st: string) { + let v = parseInt(st); + return v; + } + + public static getBoolean(st: string) { + let v = st == "true" ? true : false; + return v; + } + + public static getNumberArray(st: string) { + let v = st.replaceAll("[", ""); + v = v.replaceAll("]", ""); + let list = v.split(","); + let ret: number[] = []; + for (let i = 0; i < list.length; i++) { + const element = parseFloat(list[i]); + ret.push(element); + } + return v; + } + + public static getStringArray(st: string) { + let v = st.replaceAll("[", ""); + v = v.replaceAll("]", ""); + let list = v.split(","); + let ret: string[] = []; + for (let i = 0; i < list.length; i++) { + const element = (list[i]); + ret.push(element); + } + return ret; + } + + public static getVector2(st: string) { + + } + + public static getVector3(st: string) { + + } + + public static getVector4(st: string) { + + } + + public static getQuaternion(st: string) { + + } + + public static getColor(st: string) { + + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/PrefabTextureParser.ts b/src/loader/parser/prefab/PrefabTextureParser.ts new file mode 100644 index 00000000..78deaaf3 --- /dev/null +++ b/src/loader/parser/prefab/PrefabTextureParser.ts @@ -0,0 +1,46 @@ +import { Engine3D } from "../../../Engine3D"; +import { BitmapTexture2D } from "../../../textures/BitmapTexture2D"; +import { BytesArray } from "../../../util/BytesArray"; +import { LoaderFunctions } from "../../LoaderFunctions"; +import { ParserBase } from "../ParserBase"; +import { ParserFormat } from "../ParserFormat"; +import { PrefabParser } from "./PrefabParser"; + + +export class PrefabTextureParser extends ParserBase { + static format: ParserFormat = ParserFormat.TEXT; + + public static async parserTexture(bytesStream: BytesArray, prefabParser: PrefabParser, loaderFunctions: LoaderFunctions) { + let preTextureCount = bytesStream.readInt32(); + + let textures = []; + for (let i = 0; i < preTextureCount; i++) { + let texName = bytesStream.readUTF(); + if (PrefabParser.useWebp) { + texName = texName.replace("png", "webp"); + texName = texName.replace("jpb", "webp"); + textures.push(prefabParser.baseUrl + `webp\/` + texName); + } else { + textures.push(prefabParser.baseUrl + texName); + } + + } + + let textureList = await Engine3D.res.loadBitmapTextures(textures, Engine3D.setting.loader.numConcurrent, loaderFunctions, true); + for (const tex of textureList) { + Engine3D.res.addTexture(tex.name, tex); + } + } + + /** + * Verify parsing validity + * @param ret + * @returns + */ + public verification(): boolean { + if (this.data) { + return true; + } + throw new Error('verify failed.'); + } +} diff --git a/src/loader/parser/prefab/mats/MaterialUtilities.ts b/src/loader/parser/prefab/mats/MaterialUtilities.ts new file mode 100644 index 00000000..7f65c967 --- /dev/null +++ b/src/loader/parser/prefab/mats/MaterialUtilities.ts @@ -0,0 +1,139 @@ +import { Color, Vector2, Vector3, Vector4 } from "../../../.."; +import { Material } from "../../../../materials/Material"; +import { GetShader } from "../../../../util/SerializeDecoration"; +import { KV } from "../prefabData/KVData"; +import { PrefabTextureData } from "../prefabData/PrefabTextureData"; +import { ValueEnumType } from "../prefabData/ValueType"; + +export class MaterialUtilities { + + public static GetMaterial(shaderName: string) { + let name = shaderName; + // let name = "UnLitShader"; + let list = name.split("/"); + name = list[list.length - 1]; + + list = name.split("."); + name = list[list.length - 1]; + + let shader = GetShader(name); + if (shader) { + let material = new Material(); + material.shader = new shader(); + return material; + } else { + throw new console.error("not found shader, shader name is " + name); + + } + } + + public static applyMaterialTexture(mat: Material, textures: PrefabTextureData[]) { + for (let ii = 0; ii < textures.length; ii++) { + const texInfo = textures[ii]; + if (texInfo.property in mat) { + mat[texInfo.property] = texInfo.texture; + } else if (texInfo.property in mat.shader) { + mat.shader[texInfo.property] = texInfo.texture; + } else { + mat.setTexture(texInfo.property, texInfo.texture); + } + } + } + + public static applyMaterialProperties(mat: Material, properties: KV[]) { + for (let ii = 0; ii < properties.length; ii++) { + const propertyInfo = properties[ii]; + const key = propertyInfo.key; + // let transformInfo = mat.shader[propertyInfo.key]; + // if (transformInfo != null) { + switch (propertyInfo.type) { + case ValueEnumType.color: + case ValueEnumType.color32: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformColor(key, value); + } + } + break; + case ValueEnumType.single: + case ValueEnumType.float: + case ValueEnumType.int: + case ValueEnumType.int16: + case ValueEnumType.int32: + case ValueEnumType.int32: + case ValueEnumType.uint: + case ValueEnumType.uint32: + case ValueEnumType.uint64: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformFloat(key, value); + } + } + break; + case ValueEnumType.singleArray: + { + let value = propertyInfo.getValue()[0]; + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformFloat(key, value); + } + } + break; + case ValueEnumType.vector2: + case ValueEnumType.vector2Int: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformVector2(key, value); + } + } + break; + case ValueEnumType.vector3: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformVector3(key, value); + } + } + break; + case ValueEnumType.vector4: + { + let value = propertyInfo.getValue(); + if (key in mat) { + mat[key] = value; + } else if (key in mat.shader) { + mat.shader[key] = value; + } else { + mat.setUniformVector4(key, value); + } + } + break; + default: + break; + // } + } + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/LitHairShader.ts b/src/loader/parser/prefab/mats/shader/LitHairShader.ts new file mode 100644 index 00000000..94383506 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/LitHairShader.ts @@ -0,0 +1,220 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { ShaderLib } from "../../../../../assets/shader/ShaderLib"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; +import { Hair_shader_op, Hair_shader_tr, RenderShaderPass, PassType } from "../../../../.."; + + +@RegisterShader +export class LitHairShader extends Shader { + + constructor() { + super(); + + this.create_opPass(); + // this.create_trPass(); + + this.setDefine('USEC', true); + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + this.setDefine('USE_HAIR', true); + this.setDefine('USE_CUSTOMUNIFORM', true); + this.setDefine('USE_HAIRCOLOR', true); + + this.setDefault(); + this.debug(); + } + + private create_opPass() { + ShaderLib.register("HairShader_op", Hair_shader_op); + let colorShader = new RenderShaderPass('HairShader_op', 'HairShader_op'); + this.addRenderPass(colorShader); + + colorShader.setShaderEntry(`VertMain`, `FragMain`) + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + shaderState.blendMode = BlendMode.NONE; + shaderState.cullMode = GPUCullMode.none; + shaderState.writeMasks[0] = GPUColorWrite.ALL; + } + + private create_trPass() { + ShaderLib.register("HairShader_tr", Hair_shader_tr); + let colorShader = new RenderShaderPass('HairShader_tr', 'HairShader_tr'); + this.addRenderPass(colorShader); + + colorShader.setShaderEntry(`VertMain`, `FragMain`) + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + shaderState.depthWriteEnabled = false; + shaderState.blendMode = BlendMode.NORMAL; + shaderState.cullMode = GPUCullMode.none; + + shaderState.writeMasks[0] = GPUColorWrite.ALL; + shaderState.writeMasks[1] = 0; + shaderState.writeMasks[2] = 0; + shaderState.writeMasks[3] = 0; + } + + public debug() { + GUIHelp.addFolder("Hair"); + GUIHelp.addColor({ HairColorStart: new Color() }, "HairColorStart").onChange((v) => { + let c = new Color(); + c.copyFromArray(v); + this._HairColor0 = c; + }); + + GUIHelp.addColor({ HairColorEnd: new Color() }, "HairColorEnd").onChange((v) => { + let c = new Color(); + c.copyFromArray(v); + this._HairColor1 = c; + }); + + GUIHelp.addColor({ specularColor: new Color() }, "specularColor").onChange((v) => { + let c = new Color(); + c.copyFromArray(v); + this._SpecularColor = c; + }); + + GUIHelp.add({ roughness: 1 }, "roughness", 0.0, 1.0).onChange((v) => { + this._Roughness = v; + }); + GUIHelp.add({ metallic: 1 }, "metallic", 0.0, 1.0).onChange((v) => { + this._Metallic = v; + }); + + GUIHelp.add({ alphaCutoff: 1 }, "alphaCutoff", 0.0, 1.0).onChange((v) => { + this._AlphaCutoff = v; + }); + + GUIHelp.add({ backlit: 1 }, "backlit", 0.0, 1.0, 0.0001).onChange((v) => { + this._BackLit = v; + }); + + GUIHelp.add({ area: 0.1 }, "area", 0.0, 1.0, 0.0001).onChange((v) => { + this._Area = v; + }); + GUIHelp.endFolder(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor0`, new Color(3 / 255, 2 / 255, 2 / 255)); + this.setUniformColor(`baseColor1`, new Color(2 / 255, 2 / 255, 2 / 255)); + this.setUniformColor(`emissiveColor`, new Color(1, 1, 1)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(36 / 255, 36 / 255, 36 / 255)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 0.1); + this.setUniformFloat(`metallic`, 0.3); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.1); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`backlit`, 0.3987); + this.setUniformFloat(`area`, 0.0615); + } + + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _IDMap(value: Texture) { + this.setTexture("idMap", value); + } + + public set _DepthMap(value: Texture) { + this.setTexture("depthMap", value); + } + + public set _RootMap(value: Texture) { + this.setTexture("rootMap", value); + } + + public set _AlphaMap(value: Texture) { + this.setTexture("alphaMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + public set _HairColor0(value: Color) { + this.setUniformColor("baseColor0", value); + } + + public set _HairColor1(value: Color) { + this.setUniformColor("baseColor1", value); + } + + public set _SpecularColor(value: Color) { + this.setUniformColor("specularColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _BackLit(value: number) { + this.setUniformFloat("backlit", value); + } + + public set _Area(value: number) { + this.setUniformFloat("area", value); + } + + + public set _DoubleSidedEnable(value: number) { + let subShader = this.getSubShaders(PassType.COLOR)[0]; + subShader.shaderState.cullMode = value ? GPUCullMode.none : subShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + if (value == 0) { + // this.blendMode = BlendMode.NONE; + } else { + // this.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/LitSSSShader.ts b/src/loader/parser/prefab/mats/shader/LitSSSShader.ts new file mode 100644 index 00000000..8682bbf4 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/LitSSSShader.ts @@ -0,0 +1,178 @@ +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; +import { PBRLitSSSShader } from "../../../../../assets/shader/materials/PBRLitSSSShader"; +import { ShaderLib } from "../../../../../assets/shader/ShaderLib"; +import { PreIntegratedLutCompute } from "../../../../../gfx/graphics/webGpu/compute/PreIntegratedLutCompute"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; + + +@RegisterShader +export class LitSSSShader extends Shader { + + constructor() { + super(); + + ShaderLib.register("PBRLitSSSShader", PBRLitSSSShader); + let colorShader = new RenderShaderPass('PBRLitSSSShader', 'PBRLitSSSShader'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + this.setDefine('USE_CUSTOMUNIFORM', true); + this.setDefault(); + this.debug(); + + this.computes = [ + new PreIntegratedLutCompute(this) + ] + } + + public debug() { + GUIHelp.addFolder("face"); + GUIHelp.addColor({ SkinColor: new Color() }, "SkinColor").onChange((v) => { + let newColor = new Color(); + newColor.copyFromArray(v); + this._SkinColor = newColor; + }); + GUIHelp.add({ skinPower: 1 }, "skinPower", 0.0, 10.0).onChange((v) => { + this._SkinPower = v; + }); + GUIHelp.add({ skinColorIns: 1 }, "skinColorIns", 0.0, 10.0).onChange((v) => { + this._SkinColorIns = v; + }); + GUIHelp.add({ roughness: 1 }, "roughness", 0.0, 1.0).onChange((v) => { + this._Roughness = v; + }); + GUIHelp.add({ metallic: 1 }, "metallic", 0.0, 1.0).onChange((v) => { + this._Metallic = v; + }); + GUIHelp.add({ curveFactor: 1 }, "curveFactor", 0.0, 10.0).onChange((v) => { + this.curveFactor = v; + }); + + GUIHelp.endFolder(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformColor(`emissiveColor`, new Color(1, 1, 1)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 1.0); + this.setUniformFloat(`metallic`, 0.0); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.0); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`clearcoatFactor`, 0.0); + this.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); + this.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); + this.setUniformFloat(`clearcoatWeight`, 0.0); + + this.setUniformColor(`skinColor`, new Color(1, 0, 0)); + this.setUniformFloat(`skinPower`, 3.4); + this.setUniformFloat(`skinColorIns`, 0.5); + this.setUniformFloat(`curveFactor`, 1.0); + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _SSSMap(value: Texture) { + this.setTexture("sssMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let shader = this.getDefaultColorShader(); + shader.shaderState.cullMode = value ? GPUCullMode.none : shader.shaderState.cullMode; + } + + public set _SkinColor(value: Color) { + this.setUniformColor("skinColor", value); + } + + public set _SkinPower(value: number) { + this.setUniformFloat("skinPower", value); + } + + public set _SkinColorIns(value: number) { + this.setUniformFloat("skinColorIns", value); + } + + public set curveFactor(value: number) { + this.setUniformFloat("curveFactor", value); + } + + public set _SurfaceType(value: number) { + let shader = this.getDefaultColorShader(); + if (value == 0) { + shader.blendMode = BlendMode.NONE; + } else { + shader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/LitShader.ts b/src/loader/parser/prefab/mats/shader/LitShader.ts new file mode 100644 index 00000000..c6612406 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/LitShader.ts @@ -0,0 +1,121 @@ +import { Engine3D } from "../../../../.."; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class LitShader extends Shader { + + constructor() { + super(); + + let colorShader = new RenderShaderPass('PBRLItShader', 'PBRLItShader'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + + this.setDefault(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformColor(`emissiveColor`, new Color(0, 0, 0)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 1.0); + this.setUniformFloat(`metallic`, 0.0); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.0); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`clearcoatFactor`, 0.0); + this.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); + this.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); + this.setUniformFloat(`clearcoatWeight`, 0.0); + + this._MainTex = Engine3D.res.grayTexture; + this._BumpMap = Engine3D.res.normalTexture; + this._MaskTex = Engine3D.res.maskTexture; + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let subShader = this.getDefaultColorShader(); + subShader.shaderState.cullMode = value ? GPUCullMode.none : subShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + let subShader = this.getDefaultColorShader(); + if (value == 0) { + subShader.blendMode = BlendMode.NONE; + } else { + subShader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/QuadShader.ts b/src/loader/parser/prefab/mats/shader/QuadShader.ts new file mode 100644 index 00000000..706aeb7c --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/QuadShader.ts @@ -0,0 +1,34 @@ +import { Engine3D } from "../../../../../Engine3D"; +import { GPUCompareFunction, GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class QuadShader extends Shader { + + constructor(vs: string = 'QuadGlsl_vs', fs: string = 'QuadGlsl_fs') { + super(); + + let colorShader = new RenderShaderPass(vs, fs); + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + colorShader.blendMode = BlendMode.NONE; + shaderState.frontFace = `cw`; + shaderState.depthWriteEnabled = false; + shaderState.depthCompare = GPUCompareFunction.always; + shaderState.multisample = 0; + + this.setTexture("baseMap", Engine3D.res.blackTexture); + this.setUniformFloat(`x`, 0); + this.setUniformFloat(`y`, 0); + this.setUniformFloat(`width`, 100); + this.setUniformFloat(`height`, 100); + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/SkyShader.ts b/src/loader/parser/prefab/mats/shader/SkyShader.ts new file mode 100644 index 00000000..27d4a618 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/SkyShader.ts @@ -0,0 +1,30 @@ +import { GPUCompareFunction, GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector3 } from "../../../../../math/Vector3"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class SkyShader extends Shader { + + constructor() { + super(); + let colorShader = new RenderShaderPass('sky_vs_frag_wgsl', 'sky_fs_frag_wgsl'); + this.addRenderPass(colorShader); + + colorShader.setUniformVector3(`eyesPos`, new Vector3()); + colorShader.setUniformFloat(`exposure`, 1.0); + colorShader.setUniformFloat(`roughness`, 0.0); + + let shaderState = colorShader.shaderState; + shaderState.frontFace = `cw`; + shaderState.cullMode = GPUCullMode.back; + shaderState.depthWriteEnabled = false; + shaderState.depthCompare = GPUCompareFunction.less; + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/StandShader.ts b/src/loader/parser/prefab/mats/shader/StandShader.ts new file mode 100644 index 00000000..2dc3f3ea --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/StandShader.ts @@ -0,0 +1,485 @@ +import { Engine3D, PassType } from "../../../../.."; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class StandShader extends Shader { + + constructor() { + super(); + + let colorShader = new RenderShaderPass('PBRLItShader', 'PBRLItShader'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + colorShader.passType = PassType.COLOR; + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = true; + shaderState.castShadow = true; + shaderState.receiveEnv = true; + shaderState.acceptGI = true; + shaderState.useLight = true; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + + this.setDefault(); + } + + public setDefault() { + this.setUniformFloat(`shadowBias`, 0.00035); + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color(0.75, 0.75, 0.75, 1.0)); + this.setUniformColor(`emissiveColor`, new Color(0, 0, 0)); + this.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + this.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); + this.setUniformFloat(`envIntensity`, 1); + this.setUniformFloat(`normalScale`, 1); + this.setUniformFloat(`roughness`, 1.0); + this.setUniformFloat(`metallic`, 1.0); + this.setUniformFloat(`ao`, 1.0); + this.setUniformFloat(`roughness_min`, 0.0); + this.setUniformFloat(`roughness_max`, 1.0); + this.setUniformFloat(`metallic_min`, 0.0); + this.setUniformFloat(`metallic_max`, 1.0); + this.setUniformFloat(`emissiveIntensity`, 0.0); + this.setUniformFloat(`alphaCutoff`, 0.0); + this.setUniformFloat(`ior`, 1.5); + this.setUniformFloat(`clearcoatFactor`, 0.0); + this.setUniformFloat(`clearcoatRoughnessFactor`, 0.0); + this.setUniformColor(`clearcoatColor`, new Color(1, 1, 1)); + this.setUniformFloat(`clearcoatWeight`, 0.0); + + this.baseMap = Engine3D.res.whiteTexture; + this.normalMap = Engine3D.res.normalTexture; + this.maskMap = Engine3D.res.maskTexture; + } + + public get baseMap(): Texture { + return this.getDefaultColorShader().getTexture(`baseMap`); + } + + public set baseMap(value: Texture) { + this.getDefaultColorShader().setTexture(`baseMap`, value); + } + + public get baseColor(): Color { + return this.getDefaultColorShader().getUniform(`baseColor`); + } + + public set baseColor(value: Color) { + this.getDefaultColorShader().setUniformColor(`baseColor`, value); + } + + public get normalMap(): Texture { + return this.getDefaultColorShader().getTexture(`normalMap`); + } + + public set normalMap(value: Texture) { + this.getDefaultColorShader().setTexture(`normalMap`, value); + } + + public get doubleSide(): boolean { + return this.getDefaultColorShader().doubleSide; + } + public set doubleSide(value: boolean) { + this.getDefaultColorShader().doubleSide = value; + } + + public get alphaCutoff(): any { + return this.getDefaultColorShader().shaderState.alphaCutoff; + } + public set alphaCutoff(value: any) { + this.getDefaultColorShader().setDefine("USE_ALPHACUT", true); + this.getDefaultColorShader().shaderState.alphaCutoff = value; + this.getDefaultColorShader().setUniform(`alphaCutoff`, value); + } + + public get emissiveColor(): Color { + return this.getDefaultColorShader().getUniform(`emissiveColor`); + } + + public set emissiveColor(value: Color) { + this.getDefaultColorShader().setUniform(`emissiveColor`, value); + } + + public get emissiveIntensity(): number { + return this.getDefaultColorShader().getUniform(`emissiveIntensity`); + } + + public set emissiveIntensity(value: number) { + this.getDefaultColorShader().setUniform(`emissiveIntensity`, value); + } + + /** + * get transformUV1 + */ + public get uvTransform_1(): Vector4 { + return this.getDefaultColorShader().uniforms[`transformUV1`].vector4; + } + + /** + * set transformUV1 + */ + public set uvTransform_1(value: Vector4) { + // this.getDefaultColorShader().uniforms[`transformUV1`].v4 = value; + this.getDefaultColorShader().setUniform(`transformUV1`, value); + } + + /** + * get transformUV2 + */ + public get uvTransform_2(): Vector4 { + return this.getDefaultColorShader().uniforms[`transformUV2`].vector4; + } + + /** + * set transformUV2 + */ + public set uvTransform_2(value: Vector4) { + // this.getDefaultColorShader().uniforms[`transformUV2`].v4 = value; + this.getDefaultColorShader().setUniform(`transformUV2`, value); + } + + public get depthWriteEnabled(): boolean { + return this.getDefaultColorShader().shaderState.depthWriteEnabled; + } + public set depthWriteEnabled(value: boolean) { + this.getDefaultColorShader().shaderState.depthWriteEnabled = value; + } + + /** + * get reflectivity + */ + public get materialF0(): Vector4 { + return this.getDefaultColorShader().uniforms[`materialF0`].vector4; + } + + /** + * set reflectivity + */ + public set materialF0(value: Vector4) { + this.getDefaultColorShader().setUniform(`materialF0`, value); + } + + /** + * get specularColor + */ + public get specularColor(): Color { + return this.getDefaultColorShader().uniforms[`specularColor`].color; + } + + /**specularColor + * set reflectivity + */ + public set specularColor(value: Color) { + this.getDefaultColorShader().setUniform(`specularColor`, value); + } + + /** + * get roughness + */ + public get roughness(): number { + return this.getDefaultColorShader().uniforms[`roughness`].value; + } + + /** + * set roughness + */ + public set roughness(value: number) { + this.getDefaultColorShader().setUniform(`roughness`, value); + } + + /** + * get metallic + */ + public get metallic(): number { + return this.getDefaultColorShader().uniforms[`metallic`].value; + } + + /** + * set metallic + */ + public set metallic(value: number) { + this.getDefaultColorShader().setUniform(`metallic`, value); + } + + /** + * get Ambient Occlussion, dealing with the effect of ambient light on object occlusion + */ + public get ao(): number { + return this.getDefaultColorShader().uniforms[`ao`].value; + } + + /** + * set Ambient Occlussion, dealing with the effect of ambient light on object occlusion + */ + public set ao(value: number) { + this.getDefaultColorShader().setUniform(`ao`, value); + } + + /** + * get min metallic + */ + public get metallic_min(): number { + return this.getDefaultColorShader().uniforms[`metallic_min`].value; + } + + /** + * set min metallic + */ + public set metallic_min(value: number) { + this.getDefaultColorShader().setUniform(`metallic_min`, value); + } + + /** + * get max metallic + */ + public get metallic_max(): number { + return this.getDefaultColorShader().uniforms[`metallic_max`].value; + } + + /** + * set max metallic + */ + public set metallic_max(value: number) { + this.getDefaultColorShader().setUniform(`metallic_max`, value); + } + + /** + * get min roughness + */ + public get roughness_min(): number { + return this.getDefaultColorShader().uniforms[`roughness_min`].value; + } + + /** + * set min roughness + */ + public set roughness_min(value: number) { + this.getDefaultColorShader().setUniform(`roughness_min`, value); + } + + /** + * get max roughness + */ + public get roughness_max(): number { + return this.getDefaultColorShader().uniforms[`roughness_max`].value; + } + + /** + * set max roughness + */ + public set roughness_max(value: number) { + this.getDefaultColorShader().setUniform(`roughness_max`, value); + } + + /** + * Get the influence of Normal mapping on materials + */ + public get normalScale(): number { + return this.getDefaultColorShader().uniforms[`normalScale`].value; + } + + /** + * Set the influence of Normal mapping on materials + */ + public set normalScale(value: number) { + this.getDefaultColorShader().setUniform(`normalScale`, value); + } + + /** + * get Mask Map + * R_chanel -> AoMap + * G_chanel -> Roughness + * B_chanel -> Metallic + * A_chanel -> C + */ + public get maskMap(): Texture { + return this.getDefaultColorShader().textures[`maskMap`]; + } + + /** + * set Mask Map + * R_chanel -> AoMap + * G_chanel -> Roughness + * B_chanel -> Metallic + * A_chanel -> C + */ + public set maskMap(value: Texture) { + // USE_MR + // USE_ORMC + // USE_RMOC + // USE_CRMC + this.getDefaultColorShader().setDefine(`USE_MR`, true); + this.getDefaultColorShader().setTexture(`maskMap`, value); + } + + /** + * set Ambient Occlussion Map, dealing with the effect of ambient light on object occlusion + */ + public set aoMap(value: Texture) { + if (!value) return; + this.getDefaultColorShader().setTexture(`aoMap`, value); + if (value != Engine3D.res.whiteTexture) { + this.getDefaultColorShader().setDefine(`USE_AOTEX`, true); + } + } + + /** + * get Ambient Occlussion Map, dealing with the effect of ambient light on object occlusion + */ + public get aoMap(): Texture { + return this.getDefaultColorShader().textures[`aoMap`]; + } + + /** + * set clearCoatRoughnessMap + */ + public set clearCoatRoughnessMap(value: Texture) { + if (!value) return; + console.log("USE_CLEARCOAT_ROUGHNESS"); + + this.getDefaultColorShader().setTexture(`clearCoatRoughnessMap`, value); + this.getDefaultColorShader().setDefine(`USE_CLEARCOAT_ROUGHNESS`, true); + } + + /** + * get clearCoatRoughnessMap + */ + public get clearCoatRoughnessMap(): Texture { + return this.getDefaultColorShader().textures[`clearCoatRoughnessMap`]; + } + + /** + * get brdf query map + */ + public get brdfLUT(): Texture { + return this.getDefaultColorShader().textures[`brdfLUT`]; + } + + /** + * set brdf query map + */ + public set brdfLUT(value: Texture) { + this.getDefaultColorShader().setTexture(`brdfLUT`, value); + this.getDefaultColorShader().setTexture(`brdflutMap`, value); + } + + /** + * get emissive map + */ + public get emissiveMap(): Texture { + return this.getDefaultColorShader().textures[`emissiveMap`]; + } + + /** + * set emissive map + */ + public set emissiveMap(value: Texture) { + this.getDefaultColorShader().setTexture(`emissiveMap`, value); + } + + /** + * set intensity of environment light or color of sampled by texture + */ + public set envIntensity(value: number) { + this.getDefaultColorShader().setUniformFloat(`envIntensity`, value); + } + + /** + * get intensity of environment light or color of sampled by texture + */ + public get envIntensity() { + return this.getDefaultColorShader().uniforms[`envIntensity`].value; + } + + /** + * set factor of refractive + */ + public set ior(value: number) { + this.getDefaultColorShader().setUniformFloat(`ior`, value); + } + + /** + * get factor of refractive + */ + public get ior(): number { + return this.getDefaultColorShader().uniforms[`ior`].value; + } + + /** + * valid USE_CLEARCOAT define in shader + */ + public useCleanCoat() { + this.getDefaultColorShader().setDefine("USE_CLEARCOAT", true); + } + + /** + * Set the factor of the clearcoat + */ + public set clearcoatFactor(value: number) { + this.getDefaultColorShader().setUniformFloat(`clearcoatFactor`, value); + this.useCleanCoat(); + } + + /** + * get the factor of the clearcoat + */ + public get clearcoatFactor(): number { + return this.getDefaultColorShader().uniforms[`clearcoatFactor`].value; + } + + /** + * set the factor of the clearcoat Roughness + */ + public set clearcoatRoughnessFactor(value: number) { + this.getDefaultColorShader().setUniformFloat(`clearcoatRoughnessFactor`, value); + this.useCleanCoat(); + } + + /** + * get the factor of the clearcoat Roughness + */ + public get clearcoatRoughnessFactor(): number { + return this.getDefaultColorShader().uniforms[`clearcoatRoughnessFactor`].value; + } + + /** + * set the weight of the clearcoat + */ + public set clearcoatWeight(value: number) { + this.getDefaultColorShader().setUniformFloat(`clearcoatWeight`, value); + this.useCleanCoat(); + } + + /** + * get the weight of the clearcoat + */ + public get clearcoatWeight(): number { + return this.getDefaultColorShader().uniforms[`clearcoatWeight`].value; + } + + /** + * get the color of the clearcoat + */ + public set clearcoatColor(value: Color) { + this.getDefaultColorShader().setUniformColor(`clearcoatColor`, value); + this.useCleanCoat(); + } + + /** + * set the color of the clearcoat + */ + public get clearcoatColor(): Color { + return this.getDefaultColorShader().uniforms[`clearcoatColor`].color; + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/UnLitShader.ts b/src/loader/parser/prefab/mats/shader/UnLitShader.ts new file mode 100644 index 00000000..4ccd4ce5 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/UnLitShader.ts @@ -0,0 +1,98 @@ +import { Engine3D } from "../../../../../Engine3D"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; + + +@RegisterShader +export class UnLitShader extends Shader { + + constructor() { + super(); + let colorShader = new RenderShaderPass('UnLit', 'UnLit'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = false; + shaderState.castShadow = false; + shaderState.receiveEnv = false; + shaderState.acceptGI = false; + shaderState.useLight = false; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + + this.setDefault(); + } + + public setDefault() { + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformFloat(`alphaCutoff`, 0.0); + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let defaultShader = this.getDefaultColorShader(); + defaultShader.shaderState.cullMode = value ? GPUCullMode.none : defaultShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + let defaultShader = this.getDefaultColorShader(); + if (value == 0) { + defaultShader.blendMode = BlendMode.NONE; + } else { + defaultShader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/mats/shader/UnLitTexArrayShader.ts b/src/loader/parser/prefab/mats/shader/UnLitTexArrayShader.ts new file mode 100644 index 00000000..9b8ac7b1 --- /dev/null +++ b/src/loader/parser/prefab/mats/shader/UnLitTexArrayShader.ts @@ -0,0 +1,103 @@ +import { Engine3D } from "../../../../../Engine3D"; +import { GPUCullMode } from "../../../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../../../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../../../../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { BlendMode } from "../../../../../materials/BlendMode"; +import { Color } from "../../../../../math/Color"; +import { Vector4 } from "../../../../../math/Vector4"; +import { RegisterShader } from "../../../../../util/SerializeDecoration"; +import { Shader } from "../../../../../gfx/graphics/webGpu/shader/Shader"; +import { UnLitTextureArray } from "../../../../../assets/shader/materials/UnLitTextureArray"; +import { ShaderLib } from "../../../../../assets/shader/ShaderLib"; +import { VertexAttributeIndexShader } from "../../../../../assets/shader/core/struct/VertexAttributeIndexShader"; + + +@RegisterShader +export class UnLitTexArrayShader extends Shader { + + constructor() { + super(); + + ShaderLib.register("VertexAttributeIndexShader", VertexAttributeIndexShader); + ShaderLib.register("UnLitTextureArray", UnLitTextureArray); + let colorShader = new RenderShaderPass('UnLitTextureArray', 'UnLitTextureArray'); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + this.addRenderPass(colorShader); + + let shaderState = colorShader.shaderState; + shaderState.acceptShadow = false; + shaderState.castShadow = false; + shaderState.receiveEnv = false; + shaderState.acceptGI = false; + shaderState.useLight = false; + this.setDefine('USE_BRDF', true); + this.setDefine('USE_AO_R', true); + this.setDefine('USE_ROUGHNESS_G', true); + this.setDefine('USE_METALLIC_B', true); + this.setDefine('USE_ALPHA_A', true); + this.setDefault(); + } + + public setDefault() { + this.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + this.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + this.setUniformColor(`baseColor`, new Color()); + this.setUniformFloat(`alphaCutoff`, 0.0); + } + + public set _MainTex(value: Texture) { + this.setTexture("baseMap", value); + } + + public set _BumpMap(value: Texture) { + this.setTexture("normalMap", value); + } + + public set _MaskTex(value: Texture) { + this.setTexture("maskMap", value); + } + + public set _UVTransform(value: Vector4) { + this.setUniformVector4("transformUV1", value); + } + + public set _Metallic(value: number) { + this.setUniformFloat("metallic", value); + } + + public set _Roughness(value: number) { + this.setUniformFloat("roughness", value); + } + + + public set _MainColor(value: Color) { + this.setUniformColor("baseColor", value); + } + + public set _AlphaCutoff(value: number) { + this.setUniformFloat("alphaCutoff", value); + } + + public set _DoubleSidedEnable(value: number) { + let defaultShader = this.getDefaultColorShader(); + defaultShader.shaderState.cullMode = value ? GPUCullMode.none : defaultShader.shaderState.cullMode; + } + + public set _SurfaceType(value: number) { + let defaultShader = this.getDefaultColorShader(); + if (value == 0) { + defaultShader.blendMode = BlendMode.NONE; + } else { + defaultShader.blendMode = BlendMode.ALPHA; + } + } + + public set _AlphaCutoffEnable(value: number) { + if (value == 0) { + this.setDefine('USE_ALPHACUT', false); + } else { + this.setDefine('USE_ALPHACUT', true); + } + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/APatch.ts b/src/loader/parser/prefab/prefabData/APatch.ts new file mode 100644 index 00000000..3c91b196 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/APatch.ts @@ -0,0 +1,34 @@ +import { Vector3, View3D } from "../../../.."; +import { ComponentBase } from "../../../../components/ComponentBase"; +import { Color } from "../../../../math/Color"; +import { Vector2 } from "../../../../math/Vector2"; +import { RegisterComponent } from "../../../../util/SerializeDecoration"; + +@RegisterComponent +export class APatch extends ComponentBase { + public size: Vector2; + public blockSize: number; + public walk: Color; + public obs: Color; + + public colors: Color[]; + + public aPaths: number[]; + + public onGraphic(view?: View3D) { + return; + + // for (let i = this.size.x ; i > 0 ; i--) { + for (let i = 0; i < this.size.x; i++) { + for (let j = 0; j < this.size.y; j++) { + let index = j * this.size.x + (i); + let data = this.aPaths[index]; + let color = this.colors[data] ; + + let pos = new Vector3(-i * this.blockSize + this.object3D.x , 0 + this.object3D.y , j * this.blockSize+ this.object3D.z); + view.graphic3D.drawFillRect(`${i}-${j}` , pos , this.blockSize , this.blockSize, color ); + } + } + + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/BlendShapeData.ts b/src/loader/parser/prefab/prefabData/BlendShapeData.ts new file mode 100644 index 00000000..b71f8638 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/BlendShapeData.ts @@ -0,0 +1,44 @@ +import { BytesArray } from "../../../../util/BytesArray"; +import { BlendShapePropertyData } from "./BlendShapePropertyData"; + +export class BlendShapeData { + public vertexCount: number; + public shapeNames: string[]; + public shapeIndexs: number[]; + + public blendCount: number; + + // public positionList: Float32Array; + // public normalList: Float32Array; + + public blendShapePropertyDatas: BlendShapePropertyData[]; + public blendShapeMap: Map; + + public formBytes(byteArray: BytesArray) { + this.blendShapeMap = new Map(); + this.blendShapePropertyDatas = []; + let bytes = byteArray.readBytesArray(); + + this.vertexCount = bytes.readInt32(); + this.shapeNames = bytes.readStringArray(); + this.shapeIndexs = bytes.readIntArray(); + + this.blendCount = bytes.readInt32(); + + // let posCount = bytes.readInt32(); + // this.positionList = bytes.readFloat32Array(posCount * 3); + // let normalCount = bytes.readInt32(); + // this.normalList = bytes.readFloat32Array(normalCount * 3); + + + for (let i = 0; i < this.blendCount; i++) { + let propertyData = new BlendShapePropertyData(); + propertyData.formBytes(bytes); + + this.blendShapePropertyDatas.push(propertyData); + this.blendShapeMap.set(propertyData.shapeName, propertyData); + } + return byteArray; + } + +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/BlendShapeFrameData.ts b/src/loader/parser/prefab/prefabData/BlendShapeFrameData.ts new file mode 100644 index 00000000..07bc055c --- /dev/null +++ b/src/loader/parser/prefab/prefabData/BlendShapeFrameData.ts @@ -0,0 +1,27 @@ +import { Vector3 } from "../../../../math/Vector3"; +import { BytesArray } from "../../../../util/BytesArray"; + +export class BlendShapeFrameData { + + public weight: number; + + // public deltaVertices: Vector3[]; + // public deltaNormals: Vector3[]; + // public deltaTangents: Vector3[]; + + public deltaVertices: Float32Array; + public deltaNormals: Float32Array; + public deltaTangents: Float32Array; + + formBytes(byteArray: BytesArray) { + let bytes = byteArray.readBytesArray(); + this.weight = bytes.readFloat32(); + let len = 0; + len = bytes.readInt32(); + this.deltaVertices = bytes.readFloat32Array(len * 3); + len = bytes.readInt32(); + this.deltaNormals = bytes.readFloat32Array(len * 3); + len = bytes.readInt32(); + this.deltaTangents = bytes.readFloat32Array(len * 3); + } +} diff --git a/src/loader/parser/prefab/prefabData/BlendShapePropertyData.ts b/src/loader/parser/prefab/prefabData/BlendShapePropertyData.ts new file mode 100644 index 00000000..75ac1ed8 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/BlendShapePropertyData.ts @@ -0,0 +1,24 @@ +import { BytesArray } from "../../../.."; +import { BlendShapeFrameData } from "./BlendShapeFrameData"; + +export class BlendShapePropertyData { + public shapeName: string; + public shapeIndex: number; + public frameCount: number; + // public blendShapeFrameDatas: BlendShapeFrameData[]; + public blendPositionList = new Float32Array(); + public blendNormalList = new Float32Array(); + public formBytes(byteArray: BytesArray) { + let bytes = byteArray.readBytesArray(); + + this.shapeName = bytes.readUTF(); + this.shapeIndex = bytes.readInt32(); + this.frameCount = bytes.readInt32(); + + let len = bytes.readInt32(); + this.blendPositionList = bytes.readFloat32Array(len * 3); + + let len2 = bytes.readInt32(); + this.blendNormalList = bytes.readFloat32Array(len2 * 3); + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/KVData.ts b/src/loader/parser/prefab/prefabData/KVData.ts new file mode 100644 index 00000000..dd7eb533 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/KVData.ts @@ -0,0 +1,24 @@ +import { BytesArray } from "../../../../util/BytesArray"; +import { ValueParser } from "./ValueParser"; +import { ValueEnumType } from "./ValueType"; + + + +export class KV { + + public key: string; + public type: ValueEnumType; + private _data: any; + + public getValue(): T { + return this._data as T; + } + + formBytes(matBytes: BytesArray) { + this.key = matBytes.readUTF(); + let { t, v } = ValueParser.parser(matBytes); + this.type = t; + this._data = v; + } +} + diff --git a/src/loader/parser/prefab/prefabData/PrefabAvatarData.ts b/src/loader/parser/prefab/prefabData/PrefabAvatarData.ts new file mode 100644 index 00000000..3d26d0b6 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabAvatarData.ts @@ -0,0 +1,23 @@ +import { BytesArray } from "../../../../util/BytesArray"; +import { PrefabBoneData } from "./PrefabBoneData"; + +export class PrefabAvatarData { + public name: string; + public count: number; + public boneData: PrefabBoneData[]; + public boneMap: Map; + public formBytes(bytes: BytesArray) { + this.boneData = []; + this.boneMap = new Map(); + + this.name = bytes.readUTF(); + this.count = bytes.readInt32(); + for (let i = 0; i < this.count; i++) { + let boneData = new PrefabBoneData(); + boneData.formBytes(bytes.readBytesArray()); + this.boneData[i] = boneData; + + this.boneMap.set(boneData.boneName, boneData); + } + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabBoneData.ts b/src/loader/parser/prefab/prefabData/PrefabBoneData.ts new file mode 100644 index 00000000..75a1269f --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabBoneData.ts @@ -0,0 +1,32 @@ +import { Quaternion } from "../../../../math/Quaternion"; +import { Vector3 } from "../../../../math/Vector3"; +import { BytesArray } from "../../../../util/BytesArray"; + +export class PrefabBoneData { + public boneName: string; + public bonePath: string; + public parentBoneName: string; + public boneID: number; + public parentBoneID: number; + public instanceID: string; + public parentInstanceID: string; + public t: Vector3; + public q: Quaternion; + public s: Vector3; + + public formBytes(bytes: BytesArray) { + this.boneName = bytes.readUTF(); + this.bonePath = bytes.readUTF(); + this.parentBoneName = bytes.readUTF(); + + this.boneID = bytes.readInt32(); + this.parentBoneID = bytes.readInt32(); + + this.instanceID = bytes.readUTF(); + this.parentInstanceID = bytes.readUTF(); + + this.t = bytes.readVector3(); + this.q = bytes.readQuaternion(); + this.s = bytes.readVector3(); + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabMeshData.ts b/src/loader/parser/prefab/prefabData/PrefabMeshData.ts new file mode 100644 index 00000000..3ddee497 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabMeshData.ts @@ -0,0 +1,18 @@ +import { Matrix4 } from "../../../.."; +import { BlendShapeData } from "./BlendShapeData"; + +export class PrefabMeshData { + public name: string; + public meshName: string; + public meshID: string; + public vertexCount: number; + public vertexStrip: number; + public vertexBuffer: Float32Array; + public indices: Uint16Array | Uint32Array; + + public attributes: { attribute: string, dim: number, pos: number }[]; + + public bones: string[]; + public bindPose: Matrix4[]; + public blendShapeData: BlendShapeData; +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabNode.ts b/src/loader/parser/prefab/prefabData/PrefabNode.ts new file mode 100644 index 00000000..ab4e23ec --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabNode.ts @@ -0,0 +1,67 @@ +import { Quaternion } from "../../../../math/Quaternion"; +import { Vector3 } from "../../../../math/Vector3"; +import { BytesArray } from "../../../../util/BytesArray"; +import { KV } from "./KVData"; + +export class ComData { + comName: string; + data: KV[]; + + public static parser(bytesArray: BytesArray): ComData { + let comBuffer = bytesArray.readBytesArray(); + + let comData = new ComData(); + comData.comName = comBuffer.readUTF(); + comData.data = []; + + let count = comBuffer.readInt32(); + for (let i = 0; i < count; i++) { + let kv = new KV(); + kv.formBytes(comBuffer); + comData.data.push(kv); + } + return comData; + } +} + +export class PrefabNode { + name: string; + + parentName: string; + + position: Vector3; + + rotation: Quaternion; + + scale: Vector3; + + comDatas: ComData[]; + + child: PrefabNode[]; + + public static parser(bytesArray: BytesArray) { + let nodeBytes = bytesArray.readBytesArray(); + + let prefabNode = new PrefabNode(); + prefabNode.name = nodeBytes.readUTF(); + prefabNode.parentName = nodeBytes.readUTF(); + prefabNode.position = nodeBytes.readVector3(); + prefabNode.rotation = nodeBytes.readQuaternion(); + prefabNode.scale = nodeBytes.readVector3(); + prefabNode.comDatas = []; + prefabNode.child = []; + + let comCount = nodeBytes.readInt32(); + for (let i = 0; i < comCount; i++) { + const comData = ComData.parser(nodeBytes); + prefabNode.comDatas.push(comData); + } + + let childCount = nodeBytes.readInt32(); + for (let i = 0; i < childCount; i++) { + const childNodeData = PrefabNode.parser(nodeBytes); + prefabNode.child.push(childNodeData); + } + return prefabNode; + } +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/PrefabTextureData.ts b/src/loader/parser/prefab/prefabData/PrefabTextureData.ts new file mode 100644 index 00000000..f3541ce0 --- /dev/null +++ b/src/loader/parser/prefab/prefabData/PrefabTextureData.ts @@ -0,0 +1,16 @@ +import { BitmapTexture2D, Vector2 } from "../../../.."; + +export class PrefabTextureData { + + public property: string; + public name: string; + public texture: BitmapTexture2D; + public texelSize: Vector2; + public wrapModeU: number; + public wrapModeV: number; + public wrapModeW: number; + public wrapMode: number; + public anisoLevel: number; + public dimension: number; + public filterMode: number; +} \ No newline at end of file diff --git a/src/loader/parser/prefab/prefabData/ValueParser.ts b/src/loader/parser/prefab/prefabData/ValueParser.ts new file mode 100644 index 00000000..9f96623a --- /dev/null +++ b/src/loader/parser/prefab/prefabData/ValueParser.ts @@ -0,0 +1,135 @@ +import { GeometryBase, Material, PropertyAnimationClip, Texture } from "../../../.."; +import { Engine3D } from "../../../../Engine3D"; +import { Joint } from "../../../../components/anim/skeletonAnim/Joint"; +import { Skeleton } from "../../../../components/anim/skeletonAnim/Skeleton"; +import { Color } from "../../../../math/Color"; +import { Quaternion } from "../../../../math/Quaternion"; +import { Vector2 } from "../../../../math/Vector2"; +import { Vector3 } from "../../../../math/Vector3"; +import { Vector4 } from "../../../../math/Vector4"; +import { BytesArray } from "../../../../util/BytesArray"; +import { ValueEnumType } from "./ValueType"; + +export type CurveValueType = string | number | Vector2 | Vector3 | Vector4 | Quaternion | Color | boolean | Texture | Material | string[] | number[] | Float32Array | GeometryBase | Skeleton | PropertyAnimationClip[]; + +export class ValueParser { + public static parser(bytes: BytesArray): { t: ValueEnumType, v: CurveValueType } { + let type = bytes.readInt32(); + switch (type) { + case ValueEnumType.single: + return { t: ValueEnumType.single, v: bytes.readFloat32() }; + case ValueEnumType.boolean: + return { t: ValueEnumType.boolean, v: bytes.readBoolean() }; + case ValueEnumType.int: + return { t: ValueEnumType.int, v: bytes.readInt32() }; + case ValueEnumType.int16: + return { t: ValueEnumType.int16, v: bytes.readInt16() }; + case ValueEnumType.int32: + return { t: ValueEnumType.int32, v: bytes.readInt32() }; + case ValueEnumType.float: + return { t: ValueEnumType.float, v: bytes.readFloat32() }; + case ValueEnumType.long: + return { t: ValueEnumType.long, v: bytes.readFloat64() }; + case ValueEnumType.uint: + return { t: ValueEnumType.uint, v: bytes.readUnit32() }; + case ValueEnumType.uint32: + return { t: ValueEnumType.uint32, v: bytes.readUnit32() }; + case ValueEnumType.uint64: + return { t: ValueEnumType.uint64, v: bytes.readUnit32() }; + case ValueEnumType.double: + return { t: ValueEnumType.double, v: bytes.readFloat64() }; + case ValueEnumType.string: + return { t: ValueEnumType.string, v: bytes.readUTF() }; + case ValueEnumType.singleArray: + return { t: ValueEnumType.singleArray, v: bytes.readFloatArray() }; + case ValueEnumType.stringArray: + return { t: ValueEnumType.stringArray, v: bytes.readStringArray() }; + case ValueEnumType.floatArray: + return { t: ValueEnumType.floatArray, v: bytes.readFloatArray() }; + case ValueEnumType.vector2: + return { t: ValueEnumType.vector2, v: bytes.readVector2() }; + case ValueEnumType.vector3: + return { t: ValueEnumType.vector3, v: bytes.readVector3() }; + case ValueEnumType.vector4: + return { t: ValueEnumType.vector4, v: bytes.readVector4() }; + case ValueEnumType.color: + return { t: ValueEnumType.color, v: bytes.readColor() }; + case ValueEnumType.color32: + return { t: ValueEnumType.color32, v: bytes.readColor() }; + case ValueEnumType.animationCurve: + return { t: ValueEnumType.animationCurve, v: null } + case ValueEnumType.quaternion: + return { t: ValueEnumType.quaternion, v: bytes.readQuaternion() }; + case ValueEnumType.matrix4x4: + return { t: ValueEnumType.matrix4x4, v: null }; + case ValueEnumType.mesh: + { + let id = bytes.readUTF(); + let mesh = Engine3D.res.getGeometry(id); + return { t: ValueEnumType.mesh, v: mesh }; + } + case ValueEnumType.texture: + { + let id = bytes.readUTF(); + let texture = Engine3D.res.getTexture(id); + return { t: ValueEnumType.texture, v: texture }; + } + case ValueEnumType.material: + { + let id = bytes.readUTF(); + let mat = Engine3D.res.getMat(id); + return { t: ValueEnumType.material, v: mat }; + } + case ValueEnumType.materials: + { + let str = bytes.readStringArray(); + let mats = []; + for (let i = 0; i < str.length; i++) { + const element = str[i]; + let mat = Engine3D.res.getMat(element); + mats.push(mat); + } + return { t: ValueEnumType.materials, v: mats }; + } + + case ValueEnumType.skeleton: + break; + case ValueEnumType.animClip: + { + let animClipDatas: PropertyAnimationClip[] = []; + let animClipCount = bytes.readInt32(); + for (let i = 0; i < animClipCount; i++) { + let animationClipData = new PropertyAnimationClip(); + animationClipData.formBytes(bytes); + animClipDatas.push(animationClipData); + } + return { t: ValueEnumType.animClip, v: animClipDatas }; + } + case ValueEnumType.vector2Int: + return { t: ValueEnumType.vector2Int, v: bytes.readVector2int() }; + break; + case ValueEnumType.int32List: + return { t: ValueEnumType.int32List, v: bytes.readInt32List() }; + break; + case ValueEnumType.colorList: + let len = bytes.readInt32(); + let list = [] ; + for (let i = 0; i < len ; i++) { + const element = ValueParser.parser(bytes).v as Color; + list.push(element); + } + return { t: ValueEnumType.colorList, v: list }; + break; + case ValueEnumType.color32List: + let len2 = bytes.readInt32(); + let list2 = [] ; + for (let i = 0; i < len2 ; i++) { + const element = ValueParser.parser(bytes).v as Color; + list2.push(element); + } + return { t: ValueEnumType.color32List, v: list2 }; + break; + } + } + +} diff --git a/src/loader/parser/prefab/prefabData/ValueType.ts b/src/loader/parser/prefab/prefabData/ValueType.ts new file mode 100644 index 00000000..d8e85d8f --- /dev/null +++ b/src/loader/parser/prefab/prefabData/ValueType.ts @@ -0,0 +1,37 @@ + + +export enum ValueEnumType { + single, + boolean, + int, + int16, + int32, + float, + long, + uint, + uint32, + uint64, + double, + string, + singleArray, + stringArray, + floatArray, + vector2, + vector3, + vector4, + color, + color32, + animationCurve, + quaternion, + matrix4x4, + mesh, + texture, + material, + materials, + skeleton, + animClip, + vector2Int, + int32List, + colorList, + color32List, +} \ No newline at end of file diff --git a/src/materials/BlendMode.ts b/src/materials/BlendMode.ts index 880fb13e..9806770f 100644 --- a/src/materials/BlendMode.ts +++ b/src/materials/BlendMode.ts @@ -124,9 +124,9 @@ export class BlendFactor { blend.color.operation = 'add'; break; case BlendMode.NORMAL: - blend.color.srcFactor = 'one'; - blend.color.dstFactor = 'one-minus-src-alpha'; - blend.color.operation = 'add'; + blend.color.srcFactor = `src-alpha`; + blend.color.dstFactor = `one-minus-src-alpha`; + blend.color.operation = `add`; break; case BlendMode.SOFT_ADD: blend.color.srcFactor = `one`; diff --git a/src/materials/ColorLitMaterial.ts b/src/materials/ColorLitMaterial.ts index 455edf54..7311568f 100644 --- a/src/materials/ColorLitMaterial.ts +++ b/src/materials/ColorLitMaterial.ts @@ -1,15 +1,14 @@ -import { RenderShader } from '..'; +import { Material, RenderShaderPass, PassType, Shader } from '..'; import { Engine3D } from '../Engine3D'; import { ShaderLib } from '../assets/shader/ShaderLib'; import { ColorLitShader } from '../assets/shader/materials/ColorLitShader'; import { Color } from '../math/Color'; -import { PhysicMaterial } from './PhysicMaterial'; /** * ColorLitMaterial * @group Material */ -export class ColorLitMaterial extends PhysicMaterial { +export class ColorLitMaterial extends Material { static count = 0; /** * @constructor @@ -17,9 +16,13 @@ export class ColorLitMaterial extends PhysicMaterial { constructor() { super(); - ShaderLib.register("ColorLitShader", ColorLitShader.Ori_AllShader); + ShaderLib.register("ColorLitShader", ColorLitShader); + + this.shader = new Shader() + let renderShader = new RenderShaderPass(`ColorLitShader`, `ColorLitShader`); + renderShader.passType = PassType.COLOR; + this.shader.addRenderPass(renderShader); - let renderShader = new RenderShader(`ColorLitShader`, `ColorLitShader`); renderShader.setDefine("USE_BRDF", true); renderShader.setShaderEntry(`VertMain`, `FragMain`) renderShader.setUniformColor(`baseColor`, new Color()); diff --git a/src/materials/GIProbeMaterial.ts b/src/materials/GIProbeMaterial.ts index 7e7cd1ff..54a60274 100644 --- a/src/materials/GIProbeMaterial.ts +++ b/src/materials/GIProbeMaterial.ts @@ -1,9 +1,10 @@ -import { RenderShader } from '..'; +import { PassType, Shader } from '..'; import { GIProbeShader } from '../assets/shader/materials/GIProbeShader'; import { ShaderLib } from '../assets/shader/ShaderLib'; import { Engine3D } from '../Engine3D'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; import { Vector4 } from '../math/Vector4'; -import { PhysicMaterial } from './PhysicMaterial'; +import { Material } from './Material'; /** * @internal @@ -16,36 +17,34 @@ export enum GIProbeMaterialType { Other = 3, } -export class GIProbeMaterial extends PhysicMaterial { +export class GIProbeMaterial extends Material { static count = 0; constructor(type: GIProbeMaterialType = GIProbeMaterialType.CastGI, index: number = 0) { super(); ShaderLib.register("GIProbeShader", GIProbeShader); - this.defaultPass = new RenderShader('GIProbeShader', 'GIProbeShader'); + let newShader = new Shader(); - this.defaultPass.setDefine('USE_BRDF', true); - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`); - this.defaultPass.setUniformVector4('probeUniform', new Vector4(index, type, 0, 0)); - let shaderState = this.defaultPass.shaderState; + let colorShader = new RenderShaderPass('GIProbeShader', 'GIProbeShader'); + colorShader.passType = PassType.COLOR; + newShader.addRenderPass(colorShader); + + colorShader.setDefine('USE_BRDF', true); + colorShader.setShaderEntry(`VertMain`, `FragMain`); + colorShader.setUniformVector4('probeUniform', new Vector4(index, type, 0, 0)); + let shaderState = colorShader.shaderState; shaderState.acceptShadow = false; shaderState.castShadow = false; shaderState.receiveEnv = false; shaderState.acceptGI = false; shaderState.useLight = false; - let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); - this.brdfLUT = bdrflutTex; + newShader.setTexture("baseMap", Engine3D.res.whiteTexture); + newShader.setTexture("normalMap", Engine3D.res.normalTexture); + newShader.setTexture("emissiveMap", Engine3D.res.blackTexture); - this.baseMap = Engine3D.res.whiteTexture; - this.normalMap = Engine3D.res.normalTexture; - // this.aoMap = defaultTexture.whiteTexture; - // this.maskMap = defaultTexture.maskTexture; - // this.maskMap = defaultTexture.grayTexture; - // shader.setDefine(`USE_ARMC`, false); - this.emissiveMap = Engine3D.res.blackTexture; + this.shader = newShader; } - debug() { } } diff --git a/src/materials/GlassMaterial.ts b/src/materials/GlassMaterial.ts index 477b9468..f4388a84 100644 --- a/src/materials/GlassMaterial.ts +++ b/src/materials/GlassMaterial.ts @@ -1,16 +1,17 @@ import { ShaderLib } from '../assets/shader/ShaderLib'; import { Engine3D } from '../Engine3D'; -import { Vector4 } from '../math/Vector4'; - -import { registerMaterial } from './MaterialRegister'; import { GlassShader } from '../assets/shader/materials/GlassShader'; -import { Material, PhysicMaterial, RenderShader } from '..'; +import { Material } from './Material'; +import { Shader } from '../gfx/graphics/webGpu/shader/Shader'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; + /** * GlassMaterial * an rendering material implemented by simulating glass surfaces * @group Material */ -export class GlassMaterial extends PhysicMaterial { +export class GlassMaterial extends Material { /** * @constructor @@ -18,63 +19,55 @@ export class GlassMaterial extends PhysicMaterial { constructor() { super(); ShaderLib.register("GlassShader", GlassShader); - let colorPass = new RenderShader('GlassShader', 'GlassShader'); - this.defaultPass = colorPass; - colorPass.setDefine("USE_BRDF", true); - colorPass.setShaderEntry(`VertMain`, `FragMain`) + this.shader = new Shader(); - let shaderState = colorPass.shaderState; + let colorShader = new RenderShaderPass('GlassShader', 'GlassShader'); + colorShader.passType = PassType.COLOR; + colorShader.setDefine("USE_BRDF", true); + colorShader.setShaderEntry(`VertMain`, `FragMain`) + + let shaderState = colorShader.shaderState; shaderState.acceptShadow = true; shaderState.castShadow = true; shaderState.receiveEnv = true; shaderState.acceptGI = true; shaderState.useLight = true; - let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); - this.brdfLUT = bdrflutTex; - - this.baseMap = Engine3D.res.whiteTexture; - this.normalMap = Engine3D.res.normalTexture; - // this.aoMap = defaultTexture.whiteTexture; - // this.maskMap = defaultTexture.maskTexture; - // this.maskMap = defaultTexture.grayTexture; - // shader.setDefine(`USE_ARMC`, false); - this.emissiveMap = Engine3D.res.blackTexture; - + this.shader.setTexture("baseMap", Engine3D.res.whiteTexture); + this.shader.setTexture("normalMap", Engine3D.res.normalTexture); + this.shader.setTexture("emissiveMap", Engine3D.res.blackTexture); } - clone(): this { - console.log(`clone material ${this.name}`); + // clone(): this { + // console.log(`clone material ${this.name}`); - let ret = new GlassMaterial(); - ret.baseMap = this.baseMap; - ret.normalMap = this.normalMap; - ret.aoMap = this.aoMap; - if (this.maskMap) ret.maskMap = this.maskMap; - ret.emissiveMap = this.emissiveMap; - this.uvTransform_1 && (ret.uvTransform_1 = new Vector4().copyFrom(this.uvTransform_1)); - this.uvTransform_2 && (ret.uvTransform_2 = new Vector4().copyFrom(this.uvTransform_2)); - ret.baseColor = this.baseColor.clone(); - ret.emissiveColor = this.emissiveColor.clone(); - this.materialF0 && (ret.materialF0 = new Vector4().copyFrom(this.materialF0)); - ret.envIntensity = this.envIntensity; - ret.normalScale = this.normalScale; - ret.roughness = this.roughness; - ret.metallic = this.metallic; - ret.ao = this.ao; - ret.roughness_min = this.roughness_min; - ret.roughness_max = this.roughness_max; - ret.metallic_min = this.metallic_min; - ret.metallic_max = this.metallic_max; - ret.emissiveIntensity = this.emissiveIntensity; - ret.alphaCutoff = this.alphaCutoff; - ret.ior = this.ior; - ret.clearcoatFactor = this.clearcoatFactor; - ret.clearcoatRoughnessFactor = this.clearcoatRoughnessFactor; - return ret as this; - } + // let ret = new GlassMaterial(); + // ret.baseMap = this.baseMap; + // ret.normalMap = this.normalMap; + // ret.aoMap = this.aoMap; + // if (this.maskMap) ret.maskMap = this.maskMap; + // ret.emissiveMap = this.emissiveMap; + // this.uvTransform_1 && (ret.uvTransform_1 = new Vector4().copyFrom(this.uvTransform_1)); + // this.uvTransform_2 && (ret.uvTransform_2 = new Vector4().copyFrom(this.uvTransform_2)); + // ret.baseColor = this.baseColor.clone(); + // ret.emissiveColor = this.emissiveColor.clone(); + // this.materialF0 && (ret.materialF0 = new Vector4().copyFrom(this.materialF0)); + // ret.envIntensity = this.envIntensity; + // ret.normalScale = this.normalScale; + // ret.roughness = this.roughness; + // ret.metallic = this.metallic; + // ret.ao = this.ao; + // ret.roughness_min = this.roughness_min; + // ret.roughness_max = this.roughness_max; + // ret.metallic_min = this.metallic_min; + // ret.metallic_max = this.metallic_max; + // ret.emissiveIntensity = this.emissiveIntensity; + // ret.alphaCutoff = this.alphaCutoff; + // ret.ior = this.ior; + // ret.clearcoatFactor = this.clearcoatFactor; + // ret.clearcoatRoughnessFactor = this.clearcoatRoughnessFactor; + // return ret as this; + // } } - -registerMaterial('GlassMaterial', GlassMaterial); \ No newline at end of file diff --git a/src/materials/LambertMaterial.ts b/src/materials/LambertMaterial.ts index a82ed9f3..a0f6c4ab 100644 --- a/src/materials/LambertMaterial.ts +++ b/src/materials/LambertMaterial.ts @@ -1,12 +1,11 @@ -import { LambertShader, Material, RendererType, RenderShader } from '..'; +import { Lambert_shader, Material, PassType, RenderShaderPass, Shader } from '..'; import { ShaderLib } from '../assets/shader/ShaderLib'; import { Engine3D } from '../Engine3D'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; import { Color } from '../math/Color'; import { Vector4 } from '../math/Vector4'; -import { registerMaterial } from "./MaterialRegister"; /** * Lambert Mateiral @@ -19,13 +18,14 @@ export class LambertMaterial extends Material { */ constructor() { super(); - let colorPass = new RenderShader(`LambertShader`, `LambertShader`); + let colorPass = new RenderShaderPass(`LambertShader`, `LambertShader`); colorPass.setShaderEntry(`VertMain`, `FragMain`) - + colorPass.passType = PassType.COLOR; colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); colorPass.setUniformColor(`baseColor`, new Color(1, 1, 1, 1)); colorPass.setUniformFloat(`alphaCutoff`, 0.5); + let shaderState = colorPass.shaderState; shaderState.acceptShadow = false; shaderState.castShadow = false; @@ -33,46 +33,38 @@ export class LambertMaterial extends Material { shaderState.acceptGI = false; shaderState.useLight = false; - // let shaderState = shader.shaderState; - // shaderState.acceptShadow = true; - // shaderState.castShadow = true; - // shaderState.receiveEnv = false; - // shaderState.acceptGI = false; - // shaderState.useLight = true; - - // default value - // this.baseMap = Engine3D.res.whiteTexture; - // this.emissiveMap = Engine3D.res.blackTexture; - this.defaultPass = colorPass; + let newShader = new Shader(); + newShader.addRenderPass(colorPass); + this.shader = newShader; this.baseMap = Engine3D.res.grayTexture; } /** * set base color map texture */ - set baseMap(tex: Texture) { - this.defaultPass.setTexture(`baseMap`, tex); + public set baseMap(tex: Texture) { + this.shader.setTexture(`baseMap`, tex); } /** * get base color map texture */ - get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + public get baseMap() { + return this.shader.getTexture(`baseMap`); } /** * set base color (tint color) */ - set baseColor(color: Color) { - this.defaultPass.setUniformColor(`baseColor`, color); + public set baseColor(color: Color) { + this.shader.setUniformColor(`baseColor`, color); } /** * get base color (tint color) */ - get baseColor() { - return this.defaultPass.uniforms[`baseColor`].color; + public get baseColor() { + return this.shader.getUniformColor("baseColor"); } /** @@ -89,5 +81,4 @@ export class LambertMaterial extends Material { public set shadowMap(texture: Texture) { //not need shadowMap texture } - } \ No newline at end of file diff --git a/src/materials/LitMaterial.ts b/src/materials/LitMaterial.ts index 1e0bc92c..1a15c7be 100644 --- a/src/materials/LitMaterial.ts +++ b/src/materials/LitMaterial.ts @@ -1,69 +1,158 @@ -import { Material } from ".."; import { Engine3D } from "../Engine3D"; -import { RenderShader } from "../gfx/graphics/webGpu/shader/RenderShader"; -import { RendererType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { StandShader } from "../loader/parser/prefab/mats/shader/StandShader"; +import { Color } from "../math/Color"; +import { Material } from "./Material"; import { PhysicMaterial } from "./PhysicMaterial"; -export class LitMaterial extends PhysicMaterial { +export class LitMaterial extends Material { + constructor() { super(); - let colorPass = new RenderShader('PBRLItShader', 'PBRLItShader'); - this.defaultPass = colorPass; + let shader = new StandShader(); + this.shader = shader; + } - colorPass.setShaderEntry(`VertMain`, `FragMain`) - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = true; - shaderState.castShadow = true; - shaderState.receiveEnv = true; - shaderState.acceptGI = true; - shaderState.useLight = true; + public clone(): Material { + let litMaterial = new LitMaterial(); - let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); - this.brdfLUT = bdrflutTex; - colorPass.setDefine('USE_BRDF', true); + let colorPass = litMaterial.shader.getDefaultColorShader(); + let sourceShader = this.shader.getDefaultColorShader(); + colorPass.defineValue = { ...sourceShader.defineValue } + colorPass.setUniform(`shadowBias`, sourceShader.getUniform(`shadowBias`)); + colorPass.setUniform(`transformUV1`, sourceShader.getUniform(`transformUV1`)); + colorPass.setUniform(`transformUV2`, sourceShader.getUniform(`transformUV2`)); + colorPass.setUniform(`baseColor`, sourceShader.getUniform(`baseColor`)); + colorPass.setUniform(`specularColor`, sourceShader.getUniform(`specularColor`)); + colorPass.setUniform(`emissiveColor`, sourceShader.getUniform(`emissiveColor`)); + colorPass.setUniform(`materialF0`, sourceShader.getUniform(`materialF0`)); + colorPass.setUniform(`envIntensity`, sourceShader.getUniform(`envIntensity`)); + colorPass.setUniform(`normalScale`, sourceShader.getUniform(`normalScale`)); + colorPass.setUniform(`roughness`, sourceShader.getUniform(`roughness`)); + colorPass.setUniform(`metallic`, sourceShader.getUniform(`metallic`)); + colorPass.setUniform(`ao`, sourceShader.getUniform(`ao`)); + colorPass.setUniform(`roughness_min`, sourceShader.getUniform(`roughness_min`)); + colorPass.setUniform(`roughness_max`, sourceShader.getUniform(`roughness_max`)); + colorPass.setUniform(`metallic_min`, sourceShader.getUniform(`metallic_min`)); + colorPass.setUniform(`metallic_max`, sourceShader.getUniform(`metallic_max`)); + colorPass.setUniform(`emissiveIntensity`, sourceShader.getUniform(`emissiveIntensity`)); + colorPass.setUniform(`alphaCutoff`, sourceShader.getUniform(`alphaCutoff`)); + colorPass.setUniform(`ior`, sourceShader.getUniform(`ior`)); + colorPass.setUniform(`clearcoatFactor`, sourceShader.getUniform(`clearcoatFactor`)); + colorPass.setUniform(`clearcoatRoughnessFactor`, sourceShader.getUniform(`clearcoatRoughnessFactor`)); + colorPass.setUniform(`clearcoatColor`, sourceShader.getUniform(`clearcoatColor`)); + colorPass.setUniform(`clearcoatWeight`, sourceShader.getUniform(`clearcoatWeight`)); - this.setDefault(); + colorPass.setTexture(`baseMap`, sourceShader.getTexture(`baseMap`)); + colorPass.setTexture(`normalMap`, sourceShader.getTexture(`normalMap`)); + colorPass.setTexture(`emissiveMap`, sourceShader.getTexture(`emissiveMap`)); + colorPass.setTexture(`aoMap`, sourceShader.getTexture(`aoMap`)); + colorPass.setTexture(`maskMap`, sourceShader.getTexture(`maskMap`)); + return litMaterial; + } - this.baseMap = Engine3D.res.whiteTexture; - this.normalMap = Engine3D.res.normalTexture; - this.emissiveMap = Engine3D.res.blackTexture; + public set baseMap(texture: Texture) { + this.shader.setTexture(`baseMap`, texture); + } - this.alphaCutoff = 0.5; + public get baseMap() { + return this.shader.getTexture(`baseMap`); } - public clone(): Material { - let litMaterial = new LitMaterial(); + public set maskMap(texture: Texture) { + this.shader.setTexture(`maskMap`, texture); + } - let colorPass = litMaterial.defaultPass; - colorPass.setUniform(`shadowBias`, this.defaultPass.getUniform(`shadowBias`)); - colorPass.setUniform(`transformUV1`, this.defaultPass.getUniform(`transformUV1`)); - colorPass.setUniform(`transformUV2`, this.defaultPass.getUniform(`transformUV2`)); - colorPass.setUniform(`baseColor`, this.defaultPass.getUniform(`baseColor`)); - colorPass.setUniform(`emissiveColor`, this.defaultPass.getUniform(`emissiveColor`)); - colorPass.setUniform(`materialF0`, this.defaultPass.getUniform(`materialF0`)); - colorPass.setUniform(`envIntensity`, this.defaultPass.getUniform(`envIntensity`)); - colorPass.setUniform(`normalScale`, this.defaultPass.getUniform(`normalScale`)); - colorPass.setUniform(`roughness`, this.defaultPass.getUniform(`roughness`)); - colorPass.setUniform(`metallic`, this.defaultPass.getUniform(`metallic`)); - colorPass.setUniform(`ao`, this.defaultPass.getUniform(`ao`)); - colorPass.setUniform(`roughness_min`, this.defaultPass.getUniform(`roughness_min`)); - colorPass.setUniform(`roughness_max`, this.defaultPass.getUniform(`roughness_max`)); - colorPass.setUniform(`metallic_min`, this.defaultPass.getUniform(`metallic_min`)); - colorPass.setUniform(`metallic_max`, this.defaultPass.getUniform(`metallic_max`)); - colorPass.setUniform(`emissiveIntensity`, this.defaultPass.getUniform(`emissiveIntensity`)); - colorPass.setUniform(`alphaCutoff`, this.defaultPass.getUniform(`alphaCutoff`)); - colorPass.setUniform(`ior`, this.defaultPass.getUniform(`ior`)); - colorPass.setUniform(`clearcoatFactor`, this.defaultPass.getUniform(`clearcoatFactor`)); - colorPass.setUniform(`clearcoatRoughnessFactor`, this.defaultPass.getUniform(`clearcoatRoughnessFactor`)); - colorPass.setUniform(`clearcoatColor`, this.defaultPass.getUniform(`clearcoatColor`)); - colorPass.setUniform(`clearcoatWeight`, this.defaultPass.getUniform(`clearcoatWeight`)); - - colorPass.setTexture(`baseMap`, this.defaultPass.getTexture(`baseMap`)); - colorPass.setTexture(`normalMap`, this.defaultPass.getTexture(`normalMap`)); - colorPass.setTexture(`emissiveMap`, this.defaultPass.getTexture(`emissiveMap`)); - colorPass.setTexture(`aoMap`, this.defaultPass.getTexture(`aoMap`)); - colorPass.setTexture(`maskMap`, this.defaultPass.getTexture(`maskMap`)); - return litMaterial; + public get maskMap() { + return this.shader.getTexture(`maskMap`); + } + + + public set normalMap(texture: Texture) { + this.shader.setTexture(`normalMap`, texture); + } + + public get normalMap() { + return this.shader.getTexture(`normalMap`); + } + + public set emissiveMap(texture: Texture) { + this.shader.setTexture(`emissiveMap`, texture); + } + + public get emissiveMap() { + return this.shader.getTexture(`emissiveMap`); + } + + public set aoMap(texture: Texture) { + this.shader.setTexture(`aoMap`, texture); + } + + public get aoMap() { + return this.shader.getTexture(`aoMap`); + } + + public set alphaCutoff(value: number) { + this.shader.setUniform(`alphaCutoff`, value); + } + + public get alphaCutoff() { + return this.shader.getUniform(`alphaCutoff`); + } + + /** + * set base color (tint color) + */ + public set baseColor(color: Color) { + this.shader.setUniformColor(`baseColor`, color); + } + + /** + * get base color (tint color) + */ + public get baseColor() { + return this.shader.getUniformColor("baseColor"); + } + + public get roughness(): number { + return this.shader.getUniformFloat("roughness"); + } + + public set roughness(value: number) { + this.shader.setUniformFloat("roughness", value); + } + + public get metallic(): number { + return this.shader.getUniformFloat("metallic"); + } + + public set metallic(value: number) { + this.shader.setUniformFloat("metallic", value); + } + + public get emissiveColor(): Color { + return this.shader.getUniformColor("emissiveColor"); + } + + public set emissiveColor(value: Color) { + this.shader.setUniformColor("emissiveColor", value); + } + + public get emissiveIntensity(): number { + return this.shader.getUniformFloat("emissiveIntensity"); + } + + public set emissiveIntensity(value: number) { + this.shader.setUniformFloat("emissiveIntensity", value); + } + + public get ao(): number { + return this.shader.getUniform(`ao`); + } + + public set ao(value: number) { + this.shader.setUniform(`ao`, value); } } \ No newline at end of file diff --git a/src/materials/Material.ts b/src/materials/Material.ts index 07c0e0f0..b88ee5dc 100644 --- a/src/materials/Material.ts +++ b/src/materials/Material.ts @@ -1,109 +1,109 @@ -import { BlendMode, GPUCompareFunction } from ".."; -import { RenderShader } from "../gfx/graphics/webGpu/shader/RenderShader"; -import { RendererType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { StorageGPUBuffer } from "../gfx/graphics/webGpu/core/buffer/StorageGPUBuffer"; +import { UniformGPUBuffer } from "../gfx/graphics/webGpu/core/buffer/UniformGPUBuffer"; +import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; +import { RenderShaderPass } from "../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { PassType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { Shader } from "../gfx/graphics/webGpu/shader/Shader"; +import { Color } from "../math/Color"; +import { Vector2 } from "../math/Vector2"; +import { Vector3 } from "../math/Vector3"; +import { Vector4 } from "../math/Vector4"; +import { BlendMode } from "./BlendMode"; export class Material { - /** - * - * name of this material - */ - public name: string; - /** * * Material Unique Identifier */ public instanceID: string; - public enable: boolean = true; + /** + * + * name of this material + */ + public name: string; - private _defaultPass: RenderShader; + public enable: boolean = true; - private _renderPasses: Map; + private _defaultSubShader: RenderShaderPass; - private _depthCompare: GPUCompareFunction = GPUCompareFunction.less; + protected _shader: Shader; constructor() { - this._renderPasses = new Map(); - } - - public get depthCompare(): GPUCompareFunction { - return this._depthCompare; } - public set depthCompare(value: GPUCompareFunction) { - this._depthCompare = value; - this._defaultPass.depthCompare = value; - } - - public get defaultPass(): RenderShader { - return this._defaultPass; + public set shader(shader: Shader) { + this._shader = shader; + this._defaultSubShader = shader.getDefaultShaders()[0]; } - public set defaultPass(value: RenderShader) { - this._defaultPass = value; - this.addPass(RendererType.COLOR, value); + public get shader(): Shader { + return this._shader; } public get doubleSide(): boolean { - return this._defaultPass.doubleSide; + return this._defaultSubShader.doubleSide; } public set doubleSide(value: boolean) { - this._defaultPass.doubleSide = value; + this._defaultSubShader.doubleSide = value; } public get castShadow(): boolean { - let colorPass = this.defaultPass; - return colorPass.shaderState.castShadow; + return this._defaultSubShader.shaderState.castShadow; } public set castShadow(value: boolean) { - let colorPass = this.defaultPass; - colorPass.shaderState.castShadow = value; + this._defaultSubShader.shaderState.castShadow = value; } public get blendMode(): BlendMode { - let colorPass = this.defaultPass; - return colorPass.blendMode; + return this._defaultSubShader.blendMode; } public set blendMode(value: BlendMode) { - let colorPass = this.defaultPass; - colorPass.blendMode = value; + this._defaultSubShader.blendMode = value; + } + + public get depthCompare(): GPUCompareFunction { + return this._defaultSubShader.depthCompare; + } + + public set depthCompare(value: GPUCompareFunction) { + this._defaultSubShader.depthCompare = value; } public get transparent(): boolean { - let colorPass = this.defaultPass; - return colorPass.shaderState.transparent; + return this._defaultSubShader.shaderState.transparent; } public set transparent(value: boolean) { - let colorPass = this.defaultPass; - colorPass.shaderState.transparent = value; + this._defaultSubShader.shaderState.transparent = value; if (value) { - colorPass.renderOrder = 3000; + this._defaultSubShader.renderOrder = 3000; } } public get cullMode(): GPUCullMode { - let colorPass = this.defaultPass; - return colorPass.cullMode; + return this._defaultSubShader.cullMode; } public set cullMode(value: GPUCullMode) { - let colorPass = this.defaultPass; - colorPass.cullMode = value; + this._defaultSubShader.cullMode = value; } - /** - * @param passType - * @returns - */ - public hasPass(passType: RendererType) { - return this._renderPasses.has(passType); + public get depthWriteEnabled(): boolean { + return this._defaultSubShader.depthWriteEnabled; + } + + public set depthWriteEnabled(value: boolean) { + this._defaultSubShader.depthWriteEnabled = value; + } + + public set useBillboard(value: boolean) { + this._defaultSubShader.setDefine("USE_BILLBOARD", value); } /** @@ -111,44 +111,16 @@ export class Material { * @param passType * @returns */ - public getPass(passType: RendererType) { - return this._renderPasses.get(passType); + public getPass(passType: PassType) { + return this._shader.getSubShaders(passType); } /** * get all color render pass * @returns */ - public getAllPass(): RenderShader[] { - return this._renderPasses.get(RendererType.COLOR); - } - - public addPass(passType: RendererType, pass: RenderShader, index: number = -1): RenderShader[] { - if (!this._renderPasses.has(passType)) this._renderPasses.set(passType, []); - - let passList = this._renderPasses.get(passType); - if (passType == RendererType.COLOR && passList.length == 0) { - this._defaultPass = pass; - } - - let has = passList.indexOf(pass) != -1; - if (!has) { - if (index == -1) { - passList.push(pass); - } else { - passList.splice(index, -1, pass); - } - } - return passList; - } - - public removePass(passType: RendererType, index: number) { - if (this._renderPasses.has(passType)) { - let list = this._renderPasses.get(passType); - if (index < list.length) { - list.splice(index, 1); - } - } + public getAllPass(): RenderShaderPass[] { + return this._shader.getSubShaders(PassType.COLOR); } /** @@ -156,20 +128,92 @@ export class Material { * @returns Material */ public clone() { - return null; + let newMat = new Material(); + newMat.shader = this.shader.clone(); + return newMat; } + destroy(force: boolean) { - for (const iterator of this._renderPasses) { - let passList = iterator[1]; - for (const pass of passList) { - for (const textureName in pass.textures) { - if (textureName.indexOf("defaultOri") == -1) { - let texture = pass.textures[textureName]; - texture.destroy(force); - } - } - } - } + this._shader.destroy(); + this._shader = null; + } + + + public setDefine(define: string, value: boolean) { + this.shader.setDefine(define, value); + } + + public setTexture(propertyName: string, texture: Texture) { + this._shader.setTexture(propertyName, texture); + } + + public setStorageBuffer(propertyName: string, buffer: StorageGPUBuffer) { + this._shader.setStorageBuffer(propertyName, buffer); + } + + public setUniformBuffer(propertyName: string, buffer: UniformGPUBuffer) { + this._shader.setStorageBuffer(propertyName, buffer); + } + + + public setUniformFloat(propertyName: string, value: number) { + this._shader.setUniformFloat(propertyName, value); + } + + public setUniformVector2(propertyName: string, value: Vector2) { + this._shader.setUniformVector2(propertyName, value); + } + + public setUniformVector3(propertyName: string, value: Vector3) { + this._shader.setUniformVector3(propertyName, value); + } + + public setUniformVector4(propertyName: string, value: Vector4) { + this._shader.setUniformVector4(propertyName, value); + } + + public setUniformColor(propertyName: string, value: Color) { + this._shader.setUniformColor(propertyName, value); + } + + public getUniformFloat(str: string) { + return this._shader.getUniform(str).data; + } + + public getUniformV2(str: string): Vector2 { + return this._shader.getUniformVector2(str); + } + + public getUniformV3(str: string): Vector3 { + return this._shader.getUniformVector3(str); + } + + public getUniformV4(str: string): Vector4 { + return this._shader.getUniformVector4(str); + } + + public getUniformColor(str: string) { + return this._shader.getUniformColor(str); + } + + public getTexture(str: string) { + return this._shader.getTexture(str); + } + + public getStorageBuffer(str: string) { + return this._shader.getStorageBuffer(str); + } + + public getStructStorageBuffer(str: string) { + return this._shader.getStructStorageBuffer(str); + } + + public getUniformBuffer(str: string) { + return this._shader.getUniformBuffer(str); + } + + public applyUniform() { + this._shader.applyUniform(); } } \ No newline at end of file diff --git a/src/materials/PhysicMaterial.ts b/src/materials/PhysicMaterial.ts index 06c59757..856a825d 100644 --- a/src/materials/PhysicMaterial.ts +++ b/src/materials/PhysicMaterial.ts @@ -1,7 +1,5 @@ import { Engine3D } from '../Engine3D'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; -import { RenderShader } from '../gfx/graphics/webGpu/shader/RenderShader'; -import { RendererType } from '../gfx/renderJob/passRenderer/state/RendererType'; import { Color } from '../math/Color'; import { Vector4 } from '../math/Vector4'; import { Material } from './Material'; @@ -14,19 +12,36 @@ export class PhysicMaterial extends Material { constructor() { super(); + this.init(); } + private init() { + let bdrflutTex = Engine3D.res.getTexture(`BRDFLUT`); + this.brdfLUT = bdrflutTex; + + this.setDefault(); + this.baseMap = Engine3D.res.whiteTexture; + this.normalMap = Engine3D.res.normalTexture; + this.emissiveMap = Engine3D.res.blackTexture; + this.alphaCutoff = 0.5; + } + + // public get shader(): RenderShader { + // return this._shader; + // } + /** * Set the render shader default value */ public setDefault() { - let colorPass = this.defaultPass; + let colorPass = this.shader.getDefaultColorShader(); colorPass.setUniformFloat(`shadowBias`, 0.00035); colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); colorPass.setUniformColor(`baseColor`, new Color()); colorPass.setUniformColor(`emissiveColor`, new Color(1, 1, 1)); colorPass.setUniformVector4(`materialF0`, new Vector4(0.04, 0.04, 0.04, 1)); + colorPass.setUniformColor(`specularColor`, new Color(0.04, 0.04, 0.04)); colorPass.setUniformFloat(`envIntensity`, 1); colorPass.setUniformFloat(`normalScale`, 1); colorPass.setUniformFloat(`roughness`, 1.0); @@ -47,222 +62,236 @@ export class PhysicMaterial extends Material { public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getDefaultColorShader().getTexture(`baseMap`); } public set baseMap(value: Texture) { - this.defaultPass.setTexture(`baseMap`, value); + this.shader.getDefaultColorShader().setTexture(`baseMap`, value); } public get baseColor(): Color { - return this.defaultPass.getUniform(`baseColor`); + return this.shader.getDefaultColorShader().getUniform(`baseColor`); } public set baseColor(value: Color) { - this.defaultPass.setUniformColor(`baseColor`, value); + this.shader.getDefaultColorShader().setUniformColor(`baseColor`, value); } public get normalMap(): Texture { - return this.defaultPass.getTexture(`normalMap`); + return this.shader.getDefaultColorShader().getTexture(`normalMap`); } public set normalMap(value: Texture) { - this.defaultPass.setTexture(`normalMap`, value); + this.shader.getDefaultColorShader().setTexture(`normalMap`, value); } public get doubleSide(): boolean { - return this.defaultPass.doubleSide; + return this.shader.getDefaultColorShader().doubleSide; } public set doubleSide(value: boolean) { - this.defaultPass.doubleSide = value; + this.shader.getDefaultColorShader().doubleSide = value; } public get alphaCutoff(): any { - return this.defaultPass.shaderState.alphaCutoff; + return this.shader.getDefaultColorShader().shaderState.alphaCutoff; } public set alphaCutoff(value: any) { - this.defaultPass.setDefine("USE_ALPHACUT", true); - this.defaultPass.shaderState.alphaCutoff = value; - this.defaultPass.setUniform(`alphaCutoff`, value); + this.shader.getDefaultColorShader().setDefine("USE_ALPHACUT", true); + this.shader.getDefaultColorShader().shaderState.alphaCutoff = value; + this.shader.getDefaultColorShader().setUniform(`alphaCutoff`, value); } public get emissiveColor(): Color { - return this.defaultPass.getUniform(`emissiveColor`); + return this.shader.getDefaultColorShader().getUniform(`emissiveColor`); } public set emissiveColor(value: Color) { - this.defaultPass.setUniform(`emissiveColor`, value); + this.shader.getDefaultColorShader().setUniform(`emissiveColor`, value); } public get emissiveIntensity(): number { - return this.defaultPass.getUniform(`emissiveIntensity`); + return this.shader.getDefaultColorShader().getUniform(`emissiveIntensity`); } public set emissiveIntensity(value: number) { - this.defaultPass.setUniform(`emissiveIntensity`, value); + this.shader.getDefaultColorShader().setUniform(`emissiveIntensity`, value); } /** * get transformUV1 */ public get uvTransform_1(): Vector4 { - return this.defaultPass.uniforms[`transformUV1`].vector4; + return this.shader.getDefaultColorShader().uniforms[`transformUV1`].vector4; } /** * set transformUV1 */ public set uvTransform_1(value: Vector4) { - // this.defaultPass.uniforms[`transformUV1`].v4 = value; - this.defaultPass.setUniformVector4(`transformUV1`, value); + // this.shader.getDefaultColorShader().uniforms[`transformUV1`].v4 = value; + this.shader.getDefaultColorShader().setUniform(`transformUV1`, value); } /** * get transformUV2 */ public get uvTransform_2(): Vector4 { - return this.defaultPass.uniforms[`transformUV2`].vector4; + return this.shader.getDefaultColorShader().uniforms[`transformUV2`].vector4; } /** * set transformUV2 */ public set uvTransform_2(value: Vector4) { - // this.defaultPass.uniforms[`transformUV2`].v4 = value; - this.defaultPass.setUniformVector4(`transformUV2`, value); + // this.shader.getDefaultColorShader().uniforms[`transformUV2`].v4 = value; + this.shader.getDefaultColorShader().setUniform(`transformUV2`, value); } public get depthWriteEnabled(): boolean { - return this.defaultPass.shaderState.depthWriteEnabled; + return this.shader.getDefaultColorShader().shaderState.depthWriteEnabled; } public set depthWriteEnabled(value: boolean) { - this.defaultPass.shaderState.depthWriteEnabled = value; + this.shader.getDefaultColorShader().shaderState.depthWriteEnabled = value; } /** * get reflectivity */ public get materialF0(): Vector4 { - return this.defaultPass.uniforms[`materialF0`].vector4; + return this.shader.getDefaultColorShader().uniforms[`materialF0`].vector4; } /** * set reflectivity */ public set materialF0(value: Vector4) { - this.defaultPass.setUniformVector4(`materialF0`, value); + this.shader.getDefaultColorShader().setUniform(`materialF0`, value); + } + + /** + * get specularColor + */ + public get specularColor(): Color { + return this.shader.getDefaultColorShader().uniforms[`specularColor`].color; + } + + /**specularColor + * set reflectivity + */ + public set specularColor(value: Color) { + this.shader.getDefaultColorShader().setUniform(`specularColor`, value); } /** * get roughness */ public get roughness(): number { - return this.defaultPass.uniforms[`roughness`].value; + return this.shader.getDefaultColorShader().uniforms[`roughness`].value; } /** * set roughness */ public set roughness(value: number) { - this.defaultPass.setUniformFloat(`roughness`, value); + this.shader.getDefaultColorShader().setUniform(`roughness`, value); } /** * get metallic */ public get metallic(): number { - return this.defaultPass.uniforms[`metallic`].value; + return this.shader.getDefaultColorShader().uniforms[`metallic`].value; } /** * set metallic */ public set metallic(value: number) { - this.defaultPass.setUniformFloat(`metallic`, value); + this.shader.getDefaultColorShader().setUniform(`metallic`, value); } /** * get Ambient Occlussion, dealing with the effect of ambient light on object occlusion */ public get ao(): number { - return this.defaultPass.uniforms[`ao`].value; + return this.shader.getDefaultColorShader().uniforms[`ao`].value; } /** * set Ambient Occlussion, dealing with the effect of ambient light on object occlusion */ public set ao(value: number) { - this.defaultPass.setUniformFloat(`ao`, value); + this.shader.getDefaultColorShader().setUniform(`ao`, value); } /** * get min metallic */ public get metallic_min(): number { - return this.defaultPass.uniforms[`metallic_min`].value; + return this.shader.getDefaultColorShader().uniforms[`metallic_min`].value; } /** * set min metallic */ public set metallic_min(value: number) { - this.defaultPass.setUniformFloat(`metallic_min`, value); + this.shader.getDefaultColorShader().setUniform(`metallic_min`, value); } /** * get max metallic */ public get metallic_max(): number { - return this.defaultPass.uniforms[`metallic_max`].value; + return this.shader.getDefaultColorShader().uniforms[`metallic_max`].value; } /** * set max metallic */ public set metallic_max(value: number) { - this.defaultPass.setUniformFloat(`metallic_max`, value); + this.shader.getDefaultColorShader().setUniform(`metallic_max`, value); } /** * get min roughness */ public get roughness_min(): number { - return this.defaultPass.uniforms[`roughness_min`].value; + return this.shader.getDefaultColorShader().uniforms[`roughness_min`].value; } /** * set min roughness */ public set roughness_min(value: number) { - this.defaultPass.setUniformFloat(`roughness_min`, value); + this.shader.getDefaultColorShader().setUniform(`roughness_min`, value); } /** * get max roughness */ public get roughness_max(): number { - return this.defaultPass.uniforms[`roughness_max`].value; + return this.shader.getDefaultColorShader().uniforms[`roughness_max`].value; } /** * set max roughness */ public set roughness_max(value: number) { - this.defaultPass.setUniformFloat(`roughness_max`, value); + this.shader.getDefaultColorShader().setUniform(`roughness_max`, value); } /** * Get the influence of Normal mapping on materials */ public get normalScale(): number { - return this.defaultPass.uniforms[`normalScale`].value; + return this.shader.getDefaultColorShader().uniforms[`normalScale`].value; } /** * Set the influence of Normal mapping on materials */ public set normalScale(value: number) { - this.defaultPass.setUniformFloat(`normalScale`, value); + this.shader.getDefaultColorShader().setUniform(`normalScale`, value); } /** @@ -273,7 +302,7 @@ export class PhysicMaterial extends Material { * A_chanel -> C */ public get maskMap(): Texture { - return this.defaultPass.textures[`maskMap`]; + return this.shader.getDefaultColorShader().textures[`maskMap`]; } /** @@ -285,9 +314,11 @@ export class PhysicMaterial extends Material { */ public set maskMap(value: Texture) { // USE_MR - // USE_ARMC - this.defaultPass.setDefine(`USE_MR`, true); - this.defaultPass.setTexture(`maskMap`, value); + // USE_ORMC + // USE_RMOC + // USE_CRMC + this.shader.getDefaultColorShader().setDefine(`USE_MR`, true); + this.shader.getDefaultColorShader().setTexture(`maskMap`, value); } /** @@ -295,9 +326,9 @@ export class PhysicMaterial extends Material { */ public set aoMap(value: Texture) { if (!value) return; - this.defaultPass.setTexture(`aoMap`, value); + this.shader.getDefaultColorShader().setTexture(`aoMap`, value); if (value != Engine3D.res.whiteTexture) { - this.defaultPass.setDefine(`USE_AOTEX`, true); + this.shader.getDefaultColorShader().setDefine(`USE_AOTEX`, true); } } @@ -305,7 +336,7 @@ export class PhysicMaterial extends Material { * get Ambient Occlussion Map, dealing with the effect of ambient light on object occlusion */ public get aoMap(): Texture { - return this.defaultPass.textures[`aoMap`]; + return this.shader.getDefaultColorShader().textures[`aoMap`]; } /** @@ -315,86 +346,86 @@ export class PhysicMaterial extends Material { if (!value) return; console.log("USE_CLEARCOAT_ROUGHNESS"); - this.defaultPass.setTexture(`clearCoatRoughnessMap`, value); - this.defaultPass.setDefine(`USE_CLEARCOAT_ROUGHNESS`, true); + this.shader.getDefaultColorShader().setTexture(`clearCoatRoughnessMap`, value); + this.shader.getDefaultColorShader().setDefine(`USE_CLEARCOAT_ROUGHNESS`, true); } /** * get clearCoatRoughnessMap */ public get clearCoatRoughnessMap(): Texture { - return this.defaultPass.textures[`clearCoatRoughnessMap`]; + return this.shader.getDefaultColorShader().textures[`clearCoatRoughnessMap`]; } /** * get brdf query map */ public get brdfLUT(): Texture { - return this.defaultPass.textures[`brdfLUT`]; + return this.shader.getDefaultColorShader().textures[`brdfLUT`]; } /** * set brdf query map */ public set brdfLUT(value: Texture) { - this.defaultPass.setTexture(`brdfLUT`, value); - this.defaultPass.setTexture(`brdflutMap`, value); + this.shader.getDefaultColorShader().setTexture(`brdfLUT`, value); + this.shader.getDefaultColorShader().setTexture(`brdflutMap`, value); } /** * get emissive map */ public get emissiveMap(): Texture { - return this.defaultPass.textures[`emissiveMap`]; + return this.shader.getDefaultColorShader().textures[`emissiveMap`]; } /** * set emissive map */ public set emissiveMap(value: Texture) { - this.defaultPass.setTexture(`emissiveMap`, value); + this.shader.getDefaultColorShader().setTexture(`emissiveMap`, value); } /** * set intensity of environment light or color of sampled by texture */ public set envIntensity(value: number) { - this.defaultPass.setUniformFloat(`envIntensity`, value); + this.shader.getDefaultColorShader().setUniformFloat(`envIntensity`, value); } /** * get intensity of environment light or color of sampled by texture */ public get envIntensity() { - return this.defaultPass.uniforms[`envIntensity`].value; + return this.shader.getDefaultColorShader().uniforms[`envIntensity`].value; } /** * set factor of refractive */ public set ior(value: number) { - this.defaultPass.setUniformFloat(`ior`, value); + this.shader.getDefaultColorShader().setUniformFloat(`ior`, value); } /** * get factor of refractive */ public get ior(): number { - return this.defaultPass.uniforms[`ior`].value; + return this.shader.getDefaultColorShader().uniforms[`ior`].value; } /** * valid USE_CLEARCOAT define in shader */ public useCleanCoat() { - this.defaultPass.setDefine("USE_CLEARCOAT", true); + this.shader.getDefaultColorShader().setDefine("USE_CLEARCOAT", true); } /** * Set the factor of the clearcoat */ public set clearcoatFactor(value: number) { - this.defaultPass.setUniformFloat(`clearcoatFactor`, value); + this.shader.getDefaultColorShader().setUniformFloat(`clearcoatFactor`, value); this.useCleanCoat(); } @@ -402,14 +433,14 @@ export class PhysicMaterial extends Material { * get the factor of the clearcoat */ public get clearcoatFactor(): number { - return this.defaultPass.uniforms[`clearcoatFactor`].value; + return this.shader.getDefaultColorShader().uniforms[`clearcoatFactor`].value; } /** * set the factor of the clearcoat Roughness */ public set clearcoatRoughnessFactor(value: number) { - this.defaultPass.setUniformFloat(`clearcoatRoughnessFactor`, value); + this.shader.getDefaultColorShader().setUniformFloat(`clearcoatRoughnessFactor`, value); this.useCleanCoat(); } @@ -417,14 +448,14 @@ export class PhysicMaterial extends Material { * get the factor of the clearcoat Roughness */ public get clearcoatRoughnessFactor(): number { - return this.defaultPass.uniforms[`clearcoatRoughnessFactor`].value; + return this.shader.getDefaultColorShader().uniforms[`clearcoatRoughnessFactor`].value; } /** * set the weight of the clearcoat */ public set clearcoatWeight(value: number) { - this.defaultPass.setUniformFloat(`clearcoatWeight`, value); + this.shader.getDefaultColorShader().setUniformFloat(`clearcoatWeight`, value); this.useCleanCoat(); } @@ -432,14 +463,14 @@ export class PhysicMaterial extends Material { * get the weight of the clearcoat */ public get clearcoatWeight(): number { - return this.defaultPass.uniforms[`clearcoatWeight`].value; + return this.shader.getDefaultColorShader().uniforms[`clearcoatWeight`].value; } /** * get the color of the clearcoat */ public set clearcoatColor(value: Color) { - this.defaultPass.setUniformColor(`clearcoatColor`, value); + this.shader.getDefaultColorShader().setUniformColor(`clearcoatColor`, value); this.useCleanCoat(); } @@ -447,6 +478,6 @@ export class PhysicMaterial extends Material { * set the color of the clearcoat */ public get clearcoatColor(): Color { - return this.defaultPass.uniforms[`clearcoatColor`].color; + return this.shader.getDefaultColorShader().uniforms[`clearcoatColor`].color; } } diff --git a/src/materials/PointMaterial.ts b/src/materials/PointMaterial.ts deleted file mode 100644 index 3cc1a8ed..00000000 --- a/src/materials/PointMaterial.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Material, RenderShader } from '..'; -import { Engine3D } from '../Engine3D'; -import { ShaderLib } from '../assets/shader/ShaderLib'; -import { PointShadowDebug } from '../assets/shader/materials/PointShadowDebug'; -import { UnLit } from '../assets/shader/materials/UnLit'; -import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; -import { Color } from '../math/Color'; -import { Vector4 } from '../math/Vector4'; -import { registerMaterial } from "./MaterialRegister"; - -/** - * PointMaterial - * @group Material - */ -export class PointMaterial extends Material { - /** - * @constructor - */ - constructor() { - super(); - ShaderLib.register("UnLitShader", UnLit); - ShaderLib.register("PointShadowDebug", PointShadowDebug); - - let colorPass = new RenderShader(`UnLitShader`, `PointShadowDebug`); - this.defaultPass = colorPass; - colorPass.setShaderEntry(`VertMain`, `FragMain`) - - colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformColor(`baseColor`, new Color()); - colorPass.setUniformFloat(`alphaCutoff`, 0.5); - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = false; - shaderState.receiveEnv = false; - shaderState.acceptGI = false; - shaderState.useLight = false; - - // default value - this.baseMap = Engine3D.res.whiteTexture; - } - - /** - * set environment texture, usually referring to cubemap - */ - public set baseMap(texture: Texture) { - //not need env texture - this.defaultPass.setTexture(`baseMap`, texture); - } - - /** - * set environment texture, usually referring to cubemap - */ - public set envMap(texture: Texture) { - //not need env texture - } - - /** - * set shadow map - */ - public set shadowMap(texture: Texture) { - //not need shadowMap texture - } - - debug() { - } -} \ No newline at end of file diff --git a/src/materials/SkyMaterial.ts b/src/materials/SkyMaterial.ts index 66cec265..0bc7c7d5 100644 --- a/src/materials/SkyMaterial.ts +++ b/src/materials/SkyMaterial.ts @@ -1,9 +1,7 @@ -import { ShaderUtil } from ".."; import { Engine3D } from "../Engine3D"; -import { GPUCompareFunction, GPUCullMode } from "../gfx/graphics/webGpu/WebGPUConst"; import { Texture } from "../gfx/graphics/webGpu/core/texture/Texture"; -import { RenderShader } from "../gfx/graphics/webGpu/shader/RenderShader"; -import { RendererType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { PassType } from "../gfx/renderJob/passRenderer/state/RendererType"; +import { SkyShader } from "../loader/parser/prefab/mats/shader/SkyShader"; import { Vector3 } from "../math/Vector3"; import { Material } from "./Material"; @@ -16,28 +14,21 @@ export class SkyMaterial extends Material { constructor() { super(); - let colorPass = new RenderShader('sky_vs_frag_wgsl', 'sky_fs_frag_wgsl'); - this.defaultPass = colorPass; - colorPass.setUniformVector3(`eyesPos`, new Vector3()); - colorPass.setUniformFloat(`exposure`, 1.0); - colorPass.setUniformFloat(`roughness`, 0.0); - - let shaderState = colorPass.shaderState; - shaderState.frontFace = `cw`; - shaderState.cullMode = GPUCullMode.back; - shaderState.depthWriteEnabled = false; - shaderState.depthCompare = GPUCompareFunction.less; - + this.shader = new SkyShader(); + this.shader.setUniformVector3(`eyesPos`, new Vector3()); + this.shader.setUniformFloat(`exposure`, 1.0); + this.shader.setUniformFloat(`roughness`, 0.5); } /** * Set base map(main map) */ public set baseMap(texture: Texture) { - this.defaultPass.setTexture(`baseMap`, texture); + this.setTexture(`baseMap`, texture); const key = 'IS_HDR_SKY'; - if (this.defaultPass.defineValue[key] != texture?.isHDRTexture) { - this.defaultPass.setDefine(key, texture?.isHDRTexture ? true : false); + let defaultShader = this._shader.getDefaultShaders()[0]; + if (defaultShader.defineValue[key] != texture?.isHDRTexture) { + this._shader.setDefine(key, texture?.isHDRTexture ? true : false); } } @@ -45,7 +36,8 @@ export class SkyMaterial extends Material { * Get base map(main map) // */ public get baseMap(): Texture { - return this.defaultPass.getTexture(`baseMap`); + let defaultShader = this._shader.getDefaultColorShader(); + return defaultShader.getTexture(`baseMap`); } public set envMap(texture: Texture) { @@ -64,9 +56,11 @@ export class SkyMaterial extends Material { } public get roughness() { - return this.defaultPass.uniforms[`roughness`].value; + let defaultShader = this._shader.getDefaultColorShader(); + return defaultShader.uniforms[`roughness`].value; } public set roughness(value: number) { - if (`roughness` in this.defaultPass.uniforms) this.defaultPass.uniforms[`roughness`].value = value; + let defaultShader = this._shader.getDefaultColorShader(); + if (`roughness` in defaultShader.uniforms) defaultShader.uniforms[`roughness`].value = value; } } diff --git a/src/materials/UnLitMaterial.ts b/src/materials/UnLitMaterial.ts index eba5212c..ac508c98 100644 --- a/src/materials/UnLitMaterial.ts +++ b/src/materials/UnLitMaterial.ts @@ -1,10 +1,11 @@ import { Engine3D } from '../Engine3D'; import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; -import { RenderShader } from '../gfx/graphics/webGpu/shader/RenderShader'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; import { Color } from '../math/Color'; import { Vector4 } from '../math/Vector4'; import { Material } from './Material'; -import { RendererType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { PassType } from '../gfx/renderJob/passRenderer/state/RendererType'; +import { Shader, UnLitShader } from '..'; /** * Unlit Mateiral @@ -17,55 +18,31 @@ export class UnLitMaterial extends Material { */ constructor() { super(); - let colorPass = new RenderShader(`UnLit`, `UnLit`); - this.defaultPass = colorPass; - colorPass.setShaderEntry(`VertMain`, `FragMain`) - - colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); - colorPass.setUniformColor(`baseColor`, new Color(1, 1, 1, 1)); - colorPass.setUniformFloat(`alphaCutoff`, 0.5); - let shaderState = colorPass.shaderState; - shaderState.acceptShadow = false; - shaderState.castShadow = false; - shaderState.receiveEnv = false; - shaderState.acceptGI = false; - shaderState.useLight = false; - - // let shaderState = shader.shaderState; - // shaderState.acceptShadow = true; - // shaderState.castShadow = true; - // shaderState.receiveEnv = false; - // shaderState.acceptGI = false; - // shaderState.useLight = true; - + this.shader = new UnLitShader(); // default value - // this.emissiveMap = Engine3D.res.blackTexture; - this.defaultPass = colorPass; - // this.baseMap = Engine3D.res.grayTexture; this.baseMap = Engine3D.res.whiteTexture; } public set baseMap(texture: Texture) { - this.defaultPass.setTexture(`baseMap`, texture); + this.shader.setTexture(`baseMap`, texture); } public get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } /** * set base color (tint color) */ public set baseColor(color: Color) { - this.defaultPass.setUniformColor(`baseColor`, color); + this.shader.setUniformColor(`baseColor`, color); } /** * get base color (tint color) */ public get baseColor() { - return this.defaultPass.uniforms[`baseColor`].color; + return this.shader.getUniformColor("baseColor"); } /** diff --git a/src/materials/UnLitTexArrayMaterial.ts b/src/materials/UnLitTexArrayMaterial.ts new file mode 100644 index 00000000..889d4b6a --- /dev/null +++ b/src/materials/UnLitTexArrayMaterial.ts @@ -0,0 +1,61 @@ +import { Engine3D } from '../Engine3D'; +import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; +import { RenderShaderPass } from '../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { UnLitTexArrayShader } from '../loader/parser/prefab/mats/shader/UnLitTexArrayShader'; +import { Color } from '../math/Color'; +import { Vector4 } from '../math/Vector4'; +import { Material } from './Material'; + +/** + * Unlit Mateiral + * A non glossy surface material without specular highlights. + * @group Material + */ +export class UnLitTexArrayMaterial extends Material { + /** + * @constructor + */ + constructor() { + super(); + this.shader = new UnLitTexArrayShader(); + // default value + this.baseMap = Engine3D.res.whiteTexture; + } + + public set baseMap(texture: Texture) { + this.shader.setTexture(`baseMap`, texture); + } + + public get baseMap() { + return this.shader.getTexture(`baseMap`); + } + + /** + * set base color (tint color) + */ + public set baseColor(color: Color) { + this.shader.setUniformColor(`baseColor`, color); + } + + /** + * get base color (tint color) + */ + public get baseColor() { + return this.shader.getUniformColor("baseColor"); + } + + // /** + // * set environment texture, usually referring to cubemap + // */ + // public set envMap(texture: Texture) { + // //not need env texture + // } + + /** + * @internal + * set shadow map + */ + public set shadowMap(texture: Texture) { + //not need shadowMap texture + } +} diff --git a/src/materials/multiPass/CastPointShadowMaterialPass.ts b/src/materials/multiPass/CastPointShadowMaterialPass.ts index 49d7eb1d..e7b5903b 100644 --- a/src/materials/multiPass/CastPointShadowMaterialPass.ts +++ b/src/materials/multiPass/CastPointShadowMaterialPass.ts @@ -1,4 +1,5 @@ -import { RenderShader } from "../../gfx/graphics/webGpu/shader/RenderShader"; +import { RenderShaderPass } from "../../gfx/graphics/webGpu/shader/RenderShaderPass"; +import { PassType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { Vector3 } from "../../math/Vector3"; /** @@ -6,9 +7,10 @@ import { Vector3 } from "../../math/Vector3"; * CastPointShadowMaterialPass * @group Material */ -export class CastPointShadowMaterialPass extends RenderShader { +export class CastPointShadowMaterialPass extends RenderShaderPass { constructor() { super(`castPointShadowMap_vert`, `shadowCastMap_frag`); + this.passType = PassType.POINT_SHADOW; this.setShaderEntry("main", "main"); this.setUniformFloat("cameraFar", 5000); this.setUniformVector3("lightWorldPos", Vector3.ZERO); diff --git a/src/materials/multiPass/CastShadowMaterialPass.ts b/src/materials/multiPass/CastShadowMaterialPass.ts index 691bb0f3..97b3047d 100644 --- a/src/materials/multiPass/CastShadowMaterialPass.ts +++ b/src/materials/multiPass/CastShadowMaterialPass.ts @@ -1,4 +1,5 @@ -import { RenderShader, Texture } from '../..'; +import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; import { Vector3 } from '../../math/Vector3'; /** @@ -6,9 +7,10 @@ import { Vector3 } from '../../math/Vector3'; * CastShadowMaterialPass * @group Material */ -export class CastShadowMaterialPass extends RenderShader { +export class CastShadowMaterialPass extends RenderShaderPass { constructor() { super(`shadowCastMap_vert`, `directionShadowCastMap_frag`); + this.passType = PassType.SHADOW; this.setShaderEntry("main"); this.setUniformFloat("cameraFar", 5000); this.setUniformVector3("lightWorldPos", Vector3.ZERO); @@ -20,9 +22,4 @@ export class CastShadowMaterialPass extends RenderShader { this.setDefine(`USE_ALPHACUT`, true); // this.alphaCutoff = 0.5 ; } - - public setTexture(name: string, texture: Texture) { - // texture.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; - super.setTexture(name, texture); - } } diff --git a/src/materials/multiPass/DepthMaterialPass.ts b/src/materials/multiPass/DepthMaterialPass.ts index d9ada6a3..d1d27cbb 100644 --- a/src/materials/multiPass/DepthMaterialPass.ts +++ b/src/materials/multiPass/DepthMaterialPass.ts @@ -1,4 +1,4 @@ -import { RenderShader } from '../..'; +import { RenderShaderPass, PassType } from '../..'; /** @@ -6,9 +6,10 @@ import { RenderShader } from '../..'; * DepthMaterialPass * @group Material */ -export class DepthMaterialPass extends RenderShader { +export class DepthMaterialPass extends RenderShaderPass { constructor() { super(`ZPass_shader_vs`, `ZPass_shader_vs`); + this.passType = PassType.DEPTH; this.setShaderEntry("main"); this.useRz = false; let shaderState = this.shaderState; diff --git a/src/materials/multiPass/GBufferPass.ts b/src/materials/multiPass/GBufferPass.ts index d232224f..8765f466 100644 --- a/src/materials/multiPass/GBufferPass.ts +++ b/src/materials/multiPass/GBufferPass.ts @@ -1,21 +1,21 @@ import { Color } from '../../math/Color'; import { BlendMode } from '../BlendMode'; import { Engine3D } from '../../Engine3D'; -import { RenderShader } from '../../gfx/graphics/webGpu/shader/RenderShader'; +import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../..'; /** * @internal * GBufferPass * @group Material */ -export class GBufferPass extends RenderShader { +export class GBufferPass extends RenderShaderPass { transparency: number; constructor() { super(`gbuffer_vs`, `gbuffer_fs`); this.setShaderEntry(`VertMain`, `FragMain`) - let shaderState = this.shaderState; - // shaderState.cullMode = `none`; + this.passType = PassType.GI; this.setUniformColor(`baseColor`, new Color()); this.setUniformColor(`emissiveColor`, new Color()); diff --git a/src/materials/multiPass/SkyGBufferPass.ts b/src/materials/multiPass/SkyGBufferPass.ts index 5308e30f..33d30cd0 100644 --- a/src/materials/multiPass/SkyGBufferPass.ts +++ b/src/materials/multiPass/SkyGBufferPass.ts @@ -1,14 +1,19 @@ -import { RenderShader, SkyGBuffer_pass } from '../..'; +import { Vector3 } from '../..'; import { GPUCompareFunction, GPUCullMode } from '../../gfx/graphics/webGpu/WebGPUConst'; +import { RenderShaderPass } from '../../gfx/graphics/webGpu/shader/RenderShaderPass'; +import { PassType } from '../../gfx/renderJob/passRenderer/state/RendererType'; /** * @internal * @group Material */ -export class SkyGBufferPass extends RenderShader { +export class SkyGBufferPass extends RenderShaderPass { constructor() { super(`sky_vs_frag_wgsl`, `SkyGBuffer_fs`); + this.passType = PassType.GI; + + this.setUniformVector3(`eyesPos`, new Vector3()); this.setUniformFloat(`exposure`, 1.0); this.setUniformFloat(`roughness`, 0.0); diff --git a/src/math/AnimationCurve.ts b/src/math/AnimationCurve.ts index 672c575f..4853bb93 100644 --- a/src/math/AnimationCurve.ts +++ b/src/math/AnimationCurve.ts @@ -1,62 +1,7 @@ import { PingPong, RepeatSE } from './MathUtil'; - -/** - * Time Warp Mode - * @PingPong value min -> max -> min - * @Repeat value = value % repeatSpace - * @Clamp value = max(min( value , 1 ) , 0 ) - */ -export enum WrapTimeMode { - PingPong = 0, - Repeat = 1, - Clamp = 2, -} - -/** - * @group Math - */ -export class Keyframe { - public serializedVersion: string = '2'; - public time: number; - public value: number; - public inSlope: number = 0; - public outSlope: number = 0; - public tangentMode: number = 0; - - constructor(time: number = 0, value: number = 0) { - this.time = time; - this.value = value; - } - - public unSerialized(data: any) { - this.serializedVersion = data['serializedVersion']; - this.time = data['time']; - this.value = data['value']; - this.tangentMode = data['tangentMode']; - this.inSlope = data['inSlope'] == 'Infinity' ? NaN : data['inSlope']; - this.outSlope = data['outSlope'] == 'Infinity' ? NaN : data['outSlope']; - } - - public unSerialized2(data: any) { - this.serializedVersion = data['serializedVersion']; - this.time = data['time']; - this.value = data['value']; - this.tangentMode = data['tangentMode']; - this.inSlope = data['inTangent'] == 'Infinity' ? NaN : data['inTangent']; - this.outSlope = data['outTangent'] == 'Infinity' ? NaN : data['outTangent']; - } -} - -/** - * @internal - * @group Math - */ -export class FrameCache { - public index: number; //= lhsIndex; - public time: number; // = lhs.time + timeOffset; - public timeEnd: number; // = rhs.time + timeOffset; - public coeff: number[] = []; //= lhsIndex; -} +import { FrameCache } from './enum/FrameCache'; +import { WrapTimeMode } from './enum/WrapTimeMode'; +import { Keyframe } from './enum/Keyframe'; /** * Animation Cureve @@ -288,7 +233,11 @@ export class AnimationCurve { private calcTotalTime() { let maxTime = 0; for (let curve of this.curve) { - maxTime = Math.max(maxTime, curve.time); + if (curve) { + maxTime = Math.max(maxTime, curve.time); + } else { + console.error(curve); + } } this._totalTime = maxTime; } diff --git a/src/math/AnimationCurveClip.ts b/src/math/AnimationCurveClip.ts new file mode 100644 index 00000000..2caa150a --- /dev/null +++ b/src/math/AnimationCurveClip.ts @@ -0,0 +1,65 @@ +import { PingPong, RepeatSE } from './MathUtil'; +import { FrameCache } from './enum/FrameCache'; +import { WrapTimeMode } from './enum/WrapTimeMode'; +import { Keyframe } from './enum/Keyframe'; +import { AnimationCurve, AnimationCurveT, BytesArray, KeyframeT } from '..'; + +/** + * Animation Cureve + * has frame list data + * @group Math + */ +export class PropertyAnimationClip { + public clipName: string; + public loopTime: boolean; + public startTime: number; + public stopTime: number; + public sampleRate: number; + public useSkeletonPos: boolean; + public useSkeletonScale: boolean; + public positionCurves: Map = new Map(); + public rotationCurves: Map = new Map(); + public scaleCurves: Map = new Map(); + public floatCurves: Map = new Map(); + + public formBytes(bytes: BytesArray) { + this.clipName = bytes.readUTF(); + this.loopTime = bytes.readInt32() ? false : true; + this.startTime = bytes.readFloat32(); + this.stopTime = bytes.readFloat32(); + this.sampleRate = bytes.readInt32(); + this.useSkeletonPos = bytes.readInt32() > 0; + this.useSkeletonScale = bytes.readInt32() > 0; + if (this.useSkeletonPos) { + let positionCurvesCount = bytes.readInt32(); + for (let i = 0; i < positionCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.positionCurves.set(curveData.path, curveData); + } + } + + let rotationCurvesCount = bytes.readInt32(); + for (let i = 0; i < rotationCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.rotationCurves.set(curveData.path, curveData); + } + + if (this.useSkeletonScale) { + let scaleCurvesCount = bytes.readInt32(); + for (let i = 0; i < scaleCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.scaleCurves.set(curveData.path, curveData); + } + } + + let floatCurvesCount = bytes.readInt32(); + for (let i = 0; i < floatCurvesCount; i++) { + let curveData = new AnimationCurveT(); + curveData.formBytes(bytes); + this.floatCurves.set(curveData.attribute, curveData); + } + } +} diff --git a/src/math/AnimationCurveT.ts b/src/math/AnimationCurveT.ts new file mode 100644 index 00000000..789e5607 --- /dev/null +++ b/src/math/AnimationCurveT.ts @@ -0,0 +1,151 @@ +import { PingPong, RepeatSE, swap } from './MathUtil'; +import { FrameCache } from './enum/FrameCache'; +import { WrapTimeMode } from './enum/WrapTimeMode'; +import { Keyframe } from './enum/Keyframe'; +import { AnimationCurve, BytesArray, KeyframeT, Quaternion, Vector2, Vector3, Vector4 } from '..'; + +export type CurveValueT = number | Vector2 | Vector3 | Vector4 | Quaternion; +/** + * Animation Cureve + * has frame list data + * @group Math + */ +export class AnimationCurveT { + public path: string; + public attribute: string; + public propertys: string[]; + public preInfinity: number; + public postInfinity: number; + public rotationOrder: number; + public m_curves: AnimationCurve[]; + private k: number = 0; + + private _cacheValue: any; + private _kValue: CurveValueT; + + constructor(k: number = 1) { + this.k = k; + this.m_curves = []; + this.check(); + } + + private check() { + for (let i = 0; i < this.k; i++) { + this.m_curves[i] ||= new AnimationCurve(); + } + switch (this.k) { + case 1: + this._cacheValue = 0; + break; + case 2: + this._cacheValue = new Vector2(); + break; + case 3: + this._cacheValue = new Vector3(); + break; + case 4: + this._cacheValue = new Vector4(); + break; + default: + break; + } + } + + /** + * return this curve use total time + */ + public get totalTime() { + return this.m_curves[0].totalTime; + } + + /** + * add keyFrame to curve keyframe last and calcTotalTime + * @param keyFrame {@link Keyframe} sea: one key frame data + */ + public addKeyFrame(keyFrame: KeyframeT) { + for (let i = 0; i < this.k; i++) { + this.m_curves[i].addKeyFrame(keyFrame.getK(i)); + } + } + + /** + * remove keyframe from this curve + * @param keyFrame {@link Keyframe} + */ + public removeKeyFrame(keyFrame: KeyframeT) { + for (let i = 0; i < this.k; i++) { + this.m_curves[i].removeKeyFrame(keyFrame.getK(i)); + } + } + + /** + * get caculate frames value + * @param time + * @returns + */ + public getValue(time: number): CurveValueT { + switch (this.k) { + case 1: + this._cacheValue = this.m_curves[0].getValue(time); + break; + case 2: + this._cacheValue.x = this.m_curves[0].getValue(time); + this._cacheValue.y = this.m_curves[1].getValue(time); + break; + case 3: + this._cacheValue.x = this.m_curves[0].getValue(time); + this._cacheValue.y = this.m_curves[1].getValue(time); + this._cacheValue.z = this.m_curves[2].getValue(time); + break; + case 4: + this._cacheValue.x = this.m_curves[0].getValue(time); + this._cacheValue.y = this.m_curves[1].getValue(time); + this._cacheValue.z = this.m_curves[2].getValue(time); + this._cacheValue.w = this.m_curves[3].getValue(time); + break; + default: + break; + } + return this._cacheValue; + } + + /** + * get has Keyframe list count + * @returns int + */ + public getKeyCount(): number { + return this.m_curves[0].getKeyCount(); + } + + /** + * Get a Keyframe Data by Index + * @param index must int + * @returns Keyframe {@link Keyframe} + */ + public getKey(index: number): Keyframe[] { + let list = []; + for (let i = 0; i < this.k; i++) { + list.push(this.m_curves[i].getKey(index)); + } + return list; + } + + public formBytes(bytes: BytesArray) { + this.path = bytes.readUTF(); + this.k = bytes.readInt32(); + this.check(); + + this.attribute = bytes.readUTF(); + + this.propertys = this.attribute.split("."); + this.preInfinity = bytes.readInt32(); + this.postInfinity = bytes.readInt32(); + this.rotationOrder = bytes.readInt32(); + let curvesCount = bytes.readInt32(); + for (let i = 0; i < curvesCount; i++) { + let keyframe = new KeyframeT(0); + keyframe.formBytes(bytes); + this.addKeyFrame(keyframe); + } + } +} diff --git a/src/math/BiMap.ts b/src/math/BiMap.ts new file mode 100644 index 00000000..95cb605d --- /dev/null +++ b/src/math/BiMap.ts @@ -0,0 +1,43 @@ +//双向map +export class BiMap extends Map{ + private readonly negtive: Map; + constructor(iterable?: Iterable | null,) { + super(iterable); + this.negtive = new Map(); + if (iterable) { + for (let item of iterable) { + this.negtive.set(item[1], item[0]); + } + } + } + delete(key: K): boolean { + if (this.has(key)) { + let value = this.get(key); + this.negtive.delete(value); + return super.delete(key); + } + return false; + } + + getKey(value: V): K { + return this.negtive.get(value); + } + + deleteValue(value: V) { + let k = this.negtive.get(value); + k && this.delete(k); + return this.negtive.delete(value); + } + + set(key: K, value: V): this { + super.set(key, value); + this.negtive.set(value, key); + return this; + } + + clear(): void { + this.negtive.clear(); + super.clear(); + } + +} \ No newline at end of file diff --git a/src/math/OrderMap.ts b/src/math/OrderMap.ts new file mode 100644 index 00000000..b48e45ef --- /dev/null +++ b/src/math/OrderMap.ts @@ -0,0 +1,63 @@ +export class OrderMap extends Map{ + public readonly valueList: V[]; + public readonly keyList: K[]; + public isChange: boolean = true; + constructor(iterable?: Iterable | null, recordKey?: boolean, recordValue?: boolean) { + super(iterable); + if (recordKey) this.keyList = []; + if (recordValue) this.valueList = []; + + if (iterable) { + for (let item of iterable) { + this.valueList?.push(item[1]); + this.keyList?.push(item[0]); + } + } + } + + delete(key: K): boolean { + if (this.has(key)) { + let value = this.get(key); + this.valueList && this.deleteValue(value); + + this.keyList && this.deleteKey(key); + + this.isChange = true; + return super.delete(key); + } + return false; + } + + private deleteValue(value: V): this { + let index = this.valueList.indexOf(value); + if (index >= 0) { + this.valueList.splice(index, 1); + } + return this; + } + + private deleteKey(key: K): this { + let index = this.keyList.indexOf(key); + if (index >= 0) { + this.keyList.splice(index, 1); + } + return this; + } + + set(key: K, value: V): this { + this.delete(key); + this.keyList?.push(key); + this.valueList?.push(value); + super.set(key, value); + this.isChange = true; + return this; + } + + clear(): void { + if (this.valueList) this.valueList.length = 0; + if (this.keyList) this.keyList.length = 0; + this.isChange = true; + super.clear(); + } + +} \ No newline at end of file diff --git a/src/math/ParticleSystemCurves.ts b/src/math/ParticleSystemCurves.ts index 9978dfaa..1fd9c5ec 100644 --- a/src/math/ParticleSystemCurves.ts +++ b/src/math/ParticleSystemCurves.ts @@ -1,8 +1,9 @@ -import { AnimationCurve, FrameCache } from './AnimationCurve'; +import { AnimationCurve } from './AnimationCurve'; import { lerp } from './MathUtil'; import { Polynomial, PolynomialCurve } from './PolynomialCurve'; import { quadraticPolynomialRootsGeneric } from './Polynomials'; import { Vector2 } from './Vector2'; +import { FrameCache } from './enum/FrameCache'; /** * @internal diff --git a/src/math/Plane3D.ts b/src/math/Plane3D.ts new file mode 100644 index 00000000..5f8c532d --- /dev/null +++ b/src/math/Plane3D.ts @@ -0,0 +1,248 @@ +import { Vector3 } from ".."; +import { PlaneClassification } from "./PlaneClassification"; + +/** +* @language zh_CN +* @class Plane3D +* @classdesc +* Plane3D 类 3D空间中的平面表示数据 +* 由a,b,c,d4个分量组成 在三维空间中定义了一个平面 Ax + By + Cz + D = 0 +* @includeExample geom/Plane3D.ts +* @version +* @platform Web,Native +*/ +export class Plane3D { + /** + * @language en_US + * The A coefficient of this plane. (Also the x dimension of the plane normal) + */ + /** + * @language zh_CN + * 平面中的a分量 + * @platform Web,Native + */ + public a: number; + + /** + * @language en_US + * The B coefficient of this plane. (Also the y dimension of the plane normal) + */ + /** + * @language zh_CN + * 平面中的b分量 + * @platform Web,Native + */ + public b: number; + + /** + * @language en_US + * The C coefficient of this plane. (Also the z dimension of the plane normal) + */ + /** + * @language zh_CN + * 平面中的c分量 + * @platform Web,Native + */ + public c: number; + + /** + * @language en_US + * The D coefficient of this plane. (Also the inverse dot product between normal and point) + */ + /** + * @language zh_CN + * 平面中的d分量 + * @platform Web,Native + */ + public d: number; + + // indicates the alignment of the plane + /** + * @private + */ + public static ALIGN_ANY: number = 0; + + /** + * @private + */ + public static ALIGN_XY_AXIS: number = 1; + + /** + * @private + */ + public static ALIGN_YZ_AXIS: number = 2; + + /** + * @private + */ + public static ALIGN_XZ_AXIS: number = 3; + + /** + * @language en_US + * Create a Plane3D with ABCD coefficients + */ + /** + * @language zh_CN + * 创建一个平面实例 + * @param a + * @param b + * @param c + * @param d + * @platform Web,Native + */ + constructor(a: number = 0, b: number = 0, c: number = 0, d: number = 0) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + } + + /** + * @language zh_CN + * 填充平面的各分量的值 + * @param a + * @param b + * @param c + * @param d + * @platform Web,Native + */ + public setTo(a: number = 0, b: number = 0, c: number = 0, d: number = 0) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + } + + /** + * @language en_US + * Fills this Plane3D with the coefficients from 3 points in 3d space. + * @param p0 Vector3 + * @param p1 Vector3 + * @param p2 Vector3 + */ + + /** + * @language zh_CN + * 由3个坐标来创建一个3d平面 + * @param p0 Vector3 + * @param p1 Vector3 + * @param p2 Vector3 + * @platform Web,Native + */ + public fromPoints(p0: Vector3, p1: Vector3, p2: Vector3) { + var d1x: number = p1.x - p0.x; + var d1y: number = p1.y - p0.y; + var d1z: number = p1.z - p0.z; + + var d2x: number = p2.x - p0.x; + var d2y: number = p2.y - p0.y; + var d2z: number = p2.z - p0.z; + + this.a = d1y * d2z - d1z * d2y; + this.b = d1z * d2x - d1x * d2z; + this.c = d1x * d2y - d1y * d2x; + this.d = -(this.a * p0.x + this.b * p0.y + this.c * p0.z); + } + + /** + * @language en_US + * Fills this Plane3D with the coefficients from the plane's normal and a point in 3d space. + * @param normal Vector3 + * @param point Vector3 + */ + /** + * @language zh_CN + * 由一条normal向量和一个坐标创建一个3d平面 + * @param normal Vector3 + * @param point Vector3 + * @platform Web,Native + */ + public fromNormalAndPoint(normal: Vector3, point: Vector3) { + this.a = normal.x; + this.b = normal.y; + this.c = normal.z; + this.d = -(this.a * point.x + this.b * point.y + this.c * point.z); + } + + /** + * @language en_US + * Normalize this Plane3D + * @returns Plane3D This Plane3D. + */ + /** + * @language zh_CN + * 单位化3d平面 + * @returns number 返回平面长度 + * @platform Web,Native + */ + public normalize(): number { + var len: number = Math.sqrt(this.a * this.a + this.b * this.b + this.c * this.c); + if (len > 0.0) { + var invLength: number = 1.0 / len; + this.a *= invLength; + this.b *= invLength; + this.c *= invLength; + this.d *= invLength; + } + + return len; + } + + /** + * @language en_US + * Returns the signed distance between this Plane3D and the point p. + * @param p Vector3 + * @returns Number + */ + /** + * @language zh_CN + * 计算3d平面到点p的距离 + * @param p Vector3 + * @returns number 返回计算后的距离 + * @platform Web,Native + */ + public distance(p: Vector3): number { + return this.a * p.x + this.b * p.y + this.c * p.z + this.d; + } + + /** + * @language en_US + * Classify a point against this Plane3D. (in front, back or intersecting) + * @param p Vector3 + * @param epsilon + * @returns PlaneClassification.FRONT在平面正面 + * PlaneClassification.BACK在平面背面面 + * PlaneClassification.INTERSECT在平面上 + */ + /** + * @language zh_CN + * 计算3d平面和点p的空间关系 + * @param p Vector3 + * @param epsilon 相对偏移值 + * @returns number int Plane3.FRONT or Plane3D.BACK or Plane3D.INTERSECT + * @platform Web,Native + */ + public classifyPoint(p: Vector3, epsilon: number = 0.01): number { + + var dis: number = this.distance(p); + + if (dis < -epsilon) { + return PlaneClassification.BACK; + } + else if (dis > epsilon) { + return PlaneClassification.FRONT; + } + + return PlaneClassification.INTERSECT; + } + + /** + * @language zh_CN + * 当前Plane3D以字符串形式返回 + * @returns string + * @platform Web,Native + */ + public toString(): string { + return "Plane3D [a:" + this.a + ", b:" + this.b + ", c:" + this.c + ", d:" + this.d + "]"; + } +} \ No newline at end of file diff --git a/src/math/PlaneClassification.ts b/src/math/PlaneClassification.ts new file mode 100644 index 00000000..9a8ec358 --- /dev/null +++ b/src/math/PlaneClassification.ts @@ -0,0 +1,36 @@ +export class PlaneClassification { + /** + * @language zh_CN + * 背面 + * @platform Web,Native + */ + public static BACK: number = 0; + + /** + * @language zh_CN + * 正面 + * @platform Web,Native + */ + public static FRONT: number = 1; + + /** + * @language zh_CN + * 在法线朝上的一面 + * @platform Web,Native + */ + public static IN: number = 0; + + /** + * @language zh_CN + * 在法线朝下的一面 + * @platform Web,Native + */ + public static OUT: number = 1; + + /** + * @language zh_CN + * 相交 + * @platform Web,Native + */ + public static INTERSECT: number = 2; +} \ No newline at end of file diff --git a/src/math/PolynomialCurve.ts b/src/math/PolynomialCurve.ts index 458373e3..c3c23d82 100644 --- a/src/math/PolynomialCurve.ts +++ b/src/math/PolynomialCurve.ts @@ -1,4 +1,5 @@ -import { AnimationCurve, FrameCache } from './AnimationCurve'; +import { FrameCache } from './enum/FrameCache'; +import { AnimationCurve } from './AnimationCurve'; import { cubicPolynomialRootsGeneric } from './Polynomials'; import { Vector2 } from './Vector2'; diff --git a/src/math/Quaternion.ts b/src/math/Quaternion.ts index e2a5e76c..1927259f 100644 --- a/src/math/Quaternion.ts +++ b/src/math/Quaternion.ts @@ -7,6 +7,7 @@ import { Vector3 } from './Vector3'; * @group Math */ export class Quaternion { + public static HELP_0: Quaternion = new Quaternion(0, 0, 0, 1); public static HELP_1: Quaternion = new Quaternion(0, 0, 0, 1); public static HELP_2: Quaternion = new Quaternion(0, 0, 0, 1); @@ -548,6 +549,11 @@ export class Quaternion { } return value < minInclusive ? minInclusive : value < maxInclusive ? value : maxInclusive; } + + static serialize(value: Quaternion): Quaternion { + let v = new Quaternion(value.x, value.y, value.z, value.w); + return v; + } } /** diff --git a/src/math/Vector3.ts b/src/math/Vector3.ts index 2c72253d..157e9e1c 100644 --- a/src/math/Vector3.ts +++ b/src/math/Vector3.ts @@ -1090,6 +1090,41 @@ export class Vector3 { return dotProduct / d; } } + + public static pointInsideTriangle(pt: Vector3, pt0: Vector3, pt1: Vector3, pt2: Vector3): boolean { + Vector3.HELP_0.setTo(pt.x, pt.z, 0); + Vector3.HELP_1.setTo(pt0.x, pt0.z, 0); + Vector3.HELP_2.setTo(pt1.x, pt1.z, 0); + Vector3.HELP_3.setTo(pt2.x, pt2.z, 0); + + return Vector3.pointInsideTriangle2d(); + } + + private static pointInsideTriangle2d(): boolean { + if (Vector3.productXY(Vector3.HELP_1, Vector3.HELP_2, Vector3.HELP_3) >= 0) { + return (Vector3.productXY(Vector3.HELP_1, Vector3.HELP_2, Vector3.HELP_0) >= 0) + && (Vector3.productXY(Vector3.HELP_2, Vector3.HELP_3, Vector3.HELP_0)) >= 0 + && (Vector3.productXY(Vector3.HELP_3, Vector3.HELP_1, Vector3.HELP_0) >= 0); + } + else { + return (Vector3.productXY(Vector3.HELP_1, Vector3.HELP_2, Vector3.HELP_0) <= 0) + && (Vector3.productXY(Vector3.HELP_2, Vector3.HELP_3, Vector3.HELP_0)) <= 0 + && (Vector3.productXY(Vector3.HELP_3, Vector3.HELP_1, Vector3.HELP_0) <= 0); + } + } + + private static productXY(p1: { x: number, y: number }, p2: { x: number, y: number }, p3: { x: number, y: number }): number { + var val: number = (p1.x - p3.x) * (p2.y - p3.y) - (p1.y - p3.y) * (p2.x - p3.x); + if (val > -0.00001 && val < 0.00001) + val = 0; + return val; + } + + static serialize(position: Vector3): Vector3 { + let v = new Vector3(position.x, position.y, position.z, position.w); + return v; + } + } diff --git a/src/math/enum/FrameCache.ts b/src/math/enum/FrameCache.ts new file mode 100644 index 00000000..da66614c --- /dev/null +++ b/src/math/enum/FrameCache.ts @@ -0,0 +1,10 @@ +/** + * @internal + * @group Math + */ +export class FrameCache { + public index: number; //= lhsIndex; + public time: number; // = lhs.time + timeOffset; + public timeEnd: number; // = rhs.time + timeOffset; + public coeff: number[] = []; //= lhsIndex; +} \ No newline at end of file diff --git a/src/math/enum/Keyframe.ts b/src/math/enum/Keyframe.ts new file mode 100644 index 00000000..23ef5012 --- /dev/null +++ b/src/math/enum/Keyframe.ts @@ -0,0 +1,41 @@ +import { BytesArray, ValueParser } from "../.."; + +/** + * @group Math + */ +export class Keyframe { + public serializedVersion: string = '2'; + public time: number; + public value: number; + public inSlope: number = 0; + public outSlope: number = 0; + public tangentMode: number = 0; + + public weightedMode: number = 0; + public inWeight: number; + public outWeight: number; + + constructor(time: number = 0, value: number = 0) { + this.time = time; + this.value = value; + } + + public unSerialized(data: any) { + this.serializedVersion = data['serializedVersion']; + this.time = data['time']; + this.value = data['value']; + this.tangentMode = data['tangentMode']; + this.inSlope = data['inSlope'] == 'Infinity' ? NaN : data['inSlope']; + this.outSlope = data['outSlope'] == 'Infinity' ? NaN : data['outSlope']; + } + + public unSerialized2(data: any) { + this.serializedVersion = data['serializedVersion']; + this.time = data['time']; + this.value = data['value']; + this.tangentMode = data['tangentMode']; + this.inSlope = data['inTangent'] == 'Infinity' ? NaN : data['inTangent']; + this.outSlope = data['outTangent'] == 'Infinity' ? NaN : data['outTangent']; + } + +} \ No newline at end of file diff --git a/src/math/enum/T/KeyframeT.ts b/src/math/enum/T/KeyframeT.ts new file mode 100644 index 00000000..4b358caf --- /dev/null +++ b/src/math/enum/T/KeyframeT.ts @@ -0,0 +1,136 @@ +import { CurveValueType, ValueParser } from "../../../loader/parser/prefab/prefabData/ValueParser"; +import { ValueEnumType } from "../../../loader/parser/prefab/prefabData/ValueType"; +import { BytesArray } from "../../../util/BytesArray"; +import { Quaternion } from "../../Quaternion"; +import { Vector2 } from "../../Vector2"; +import { Vector3 } from "../../Vector3"; +import { Vector4 } from "../../Vector4"; +import { Keyframe } from "../Keyframe"; + +/** + * @group Math + */ +export class KeyframeT { + public serializedVersion: string = '2'; + public time: number; + public tangentMode: number = 0; + public weightedMode: number = 0; + // public value: CurveValueType; + // public inSlope: CurveValueType; + // public outSlope: CurveValueType; + // public inWeight: CurveValueType + // public outWeight: CurveValueType + + public propertyKeyFrame: { [k: number]: Keyframe }; + + constructor(time: number = 0) { + this.time = time; + this.propertyKeyFrame = {}; + } + + public getK(k: number) { + return this.propertyKeyFrame[k]; + } + + private split(type: ValueEnumType, value: CurveValueType, property: string) { + switch (type) { + case ValueEnumType.single: + { + let keyFrame = this.getKeyFrame(0); + keyFrame[property] = value; + } + break; + case ValueEnumType.float: + { + let keyFrame = this.getKeyFrame(0); + keyFrame[property] = value; + } + break; + case ValueEnumType.vector2: + { + let v = value as Vector2; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + } + break; + case ValueEnumType.vector3: + { + let v = value as Vector3; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + let z_kf = this.getKeyFrame(2); + z_kf[property] = v.z; + } + break; + case ValueEnumType.vector4: + { + let v = value as Vector4; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + let z_kf = this.getKeyFrame(2); + z_kf[property] = v.y; + let w_kf = this.getKeyFrame(3); + w_kf[property] = v.y; + } + break; + case ValueEnumType.quaternion: + { + let v = value as Quaternion; + let x_kf = this.getKeyFrame(0); + x_kf[property] = v.x; + let y_kf = this.getKeyFrame(1); + y_kf[property] = v.y; + let z_kf = this.getKeyFrame(2); + z_kf[property] = v.z; + let w_kf = this.getKeyFrame(3); + w_kf[property] = v.w; + } + break; + } + } + + private getKeyFrame(k: number): Keyframe { + let keyFrame = this.propertyKeyFrame[k]; + if (!keyFrame) { + keyFrame = new Keyframe(); + keyFrame.time = this.time; + keyFrame.tangentMode = this.tangentMode; + keyFrame.weightedMode = this.weightedMode; + this.propertyKeyFrame[k] = keyFrame; + } + + return keyFrame; + } + + public formBytes(bytes: BytesArray) { + this.time = bytes.readFloat32(); + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "value"); + } + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "inSlope"); + } + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "outSlope"); + } + this.tangentMode = bytes.readInt32(); + this.weightedMode = bytes.readInt32(); + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "inWeight"); + } + { + let { t, v } = ValueParser.parser(bytes); + this.split(t, v, "outWeight"); + } + } +} \ No newline at end of file diff --git a/src/math/enum/T/ValueOp.ts b/src/math/enum/T/ValueOp.ts new file mode 100644 index 00000000..aeeab6ae --- /dev/null +++ b/src/math/enum/T/ValueOp.ts @@ -0,0 +1,39 @@ +import { CurveValueType, Quaternion, ValueEnumType, Vector2, Vector3, Vector4 } from "../../.."; + +export class ValueOp { + public static sub(v1: T, v2: T) { + let t = v1.constructor.name; + switch (t) { + case `number`: + return (v1 as number) - (v2 as number); + case 'Vector2': + { + let vv1 = v1 as Vector2; + let vv2 = v2 as Vector2; + return new Vector2(vv1.x - vv2.x, vv1.y - vv2.y); + } + case 'Vector3': + { + let vv1 = v1 as Vector3; + let vv2 = v2 as Vector3; + return new Vector3(vv1.x - vv2.x, vv1.y - vv2.y, vv1.z - vv2.z) + } + case 'Vector4': + { + let vv1 = v1 as Vector4; + let vv2 = v2 as Vector4; + return new Vector4(vv1.x - vv2.x, vv1.y - vv2.y, vv1.z - vv2.z, vv1.w - vv2.w) + } + case 'Quaternion': + { + let vv1 = v1 as Quaternion; + let vv2 = v2 as Quaternion; + return new Quaternion(vv1.x - vv2.x, vv1.y - vv2.y, vv1.z - vv2.z, vv1.w - vv2.w) + } + default: + break; + } + + + } +} \ No newline at end of file diff --git a/src/math/enum/WrapTimeMode.ts b/src/math/enum/WrapTimeMode.ts new file mode 100644 index 00000000..b290d063 --- /dev/null +++ b/src/math/enum/WrapTimeMode.ts @@ -0,0 +1,11 @@ +/** + * Time Warp Mode + * @PingPong value min -> max -> min + * @Repeat value = value % repeatSpace + * @Clamp value = max(min( value , 1 ) , 0 ) + */ +export enum WrapTimeMode { + PingPong = 0, + Repeat = 1, + Clamp = 2, +} \ No newline at end of file diff --git a/src/math/navigation/DoubleArray.ts b/src/math/navigation/DoubleArray.ts new file mode 100644 index 00000000..25f0bb33 --- /dev/null +++ b/src/math/navigation/DoubleArray.ts @@ -0,0 +1,52 @@ +export class DoubleArray { + + private _keys: Array = new Array(); + + private _values: Array = new Array(); + + public getIndexByKey(key: any): number { + return this._keys.indexOf(key); + } + + public getValueByKey(key: any): any { + var index: number = this.getIndexByKey(key); + if (index > -1) { + return this._values[index]; + } + return null; + } + + public put(key: any, value: any): any { + if (key == null) + return null; + var old: any = this.remove(key); + this._keys.push(key); + this._values.push(value); + return old; + } + + public remove(key: any): any { + var index: number = this._keys.indexOf(key) + var item: any; + if (index > -1) { + item = this._values[index]; + this._keys.splice(index, 1); + this._values.splice(index, 1); + } + return item; + } + + public getValues(): Array { + return this._values; + } + + public getKeys(): Array { + return this._keys; + } + + public clear(): void { + this._values.length = 0; + this._keys.length = 0; + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DAstar.ts b/src/math/navigation/Navi3DAstar.ts new file mode 100644 index 00000000..41eeb91e --- /dev/null +++ b/src/math/navigation/Navi3DAstar.ts @@ -0,0 +1,108 @@ +import { Navi3DMaskType } from "./Navi3DMaskType"; +import { Navi3DMesh } from "./Navi3DMesh"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DAstar { + + private _openedList: Array; + private _closedList: Array; + private _endNode: Navi3DTriangle; + private _startNode: Navi3DTriangle; + private _triangleChannel: Array; + private _navMesh: Navi3DMesh; + private _findIndex: number = 0; + + constructor() { + this._openedList = new Array(); + this._closedList = new Array(); + } + + public findPath(navMesh: Navi3DMesh, startTriangle: Navi3DTriangle, endTriangle: Navi3DTriangle): boolean { + this._findIndex++; + this._navMesh = navMesh; + + this._startNode = startTriangle; + this._endNode = endTriangle; + + this._openedList.length = 0; + this._closedList.length = 0; + + if (this._startNode && this._endNode) { + this._startNode.gg = 0; + this._startNode.h = 0; + this._startNode.f = 0; + this._startNode.parent = null; + return this.search(); + } + return false; + } + + private search(): boolean { + var node: Navi3DTriangle = this._startNode; + var neibours: Array = []; + var test: Navi3DTriangle; + while (node != this._endNode) { + neibours = node.getNeibourTriangles(neibours, Navi3DMaskType.WalkAble, Navi3DMaskType.WalkAble); + for (test of neibours) { + if (test.closeId == this._findIndex) + continue; + if (test == node || !test.walkAble) { + continue; + } + var g: number = node.gg + Navi3DPoint.calcDistance(test, node) * test.costMultiplier; + var h: number = Navi3DPoint.calcDistance(test, this._endNode); + var f: number = g + h; + if (test.openId == this._findIndex) { + if (test.f > f) { + test.f = f; + test.gg = g; + test.h = h; + test.parent = node; + } + } + else { + test.f = f; + test.gg = g; + test.h = h; + test.parent = node; + test.openId = this._findIndex; + this._openedList.push(test); + } + } + node.closeId = this._findIndex; + this._closedList.push(node); + if (this._openedList.length == 0) { + return false; + } + this._openedList.sort(function (a: Navi3DTriangle, b: Navi3DTriangle) { + return a.f - b.f; + }); + node = (this._openedList.shift()); + } + this.buildPath(); + return true; + } + + private buildPath(): void { + this._triangleChannel = []; + var node: Navi3DTriangle = this._endNode; + this._triangleChannel.push(node); + while (node != this._startNode) { + node = node.parent; + this._triangleChannel.unshift(node); + } + } + + public get channel(): Array { + return this._triangleChannel; + } + +} + + + + + + + diff --git a/src/math/navigation/Navi3DConst.ts b/src/math/navigation/Navi3DConst.ts new file mode 100644 index 00000000..6483a107 --- /dev/null +++ b/src/math/navigation/Navi3DConst.ts @@ -0,0 +1,10 @@ +export class Navi3DConst { + public static SetConst(epsilon: number) { + this.EPSILON = epsilon; + this.POWER_EPSILON = epsilon * epsilon; + } + + public static EPSILON: number = 0.1; + + public static POWER_EPSILON: number = this.EPSILON * this.EPSILON; +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DEdge.ts b/src/math/navigation/Navi3DEdge.ts new file mode 100644 index 00000000..24cc45f9 --- /dev/null +++ b/src/math/navigation/Navi3DEdge.ts @@ -0,0 +1,147 @@ +import { Vector3 } from "../Vector3"; +import { Navi3DMaskType } from "./Navi3DMaskType"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DPointFat } from "./Navi3DPointFat"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DEdge { + + private _edgeMask: number = 0; + private _edgeSize: number = 0; + private _pointA: Navi3DPoint; + private _pointB: Navi3DPoint; + private _triangleOwners: Array; + private _centerPoint: Vector3; + + private _edgeDirA2B: Vector3; + + public crossPoint: Vector3; + + public fatPointA: Navi3DPointFat; + + public fatPointB: Navi3DPointFat; + + private static CALC_FAT_VECTOR: Vector3 = new Vector3(); + + constructor(point0: Navi3DPoint, point1: Navi3DPoint) { + this._pointA = point0; + this._pointB = point1; + if (point0.id >= point1.id) { + throw new Error("edge point order error!!!"); + } + this._triangleOwners = new Array(); + this._centerPoint = new Vector3(); + this._edgeMask = Navi3DMaskType.WalkAble; + Navi3DPoint.CALC_VECTOR3D1.setTo(point0.x - point1.x, point0.y - point1.y, point0.z - point1.z); + this._edgeSize = Navi3DPoint.CALC_VECTOR3D1.length; + + this._centerPoint.setTo((point0.x + point1.x) / 2, (point0.y + point1.y) / 2, (point0.z + point1.z) / 2); + } + + public get size(): Number { + return this._edgeSize; + } + + public get triangleOwners(): Array { + return this._triangleOwners; + } + + public get centerPoint(): Vector3 { + return this._centerPoint; + } + + public initFatPoints(radius: number): void { + this._edgeDirA2B = this._pointB.subtract(this._pointA); + this._edgeDirA2B.normalize(); + + this.fatPointA = this.fatPointA || new Navi3DPointFat(this._pointA, this); + this.fatPointB = this.fatPointB || new Navi3DPointFat(this._pointB, this); + + if (this.fatPointA.radius != radius) { + Navi3DEdge.CALC_FAT_VECTOR.copyFrom(this._edgeDirA2B); + Navi3DEdge.CALC_FAT_VECTOR.scaleBy(radius); + Navi3DEdge.CALC_FAT_VECTOR.incrementBy(this._pointA); + this.fatPointA.copyFrom(Navi3DEdge.CALC_FAT_VECTOR); + this.fatPointA.radius = radius; + } + + if (this.fatPointB.radius != radius) { + Navi3DEdge.CALC_FAT_VECTOR.copyFrom(this._edgeDirA2B); + Navi3DEdge.CALC_FAT_VECTOR.scaleBy(-radius); + Navi3DEdge.CALC_FAT_VECTOR.incrementBy(this._pointB); + this.fatPointB.copyFrom(Navi3DEdge.CALC_FAT_VECTOR); + this.fatPointB.radius = radius; + } + + } + + public getFatPoint(pt: Navi3DPoint): Navi3DPointFat { + if (pt == this._pointA) + return this.fatPointA; + return this.fatPointB; + } + + public getAnotherFatPoint(pt: Navi3DPoint): Navi3DPointFat { + if (pt == this._pointA) + return this.fatPointB; + return this.fatPointA; + } + + public getAnotherPoint(pt: Navi3DPoint): Navi3DPoint { + if (pt == this._pointA) + return this._pointB; + return this._pointA; + } + + public containsPoint(pt: Vector3): Navi3DPoint { + if (Navi3DPoint.equalPoint(pt, this._pointA)) + return this._pointA; + if (Navi3DPoint.equalPoint(pt, this._pointB)) + return this._pointB; + return null; + } + + public addTriangleOwners(triangle: Navi3DTriangle): void { + if (triangle.edges.indexOf(this) == -1) { + throw new Error("the edge is not belong triangle!!!"); + } + if (this._triangleOwners.indexOf(triangle) == -1) { + this._triangleOwners.push(triangle); + } + } + + public getPublicPoint(edge: Navi3DEdge): Navi3DPoint { + if (this._pointA == edge._pointA || this._pointA == edge._pointB) { + return this._pointA; + } + else if (this._pointB == edge._pointA || this._pointB == edge._pointB) { + return this._pointB; + } + return null; + } + + public getEqualPoint(p: Vector3): Navi3DPoint { + if (Navi3DPoint.equalPoint(p, this._pointA)) + return this._pointA; + if (Navi3DPoint.equalPoint(p, this._pointB)) + return this._pointB; + return null; + } + + public get pointA(): Navi3DPoint { + return this._pointA; + } + + public get pointB(): Navi3DPoint { + return this._pointB; + } + + public get walkAble(): boolean { + return (this._edgeMask & Navi3DMaskType.WalkAble) == Navi3DMaskType.WalkAble; + } + + public testMask(value: number): boolean { + return (this._edgeMask & value) == value; + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DFunnel.ts b/src/math/navigation/Navi3DFunnel.ts new file mode 100644 index 00000000..0d8c5269 --- /dev/null +++ b/src/math/navigation/Navi3DFunnel.ts @@ -0,0 +1,312 @@ +import { Plane3D } from "../Plane3D"; +import { PlaneClassification } from "../PlaneClassification"; +import { Vector3 } from "../Vector3"; +import { Navi3DConst } from "./Navi3DConst"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DPointFat } from "./Navi3DPointFat"; +import { Navi3DRouter } from "./Navi3DRouter"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DFunnel { + + private _aiRadius: number = 0; + + private _router: Navi3DRouter; + + private _result: Array; + + private _tempPublicEdgeList: Array = new Array(); + + private _tempSamePlaneList: Array = new Array(); + + private static CROSS_TEST_DIRECTION: Vector3 = new Vector3(); + + constructor() { + this._router = new Navi3DRouter(); + } + + public searchPath(startPt: Vector3, endPt: Vector3, triangleList: Array, radius: number = 0): boolean { + if (radius <= 0) + radius = 1; + this._aiRadius = radius * 1.5; + // + //起点终点判断 + if (!this.searchEnable(startPt, endPt, triangleList)) + return false; + + this.search(startPt, endPt, triangleList); + return true; + } + + public get path(): Array { + return this._result; + } + + private searchEnable(startPt: Vector3, endPt: Vector3, triangleList: Array): boolean { + if (startPt == null || endPt == null || triangleList == null) + return false; + + if (triangleList[0].plane.classifyPoint(startPt, Navi3DConst.EPSILON) != PlaneClassification.INTERSECT) { + return false; + } + if (triangleList[triangleList.length - 1].plane.classifyPoint(endPt, Navi3DConst.EPSILON) != PlaneClassification.INTERSECT) { + return false; + } + return true; + } + + private search(startPt: Vector3, endPt: Vector3, triangleList: Array): void { + this._tempPublicEdgeList.length = 0; + this._tempSamePlaneList.length = 0; + var i: number = 0; + var crossedEdgeCount: number = triangleList.length - 1; + var tr: Navi3DTriangle; + var curEdge: Navi3DEdge; + var pt: Vector3; + var plane: Plane3D; + var crossPoint: Vector3; + + for (i = 0; i < crossedEdgeCount; i++) { + curEdge = triangleList[i].getPublicEdge(triangleList[i + 1]); + curEdge.crossPoint = null; + curEdge.initFatPoints(this._aiRadius); + this._tempPublicEdgeList.push(curEdge); + tr = triangleList[i]; + plane = tr.plane; + tr = triangleList[i + 1]; + pt = tr.getEdgeAgainstPoint(curEdge); + + this._tempSamePlaneList.push(plane.classifyPoint(pt, Navi3DConst.EPSILON) == PlaneClassification.INTERSECT); + } + + this._router.continuePass(startPt, endPt, this._tempPublicEdgeList[0]); + crossedEdgeCount = this._tempPublicEdgeList.length; + + + var cornerPoint: Vector3; + var cornerEdge: Navi3DEdge; + var continuePass: boolean; + var lastEdge: boolean; + + for (i = 0; i < crossedEdgeCount; i++) { + curEdge = this._tempPublicEdgeList[i]; + tr = triangleList[i + 1]; + lastEdge = i == crossedEdgeCount - 1; + if (lastEdge) { + pt = endPt; + } + else { + pt = tr.getEdgeAgainstPoint(curEdge); + } + + continuePass = this._router.passEdge(curEdge, this._tempPublicEdgeList[i + 1], pt, lastEdge); + if (!continuePass) { + cornerPoint = this._router.cornerPoint; + cornerEdge = this._router.cornerEdge; + i = this._tempPublicEdgeList.indexOf(cornerEdge); + this._router.continuePass(cornerPoint, endPt, this._tempPublicEdgeList[i + 1]); + } + } + + + this.pushAllPathPoint2(startPt, endPt); + if (this._result.length >= 3) { + this.optimusTerminusFat(); + this.optimusByRadius(); + } + + //copy result + let list: Vector3[] = []; + for (let point of this._result) { + list.push(new Vector3().copyFrom(point)); + } + this._result = list; + } + + private optimusTerminusFat(): void { + var startFat: Navi3DPointFat; + var endFat: Navi3DPointFat; + var pt: any; + + pt = this._result[1]; + if (pt instanceof Navi3DPointFat) { + startFat = pt; + } + + pt = this._result[this._result.length - 2]; + if (pt instanceof Navi3DPointFat) { + endFat = pt; + } + + if (startFat) { + this._result[1] = startFat.scalePoint(); + } + if (endFat && startFat != endFat) { + this._result[this._result.length - 2] = endFat.scalePoint(); + } + + } + + private pushAllPathPoint2(startPt: Vector3, endPt: Vector3): void { + var crossedEdgeCount: number = this._tempPublicEdgeList.length; + var curEdge: Navi3DEdge; + var curEdgeJ: Navi3DEdge; + + this._result = new Array(); + this._result.push(startPt); + + + var fromPoint: Vector3 = startPt; + var toPoint: Vector3; + var fatPoint: Navi3DPointFat; + var crossPoint: Vector3; + + + for (var i: number = 0; i < crossedEdgeCount; i++) { + curEdge = this._tempPublicEdgeList[i]; + fatPoint = null; + if (curEdge.crossPoint) { + fatPoint = this.getFatPoint(curEdge, curEdge.crossPoint); + if (fatPoint) { + this._result.push(fatPoint); + } + else { + this._result.push(curEdge.crossPoint); + } + fromPoint = curEdge.crossPoint; + } + else { + curEdgeJ = null; + toPoint = null; + //找到下一个点 + for (var j: number = i + 1; j < crossedEdgeCount; j++) { + curEdgeJ = this._tempPublicEdgeList[j]; + toPoint = curEdgeJ.crossPoint; + if (toPoint) { + break; + } + } + + if (toPoint == null) { + toPoint = endPt; + } + fatPoint = this.getFatPoint(curEdge, toPoint); + if (fatPoint) { + this._result.push(fatPoint); + } + else { + if (toPoint == fromPoint) { + crossPoint = toPoint.clone(); + } else { + Navi3DFunnel.CROSS_TEST_DIRECTION.setTo(toPoint.x - fromPoint.x, 0, toPoint.z - fromPoint.z); + crossPoint = this._router.calcCrossEdge(curEdge, fromPoint, Navi3DFunnel.CROSS_TEST_DIRECTION); + } + this._result.push(crossPoint); + } + } + } + this._result.push(endPt); + } + + private optimusByRadius(): void { + var optimusResult: Array = new Array(); + optimusResult.length = this._result.length; + + var count: number = this._result.length - 2; + var pt0: Vector3; + var pt1: Vector3; + var pt2: Vector3; + + var fatPt0: Navi3DPointFat; + var fatPt1: Navi3DPointFat; + var fatPt2: Navi3DPointFat; + + var edgePt0: Navi3DPoint; + var edgePt1: Navi3DPoint; + var edgePt2: Navi3DPoint; + + + var centerEdge: Navi3DEdge; + + var checkEnable: boolean; + var optimusPoint: Vector3; + var i: number; + + + for (i = 0; i < count; i++) { + edgePt0 = edgePt1 = edgePt2 = null; + fatPt0 = fatPt1 = fatPt2 = null; + checkEnable = false; + optimusPoint = null; + + pt0 = this._result[i]; + pt1 = this._result[i + 1]; + pt2 = this._result[i + 2]; + if (pt0 instanceof Navi3DPointFat) { + fatPt0 = pt0; + } + if (pt1 instanceof Navi3DPointFat) { + fatPt1 = pt1; + } + if (pt2 instanceof Navi3DPointFat) { + fatPt2 = pt2; + } + + if (fatPt0) { + edgePt0 = fatPt0.ownerPoint; + } + if (fatPt1) { + edgePt1 = fatPt1.ownerPoint; + } + if (fatPt2) { + edgePt2 = fatPt2.ownerPoint; + } + + if (edgePt0 && edgePt1 && edgePt0 == edgePt1 && edgePt1 != edgePt2) { + checkEnable = true; + } + + if (edgePt2 && edgePt1 && edgePt2 == edgePt1 && edgePt0 != edgePt1) { + checkEnable = true; + } + + if (checkEnable) { + Navi3DFunnel.CROSS_TEST_DIRECTION.copyFrom(pt0); + Navi3DFunnel.CROSS_TEST_DIRECTION.decrementBy(pt2); + centerEdge = fatPt1.ownerEdge; + + checkEnable = this._router.hasCrossPoint(centerEdge.pointA, centerEdge.pointB, pt2, Navi3DFunnel.CROSS_TEST_DIRECTION); + if (checkEnable) { + optimusPoint = this._router.calcCrossPointOut(edgePt1, pt1, pt2, Navi3DFunnel.CROSS_TEST_DIRECTION); + } + if (optimusPoint) { + optimusResult[i + 1] = optimusPoint; + } + } + } + } + + private getFatPoint(edge: Navi3DEdge, target: Vector3): Navi3DPointFat { + if (edge == null) + return null; + var fatPoint: Navi3DPointFat; + if (target instanceof Navi3DPointFat) { + fatPoint = target; + } + var edgePoint: Navi3DPoint; + if (fatPoint) { + edgePoint = fatPoint.ownerPoint; + } + else { + edgePoint = edge.getEqualPoint(target); + } + + if (edgePoint == null) + return null; + fatPoint = edge.getFatPoint(edgePoint); + return fatPoint; + } + + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DMaskType.ts b/src/math/navigation/Navi3DMaskType.ts new file mode 100644 index 00000000..ba980ba4 --- /dev/null +++ b/src/math/navigation/Navi3DMaskType.ts @@ -0,0 +1,3 @@ +export class Navi3DMaskType { + public static WalkAble: number = 1; +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DMergeVertex.ts b/src/math/navigation/Navi3DMergeVertex.ts new file mode 100644 index 00000000..3d2c00e9 --- /dev/null +++ b/src/math/navigation/Navi3DMergeVertex.ts @@ -0,0 +1,63 @@ +import { GeometryBase } from "../../core/geometry/GeometryBase"; +import { VertexAttributeName } from "../../core/geometry/VertexAttributeName"; +import { Vector3 } from "../Vector3"; + +export class Navi3DMergeVertex { + vertex: Vector3[]; + indices: number[]; + + merge(geometry: GeometryBase, threshould: number = 0.1): this { + let vertex = geometry.getAttribute(VertexAttributeName.position).data; + this.makeOriginVertex(vertex); + + let sameVertexIndex: Map = new Map(); + let redirectionIndex: number[] = []; + let mergePointCount: number = 0; + for (let i = 0, c = this.vertex.length; i < c; i++) { + let item = this.vertex[i]; + let samePointIndex = -1; + sameVertexIndex.forEach((v, i) => { + let distance = Vector3.distance(v, item); + if (distance < threshould) { + samePointIndex = i; + } + }) + if (samePointIndex > -1) { + redirectionIndex[i] = samePointIndex; + // console.log('points merged:', i, samePointIndex); + mergePointCount++; + } else { + sameVertexIndex.set(i, item); + redirectionIndex[i] = i; + } + } + console.log('mergePointCount:', mergePointCount); + + //force modify indices + this.indices = []; + let indices = geometry.getAttribute(VertexAttributeName.indices).data; + for (const i of indices) { + this.indices.push(redirectionIndex[i]); + } + return this; + } + + parse(geometry: GeometryBase): this { + let vertex = geometry.getAttribute(VertexAttributeName.position).data; + this.makeOriginVertex(vertex); + this.indices = []; + let indices = geometry.getAttribute(VertexAttributeName.indices).data; + for (const i of indices) { + this.indices.push(i); + } + return this; + } + + private makeOriginVertex(source) { + this.vertex = []; + for (let i = 0, c = source.length / 3; i < c; i++) { + let v = new Vector3(source[i * 3], source[i * 3 + 1], source[i * 3 + 2]); + this.vertex.push(v); + } + } +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DMesh.ts b/src/math/navigation/Navi3DMesh.ts new file mode 100644 index 00000000..dc8e37d2 --- /dev/null +++ b/src/math/navigation/Navi3DMesh.ts @@ -0,0 +1,167 @@ +import { IQuadNode } from "../../core/tree/quad/IQuadNode"; +import { QuadRoot } from "../../core/tree/quad/QuadRoot"; +import { Vector3 } from "../Vector3"; +import { DoubleArray } from "./DoubleArray"; +import { Navi3DAstar } from "./Navi3DAstar"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DFunnel } from "./Navi3DFunnel"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DTriangle } from "./Navi3DTriangle"; + +export class Navi3DMesh { + + private _nav3dPoints: Array; + private _nav3dEdges: Array; + private _nav3dTriangles: Array; + private _path: Array; + private _edgesDict: DoubleArray; + + private _nav3dAstar: Navi3DAstar; + + private _nav3dFunnel: Navi3DFunnel; + + private _terrainQuad: QuadRoot; + + private _triangleList: Array; + + public get edges(): Array { + return this._nav3dEdges; + } + + public get points(): Array { + return this._nav3dPoints; + } + + public get path(): Array { + return this._path; + } + + public get triangles(): Array { + return this._nav3dTriangles; + } + + constructor(pointList: Array, triangleIndexList: Array>) { + this._nav3dPoints = new Array(); + this._nav3dEdges = new Array(); + this._nav3dTriangles = new Array(); + this._edgesDict = new DoubleArray(); + + this.initPoints(pointList); + this.initEdgesAndTriangles(triangleIndexList); + + this.createConnections(); + + + this._nav3dAstar = new Navi3DAstar(); + this._nav3dFunnel = new Navi3DFunnel(); + + + this._terrainQuad = new QuadRoot(8, 128); + this._terrainQuad.createQuadTree(this._nav3dTriangles); + } + + public getTriangleAtPoint(point: Vector3, threshold: number = 5): IQuadNode { + return this._terrainQuad.getTriangleAtPoint(point, threshold); + } + + public findPath(startPt: Vector3, endPt: Vector3, aiRadius: number = 5): boolean { + this._path = null; + this._triangleList = null; + + var startNode: Navi3DTriangle = this.getTriangleAtPoint(startPt, 10) as any; + var endNode: Navi3DTriangle = this.getTriangleAtPoint(endPt, 10) as any; + + var success: boolean = this._nav3dAstar.findPath(this, startNode, endNode); + if (success) { + this._triangleList = this._nav3dAstar.channel; + success = this._nav3dFunnel.searchPath(startPt, endPt, this._triangleList, aiRadius); + this._path = this._nav3dFunnel.path; + return success; + } + return false; + } + + private initPoints(pointList: Array): void { + var point: Vector3; + var nevPoint: Navi3DPoint; + var count: number = pointList.length; + for (var i: number = 0; i < count; i++) { + point = pointList[i]; + nevPoint = new Navi3DPoint(i, point.x, point.y, point.z); + this._nav3dPoints.push(nevPoint); + } + } + + private initEdgesAndTriangles(triangleIndexList: Array>): void { + var indexOrderList: Array; + + var edge0: Navi3DEdge; + var edge1: Navi3DEdge; + var edge2: Navi3DEdge; + + var triangle: Navi3DTriangle; + + var count: number = triangleIndexList.length; + for (var i: number = 0; i < count; i++) { + indexOrderList = triangleIndexList[i]; + edge0 = this.tryCreateEdge(indexOrderList[0], indexOrderList[1]); + edge1 = this.tryCreateEdge(indexOrderList[1], indexOrderList[2]); + edge2 = this.tryCreateEdge(indexOrderList[2], indexOrderList[0]); + + if (edge0 == null || edge1 == null || edge2 == null) + continue; + triangle = new Navi3DTriangle(i, edge0, edge1, edge2); + this._nav3dTriangles.push(triangle); + } + } + + private tryCreateEdge(pointAId: number, pointBId: number): Navi3DEdge { + if (pointAId == pointBId) { + throw new Error("edge point index error!!!"); + } + if (pointAId > pointBId) { + var tempId: number = pointAId; + pointAId = pointBId; + pointBId = tempId; + } + var edge: Navi3DEdge = this._edgesDict.getValueByKey(pointAId + "_" + pointBId); + if (edge == null) { + edge = new Navi3DEdge(this._nav3dPoints[pointAId], this._nav3dPoints[pointBId]); + this._nav3dEdges.push(edge); + this._edgesDict.put(pointAId + "_" + pointBId, edge); + + } + return edge; + } + + private createConnections(): void { + var triangleACount: number = this._nav3dTriangles.length; + var triangleBCount: number = this._nav3dTriangles.length; + var triangleA: Navi3DTriangle; + var triangleB: Navi3DTriangle; + var edge: Navi3DEdge; + var publicEdge: Navi3DEdge; + + for (var i: number = 0; i < triangleACount; i++) { + //边上面记录拥有这条边的三角形 + triangleA = this._nav3dTriangles[i]; + for (edge of triangleA.edges) { + edge.addTriangleOwners(triangleA); + } + + for (var j: number = 0; j < triangleBCount; j++) { + //三角形相邻关系 + triangleB = this._nav3dTriangles[j]; + if (triangleA == triangleB) + continue; + publicEdge = triangleA.loopPublicEdge(triangleB); + if (publicEdge) { + triangleA.addNeibour(publicEdge, triangleB); + triangleB.addNeibour(publicEdge, triangleA); + } + } + } + + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DPoint.ts b/src/math/navigation/Navi3DPoint.ts new file mode 100644 index 00000000..ce54494e --- /dev/null +++ b/src/math/navigation/Navi3DPoint.ts @@ -0,0 +1,36 @@ +import { Vector3 } from "../Vector3"; +import { Navi3DConst } from "./Navi3DConst"; + +export class Navi3DPoint extends Vector3 { + + public static CALC_VECTOR3D1: Vector3 = new Vector3(); + + public static CALC_VECTOR3D2: Vector3 = new Vector3(); + + public static CALC_VECTOR3D3: Vector3 = new Vector3(); + + public static CALC_VECTOR3D4: Vector3 = new Vector3(); + + public static CALC_VECTOR3D5: Vector3 = new Vector3(); + + private _pointId: number = 0; + + constructor(id: number, X: number, Y: number, Z: number) { + super(X, Y, Z, 0); + this._pointId = id; + } + + public get id(): number { + return this._pointId; + } + + public static equalPoint(p1: Vector3, p2: Vector3): boolean { + return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z) < Navi3DConst.POWER_EPSILON; + } + + public static calcDistance(pt1: Vector3, pt2: Vector3): number { + Navi3DPoint.CALC_VECTOR3D3.setTo(pt1.x - pt2.x, pt1.y - pt2.y, pt1.z - pt2.z); + return Navi3DPoint.CALC_VECTOR3D3.length; + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DPoint2D.ts b/src/math/navigation/Navi3DPoint2D.ts new file mode 100644 index 00000000..ce9ac6cb --- /dev/null +++ b/src/math/navigation/Navi3DPoint2D.ts @@ -0,0 +1,36 @@ +export class Navi3DPoint2D { + public x: number; + + public y: number; + + public setTo(X: number, Y: number): void { + this.x = X; + this.y = Y; + } + + public equals(X: number, Y: number): boolean { + return X == this.x && Y == this.y; + } + + public equalPoint(pt: Navi3DPoint2D): boolean { + return this.equals(pt.x, pt.y); + } + + public get length(): number { + return Math.sqrt(this.x * this.x + this.y * this.y); + } + + public clone(): Navi3DPoint2D { + var point: Navi3DPoint2D = new Navi3DPoint2D(); + point.setTo(this.x, this.y); + return point; + } + + public normalize(): void { + var size: number = length; + if (size == 0) + return; + this.setTo(this.x / size, this.y / size); + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DPointFat.ts b/src/math/navigation/Navi3DPointFat.ts new file mode 100644 index 00000000..76725f6a --- /dev/null +++ b/src/math/navigation/Navi3DPointFat.ts @@ -0,0 +1,36 @@ +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DPoint } from "./Navi3DPoint"; + +export class Navi3DPointFat extends Navi3DPoint { + + private _ownerPoint: Navi3DPoint; + private _ownerEdge: Navi3DEdge; + + public radius: number = 0; + + constructor(_point: Navi3DPoint, _edge: Navi3DEdge) { + super(_point.id, 0, 0, 0); + this._ownerEdge = _edge; + this._ownerPoint = _point; + } + + public get ownerPoint(): Navi3DPoint { + return this._ownerPoint; + } + + public get ownerEdge(): Navi3DEdge { + return this._ownerEdge; + } + + public scalePoint(value: number = 0.7): Navi3DPointFat { + var point: Navi3DPointFat = new Navi3DPointFat(this._ownerPoint, this._ownerEdge); + point.copyFrom(this); + point.decrementBy(this._ownerPoint); + point.scaleBy(value); + point.radius = point.length; + point.incrementBy(this._ownerPoint); + return point; + + } + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DRouter.ts b/src/math/navigation/Navi3DRouter.ts new file mode 100644 index 00000000..91d5ba3b --- /dev/null +++ b/src/math/navigation/Navi3DRouter.ts @@ -0,0 +1,218 @@ +import { Vector3 } from "../Vector3"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DPoint } from "./Navi3DPoint"; + +export class Navi3DRouter { + + public endPoint: Vector3; + + public curPoint: Vector3; + + public rayA: Vector3; + + public rayB: Vector3; + + public rayAPoint: Navi3DPoint; + + public rayBPoint: Navi3DPoint; + + public static RAY_1: Vector3 = new Vector3(); + + public static RAY_2: Vector3 = new Vector3(); + + public static TEST_RAY: Vector3 = new Vector3(); + + public static TEST_RAY_1: Vector3 = new Vector3(); + + public static TEST_RAY_2: Vector3 = new Vector3(); + + private static CALC_CROSS_POINT: Vector3 = new Vector3(); + + private static CALC_CROSS_TEST: Vector3 = new Vector3(); + + public cornerPoint: Navi3DPoint; + + public cornerEdge: Navi3DEdge; + + public continuePass(fromPt: Vector3, endPt: Vector3, fromEdge: Navi3DEdge): void { + this.resetData(); + this.curPoint = fromPt; + this.endPoint = endPt; + this.cornerEdge = fromEdge; + } + + public passEdge(commonEdge: Navi3DEdge, nextCommonEdge: Navi3DEdge, targetPoint: Vector3, lastEdge: boolean): boolean { + if (this.rayA == null || this.rayB == null) { + this.rayA = Navi3DRouter.RAY_1; + this.rayB = Navi3DRouter.RAY_2; + this.rayAPoint = commonEdge.pointA; + this.rayBPoint = commonEdge.pointB; + + this.rayA.setTo(this.rayAPoint.x - this.curPoint.x, 0, this.rayAPoint.z - this.curPoint.z); + this.rayB.setTo(this.rayBPoint.x - this.curPoint.x, 0, this.rayBPoint.z - this.curPoint.z); + } + + if (lastEdge) { + return this.checkEndPoint(targetPoint); + } + + Navi3DRouter.TEST_RAY.setTo(targetPoint.x - this.curPoint.x, 0, targetPoint.z - this.curPoint.z); + + if (this.isPointAtCenter(Navi3DRouter.TEST_RAY, this.rayA, this.rayB)) { + if (!this.hasCrossPoint(nextCommonEdge.pointA, nextCommonEdge.pointB, this.rayAPoint, this.rayA)) { + this.rayA.copyFrom(Navi3DRouter.TEST_RAY); + if (targetPoint instanceof Navi3DPoint) { + this.rayAPoint = targetPoint; + } + else { + this.rayAPoint = null; + } + + } + else { + this.rayB.copyFrom(Navi3DRouter.TEST_RAY); + if (targetPoint instanceof Navi3DPoint) { + this.rayBPoint = targetPoint; + } + else { + this.rayBPoint = null; + } + } + + var anotherPoint: Navi3DPoint = nextCommonEdge.getAnotherPoint(targetPoint); + Navi3DRouter.TEST_RAY.setTo(anotherPoint.x - this.curPoint.x, 0, anotherPoint.z - this.curPoint.z); + if (anotherPoint == this.rayAPoint || anotherPoint == this.rayBPoint || this.isPointAtCenter(Navi3DRouter.TEST_RAY, this.rayA, this.rayB)) { + this.cornerEdge = nextCommonEdge; + } + } + else { + var needReturn: boolean; + Navi3DRouter.TEST_RAY_1.copyFrom(nextCommonEdge.pointA); + Navi3DRouter.TEST_RAY_1.decrementBy(this.curPoint); + Navi3DRouter.TEST_RAY_2.copyFrom(nextCommonEdge.pointB); + Navi3DRouter.TEST_RAY_2.decrementBy(this.curPoint); + Navi3DRouter.TEST_RAY_1.y = 0; + Navi3DRouter.TEST_RAY_2.y = 0; + if (this.isPointAtCenter(this.rayA, Navi3DRouter.TEST_RAY_1, Navi3DRouter.TEST_RAY_2) + || this.isPointAtCenter(this.rayB, Navi3DRouter.TEST_RAY_1, Navi3DRouter.TEST_RAY_2)) { + needReturn = false; + } + else { + needReturn = true; + } + + if (needReturn) { + if (this.isPointAtCenter(this.rayA, Navi3DRouter.TEST_RAY, this.rayB)) { + this.cornerPoint = this.rayAPoint; + } + else { + this.cornerPoint = this.rayBPoint; + } + + this.cornerEdge.crossPoint = this.cornerPoint; + return false; + } + } + return true; + } + + private checkEndPoint(targetPoint: Vector3): boolean { + + Navi3DRouter.TEST_RAY.setTo(targetPoint.x - this.curPoint.x, 0, targetPoint.z - this.curPoint.z); + if (this.isPointAtCenter(Navi3DRouter.TEST_RAY, this.rayA, this.rayB)) { + // + } + else { + if (this.isPointAtCenter(this.rayA, Navi3DRouter.TEST_RAY, this.rayB)) { + this.cornerPoint = this.rayAPoint; + } + else { + this.cornerPoint = this.rayBPoint; + } + this.cornerEdge.crossPoint = this.cornerPoint; + return false; + } + return true; + } + + public calcCrossEdge(_edge: Navi3DEdge, linePoint: Vector3, lineDirection: Vector3): Vector3 { + return this.calcCrossPoint(_edge.fatPointA, _edge.fatPointB, linePoint, lineDirection); + } + + public calcCrossPoint(segmentPt1: Vector3, segmentPt2: Vector3, linePoint: Vector3, lineDirection: Vector3): Vector3 { + Navi3DRouter.CALC_CROSS_POINT.copyFrom(segmentPt2); + Navi3DRouter.CALC_CROSS_POINT.decrementBy(segmentPt1); + + let distance = Navi3DRouter.CALC_CROSS_POINT.x * lineDirection.z - lineDirection.x * Navi3DRouter.CALC_CROSS_POINT.z; + var scale: number = 0; + if (distance != 0) { + scale = ((segmentPt1.z - linePoint.z) * lineDirection.x - (segmentPt1.x - linePoint.x) * lineDirection.z) / distance; + } + + if (scale > 1) { + scale = 1; + } + else if (scale < 0) { + scale = 0; + } + Navi3DRouter.CALC_CROSS_POINT.scaleBy(scale); + Navi3DRouter.CALC_CROSS_POINT.incrementBy(segmentPt1); + return Navi3DRouter.CALC_CROSS_POINT.clone(); + } + + public calcCrossPointOut(segmentPt1: Vector3, segmentPt2: Vector3, linePoint: Vector3, lineDirection: Vector3): Vector3 { + Navi3DRouter.CALC_CROSS_POINT.copyFrom(segmentPt2); + Navi3DRouter.CALC_CROSS_POINT.decrementBy(segmentPt1); + + var scale: number = ((segmentPt1.z - linePoint.z) * lineDirection.x - (segmentPt1.x - linePoint.x) * lineDirection.z) / + (Navi3DRouter.CALC_CROSS_POINT.x * lineDirection.z - lineDirection.x * Navi3DRouter.CALC_CROSS_POINT.z); + + if (scale <= 1 && scale >= 0) { + return null; + } + Navi3DRouter.CALC_CROSS_POINT.scaleBy(scale); + Navi3DRouter.CALC_CROSS_POINT.incrementBy(segmentPt1); + return Navi3DRouter.CALC_CROSS_POINT.clone(); + } + + public hasCrossPoint(segmentPt1: Vector3, segmentPt2: Vector3, linePoint: Vector3, lineDirection: Vector3): boolean { + Navi3DRouter.CALC_CROSS_TEST.copyFrom(segmentPt2); + Navi3DRouter.CALC_CROSS_TEST.decrementBy(segmentPt1); + + var scale: number = ((segmentPt1.z - linePoint.z) * lineDirection.x - (segmentPt1.x - linePoint.x) * lineDirection.z) / + (Navi3DRouter.CALC_CROSS_TEST.x * lineDirection.z - lineDirection.x * Navi3DRouter.CALC_CROSS_TEST.z); + return scale <= 1 && scale >= 0; + } + + private isPointAtCenter(point: Vector3, vectorA: Vector3, vectorB: Vector3): boolean { + var cp1: Vector3 = vectorA.crossProduct(point); + if (cp1.length == 0 && point.length < vectorA.length) { + return true; + } + + var cp2: Vector3 = vectorB.crossProduct(point); + if (cp2.length == 0 && point.length < vectorB.length) { + return true; + } + + cp1.normalize(); + cp2.normalize(); + cp1.incrementBy(cp2); + + return cp1.length < 0.01; + } + + public resetData(): void { + this.cornerEdge = null; + this.cornerPoint = null; + + this.curPoint = null; + this.rayA = this.rayB = null; + this.rayAPoint = this.rayBPoint = null; + + Navi3DRouter.RAY_1.setTo(0, 0, 0); + Navi3DRouter.RAY_2.setTo(0, 0, 0); + } + + +} \ No newline at end of file diff --git a/src/math/navigation/Navi3DTriangle.ts b/src/math/navigation/Navi3DTriangle.ts new file mode 100644 index 00000000..d2c8d783 --- /dev/null +++ b/src/math/navigation/Navi3DTriangle.ts @@ -0,0 +1,222 @@ +import { IQuadNode } from "../../core/tree/quad/IQuadNode"; +import { QuadAABB } from "../../core/tree/quad/QuadAABB"; +import { Plane3D } from "../Plane3D"; +import { Vector3 } from "../Vector3"; +import { DoubleArray } from "./DoubleArray"; +import { Navi3DEdge } from "./Navi3DEdge"; +import { Navi3DMaskType } from "./Navi3DMaskType"; +import { Navi3DPoint } from "./Navi3DPoint"; +import { Navi3DPoint2D } from "./Navi3DPoint2D"; + +export class Navi3DTriangle extends Vector3 implements IQuadNode { + + private _id: number = 0; + private _plane: Plane3D; + private _points: Array = new Array(); + + private _edges: Array = new Array(); + + private _neibourTriangles: DoubleArray = new DoubleArray(); + + private _pointAgainstEdge: DoubleArray = new DoubleArray(); + + private _edgeAgainstPoint: DoubleArray = new DoubleArray(); + + private _mask: number = 0; + + private _aabbBox: QuadAABB; + + public f: number = 0; + + public gg: number = 0; + + public h: number = 0; + + public parent: Navi3DTriangle; + + public costMultiplier: number = 1.0; + + public openId: number = 0; + + public closeId: number = 0; + + public get aabb(): QuadAABB { + return this._aabbBox; + } + + public initAABB(): void { + this._aabbBox = new QuadAABB(); + //添加节点 + this._aabbBox.addPoint(this._points[0]); + this._aabbBox.addPoint(this._points[1]); + this._aabbBox.addPoint(this._points[2]); + } + + public calcGlobalQuadAABB(): void { + } + + public get isTriangle(): boolean { + return true; + } + + constructor(Id: number, edgeA: Navi3DEdge, edgeB: Navi3DEdge, edgeC: Navi3DEdge) { + super(0, 0, 0, 0); + + this._id = Id; + this._mask = Navi3DMaskType.WalkAble; + this._edges.push(edgeA, edgeB, edgeC); + var edge: Navi3DEdge; + for (edge of this._edges) { + if (this._points.indexOf(edge.pointA) == -1) { + this._points.push(edge.pointA); + } + if (this._points.indexOf(edge.pointB) == -1) { + this._points.push(edge.pointB); + } + } + + this.x = (this._points[0].x + this._points[1].x + this._points[2].x) / 3; + this.y = (this._points[0].y + this._points[1].y + this._points[2].y) / 3; + this.z = (this._points[0].z + this._points[1].z + this._points[2].z) / 3; + + this._plane = new Plane3D(); + this._plane.fromPoints(this._points[0], this._points[1], this._points[2]); + this._plane.normalize(); + + this.genarateAgainstData(); + + this.initAABB(); + } + + private genarateAgainstData(): void { + var edge: Navi3DEdge; + var point: Navi3DPoint; + for (edge of this._edges) { + for (point of this._points) { + if (edge.pointA != point && edge.pointB != point) { + this._edgeAgainstPoint.put(edge, point); + this._pointAgainstEdge.put(point, edge); + } + } + } + } + + public get id(): number { + return this._id; + } + + public get plane(): Plane3D { + return this._plane; + } + + public get points(): Array { + return this._points; + } + + public addNeibour(edge: Navi3DEdge, triangle: Navi3DTriangle): void { + if (this._edges.indexOf(edge) >= 0) { + this._neibourTriangles.put(edge, triangle); + } + else { + throw new Error("the edge is not in triangle!!!"); + } + } + + public getNeibourTriangles(list: Array = null, edgeMask: number = 1, triangleMask: number = 1): Array { + list = list || new Array(); + list.length = 0; + var neibour: Navi3DTriangle; + var edge: Navi3DEdge; + var keys: Array = this._neibourTriangles.getKeys(); + var obj: any; + for (obj of keys) { + edge = obj; + if (edge.testMask(edgeMask)) { + neibour = this._neibourTriangles.getValueByKey(edge); + if (neibour.testMask(triangleMask)) { + list.push(neibour); + } + } + } + return list; + + } + + public getEdges(list: Array = null, edgeMask: number = 1): Array { + list = list || new Array(); + list.length = 0; + var edge: Navi3DEdge; + for (edge of this._edges) { + if (edge.testMask(edgeMask)) { + list.push(edge); + } + } + return list; + } + + public get walkAble(): boolean { + return this.testMask(Navi3DMaskType.WalkAble); + } + + public get edges(): Array { + return this._edges; + } + + public testMask(value: number): boolean { + return (this._mask & value) == value; + } + + public getEdgeAgainstPoint(edge: Navi3DEdge): Navi3DPoint { + return this._edgeAgainstPoint.getValueByKey(edge); + } + + public getPointAgainstEdge(point: Navi3DPoint): Navi3DEdge { + return this._pointAgainstEdge.getValueByKey(point); + } + + public getPublicEdge(triangle: Navi3DTriangle): Navi3DEdge { + if (triangle && triangle != this) { + var keys: Array = this._neibourTriangles.getKeys(); + var obj: any; + for (obj of keys) { + if (this._neibourTriangles.getValueByKey(obj) == triangle) + return obj; + } + } + return null; + } + + public loopPublicEdge(triangle: Navi3DTriangle): Navi3DEdge { + var edgeA: Navi3DEdge; + var edgeB: Navi3DEdge; + if (triangle && triangle != this) { + for (edgeA of this._edges) { + for (edgeB of triangle._edges) { + if (edgeA == edgeB) + return edgeA; + } + } + } + return null; + } + + public randomPoint(): Vector3 { + var pt0: Vector3 = this._points[2].subtract(this._points[0]); + // if(Math.random() > 0.5) + { + pt0.scaleBy(Math.random()); + } + pt0.incrementBy(this._points[0]); + + var pt1: Vector3 = this._points[1].subtract(pt0); + + // if(Math.random() > 0.5) + { + pt1.scaleBy(Math.random()); + } + pt1.incrementBy(pt0); + + return pt1; + } + +} \ No newline at end of file diff --git a/src/setting/EngineSetting.ts b/src/setting/EngineSetting.ts index 24a578bd..932afe8e 100644 --- a/src/setting/EngineSetting.ts +++ b/src/setting/EngineSetting.ts @@ -1,5 +1,6 @@ import { GlobalIlluminationSetting } from "./GlobalIlluminationSetting"; import { LightSetting } from "./LightSetting"; +import { LoaderSetting } from "./LoaderSetting"; import { MaterialSetting } from "./MaterialSetting"; import { OcclusionQuerySetting } from "./OcclusionQuerySetting"; import { PickSetting } from "./PickSetting"; @@ -48,4 +49,9 @@ export type EngineSetting = { * @internal */ material: MaterialSetting; + + /** + * loader setting + */ + loader: LoaderSetting; } \ No newline at end of file diff --git a/src/setting/LoaderSetting.ts b/src/setting/LoaderSetting.ts new file mode 100644 index 00000000..eb6489ea --- /dev/null +++ b/src/setting/LoaderSetting.ts @@ -0,0 +1,11 @@ + +/** + * Loader Setting + * @group Setting + */ +export type LoaderSetting = { + /** + * Number of concurrent loading + */ + numConcurrent: number; +}; diff --git a/src/setting/RenderSetting.ts b/src/setting/RenderSetting.ts index 2bfc6e8c..f050347a 100644 --- a/src/setting/RenderSetting.ts +++ b/src/setting/RenderSetting.ts @@ -1,10 +1,10 @@ -import { BloomSetting } from "./post/BloomSetting"; import { DepthOfViewSetting } from "./post/DepthOfViewSetting"; import { GlobalFogSetting } from "./post/GlobalFogSetting"; import { GTAOSetting } from "./post/GTAOSetting"; import { OutlineSetting } from "./post/OutlineSetting"; import { SSRSetting } from "./post/SSRSetting"; import { TAASetting } from "./post/TAASetting"; +import { BloomSetting } from "./post/BloomSetting"; export type RenderSetting = { debug: boolean; @@ -30,7 +30,7 @@ export type RenderSetting = { */ postProcessing: { enable?: boolean; - bloom?: BloomSetting; + bloom?: BloomSetting, ssao?: { debug: any; enable: boolean; diff --git a/src/setting/ShadowSetting.ts b/src/setting/ShadowSetting.ts index f287a342..c0d7e3cf 100644 --- a/src/setting/ShadowSetting.ts +++ b/src/setting/ShadowSetting.ts @@ -46,6 +46,10 @@ export type ShadowSetting = { * shadow mapping Size */ shadowSize: number; + /** + * shadow depth offset bias + */ + shadowBias: number; /** * Shadow softness */ diff --git a/src/setting/post/BloomSetting.ts b/src/setting/post/BloomSetting.ts index 2d480a56..11b75e6e 100644 --- a/src/setting/post/BloomSetting.ts +++ b/src/setting/post/BloomSetting.ts @@ -4,37 +4,12 @@ * @group Setting */ export type BloomSetting = { - /** - * enable - */ - enable: boolean; - /** - * Screen horizontal blur radius - */ - blurX: number; - /** - * Screen vertical blur radius - */ - blurY: number; - /** - * Strength setting - */ - strength: number; - - /** - * exposure setting - */ - exposure?: number; - /** - * Radius setting - */ - radius: number; - /** - * Luminosity threshold - */ - luminosityThreshold: number; - /** - * use debug or not - */ - debug: boolean; + enable?: boolean, + downSampleStep: number; + downSampleBlurSize: number; + downSampleBlurSigma: number; + upSampleBlurSize: number; + upSampleBlurSigma: number; + luminanceThreshole: number; + bloomIntensity: number; }; \ No newline at end of file diff --git a/src/shape/BoxGeometry.ts b/src/shape/BoxGeometry.ts index c68456b2..bce84985 100644 --- a/src/shape/BoxGeometry.ts +++ b/src/shape/BoxGeometry.ts @@ -196,7 +196,10 @@ export class BoxGeometry extends GeometryBase { indexStart: 0, indexCount: indices_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); } diff --git a/src/shape/CylinderGeometry.ts b/src/shape/CylinderGeometry.ts index a03baad7..0a853237 100644 --- a/src/shape/CylinderGeometry.ts +++ b/src/shape/CylinderGeometry.ts @@ -79,7 +79,10 @@ export class CylinderGeometry extends GeometryBase { indexStart: start, indexCount: count, vertexStart: start, + vertexCount: 0, + firstStart: 0, index: index, + topology: 0, }); } diff --git a/src/shape/PlaneGeometry.ts b/src/shape/PlaneGeometry.ts index 3c4b78e2..e308dfa6 100644 --- a/src/shape/PlaneGeometry.ts +++ b/src/shape/PlaneGeometry.ts @@ -146,7 +146,10 @@ export class PlaneGeometry extends GeometryBase { indexStart: 0, indexCount: indices_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0 }); } diff --git a/src/shape/SphereGeometry.ts b/src/shape/SphereGeometry.ts index 645122d8..53913108 100644 --- a/src/shape/SphereGeometry.ts +++ b/src/shape/SphereGeometry.ts @@ -103,7 +103,7 @@ export class SphereGeometry extends GeometryBase { normal_arr[ni++] = z * normLen; uv_arr[ui++] = i / _segmentsW; - uv_arr[ui++] = j / _segmentsH; + uv_arr[ui++] = 1.0 - j / _segmentsH; if (i > 0 && j > 0) { var a: number = (_segmentsW + 1) * j + i; @@ -156,7 +156,10 @@ export class SphereGeometry extends GeometryBase { indexStart: 0, indexCount: indice_arr.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0 }); this.bounds = new BoundingBox(Vector3.ZERO, new Vector3(this.radius * 2, this.radius * 2, this.radius * 2)) diff --git a/src/shape/StripeGeometry.ts b/src/shape/StripeGeometry.ts new file mode 100644 index 00000000..f7a4dc36 --- /dev/null +++ b/src/shape/StripeGeometry.ts @@ -0,0 +1,83 @@ +import { BoundingBox } from "../core/bound/BoundingBox"; +import { GeometryBase } from "../core/geometry/GeometryBase"; +import { VertexAttributeName } from "../core/geometry/VertexAttributeName"; +import { Vector3 } from "../math/Vector3"; + +/** + * Plane geometry + * @group Geometry + */ +export class StripeGeometry extends GeometryBase { + + segments: [Vector3, Vector3][]; + /** + * + * @constructor + * @param width Width of the plane + * @param height Height of the plane + * @param segmentW Number of width segments of a plane + * @param segmentH Number of height segments of a plane + * @param up Define the normal vector of a plane + */ + constructor(segments: [Vector3, Vector3][]) { + super(); + // this.geometrySource = new SerializeGeometrySource().setPrimitive('primitive-plane'); + this.segments = segments; + this.buildGeometry(); + } + + private buildGeometry(): void { + + this.bounds = new BoundingBox(); + let numIndices = (this.segments.length - 1) * 2 * 3; + + let vertexCount = this.segments.length * 2; + let position_arr = new Float32Array(vertexCount * 3); + let normal_arr = new Float32Array(vertexCount * 3); + let uv_arr = new Float32Array(vertexCount * 2); + let indices_arr = new Uint16Array(numIndices); + //210 123 + + let index = 0; + for (let item of this.segments) { + position_arr[index++] = item[0].x; + position_arr[index++] = item[0].y; + position_arr[index++] = item[0].z; + position_arr[index++] = item[1].x; + position_arr[index++] = item[1].y; + position_arr[index++] = item[1].z; + } + + index = 0; + let offset = 0; + while (index < numIndices) { + indices_arr[index++] = 2 + offset; + indices_arr[index++] = 1 + offset; + indices_arr[index++] = 0 + offset; + indices_arr[index++] = 1 + offset; + indices_arr[index++] = 2 + offset; + indices_arr[index++] = 3 + offset; + + offset += 2; + } + + this.setIndices(indices_arr); + this.setAttribute(VertexAttributeName.position, position_arr); + this.setAttribute(VertexAttributeName.normal, normal_arr); + this.setAttribute(VertexAttributeName.uv, uv_arr); + this.setAttribute(VertexAttributeName.TEXCOORD_1, uv_arr); + + this.addSubGeometry({ + indexStart: 0, + indexCount: indices_arr.length, + vertexStart: 0, + vertexCount: 0, + firstStart: 0, + index: 0, + topology: 0, + }); + + this.computeNormals(); + } + +} diff --git a/src/shape/TorusGeometry.ts b/src/shape/TorusGeometry.ts index 8e516f61..169cee0d 100644 --- a/src/shape/TorusGeometry.ts +++ b/src/shape/TorusGeometry.ts @@ -114,7 +114,10 @@ export class TorusGeometry extends GeometryBase { indexStart: 0, indexCount: indicesData.length, vertexStart: 0, + vertexCount: 0, + firstStart: 0, index: 0, + topology: 0, }); } diff --git a/src/textures/BitmapTexture2D.ts b/src/textures/BitmapTexture2D.ts index 15751ede..06f30a03 100644 --- a/src/textures/BitmapTexture2D.ts +++ b/src/textures/BitmapTexture2D.ts @@ -10,6 +10,7 @@ import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; */ export class BitmapTexture2D extends Texture { private _source: HTMLCanvasElement | ImageBitmap | OffscreenCanvas | HTMLImageElement; + public premultiplyAlpha: PremultiplyAlpha = 'none'; /** * @constructor @@ -18,6 +19,10 @@ export class BitmapTexture2D extends Texture { constructor(useMipmap: boolean = true) { super(); this.useMipmap = useMipmap; + + this.lodMinClamp = 0; + this.lodMaxClamp = 4; + // this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; } @@ -37,7 +42,7 @@ export class BitmapTexture2D extends Texture { if (this._source instanceof HTMLImageElement) { this._source.decode().then(async () => { if (this._source instanceof HTMLImageElement) { - const imageBitmap = await createImageBitmap(this._source, { imageOrientation: this.flipY ? "flipY" : "from-image" }); + const imageBitmap = await createImageBitmap(this._source, { imageOrientation: this.flipY ? "flipY" : "from-image", premultiplyAlpha: 'none' }); this.generate(imageBitmap); } }); @@ -55,6 +60,7 @@ export class BitmapTexture2D extends Texture { * @param loaderFunctions callback function when load complete */ public async load(url: string, loaderFunctions?: LoaderFunctions) { + this.name = StringUtil.getURLName(url); if (url.indexOf(';base64') != -1) { const img = document.createElement('img'); let start = url.indexOf('data:image'); @@ -66,25 +72,32 @@ export class BitmapTexture2D extends Texture { const imageBitmap = await createImageBitmap(img, { resizeWidth: img.width, resizeHeight: img.height, - imageOrientation: this.flipY ? "flipY" : "from-image" + imageOrientation: this.flipY ? "flipY" : "from-image", + premultiplyAlpha: 'none' }); this.format = GPUTextureFormat.rgba8unorm; this.generate(imageBitmap); } else { - const r = await fetch(url, { - headers: Object.assign({ - 'Accept': 'image/avif,image/webp,*/*' - }, loaderFunctions?.headers) - }); - // const img = await r.blob(); - // await this.loadFromBlob(img); - let chunks = await LoaderBase.read(url, r, loaderFunctions); - let img = new Blob([chunks], { type: 'image/jpeg' }); - chunks = null; + return new Promise((succ, fial) => { + fetch(url, { + headers: Object.assign({ + 'Accept': 'image/avif,image/webp,*/*' + }, loaderFunctions?.headers) + }).then((r) => { + // const img = await r.blob(); + // await this.loadFromBlob(img); + LoaderBase.read(url, r, loaderFunctions).then((chunks) => { + let img = new Blob([chunks], { type: 'image/jpeg' }); + chunks = null; + this.loadFromBlob(img).then(() => { + succ(true); + }); + }); + + }) + }) - await this.loadFromBlob(img); } - this.name = StringUtil.getURLName(url); return true; } @@ -96,14 +109,15 @@ export class BitmapTexture2D extends Texture { */ public async loadFromBlob(imgData: Blob) { this.imageData = imgData; - let imageBitmap = await createImageBitmap(imgData, { imageOrientation: this.flipY ? 'flipY' : 'from-image' }); + let imageBitmap = await createImageBitmap(imgData, { imageOrientation: this.flipY ? 'flipY' : 'from-image', premultiplyAlpha: 'none' }); if (imageBitmap.width < 32 || imageBitmap.height < 32) { let width = Math.max(imageBitmap.width, 32); let height = Math.max(imageBitmap.height, 32); imageBitmap = await createImageBitmap(imageBitmap, { resizeWidth: width, resizeHeight: height, - imageOrientation: this.flipY ? "flipY" : "from-image" + imageOrientation: this.flipY ? "flipY" : "from-image", + premultiplyAlpha: 'none' }); } this.format = GPUTextureFormat.rgba8unorm; diff --git a/src/textures/BitmapTexture2DArray.ts b/src/textures/BitmapTexture2DArray.ts index 6a530a84..a07c316c 100644 --- a/src/textures/BitmapTexture2DArray.ts +++ b/src/textures/BitmapTexture2DArray.ts @@ -51,11 +51,11 @@ export class BitmapTexture2DArray extends Texture implements ITexture { if (bitmapTexture.width != this.width || bitmapTexture.height != this.height) { console.error("bitmap texture muse match bitmapTextureArray size!"); } - if (this._bitmapTextures.indexOf(bitmapTexture) == -1) { - bitmapTexture.pid = this._bitmapTextures.length; - this._bitmapTextures.push(bitmapTexture); - this.updateTexture(); - } + // if (this._bitmapTextures.indexOf(bitmapTexture) == -1) { + bitmapTexture.pid = this._bitmapTextures.length; + this._bitmapTextures.push(bitmapTexture); + this.updateTexture(); + // } } /** diff --git a/src/textures/ShadowTexture.ts b/src/textures/ShadowTexture.ts new file mode 100644 index 00000000..2c46720c --- /dev/null +++ b/src/textures/ShadowTexture.ts @@ -0,0 +1,186 @@ +import { Texture } from '../gfx/graphics/webGpu/core/texture/Texture'; +import { GPUAddressMode, GPUTextureFormat } from '../gfx/graphics/webGpu/WebGPUConst'; +import { webGPUContext } from '../gfx/graphics/webGpu/Context3D'; +import { GPUContext } from '../gfx/renderJob/GPUContext'; +import { UUID } from '../util/Global'; +import { CResizeEvent } from '..'; +/** + * @internal + * Render target texture + * Render what we want to render onto a texture instead of rendering it onto the screen as we usually do + * @group Texture + */ +export class ShadowTexture extends Texture { + public resolveTarget: GPUTextureView; + sampleCount: number; + // storeOp: string = 'store'; + // loadOp: GPULoadOp = `load`; + // clearValue: GPUColor = [0, 0, 0, 0]; + + public clone() { + let texture = new ShadowTexture(this.width, this.height, this.format, this.useMipmap, this.usage, this.numberLayer, this.sampleCount); + texture.name = "clone_" + texture.name; + return texture; + } + + /** + * create virtual texture + * @param width width of texture + * @param height height of texture + * @param format GPUTextureFormat, default value is rgba8unorm + * @param useMipmap whether or not gen mipmap + * @returns + */ + constructor(width: number, height: number, format: GPUTextureFormat = GPUTextureFormat.rgba8unorm, useMipMap: boolean = false, usage?: GPUFlagsConstant, numberLayer: number = 1, sampleCount: number = 0, clear: boolean = true) { + super(width, height, numberLayer); + let device = webGPUContext.device; + this.name = UUID(); + + this.useMipmap = useMipMap; + this.sampleCount = sampleCount; + this.format = format; + this.numberLayer = numberLayer; + + if (usage != undefined) { + this.usage = usage; + } else { + this.usage = usage | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST; + } + + // if (this.usage & GPUTextureUsage.RENDER_ATTACHMENT || this.format == GPUTextureFormat.depth24plus || this.format == GPUTextureFormat.depth32float) { + // webGPUContext.addEventListener(CResizeEvent.RESIZE, (e) => { + // let { width, height } = e.data; + // this.resize(width, height); + // }, this); + // } + this.resize(width, height); + } + + public resize(width, height) { + let device = webGPUContext.device; + if (this.gpuTexture) { + this.gpuTexture = null; + // Texture.delayDestroyTexture(this.gpuTexture); + this.view = null; + } + + this.width = width; + this.height = height; + + this.createTextureDescriptor(width, height, 1, this.format, this.usage, this.numberLayer, this.sampleCount); + // this.loadOp = clear ? `clear` : `load` + // this.loadOp = `clear` + + this.useMipmap = false; + + this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; + + if (this.format == GPUTextureFormat.rgba32float) { + this.samplerBindingLayout.type = `non-filtering`; + this.textureBindingLayout.sampleType = `unfilterable-float`; + this.gpuSampler = device.createSampler({}); + } else if (this.format == GPUTextureFormat.depth32float) { + this.samplerBindingLayout.type = `filtering`; + this.sampler_comparisonBindingLayout.type = `comparison`; + this.textureBindingLayout.sampleType = `depth`; + this.gpuSampler = webGPUContext.device.createSampler({}); + this.gpuSampler_comparison = webGPUContext.device.createSampler({ + compare: 'less', + label: "sampler_comparison" + }); + } else if (this.format == GPUTextureFormat.depth24plus) { + this.samplerBindingLayout = { + type: `filtering`, + } + this.sampler_comparisonBindingLayout = { + type: 'comparison', + } + this.textureBindingLayout.sampleType = `depth`; + this.gpuSampler = webGPUContext.device.createSampler({}); + this.gpuSampler_comparison = webGPUContext.device.createSampler({ + compare: 'less', + label: "sampler_comparison" + }); + } else { + this.samplerBindingLayout.type = `filtering`; + this.textureBindingLayout.sampleType = `float`; + if (this.sampleCount > 0) { + this.textureBindingLayout.multisampled = true; + } + this.minFilter = 'linear'; + this.magFilter = 'linear'; + this.mipmapFilter = `linear`; + this.maxAnisotropy = 16; + + this.addressModeU = GPUAddressMode.clamp_to_edge; + this.addressModeV = GPUAddressMode.clamp_to_edge; + // this.visibility = GPUShaderStage.FRAGMENT; + this.gpuSampler = device.createSampler(this); + } + } + + /** + * create rt texture + * @param width texture width + * @param height texture height + * @param data texture pixel data + * @param useMipmap texture use mipmap switch + * @returns + */ + public create(width: number, height: number, useMiamp: boolean = true) { + let device = webGPUContext.device; + const bytesPerRow = width * 4; + let td = new Float32Array(width * height * 4); + + const textureDataBuffer = device.createBuffer({ + size: td.byteLength, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, + }); + + device.queue.writeBuffer(textureDataBuffer, 0, td); + const commandEncoder = GPUContext.beginCommandEncoder(); + commandEncoder.copyBufferToTexture( + { + buffer: textureDataBuffer, + bytesPerRow: bytesPerRow, + }, + { + texture: this.getGPUTexture(), + }, + { + width: width, + height: height, + depthOrArrayLayers: 1, + }, + ); + + GPUContext.endCommandEncoder(commandEncoder); + } + + public readTextureToImage() { + let device = webGPUContext.device; + let w = webGPUContext.windowWidth; + let h = webGPUContext.windowHeight; + const bytesPerRow = w * 4; + let td = new Float32Array(w * h * 4); + + const textureBuffer = device.createBuffer({ + size: td.byteLength, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, + }); + const commandEncoder = GPUContext.beginCommandEncoder(); + commandEncoder.copyTextureToBuffer( + { + texture: this.getGPUTexture() + }, + { + buffer: textureBuffer + }, + [w, h] + ); + + let arryBuffer = textureBuffer.getMappedRange(0, td.byteLength); + return arryBuffer; + } + +} diff --git a/src/textures/VirtualTexture.ts b/src/textures/VirtualTexture.ts index afbd24f3..43b28807 100644 --- a/src/textures/VirtualTexture.ts +++ b/src/textures/VirtualTexture.ts @@ -3,6 +3,7 @@ import { GPUAddressMode, GPUTextureFormat } from '../gfx/graphics/webGpu/WebGPUC import { webGPUContext } from '../gfx/graphics/webGpu/Context3D'; import { GPUContext } from '../gfx/renderJob/GPUContext'; import { UUID } from '../util/Global'; +import { CResizeEvent } from '..'; /** * @internal * Render target texture @@ -11,10 +12,17 @@ import { UUID } from '../util/Global'; */ export class VirtualTexture extends Texture { public resolveTarget: GPUTextureView; + sampleCount: number; // storeOp: string = 'store'; // loadOp: GPULoadOp = `load`; // clearValue: GPUColor = [0, 0, 0, 0]; + public clone() { + let texture = new VirtualTexture(this.width, this.height, this.format, this.useMipmap, this.usage, this.numberLayer, this.sampleCount); + texture.name = "clone_" + texture.name; + return texture; + } + /** * create virtual texture * @param width width of texture @@ -23,19 +31,43 @@ export class VirtualTexture extends Texture { * @param useMipmap whether or not gen mipmap * @returns */ - constructor(width: number, height: number, format: GPUTextureFormat = GPUTextureFormat.rgba8unorm, useMipMap: boolean = false, usage?: number, textureCount: number = 1, sampleCount: number = 0, clear: boolean = true) { - super(width, height, textureCount); + constructor(width: number, height: number, format: GPUTextureFormat = GPUTextureFormat.rgba8unorm, useMipMap: boolean = false, usage?: GPUFlagsConstant, numberLayer: number = 1, sampleCount: number = 0, clear: boolean = true) { + super(width, height, numberLayer); let device = webGPUContext.device; this.name = UUID(); + this.useMipmap = useMipMap; + this.sampleCount = sampleCount; + this.format = format; + this.numberLayer = numberLayer; + if (usage != undefined) { this.usage = usage; } else { - this.usage = GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST; + this.usage = usage | GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST; + } + + if (this.usage & GPUTextureUsage.RENDER_ATTACHMENT || this.format == GPUTextureFormat.depth24plus || this.format == GPUTextureFormat.depth32float) { + webGPUContext.addEventListener(CResizeEvent.RESIZE, (e) => { + let { width, height } = e.data; + this.resize(width, height); + }, this); + } + this.resize(width, height); + } + + public resize(width, height) { + let device = webGPUContext.device; + if (this.gpuTexture) { + Texture.delayDestroyTexture(this.gpuTexture); + this.gpuTexture = null; + this.view = null; } - this.createTextureDescriptor(width, height, 1, format, this.usage, textureCount, sampleCount); + this.width = width; + this.height = height; + this.createTextureDescriptor(width, height, 1, this.format, this.usage, this.numberLayer, this.sampleCount); // this.loadOp = clear ? `clear` : `load` // this.loadOp = `clear` @@ -43,11 +75,11 @@ export class VirtualTexture extends Texture { this.visibility = GPUShaderStage.COMPUTE | GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT; - if (format == GPUTextureFormat.rgba32float) { + if (this.format == GPUTextureFormat.rgba32float) { this.samplerBindingLayout.type = `non-filtering`; this.textureBindingLayout.sampleType = `unfilterable-float`; this.gpuSampler = device.createSampler({}); - } else if (format == GPUTextureFormat.depth32float) { + } else if (this.format == GPUTextureFormat.depth32float) { this.samplerBindingLayout.type = `filtering`; this.sampler_comparisonBindingLayout.type = `comparison`; this.textureBindingLayout.sampleType = `depth`; @@ -56,7 +88,7 @@ export class VirtualTexture extends Texture { compare: 'less', label: "sampler_comparison" }); - } else if (format == GPUTextureFormat.depth24plus) { + } else if (this.format == GPUTextureFormat.depth24plus) { this.samplerBindingLayout = { type: `filtering`, } @@ -72,7 +104,7 @@ export class VirtualTexture extends Texture { } else { this.samplerBindingLayout.type = `filtering`; this.textureBindingLayout.sampleType = `float`; - if (sampleCount > 0) { + if (this.sampleCount > 0) { this.textureBindingLayout.multisampled = true; } this.minFilter = 'linear'; diff --git a/src/util/BytesArray.ts b/src/util/BytesArray.ts new file mode 100644 index 00000000..a282f73c --- /dev/null +++ b/src/util/BytesArray.ts @@ -0,0 +1,290 @@ +import { Color, Matrix4, Quaternion, StringUtil, Vector2, Vector3, Vector4 } from ".."; + +/** + * @internal + * @group Util + */ +export class BytesArray extends DataView { + + public position: number = 0; + public littleEndian?: boolean = true; + constructor(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) { + super(buffer, byteOffset, byteLength); + this.position = 0; + this.position += this.byteOffset; + } + + //TODO Improve read/write byte + public readUTF() { + let len = this.readInt32(); + + let b = len % 4; + if (b > 0 && b < 4) { + b = 4 - b; + } + + let ret = ""; + // let count = Math.floor(len / 65535) + 1; + // for (let i = 0; i < count; i++) { + let strBuffer = new Int8Array(this.buffer, this.position, len); + this.position += len * Int8Array.BYTES_PER_ELEMENT; + ret += String.fromCharCode.apply(null, strBuffer); + // } + + this.position += b * Int8Array.BYTES_PER_ELEMENT; + return ret; + } + + public readStringArray() { + let ret: string[] = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + ret.push(this.readUTF()); + } + return ret; + } + + public readByte(): number { + let ret = this.buffer[this.position]; + this.position += 1; + return ret; + } + + public readBoolean(): boolean { + let ret = this.readInt32(); + this.position += 4; + return ret == 1 ? true : false; + } + + public readBytes(byteLen: number) { + let bufferView = new DataView(this.buffer, this.position, byteLen); + this.position += byteLen; + return bufferView.buffer; + } + + public readBytesArray() { + let byteLen = this.readInt32(); + let bufferView = new BytesArray(this.buffer.slice(this.position, this.position + byteLen)); + this.position += byteLen; + return bufferView; + } + + public readUnit8(): number { + let ret = this.getUint8(this.position); + this.position += Uint8Array.BYTES_PER_ELEMENT; + return ret; + } + + public readUnit16(): number { + let ret = this.getUint16(this.position); + this.position += Uint16Array.BYTES_PER_ELEMENT; + return ret; + } + + public readUnit32(): number { + let ret = this.getUint32(this.position); + this.position += Uint32Array.BYTES_PER_ELEMENT; + return ret; + } + + public readInt8(): number { + let ret = this.getInt8(this.position); + this.position += Int8Array.BYTES_PER_ELEMENT; + return ret; + } + + public readInt16(): number { + let ret = this.getInt16(this.position, this.littleEndian); + this.position += Int16Array.BYTES_PER_ELEMENT; + return ret; + } + + + public readInt32(): number { + let ret = this.getInt32(this.position, this.littleEndian); + this.position += Int32Array.BYTES_PER_ELEMENT; + return ret; + } + + public readFloat32(): number { + let ret = this.getFloat32(this.position, this.littleEndian); + this.position += Float32Array.BYTES_PER_ELEMENT; + return ret; + } + + public readFloat64(): number { + let ret = this.getFloat64(this.position, this.littleEndian); + this.position += Float64Array.BYTES_PER_ELEMENT; + return ret; + } + + public readInt32Array(): Int32Array { + let len = this.readInt32(); + let ret = new Int32Array(this.buffer, this.position, len); + ret = ret.slice(0, len); + this.position += ret.byteLength; + return ret; + } + + public readInt32List(): number[] { + let len = this.readInt32(); + let ret = []; + for (let i = 0; i < len; i++) { + ret.push(this.readInt32()); + } + return ret; + } + + public readFloatArray(): number[] { + let len = this.readInt32(); + let ret = []; + for (let i = 0; i < len; i++) { + let v = this.readFloat32(); + ret.push(v); + } + return ret; + } + + public readIntArray(): number[] { + let len = this.readInt32(); + let ret = []; + for (let i = 0; i < len; i++) { + let v = this.readInt32(); + ret.push(v); + } + return ret; + } + + public readVector2int() { + let v = new Vector2(); + v.x = this.readInt32(); + v.y = this.readInt32(); + return v; + } + + public readVector2() { + let v = new Vector2(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + return v; + } + + public readVector3() { + let v = new Vector3(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + v.z = this.readFloat32(); + return v; + } + + public readVector3Array() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readVector3()); + } + return list; + } + + public readVector4() { + let v = new Vector4(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + v.z = this.readFloat32(); + v.w = this.readFloat32(); + return v; + } + + public readVector4Array() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readVector4()); + } + return list; + } + + + public readColor() { + let v = new Color(); + v.r = this.readFloat32(); + v.g = this.readFloat32(); + v.b = this.readFloat32(); + v.a = this.readFloat32(); + return v; + } + + public readColorArray() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readColor()); + } + return list; + } + + public readQuaternion() { + let v = new Quaternion(); + v.x = this.readFloat32(); + v.y = this.readFloat32(); + v.z = this.readFloat32(); + v.w = this.readFloat32(); + return v; + } + + public readQuaternionArray() { + let list = []; + let len = this.readInt32(); + for (let i = 0; i < len; i++) { + list.push(this.readQuaternion()); + } + return list; + } + + public readMatrix44(): Matrix4 { + let m = new Matrix4(); + let rawData = m.rawData; + rawData[0] = this.readFloat32(); + rawData[1] = this.readFloat32(); + rawData[2] = this.readFloat32(); + rawData[3] = this.readFloat32(); + rawData[4] = this.readFloat32(); + rawData[5] = this.readFloat32(); + rawData[6] = this.readFloat32(); + rawData[7] = this.readFloat32(); + rawData[8] = this.readFloat32(); + rawData[9] = this.readFloat32(); + rawData[10] = this.readFloat32(); + rawData[11] = this.readFloat32(); + rawData[12] = this.readFloat32(); + rawData[13] = this.readFloat32(); + rawData[14] = this.readFloat32(); + rawData[15] = this.readFloat32(); + return m; + } + + public readMatrix44Array(): Matrix4[] { + let len = this.readInt32(); + let list = []; + for (let i = 0; i < len; i++) { + let m = this.readMatrix44(); + list.push(m); + } + return list; + } + + public readFloat32Array(len: number): Float32Array { + let ret = new Float32Array(this.buffer, this.position, len); + ret = ret.slice(0, this.byteLength); + this.position += len * Float32Array.BYTES_PER_ELEMENT; + return ret; + } + + public getFloat32Array(): Float32Array { + let ret = new Float32Array(this.buffer, this.byteOffset, this.byteLength / Float32Array.BYTES_PER_ELEMENT); + ret = ret.slice(0, this.byteLength); + return ret; + } + + +} diff --git a/src/util/BytesStream.ts b/src/util/BytesStream.ts deleted file mode 100644 index 8f608c6f..00000000 --- a/src/util/BytesStream.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @internal - * @group Util - */ -export class BytesStream extends DataView { - public position: number = 0; - constructor(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number) { - super(buffer, byteOffset, byteLength); - } - - //TODO Improve read/write byte -} diff --git a/src/util/GeometryUtil.ts b/src/util/GeometryUtil.ts index 73323f94..a0830db1 100644 --- a/src/util/GeometryUtil.ts +++ b/src/util/GeometryUtil.ts @@ -1,4 +1,4 @@ -import { Matrix4 } from '..'; +import { Matrix4, VertexAttributeName } from '..'; import { GeometryBase } from '../core/geometry/GeometryBase'; import { ShaderReflection } from '../gfx/graphics/webGpu/shader/value/ShaderReflectionInfo'; /** @@ -9,6 +9,53 @@ export class GeometryUtil { } + public static mergeNumber(geometries: GeometryBase, num: number, target?: GeometryBase) { + let targetGeo = target || new GeometryBase(); + + let posLen = geometries.getAttribute(VertexAttributeName.position).data.length / 3; + let meshIndexList = new Float32Array(posLen * num); + for (const iterator of geometries.vertexAttributeMap) { + let attName = iterator[1].attribute; + if (attName == VertexAttributeName.indices) continue; + + let data = geometries.getAttribute(attName).data; + let len = data.length; + let attData = new Float32Array(len * num); + for (let i = 0; i < num; i++) { + attData.set(data, len * i); + for (let ii = 0; ii < posLen; ii++) { + meshIndexList[posLen * i + ii] = i; + } + } + targetGeo.setAttribute(attName, attData); + } + targetGeo.setAttribute(VertexAttributeName.vIndex, meshIndexList); + + let indexArray = geometries.getAttribute(VertexAttributeName.indices).data as Int16Array; + let indexLen = indexArray.length; + let newIndexArray = new Uint32Array(indexArray.length * num); + for (let i = 0; i < num; i++) { + for (let j = 0; j < indexLen; j++) { + let skipFace = i * posLen; + let index = i * indexLen; + const ii = indexArray[j] + skipFace; + newIndexArray[index + j] = ii; + } + } + + targetGeo.setIndices(newIndexArray); + targetGeo.addSubGeometry({ + indexStart: 0, + indexCount: newIndexArray.length, + vertexStart: 0, + index: 0, + vertexCount: 0, + firstStart: 0, + topology: 0 + }) + return targetGeo; + } + public static generateNormal() { } public static generateTangent() { } public static packUV() { } diff --git a/src/util/Global.ts b/src/util/Global.ts index 7fb9aff1..bd5506b6 100644 --- a/src/util/Global.ts +++ b/src/util/Global.ts @@ -1,3 +1,5 @@ +import { ParserFormat } from "../loader/parser/ParserFormat"; + /** * UUID * @param len @@ -66,8 +68,15 @@ export let ArrayItemIndex = function (array: any[], item: any) { return -1; } +export let mergeFunctions = (...funcs) => { + return function (...args) { + funcs.forEach(func => func.apply(this, args)); + }; +} + /** * Constructor */ export type Ctor = { new(any?): T, prototype: any }; +export type Parser = { new(any?): T, prototype: any, format: ParserFormat }; diff --git a/src/util/Object3DUtil.ts b/src/util/Object3DUtil.ts index de6d4fe7..66e1c663 100644 --- a/src/util/Object3DUtil.ts +++ b/src/util/Object3DUtil.ts @@ -46,6 +46,8 @@ export class Object3DUtil { this.initHeap(); let mat = new LitMaterial(); + mat.roughness = 0.5; + mat.metallic = 0.1; mat.baseColor = new Color(r, g, b, 1); let obj = new Object3D(); diff --git a/src/util/SerializeDecoration.ts b/src/util/SerializeDecoration.ts index d28a67ae..398b8b0d 100644 --- a/src/util/SerializeDecoration.ts +++ b/src/util/SerializeDecoration.ts @@ -85,4 +85,28 @@ export function RegisterComponent(cls, key, p1?, p2?, p3?): any { dic = window['__Component__'] = {}; } dic[cls.name] = cls; +} + +export function GetComponentClass(name: string) { + let coms = window['__Component__']; + if (coms[name]) { + return coms[name]; + } + return null; +} + +export function RegisterShader(cls, key, p1?, p2?, p3?): any { + let dic: { [name: string]: any } = window['__shader__']; + if (!dic) { + dic = window['__shader__'] = {}; + } + dic[cls.name] = cls; +} + +export function GetShader(name: string) { + let coms = window['__shader__']; + if (coms[name]) { + return coms[name]; + } + return null; } \ No newline at end of file diff --git a/src/util/StorageUtil.ts b/src/util/StorageUtil.ts new file mode 100644 index 00000000..bfbb15f6 --- /dev/null +++ b/src/util/StorageUtil.ts @@ -0,0 +1,19 @@ +export class StorageUtil { + + public static localData: any; + public static load(dataTable: string): T { + let jsonData = localStorage.getItem(dataTable); + if (jsonData) { + this.localData = JSON.parse(jsonData); + } else { + this.localData = {}; + StorageUtil.save(dataTable, this.localData); + } + return this.localData as T; + } + + public static save(table: string, data: T) { + let json = JSON.stringify(data) + localStorage.setItem(table, json); + } +} \ No newline at end of file diff --git a/test/components/PostEffects_HDRBloom.test.ts b/test/components/PostEffects_HDRBloom.test.ts index a1b37492..0aca8460 100644 --- a/test/components/PostEffects_HDRBloom.test.ts +++ b/test/components/PostEffects_HDRBloom.test.ts @@ -1,7 +1,7 @@ import { test, end, delay } from '../util' -import { Camera3D, CameraUtil, Engine3D, HDRBloomPost, Object3D, PostProcessingComponent, Scene3D, View3D } from '@orillusion/core'; +import { BloomPost, Camera3D, CameraUtil, Engine3D, Object3D, PostProcessingComponent, Scene3D, View3D } from '@orillusion/core'; -await test('Post HDRBloomPost test', async () => { +await test('Post BloomPost test', async () => { await Engine3D.init(); Engine3D.frameRate = 10; @@ -11,7 +11,7 @@ await test('Post HDRBloomPost test', async () => { Engine3D.startRenderView(view); let postProcessing = view.scene.addComponent(PostProcessingComponent); - postProcessing.addPost(HDRBloomPost); + postProcessing.addPost(BloomPost); await delay(100) Engine3D.pause() }) diff --git a/test/shader/RenderShader.test.ts b/test/shader/RenderShader.test.ts index 678833d6..4fd28811 100644 --- a/test/shader/RenderShader.test.ts +++ b/test/shader/RenderShader.test.ts @@ -1,5 +1,5 @@ import { test, expect, end, delay } from '../util' -import { Engine3D, RenderShader, ShaderLib } from '@orillusion/core'; +import { Engine3D, RenderShaderPass, ShaderLib } from '@orillusion/core'; const a = Engine3D; @@ -55,7 +55,7 @@ await test('RenderShader', async () => { expect(ShaderLib.getShader('TestShader')).toEqual(shaderCode); - let renderShader = new RenderShader('TestShader', 'TestShader'); + let renderShader = new RenderShaderPass('TestShader', 'TestShader'); renderShader.setShaderEntry('vsMain', 'fsMain'); expect(renderShader.vsEntryPoint).toEqual('vsMain'); diff --git a/vite.config.js b/vite.config.js index 1f2e31dd..403e39bc 100644 --- a/vite.config.js +++ b/vite.config.js @@ -2,12 +2,11 @@ import { defineConfig } from 'vite' import { readFile, writeFile, readdir, lstat } from 'fs/promises' import { resolve, parse } from 'path' -// import basicSsl from '@vitejs/plugin-basic-ssl' export default defineConfig(option => ({ server: { host: '0.0.0.0', port: 8000, - // hmr: false // open this line if no auto hot-reload required + hmr: false // open this line if no auto hot-reload required }, publicDir: option.command === 'build' ? false : 'public', resolve: { @@ -59,12 +58,11 @@ export default defineConfig(option => ({ }, { name: 'cors', configureServer: server => { - server.middlewares.use((_req, res, next) => { - res.setHeader("Cross-Origin-Resource-Policy", "cross-origin") - res.setHeader("Cross-Origin-Opener-Policy", "same-origin") - res.setHeader("Cross-Origin-Embedder-Policy", "require-corp") - next(); - }) + // server.middlewares.use((_req, res, next) => { + // res.setHeader("Cross-Origin-Resource-Policy", "cross-origin") + // res.setHeader("Cross-Origin-Opener-Policy", "same-origin") + // res.setHeader("Cross-Origin-Embedder-Policy", "require-corp") + // }) } }], build: { From 8ad71695df37ce3b21833773fe4c429817d2108c Mon Sep 17 00:00:00 2001 From: hellmor Date: Tue, 31 Oct 2023 22:39:19 +0800 Subject: [PATCH 07/14] fix: Character loss during text layout. (#317) Character loss during text layout. --- src/components/gui/uiComponents/TextFieldLayout.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/gui/uiComponents/TextFieldLayout.ts b/src/components/gui/uiComponents/TextFieldLayout.ts index 50b307ab..60c966b9 100644 --- a/src/components/gui/uiComponents/TextFieldLayout.ts +++ b/src/components/gui/uiComponents/TextFieldLayout.ts @@ -217,17 +217,18 @@ export class TextFieldLayout { let parseText = (): void => { let curLine: TextFieldLine = null; let totalLength: number = text.length; - let autoWrap = false; for (let i = 0; i < totalLength; i++) { - if (curLine == null) curLine = makeLine(); + curLine ||= makeLine(); let char = text.charAt(i); - if (char == '\n' || autoWrap) { - //换行符 + if (char == '\n' || char == '\t') { + //wrap symbol curLine = null; - autoWrap = false; } else { makeQuad(char, curLine); - autoWrap = curLine.width + unitSize >= maxTextWidthReal; + let autoWrap = curLine.width + halfUnitSize >= maxTextWidthReal; + if (autoWrap) { + curLine = makeLine(); + } } } }; From 934c42d2d5e05d7d50f2ed443cda7c4eeb6c10e0 Mon Sep 17 00:00:00 2001 From: OldGentleMan Date: Wed, 1 Nov 2023 11:31:39 +0800 Subject: [PATCH 08/14] chore: chore graphic sample (#320) add graphic sample chore graphic sample chore graphic sample --- .../Sample_GraphicMeshWave.ts | 0 .../Sample_GraphicMesh_0.ts | 0 .../Sample_GraphicMesh_1.ts | 50 +++- .../Sample_GraphicMesh_2.ts | 0 .../Sample_GraphicMesh_3.ts | 0 .../Sample_GraphicMesh_4.ts | 0 samples/graphic/Sample_GraphicMesh_5.ts | 232 ++++++++++++++++++ samples/graphic/Sample_GraphicMesh_6.ts | 171 +++++++++++++ samples/graphic/Sample_GraphicMesh_7.ts | 184 ++++++++++++++ 9 files changed, 628 insertions(+), 9 deletions(-) rename samples/{material => graphic}/Sample_GraphicMeshWave.ts (100%) rename samples/{material => graphic}/Sample_GraphicMesh_0.ts (100%) rename samples/{material => graphic}/Sample_GraphicMesh_1.ts (87%) rename samples/{material => graphic}/Sample_GraphicMesh_2.ts (100%) rename samples/{material => graphic}/Sample_GraphicMesh_3.ts (100%) rename samples/{material => graphic}/Sample_GraphicMesh_4.ts (100%) create mode 100644 samples/graphic/Sample_GraphicMesh_5.ts create mode 100644 samples/graphic/Sample_GraphicMesh_6.ts create mode 100644 samples/graphic/Sample_GraphicMesh_7.ts diff --git a/samples/material/Sample_GraphicMeshWave.ts b/samples/graphic/Sample_GraphicMeshWave.ts similarity index 100% rename from samples/material/Sample_GraphicMeshWave.ts rename to samples/graphic/Sample_GraphicMeshWave.ts diff --git a/samples/material/Sample_GraphicMesh_0.ts b/samples/graphic/Sample_GraphicMesh_0.ts similarity index 100% rename from samples/material/Sample_GraphicMesh_0.ts rename to samples/graphic/Sample_GraphicMesh_0.ts diff --git a/samples/material/Sample_GraphicMesh_1.ts b/samples/graphic/Sample_GraphicMesh_1.ts similarity index 87% rename from samples/material/Sample_GraphicMesh_1.ts rename to samples/graphic/Sample_GraphicMesh_1.ts index 81a70d9f..8c24588e 100644 --- a/samples/material/Sample_GraphicMesh_1.ts +++ b/samples/graphic/Sample_GraphicMesh_1.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode } from "@orillusion/core"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, Color } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; import { Stats } from "@orillusion/stats"; @@ -11,6 +11,9 @@ export class Sample_GraphicMesh_1 { height: number; cafe: number = 47; frame: number = 16; + view: View3D; + + colors: Color[]; constructor() { } @@ -24,7 +27,7 @@ export class Sample_GraphicMesh_1 { Engine3D.setting.render.debug = true; Engine3D.setting.shadow.shadowBound = 5; - + this.colors = []; GUIHelp.init(); @@ -37,11 +40,11 @@ export class Sample_GraphicMesh_1 { camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); - let view = new View3D(); - view.scene = this.scene; - view.camera = camera; + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; - Engine3D.startRenderView(view); + Engine3D.startRenderView(this.view); GUIUtil.renderDebug(); @@ -135,7 +138,7 @@ export class Sample_GraphicMesh_1 { GUIHelp.add(this, "cafe", 0.0, 100.0); GUIHelp.add(this, "frame", 0.0, 100.0); { - this.width = 200; + this.width = 100; this.height = 100; // let geometry = new BoxGeometry(1, 1, 1); let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); @@ -152,23 +155,52 @@ export class Sample_GraphicMesh_1 { const element = this.parts[i]; // mr.setTextureID(i, i % texts.length); // mr.setTextureID(i, 52); - mr.setTextureID(i, 35); + mr.setTextureID(i, 39); // mr.setTextureID(i, 39); // mr.setTextureID(i, 18); + + element.transform.scaleX = 2; + element.transform.scaleY = 2; + element.transform.scaleZ = 2; + + // let c = Color.random(); + // c.a = 0.55; + // this.colors.push(c); } + + let c1 = new Color(0.65, 0.1, 0.2, 0.15); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c1); + this.colors.push(c2); } } + private tmpArray: any[] = []; update() { if (this.parts) { let pos = new Vector3(); + this.tmpArray.length = 0; for (let i = 0; i < this.parts.length; i++) { const element = this.parts[i]; let tmp = this.sphericalFibonacci(i, this.parts.length); - tmp.scaleBy(Math.sin((i + Time.frame * 0.01 * this.frame * 0.01)) * this.cafe); + let sc = Math.sin((i + Time.frame * 0.01 * this.frame * 0.01)) * this.cafe + tmp.scaleBy(sc); element.transform.localPosition = tmp; + + if (sc > 10) { + this.tmpArray.push(element); + } + } + + for (let i = 0; i < this.tmpArray.length - 1; i++) { + this.view.graphic3D.Clear(i.toString()); + this.view.graphic3D.drawLines(i.toString(), [ + this.tmpArray[i].transform.worldPosition, + this.tmpArray[i + 1].transform.worldPosition, + ], + this.colors); } } } diff --git a/samples/material/Sample_GraphicMesh_2.ts b/samples/graphic/Sample_GraphicMesh_2.ts similarity index 100% rename from samples/material/Sample_GraphicMesh_2.ts rename to samples/graphic/Sample_GraphicMesh_2.ts diff --git a/samples/material/Sample_GraphicMesh_3.ts b/samples/graphic/Sample_GraphicMesh_3.ts similarity index 100% rename from samples/material/Sample_GraphicMesh_3.ts rename to samples/graphic/Sample_GraphicMesh_3.ts diff --git a/samples/material/Sample_GraphicMesh_4.ts b/samples/graphic/Sample_GraphicMesh_4.ts similarity index 100% rename from samples/material/Sample_GraphicMesh_4.ts rename to samples/graphic/Sample_GraphicMesh_4.ts diff --git a/samples/graphic/Sample_GraphicMesh_5.ts b/samples/graphic/Sample_GraphicMesh_5.ts new file mode 100644 index 00000000..2d1e48de --- /dev/null +++ b/samples/graphic/Sample_GraphicMesh_5.ts @@ -0,0 +1,232 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, Color } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_5 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + view: View3D; + + colors: Color[]; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + this.colors = []; + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/glow_0026.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0001.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0003.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0009.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0017.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0022.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/wave_0025.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0012.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/Vortex_0016.png") as BitmapTexture2D); + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0002.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0004.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0005.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0006.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0007.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0010.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0011.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0013.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0014.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0016.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0018.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0019.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0020.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0021.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0023.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0024.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0025.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0027.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0028.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0031.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/128/star_0035.png") as BitmapTexture2D); + + // texts.push(Engine3D.res.grayTexture); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 100; + this.height = 100; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 39); + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + + element.transform.scaleX = 2; + element.transform.scaleY = 2; + element.transform.scaleZ = 2; + + // let c = Color.random(); + // c.a = 0.55; + // this.colors.push(c); + } + + let c1 = new Color(0.65, 0.1, 0.2, 0.15); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c1); + this.colors.push(c2); + } + } + + private tmpArray: any[] = []; + update() { + if (this.parts) { + let pos = new Vector3(); + this.tmpArray.length = 0; + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + let sc = Math.sin((i + Time.frame * 0.01 * this.frame * 0.01)) * this.cafe + tmp.scaleBy(sc); + + element.transform.localPosition = tmp; + + if (sc > this.cafe * 0.85) { + this.tmpArray.push(element); + } + } + + for (let i = 0; i < this.tmpArray.length - 1; i++) { + this.view.graphic3D.Clear(i.toString()); + this.view.graphic3D.drawLines(i.toString(), [ + this.tmpArray[i].transform.worldPosition, + this.tmpArray[i + 1].transform.worldPosition, + ], + this.colors); + } + } + } + + private wave(i: number, pos: Vector3) { + let x = Math.floor(i / this.width); + let z = i % this.height; + pos.set(x, 0, z); + pos.y = Math.sin((x + Time.frame * 0.01) / 8) * 15 * Math.cos((z + Time.frame * 0.01) / 15); + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + + } + +} diff --git a/samples/graphic/Sample_GraphicMesh_6.ts b/samples/graphic/Sample_GraphicMesh_6.ts new file mode 100644 index 00000000..53f45ac1 --- /dev/null +++ b/samples/graphic/Sample_GraphicMesh_6.ts @@ -0,0 +1,171 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, Color } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_6 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + view: View3D; + + colors: Color[]; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + this.colors = []; + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + await this.initScene(); + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 15; + this.height = 15; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 0); + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + + element.transform.scaleX = 5.5; + element.transform.scaleY = 5.5; + element.transform.scaleZ = 5.5; + + // let c = Color.random(); + // c.a = 0.55; + // this.colors.push(c); + } + + let c1 = new Color(0.65, 0.1, 0.2, 0.15); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c1); + this.colors.push(c2); + } + + this.updateOnce(1000); + } + + private tmpArray: any[] = []; + update() { + } + + updateOnce(engineFrame: number) { + if (this.parts) { + let pos = new Vector3(); + this.tmpArray.length = 0; + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + tmp.scaleBy(this.cafe); + + element.transform.localPosition = tmp; + + // if (sc > this.cafe * 0.95) { + this.tmpArray.push(element); + // } + } + + for (let i = 0; i < this.tmpArray.length - 1; i++) { + this.view.graphic3D.Clear(i.toString()); + this.view.graphic3D.drawLines(i.toString(), [ + Vector3.ZERO, + this.tmpArray[i + 1].transform.worldPosition, + ], + this.colors); + } + } + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + } + +} diff --git a/samples/graphic/Sample_GraphicMesh_7.ts b/samples/graphic/Sample_GraphicMesh_7.ts new file mode 100644 index 00000000..7bfffc60 --- /dev/null +++ b/samples/graphic/Sample_GraphicMesh_7.ts @@ -0,0 +1,184 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, Color, PostProcessingComponent, BloomPost } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_7 { + lightObj3D: Object3D; + scene: Scene3D; + parts: Object3D[]; + width: number; + height: number; + cafe: number = 47; + frame: number = 16; + view: View3D; + + colors: Color[]; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + this.colors = []; + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + let post = this.scene.addComponent(PostProcessingComponent); + let bloom = post.addPost(BloomPost); + bloom.bloomIntensity = 10.0 + GUIUtil.renderBloom(bloom); + + await this.initScene(); + + + + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 15; + this.height = 15; + // let geometry = new BoxGeometry(1, 1, 1); + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = mr.object3Ds; + + mr.material.blendMode = BlendMode.ADD; + // mr.material.doubleSide = true; + mr.material.transparent = true; + mr.material.depthWriteEnabled = false; + mr.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + // mr.setTextureID(i, i % texts.length); + // mr.setTextureID(i, 52); + mr.setTextureID(i, 0); + // mr.setTextureID(i, 39); + // mr.setTextureID(i, 18); + + element.transform.scaleX = 5.5; + element.transform.scaleY = 5.5; + element.transform.scaleZ = 5.5; + + // let c = Color.random(); + // c.a = 0.55; + // this.colors.push(c); + } + + let c1 = new Color(0.65, 0.1, 0.2, 0.15); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + } + + this.updateOnce(1000); + } + + private tmpArray: any[] = []; + update() { + } + + updateOnce(engineFrame: number) { + if (this.parts) { + let pos = new Vector3(); + this.tmpArray.length = 0; + for (let i = 0; i < this.parts.length; i++) { + const element = this.parts[i]; + + let tmp = this.sphericalFibonacci(i, this.parts.length); + tmp.scaleBy(this.cafe); + + element.transform.localPosition = tmp; + + // if (sc > this.cafe * 0.95) { + this.tmpArray.push(element); + // } + } + + for (let i = 0; i < this.tmpArray.length / 3; i++) { + this.view.graphic3D.Clear(i.toString()); + this.view.graphic3D.drawLines(i.toString(), [ + this.tmpArray[i * 3 + 0].transform.worldPosition, + this.tmpArray[i * 3 + 1].transform.worldPosition, + this.tmpArray[i * 3 + 2].transform.worldPosition, + ], + this.colors); + } + } + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + } + +} From 4ca35b576454cb52aee47ddbc271a4d36a906e78 Mon Sep 17 00:00:00 2001 From: OldGentleMan Date: Wed, 1 Nov 2023 13:51:10 +0800 Subject: [PATCH 09/14] fix: fix gltf sample (#321) add graphic mesh material data fix gltf sample fix emissive color fix image material fix chromaKey material --- packages/media-extention/ChromaKeyMaterial.ts | 79 ++++---- packages/media-extention/ImageMaterial.ts | 37 ++-- packages/media-extention/VideoMaterial.ts | 1 - samples/graphic/Sample_GraphicMesh_7.ts | 23 +-- samples/graphic/Sample_GraphicMesh_Color.ts | 173 +++++++++++++++++ .../graphic/Sample_GraphicMesh_SpriteSheet.ts | 179 ++++++++++++++++++ samples/loader/Sample_LoadGLB.ts | 47 +++-- samples/material/Sample_ClearCoat.ts | 2 +- samples/utils/ExampleScene.ts | 6 +- .../core/struct/VertexAttributeIndexShader.ts | 5 + src/assets/shader/lighting/BxDF_frag.ts | 4 +- .../shader/materials/UnLitTextureArray.ts | 6 +- .../graphic/new/Graphic3DMeshRenderer.ts | 34 +++- .../parser/gltf/GLTFSubParserConverter.ts | 2 +- src/materials/LitMaterial.ts | 47 +++++ src/materials/SkyMaterial.ts | 2 +- src/math/Color.ts | 16 ++ src/math/UV.ts | 9 + src/textures/BitmapTexture2DArray.ts | 2 +- 19 files changed, 562 insertions(+), 112 deletions(-) create mode 100644 samples/graphic/Sample_GraphicMesh_Color.ts create mode 100644 samples/graphic/Sample_GraphicMesh_SpriteSheet.ts diff --git a/packages/media-extention/ChromaKeyMaterial.ts b/packages/media-extention/ChromaKeyMaterial.ts index c22c7e80..2830ff87 100644 --- a/packages/media-extention/ChromaKeyMaterial.ts +++ b/packages/media-extention/ChromaKeyMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Vector4, Color, BlendMode, registerMaterial, Material, RenderShaderPass, Texture } from "@orillusion/core"; +import { Engine3D, ShaderLib, Vector4, Color, BlendMode, registerMaterial, Material, RenderShaderPass, Texture, Shader, PassType } from "@orillusion/core"; import { ChromaKeyShader } from "./ChromaKeyShader"; /** @@ -14,33 +14,38 @@ export class ChromaKeyMaterial extends Material { super(); ShaderLib.register("ChromaKeyShader", ChromaKeyShader); - this.defaultPass = new RenderShaderPass( + let newShader = new Shader(); + + let colorPass = new RenderShaderPass( `ChromaKeyShader`, `ChromaKeyShader` ); - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`); + colorPass.setShaderEntry(`VertMain`, `FragMain`); + colorPass.passType = PassType.COLOR; - this.defaultPass.setUniformVector4( + colorPass.setUniformVector4( `transformUV1`, new Vector4(0, 0, 1, 1) ); - this.defaultPass.setUniformVector4( + colorPass.setUniformVector4( `transformUV2`, new Vector4(0, 0, 1, 1) ); - this.defaultPass.setUniformColor(`baseColor`, new Color()); - this.defaultPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); - this.defaultPass.setUniformFloat(`alphaCutoff`, 0.5); - - this.defaultPass.setUniformColor(`keyColor`, new Color(0, 1, 0, 0)); - this.defaultPass.setUniformFloat(`colorCutoff`, 0.4); - this.defaultPass.setUniformFloat(`colorFeathering`, 0.5); - this.defaultPass.setUniformFloat(`maskFeathering`, 1); - this.defaultPass.setUniformFloat(`sharpening`, 0.5); - this.defaultPass.setUniformFloat(`despoil`, 0.6); - this.defaultPass.setUniformFloat(`despoilLuminanceAdd`, 0); - - let shaderState = this.defaultPass.shaderState; + colorPass.setUniformColor(`baseColor`, new Color()); + colorPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); + colorPass.setUniformFloat(`alphaCutoff`, 0.5); + + colorPass.setUniformColor(`keyColor`, new Color(0, 1, 0, 0)); + colorPass.setUniformFloat(`colorCutoff`, 0.4); + colorPass.setUniformFloat(`colorFeathering`, 0.5); + colorPass.setUniformFloat(`maskFeathering`, 1); + colorPass.setUniformFloat(`sharpening`, 0.5); + colorPass.setUniformFloat(`despoil`, 0.6); + colorPass.setUniformFloat(`despoilLuminanceAdd`, 0); + + newShader.addRenderPass(colorPass); + + let shaderState = colorPass.shaderState; shaderState.acceptShadow = false; shaderState.receiveEnv = false; shaderState.acceptGI = false; @@ -50,127 +55,127 @@ export class ChromaKeyMaterial extends Material { shaderState.blendMode = BlendMode.ALPHA; // default value - this.defaultPass.setTexture(`baseMap`, Engine3D.res.whiteTexture); + this.shader.setTexture(`baseMap`, Engine3D.res.whiteTexture); } public set baseMap(value: Texture) { - this.defaultPass.setTexture(`baseMap`, value); + this.shader.setTexture(`baseMap`, value); } public get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } /** * Set the clip rect area */ public set rectClip(value: Vector4) { - this.defaultPass.uniforms[`rectClip`].vector4 = value; + this.shader.setUniformVector4(`rectClip`, value); } /** * Get current clip rect area */ public get rectClip(): Vector4 { - return this.defaultPass.uniforms[`rectClip`].vector4; + return this.shader.getUniformVector4(`rectClip`); } /** * Set the chromakey color */ public set keyColor(value: Color) { - this.defaultPass.uniforms[`keyColor`].color = value; + this.shader.setUniformColor(`keyColor`, value); } /** * Get the chromakey color */ public get keyColor(): Color { - return this.defaultPass.uniforms[`keyColor`].color; + return this.shader.getUniformColor(`keyColor`); } /** * Set the color cutoff factor */ public set colorCutoff(value: number) { - this.defaultPass.uniforms[`colorCutoff`].value = value; + this.shader.setUniformFloat(`colorCutoff`, value); } /** * Get the color cutoff factor */ public get colorCutoff(): number { - return this.defaultPass.uniforms[`colorCutoff`].value; + return this.shader.getUniformFloat(`colorCutoff`); } /** * Set the color feather factor */ public set colorFeathering(value: number) { - this.defaultPass.uniforms[`colorFeathering`].value = value; + this.shader.setUniformFloat(`colorFeathering`, value); } /** * Get the color feather factor */ public get colorFeathering(): number { - return this.defaultPass.uniforms[`colorFeathering`].value; + return this.shader.getUniformFloat(`colorFeathering`); } /** * Set the mask feather factor */ public set maskFeathering(value: number) { - this.defaultPass.uniforms[`maskFeathering`].value = value; + this.shader.setUniformFloat(`maskFeathering`, value); } /** * Get the mask feather factor */ public get maskFeathering(): number { - return this.defaultPass.uniforms[`maskFeathering`].value; + return this.shader.getUniformFloat(`maskFeathering`); } /** * Set the sharpen factor */ public set sharpening(value: number) { - this.defaultPass.uniforms[`sharpening`].value = value; + this.shader.setUniformFloat(`sharpening`, value); } /** * Get the sharpen factor */ public get sharpening(): number { - return this.defaultPass.uniforms[`sharpening`].value; + return this.shader.getUniformFloat(`sharpening`); } /** * Set the despoil factor */ public set despoil(value: number) { - this.defaultPass.uniforms[`despoil`].value = value; + this.shader.setUniformFloat(`despoil`, value); } /** * Get the despoil factor */ public get despoil(): number { - return this.defaultPass.uniforms[`despoil`].value; + return this.shader.getUniformFloat(`despoil`); } /** * Set the despoil luminance factor */ public set despoilLuminanceAdd(value: number) { - this.defaultPass.uniforms[`despoilLuminanceAdd`].value = value; + this.shader.setUniformFloat(`despoilLuminanceAdd`, value); } /** * Get the despoil luminance factor */ public get despoilLuminanceAdd(): number { - return this.defaultPass.uniforms[`despoilLuminanceAdd`].value; + return this.shader.getUniformFloat(`despoilLuminanceAdd`); } /** diff --git a/packages/media-extention/ImageMaterial.ts b/packages/media-extention/ImageMaterial.ts index 7c396d18..cd09b58e 100644 --- a/packages/media-extention/ImageMaterial.ts +++ b/packages/media-extention/ImageMaterial.ts @@ -1,4 +1,4 @@ -import { Engine3D, ShaderLib, Vector4, Color, Texture, Material, RenderShaderPass } from "@orillusion/core"; +import { Engine3D, ShaderLib, Vector4, Color, Texture, Material, RenderShaderPass, Shader, PassType } from "@orillusion/core"; import ImageMaterialShader from "./ImageMaterialShader.wgsl?raw"; @@ -15,60 +15,65 @@ export class ImageMaterial extends Material { constructor() { super(); ShaderLib.register("ImageMaterialShader", ImageMaterialShader); - this.defaultPass = new RenderShaderPass(`ImageMaterialShader`, `ImageMaterialShader`); - this.defaultPass.setShaderEntry(`VertMain`, `FragMain`) - this.defaultPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); - this.defaultPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); - this.defaultPass.setUniformColor(`baseColor`, new Color()); - this.defaultPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); - this.defaultPass.setUniformFloat(`alphaCutoff`, 0.5); + let newShader = new Shader(); - let shaderState = this.defaultPass.shaderState; + let defaultPass = new RenderShaderPass(`ImageMaterialShader`, `ImageMaterialShader`); + defaultPass.passType = PassType.COLOR; + defaultPass.setShaderEntry(`VertMain`, `FragMain`) + defaultPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); + defaultPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); + defaultPass.setUniformColor(`baseColor`, new Color()); + defaultPass.setUniformVector4(`rectClip`, new Vector4(0, 0, 0, 0)); + defaultPass.setUniformFloat(`alphaCutoff`, 0.5); + newShader.addRenderPass(defaultPass); + + let shaderState = defaultPass.shaderState; shaderState.acceptShadow = false; shaderState.receiveEnv = false; shaderState.acceptGI = false; shaderState.useLight = false; shaderState.castShadow = false; shaderState.useZ = false; + this.shader = newShader; // default value - this.defaultPass.setTexture(`baseMap`, Engine3D.res.whiteTexture); + this.shader.setTexture(`baseMap`, Engine3D.res.whiteTexture); } public set baseMap(value: Texture) { - this.defaultPass.setTexture(`baseMap`, value); + this.shader.setTexture(`baseMap`, value); } public get baseMap() { - return this.defaultPass.getTexture(`baseMap`); + return this.shader.getTexture(`baseMap`); } /** * set base color (tint color) */ public set baseColor(color: Color) { - this.defaultPass.setUniformColor(`baseColor`, color); + this.shader.setUniformColor(`baseColor`, color); } /** * get base color (tint color) */ public get baseColor() { - return this.defaultPass.uniforms[`baseColor`].color; + return this.shader.getUniformColor(`baseColor`); } /** * Set the clip rect area */ public set rectClip(value: Vector4) { - this.defaultPass.uniforms[`rectClip`].vector4 = value; + this.shader.setUniformVector4(`rectClip`, value); } /** * Get the clip rect area */ public get rectClip(): Vector4 { - return this.defaultPass.uniforms[`rectClip`].vector4; + return this.shader.getUniformVector4(`rectClip`); } /** diff --git a/packages/media-extention/VideoMaterial.ts b/packages/media-extention/VideoMaterial.ts index acc01e85..05e0c977 100644 --- a/packages/media-extention/VideoMaterial.ts +++ b/packages/media-extention/VideoMaterial.ts @@ -22,7 +22,6 @@ export class VideoMaterial extends Material { colorPass.passType = PassType.COLOR; colorPass.setShaderEntry(`VertMain`, `FragMain`) - colorPass.setShaderEntry(`VertMain`, `FragMain`) colorPass.setUniformVector4(`transformUV1`, new Vector4(0, 0, 1, 1)); colorPass.setUniformVector4(`transformUV2`, new Vector4(0, 0, 1, 1)); colorPass.setUniformColor(`baseColor`, new Color()); diff --git a/samples/graphic/Sample_GraphicMesh_7.ts b/samples/graphic/Sample_GraphicMesh_7.ts index 7bfffc60..b753c7ea 100644 --- a/samples/graphic/Sample_GraphicMesh_7.ts +++ b/samples/graphic/Sample_GraphicMesh_7.ts @@ -55,8 +55,6 @@ export class Sample_GraphicMesh_7 { await this.initScene(); - - sky.relativeTransform = this.lightObj3D.transform; } @@ -91,32 +89,21 @@ export class Sample_GraphicMesh_7 { { this.width = 15; this.height = 15; - // let geometry = new BoxGeometry(1, 1, 1); let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); let mr = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); this.parts = mr.object3Ds; mr.material.blendMode = BlendMode.ADD; - // mr.material.doubleSide = true; mr.material.transparent = true; mr.material.depthWriteEnabled = false; mr.material.useBillboard = true; for (let i = 0; i < this.width * this.height; i++) { const element = this.parts[i]; - // mr.setTextureID(i, i % texts.length); - // mr.setTextureID(i, 52); mr.setTextureID(i, 0); - // mr.setTextureID(i, 39); - // mr.setTextureID(i, 18); - element.transform.scaleX = 5.5; element.transform.scaleY = 5.5; element.transform.scaleZ = 5.5; - - // let c = Color.random(); - // c.a = 0.55; - // this.colors.push(c); } let c1 = new Color(0.65, 0.1, 0.2, 0.15); @@ -142,25 +129,21 @@ export class Sample_GraphicMesh_7 { this.tmpArray.length = 0; for (let i = 0; i < this.parts.length; i++) { const element = this.parts[i]; - let tmp = this.sphericalFibonacci(i, this.parts.length); tmp.scaleBy(this.cafe); - element.transform.localPosition = tmp; - - // if (sc > this.cafe * 0.95) { this.tmpArray.push(element); - // } } for (let i = 0; i < this.tmpArray.length / 3; i++) { this.view.graphic3D.Clear(i.toString()); - this.view.graphic3D.drawLines(i.toString(), [ + this.view.graphic3D.drawLines(i.toString(), + [ this.tmpArray[i * 3 + 0].transform.worldPosition, this.tmpArray[i * 3 + 1].transform.worldPosition, this.tmpArray[i * 3 + 2].transform.worldPosition, ], - this.colors); + this.colors); } } } diff --git a/samples/graphic/Sample_GraphicMesh_Color.ts b/samples/graphic/Sample_GraphicMesh_Color.ts new file mode 100644 index 00000000..4bfc06f7 --- /dev/null +++ b/samples/graphic/Sample_GraphicMesh_Color.ts @@ -0,0 +1,173 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, Color, PostProcessingComponent, BloomPost, ColorUtil, Graphic3DMeshRenderer } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_Color { + private lightObj3D: Object3D; + private scene: Scene3D; + private parts: Object3D[]; + private width: number; + private height: number; + private cafe: number = 47; + private frame: number = 16; + private view: View3D; + private colors: Color[]; + private tmpArray: any[] = []; + + private color1: Color ; + private color2: Color ; + graphicMeshRenderer: Graphic3DMeshRenderer; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + this.colors = []; + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + let post = this.scene.addComponent(PostProcessingComponent); + let bloom = post.addPost(BloomPost); + bloom.bloomIntensity = 10.0 + GUIUtil.renderBloom(bloom); + + await this.initScene(); + + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + texts.push(await Engine3D.res.loadTexture("textures/128/star_0008.png") as BitmapTexture2D); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 15; + this.height = 15; + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + this.graphicMeshRenderer = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = this.graphicMeshRenderer.object3Ds; + + this.graphicMeshRenderer.material.blendMode = BlendMode.ADD; + this.graphicMeshRenderer.material.transparent = true; + this.graphicMeshRenderer.material.depthWriteEnabled = false; + this.graphicMeshRenderer.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + this.graphicMeshRenderer.setTextureID(i, 0); + element.transform.scaleX = 5.5; + element.transform.scaleY = 5.5; + element.transform.scaleZ = 5.5; + } + + this.color1 = new Color(1.5, 0.1, 0.2, 1.0); + this.color2 = new Color(0.1, 0.1, 4.5, 1.0); + let c2 = new Color(1.0, 1.1, 0.2, 0.65); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + } + + this.updateOnce(1000); + } + + update() { + this.updateOnce(Time.frame); + } + + updateOnce(engineFrame: number) { + if (this.parts) { + this.tmpArray.length = 0; + let len = this.parts.length ; + for (let i = 0; i < len; i++) { + const element = this.parts[i]; + let tmp = this.sphericalFibonacci(i, len); + tmp.scaleBy(this.cafe); + element.transform.localPosition = tmp; + this.tmpArray.push(element); + + let c = Color.lerp( Math.sin(engineFrame*0.001 + (i/len)), this.color1,this.color2, Color.COLOR_0 ); + this.graphicMeshRenderer.setBaseColor(i,c); + } + + for (let i = 0; i < this.tmpArray.length - 1; i++) { + this.view.graphic3D.Clear(i.toString()); + this.view.graphic3D.drawLines(i.toString(), [ + Vector3.ZERO, + this.tmpArray[i + 1].transform.worldPosition, + ], + this.colors); + } + } + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + } + +} diff --git a/samples/graphic/Sample_GraphicMesh_SpriteSheet.ts b/samples/graphic/Sample_GraphicMesh_SpriteSheet.ts new file mode 100644 index 00000000..03f21098 --- /dev/null +++ b/samples/graphic/Sample_GraphicMesh_SpriteSheet.ts @@ -0,0 +1,179 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { Object3D, Scene3D, Engine3D, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight, KelvinUtil, LitMaterial, MeshRenderer, BoxGeometry, SphereGeometry, VirtualTexture, GPUTextureFormat, UnLitMaterial, UnLitTexArrayMaterial, BitmapTexture2DArray, BitmapTexture2D, PlaneGeometry, Vector3, Graphic3DMesh, Matrix4, Time, BlendMode, Color, PostProcessingComponent, BloomPost, ColorUtil, Graphic3DMeshRenderer, UV } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Stats } from "@orillusion/stats"; + +export class Sample_GraphicMesh_SpriteSheet { + private lightObj3D: Object3D; + private scene: Scene3D; + private parts: Object3D[]; + private width: number; + private height: number; + private cafe: number = 47; + private frame: number = 16; + private view: View3D; + private colors: Color[]; + private tmpArray: any[] = []; + + private color1: Color; + private color2: Color; + graphicMeshRenderer: Graphic3DMeshRenderer; + + constructor() { } + + async run() { + + Matrix4.maxCount = 500000; + Matrix4.allocCount = 500000; + + await Engine3D.init({ beforeRender: () => this.update() }); + + Engine3D.setting.render.debug = true; + Engine3D.setting.shadow.shadowBound = 5; + + this.colors = []; + + GUIHelp.init(); + + this.scene = new Scene3D(); + this.scene.addComponent(Stats); + let sky = this.scene.addComponent(AtmosphericComponent); + sky.enable = false; + let camera = CameraUtil.createCamera3DObject(this.scene); + camera.perspective(60, Engine3D.aspect, 1, 5000.0); + + camera.object3D.addComponent(HoverCameraController).setCamera(30, 0, 120); + + this.view = new View3D(); + this.view.scene = this.scene; + this.view.camera = camera; + + Engine3D.startRenderView(this.view); + + GUIUtil.renderDebug(); + + let post = this.scene.addComponent(PostProcessingComponent); + let bloom = post.addPost(BloomPost); + bloom.bloomIntensity = 10.0 + GUIUtil.renderBloom(bloom); + + await this.initScene(); + + sky.relativeTransform = this.lightObj3D.transform; + } + + async initScene() { + /******** light *******/ + { + this.lightObj3D = new Object3D(); + this.lightObj3D.rotationX = 21; + this.lightObj3D.rotationY = 108; + this.lightObj3D.rotationZ = 10; + let directLight = this.lightObj3D.addComponent(DirectLight); + directLight.lightColor = KelvinUtil.color_temperature_to_rgb(5355); + directLight.castShadow = false; + directLight.intensity = 10; + GUIUtil.renderDirLight(directLight); + this.scene.addChild(this.lightObj3D); + } + + let texts = []; + + // texts.push(await Engine3D.res.loadTexture("textures/spriteSheet/sequence_0031.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/spriteSheet/sequence_0050.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/spriteSheet/sequence_0036.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/spriteSheet/sequence_0053.png") as BitmapTexture2D); + // texts.push(await Engine3D.res.loadTexture("textures/spriteSheet/sequence_0041.png") as BitmapTexture2D); + texts.push(await Engine3D.res.loadTexture("textures/spriteSheet/sequence_0040.png") as BitmapTexture2D); + + let bitmapTexture2DArray = new BitmapTexture2DArray(texts[0].width, texts[0].height, texts.length); + bitmapTexture2DArray.setTextures(texts); + + let mat = new UnLitTexArrayMaterial(); + mat.baseMap = bitmapTexture2DArray; + mat.name = "LitMaterial"; + + GUIHelp.add(this, "cafe", 0.0, 100.0); + GUIHelp.add(this, "frame", 0.0, 100.0); + { + this.width = 15; + this.height = 15; + let geometry = new PlaneGeometry(1, 1, 1, 1, Vector3.Z_AXIS); + this.graphicMeshRenderer = Graphic3DMesh.draw(this.scene, geometry, bitmapTexture2DArray, this.width * this.height); + this.parts = this.graphicMeshRenderer.object3Ds; + + this.graphicMeshRenderer.material.blendMode = BlendMode.ADD; + this.graphicMeshRenderer.material.transparent = true; + this.graphicMeshRenderer.material.depthWriteEnabled = false; + this.graphicMeshRenderer.material.useBillboard = true; + + for (let i = 0; i < this.width * this.height; i++) { + const element = this.parts[i]; + this.graphicMeshRenderer.setTextureID(i, 0); + element.transform.scaleX = 5.5; + element.transform.scaleY = 5.5; + element.transform.scaleZ = 5.5; + } + + this.color1 = new Color(1.5, 0.1, 0.2, 1.0); + this.color2 = new Color(0.1, 0.1, 4.5, 1.0); + let c2 = new Color(1.0, 1.1, 0.2, 0.45); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + this.colors.push(c2); + } + + this.updateOnce(1000); + } + + update() { + this.updateOnce(Time.frame); + } + + updateOnce(engineFrame: number) { + if (this.parts) { + this.tmpArray.length = 0; + let len = this.parts.length; + for (let i = 0; i < len; i++) { + const element = this.parts[i]; + let tmp = this.sphericalFibonacci(i, len); + tmp.scaleBy(this.cafe); + element.transform.localPosition = tmp; + this.tmpArray.push(element); + + // let c = Color.lerp(Math.sin(engineFrame * 0.001 + (i / len)), this.color1, this.color2, Color.COLOR_0); + // this.graphicMeshRenderer.setBaseColor(i, c); + this.graphicMeshRenderer.setUVRect(i, UV.getUVSheet((i / len) * 100 + engineFrame * 0.08, 3, 3)); + } + + for (let i = 0; i < this.tmpArray.length - 1; i++) { + this.view.graphic3D.Clear(i.toString()); + this.view.graphic3D.drawLines(i.toString(), [ + Vector3.ZERO, + this.tmpArray[i + 1].transform.worldPosition, + ], + this.colors); + } + } + } + + public madfrac(A: number, B: number): number { + return A * B - Math.floor(A * B); + } + + public sphericalFibonacci(i: number, n: number): Vector3 { + const PHI = Math.sqrt(5.0) * 0.5 + 0.5; + let phi = 2.0 * Math.PI * this.madfrac(i, PHI - 1); + let cosTheta = 1.0 - (2.0 * i + 1.0) * (1.0 / n); + let sinTheta = Math.sqrt(Math.max(Math.min(1.0 - cosTheta * cosTheta, 1.0), 0.0)); + + return new Vector3( + Math.cos(phi) * sinTheta, + Math.sin(phi) * sinTheta, + cosTheta); + } + +} diff --git a/samples/loader/Sample_LoadGLB.ts b/samples/loader/Sample_LoadGLB.ts index 2ef82b3b..d24ac932 100644 --- a/samples/loader/Sample_LoadGLB.ts +++ b/samples/loader/Sample_LoadGLB.ts @@ -83,14 +83,6 @@ export class Sample_LoadGLB { rotation: [180, 0, 0] } ) - list[`Mark-XLIV`] = JSON.stringify( - { - url: `gltfs/glb/Mark-XLIV.glb`, - scale: 0.1, - offset: [0, 0, 0], - rotation: [0, 0, 0] - } - ) list[`PotionBottle`] = JSON.stringify( { url: `gltfs/glb/PotionBottle.glb`, @@ -109,28 +101,33 @@ export class Sample_LoadGLB { ) let model: Object3D; + let { url, scale, offset, rotation } = JSON.parse(list[`HIE-Hand-Armor`]); + this.loadGLB(model, url, offset, scale, rotation); GUIHelp.add({ Model: `HIE-Hand-Armor` }, 'Model', list).onChange(async (v) => { let { url, scale, offset, rotation } = JSON.parse(v); - if (model) { - this.scene.removeChild(model); - } - model = (await Engine3D.res.loadGltf(url, { onProgress: (e) => this.onLoadProgress(e), onComplete: (e) => this.onComplete(e) })) as Object3D; - this.scene.addChild(model); - model.x = offset[0]; - model.y = offset[1]; - model.z = offset[2]; - - model.scaleX = scale; - model.scaleY = scale; - model.scaleZ = scale; - - model.rotationX = rotation[0]; - model.rotationY = rotation[1]; - model.rotationZ = rotation[2]; - + this.loadGLB(model, url, offset, scale, rotation); }); } + private async loadGLB(model: Object3D, url: string, offset: number[], scale: number, rotation: number[]) { + if (model) { + this.scene.removeChild(model); + } + model = (await Engine3D.res.loadGltf(url, { onProgress: (e) => this.onLoadProgress(e), onComplete: (e) => this.onComplete(e) })) as Object3D; + this.scene.addChild(model); + model.x = offset[0]; + model.y = offset[1]; + model.z = offset[2]; + + model.scaleX = scale; + model.scaleY = scale; + model.scaleZ = scale; + + model.rotationX = rotation[0]; + model.rotationY = rotation[1]; + model.rotationZ = rotation[2]; + } + onLoadProgress(e) { console.log(e); } diff --git a/samples/material/Sample_ClearCoat.ts b/samples/material/Sample_ClearCoat.ts index dedc92c5..3b7b013a 100644 --- a/samples/material/Sample_ClearCoat.ts +++ b/samples/material/Sample_ClearCoat.ts @@ -72,7 +72,7 @@ class Sample_ClearCoat { // model.transform.scaleZ = 10; // model.transform.y = -5; - let clearCoatRoughnessTex = await Engine3D.res.loadTexture("PBR/ClearCoatTest/T_Imperfections_Wipe_Mask.PNG"); + let clearCoatRoughnessTex = await Engine3D.res.loadTexture("materials/T_Imperfections_FingerPrints_Mask2.jpg"); // this.scene.addChild(model); let space = 50; diff --git a/samples/utils/ExampleScene.ts b/samples/utils/ExampleScene.ts index 1554b209..76f17251 100644 --- a/samples/utils/ExampleScene.ts +++ b/samples/utils/ExampleScene.ts @@ -48,10 +48,10 @@ let exampleSceneParam: ExampleSceneParam; export function createSceneParam(): ExampleSceneParam { let param: ExampleSceneParam = { camera: { - near: 1, - far: 5000, + near: 0.01, + far: 1000, distance: 100, - fov: 60, + fov: 45, pitch: -15, roll: -30, }, diff --git a/src/assets/shader/core/struct/VertexAttributeIndexShader.ts b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts index 99821333..475785bf 100644 --- a/src/assets/shader/core/struct/VertexAttributeIndexShader.ts +++ b/src/assets/shader/core/struct/VertexAttributeIndexShader.ts @@ -34,6 +34,11 @@ export let VertexAttributeIndexShader: string = /*wgsl*/ ` struct GraphicNodeStruct{ matrixIndex:f32, texIndex:f32, + tex2Index:f32, + tex3Index:f32, + baseColor:vec4f, + emissiveColor:vec4f, + uvRect:vec4f, } var ORI_VertexOut: VertexOutput ; diff --git a/src/assets/shader/lighting/BxDF_frag.ts b/src/assets/shader/lighting/BxDF_frag.ts index d2d39a73..5544a3b7 100644 --- a/src/assets/shader/lighting/BxDF_frag.ts +++ b/src/assets/shader/lighting/BxDF_frag.ts @@ -134,7 +134,6 @@ export let BxDF_frag: string = /*wgsl*/ ` #endif var color = specColor + indirectResult ; - color += fragData.Emissive.xyz ; var clearCoatColor = vec3(0.0); #if USE_CLEARCOAT @@ -147,8 +146,7 @@ export let BxDF_frag: string = /*wgsl*/ ` #endif var retColor = (LinearToGammaSpace(color.rgb)); - // retColor += fragData.Emissive.xyz ; - // ORI_FragmentOutput.color = vec4( irradiance * min(fragData.Albedo.rgb,vec3f(1.0)) ,fragData.Albedo.a) ; + retColor += fragData.Emissive.xyz ; ORI_FragmentOutput.color = vec4( retColor.rgb * fragData.Albedo.a ,fragData.Albedo.a) ; } diff --git a/src/assets/shader/materials/UnLitTextureArray.ts b/src/assets/shader/materials/UnLitTextureArray.ts index ad161668..bc5bec6f 100644 --- a/src/assets/shader/materials/UnLitTextureArray.ts +++ b/src/assets/shader/materials/UnLitTextureArray.ts @@ -52,9 +52,10 @@ export let UnLitTextureArray: string = /*wgsl*/ ` // irradiance += (globalUniform.skyExposure * textureSampleLevel(prefilterMap, prefilterMapSampler, ORI_VertexVarying.vWorldNormal.xyz, 0.8 * (MAX_REFLECTION_LOD) ).rgb); graphicNode = graphicBuffer[u32(round(ORI_VertexVarying.index))]; - + var uv = transformUV1.zw * ORI_VertexVarying.fragUV0 + transformUV1.xy; - let color = textureSample(baseMap,baseMapSampler,uv, u32(round(graphicNode.texIndex)) ); + uv = graphicNode.uvRect.zw * uv.xy + graphicNode.uvRect.xy; + var color = textureSample(baseMap,baseMapSampler,uv, u32(round(graphicNode.texIndex)) ) * graphicNode.baseColor ; // let color = textureSample(baseMap,baseMapSampler,uv, u32(round(ORI_VertexVarying.index))); // ORI_ViewDir = normalize( globalUniform.CameraPos.xyz - ORI_VertexVarying.vWorldPos.xyz); @@ -62,6 +63,7 @@ export let UnLitTextureArray: string = /*wgsl*/ ` // irradiance = LinearToGammaSpace(irradiance.rgb) * color.rgb ;//* att ; + color += graphicNode.emissiveColor ; if(color.w < 0.5){ discard ; } diff --git a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts index 82ca2a14..b3e56f62 100644 --- a/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts +++ b/src/gfx/renderJob/passRenderer/graphic/new/Graphic3DMeshRenderer.ts @@ -1,3 +1,4 @@ +import { Color, Vector4 } from "../../../../.."; import { MeshRenderer } from "../../../../../components/renderer/MeshRenderer"; import { View3D } from "../../../../../core/View3D"; import { Object3D } from "../../../../../core/entities/Object3D"; @@ -23,7 +24,8 @@ export class Graphic3DMeshRenderer extends MeshRenderer { mat.baseMap = tex; this.material = mat; - this.transformBuffer = new StorageGPUBuffer(num * 2, 0); + this.transformBuffer = new StorageGPUBuffer( num * (4 * 4) , 0); + // this.transformBuffer = new StorageGPUBuffer( num * 2 , 0); this.material.setStorageBuffer("graphicBuffer", this.transformBuffer); this.object3Ds = []; @@ -34,6 +36,11 @@ export class Graphic3DMeshRenderer extends MeshRenderer { this.transformBuffer.setFloat("matrix_" + i, element.transform.worldMatrix.index); this.transformBuffer.setFloat("texId_" + i, 1); + this.transformBuffer.setFloat("texId2_" + i, 1); + this.transformBuffer.setFloat("texId3_" + i, 1); + this.transformBuffer.setColor("baseColor_" + i, new Color() ); + this.transformBuffer.setColor("emissiveColor_" + i, new Color(0,0,0,0)); + this.transformBuffer.setVector4("uvRect_" + i, new Vector4(0,0,1,1) ); } this.transformBuffer.apply(); @@ -45,6 +52,31 @@ export class Graphic3DMeshRenderer extends MeshRenderer { this._onChange = true; } + // public setTexture2ID(i: number, id: number) { + // this.transformBuffer.setFloat("texId_" + i, id); + // this._onChange = true; + // } + + // public setTexture3ID(i: number, id: number) { + // this.transformBuffer.setFloat("texId_" + i, id); + // this._onChange = true; + // } + + public setBaseColor(i: number, color: Color) { + this.transformBuffer.setColor("baseColor_" + i, color); + this._onChange = true; + } + + public setEmissiveColor(i: number, color: Color) { + this.transformBuffer.setColor("emissiveColor_" + i, color); + this._onChange = true; + } + + public setUVRect(i: number, v: Vector4) { + this.transformBuffer.setVector4("uvRect_" + i, v); + this._onChange = true; + } + public onUpdate(view?: View3D) { if (this._onChange) { this._onChange = false; diff --git a/src/loader/parser/gltf/GLTFSubParserConverter.ts b/src/loader/parser/gltf/GLTFSubParserConverter.ts index 07d95f5b..99479482 100644 --- a/src/loader/parser/gltf/GLTFSubParserConverter.ts +++ b/src/loader/parser/gltf/GLTFSubParserConverter.ts @@ -180,7 +180,7 @@ export class GLTFSubParserConverter { let physicMaterial = (newMat = this.applyMaterialExtensions(primitive.material, newMat)); if (`enableBlend` in primitive.material) { if (primitive.material[`enableBlend`]) { - physicMaterial.blendMode = BlendMode.NORMAL; + physicMaterial.blendMode = BlendMode.SOFT_ADD; } else { physicMaterial.blendMode = BlendMode.NONE; } diff --git a/src/materials/LitMaterial.ts b/src/materials/LitMaterial.ts index 1a15c7be..ae7128ba 100644 --- a/src/materials/LitMaterial.ts +++ b/src/materials/LitMaterial.ts @@ -94,6 +94,53 @@ export class LitMaterial extends Material { return this.shader.getTexture(`aoMap`); } + public set clearCoatRoughnessMap(texture: Texture) { + this.shader.setTexture(`clearCoatRoughnessMap`, texture); + this.shader.setDefine(`USE_CLEARCOAT`, true); + this.shader.setDefine(`USE_CLEARCOAT_ROUGHNESS`, true); + } + + public get clearCoatRoughnessMap() { + return this.shader.getTexture(`clearCoatRoughnessMap`); + } + + public set clearcoatColor(value: Color) { + this.shader.setUniformColor(`clearcoatColor`, value); + this.shader.setDefine(`USE_CLEARCOAT`, true); + } + + public get clearcoatColor() { + return this.shader.getUniformColor(`clearcoatColor`); + } + + public set clearcoatWeight(value: number) { + this.shader.setUniformFloat(`clearcoatWeight`, value); + this.shader.setDefine(`USE_CLEARCOAT`, true); + } + + public get clearcoatWeight() { + return this.shader.getUniformFloat(`clearcoatWeight`); + } + + public set clearcoatFactor(value: number) { + this.shader.setUniformFloat(`clearcoatFactor`, value); + this.shader.setDefine(`USE_CLEARCOAT`, true); + } + + public get clearcoatFactor() { + return this.shader.getUniformFloat(`clearcoatFactor`); + } + + + public set clearcoatRoughnessFactor(value: number) { + this.shader.setUniformFloat(`clearcoatRoughnessFactor`, value); + this.shader.setDefine(`USE_CLEARCOAT`, true); + } + + public get clearcoatRoughnessFactor() { + return this.shader.getUniformFloat(`clearcoatRoughnessFactor`); + } + public set alphaCutoff(value: number) { this.shader.setUniform(`alphaCutoff`, value); } diff --git a/src/materials/SkyMaterial.ts b/src/materials/SkyMaterial.ts index 0bc7c7d5..f8f807fa 100644 --- a/src/materials/SkyMaterial.ts +++ b/src/materials/SkyMaterial.ts @@ -17,7 +17,7 @@ export class SkyMaterial extends Material { this.shader = new SkyShader(); this.shader.setUniformVector3(`eyesPos`, new Vector3()); this.shader.setUniformFloat(`exposure`, 1.0); - this.shader.setUniformFloat(`roughness`, 0.5); + this.shader.setUniformFloat(`roughness`, 0.0); } /** diff --git a/src/math/Color.ts b/src/math/Color.ts index db956d2d..8320908b 100644 --- a/src/math/Color.ts +++ b/src/math/Color.ts @@ -307,6 +307,22 @@ export class Color { return dst; } + /** + * lerp two color + * @param v + * @param c1 + * @param c2 + * @param target + * @returns + */ + public static lerp(v:number, c1:Color,c2:Color,target?:Color){ + let ret = target ? target : new Color(); + ret.r = (c2.r - c1.r) * v + c1.r ; + ret.g = (c2.g - c1.g) * v + c1.g ; + ret.b = (c2.b - c1.b) * v + c1.b ; + ret.a = (c2.a - c1.a) * v + c1.a ; + return target ; + } public static PRIMARY = 0x3f51b5; // diff --git a/src/math/UV.ts b/src/math/UV.ts index 06de89c0..5bbac7eb 100644 --- a/src/math/UV.ts +++ b/src/math/UV.ts @@ -1,3 +1,4 @@ +import { Vector4 } from '..'; import { Vector2 } from './Vector2'; /*** @@ -20,4 +21,12 @@ export class UV extends Vector2 { public length(): number { return 0; } + + public static getUVSheet(frame: number, countX: number, countY: number) { + let f = Math.floor(frame % (countX * countY)); + let fx = Math.floor(f / countX); + let fy = f % countX; + return new Vector4((fx / countX), (fy / countY), 1 / countX, 1 / countY); + } } + diff --git a/src/textures/BitmapTexture2DArray.ts b/src/textures/BitmapTexture2DArray.ts index a07c316c..f6897ae9 100644 --- a/src/textures/BitmapTexture2DArray.ts +++ b/src/textures/BitmapTexture2DArray.ts @@ -49,7 +49,7 @@ export class BitmapTexture2DArray extends Texture implements ITexture { */ public addTexture(bitmapTexture: BitmapTexture2D) { if (bitmapTexture.width != this.width || bitmapTexture.height != this.height) { - console.error("bitmap texture muse match bitmapTextureArray size!"); + console.error("bitmap texture must match bitmapTextureArray size!"); } // if (this._bitmapTextures.indexOf(bitmapTexture) == -1) { bitmapTexture.pid = this._bitmapTextures.length; From db69b98a250e89900840a610c49d5f1b067fe5b8 Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Wed, 1 Nov 2023 14:17:42 +0800 Subject: [PATCH 10/14] bump v0.7.0 update all dependencies --- CHANGELOG.md | 17 +++++++++ package.json | 2 +- packages/effect/package.json | 4 +-- packages/media-extention/package.json | 4 +-- packages/particle/package.json | 4 +-- packages/physics/package.json | 4 +-- packages/post/package.json | 2 +- packages/stats/package.json | 4 +-- packages/uiTool/package.json | 36 ------------------- public | 2 +- .../parser/prefab/mats/MaterialUtilities.ts | 1 - 11 files changed, 30 insertions(+), 50 deletions(-) delete mode 100644 packages/uiTool/package.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 29ee75e7..dd661031 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +# [0.7.0](https://github.com/Orillusion/orillusion/compare/v0.6.9...v0.7.0) (2023-11-01) + + +### Bug Fixes + +* Character loss during text layout. ([#317](https://github.com/Orillusion/orillusion/issues/317)) ([8ad7169](https://github.com/Orillusion/orillusion/commit/8ad71695df37ce3b21833773fe4c429817d2108c)) +* fix gltf sample ([#321](https://github.com/Orillusion/orillusion/issues/321)) ([4ca35b5](https://github.com/Orillusion/orillusion/commit/4ca35b576454cb52aee47ddbc271a4d36a906e78)) +* **particle:** add get baseMap ([e59bd9f](https://github.com/Orillusion/orillusion/commit/e59bd9f4d43e98941ef634aff5c4e525a02cc6f1)) + + +### Features + +* add graphic bath mesh ([#319](https://github.com/Orillusion/orillusion/issues/319)) ([7df4f95](https://github.com/Orillusion/orillusion/commit/7df4f95c9bfa85dc2aae121a64916121c2741988)) +* **audio:** move audio to @orillusion/media-extension ([166d286](https://github.com/Orillusion/orillusion/commit/166d2866b3e427339082f6bbdc7d391d4b91e784)) + + + ## [0.6.9](https://github.com/Orillusion/orillusion/compare/v0.6.8...v0.6.9) (2023-09-06) ### Bug Fixes diff --git a/package.json b/package.json index 65c16ddd..db371c08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/core", - "version": "0.6.9", + "version": "0.7.0", "author": "Orillusion", "description": "Orillusion WebGPU Engine", "main": "./dist/orillusion.umd.js", diff --git a/packages/effect/package.json b/packages/effect/package.json index 0df0c639..1bf36ae6 100644 --- a/packages/effect/package.json +++ b/packages/effect/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/effect", - "version": "0.1.0", + "version": "0.1.1", "author": "Orillusion", "description": "Orillusion Effects Plugin", "main": "./dist/effect.umd.js", @@ -19,6 +19,6 @@ "url": "git+https://github.com/Orillusion/orillusion.git" }, "dependencies": { - "@orillusion/core": "^0.6.9" + "@orillusion/core": "^0.7.0" } } diff --git a/packages/media-extention/package.json b/packages/media-extention/package.json index 13e92ff0..80f6baa8 100644 --- a/packages/media-extention/package.json +++ b/packages/media-extention/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/media-extention", - "version": "0.3.1", + "version": "0.3.2", "author": "Orillusion", "description": "Orillusion Media Material Extention", "main": "./dist/media.umd.js", @@ -21,6 +21,6 @@ "url": "git+https://github.com/Orillusion/orillusion.git" }, "dependencies": { - "@orillusion/core": "^0.6.9" + "@orillusion/core": "^0.7.0" } } diff --git a/packages/particle/package.json b/packages/particle/package.json index fa8da685..ab16b5c7 100644 --- a/packages/particle/package.json +++ b/packages/particle/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/particle", - "version": "0.0.3", + "version": "0.1.0", "author": "Orillusion", "description": "Orillusion Particle Plugin", "main": "./dist/particle.umd.js", @@ -21,6 +21,6 @@ "url": "git+https://github.com/Orillusion/orillusion.git" }, "dependencies": { - "@orillusion/core": "^0.6.9" + "@orillusion/core": "^0.7.0" } } diff --git a/packages/physics/package.json b/packages/physics/package.json index 6d802bf4..9ad3ab65 100644 --- a/packages/physics/package.json +++ b/packages/physics/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/physics", - "version": "0.2.0", + "version": "0.2.1", "author": "Orillusion", "description": "Orillusion Physics Plugin, Powerd by Ammo.js", "main": "./dist/physics.umd.js", @@ -22,6 +22,6 @@ }, "dependencies": { "@orillusion/ammo": "^0.1.1", - "@orillusion/core": "^0.6.0" + "@orillusion/core": "^0.7.0" } } diff --git a/packages/post/package.json b/packages/post/package.json index 4b5abb5b..398bd599 100644 --- a/packages/post/package.json +++ b/packages/post/package.json @@ -19,6 +19,6 @@ "url": "git+https://github.com/Orillusion/orillusion.git" }, "dependencies": { - "@orillusion/core": "^0.6.0" + "@orillusion/core": "^0.7.0" } } diff --git a/packages/stats/package.json b/packages/stats/package.json index 2bc62291..9ac88616 100644 --- a/packages/stats/package.json +++ b/packages/stats/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/stats", - "version": "0.2.0", + "version": "0.2.1", "author": "Orillusion", "description": "Orillusion Stats Plugin", "main": "./dist/stats.umd.js", @@ -21,6 +21,6 @@ "url": "git+https://github.com/Orillusion/orillusion.git" }, "dependencies": { - "@orillusion/core": "^0.6.0" + "@orillusion/core": "^0.7.0" } } diff --git a/packages/uiTool/package.json b/packages/uiTool/package.json deleted file mode 100644 index 67e65595..00000000 --- a/packages/uiTool/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@orillusion/uitool", - "version": "0.1.7", - "author": "Orillusion", - "description": "Orillusion ui tool", - "main": "./dist/uitool.umd.js", - "module": "./dist/uitool.es.js", - "types": "./dist/UITool.d.ts", - "files": [ - "dist", - "tsconfig.json", - "tsconfig.node.json" - ], - "type": "module", - "scripts": { - "dev": "vite", - "build": "vue-tsc && vite build", - "build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json", - "build:publish": "npm run build && npm run build:types && npm publish", - "preview": "vite preview" - }, - "devDependencies": { - "@types/node": "^18.15.11", - "@vitejs/plugin-vue": "^4.1.0", - "element-plus": "^2.3.1", - "nanoid": "^4.0.2", - "typescript": "^4.9.3", - "unplugin-auto-import": "^0.15.3", - "unplugin-vue-components": "^0.24.1", - "vite": "^4.2.0", - "vite-plugin-css-injected-by-js": "^3.1.0", - "vue": "^3.2.47", - "vue-tsc": "^1.2.0", - "@orillusion/core": "^0.6.2" - } -} diff --git a/public b/public index 1e9b664b..5f32b408 160000 --- a/public +++ b/public @@ -1 +1 @@ -Subproject commit 1e9b664bf6b6fc2985cfa5608463b57eed1324e5 +Subproject commit 5f32b408d1314243ece38c4fd47c871206cd7996 diff --git a/src/loader/parser/prefab/mats/MaterialUtilities.ts b/src/loader/parser/prefab/mats/MaterialUtilities.ts index 7f65c967..ecea5dcd 100644 --- a/src/loader/parser/prefab/mats/MaterialUtilities.ts +++ b/src/loader/parser/prefab/mats/MaterialUtilities.ts @@ -65,7 +65,6 @@ export class MaterialUtilities { case ValueEnumType.int: case ValueEnumType.int16: case ValueEnumType.int32: - case ValueEnumType.int32: case ValueEnumType.uint: case ValueEnumType.uint32: case ValueEnumType.uint64: From 17b739db45aa6dad5981a52da7f77b784a136659 Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Wed, 1 Nov 2023 14:25:02 +0800 Subject: [PATCH 11/14] chore: remove unused script --- index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/index.html b/index.html index ff36f92d..8f11abcc 100644 --- a/index.html +++ b/index.html @@ -119,7 +119,6 @@ - \ No newline at end of file From e90839de1ced33ca2101c603fdc6567e4b2683f3 Mon Sep 17 00:00:00 2001 From: ShuangLiu Date: Wed, 1 Nov 2023 15:37:17 +0800 Subject: [PATCH 12/14] fix(media): fix ChromaKeyMaterial error --- packages/media-extention/ChromaKeyMaterial.ts | 3 ++- packages/media-extention/package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/media-extention/ChromaKeyMaterial.ts b/packages/media-extention/ChromaKeyMaterial.ts index 2830ff87..33f5a8ac 100644 --- a/packages/media-extention/ChromaKeyMaterial.ts +++ b/packages/media-extention/ChromaKeyMaterial.ts @@ -53,7 +53,8 @@ export class ChromaKeyMaterial extends Material { shaderState.castShadow = false; shaderState.useZ = false; shaderState.blendMode = BlendMode.ALPHA; - + this.shader = newShader; + // default value this.shader.setTexture(`baseMap`, Engine3D.res.whiteTexture); } diff --git a/packages/media-extention/package.json b/packages/media-extention/package.json index 80f6baa8..c4d6facf 100644 --- a/packages/media-extention/package.json +++ b/packages/media-extention/package.json @@ -1,6 +1,6 @@ { "name": "@orillusion/media-extention", - "version": "0.3.2", + "version": "0.3.3", "author": "Orillusion", "description": "Orillusion Media Material Extention", "main": "./dist/media.umd.js", From e09b24386bb517d1277e00dcaa4105999d2dd856 Mon Sep 17 00:00:00 2001 From: moyuer1992 Date: Fri, 10 Nov 2023 18:47:04 +0800 Subject: [PATCH 13/14] feat(sample): update physics car sample (#327) * update physics car sample --------- Co-authored-by: ShuangLiu --- samples/physics/Sample_PhysicsCar.ts | 692 ++++++++++++++------------- 1 file changed, 354 insertions(+), 338 deletions(-) diff --git a/samples/physics/Sample_PhysicsCar.ts b/samples/physics/Sample_PhysicsCar.ts index abd75aaf..b17337fa 100644 --- a/samples/physics/Sample_PhysicsCar.ts +++ b/samples/physics/Sample_PhysicsCar.ts @@ -1,14 +1,17 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { Ammo, Physics, Rigidbody } from "@orillusion/physics"; import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; -import { Scene3D, Object3D, LitMaterial, Engine3D, BoxGeometry, MeshRenderer, ColliderComponent, BoxColliderShape, Vector3, PlaneGeometry, Color, ComponentBase, KeyCode, KeyEvent, Quaternion, CylinderGeometry } from "@orillusion/core"; -import { GUIUtil } from "@samples/utils/GUIUtil"; +import { Scene3D, Object3D, Engine3D, ColliderComponent, BoxColliderShape, Vector3, ComponentBase, KeyCode, KeyEvent, Quaternion, BoundUtil, Camera3D, Vector3Ex, MeshRenderer, LitMaterial, Color, BoxGeometry } from "@orillusion/core"; class Sample_PhysicsCar { private scene: Scene3D; - private materials: LitMaterial[]; - private boxGeometry: BoxGeometry; + private car: Object3D; + private boxes: Object3D[]; + private road: Object3D; + private camera: Camera3D; + private controller: fixedCameraController + public score = { Score: 0 } async run() { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.updateFrameRate = 1; @@ -19,357 +22,370 @@ class Sample_PhysicsCar { await Engine3D.init({ renderLoop: () => this.loop() }); let sceneParam = createSceneParam(); - sceneParam.camera.distance = 50; let exampleScene = createExampleScene(sceneParam); - - GUIHelp.init(); - GUIUtil.renderDirLight(exampleScene.light, false); - + this.camera = exampleScene.camera; this.scene = exampleScene.scene; await this.initScene(this.scene); Engine3D.startRenderView(exampleScene.view); + + GUIHelp.init(); + GUIHelp.open(); + GUIHelp.add(this.controller, 'enable').name('Fix Camera'); + GUIHelp.add(this.score, 'Score').listen(); + GUIHelp.addButton('Reset', () => { + location.reload() + }) } async initScene(scene: Scene3D) { - this.createGround(); - } - - private createGround() { - let floorMat = new LitMaterial(); - floorMat.baseMap = Engine3D.res.grayTexture; - floorMat.roughness = 0.85; - floorMat.metallic = 0.01; - floorMat.envIntensity = 0.01; - - let floor = new Object3D(); - let renderer = floor.addComponent(MeshRenderer); - - renderer.castShadow = true; - renderer.receiveShadow = true; - renderer.geometry = new PlaneGeometry(200, 200, 1, 1); - renderer.material = floorMat; - - let rigidBody = floor.addComponent(Rigidbody); - rigidBody.mass = 0; - rigidBody.friction = 2; - // rigidBody.restitution = 0.1; - - let collider = floor.addComponent(ColliderComponent); - collider.shape = new BoxColliderShape(); - collider.shape.size = new Vector3(200, 1, 200); - this.scene.addChild(floor); - - class CarController extends ComponentBase { - actions = {}; - syncList = []; - keysActions = { - KeyUp: 'acceleration', - KeyDown: 'braking', - KeyLeft: 'left', - KeyRight: 'right', - }; - start() { - Engine3D.inputSystem.addEventListener(KeyEvent.KEY_UP, this.keyUp, this); - Engine3D.inputSystem.addEventListener(KeyEvent.KEY_DOWN, this.keyDown, this); - } - - stop() { - Engine3D.inputSystem.removeEventListener(KeyEvent.KEY_UP, this.keyUp, this); - Engine3D.inputSystem.removeEventListener(KeyEvent.KEY_DOWN, this.keyDown, this); - } - - destroy(force) { - Engine3D.inputSystem.removeEventListener(KeyEvent.KEY_UP, this.keyUp, this); - Engine3D.inputSystem.removeEventListener(KeyEvent.KEY_DOWN, this.keyDown, this); - } - - keyUp(e) { - switch (e.keyCode) { - case KeyCode.Key_Up: - this.actions[this.keysActions['KeyUp']] = false; - break; - case KeyCode.Key_Down: - this.actions[this.keysActions['KeyDown']] = false; - break; - case KeyCode.Key_Left: - this.actions[this.keysActions['KeyLeft']] = false; - break; - case KeyCode.Key_Right: - this.actions[this.keysActions['KeyRight']] = false; - break; - } + // load a car model + { + this.car = await Engine3D.res.loadGltf( + "https://cdn.orillusion.com/gltfs/glb/vevhicle.glb" + ); + this.car.y = 2 + let collider = this.car.addComponent(ColliderComponent); + collider.shape = new BoxColliderShape(); + collider.shape.size = BoundUtil.genMeshBounds(this.car).size.clone(); + scene.addChild(this.car); + // add keyboard controller to the car + this.car.addComponent(VehicleKeyboardController); + // fix the camera to the car + this.controller = this.camera.object3D.addComponent( + fixedCameraController + ); + this.controller.target = this.car; + this.controller.distance = 50; + } + // add a plane as road + { + this.road = new Object3D(); + let mr = this.road.addComponent(MeshRenderer); + mr.geometry = new BoxGeometry(200, 0.1, 40); + let mat = (mr.material = new LitMaterial()); + mat.roughness = 1; + mat.metallic = 0; + mat.baseMap = await Engine3D.res.loadTexture("data:image/webp;base64,UklGRqAAAABXRUJQVlA4TJMAAAAvV8INER8gEEhxXGstIEmxu7qVgCTF7upWAgFCiv8qJwJXoF8wimQrDiiLCnCG0KzXL4DlRKoj+j8BtSxpW5XY2teypI3/+I//+I//+I//+I//+I//+I//+I//+I//+G8vkFO/Yzuj24P/flBy6nds0+Q//uM//uM//uM//uM//uM//uM//uM//uM//gOwL9Z0FwUA"); + let collider = this.road.addComponent(ColliderComponent); + collider.shape = new BoxColliderShape(); + collider.shape.size = BoundUtil.genMeshBounds( + this.road + ).size.clone(); + console.log(collider.shape.size) + this.road.rotationY = -90; + let rigidbody = this.road.addComponent(Rigidbody); + rigidbody.mass = 0; + scene.addChild(this.road); + } + // add boxes + { + let geometry = new BoxGeometry(1,1,1) + let mat = new LitMaterial(); + mat.baseColor = Color.random() + this.boxes = []; + for (let i = 0; i < 20; i++) { + this.boxes[i] = new Object3D() + let mr = this.boxes[i].addComponent(MeshRenderer) + mr.geometry = geometry; + mr.material = mat; + this.boxes[i].x = Math.random() * 30 - 15; + this.boxes[i].y = Math.random() * 2; + this.boxes[i].z = Math.random() * 200 - 100; + let rigidbody = this.boxes[i].addComponent(Rigidbody); + rigidbody.mass = 1; + let collider = this.boxes[i].addComponent(ColliderComponent); + collider.shape = new BoxColliderShape(); + collider.shape.size = BoundUtil.genMeshBounds( + this.boxes[i] + ).size.clone(); + scene.addChild(this.boxes[i]); } + } + } - keyDown(e) { - // console.log(e.keyCode); - switch (e.keyCode) { - case KeyCode.Key_Up: - this.actions[this.keysActions['KeyUp']] = true; - break; - case KeyCode.Key_Down: - this.actions[this.keysActions['KeyDown']] = true; - break; - case KeyCode.Key_Left: - this.actions[this.keysActions['KeyLeft']] = true; - break; - case KeyCode.Key_Right: - this.actions[this.keysActions['KeyRight']] = true; - break; - } + private loop() { + Physics.update(); + this.boxes.map((box, index) => { + if (box.y < -5) { + this.score.Score++; + this.scene.removeChild(box); + this.boxes.splice(index, 1); } + }); + } +} - onUpdate(view) { - if (Physics.isInited) { - for (let i = 0; i < this.syncList.length; i++) { - this.syncList[i](16); - } - } +enum VehicleControlType { + acceleration, + braking, + left, + right, +} +/** + * Keyboard controller for the car + */ +class VehicleKeyboardController extends ComponentBase { + protected mBody: Object3D; + protected mWheels: Object3D[]; + protected mEngineForce = 0; + protected mBreakingForce = 0; + protected mVehicleSteering = 0; + protected mAmmoVehicle; + protected mVehicleArgs = { + bodyMass: 800, + friction: 1000, + suspensionStiffness: 20.0, + suspensionDamping: 2.3, + suspensionCompression: 4.4, + suspensionRestLength: 0.6, + rollInfluence: 0.2, + steeringIncrement: 0.04, + steeringClamp: 0.5, + maxEngineForce: 1500, + maxBreakingForce: 500 + } + protected mVehicleControlState = [false, false, false, false]; + async start() { + this.mBody = this.object3D; + let w1 = this.object3D.getChildByName("wheel_1"); + let w2 = this.object3D.getChildByName("wheel_2"); + let w3 = this.object3D.getChildByName("wheel_3"); + let w4 = this.object3D.getChildByName("wheel_4"); + this.mWheels = [w1, w2, w3, w4]; + this.initController(); + } + initController() { + let bound = BoundUtil.genMeshBounds(this.mBody); + this.mBody.entityChildren[0].transform.y = -bound.size.y / 2 - 0.05; + let geometry = new Ammo.btBoxShape( + new Ammo.btVector3( + bound.size.x / 2, + bound.size.y / 2, + bound.size.z / 2 + ) + ); + let transform = new Ammo.btTransform(); + transform.setIdentity(); + transform.setOrigin( + new Ammo.btVector3( + this.mBody.transform.worldPosition.z, + this.mBody.transform.worldPosition.y, + this.mBody.transform.worldPosition.z + ) + ); + transform.setRotation(new Ammo.btQuaternion(0, 0, 0, 1)); + let motionState = new Ammo.btDefaultMotionState(transform); + let localInertia = new Ammo.btVector3(0, 0, 0); + geometry.calculateLocalInertia( + this.mVehicleArgs.bodyMass, + localInertia + ); + let bodyRb = new Ammo.btRigidBody( + new Ammo.btRigidBodyConstructionInfo( + this.mVehicleArgs.bodyMass, + motionState, + geometry, + localInertia + ) + ); + bodyRb.setActivationState(4); + Physics.world.addRigidBody(bodyRb); + //raycast Vehicle + let tuning = new Ammo.btVehicleTuning(); + let rayCaster = new Ammo.btDefaultVehicleRaycaster(Physics.world); + let vehicle = new Ammo.btRaycastVehicle(tuning, bodyRb, rayCaster); + vehicle.setCoordinateSystem(0, 1, 2); + this.mAmmoVehicle = vehicle; + Physics.world.addAction(vehicle); + let wheelDirectCS0 = new Ammo.btVector3(0, -1, 0); + let wheelAxleCS = new Ammo.btVector3(-1, 0, 0); + let addWheel = (isFront:boolean, x:number, y:number, z:number, radius:number) => { + let pos = new Ammo.btVector3(x, y, z); + let wheelInfo = vehicle.addWheel( + pos, + wheelDirectCS0, + wheelAxleCS, + this.mVehicleArgs.suspensionRestLength, + radius, + tuning, + isFront + ); + wheelInfo.set_m_suspensionStiffness(this.mVehicleArgs.suspensionStiffness); + wheelInfo.set_m_wheelsDampingRelaxation(this.mVehicleArgs.suspensionDamping); + wheelInfo.set_m_wheelsDampingCompression(this.mVehicleArgs.suspensionCompression); + wheelInfo.set_m_frictionSlip(this.mVehicleArgs.friction); + wheelInfo.set_m_rollInfluence(this.mVehicleArgs.rollInfluence); + }; + + const r = BoundUtil.genMeshBounds(this.mWheels[0]).size.y / 2; + const x =this.mWheels[0].transform.worldPosition.x - this.mBody.transform.worldPosition.x; + const y = BoundUtil.genMeshBounds(this.mWheels[0]).size.y - r + 0.1; + const z = this.mWheels[0].transform.worldPosition.z - this.mBody.transform.worldPosition.z; + addWheel(true, -x, -y, z, r); + addWheel(true, x, -y, z, r); + addWheel(false, -x, -y, -z, r); + addWheel(false, x, -y, -z, r); + } + onEnable() { + Engine3D.inputSystem.addEventListener(KeyEvent.KEY_UP, this.onKeyUp, this); + Engine3D.inputSystem.addEventListener(KeyEvent.KEY_DOWN, this.onKeyDown, this); + } + onDisable() { + Engine3D.inputSystem.addEventListener(KeyEvent.KEY_UP, this.onKeyUp, this); + Engine3D.inputSystem.addEventListener(KeyEvent.KEY_DOWN, this.onKeyDown, this); + } + onUpdate() { + if (!this.mAmmoVehicle) return; + const vehicle = this.mAmmoVehicle; + const speed = vehicle.getCurrentSpeedKmHour(); + this.mBreakingForce = 0; + this.mEngineForce = 0; + if (this.mVehicleControlState[VehicleControlType.acceleration]) { + if (speed < -1) + this.mBreakingForce = Math.min(this.mVehicleArgs.maxEngineForce / 3, 1000); + else this.mEngineForce = this.mVehicleArgs.maxEngineForce; + } + if (this.mVehicleControlState[VehicleControlType.braking]) { + if (speed > 1) + this.mBreakingForce = Math.min(this.mVehicleArgs.maxEngineForce / 3, 1000); + else this.mEngineForce = -this.mVehicleArgs.maxEngineForce / 2; + } + if (this.mVehicleControlState[VehicleControlType.left]) { + if (this.mVehicleSteering < this.mVehicleArgs.steeringClamp) + this.mVehicleSteering += this.mVehicleArgs.steeringIncrement; + } else if (this.mVehicleControlState[VehicleControlType.right]) { + if (this.mVehicleSteering > -this.mVehicleArgs.steeringClamp) + this.mVehicleSteering -= this.mVehicleArgs.steeringIncrement; + } else { + if (this.mVehicleSteering < -this.mVehicleArgs.steeringIncrement) { + this.mVehicleSteering += this.mVehicleArgs.steeringIncrement; + } else { + if (this.mVehicleSteering > this.mVehicleArgs.steeringIncrement) + this.mVehicleSteering -= + this.mVehicleArgs.steeringIncrement; + else this.mVehicleSteering = 0; } } - - let url = "gltfs/pbrCar/pbrCar.glb" - Engine3D.res.loadGltf(url).then((e) => { - let body = e.getChildByName("Exoplanet-Rover_Exoplanet-Rover_0") as Object3D; - let scene = this.scene; - let bodyMass = 1300; - - - var chassisWidth = 2.8; - var chassisHeight = .6; - var chassisLength = 4; - var massVehicle = 800; - - var wheelAxisPositionBack = -1.3; - var wheelAxisHeightBack = .3; - var wheelRadiusBack = .4; - var wheelWidthBack = .4; - var wheelHalfTrackBack = 1.2; - - var wheelAxisFrontPosition = 1.7; - var wheelAxisHeightFront = .3; - var wheelRadiusFront = .4; - var wheelWidthFront = .4; - var wheelHalfTrackFront = 1.2; - - var friction = 1000; - var suspensionStiffness = 10.0; - var suspensionDamping = 6.3; - var suspensionCompression = 2.4; - var suspensionRestLength = 0.45; - var rollInfluence = 0.1; - - var steeringIncrement = .04; - var steeringClamp = .5; - var maxEngineForce = 2000; - var maxBreakingForce = 100; - - let bodyObj = new Object3D(); - let bodyMat = new LitMaterial(); - bodyMat.baseMap = Engine3D.res.whiteTexture; - bodyMat.normalMap = Engine3D.res.normalTexture; - bodyMat.aoMap = Engine3D.res.whiteTexture; - bodyMat.maskMap = Engine3D.res.whiteTexture; - bodyMat.emissiveMap = Engine3D.res.blackTexture; - let bodyMr = bodyObj.addComponent(MeshRenderer); - let carController = bodyObj.addComponent(CarController); - bodyMr.geometry = new BoxGeometry(chassisWidth * 0.5, chassisHeight * 0.5, chassisLength * 0.5); - bodyMr.material = bodyMat; - var geometry = new Ammo.btBoxShape(new Ammo.btVector3(chassisWidth * 0.5, chassisHeight * 0.5, chassisLength * 0.5)); - var transform = new Ammo.btTransform(); - transform.setIdentity(); - transform.setOrigin(new Ammo.btVector3(bodyObj.x, bodyObj.y, bodyObj.z)); - transform.setRotation(new Ammo.btQuaternion(0, 0, 0, 1)); - var motionState = new Ammo.btDefaultMotionState(transform); - var localInertia = new Ammo.btVector3(0, 0, 0); - geometry.calculateLocalInertia(bodyMass, localInertia); - var bodyRb = new Ammo.btRigidBody(new Ammo.btRigidBodyConstructionInfo(bodyMass, motionState, geometry, localInertia)); - bodyRb.setActivationState(4); - Physics.world.addRigidBody(bodyRb); - - body.scaleX = 0.0055; - body.scaleY = 0.0055; - body.scaleZ = 0.0055; - body.rotationX = 0; - body.y = -1.1; - body.z = -0.15 - bodyObj.addChild(body); - - bodyObj.y = 10 - scene.addChild(bodyObj); - - //raycast Vehicle - let engineForce = 0; - let vehicleSteering = 0; - let breakingForce = 0; - let tuning = new Ammo.btVehicleTuning(); - let rayCaster = new Ammo.btDefaultVehicleRaycaster(Physics.world); - let vehicle = new Ammo.btRaycastVehicle(tuning, bodyRb, rayCaster); - vehicle.setCoordinateSystem(0, 1, 2); - Physics.world.addAction(vehicle); - - //create wheels - - const FRONT_LEFT = 0; - const FRONT_RIGHT = 1; - const BACK_LEFT = 2; - const BACK_RIGHT = 3; - - let wheelMeshes = []; - let wheelDirectCS0 = new Ammo.btVector3(0, -1, 0); - let wheelAxleCS = new Ammo.btVector3(-1, 0, 0); - - let addWheel = (name, isFront, pos, radius, width, index) => { - let wheelInfo = vehicle.addWheel(pos, wheelDirectCS0, wheelAxleCS, suspensionRestLength, radius, tuning, isFront); - wheelInfo.set_m_suspensionStiffness(suspensionStiffness); - wheelInfo.set_m_wheelsDampingRelaxation(suspensionDamping); - wheelInfo.set_m_wheelsDampingCompression(suspensionCompression); - wheelInfo.set_m_frictionSlip(friction); - wheelInfo.set_m_rollInfluence(rollInfluence); - wheelMeshes[index] = this.createWheelObject(name, radius, width, e); - }; - - addWheel("ExoRov_FrontWheel_L_ExoRov_Wheels_0", true, new Ammo.btVector3(wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition), wheelRadiusFront, wheelWidthFront, FRONT_LEFT); - addWheel("ExoRov_FrontWheel_R_ExoRov_Wheels_0", true, new Ammo.btVector3(-wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition), wheelRadiusFront, wheelWidthFront, FRONT_RIGHT); - addWheel("ExoRov_BackWheel_L_ExoRov_Wheels_0", false, new Ammo.btVector3(-wheelHalfTrackBack, wheelAxisHeightBack, wheelAxisPositionBack), wheelRadiusBack, wheelWidthBack, BACK_LEFT); - addWheel("ExoRov_BackWheel_R_ExoRov_Wheels_0", false, new Ammo.btVector3(wheelHalfTrackBack, wheelAxisHeightBack, wheelAxisPositionBack), wheelRadiusBack, wheelWidthBack, BACK_RIGHT); - - let syncList = carController.syncList; - let actions = carController.actions; - function sync(dt) { - var speed = vehicle.getCurrentSpeedKmHour(); - - breakingForce = 0; - engineForce = 0; - // console.log(actions); - if (actions['acceleration']) { - if (speed < -1) breakingForce = maxBreakingForce; - else engineForce = maxEngineForce; - } - if (actions[`braking`]) { - if (speed > 1) breakingForce = maxBreakingForce; - else engineForce = -maxEngineForce / 2; - } - if (actions[`left`]) { - if (vehicleSteering < steeringClamp) vehicleSteering += steeringIncrement; - } else { - if (actions[`right`]) { - if (vehicleSteering > -steeringClamp) vehicleSteering -= steeringIncrement; - } else { - if (vehicleSteering < -steeringIncrement) vehicleSteering += steeringIncrement; - else { - if (vehicleSteering > steeringIncrement) vehicleSteering -= steeringIncrement; - else { - vehicleSteering = 0; - } - } - } - } - - vehicle.applyEngineForce(engineForce, BACK_LEFT); - vehicle.applyEngineForce(engineForce, BACK_RIGHT); - - vehicle.setBrake(breakingForce / 2, FRONT_LEFT); - vehicle.setBrake(breakingForce / 2, FRONT_RIGHT); - vehicle.setBrake(breakingForce, BACK_LEFT); - vehicle.setBrake(breakingForce, BACK_RIGHT); - - vehicle.setSteeringValue(vehicleSteering, FRONT_LEFT); - vehicle.setSteeringValue(vehicleSteering, FRONT_RIGHT); - - var tm, p, q, i; - var n = vehicle.getNumWheels(); - - // console.log("getNumWheels",n); - // console.log("engineForce",engineForce); - // console.log("breakingForce",breakingForce); - - for (i = 0; i < n; i++) { - vehicle.updateWheelTransform(i, true); - tm = vehicle.getWheelTransformWS(i); - p = tm.getOrigin(); - q = tm.getRotation(); - let obj = wheelMeshes[i]; - obj.transform.x = p.x(); - obj.transform.y = p.y(); - obj.transform.z = p.z(); - let qua = Quaternion.HELP_0; - - qua.set(q.x(), q.y(), q.z(), q.w()); - obj.transform.localRotQuat = qua; - } - - tm = vehicle.getChassisWorldTransform(); - p = tm.getOrigin(); - let q2 = tm.getRotation(); - bodyObj.x = p.x(); - bodyObj.y = p.y(); - bodyObj.z = p.z(); - let qua = Quaternion.HELP_0; - // q. - qua.set(q2.x(), q2.y(), q2.z(), q2.w()); - // qua. - bodyObj.transform.localRotQuat = qua; + const FRONT_LEFT = 0; + const FRONT_RIGHT = 1; + const BACK_LEFT = 2; + const BACK_RIGHT = 3; + vehicle.applyEngineForce(this.mEngineForce, BACK_LEFT); + vehicle.applyEngineForce(this.mEngineForce, BACK_RIGHT); + vehicle.setBrake(this.mBreakingForce / 2, FRONT_LEFT); + vehicle.setBrake(this.mBreakingForce / 2, FRONT_RIGHT); + vehicle.setBrake(this.mBreakingForce, BACK_LEFT); + vehicle.setBrake(this.mBreakingForce, BACK_RIGHT); + vehicle.setSteeringValue(this.mVehicleSteering, FRONT_LEFT); + vehicle.setSteeringValue(this.mVehicleSteering, FRONT_RIGHT); + + // update wheel rotation + const n = vehicle.getNumWheels(); + const angle = 40; + for (let i = 0; i < n; i++) { + let wheel = this.mWheels[i] + wheel.rotationX += speed; + if (i < 2) { + let offset = wheel.rotationZ; + this.mVehicleSteering === 0 + ? (wheel.rotationZ-= offset / 5) + : (wheel.rotationZ = offset - this.mVehicleSteering * 10); + if (wheel.rotationZ < -angle) + wheel.rotationZ = -angle; + else if (wheel.rotationZ > angle) + wheel.rotationZ = angle; } - - syncList.push(sync); - - let wheelMat = new LitMaterial(); - wheelMat.baseMap = Engine3D.res.whiteTexture; - wheelMat.normalMap = Engine3D.res.normalTexture; - wheelMat.aoMap = Engine3D.res.whiteTexture; - wheelMat.maskMap = Engine3D.res.whiteTexture; - wheelMat.emissiveMap = Engine3D.res.blackTexture; - wheelMat.roughness = 0.85; - wheelMat.metallic = 0.01; - wheelMat.envIntensity = 0.01; - }) + } + // update body position + let tm, p, q, qua = Quaternion.HELP_0; + tm = vehicle.getChassisWorldTransform(); + p = tm.getOrigin(); + this.mBody.x = p.x() + this.mBody.y = p.y() + this.mBody.z = p.z() + q = tm.getRotation(); + qua.set(q.x(), q.y(), q.z(), q.w()); + this.mBody.transform.localRotQuat = qua; } - - private loop() { - Physics.update(); + onKeyUp(e:KeyEvent) { + this.updateControlState(e.keyCode, false); } + onKeyDown(e:KeyEvent) { + this.updateControlState(e.keyCode, true); + } + updateControlState(keyCode:number, state:boolean) { + switch (keyCode) { + case KeyCode.Key_W: + this.mVehicleControlState[VehicleControlType.acceleration] = + state; + break; + case KeyCode.Key_Up: + this.mVehicleControlState[VehicleControlType.acceleration] = + state; + break; + case KeyCode.Key_S: + this.mVehicleControlState[VehicleControlType.braking] = state; + break; + case KeyCode.Key_Down: + this.mVehicleControlState[VehicleControlType.braking] = state; + break; + case KeyCode.Key_A: + this.mVehicleControlState[VehicleControlType.left] = state; + break; + case KeyCode.Key_Left: + this.mVehicleControlState[VehicleControlType.left] = state; + break; + case KeyCode.Key_D: + this.mVehicleControlState[VehicleControlType.right] = state; + break; + case KeyCode.Key_Right: + this.mVehicleControlState[VehicleControlType.right] = state; + break; + } + } +} - private createWheelObject(name: string, radius: number, width: number, skin: Object3D) { - - let wheelMat = new LitMaterial(); - wheelMat.baseMap = Engine3D.res.redTexture; - wheelMat.normalMap = Engine3D.res.normalTexture; - wheelMat.aoMap = Engine3D.res.whiteTexture; - wheelMat.maskMap = Engine3D.res.whiteTexture; - wheelMat.emissiveMap = Engine3D.res.blackTexture; - // wheelMat.blendMode = BlendMode.NORMAL; - wheelMat.roughness = 0.85; - wheelMat.metallic = 0.01; - wheelMat.envIntensity = 0.01; - wheelMat.doubleSide = true; - - let wheel = new Object3D(); - // let leftFrontWheel = new Object3D(); - let mr = wheel.addComponent(MeshRenderer); - - mr.geometry = new CylinderGeometry(radius * 2, radius * 2, width, 24, 1); - mr.materials = [wheelMat, wheelMat, wheelMat]; - let q = Quaternion.HELP_0; - q.fromEulerAngles(0, 0, 90); - wheel.transform.localRotQuat = q.clone(); - var p = new Object3D(); - p.addChild(wheel); - this.scene.addChild(p); - - var wheelSkin = skin.getChildByName(name) as Object3D; - wheelSkin.scaleX = 0.005; - wheelSkin.scaleY = 0.005; - wheelSkin.scaleZ = 0.005; - wheelSkin.x = 0; - wheelSkin.y = 0; - wheelSkin.z = 0; - wheelSkin.rotationX = 0; - wheelSkin.rotationY = 0; - wheelSkin.rotationZ = 0; - p.addChild(wheelSkin); - - return p; +/** + * Fix camera to a target + */ +class fixedCameraController extends ComponentBase { + private camera: Camera3D; + public distance = 50; // distance to target + public pitch = 30; // camera pitch angle + private _tempDir: Vector3; + private _tempPos: Vector3; + private _target: Object3D; + start() { + this._tempDir = new Vector3(); + this._tempPos = new Vector3(); + this.camera = this.object3D.getComponent(Camera3D); + } + get target() { + return this._target; + } + set target(obj) { + this._target = obj; + } + onUpdate() { + if (!this._target) return; + this._tempDir.set(0, 0, -1); + const q = Quaternion.HELP_0; + q.fromEulerAngles(this.pitch, 0, 0.0); + this._tempDir.applyQuaternion(q); + this._tempDir = this._target.transform.worldMatrix.transformVector( + this._tempDir, + this._tempDir + ); + this._tempDir.normalize(); + let position = this._target.transform.worldPosition; + this._tempPos = Vector3Ex.mulScale( + this._tempDir, + this.distance, + this._tempPos + ); + this._tempPos = position.add(this._tempPos, this._tempPos); + this.camera.lookAt(this._tempPos, this._target.transform.worldPosition); } } -new Sample_PhysicsCar().run(); \ No newline at end of file +new Sample_PhysicsCar().run(); From 5becdc48739e4ce7745d15a60c46612f991ae5f2 Mon Sep 17 00:00:00 2001 From: hellmor Date: Tue, 14 Nov 2023 17:46:04 +0800 Subject: [PATCH 14/14] fix: Auto sort transparent renderers. (#318) Auto sort transparent renderers after renderOrder changed. --- src/gfx/renderJob/collect/EntityCollect.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gfx/renderJob/collect/EntityCollect.ts b/src/gfx/renderJob/collect/EntityCollect.ts index e1afaa4d..24ff83bf 100644 --- a/src/gfx/renderJob/collect/EntityCollect.ts +++ b/src/gfx/renderJob/collect/EntityCollect.ts @@ -261,6 +261,7 @@ export class EntityCollect { public getRenderNodes(scene: Scene3D, camera: Camera3D): CollectInfo { + this.autoSortRenderNodes(scene); this._collectInfo.clean(); this._collectInfo.sky = this.sky;