@zephyr3d/scene 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/asset/assetmanager.js +1 -1
- package/dist/asset/loaders/gltf/gltf_loader.js +4 -8
- package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
- package/dist/camera/camera.js +25 -2
- package/dist/camera/camera.js.map +1 -1
- package/dist/index.d.ts +4641 -4371
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/material/grassmaterial.js +15 -0
- package/dist/material/grassmaterial.js.map +1 -1
- package/dist/material/material.js +79 -347
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +88 -100
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/albedocolor.js +11 -3
- package/dist/material/mixins/albedocolor.js.map +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js +8 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
- package/dist/material/mixins/pbr/common.js +2 -0
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/mixins/vertexcolor.js +2 -0
- package/dist/material/mixins/vertexcolor.js.map +1 -1
- package/dist/material/pbrmr.js +1 -1
- package/dist/material/pbrsg.js +9 -4
- package/dist/material/pbrsg.js.map +1 -1
- package/dist/material/shader/helper.js +94 -115
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/terrainmaterial.js +16 -0
- package/dist/material/terrainmaterial.js.map +1 -1
- package/dist/posteffect/bloom.js +3 -4
- package/dist/posteffect/bloom.js.map +1 -1
- package/dist/posteffect/compositor.js +5 -6
- package/dist/posteffect/compositor.js.map +1 -1
- package/dist/posteffect/fxaa.js +1 -2
- package/dist/posteffect/fxaa.js.map +1 -1
- package/dist/posteffect/grayscale.js +1 -2
- package/dist/posteffect/grayscale.js.map +1 -1
- package/dist/posteffect/posteffect.js +0 -74
- package/dist/posteffect/posteffect.js.map +1 -1
- package/dist/posteffect/sao.js +2 -5
- package/dist/posteffect/sao.js.map +1 -1
- package/dist/posteffect/tonemap.js +1 -2
- package/dist/posteffect/tonemap.js.map +1 -1
- package/dist/posteffect/water.js +18 -14
- package/dist/posteffect/water.js.map +1 -1
- package/dist/render/abuffer_oit.js +352 -0
- package/dist/render/abuffer_oit.js.map +1 -0
- package/dist/render/depthpass.js +10 -13
- package/dist/render/depthpass.js.map +1 -1
- package/dist/render/drawable_mixin.js +110 -0
- package/dist/render/drawable_mixin.js.map +1 -0
- package/dist/render/globalbindgroup_allocator.js +58 -0
- package/dist/render/globalbindgroup_allocator.js.map +1 -0
- package/dist/render/lightpass.js +69 -43
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/oit.js +16 -0
- package/dist/render/oit.js.map +1 -0
- package/dist/render/render_queue.js +250 -96
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderbundle_wrapper.js +20 -0
- package/dist/render/renderbundle_wrapper.js.map +1 -0
- package/dist/render/renderer.js +12 -9
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/renderpass.js +92 -34
- package/dist/render/renderpass.js.map +1 -1
- package/dist/render/shadowmap_pass.js +12 -31
- package/dist/render/shadowmap_pass.js.map +1 -1
- package/dist/render/sky.js +2 -2
- package/dist/render/watermesh.js +140 -48
- package/dist/render/watermesh.js.map +1 -1
- package/dist/render/weightedblended_oit.js +188 -0
- package/dist/render/weightedblended_oit.js.map +1 -0
- package/dist/scene/batchgroup.js +8 -35
- package/dist/scene/batchgroup.js.map +1 -1
- package/dist/scene/environment.js +2 -3
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/graph_node.js +1 -1
- package/dist/scene/mesh.js +11 -32
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/octree.js +3 -3
- package/dist/scene/scene.js +2 -29
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +6 -1
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/terrain/grass.js +17 -11
- package/dist/scene/terrain/grass.js.map +1 -1
- package/dist/scene/terrain/patch.js +18 -15
- package/dist/scene/terrain/patch.js.map +1 -1
- package/dist/scene/terrain/quadtree.js +1 -1
- package/dist/scene/terrain/terrain.js +0 -8
- package/dist/scene/terrain/terrain.js.map +1 -1
- package/dist/shaders/water.js +4 -4
- package/dist/shadow/esm.js +0 -1
- package/dist/shadow/esm.js.map +1 -1
- package/dist/shadow/shadowmapper.js +1 -2
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shadow/vsm.js +1 -2
- package/dist/shadow/vsm.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -9,7 +9,6 @@ export { CylinderShape } from './shapes/cylinder.js';
|
|
|
9
9
|
export { TorusShape } from './shapes/torus.js';
|
|
10
10
|
export { PlaneShape } from './shapes/plane.js';
|
|
11
11
|
export { SphereShape } from './shapes/sphere.js';
|
|
12
|
-
export { RenderScheme } from './render/renderscheme.js';
|
|
13
12
|
export { RenderPass } from './render/renderpass.js';
|
|
14
13
|
export { SceneRenderer } from './render/renderer.js';
|
|
15
14
|
export { LightPass } from './render/lightpass.js';
|
|
@@ -23,6 +22,9 @@ export { Primitive } from './render/primitive.js';
|
|
|
23
22
|
export { CullVisitor } from './render/cull_visitor.js';
|
|
24
23
|
export { TemporalCache } from './render/temporalcache.js';
|
|
25
24
|
export { WaterMesh, defaultBuildParams } from './render/watermesh.js';
|
|
25
|
+
export { OIT } from './render/oit.js';
|
|
26
|
+
export { WeightedBlendedOIT } from './render/weightedblended_oit.js';
|
|
27
|
+
export { ABufferOIT } from './render/abuffer_oit.js';
|
|
26
28
|
export { ShaderHelper } from './material/shader/helper.js';
|
|
27
29
|
export { LambertMaterial } from './material/lambert.js';
|
|
28
30
|
export { BlinnMaterial } from './material/blinn.js';
|
|
@@ -54,7 +56,7 @@ export { SceneNode } from './scene/scene_node.js';
|
|
|
54
56
|
export { BatchGroup } from './scene/batchgroup.js';
|
|
55
57
|
export { Terrain } from './scene/terrain/terrain.js';
|
|
56
58
|
export { HeightField, HeightfieldBBoxTree } from './scene/terrain/heightfield.js';
|
|
57
|
-
export { TerrainPatch } from './scene/terrain/patch.js';
|
|
59
|
+
export { TerrainPatch, TerrainPatchBase } from './scene/terrain/patch.js';
|
|
58
60
|
export { Quadtree, QuadtreeNode } from './scene/terrain/quadtree.js';
|
|
59
61
|
export { XForm } from './scene/xform.js';
|
|
60
62
|
export { AnimationClip } from './animation/animation.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -43,6 +43,12 @@ import { mixinFoliage } from './mixins/foliage.js';
|
|
|
43
43
|
*/ supportLighting() {
|
|
44
44
|
return true;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* {@inheritDoc Material.supportInstancing}
|
|
48
|
+
* @override
|
|
49
|
+
*/ supportInstancing() {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
46
52
|
applyUniformValues(bindGroup, ctx, pass) {
|
|
47
53
|
super.applyUniformValues(bindGroup, ctx, pass);
|
|
48
54
|
bindGroup.setTexture('terrainNormalMap', this._terrainNormalMap);
|
|
@@ -87,6 +93,15 @@ import { mixinFoliage } from './mixins/foliage.js';
|
|
|
87
93
|
this.outputFragmentColor(scope, scope.$inputs.worldPos, null);
|
|
88
94
|
}
|
|
89
95
|
}
|
|
96
|
+
apply(ctx) {
|
|
97
|
+
this.alphaToCoverage = ctx.device.getFrameBufferSampleCount() > 1;
|
|
98
|
+
this.alphaCutoff = this.alphaToCoverage ? 1 : 0.8;
|
|
99
|
+
return super.apply(ctx);
|
|
100
|
+
}
|
|
101
|
+
updateRenderStates(pass, stateSet, ctx) {
|
|
102
|
+
super.updateRenderStates(pass, stateSet, ctx);
|
|
103
|
+
stateSet.useRasterizerState().setCullMode('none');
|
|
104
|
+
}
|
|
90
105
|
}
|
|
91
106
|
|
|
92
107
|
export { GrassMaterial };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grassmaterial.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"grassmaterial.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { List } from '@zephyr3d/base';
|
|
2
1
|
import { ProgramBuilder } from '@zephyr3d/device';
|
|
3
|
-
import {
|
|
4
|
-
import { QUEUE_OPAQUE, RENDER_PASS_TYPE_LIGHT, RENDER_PASS_TYPE_SHADOWMAP, RENDER_PASS_TYPE_DEPTH } from '../values.js';
|
|
5
|
-
import { ShaderHelper } from './shader/helper.js';
|
|
2
|
+
import { QUEUE_OPAQUE } from '../values.js';
|
|
6
3
|
|
|
7
4
|
/**
|
|
8
5
|
* Base class for any kind of materials
|
|
@@ -10,41 +7,23 @@ import { ShaderHelper } from './shader/helper.js';
|
|
|
10
7
|
* @public
|
|
11
8
|
*/ class Material {
|
|
12
9
|
/** @internal */ static _nextId = 0;
|
|
13
|
-
/** @internal */
|
|
14
|
-
/** @internal */ static _drawableTimestamps = new WeakMap();
|
|
15
|
-
/** @internal */ static _drawableIterators = new WeakMap();
|
|
16
|
-
/** @internal */ static _drawableLRU = new List();
|
|
17
|
-
/** @internal */ static _materialTimestamps = new WeakMap();
|
|
18
|
-
/** @internal */ static _materialIterators = new WeakMap();
|
|
19
|
-
/** @internal */ static _materialLRU = new List();
|
|
20
|
-
/** @internal */ static _gcOptions = {
|
|
21
|
-
disabled: true,
|
|
22
|
-
drawableCountThreshold: 500,
|
|
23
|
-
materialCountThreshold: 200,
|
|
24
|
-
inactiveTimeDuration: 30000
|
|
25
|
-
};
|
|
26
|
-
/** @internal */ static _boneMatrixTextureSampler = null;
|
|
27
|
-
/** @internal */ //private static _instanceBindGroupPool: InstanceBindGroupPool = new InstanceBindGroupPool();
|
|
28
|
-
/** @internal */ static _drawableBindGroupMap = new WeakMap();
|
|
10
|
+
/** @internal */ _states;
|
|
29
11
|
/** @internal */ _numPasses;
|
|
30
12
|
/** @internal */ _hash;
|
|
31
|
-
/** @internal */ _renderStateSet;
|
|
32
|
-
/** @internal */ _bindGroupMap;
|
|
33
13
|
/** @internal */ _optionTag;
|
|
34
|
-
/** @internal */ _materialBindGroup;
|
|
35
14
|
/** @internal */ _id;
|
|
15
|
+
/** @internal */ _currentHash;
|
|
36
16
|
/**
|
|
37
17
|
* Creates an instance of material
|
|
38
18
|
*/ constructor(){
|
|
39
19
|
this._id = ++Material._nextId;
|
|
20
|
+
this._states = {};
|
|
40
21
|
this._numPasses = 1;
|
|
41
22
|
this._hash = [
|
|
42
|
-
|
|
23
|
+
null
|
|
43
24
|
];
|
|
44
|
-
this._renderStateSet = null;
|
|
45
|
-
this._bindGroupMap = {};
|
|
46
25
|
this._optionTag = 0;
|
|
47
|
-
this.
|
|
26
|
+
this._currentHash = [];
|
|
48
27
|
}
|
|
49
28
|
/** Unique identifier of the material */ get instanceId() {
|
|
50
29
|
return this._id;
|
|
@@ -54,94 +33,91 @@ import { ShaderHelper } from './shader/helper.js';
|
|
|
54
33
|
}
|
|
55
34
|
set numPasses(val) {
|
|
56
35
|
while(this._hash.length < val){
|
|
57
|
-
this._hash.push(
|
|
36
|
+
this._hash.push(null);
|
|
58
37
|
}
|
|
59
38
|
this._numPasses = val;
|
|
60
39
|
}
|
|
61
|
-
/** @internal */ getHash(
|
|
62
|
-
if (this._hash[pass]
|
|
63
|
-
this._hash[pass]
|
|
40
|
+
/** @internal */ getHash(pass) {
|
|
41
|
+
if (this._hash[pass] === null) {
|
|
42
|
+
this._hash[pass] = this.createHash(pass);
|
|
64
43
|
}
|
|
65
|
-
return this._hash[pass]
|
|
66
|
-
}
|
|
67
|
-
/** Render states associated to this material */ get stateSet() {
|
|
68
|
-
if (!this._renderStateSet) {
|
|
69
|
-
this._renderStateSet = this.createRenderStateSet();
|
|
70
|
-
}
|
|
71
|
-
return this._renderStateSet;
|
|
72
|
-
}
|
|
73
|
-
set stateSet(stateset) {
|
|
74
|
-
this._renderStateSet = stateset;
|
|
44
|
+
return this._hash[pass];
|
|
75
45
|
}
|
|
76
46
|
getQueueType() {
|
|
77
47
|
return QUEUE_OPAQUE;
|
|
78
48
|
}
|
|
79
|
-
/** Returns true if
|
|
49
|
+
/** Returns true if given pass is transparent */ isTransparentPass(pass) {
|
|
80
50
|
return false;
|
|
81
51
|
}
|
|
82
52
|
/** Returns true if shading of the material will be affected by lights */ supportLighting() {
|
|
83
53
|
return true;
|
|
84
54
|
}
|
|
55
|
+
/** Returns true if this material supports geometry instancing */ supportInstancing() {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
85
58
|
/** Returns true if this material supports geometry instancing */ isBatchable() {
|
|
86
59
|
return false;
|
|
87
60
|
}
|
|
88
|
-
/**
|
|
89
|
-
|
|
90
|
-
*
|
|
91
|
-
* @param primitive - The prmitive to be drawn
|
|
92
|
-
* @param ctx - The context of current drawing task
|
|
93
|
-
* @param numInstances - How many instances should be drawn. if zero, the instance count will be automatically detected.
|
|
94
|
-
*/ draw(primitive, ctx, numInstances = 0) {
|
|
95
|
-
for(let i = 0; i < this._numPasses; i++){
|
|
96
|
-
if (this.beginDraw(i, ctx)) {
|
|
97
|
-
this.drawPrimitive(i, primitive, ctx, numInstances);
|
|
98
|
-
this.endDraw(i);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
61
|
+
/** @internal */ get coreMaterial() {
|
|
62
|
+
return this;
|
|
101
63
|
}
|
|
102
64
|
/**
|
|
103
|
-
*
|
|
104
|
-
* @param ctx -
|
|
105
|
-
* @returns true if
|
|
106
|
-
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
65
|
+
* Apply material
|
|
66
|
+
* @param ctx - Draw context
|
|
67
|
+
* @returns true if no error, otherwise false
|
|
68
|
+
*/ apply(ctx) {
|
|
69
|
+
for(let pass = 0; pass < this._numPasses; pass++){
|
|
70
|
+
const hash = this.calcGlobalHash(ctx, pass);
|
|
71
|
+
let state = this._states[hash];
|
|
72
|
+
if (!state) {
|
|
73
|
+
const program = this.createProgram(ctx, pass) ?? null;
|
|
74
|
+
const bindGroup = program.bindGroupLayouts.length > 2 ? ctx.device.createBindGroup(program.bindGroupLayouts[2]) : null;
|
|
75
|
+
state = {
|
|
76
|
+
program,
|
|
77
|
+
bindGroup,
|
|
78
|
+
renderStateSet: ctx.device.createRenderStateSet(),
|
|
79
|
+
materialTag: -1
|
|
80
|
+
};
|
|
81
|
+
this._states[hash] = state;
|
|
116
82
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (ctx.instanceData) {
|
|
120
|
-
this.applyInstanceBindGroups(ctx, hash);
|
|
121
|
-
} else {
|
|
122
|
-
this.applyDrawableBindGroups(ctx, hash);
|
|
123
|
-
}
|
|
83
|
+
if (!state.program) {
|
|
84
|
+
return false;
|
|
124
85
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
Material._materialTimestamps.set(this, ctx.timestamp);
|
|
130
|
-
Material.lruPutMaterial(this);
|
|
131
|
-
return true;
|
|
86
|
+
this.applyUniforms(state.bindGroup, ctx, state.materialTag !== this._optionTag, pass);
|
|
87
|
+
state.materialTag = this._optionTag;
|
|
88
|
+
this.updateRenderStates(pass, state.renderStateSet, ctx);
|
|
89
|
+
this._currentHash[pass] = hash;
|
|
132
90
|
}
|
|
133
|
-
return false;
|
|
134
91
|
}
|
|
135
|
-
/**
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
92
|
+
/** @internal */ bind(device, pass) {
|
|
93
|
+
const hash = this._currentHash[pass];
|
|
94
|
+
const state = this._states[hash];
|
|
95
|
+
if (!state) {
|
|
96
|
+
console.error('Material.bind() failed: state not found');
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
if (!state.program) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
device.setProgram(state.program);
|
|
103
|
+
device.setBindGroup(2, state.bindGroup);
|
|
104
|
+
device.setRenderStates(state.renderStateSet);
|
|
105
|
+
}
|
|
106
|
+
/** @internal */ calcGlobalHash(ctx, pass) {
|
|
107
|
+
return `${this.getHash(pass)}:${Number(!!ctx.skinAnimation)}:${Number(!!ctx.instancing)}:${ctx.renderPassHash}`;
|
|
139
108
|
}
|
|
140
109
|
/**
|
|
141
|
-
*
|
|
142
|
-
* @
|
|
143
|
-
|
|
144
|
-
|
|
110
|
+
* Draws a primitive using this material
|
|
111
|
+
* @internal
|
|
112
|
+
*
|
|
113
|
+
* @param primitive - The prmitive to be drawn
|
|
114
|
+
* @param ctx - The context of current drawing task
|
|
115
|
+
* @param numInstances - How many instances should be drawn. if zero, the instance count will be automatically detected.
|
|
116
|
+
*/ draw(primitive, ctx, numInstances = 0) {
|
|
117
|
+
for(let pass = 0; pass < this._numPasses; pass++){
|
|
118
|
+
this.bind(ctx.device, pass);
|
|
119
|
+
this.drawPrimitive(pass, primitive, ctx, numInstances);
|
|
120
|
+
}
|
|
145
121
|
}
|
|
146
122
|
/**
|
|
147
123
|
* Sets all uniform values to the bind group of the material if needed
|
|
@@ -153,222 +129,14 @@ import { ShaderHelper } from './shader/helper.js';
|
|
|
153
129
|
this._applyUniforms(bindGroup, ctx, pass);
|
|
154
130
|
}
|
|
155
131
|
}
|
|
156
|
-
/**
|
|
157
|
-
* Fetch the gpu program of the material for drawing
|
|
158
|
-
* @param ctx - The context for current drawing task
|
|
159
|
-
* @returns Information of the gpu program
|
|
160
|
-
*/ getOrCreateProgram(ctx, pass) {
|
|
161
|
-
const programMap = Material._programMap;
|
|
162
|
-
const renderPassType = ctx.renderPass.type;
|
|
163
|
-
const hash = `${this.getHash(renderPassType, pass)}:${!!ctx.target.getBoneMatrices()}:${Number(!!ctx.instanceData)}:${ctx.renderPassHash}`;
|
|
164
|
-
let programInfo = programMap[hash];
|
|
165
|
-
if (!programInfo || programInfo.programs[renderPassType] === undefined) {
|
|
166
|
-
const program = this.createProgram(ctx, pass) ?? null;
|
|
167
|
-
if (!programInfo) {
|
|
168
|
-
programInfo = {
|
|
169
|
-
programs: [
|
|
170
|
-
null,
|
|
171
|
-
null,
|
|
172
|
-
null
|
|
173
|
-
],
|
|
174
|
-
hash
|
|
175
|
-
};
|
|
176
|
-
programMap[hash] = programInfo;
|
|
177
|
-
}
|
|
178
|
-
programInfo.programs[renderPassType] = program;
|
|
179
|
-
}
|
|
180
|
-
return programInfo;
|
|
181
|
-
}
|
|
182
|
-
dispose() {
|
|
183
|
-
this.clearBindGroupCache();
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Sets the options of garbage collection
|
|
187
|
-
* @param opt - The options to set
|
|
188
|
-
*/ static setGCOptions(opt) {
|
|
189
|
-
this._gcOptions = Object.assign({}, this._gcOptions, opt || {});
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Gets the options of garbage collection
|
|
193
|
-
* @returns The options of garbage collection
|
|
194
|
-
*/ static getGCOptions() {
|
|
195
|
-
return this._gcOptions;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Performs a garbage collection for this material
|
|
199
|
-
* @param ts - Current time stamp
|
|
200
|
-
* @returns How many bind groups have been garbage collected
|
|
201
|
-
*/ static garbageCollect(ts) {
|
|
202
|
-
let n = 0;
|
|
203
|
-
ts -= this._gcOptions.inactiveTimeDuration;
|
|
204
|
-
while(this._drawableLRU.length > this._gcOptions.drawableCountThreshold){
|
|
205
|
-
const iter = this._drawableLRU.begin();
|
|
206
|
-
if (this._drawableTimestamps.get(iter.data) < ts) {
|
|
207
|
-
const bindGroups = this._drawableBindGroupMap.get(iter.data);
|
|
208
|
-
if (bindGroups) {
|
|
209
|
-
for(const k in bindGroups){
|
|
210
|
-
for (const bindGroup of bindGroups[k].bindGroup){
|
|
211
|
-
if (bindGroup) {
|
|
212
|
-
this.bindGroupGarbageCollect(bindGroup);
|
|
213
|
-
n++;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
this._drawableBindGroupMap.delete(iter.data);
|
|
219
|
-
this._drawableIterators.delete(iter.data);
|
|
220
|
-
this._drawableLRU.remove(iter);
|
|
221
|
-
} else {
|
|
222
|
-
break;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
while(this._materialLRU.length > this._gcOptions.materialCountThreshold){
|
|
226
|
-
const iter = this._materialLRU.begin();
|
|
227
|
-
const mat = iter.data;
|
|
228
|
-
if (this._materialTimestamps.get(mat) < ts && mat._bindGroupMap) {
|
|
229
|
-
n += mat.clearBindGroupCache();
|
|
230
|
-
this._materialIterators.delete(mat);
|
|
231
|
-
this._materialLRU.remove(iter);
|
|
232
|
-
} else {
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (n > 0 && this._gcOptions.verbose) {
|
|
237
|
-
console.log(`INFO: ${n} bind groups have been garbage collected`);
|
|
238
|
-
}
|
|
239
|
-
return n;
|
|
240
|
-
}
|
|
241
132
|
/** @internal */ optionChanged(changeHash) {
|
|
242
133
|
this._optionTag++;
|
|
243
134
|
if (changeHash) {
|
|
244
135
|
for(let i = 0; i < this._numPasses; i++){
|
|
245
|
-
this._hash[i] =
|
|
136
|
+
this._hash[i] = null;
|
|
246
137
|
}
|
|
247
138
|
}
|
|
248
139
|
}
|
|
249
|
-
/** @internal */ static getProgramByHashIndex(hash, index) {
|
|
250
|
-
return this._programMap[hash].programs[index];
|
|
251
|
-
}
|
|
252
|
-
/** @internal */ applyMaterialBindGroups(ctx, hash, pass) {
|
|
253
|
-
const index = ctx.renderPass.type;
|
|
254
|
-
let bindGroupInfo = this._bindGroupMap[hash];
|
|
255
|
-
if (!bindGroupInfo) {
|
|
256
|
-
// bindGroups not created or have been garbage collected
|
|
257
|
-
const materialBindGroup = [
|
|
258
|
-
RENDER_PASS_TYPE_LIGHT,
|
|
259
|
-
RENDER_PASS_TYPE_SHADOWMAP,
|
|
260
|
-
RENDER_PASS_TYPE_DEPTH
|
|
261
|
-
].map((k)=>{
|
|
262
|
-
const program = Material._programMap[hash].programs[k];
|
|
263
|
-
return program?.bindGroupLayouts[2] ? Application.instance.device.createBindGroup(program.bindGroupLayouts[2]) : null;
|
|
264
|
-
});
|
|
265
|
-
bindGroupInfo = this._bindGroupMap[hash] = {
|
|
266
|
-
materialBindGroup,
|
|
267
|
-
bindGroupTag: [
|
|
268
|
-
0,
|
|
269
|
-
0,
|
|
270
|
-
0
|
|
271
|
-
],
|
|
272
|
-
materialTag: [
|
|
273
|
-
-1,
|
|
274
|
-
-1,
|
|
275
|
-
-1
|
|
276
|
-
]
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
const bindGroup = bindGroupInfo.materialBindGroup[index];
|
|
280
|
-
if (bindGroup) {
|
|
281
|
-
this.applyUniforms(bindGroup, ctx, bindGroupInfo.materialTag[index] < this._optionTag || bindGroupInfo.bindGroupTag[index] !== bindGroup.cid, pass);
|
|
282
|
-
bindGroupInfo.materialTag[index] = this._optionTag;
|
|
283
|
-
bindGroupInfo.bindGroupTag[index] = bindGroup.cid;
|
|
284
|
-
Application.instance.device.setBindGroup(2, bindGroup);
|
|
285
|
-
} else {
|
|
286
|
-
Application.instance.device.setBindGroup(2, null);
|
|
287
|
-
}
|
|
288
|
-
return bindGroup;
|
|
289
|
-
}
|
|
290
|
-
/** @internal */ getDrawableBindGroup(ctx, hash) {
|
|
291
|
-
let drawableBindGroups = Material._drawableBindGroupMap.get(ctx.target);
|
|
292
|
-
if (!drawableBindGroups) {
|
|
293
|
-
drawableBindGroups = {};
|
|
294
|
-
Material._drawableBindGroupMap.set(ctx.target, drawableBindGroups);
|
|
295
|
-
}
|
|
296
|
-
let drawableBindGroup = drawableBindGroups[hash];
|
|
297
|
-
if (!drawableBindGroup) {
|
|
298
|
-
const bindGroup = [
|
|
299
|
-
RENDER_PASS_TYPE_LIGHT,
|
|
300
|
-
RENDER_PASS_TYPE_SHADOWMAP,
|
|
301
|
-
RENDER_PASS_TYPE_DEPTH
|
|
302
|
-
].map((k)=>{
|
|
303
|
-
const program = Material._programMap[hash].programs[k];
|
|
304
|
-
return program?.bindGroupLayouts[1] ? Application.instance.device.createBindGroup(program.bindGroupLayouts[1]) : null;
|
|
305
|
-
});
|
|
306
|
-
drawableBindGroup = drawableBindGroups[hash] = {
|
|
307
|
-
bindGroup,
|
|
308
|
-
bindGroupTag: [
|
|
309
|
-
0,
|
|
310
|
-
0,
|
|
311
|
-
0
|
|
312
|
-
],
|
|
313
|
-
xformTag: [
|
|
314
|
-
-1,
|
|
315
|
-
-1,
|
|
316
|
-
-1
|
|
317
|
-
]
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
return drawableBindGroup;
|
|
321
|
-
}
|
|
322
|
-
/** @internal */ applyInstanceBindGroups(ctx, hash) {
|
|
323
|
-
if (ctx.instanceData) {
|
|
324
|
-
if (ctx.instanceData.bindGroup.dirty) {
|
|
325
|
-
ctx.instanceData.bindGroup.bindGroup.setRawData(ShaderHelper.getWorldMatricesUniformName(), 0, ctx.instanceData.bindGroup.buffer, 0, ctx.instanceData.currentSize * 4);
|
|
326
|
-
ctx.instanceData.bindGroup.dirty = false;
|
|
327
|
-
}
|
|
328
|
-
Application.instance.device.setBindGroup(3, ctx.instanceData.bindGroup.bindGroup ?? null);
|
|
329
|
-
} else {
|
|
330
|
-
Application.instance.device.setBindGroup(3, null);
|
|
331
|
-
}
|
|
332
|
-
const bindGroup = this.getDrawableBindGroup(ctx, hash).bindGroup?.[ctx.renderPass.type];
|
|
333
|
-
if (bindGroup) {
|
|
334
|
-
if (ctx.instanceData) {
|
|
335
|
-
bindGroup.setValue(ShaderHelper.getInstanceBufferStrideUniformName(), ctx.instanceData.stride);
|
|
336
|
-
}
|
|
337
|
-
Application.instance.device.setBindGroup(1, bindGroup);
|
|
338
|
-
} else {
|
|
339
|
-
Application.instance.device.setBindGroup(1, null);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
/** @internal */ applyDrawableBindGroups(ctx, hash) {
|
|
343
|
-
const device = Application.instance.device;
|
|
344
|
-
const index = ctx.renderPass.type;
|
|
345
|
-
const drawableBindGroup = this.getDrawableBindGroup(ctx, hash);
|
|
346
|
-
if (drawableBindGroup.bindGroup) {
|
|
347
|
-
const bindGroup = drawableBindGroup.bindGroup[index];
|
|
348
|
-
if (drawableBindGroup.xformTag[index] < ctx.target.getXForm().getTag() || drawableBindGroup.bindGroupTag[index] !== bindGroup.cid) {
|
|
349
|
-
bindGroup.setValue(ShaderHelper.getWorldMatrixUniformName(), ctx.target.getXForm().worldMatrix);
|
|
350
|
-
drawableBindGroup.xformTag[index] = ctx.target.getXForm().getTag();
|
|
351
|
-
drawableBindGroup.bindGroupTag[index] = bindGroup.cid;
|
|
352
|
-
}
|
|
353
|
-
const boneMatrices = ctx.target.getBoneMatrices();
|
|
354
|
-
if (boneMatrices) {
|
|
355
|
-
if (!Material._boneMatrixTextureSampler) {
|
|
356
|
-
Material._boneMatrixTextureSampler = device.createSampler({
|
|
357
|
-
magFilter: 'nearest',
|
|
358
|
-
minFilter: 'nearest',
|
|
359
|
-
mipFilter: 'none'
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
bindGroup.setTexture(ShaderHelper.getBoneMatricesUniformName(), boneMatrices);
|
|
363
|
-
bindGroup.setValue(ShaderHelper.getBoneTextureSizeUniformName(), boneMatrices.width);
|
|
364
|
-
bindGroup.setValue(ShaderHelper.getBoneInvBindMatrixUniformName(), ctx.target.getInvBindMatrix());
|
|
365
|
-
}
|
|
366
|
-
device.setBindGroup(1, bindGroup);
|
|
367
|
-
} else {
|
|
368
|
-
device.setBindGroup(1, null);
|
|
369
|
-
}
|
|
370
|
-
device.setBindGroup(3, null);
|
|
371
|
-
}
|
|
372
140
|
/**
|
|
373
141
|
* Convert pass to hash
|
|
374
142
|
* @param pass - pass number
|
|
@@ -376,47 +144,8 @@ import { ShaderHelper } from './shader/helper.js';
|
|
|
376
144
|
*/ passToHash(pass) {
|
|
377
145
|
return String(pass);
|
|
378
146
|
}
|
|
379
|
-
/** @internal */ createHash(
|
|
380
|
-
return `${this.constructor.name}|${
|
|
381
|
-
}
|
|
382
|
-
/** @internal */ clearBindGroupCache() {
|
|
383
|
-
let n = 0;
|
|
384
|
-
for(const k in this._bindGroupMap){
|
|
385
|
-
for (const bindGroup of this._bindGroupMap[k].materialBindGroup){
|
|
386
|
-
if (bindGroup) {
|
|
387
|
-
Material.bindGroupGarbageCollect(bindGroup);
|
|
388
|
-
n++;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
this._bindGroupMap = {};
|
|
393
|
-
return n;
|
|
394
|
-
}
|
|
395
|
-
/** @internal */ static bindGroupGarbageCollect(bindGroup) {
|
|
396
|
-
const layout = bindGroup.getLayout();
|
|
397
|
-
for (const entry of layout.entries){
|
|
398
|
-
if (entry.buffer) {
|
|
399
|
-
const buffer = bindGroup.getBuffer(entry.name);
|
|
400
|
-
if (buffer) {
|
|
401
|
-
buffer.dispose();
|
|
402
|
-
bindGroup.setBuffer(entry.name, null);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
/** @internal */ static lruPutDrawable(drawable) {
|
|
408
|
-
const iter = this._drawableIterators.get(drawable);
|
|
409
|
-
if (iter) {
|
|
410
|
-
this._drawableLRU.remove(iter);
|
|
411
|
-
}
|
|
412
|
-
this._drawableIterators.set(drawable, this._drawableLRU.append(drawable));
|
|
413
|
-
}
|
|
414
|
-
/** @internal */ static lruPutMaterial(material) {
|
|
415
|
-
const iter = this._materialIterators.get(material);
|
|
416
|
-
if (iter) {
|
|
417
|
-
this._materialLRU.remove(iter);
|
|
418
|
-
}
|
|
419
|
-
this._materialIterators.set(material, this._materialLRU.append(material));
|
|
147
|
+
/** @internal */ createHash(pass) {
|
|
148
|
+
return `${this.constructor.name}|${pass}|${this._createHash()}`;
|
|
420
149
|
}
|
|
421
150
|
/**
|
|
422
151
|
* Draw primitve
|
|
@@ -427,18 +156,15 @@ import { ShaderHelper } from './shader/helper.js';
|
|
|
427
156
|
if (numInstances > 0) {
|
|
428
157
|
primitive.drawInstanced(numInstances);
|
|
429
158
|
} else if (ctx.instanceData) {
|
|
430
|
-
primitive.drawInstanced(ctx.instanceData.
|
|
159
|
+
primitive.drawInstanced(ctx.instanceData.numInstances);
|
|
431
160
|
} else {
|
|
432
161
|
primitive.draw();
|
|
433
162
|
}
|
|
434
163
|
}
|
|
435
164
|
/** @internal */ createProgram(ctx, pass) {
|
|
436
|
-
const pb = new ProgramBuilder(
|
|
165
|
+
const pb = new ProgramBuilder(ctx.device);
|
|
437
166
|
return this._createProgram(pb, ctx, pass);
|
|
438
167
|
}
|
|
439
|
-
/** @internal */ createRenderStateSet() {
|
|
440
|
-
return Application.instance.device.createRenderStateSet();
|
|
441
|
-
}
|
|
442
168
|
/**
|
|
443
169
|
* Creates the shader program
|
|
444
170
|
* @param pb - The program builder
|
|
@@ -454,9 +180,15 @@ import { ShaderHelper } from './shader/helper.js';
|
|
|
454
180
|
* @param ctx - The drawing context
|
|
455
181
|
*/ _applyUniforms(bindGroup, ctx, pass) {}
|
|
456
182
|
/**
|
|
183
|
+
* Update render states according to draw context and current material pass
|
|
184
|
+
* @param pass - Current material pass
|
|
185
|
+
* @param renderStates - Render state set to be updated
|
|
186
|
+
* @param ctx - Draw context
|
|
187
|
+
*/ updateRenderStates(pass, renderStates, ctx) {}
|
|
188
|
+
/**
|
|
457
189
|
* Calculates the hash code of the shader program
|
|
458
190
|
* @returns The hash code
|
|
459
|
-
*/ _createHash(
|
|
191
|
+
*/ _createHash() {
|
|
460
192
|
return '';
|
|
461
193
|
}
|
|
462
194
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"material.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"material.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|