@zephyr3d/scene 0.2.0 → 0.3.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 +85 -93
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/camera/camera.js +1 -0
- package/dist/camera/camera.js.map +1 -1
- package/dist/index.d.ts +2511 -2329
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/material/blinn.js +5 -5
- package/dist/material/grassmaterial.js +14 -14
- package/dist/material/material.js +32 -54
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +215 -80
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/albedocolor.js +11 -7
- package/dist/material/mixins/albedocolor.js.map +1 -1
- package/dist/material/mixins/foliage.js +7 -7
- package/dist/material/mixins/lightmodel/blinnphong.js +5 -5
- package/dist/material/mixins/lightmodel/lambert.js +5 -5
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +5 -5
- package/dist/material/mixins/lit.js +72 -72
- package/dist/material/mixins/pbr/common.js +4 -4
- package/dist/material/mixins/texture.js +6 -6
- package/dist/material/mixins/vertexcolor.js +5 -5
- package/dist/material/pbrmr.js +5 -5
- package/dist/material/shader/helper.js +20 -18
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/terrainmaterial.js +12 -12
- package/dist/posteffect/bloom.js +1 -0
- package/dist/posteffect/bloom.js.map +1 -1
- package/dist/posteffect/compositor.js +1 -0
- package/dist/posteffect/compositor.js.map +1 -1
- package/dist/posteffect/water.js +1 -0
- package/dist/posteffect/water.js.map +1 -1
- package/dist/render/cull_visitor.js +24 -3
- package/dist/render/cull_visitor.js.map +1 -1
- package/dist/render/primitive.js +31 -0
- package/dist/render/primitive.js.map +1 -1
- package/dist/render/render_queue.js +111 -38
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +9 -0
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/sky.js +2 -4
- package/dist/render/sky.js.map +1 -1
- package/dist/scene/batchgroup.js +126 -0
- package/dist/scene/batchgroup.js.map +1 -0
- package/dist/scene/environment.js +1 -0
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/graph_node.js +8 -0
- package/dist/scene/graph_node.js.map +1 -1
- package/dist/scene/mesh.js +35 -2
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/octree.js +37 -72
- package/dist/scene/octree.js.map +1 -1
- package/dist/scene/octree_update_visitor.js +5 -1
- package/dist/scene/octree_update_visitor.js.map +1 -1
- package/dist/scene/scene.js +7 -17
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +57 -44
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/xform.js +61 -36
- package/dist/scene/xform.js.map +1 -1
- package/dist/shadow/esm.js +1 -0
- package/dist/shadow/esm.js.map +1 -1
- package/dist/shadow/shadowmapper.js +22 -6
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shadow/vsm.js +1 -0
- package/dist/shadow/vsm.js.map +1 -1
- package/dist/shapes/box.js +15 -6
- package/dist/shapes/box.js.map +1 -1
- package/dist/shapes/cylinder.js +1 -4
- package/dist/shapes/cylinder.js.map +1 -1
- package/dist/shapes/shape.js +5 -0
- package/dist/shapes/shape.js.map +1 -1
- package/dist/shapes/sphere.js +3 -0
- package/dist/shapes/sphere.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ export { SceneRenderer } from './render/renderer.js';
|
|
|
15
15
|
export { LightPass } from './render/lightpass.js';
|
|
16
16
|
export { ShadowMapPass } from './render/shadowmap_pass.js';
|
|
17
17
|
export { DepthPass } from './render/depthpass.js';
|
|
18
|
-
export { RenderQueue } from './render/render_queue.js';
|
|
18
|
+
export { InstanceBindGroupAllocator, RenderQueue } from './render/render_queue.js';
|
|
19
19
|
export { SkyRenderer } from './render/sky.js';
|
|
20
20
|
export { Clipmap } from './render/clipmap.js';
|
|
21
21
|
export { EnvConstantAmbient, EnvHemisphericAmbient, EnvIBL, EnvironmentLighting } from './render/envlight.js';
|
|
@@ -51,6 +51,7 @@ export { Mesh } from './scene/mesh.js';
|
|
|
51
51
|
export { Model } from './scene/model.js';
|
|
52
52
|
export { Octree, OctreeNode, OctreeNodeChunk, OctreePlacement } from './scene/octree.js';
|
|
53
53
|
export { SceneNode } from './scene/scene_node.js';
|
|
54
|
+
export { BatchGroup } from './scene/batchgroup.js';
|
|
54
55
|
export { Terrain } from './scene/terrain/terrain.js';
|
|
55
56
|
export { HeightField, HeightfieldBBoxTree } from './scene/terrain/heightfield.js';
|
|
56
57
|
export { TerrainPatch } from './scene/terrain/patch.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/material/blinn.js
CHANGED
|
@@ -3,14 +3,14 @@ import { mixinVertexColor } from './mixins/vertexcolor.js';
|
|
|
3
3
|
import { mixinBlinnPhong } from './mixins/lightmodel/blinnphong.js';
|
|
4
4
|
import { ShaderHelper } from './shader/helper.js';
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* Blinn material
|
|
8
|
-
* @public
|
|
6
|
+
/**
|
|
7
|
+
* Blinn material
|
|
8
|
+
* @public
|
|
9
9
|
*/ class BlinnMaterial extends applyMaterialMixins(MeshMaterial, mixinBlinnPhong, mixinVertexColor) {
|
|
10
10
|
/** @internal */ static FEATURE_VERTEX_NORMAL = this.defineFeature();
|
|
11
11
|
/** @internal */ static FEATURE_VERTEX_TANGENT = this.defineFeature();
|
|
12
|
-
/**
|
|
13
|
-
* Creates an instance of BlinnMaterial class
|
|
12
|
+
/**
|
|
13
|
+
* Creates an instance of BlinnMaterial class
|
|
14
14
|
*/ constructor(){
|
|
15
15
|
super();
|
|
16
16
|
this.useFeature(BlinnMaterial.FEATURE_VERTEX_NORMAL, true);
|
|
@@ -5,18 +5,18 @@ import { RENDER_PASS_TYPE_LIGHT } from '../values.js';
|
|
|
5
5
|
import { ShaderHelper } from './shader/helper.js';
|
|
6
6
|
import { mixinFoliage } from './mixins/foliage.js';
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* Terrain grass material
|
|
10
|
-
* @public
|
|
8
|
+
/**
|
|
9
|
+
* Terrain grass material
|
|
10
|
+
* @public
|
|
11
11
|
*/ class GrassMaterial extends applyMaterialMixins(MeshMaterial, mixinPBRMetallicRoughness, mixinFoliage) {
|
|
12
12
|
/** @internal */ _terrainSize;
|
|
13
13
|
/** @internal */ _terrainNormalMap;
|
|
14
14
|
/** @internal */ _textureSize;
|
|
15
|
-
/**
|
|
16
|
-
* Creates an instance of GrassMaterial class
|
|
17
|
-
* @param terrainSize - terrain size
|
|
18
|
-
* @param normalMap - normal map
|
|
19
|
-
* @param grassTexture - grass texture
|
|
15
|
+
/**
|
|
16
|
+
* Creates an instance of GrassMaterial class
|
|
17
|
+
* @param terrainSize - terrain size
|
|
18
|
+
* @param normalMap - normal map
|
|
19
|
+
* @param grassTexture - grass texture
|
|
20
20
|
*/ constructor(terrainSize, normalMap, grassTexture){
|
|
21
21
|
super();
|
|
22
22
|
this.metallic = 0;
|
|
@@ -31,15 +31,15 @@ import { mixinFoliage } from './mixins/foliage.js';
|
|
|
31
31
|
this._textureSize.setXY(grassTexture.width, grassTexture.height);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
/**
|
|
35
|
-
* {@inheritDoc MeshMaterial.isTransparentPass}
|
|
36
|
-
* @override
|
|
34
|
+
/**
|
|
35
|
+
* {@inheritDoc MeshMaterial.isTransparentPass}
|
|
36
|
+
* @override
|
|
37
37
|
*/ isTransparentPass(pass) {
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
|
-
/**
|
|
41
|
-
* {@inheritDoc Material.supportLighting}
|
|
42
|
-
* @override
|
|
40
|
+
/**
|
|
41
|
+
* {@inheritDoc Material.supportLighting}
|
|
42
|
+
* @override
|
|
43
43
|
*/ supportLighting() {
|
|
44
44
|
return true;
|
|
45
45
|
}
|
|
@@ -4,48 +4,6 @@ import { Application } from '../app.js';
|
|
|
4
4
|
import { QUEUE_OPAQUE, RENDER_PASS_TYPE_LIGHT, RENDER_PASS_TYPE_SHADOWMAP, RENDER_PASS_TYPE_DEPTH } from '../values.js';
|
|
5
5
|
import { ShaderHelper } from './shader/helper.js';
|
|
6
6
|
|
|
7
|
-
class InstanceBindGroupPool {
|
|
8
|
-
_bindGroups;
|
|
9
|
-
_frameStamp;
|
|
10
|
-
constructor(){
|
|
11
|
-
this._bindGroups = [];
|
|
12
|
-
this._frameStamp = -1;
|
|
13
|
-
}
|
|
14
|
-
apply(hash, index, worldMatrices) {
|
|
15
|
-
const device = Application.instance.device;
|
|
16
|
-
const maxSize = device.getDeviceCaps().shaderCaps.maxUniformBufferSize;
|
|
17
|
-
if (device.frameInfo.frameCounter !== this._frameStamp) {
|
|
18
|
-
this._frameStamp = device.frameInfo.frameCounter;
|
|
19
|
-
for (const bindGroup of this._bindGroups){
|
|
20
|
-
bindGroup.freeSize = maxSize;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
let bindGroupIndex = -1;
|
|
24
|
-
for(let i = 0; i < this._bindGroups.length; i++){
|
|
25
|
-
if (this._bindGroups[i].freeSize >= worldMatrices.length * 64) {
|
|
26
|
-
bindGroupIndex = i;
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (bindGroupIndex < 0) {
|
|
31
|
-
const program = Material.getProgramByHashIndex(hash, index);
|
|
32
|
-
const bindGroup = program?.bindGroupLayouts[3] ? device.createBindGroup(program.bindGroupLayouts[3]) : null;
|
|
33
|
-
this._bindGroups.push({
|
|
34
|
-
bindGroup: bindGroup,
|
|
35
|
-
freeSize: maxSize
|
|
36
|
-
});
|
|
37
|
-
bindGroupIndex = this._bindGroups.length - 1;
|
|
38
|
-
}
|
|
39
|
-
const bindGroup = this._bindGroups[bindGroupIndex];
|
|
40
|
-
const offset = (maxSize - bindGroup.freeSize) / 64;
|
|
41
|
-
for (const matrix of worldMatrices){
|
|
42
|
-
bindGroup.bindGroup.setRawData(ShaderHelper.getWorldMatricesUniformName(), maxSize - bindGroup.freeSize, matrix);
|
|
43
|
-
bindGroup.freeSize -= 64;
|
|
44
|
-
}
|
|
45
|
-
device.setBindGroup(3, bindGroup.bindGroup);
|
|
46
|
-
return offset;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
7
|
/**
|
|
50
8
|
* Base class for any kind of materials
|
|
51
9
|
*
|
|
@@ -66,7 +24,7 @@ class InstanceBindGroupPool {
|
|
|
66
24
|
inactiveTimeDuration: 30000
|
|
67
25
|
};
|
|
68
26
|
/** @internal */ static _boneMatrixTextureSampler = null;
|
|
69
|
-
/** @internal */ static _instanceBindGroupPool = new InstanceBindGroupPool();
|
|
27
|
+
/** @internal */ //private static _instanceBindGroupPool: InstanceBindGroupPool = new InstanceBindGroupPool();
|
|
70
28
|
/** @internal */ static _drawableBindGroupMap = new WeakMap();
|
|
71
29
|
/** @internal */ _numPasses;
|
|
72
30
|
/** @internal */ _hash;
|
|
@@ -88,7 +46,7 @@ class InstanceBindGroupPool {
|
|
|
88
46
|
this._optionTag = 0;
|
|
89
47
|
this._materialBindGroup = null;
|
|
90
48
|
}
|
|
91
|
-
/** Unique identifier of the material */ get
|
|
49
|
+
/** Unique identifier of the material */ get instanceId() {
|
|
92
50
|
return this._id;
|
|
93
51
|
}
|
|
94
52
|
get numPasses() {
|
|
@@ -125,7 +83,7 @@ class InstanceBindGroupPool {
|
|
|
125
83
|
return true;
|
|
126
84
|
}
|
|
127
85
|
/** Returns true if this material supports geometry instancing */ isBatchable() {
|
|
128
|
-
return
|
|
86
|
+
return false;
|
|
129
87
|
}
|
|
130
88
|
/**
|
|
131
89
|
* Draws a primitive using this material
|
|
@@ -146,7 +104,6 @@ class InstanceBindGroupPool {
|
|
|
146
104
|
* @param ctx - The context of current drawing task
|
|
147
105
|
* @returns true if succeeded, otherwise false
|
|
148
106
|
*/ beginDraw(pass, ctx) {
|
|
149
|
-
const numInstances = ctx.instanceData?.worldMatrices?.length || 1;
|
|
150
107
|
const device = Application.instance.device;
|
|
151
108
|
const programInfo = this.getOrCreateProgram(ctx, pass);
|
|
152
109
|
if (programInfo) {
|
|
@@ -159,7 +116,7 @@ class InstanceBindGroupPool {
|
|
|
159
116
|
}
|
|
160
117
|
this._materialBindGroup = this.applyMaterialBindGroups(ctx, hash, pass);
|
|
161
118
|
if (pass === 0) {
|
|
162
|
-
if (
|
|
119
|
+
if (ctx.instanceData) {
|
|
163
120
|
this.applyInstanceBindGroups(ctx, hash);
|
|
164
121
|
} else {
|
|
165
122
|
this.applyDrawableBindGroups(ctx, hash);
|
|
@@ -203,7 +160,7 @@ class InstanceBindGroupPool {
|
|
|
203
160
|
*/ getOrCreateProgram(ctx, pass) {
|
|
204
161
|
const programMap = Material._programMap;
|
|
205
162
|
const renderPassType = ctx.renderPass.type;
|
|
206
|
-
const hash = `${this.getHash(renderPassType, pass)}:${!!ctx.target.getBoneMatrices()}:${Number(!!
|
|
163
|
+
const hash = `${this.getHash(renderPassType, pass)}:${!!ctx.target.getBoneMatrices()}:${Number(!!ctx.instanceData)}:${ctx.renderPassHash}`;
|
|
207
164
|
let programInfo = programMap[hash];
|
|
208
165
|
if (!programInfo || programInfo.programs[renderPassType] === undefined) {
|
|
209
166
|
const program = this.createProgram(ctx, pass) ?? null;
|
|
@@ -363,11 +320,20 @@ class InstanceBindGroupPool {
|
|
|
363
320
|
return drawableBindGroup;
|
|
364
321
|
}
|
|
365
322
|
/** @internal */ applyInstanceBindGroups(ctx, hash) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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];
|
|
369
333
|
if (bindGroup) {
|
|
370
|
-
|
|
334
|
+
if (ctx.instanceData) {
|
|
335
|
+
bindGroup.setValue(ShaderHelper.getInstanceBufferStrideUniformName(), ctx.instanceData.stride);
|
|
336
|
+
}
|
|
371
337
|
Application.instance.device.setBindGroup(1, bindGroup);
|
|
372
338
|
} else {
|
|
373
339
|
Application.instance.device.setBindGroup(1, null);
|
|
@@ -460,8 +426,8 @@ class InstanceBindGroupPool {
|
|
|
460
426
|
*/ drawPrimitive(pass, primitive, ctx, numInstances) {
|
|
461
427
|
if (numInstances > 0) {
|
|
462
428
|
primitive.drawInstanced(numInstances);
|
|
463
|
-
} else if (ctx.instanceData
|
|
464
|
-
primitive.drawInstanced(ctx.instanceData.
|
|
429
|
+
} else if (ctx.instanceData) {
|
|
430
|
+
primitive.drawInstanced(ctx.instanceData.currentSize / ctx.instanceData.stride);
|
|
465
431
|
} else {
|
|
466
432
|
primitive.draw();
|
|
467
433
|
}
|
|
@@ -493,6 +459,18 @@ class InstanceBindGroupPool {
|
|
|
493
459
|
*/ _createHash(renderPassType) {
|
|
494
460
|
return '';
|
|
495
461
|
}
|
|
462
|
+
/**
|
|
463
|
+
* True if this is a material instance
|
|
464
|
+
* @internal
|
|
465
|
+
**/ get $isInstance() {
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Returns the instance uniforms if this is a material instance
|
|
470
|
+
* @internal
|
|
471
|
+
**/ get $instanceUniforms() {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
496
474
|
}
|
|
497
475
|
|
|
498
476
|
export { Material };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"material.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"material.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -4,14 +4,15 @@ import { Material } from './material.js';
|
|
|
4
4
|
import { encodeNormalizedFloatToRGBA } from '../shaders/misc.js';
|
|
5
5
|
import { Application } from '../app.js';
|
|
6
6
|
import { ShaderHelper } from './shader/helper.js';
|
|
7
|
+
import { Vector4, Vector3, Vector2 } from '@zephyr3d/base';
|
|
7
8
|
|
|
8
|
-
/**
|
|
9
|
-
* Apply material mixins to specific material class
|
|
10
|
-
* @param target - Material class
|
|
11
|
-
* @param mixins - mixins
|
|
12
|
-
* @returns Mixed mesh material class
|
|
13
|
-
*
|
|
14
|
-
* @public
|
|
9
|
+
/**
|
|
10
|
+
* Apply material mixins to specific material class
|
|
11
|
+
* @param target - Material class
|
|
12
|
+
* @param mixins - mixins
|
|
13
|
+
* @returns Mixed mesh material class
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
15
16
|
*/ function applyMaterialMixins(target, ...mixins) {
|
|
16
17
|
let r = target;
|
|
17
18
|
for (const m of mixins){
|
|
@@ -22,11 +23,12 @@ import { ShaderHelper } from './shader/helper.js';
|
|
|
22
23
|
let FEATURE_ALPHATEST = 0;
|
|
23
24
|
let FEATURE_ALPHABLEND = 0;
|
|
24
25
|
let FEATURE_ALPHATOCOVERAGE = 0;
|
|
25
|
-
/**
|
|
26
|
-
* Base class for any kind of mesh materials
|
|
27
|
-
*
|
|
28
|
-
* @public
|
|
26
|
+
/**
|
|
27
|
+
* Base class for any kind of mesh materials
|
|
28
|
+
*
|
|
29
|
+
* @public
|
|
29
30
|
*/ class MeshMaterial extends Material {
|
|
31
|
+
/** @internal */ static INSTANCE_UNIFORMS = [];
|
|
30
32
|
/** @internal */ static NEXT_FEATURE_INDEX = 3;
|
|
31
33
|
/** @internal */ _featureStates;
|
|
32
34
|
/** @internal */ _alphaCutoff;
|
|
@@ -35,9 +37,9 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
35
37
|
/** @internal */ _opacity;
|
|
36
38
|
/** @internal */ _ctx;
|
|
37
39
|
/** @internal */ _materialPass;
|
|
38
|
-
/**
|
|
39
|
-
* Creates an instance of MeshMaterial class
|
|
40
|
-
* @param args - constructor arguments
|
|
40
|
+
/**
|
|
41
|
+
* Creates an instance of MeshMaterial class
|
|
42
|
+
* @param args - constructor arguments
|
|
41
43
|
*/ constructor(...args){
|
|
42
44
|
super();
|
|
43
45
|
this._featureStates = [];
|
|
@@ -56,6 +58,136 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
56
58
|
this.NEXT_FEATURE_INDEX++;
|
|
57
59
|
return val;
|
|
58
60
|
}
|
|
61
|
+
/** Define instance uniform index */ static defineInstanceUniform(prop, type) {
|
|
62
|
+
if (this.INSTANCE_UNIFORMS.findIndex((val)=>val[0] === prop) >= 0) {
|
|
63
|
+
throw new Error(`${this.name}.defineInstanceUniform(): ${prop} was already defined`);
|
|
64
|
+
}
|
|
65
|
+
if (type !== 'float' && type !== 'vec2' && type !== 'vec3' && type !== 'vec4') {
|
|
66
|
+
throw new Error(`${this.name}.defineInstanceUniform(): invalid uniform type ${type}`);
|
|
67
|
+
}
|
|
68
|
+
this.INSTANCE_UNIFORMS = [
|
|
69
|
+
...this.INSTANCE_UNIFORMS,
|
|
70
|
+
[
|
|
71
|
+
prop,
|
|
72
|
+
type
|
|
73
|
+
]
|
|
74
|
+
];
|
|
75
|
+
return this.INSTANCE_UNIFORMS.length - 1;
|
|
76
|
+
}
|
|
77
|
+
getInstancedUniform(scope, uniformIndex) {
|
|
78
|
+
//return ShaderHelper.getInstancedUniform(scope, 4 + uniformIndex);
|
|
79
|
+
const pb = scope.$builder;
|
|
80
|
+
const instanceID = pb.shaderKind === 'vertex' ? scope.$builtins.instanceIndex : scope.$inputs.zInstanceID;
|
|
81
|
+
const uniformName = ShaderHelper.getWorldMatricesUniformName();
|
|
82
|
+
const strideName = ShaderHelper.getInstanceBufferStrideUniformName();
|
|
83
|
+
return scope[uniformName].at(pb.add(pb.mul(scope[strideName], instanceID), 4 + uniformIndex));
|
|
84
|
+
}
|
|
85
|
+
/** Create material instance */ createInstance() {
|
|
86
|
+
const instanceUniforms = this.constructor.INSTANCE_UNIFORMS;
|
|
87
|
+
const uniformsHolder = instanceUniforms.length > 0 ? new Float32Array(4 * instanceUniforms.length) : null;
|
|
88
|
+
const batchable = Application.instance.device.type !== 'webgl';
|
|
89
|
+
// Copy original uniform values
|
|
90
|
+
for(let i = 0; i < instanceUniforms.length; i++){
|
|
91
|
+
const [prop, type] = instanceUniforms[i];
|
|
92
|
+
const value = this[prop];
|
|
93
|
+
switch(type){
|
|
94
|
+
case 'float':
|
|
95
|
+
{
|
|
96
|
+
uniformsHolder[i * 4] = Number(value);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'vec2':
|
|
100
|
+
{
|
|
101
|
+
if (!(value instanceof Vector2)) {
|
|
102
|
+
throw new Error(`Instance uniform property ${prop} must be of type Vector2`);
|
|
103
|
+
}
|
|
104
|
+
uniformsHolder[i * 4] = value.x;
|
|
105
|
+
uniformsHolder[i * 4 + 1] = value.y;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case 'vec3':
|
|
109
|
+
{
|
|
110
|
+
if (!(value instanceof Vector3)) {
|
|
111
|
+
throw new Error(`Instance uniform property ${prop} must be of type Vector3`);
|
|
112
|
+
}
|
|
113
|
+
uniformsHolder[i * 4] = value.x;
|
|
114
|
+
uniformsHolder[i * 4 + 1] = value.y;
|
|
115
|
+
uniformsHolder[i * 4 + 2] = value.z;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'vec4':
|
|
119
|
+
{
|
|
120
|
+
if (!(value instanceof Vector4)) {
|
|
121
|
+
throw new Error(`Instance uniform property ${prop} must be of type Vector4`);
|
|
122
|
+
}
|
|
123
|
+
uniformsHolder[i * 4] = value.x;
|
|
124
|
+
uniformsHolder[i * 4 + 1] = value.y;
|
|
125
|
+
uniformsHolder[i * 4 + 2] = value.z;
|
|
126
|
+
uniformsHolder[i * 4 + 3] = value.w;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const handler = {
|
|
132
|
+
get (target, prop, receiver) {
|
|
133
|
+
if (prop === 'isBatchable') {
|
|
134
|
+
return ()=>batchable;
|
|
135
|
+
} else if (prop === '$instanceUniforms') {
|
|
136
|
+
return uniformsHolder;
|
|
137
|
+
} else if (prop === '$isInstance') {
|
|
138
|
+
return true;
|
|
139
|
+
} else if (prop === 'beginDraw') {
|
|
140
|
+
if (!batchable || !target.isBatchable()) {
|
|
141
|
+
for(let i = 0; i < instanceUniforms.length; i++){
|
|
142
|
+
const name = instanceUniforms[i][0];
|
|
143
|
+
const type = instanceUniforms[i][1];
|
|
144
|
+
switch(type){
|
|
145
|
+
case 'float':
|
|
146
|
+
target[name] = uniformsHolder[i * 4];
|
|
147
|
+
break;
|
|
148
|
+
case 'vec2':
|
|
149
|
+
target[name] = new Vector2(uniformsHolder[i * 4], uniformsHolder[i * 4 + 1]);
|
|
150
|
+
break;
|
|
151
|
+
case 'vec3':
|
|
152
|
+
target[name] = new Vector3(uniformsHolder[i * 4], uniformsHolder[i * 4 + 1], uniformsHolder[i * 4 + 2]);
|
|
153
|
+
case 'vec4':
|
|
154
|
+
target[name] = new Vector4(uniformsHolder[i * 4], uniformsHolder[i * 4 + 1], uniformsHolder[i * 4 + 2], uniformsHolder[i * 4 + 3]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
} else if (typeof prop === 'string') {
|
|
159
|
+
const index = instanceUniforms.findIndex((val)=>val[0] === prop);
|
|
160
|
+
if (index >= 0) {
|
|
161
|
+
switch(instanceUniforms[index][1]){
|
|
162
|
+
case 'float':
|
|
163
|
+
return uniformsHolder[index * 4];
|
|
164
|
+
case 'vec2':
|
|
165
|
+
return new Vector2(uniformsHolder[index * 4], uniformsHolder[index * 4 + 1]);
|
|
166
|
+
case 'vec3':
|
|
167
|
+
return new Vector3(uniformsHolder[index * 4], uniformsHolder[index * 4 + 1], uniformsHolder[index * 4 + 2]);
|
|
168
|
+
case 'vec4':
|
|
169
|
+
return new Vector4(uniformsHolder[index * 4], uniformsHolder[index * 4 + 1], uniformsHolder[index * 4 + 2], uniformsHolder[index * 4 + 3]);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return Reflect.get(target, prop, receiver);
|
|
174
|
+
},
|
|
175
|
+
set (target, prop, value, receiver) {
|
|
176
|
+
const i = instanceUniforms.findIndex((val)=>val[0] === prop);
|
|
177
|
+
if (i >= 0) {
|
|
178
|
+
if (typeof value === 'number') {
|
|
179
|
+
uniformsHolder[i * 4 + 0] = value;
|
|
180
|
+
} else if (value instanceof Float32Array) {
|
|
181
|
+
uniformsHolder.set(value);
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
} else {
|
|
185
|
+
return Reflect.set(target, prop, value, receiver);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
return new Proxy(this, handler);
|
|
190
|
+
}
|
|
59
191
|
/** Draw context for shader creation */ get drawContext() {
|
|
60
192
|
return this._ctx;
|
|
61
193
|
}
|
|
@@ -107,10 +239,10 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
107
239
|
/** Returns true if shading of the material will be affected by lights */ supportLighting() {
|
|
108
240
|
return true;
|
|
109
241
|
}
|
|
110
|
-
/**
|
|
111
|
-
* Update render states according to draw context and current material pass
|
|
112
|
-
* @param pass - Current material pass
|
|
113
|
-
* @param ctx - Draw context
|
|
242
|
+
/**
|
|
243
|
+
* Update render states according to draw context and current material pass
|
|
244
|
+
* @param pass - Current material pass
|
|
245
|
+
* @param ctx - Draw context
|
|
114
246
|
*/ updateRenderStates(pass, ctx) {
|
|
115
247
|
const blending = this.featureUsed(FEATURE_ALPHABLEND) || ctx.lightBlending;
|
|
116
248
|
const a2c = this.featureUsed(FEATURE_ALPHATOCOVERAGE);
|
|
@@ -144,12 +276,12 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
144
276
|
this.stateSet.defaultRasterizerState();
|
|
145
277
|
}
|
|
146
278
|
}
|
|
147
|
-
/**
|
|
148
|
-
* Submit Uniform values before rendering with this material.
|
|
149
|
-
*
|
|
150
|
-
* @param bindGroup - Bind group for this material
|
|
151
|
-
* @param ctx - Draw context
|
|
152
|
-
* @param pass - Current pass of the material
|
|
279
|
+
/**
|
|
280
|
+
* Submit Uniform values before rendering with this material.
|
|
281
|
+
*
|
|
282
|
+
* @param bindGroup - Bind group for this material
|
|
283
|
+
* @param ctx - Draw context
|
|
284
|
+
* @param pass - Current pass of the material
|
|
153
285
|
*/ applyUniformValues(bindGroup, ctx, pass) {
|
|
154
286
|
if (this.featureUsed(FEATURE_ALPHATEST)) {
|
|
155
287
|
bindGroup.setValue('zAlphaCutoff', this._alphaCutoff);
|
|
@@ -158,21 +290,21 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
158
290
|
bindGroup.setValue('zOpacity', this._opacity);
|
|
159
291
|
}
|
|
160
292
|
}
|
|
161
|
-
/**
|
|
162
|
-
* Determine which queue should be used to render this material.
|
|
163
|
-
* @returns QUEUE_TRANSPARENT or QUEUE_OPAQUE
|
|
293
|
+
/**
|
|
294
|
+
* Determine which queue should be used to render this material.
|
|
295
|
+
* @returns QUEUE_TRANSPARENT or QUEUE_OPAQUE
|
|
164
296
|
*/ getQueueType() {
|
|
165
297
|
return this.isTransparentPass(0) ? QUEUE_TRANSPARENT : QUEUE_OPAQUE;
|
|
166
298
|
}
|
|
167
|
-
/**
|
|
168
|
-
* Determine if a certain pass of this material is translucent.
|
|
169
|
-
* @param pass - Pass of the material
|
|
170
|
-
* @returns True if it is translucent, otherwise false.
|
|
299
|
+
/**
|
|
300
|
+
* Determine if a certain pass of this material is translucent.
|
|
301
|
+
* @param pass - Pass of the material
|
|
302
|
+
* @returns True if it is translucent, otherwise false.
|
|
171
303
|
*/ isTransparentPass(pass) {
|
|
172
304
|
return this.featureUsed(FEATURE_ALPHABLEND);
|
|
173
305
|
}
|
|
174
|
-
/**
|
|
175
|
-
* {@inheritdoc Material.beginDraw}
|
|
306
|
+
/**
|
|
307
|
+
* {@inheritdoc Material.beginDraw}
|
|
176
308
|
*/ beginDraw(pass, ctx) {
|
|
177
309
|
this.updateRenderStates(pass, ctx);
|
|
178
310
|
return super.beginDraw(pass, ctx);
|
|
@@ -185,51 +317,51 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
185
317
|
}
|
|
186
318
|
return this._createProgram(pb, ctx, pass);
|
|
187
319
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Check if a feature is in use for given render pass type.
|
|
190
|
-
*
|
|
191
|
-
* @param feature - The feature index
|
|
192
|
-
* @returns true if the feature is in use, otherwise false.
|
|
320
|
+
/**
|
|
321
|
+
* Check if a feature is in use for given render pass type.
|
|
322
|
+
*
|
|
323
|
+
* @param feature - The feature index
|
|
324
|
+
* @returns true if the feature is in use, otherwise false.
|
|
193
325
|
*/ featureUsed(feature) {
|
|
194
326
|
return this._featureStates[feature];
|
|
195
327
|
}
|
|
196
|
-
/**
|
|
197
|
-
* Use or unuse a feature of the material, this will cause the shader to be rebuild.
|
|
198
|
-
*
|
|
199
|
-
* @param feature - Which feature will be used or unused
|
|
200
|
-
* @param use - true if use the feature, otherwise false
|
|
328
|
+
/**
|
|
329
|
+
* Use or unuse a feature of the material, this will cause the shader to be rebuild.
|
|
330
|
+
*
|
|
331
|
+
* @param feature - Which feature will be used or unused
|
|
332
|
+
* @param use - true if use the feature, otherwise false
|
|
201
333
|
*/ useFeature(feature, use) {
|
|
202
334
|
if (this._featureStates[feature] !== use) {
|
|
203
335
|
this._featureStates[feature] = use;
|
|
204
336
|
this.optionChanged(true);
|
|
205
337
|
}
|
|
206
338
|
}
|
|
207
|
-
/**
|
|
208
|
-
* {@inheritDoc Material._createHash}
|
|
209
|
-
* @override
|
|
210
|
-
*
|
|
211
|
-
* @internal
|
|
339
|
+
/**
|
|
340
|
+
* {@inheritDoc Material._createHash}
|
|
341
|
+
* @override
|
|
342
|
+
*
|
|
343
|
+
* @internal
|
|
212
344
|
*/ _createHash(renderPassType) {
|
|
213
345
|
return this._featureStates.map((val)=>val === undefined ? '' : val).join('|');
|
|
214
346
|
}
|
|
215
|
-
/**
|
|
216
|
-
* {@inheritDoc Material._applyUniforms}
|
|
217
|
-
* @override
|
|
218
|
-
*
|
|
219
|
-
* @internal
|
|
347
|
+
/**
|
|
348
|
+
* {@inheritDoc Material._applyUniforms}
|
|
349
|
+
* @override
|
|
350
|
+
*
|
|
351
|
+
* @internal
|
|
220
352
|
*/ _applyUniforms(bindGroup, ctx, pass) {
|
|
221
353
|
this.applyUniformValues(bindGroup, ctx, pass);
|
|
222
354
|
}
|
|
223
|
-
/**
|
|
224
|
-
* Check if the color should be computed in fragment shader, this is required for forward render pass or alpha test is in use or alpha to coverage is in use.
|
|
225
|
-
*
|
|
226
|
-
* @returns - true if the color should be computed in fragment shader, otherwise false.
|
|
355
|
+
/**
|
|
356
|
+
* Check if the color should be computed in fragment shader, this is required for forward render pass or alpha test is in use or alpha to coverage is in use.
|
|
357
|
+
*
|
|
358
|
+
* @returns - true if the color should be computed in fragment shader, otherwise false.
|
|
227
359
|
*/ needFragmentColor(ctx) {
|
|
228
360
|
return (ctx ?? this.drawContext).renderPass.type === RENDER_PASS_TYPE_LIGHT || this._alphaCutoff > 0 || this.alphaToCoverage;
|
|
229
361
|
}
|
|
230
|
-
/**
|
|
231
|
-
* Vertex shader implementation of this material
|
|
232
|
-
* @param scope - Shader scope
|
|
362
|
+
/**
|
|
363
|
+
* Vertex shader implementation of this material
|
|
364
|
+
* @param scope - Shader scope
|
|
233
365
|
*/ vertexShader(scope) {
|
|
234
366
|
const pb = scope.$builder;
|
|
235
367
|
ShaderHelper.prepareVertexShader(pb, this.drawContext);
|
|
@@ -237,10 +369,13 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
237
369
|
scope.$inputs.zBlendIndices = pb.vec4().attrib('blendIndices');
|
|
238
370
|
scope.$inputs.zBlendWeights = pb.vec4().attrib('blendWeights');
|
|
239
371
|
}
|
|
372
|
+
if (this.drawContext.instanceData) {
|
|
373
|
+
scope.$outputs.zInstanceID = scope.$builtins.instanceIndex;
|
|
374
|
+
}
|
|
240
375
|
}
|
|
241
|
-
/**
|
|
242
|
-
* Fragment shader implementation of this material
|
|
243
|
-
* @param scope - Shader scope
|
|
376
|
+
/**
|
|
377
|
+
* Fragment shader implementation of this material
|
|
378
|
+
* @param scope - Shader scope
|
|
244
379
|
*/ fragmentShader(scope) {
|
|
245
380
|
const pb = scope.$builder;
|
|
246
381
|
ShaderHelper.prepareFragmentShader(pb, this.drawContext);
|
|
@@ -253,11 +388,11 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
253
388
|
}
|
|
254
389
|
}
|
|
255
390
|
}
|
|
256
|
-
/**
|
|
257
|
-
* {@inheritDoc Material._createProgram}
|
|
258
|
-
* @override
|
|
259
|
-
*
|
|
260
|
-
* @internal
|
|
391
|
+
/**
|
|
392
|
+
* {@inheritDoc Material._createProgram}
|
|
393
|
+
* @override
|
|
394
|
+
*
|
|
395
|
+
* @internal
|
|
261
396
|
*/ _createProgram(pb, ctx, pass) {
|
|
262
397
|
const that = this;
|
|
263
398
|
this._ctx = ctx;
|
|
@@ -275,20 +410,20 @@ let FEATURE_ALPHATOCOVERAGE = 0;
|
|
|
275
410
|
});
|
|
276
411
|
}
|
|
277
412
|
});
|
|
278
|
-
/*
|
|
279
|
-
if (program) {
|
|
280
|
-
console.log(program.getShaderSource('vertex'));
|
|
281
|
-
console.log(program.getShaderSource('fragment'));
|
|
282
|
-
}
|
|
413
|
+
/*
|
|
414
|
+
if (program) {
|
|
415
|
+
console.log(program.getShaderSource('vertex'));
|
|
416
|
+
console.log(program.getShaderSource('fragment'));
|
|
417
|
+
}
|
|
283
418
|
*/ return program;
|
|
284
419
|
}
|
|
285
|
-
/**
|
|
286
|
-
* Calculate final fragment color for output.
|
|
287
|
-
*
|
|
288
|
-
* @param scope - Shader scope
|
|
289
|
-
* @param color - Lit fragment color
|
|
290
|
-
*
|
|
291
|
-
* @returns The final fragment color
|
|
420
|
+
/**
|
|
421
|
+
* Calculate final fragment color for output.
|
|
422
|
+
*
|
|
423
|
+
* @param scope - Shader scope
|
|
424
|
+
* @param color - Lit fragment color
|
|
425
|
+
*
|
|
426
|
+
* @returns The final fragment color
|
|
292
427
|
*/ outputFragmentColor(scope, worldPos, color) {
|
|
293
428
|
const pb = scope.$builder;
|
|
294
429
|
const that = this;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meshmaterial.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"meshmaterial.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|