diff --git a/public b/public index 878ff06d..313900a1 160000 --- a/public +++ b/public @@ -1 +1 @@ -Subproject commit 878ff06dc4d6bb821d48e9a7a7e61f04462c50e2 +Subproject commit 313900a1f85dc0e78dbb0ddfd16ecda58ede66b3 diff --git a/samples/base/Sample_AddRemove.ts b/samples/base/Sample_AddRemove.ts index 581fa32e..23246857 100644 --- a/samples/base/Sample_AddRemove.ts +++ b/samples/base/Sample_AddRemove.ts @@ -51,6 +51,7 @@ class Sample_AddRemove { if (obj) { list.splice(index, 1) this.view.scene.removeChild(obj) + obj.destroy(true); } }); diff --git a/samples/base/Sample_Destroy.ts b/samples/base/Sample_Destroy.ts index f1b2f334..0036c47b 100644 --- a/samples/base/Sample_Destroy.ts +++ b/samples/base/Sample_Destroy.ts @@ -38,39 +38,36 @@ class Sample_Destroy { // add light object scene3D.addChild(light) { - // create new object - const obj: Object3D = new Object3D() - // add MeshRenderer - let mr: MeshRenderer = obj.addComponent(MeshRenderer) - // set geometry - mr.geometry = new BoxGeometry(1, 1, 1) - // set material - mr.material = new LitMaterial() - // set rotation - obj.rotationY = 45 - obj.x = -2 - // add object - scene3D.addChild(obj) - } - { - // create new object - const obj: Object3D = new Object3D() - // add MeshRenderer - let mr: MeshRenderer = obj.addComponent(MeshRenderer) - // set geometry - mr.geometry = new BoxGeometry(1, 1, 1) - // set material - mr.material = new LitMaterial() - // set rotation - obj.rotationY = 45 - obj.x = 2 - // add object - scene3D.addChild(obj) + let list: Object3D[] = []; + GUIHelp.addButton("add", () => { + for (let i = 0; i < 20; i++) { + // create new object + const obj: Object3D = new Object3D() + // add MeshRenderer + let mr: MeshRenderer = obj.addComponent(MeshRenderer) + // set geometry + mr.geometry = new BoxGeometry(1, 1, 1) + // set material + mr.material = new LitMaterial() + // set rotation + obj.rotationY = 45 + obj.x = 2 + // add object + scene3D.addChild(obj) + obj.x = Math.random() * 50 - 25; + obj.y = Math.random() * 50 - 25; + obj.z = Math.random() * 50 - 25; + list.push(obj); + } + }); + + GUIHelp.addButton("del", () => { + for (let i = 0; i < list.length; i++) { + const obj = list[i]; + obj.destroy(true); + } + }); - // debug gui - GUIHelp.addButton('destroy', () => { - obj.destroy(true) - }) } // create a view with target scene and camera let view = new View3D() diff --git a/src/assets/Res.ts b/src/assets/Res.ts index 351c42ff..e77d0e3b 100644 --- a/src/assets/Res.ts +++ b/src/assets/Res.ts @@ -23,6 +23,7 @@ import { GUIAtlasTexture } from '../components/gui/core/GUIAtlasTexture'; import { FontParser, FontInfo } from '../loader/parser/FontParser'; import { fonts } from './Fonts'; import { AtlasParser } from '../loader/parser/AtlasParser'; +import { Reference } from '../util/Reference'; /** * Resource management classes for textures, materials, models, and preset bodies. @@ -435,13 +436,25 @@ export class Res { this.grayTexture = this.createTexture(32, 32, 128, 128, 128, 255.0, 'default-grayTexture'); let brdf = new BRDFLUTGenerate(); - let texture = brdf.generateBRDFLUTTexture(); - let BRDFLUT = texture.name = 'BRDFLUT'; - this.addTexture(BRDFLUT, texture); + let brdf_texture = brdf.generateBRDFLUTTexture(); + let BRDFLUT = brdf_texture.name = 'BRDFLUT'; + this.addTexture(BRDFLUT, brdf_texture); this.defaultSky = new HDRTextureCube(); this.defaultSky.createFromTexture(128, this.blackTexture); + Reference.getInstance().attached(this.defaultSky, this); + Reference.getInstance().attached(brdf_texture, this); + + Reference.getInstance().attached(this.normalTexture, this); + Reference.getInstance().attached(this.maskTexture, this); + Reference.getInstance().attached(this.whiteTexture, this); + Reference.getInstance().attached(this.blackTexture, this); + Reference.getInstance().attached(this.redTexture, this); + Reference.getInstance().attached(this.blueTexture, this); + Reference.getInstance().attached(this.greenTexture, this); + Reference.getInstance().attached(this.yellowTexture, this); + Reference.getInstance().attached(this.grayTexture, this); this.defaultGUITexture = new GUITexture(this.whiteTexture); this.defaultGUISprite = new GUISprite(this.defaultGUITexture); this.defaultGUISprite.trimSize.set(4, 4) diff --git a/src/components/renderer/MeshRenderer.ts b/src/components/renderer/MeshRenderer.ts index 2c02218e..8241c7cb 100644 --- a/src/components/renderer/MeshRenderer.ts +++ b/src/components/renderer/MeshRenderer.ts @@ -8,6 +8,7 @@ import { RendererType } from '../../gfx/renderJob/passRenderer/state/RendererTyp import { MaterialBase } from '../../materials/MaterialBase'; import { MorphTargetData } from '../anim/morphAnim/MorphTargetData'; import { RenderNode } from './RenderNode'; +import { Reference } from '../..'; /** * The mesh renderer component is a component used to render the mesh @@ -40,7 +41,8 @@ export class MeshRenderer extends RenderNode { } public set geometry(value: GeometryBase) { - this._geometry = value; + //this must use super geometry has reference in super + super.geometry = value; let isMorphTarget = value.morphTargetDictionary != null; if (isMorphTarget) { this.morphData ||= new MorphTargetData(); @@ -56,7 +58,6 @@ export class MeshRenderer extends RenderNode { } this.object3D.bound = this._geometry.bounds.clone(); - if (this._readyPipeline) { this.initPipeline(); } @@ -121,18 +122,11 @@ export class MeshRenderer extends RenderNode { } } } - super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer); } public destroy(force?: boolean): void { - if (force) { - this.geometry.destroy(force); - this.materials.forEach(mat => { - mat.destroy(force); - }); - } - super.destroy(); + super.destroy(force); } cloneTo(obj: Object3D) { diff --git a/src/components/renderer/RenderNode.ts b/src/components/renderer/RenderNode.ts index 8bd97628..dd882380 100644 --- a/src/components/renderer/RenderNode.ts +++ b/src/components/renderer/RenderNode.ts @@ -1,4 +1,4 @@ -import { ShadowLightsCollect } from "../.."; +import { Reference, ShadowLightsCollect } from "../.."; import { Engine3D } from "../../Engine3D"; import { View3D } from "../../core/View3D"; import { GeometryBase } from "../../core/geometry/GeometryBase"; @@ -67,6 +67,12 @@ export class RenderNode extends ComponentBase { } public set geometry(value: GeometryBase) { + if (this._geometry != value) { + if (this._geometry) { + Reference.getInstance().detached(this._geometry, this) + } + Reference.getInstance().attached(value, this) + } this._geometry = value; } @@ -95,6 +101,15 @@ export class RenderNode extends ComponentBase { } public set materials(value: MaterialBase[]) { + for (let i = 0; i < this._materials.length; i++) { + let mat = this._materials[i]; + Reference.getInstance().detached(mat, this) + } + for (let i = 0; i < value.length; i++) { + let mat = value[i]; + Reference.getInstance().attached(mat, this) + } + this._materials = value; let transparent = false; let sort = 0; @@ -413,15 +428,15 @@ export class RenderNode extends ComponentBase { renderShader.setTexture(`brdflutMap`, bdrflutTex); let shadowRenderer = Engine3D.getRenderJob(view).shadowMapPassRenderer; - if (shadowRenderer && shadowRenderer.depth2DTextureArray) { - renderShader.setTexture(`shadowMap`, Engine3D.getRenderJob(view).shadowMapPassRenderer.depth2DTextureArray); + 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) { let pointShadowRenderer = Engine3D.getRenderJob(view).pointLightShadowRenderer; - if (pointShadowRenderer && pointShadowRenderer.cubeTextureArray) { - renderShader.setTexture(`pointShadowMap`, pointShadowRenderer.cubeTextureArray); + if (pointShadowRenderer && pointShadowRenderer.cubeArrayTexture) { + renderShader.setTexture(`pointShadowMap`, pointShadowRenderer.cubeArrayTexture); } // } @@ -459,6 +474,19 @@ export class RenderNode extends ComponentBase { public destroy(force?: boolean) { super.destroy(force); + Reference.getInstance().detached(this._geometry, this); + if (!Reference.getInstance().hasReference(this._geometry)) { + this._geometry.destroy(force); + } + + for (let i = 0; i < this._materials.length; i++) { + const mat = this._materials[i]; + Reference.getInstance().detached(mat, this); + if (!Reference.getInstance().hasReference(mat)) { + mat.destroy(force); + } + } + this._geometry = null; this._materials = null; this._combineShaderRefection = null; diff --git a/src/gfx/graphics/webGpu/shader/ComputeShader.ts b/src/gfx/graphics/webGpu/shader/ComputeShader.ts index 87a6e912..9f5f5b43 100644 --- a/src/gfx/graphics/webGpu/shader/ComputeShader.ts +++ b/src/gfx/graphics/webGpu/shader/ComputeShader.ts @@ -174,7 +174,7 @@ export class ComputeShader extends ShaderBase { resource: texture.getGPUView(), } entries.push(entry); - Reference.getInstance().attache(texture, this); + Reference.getInstance().attached(texture, this); } else { console.error(`ComputeShader(${this.instanceID})`, `texture ${refs.varName} is missing! `); } @@ -186,7 +186,7 @@ export class ComputeShader extends ShaderBase { resource: texture.getGPUView(), } entries.push(entry); - Reference.getInstance().attache(texture, this); + Reference.getInstance().attached(texture, this); } else { console.error(`ComputeShader(${this.instanceID})`, `texture ${refs.varName} is missing! `); } diff --git a/src/gfx/graphics/webGpu/shader/RenderShader.ts b/src/gfx/graphics/webGpu/shader/RenderShader.ts index 3eea1e88..e6929ac0 100644 --- a/src/gfx/graphics/webGpu/shader/RenderShader.ts +++ b/src/gfx/graphics/webGpu/shader/RenderShader.ts @@ -627,7 +627,7 @@ export class RenderShader extends ShaderBase { // if(info.binding == 8){ // console.log(info.binding, entry ); // } - Reference.getInstance().attache(texture, this); + Reference.getInstance().attached(texture, this); } break; case `texture_external`: @@ -641,7 +641,7 @@ export class RenderShader extends ShaderBase { entries.push(entry); this._textureGroup = index; // console.log(info.binding, entry ); - Reference.getInstance().attache(texture, this); + Reference.getInstance().attached(texture, this); } break; default: @@ -655,7 +655,7 @@ export class RenderShader extends ShaderBase { entries.push(entry); this._textureGroup = index; // console.log(info.binding, entry ); - Reference.getInstance().attache(texture, this); + Reference.getInstance().attached(texture, this); } break; } diff --git a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts index f6bc8296..753f8911 100644 --- a/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/PointLightShadowRenderer.ts @@ -21,6 +21,7 @@ import { WebGPUDescriptorCreator } from '../../../graphics/webGpu/descriptor/Web import { RendererPassState } from '../state/RendererPassState'; import { RendererType } from '../state/RendererType'; import { ILight } from '../../../../components/lights/ILight'; +import { Reference } from '../../../..'; type CubeShadowMapInfo = { cubeCamera: CubeCamera, @@ -37,7 +38,7 @@ export class PointLightShadowRenderer extends RendererBase { private _forceUpdate = false; private _shadowCameraDic: Map; public shadowCamera: Camera3D; - public cubeTextureArray: DepthCubeArrayTexture; + public cubeArrayTexture: DepthCubeArrayTexture; public colorTexture: VirtualTexture; public shadowSize: number = 1024; constructor() { @@ -46,11 +47,11 @@ export class PointLightShadowRenderer extends RendererBase { // this.shadowSize = Engine3D.setting.shadow.pointShadowSize; this._shadowCameraDic = new Map(); - this.cubeTextureArray = new DepthCubeArrayTexture(this.shadowSize, this.shadowSize, 8); + this.cubeArrayTexture = new DepthCubeArrayTexture(this.shadowSize, this.shadowSize, 8); this.colorTexture = new VirtualTexture(this.shadowSize, this.shadowSize, GPUTextureFormat.bgra8unorm, false); - } - + Reference.getInstance().attached(this.cubeArrayTexture, this); + } public getShadowCamera(view: View3D, lightBase: ILight): CubeShadowMapInfo { let cubeShadowMapInfo: CubeShadowMapInfo; @@ -63,7 +64,7 @@ export class PointLightShadowRenderer extends RendererBase { let rendererPassStates: RendererPassState[] = []; for (let i = 0; i < 6; i++) { - let depthTexture = new VirtualTexture(this.shadowSize, this.shadowSize, this.cubeTextureArray.format, false); + let depthTexture = new VirtualTexture(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; @@ -152,7 +153,7 @@ export class PointLightShadowRenderer extends RendererBase { origin: { x: 0, y: 0, z: 0 }, }, { - texture: this.cubeTextureArray.getGPUTexture(), + texture: this.cubeArrayTexture.getGPUTexture(), mipLevel: 0, origin: { x: 0, y: 0, z: light.shadowIndex * 6 + i }, }, diff --git a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts index 837f79b2..e0353372 100644 --- a/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts +++ b/src/gfx/renderJob/passRenderer/shadow/ShadowMapPassRenderer.ts @@ -20,6 +20,7 @@ import { RendererPassState } from "../state/RendererPassState"; import { RendererType } from "../state/RendererType"; import { RendererBase } from "../RendererBase"; import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; +import { Reference } from "../../../../util/Reference"; /** * @internal @@ -28,7 +29,7 @@ import { ClusterLightingBuffer } from "../cluster/ClusterLightingBuffer"; export class ShadowMapPassRenderer extends RendererBase { // public shadowCamera: Camera3D; public shadowPassCount: number; - public depth2DTextureArray: Depth2DTextureArray; + public depth2DArrayTexture: Depth2DTextureArray; public rendererPassStates: RendererPassState[]; private _forceUpdate = false; constructor() { @@ -45,7 +46,8 @@ export class ShadowMapPassRenderer extends RendererBase { setShadowMap(size: number) { this.rendererPassStates = []; - this.depth2DTextureArray = new Depth2DTextureArray(size, size); + this.depth2DArrayTexture = new Depth2DTextureArray(size, size); + Reference.getInstance().attached(this.depth2DArrayTexture, this); for (let i = 0; i < 8; i++) { let rtFrame = new RTFrame([], []); @@ -115,7 +117,7 @@ export class ShadowMapPassRenderer extends RendererBase { origin: { x: 0, y: 0, z: 0 }, }, { - texture: this.depth2DTextureArray.getGPUTexture(), + texture: this.depth2DArrayTexture.getGPUTexture(), mipLevel: 0, origin: { x: 0, y: 0, z: light.shadowIndex }, }, diff --git a/src/gfx/renderJob/post/PostBase.ts b/src/gfx/renderJob/post/PostBase.ts index bc879ba3..10e151f3 100644 --- a/src/gfx/renderJob/post/PostBase.ts +++ b/src/gfx/renderJob/post/PostBase.ts @@ -30,7 +30,7 @@ export class PostBase { let rt = RTResourceMap.createRTTexture(name, rtWidth, rtHeight, format, useMipmap, sampleCount); rt.name = name; this.virtualTexture.set(name, rt); - Reference.getInstance().attache(rt, this); + Reference.getInstance().attached(rt, this); return rt; } diff --git a/src/util/Reference.ts b/src/util/Reference.ts index b5cb3255..504caaec 100644 --- a/src/util/Reference.ts +++ b/src/util/Reference.ts @@ -13,11 +13,11 @@ export class Reference { } /** - * current instance attache from parent instance + * current instance attached from parent instance * @param ref reference current * @param target reference parent */ - public attache(ref: any, target: any) { + public attached(ref: any, target: any) { this.reference ||= new Map>(); let refMap = this.reference.get(ref);