@zephyr3d/scene 0.1.1 → 0.2.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.
Files changed (146) hide show
  1. package/dist/asset/assetmanager.js +124 -67
  2. package/dist/asset/assetmanager.js.map +1 -1
  3. package/dist/asset/builtin.js +2 -2
  4. package/dist/asset/loaders/gltf/gltf_loader.js +105 -59
  5. package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
  6. package/dist/asset/loaders/hdr/hdr.js +1 -1
  7. package/dist/blitter/blitter.js +0 -1
  8. package/dist/blitter/blitter.js.map +1 -1
  9. package/dist/blitter/depthlimitedgaussion.js +0 -1
  10. package/dist/blitter/depthlimitedgaussion.js.map +1 -1
  11. package/dist/blitter/gaussianblur.js +0 -1
  12. package/dist/blitter/gaussianblur.js.map +1 -1
  13. package/dist/camera/camera.js +10 -8
  14. package/dist/camera/camera.js.map +1 -1
  15. package/dist/camera/orbit.js +24 -7
  16. package/dist/camera/orbit.js.map +1 -1
  17. package/dist/index.d.ts +1842 -2484
  18. package/dist/index.js +21 -10
  19. package/dist/index.js.map +1 -1
  20. package/dist/material/blinn.js +47 -57
  21. package/dist/material/blinn.js.map +1 -1
  22. package/dist/material/grassmat.js +127 -0
  23. package/dist/material/grassmat.js.map +1 -0
  24. package/dist/material/grassmaterial.js +66 -194
  25. package/dist/material/grassmaterial.js.map +1 -1
  26. package/dist/material/lambert.js +48 -22
  27. package/dist/material/lambert.js.map +1 -1
  28. package/dist/material/lightmodel.js +4 -4
  29. package/dist/material/material.js +100 -59
  30. package/dist/material/material.js.map +1 -1
  31. package/dist/material/meshmaterial.js +227 -186
  32. package/dist/material/meshmaterial.js.map +1 -1
  33. package/dist/material/mixins/albedocolor.js +29 -100
  34. package/dist/material/mixins/albedocolor.js.map +1 -1
  35. package/dist/material/mixins/foliage.js +47 -0
  36. package/dist/material/mixins/foliage.js.map +1 -0
  37. package/dist/material/mixins/ggxlut.js +213 -0
  38. package/dist/material/mixins/ggxlut.js.map +1 -0
  39. package/dist/material/mixins/lightmodel/blinnphong.js +89 -0
  40. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -0
  41. package/dist/material/mixins/lightmodel/lambert.js +58 -0
  42. package/dist/material/mixins/lightmodel/lambert.js.map +1 -0
  43. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +132 -0
  44. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -0
  45. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +105 -0
  46. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -0
  47. package/dist/material/mixins/lit.js +464 -0
  48. package/dist/material/mixins/lit.js.map +1 -0
  49. package/dist/material/mixins/pbr/common.js +451 -0
  50. package/dist/material/mixins/pbr/common.js.map +1 -0
  51. package/dist/material/mixins/pbr/metallicroughness.js +126 -0
  52. package/dist/material/mixins/pbr/metallicroughness.js.map +1 -0
  53. package/dist/material/mixins/pbr/specularglossness.js +104 -0
  54. package/dist/material/mixins/pbr/specularglossness.js.map +1 -0
  55. package/dist/material/mixins/texture.js +157 -0
  56. package/dist/material/mixins/texture.js.map +1 -0
  57. package/dist/material/mixins/vertexcolor.js +16 -11
  58. package/dist/material/mixins/vertexcolor.js.map +1 -1
  59. package/dist/material/pbrmr.js +65 -0
  60. package/dist/material/pbrmr.js.map +1 -0
  61. package/dist/material/pbrsg.js +64 -0
  62. package/dist/material/pbrsg.js.map +1 -0
  63. package/dist/material/shader/helper.js +903 -0
  64. package/dist/material/shader/helper.js.map +1 -0
  65. package/dist/material/terrainmat.js +357 -0
  66. package/dist/material/terrainmat.js.map +1 -0
  67. package/dist/material/terrainmaterial.js +311 -103
  68. package/dist/material/terrainmaterial.js.map +1 -1
  69. package/dist/material/unlit.js +12 -9
  70. package/dist/material/unlit.js.map +1 -1
  71. package/dist/posteffect/bloom.js +8 -6
  72. package/dist/posteffect/bloom.js.map +1 -1
  73. package/dist/posteffect/compositor.js +14 -6
  74. package/dist/posteffect/compositor.js.map +1 -1
  75. package/dist/posteffect/posteffect.js +1 -1
  76. package/dist/posteffect/sao.js +8 -5
  77. package/dist/posteffect/sao.js.map +1 -1
  78. package/dist/posteffect/tonemap.js +2 -2
  79. package/dist/posteffect/water.js +10 -8
  80. package/dist/posteffect/water.js.map +1 -1
  81. package/dist/render/cluster_light.js +6 -5
  82. package/dist/render/cluster_light.js.map +1 -1
  83. package/dist/render/depthpass.js +46 -0
  84. package/dist/render/depthpass.js.map +1 -0
  85. package/dist/render/envlight.js +26 -24
  86. package/dist/render/envlight.js.map +1 -1
  87. package/dist/render/fullscreenquad.js +38 -0
  88. package/dist/render/fullscreenquad.js.map +1 -0
  89. package/dist/render/lightpass.js +98 -0
  90. package/dist/render/lightpass.js.map +1 -0
  91. package/dist/render/render_queue.js +2 -1
  92. package/dist/render/render_queue.js.map +1 -1
  93. package/dist/render/renderer.js +191 -0
  94. package/dist/render/renderer.js.map +1 -0
  95. package/dist/render/renderpass.js +10 -8
  96. package/dist/render/renderpass.js.map +1 -1
  97. package/dist/render/shadowmap_pass.js +3 -4
  98. package/dist/render/shadowmap_pass.js.map +1 -1
  99. package/dist/render/sky.js +31 -15
  100. package/dist/render/sky.js.map +1 -1
  101. package/dist/scene/environment.js +8 -6
  102. package/dist/scene/environment.js.map +1 -1
  103. package/dist/scene/graph_node.js +3 -0
  104. package/dist/scene/graph_node.js.map +1 -1
  105. package/dist/scene/mesh.js +13 -12
  106. package/dist/scene/mesh.js.map +1 -1
  107. package/dist/scene/scene.js +11 -15
  108. package/dist/scene/scene.js.map +1 -1
  109. package/dist/scene/scene_node.js +10 -16
  110. package/dist/scene/scene_node.js.map +1 -1
  111. package/dist/scene/terrain/grass.js +4 -14
  112. package/dist/scene/terrain/grass.js.map +1 -1
  113. package/dist/scene/terrain/patch.js +3 -3
  114. package/dist/scene/terrain/terrain.js +4 -9
  115. package/dist/scene/terrain/terrain.js.map +1 -1
  116. package/dist/shaders/framework.js +17 -3
  117. package/dist/shaders/framework.js.map +1 -1
  118. package/dist/shaders/misc.js +13 -161
  119. package/dist/shaders/misc.js.map +1 -1
  120. package/dist/shaders/noise.js +7 -7
  121. package/dist/shaders/pbr.js +1 -82
  122. package/dist/shaders/pbr.js.map +1 -1
  123. package/dist/shaders/shadow.js +33 -31
  124. package/dist/shaders/shadow.js.map +1 -1
  125. package/dist/shaders/water.js +3 -9
  126. package/dist/shaders/water.js.map +1 -1
  127. package/dist/shadow/esm.js +11 -9
  128. package/dist/shadow/esm.js.map +1 -1
  129. package/dist/shadow/pcf_opt.js +15 -15
  130. package/dist/shadow/pcf_pd.js +15 -15
  131. package/dist/shadow/shadowmapper.js +13 -15
  132. package/dist/shadow/shadowmapper.js.map +1 -1
  133. package/dist/shadow/ssm.js +21 -55
  134. package/dist/shadow/ssm.js.map +1 -1
  135. package/dist/shadow/vsm.js +15 -13
  136. package/dist/shadow/vsm.js.map +1 -1
  137. package/dist/shapes/torus.js +2 -2
  138. package/dist/utility/bounding_volume.js +27 -27
  139. package/dist/utility/pmrem.js +4 -4
  140. package/dist/utility/sheenlut.js +196 -0
  141. package/dist/utility/sheenlut.js.map +1 -0
  142. package/dist/utility/shprojection.js +0 -1
  143. package/dist/utility/shprojection.js.map +1 -1
  144. package/dist/values.js +11 -8
  145. package/dist/values.js.map +1 -1
  146. package/package.json +9 -9
@@ -1,49 +1,75 @@
1
- import { LitMaterial } from './lit.js';
2
- import { mixinAlbedoColor } from './mixins/albedocolor.js';
1
+ import { mixinLight } from './mixins/lit.js';
3
2
  import { mixinVertexColor } from './mixins/vertexcolor.js';
4
- import { applyMaterialMixins } from './meshmaterial.js';
3
+ import { applyMaterialMixins, MeshMaterial } from './meshmaterial.js';
4
+ import { ShaderHelper } from './shader/helper.js';
5
5
 
6
6
  /**
7
7
  * Lambert material
8
8
  * @public
9
- */ class LambertMaterial extends applyMaterialMixins(LitMaterial, mixinVertexColor, mixinAlbedoColor) {
9
+ */ class LambertMaterial extends applyMaterialMixins(MeshMaterial, mixinLight, mixinVertexColor) {
10
+ static FEATURE_VERTEX_NORMAL = this.defineFeature();
11
+ static FEATURE_VERTEX_TANGENT = this.defineFeature();
10
12
  constructor(){
11
13
  super();
14
+ this.useFeature(LambertMaterial.FEATURE_VERTEX_NORMAL, true);
12
15
  }
13
- vertexShader(scope, ctx) {
14
- super.vertexShader(scope, ctx);
15
- scope.$inputs.zPos = scope.$builder.vec3().attrib('position');
16
- this.transformVertexAndNormal(scope);
16
+ /** true if vertex normal attribute presents */ get vertexNormal() {
17
+ return this.featureUsed(LambertMaterial.FEATURE_VERTEX_NORMAL);
17
18
  }
18
- fragmentShader(scope, ctx) {
19
- super.fragmentShader(scope, ctx);
19
+ set vertexNormal(val) {
20
+ this.useFeature(LambertMaterial.FEATURE_VERTEX_NORMAL, !!val);
21
+ }
22
+ /** true if vertex normal attribute presents */ get vertexTangent() {
23
+ return this.featureUsed(LambertMaterial.FEATURE_VERTEX_TANGENT);
24
+ }
25
+ set vertexTangent(val) {
26
+ this.useFeature(LambertMaterial.FEATURE_VERTEX_TANGENT, !!val);
27
+ }
28
+ vertexShader(scope) {
29
+ super.vertexShader(scope);
30
+ const pb = scope.$builder;
31
+ scope.$l.oPos = ShaderHelper.resolveVertexPosition(scope);
32
+ scope.$outputs.worldPos = pb.mul(ShaderHelper.getWorldMatrix(scope), pb.vec4(scope.oPos, 1)).xyz;
33
+ ShaderHelper.setClipSpacePosition(scope, pb.mul(ShaderHelper.getViewProjectionMatrix(scope), pb.vec4(scope.$outputs.worldPos, 1)));
34
+ if (this.vertexNormal) {
35
+ scope.$l.oNorm = ShaderHelper.resolveVertexNormal(scope);
36
+ scope.$outputs.wNorm = pb.mul(ShaderHelper.getNormalMatrix(scope), pb.vec4(scope.oNorm, 0)).xyz;
37
+ if (this.vertexTangent) {
38
+ scope.$l.oTangent = ShaderHelper.resolveVertexTangent(scope);
39
+ scope.$outputs.wTangent = pb.mul(ShaderHelper.getNormalMatrix(scope), pb.vec4(scope.oTangent.xyz, 0)).xyz;
40
+ scope.$outputs.wBinormal = pb.mul(pb.cross(scope.$outputs.wNorm, scope.$outputs.wTangent), scope.oTangent.w);
41
+ }
42
+ }
43
+ }
44
+ fragmentShader(scope) {
45
+ super.fragmentShader(scope);
20
46
  const pb = scope.$builder;
21
47
  const that = this;
22
- if (this.needFragmentColor(ctx)) {
23
- scope.$l.albedo = this.calculateAlbedoColor(scope, ctx);
48
+ if (this.needFragmentColor()) {
49
+ scope.$l.albedo = this.calculateAlbedoColor(scope);
24
50
  if (this.vertexColor) {
25
- scope.albedo = pb.mul(scope.albedo, this.getVertexColor(scope, ctx));
51
+ scope.albedo = pb.mul(scope.albedo, this.getVertexColor(scope));
26
52
  }
27
53
  scope.$l.color = pb.vec3(0);
28
- scope.$l.normal = this.calculateNormal(scope, ctx);
29
- if (this.needCalculateEnvLight(ctx)) {
30
- scope.color = pb.add(scope.color, this.getEnvLightIrradiance(scope, scope.normal, ctx));
54
+ scope.$l.normal = this.calculateNormal(scope, scope.$inputs.worldPos, scope.$inputs.wNorm, scope.$inputs.wTangent, scope.$inputs.wBinormal);
55
+ if (this.needCalculateEnvLight()) {
56
+ scope.color = pb.add(scope.color, this.getEnvLightIrradiance(scope, scope.normal));
31
57
  }
32
- this.forEachLight(scope, ctx, function(type, posRange, dirCutoff, colorIntensity, shadow) {
33
- this.$l.lightAtten = that.calculateLightAttenuation(this, type, posRange, dirCutoff);
34
- this.$l.lightDir = that.calculateLightDirection(this, type, posRange, dirCutoff);
58
+ this.forEachLight(scope, function(type, posRange, dirCutoff, colorIntensity, shadow) {
59
+ this.$l.lightAtten = that.calculateLightAttenuation(this, type, scope.$inputs.worldPos, posRange, dirCutoff);
60
+ this.$l.lightDir = that.calculateLightDirection(this, type, scope.$inputs.worldPos, posRange, dirCutoff);
35
61
  this.$l.NoL = pb.clamp(pb.dot(this.normal, this.lightDir), 0, 1);
36
62
  this.$l.lightContrib = pb.mul(colorIntensity.rgb, colorIntensity.a, this.NoL, this.lightAtten);
37
63
  if (shadow) {
38
- this.$l.shadow = pb.vec3(that.calculateShadow(this, this.NoL, ctx));
64
+ this.$l.shadow = pb.vec3(that.calculateShadow(this, scope.$inputs.worldPos, this.NoL));
39
65
  this.lightContrib = pb.mul(this.lightContrib, this.shadow);
40
66
  }
41
67
  this.color = pb.add(this.color, this.lightContrib);
42
68
  });
43
69
  scope.$l.litColor = pb.mul(scope.albedo, pb.vec4(scope.color, 1));
44
- this.outputFragmentColor(scope, scope.litColor, ctx);
70
+ this.outputFragmentColor(scope, scope.$inputs.worldPos, scope.litColor);
45
71
  } else {
46
- this.outputFragmentColor(scope, null, ctx);
72
+ this.outputFragmentColor(scope, scope.$inputs.worldPos, null);
47
73
  }
48
74
  }
49
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lambert.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"lambert.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -906,10 +906,10 @@ const TEX_NAME_CLEARCOAT_NORMAL = 'clearcoatNormal';
906
906
  ], function() {
907
907
  this.$l.n = this.bits;
908
908
  this.n = pb.compOr(pb.sal(this.n, 16), pb.sar(this.n, 16));
909
- this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x55555555), 1), pb.sar(pb.compAnd(this.n, 0xAAAAAAAA), 1));
910
- this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x33333333), 2), pb.sar(pb.compAnd(this.n, 0xCCCCCCCC), 2));
911
- this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x0F0F0F0F), 4), pb.sar(pb.compAnd(this.n, 0xF0F0F0F0), 4));
912
- this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x00FF00FF), 8), pb.sar(pb.compAnd(this.n, 0xFF00FF00), 8));
909
+ this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x55555555), 1), pb.sar(pb.compAnd(this.n, 0xaaaaaaaa), 1));
910
+ this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x33333333), 2), pb.sar(pb.compAnd(this.n, 0xcccccccc), 2));
911
+ this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x0f0f0f0f), 4), pb.sar(pb.compAnd(this.n, 0xf0f0f0f0), 4));
912
+ this.n = pb.compOr(pb.sal(pb.compAnd(this.n, 0x00ff00ff), 8), pb.sar(pb.compAnd(this.n, 0xff00ff00), 8));
913
913
  this.$return(pb.mul(pb.float(this.n), 2.3283064365386963e-10));
914
914
  });
915
915
  pb.func('hammersley2d', [
@@ -1,7 +1,8 @@
1
1
  import { List } from '@zephyr3d/base';
2
2
  import { ProgramBuilder } from '@zephyr3d/device';
3
3
  import { Application } from '../app.js';
4
- import { RENDER_PASS_TYPE_FORWARD, RENDER_PASS_TYPE_SHADOWMAP, RENDER_PASS_TYPE_DEPTH_ONLY } from '../values.js';
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';
5
6
 
6
7
  class InstanceBindGroupPool {
7
8
  _bindGroups;
@@ -38,7 +39,7 @@ class InstanceBindGroupPool {
38
39
  const bindGroup = this._bindGroups[bindGroupIndex];
39
40
  const offset = (maxSize - bindGroup.freeSize) / 64;
40
41
  for (const matrix of worldMatrices){
41
- bindGroup.bindGroup.setRawData('worldMatrix', maxSize - bindGroup.freeSize, matrix);
42
+ bindGroup.bindGroup.setRawData(ShaderHelper.getWorldMatricesUniformName(), maxSize - bindGroup.freeSize, matrix);
42
43
  bindGroup.freeSize -= 64;
43
44
  }
44
45
  device.setBindGroup(3, bindGroup.bindGroup);
@@ -47,9 +48,9 @@ class InstanceBindGroupPool {
47
48
  }
48
49
  /**
49
50
  * Base class for any kind of materials
51
+ *
50
52
  * @public
51
53
  */ class Material {
52
- /** @internal */ static _debugChannel = '';
53
54
  /** @internal */ static _nextId = 0;
54
55
  /** @internal */ static _programMap = {};
55
56
  /** @internal */ static _drawableTimestamps = new WeakMap();
@@ -59,7 +60,7 @@ class InstanceBindGroupPool {
59
60
  /** @internal */ static _materialIterators = new WeakMap();
60
61
  /** @internal */ static _materialLRU = new List();
61
62
  /** @internal */ static _gcOptions = {
62
- disabled: false,
63
+ disabled: true,
63
64
  drawableCountThreshold: 500,
64
65
  materialCountThreshold: 200,
65
66
  inactiveTimeDuration: 30000
@@ -67,6 +68,7 @@ class InstanceBindGroupPool {
67
68
  /** @internal */ static _boneMatrixTextureSampler = null;
68
69
  /** @internal */ static _instanceBindGroupPool = new InstanceBindGroupPool();
69
70
  /** @internal */ static _drawableBindGroupMap = new WeakMap();
71
+ /** @internal */ _numPasses;
70
72
  /** @internal */ _hash;
71
73
  /** @internal */ _renderStateSet;
72
74
  /** @internal */ _bindGroupMap;
@@ -77,26 +79,32 @@ class InstanceBindGroupPool {
77
79
  * Creates an instance of material
78
80
  */ constructor(){
79
81
  this._id = ++Material._nextId;
80
- this._hash = [];
82
+ this._numPasses = 1;
83
+ this._hash = [
84
+ []
85
+ ];
81
86
  this._renderStateSet = null;
82
87
  this._bindGroupMap = {};
83
88
  this._optionTag = 0;
84
89
  this._materialBindGroup = null;
85
90
  }
86
- /** Debug channel */ static get debugChannel() {
87
- return this._debugChannel;
88
- }
89
- static set debugChannel(val) {
90
- this._debugChannel = val;
91
- }
92
91
  /** Unique identifier of the material */ get id() {
93
92
  return this._id;
94
93
  }
95
- /** @internal */ getHash(renderPassType) {
96
- if (this._hash[renderPassType] === void 0) {
97
- this._hash[renderPassType] = this.createHash(renderPassType);
94
+ get numPasses() {
95
+ return this._numPasses;
96
+ }
97
+ set numPasses(val) {
98
+ while(this._hash.length < val){
99
+ this._hash.push([]);
100
+ }
101
+ this._numPasses = val;
102
+ }
103
+ /** @internal */ getHash(renderPassType, pass) {
104
+ if (this._hash[pass][renderPassType] === void 0) {
105
+ this._hash[pass][renderPassType] = this.createHash(renderPassType, pass);
98
106
  }
99
- return this._hash[renderPassType];
107
+ return this._hash[pass][renderPassType];
100
108
  }
101
109
  /** Render states associated to this material */ get stateSet() {
102
110
  if (!this._renderStateSet) {
@@ -107,44 +115,55 @@ class InstanceBindGroupPool {
107
115
  set stateSet(stateset) {
108
116
  this._renderStateSet = stateset;
109
117
  }
110
- /** Returns true if this is a transparency material */ isTransparent() {
118
+ getQueueType() {
119
+ return QUEUE_OPAQUE;
120
+ }
121
+ /** Returns true if this is a transparency material */ isTransparentPass(pass) {
111
122
  return false;
112
123
  }
113
124
  /** Returns true if shading of the material will be affected by lights */ supportLighting() {
114
125
  return true;
115
126
  }
127
+ /** Returns true if this material supports geometry instancing */ isBatchable() {
128
+ return true;
129
+ }
116
130
  /**
117
131
  * Draws a primitive using this material
132
+ *
118
133
  * @param primitive - The prmitive to be drawn
119
134
  * @param ctx - The context of current drawing task
120
- */ draw(primitive, ctx) {
121
- if (this.beginDraw(ctx)) {
122
- if (ctx.instanceData?.worldMatrices.length > 1) {
123
- primitive.drawInstanced(ctx.instanceData.worldMatrices.length);
124
- } else {
125
- primitive.draw();
135
+ * @param numInstances - How many instances should be drawn. if zero, the instance count will be automatically detected.
136
+ */ draw(primitive, ctx, numInstances = 0) {
137
+ for(let i = 0; i < this._numPasses; i++){
138
+ if (this.beginDraw(i, ctx)) {
139
+ this.drawPrimitive(i, primitive, ctx, numInstances);
140
+ this.endDraw(i);
126
141
  }
127
- this.endDraw();
128
142
  }
129
143
  }
130
144
  /**
131
145
  * Prepares for drawing
132
146
  * @param ctx - The context of current drawing task
133
147
  * @returns true if succeeded, otherwise false
134
- */ beginDraw(ctx) {
148
+ */ beginDraw(pass, ctx) {
135
149
  const numInstances = ctx.instanceData?.worldMatrices?.length || 1;
136
150
  const device = Application.instance.device;
137
- const programInfo = this.getOrCreateProgram(ctx);
151
+ const programInfo = this.getOrCreateProgram(ctx, pass);
138
152
  if (programInfo) {
139
153
  const hash = programInfo.hash;
140
154
  if (!programInfo.programs[ctx.renderPass.type]) {
141
- return null;
155
+ return false;
142
156
  }
143
- this._materialBindGroup = this.applyMaterialBindGroups(ctx, hash);
144
- if (numInstances > 1) {
145
- this.applyInstanceBindGroups(ctx, hash);
146
- } else {
147
- this.applyDrawableBindGroups(ctx, hash);
157
+ if (pass > 0) {
158
+ this.optionChanged(false);
159
+ }
160
+ this._materialBindGroup = this.applyMaterialBindGroups(ctx, hash, pass);
161
+ if (pass === 0) {
162
+ if (numInstances > 1) {
163
+ this.applyInstanceBindGroups(ctx, hash);
164
+ } else {
165
+ this.applyDrawableBindGroups(ctx, hash);
166
+ }
148
167
  }
149
168
  ctx.renderPass.applyRenderStates(device, this.stateSet, ctx);
150
169
  device.setProgram(programInfo.programs[ctx.renderPass.type]);
@@ -158,7 +177,7 @@ class InstanceBindGroupPool {
158
177
  }
159
178
  /**
160
179
  * Ends drawing a primitive
161
- */ endDraw() {
180
+ */ endDraw(pass) {
162
181
  this._materialBindGroup = null;
163
182
  }
164
183
  /**
@@ -172,24 +191,22 @@ class InstanceBindGroupPool {
172
191
  * @param bindGroup - The bind group of the material
173
192
  * @param ctx - The context of current drawing task
174
193
  * @param needUpdate - true if the uniform values needs to update
175
- */ applyUniforms(bindGroup, ctx, needUpdate) {
194
+ */ applyUniforms(bindGroup, ctx, needUpdate, pass) {
176
195
  if (needUpdate) {
177
- this._applyUniforms(bindGroup, ctx);
196
+ this._applyUniforms(bindGroup, ctx, pass);
178
197
  }
179
198
  }
180
199
  /**
181
200
  * Fetch the gpu program of the material for drawing
182
201
  * @param ctx - The context for current drawing task
183
202
  * @returns Information of the gpu program
184
- */ getOrCreateProgram(ctx) {
203
+ */ getOrCreateProgram(ctx, pass) {
185
204
  const programMap = Material._programMap;
186
205
  const renderPassType = ctx.renderPass.type;
187
- const hash = `${Material.debugChannel}:${this.getHash(renderPassType)}:${!!ctx.target.getBoneMatrices()}:${Number(!!(ctx.instanceData?.worldMatrices.length > 1))}:${ctx.renderPassHash}`;
206
+ const hash = `${this.getHash(renderPassType, pass)}:${!!ctx.target.getBoneMatrices()}:${Number(!!(ctx.instanceData?.worldMatrices.length > 1))}:${ctx.renderPassHash}`;
188
207
  let programInfo = programMap[hash];
189
- if (!programInfo || !programInfo.programs[renderPassType] || programInfo.programs[renderPassType].disposed) {
190
- console.time(hash);
191
- const program = this.createProgram(ctx);
192
- console.timeEnd(hash);
208
+ if (!programInfo || programInfo.programs[renderPassType] === undefined) {
209
+ const program = this.createProgram(ctx, pass) ?? null;
193
210
  if (!programInfo) {
194
211
  programInfo = {
195
212
  programs: [
@@ -203,7 +220,7 @@ class InstanceBindGroupPool {
203
220
  }
204
221
  programInfo.programs[renderPassType] = program;
205
222
  }
206
- return programInfo || null;
223
+ return programInfo;
207
224
  }
208
225
  dispose() {
209
226
  this.clearBindGroupCache();
@@ -267,21 +284,23 @@ class InstanceBindGroupPool {
267
284
  /** @internal */ optionChanged(changeHash) {
268
285
  this._optionTag++;
269
286
  if (changeHash) {
270
- this._hash = [];
287
+ for(let i = 0; i < this._numPasses; i++){
288
+ this._hash[i] = [];
289
+ }
271
290
  }
272
291
  }
273
292
  /** @internal */ static getProgramByHashIndex(hash, index) {
274
293
  return this._programMap[hash].programs[index];
275
294
  }
276
- /** @internal */ applyMaterialBindGroups(ctx, hash) {
295
+ /** @internal */ applyMaterialBindGroups(ctx, hash, pass) {
277
296
  const index = ctx.renderPass.type;
278
297
  let bindGroupInfo = this._bindGroupMap[hash];
279
298
  if (!bindGroupInfo) {
280
299
  // bindGroups not created or have been garbage collected
281
300
  const materialBindGroup = [
282
- RENDER_PASS_TYPE_FORWARD,
301
+ RENDER_PASS_TYPE_LIGHT,
283
302
  RENDER_PASS_TYPE_SHADOWMAP,
284
- RENDER_PASS_TYPE_DEPTH_ONLY
303
+ RENDER_PASS_TYPE_DEPTH
285
304
  ].map((k)=>{
286
305
  const program = Material._programMap[hash].programs[k];
287
306
  return program?.bindGroupLayouts[2] ? Application.instance.device.createBindGroup(program.bindGroupLayouts[2]) : null;
@@ -302,7 +321,7 @@ class InstanceBindGroupPool {
302
321
  }
303
322
  const bindGroup = bindGroupInfo.materialBindGroup[index];
304
323
  if (bindGroup) {
305
- this.applyUniforms(bindGroup, ctx, bindGroupInfo.materialTag[index] < this._optionTag || bindGroupInfo.bindGroupTag[index] !== bindGroup.cid);
324
+ this.applyUniforms(bindGroup, ctx, bindGroupInfo.materialTag[index] < this._optionTag || bindGroupInfo.bindGroupTag[index] !== bindGroup.cid, pass);
306
325
  bindGroupInfo.materialTag[index] = this._optionTag;
307
326
  bindGroupInfo.bindGroupTag[index] = bindGroup.cid;
308
327
  Application.instance.device.setBindGroup(2, bindGroup);
@@ -320,9 +339,9 @@ class InstanceBindGroupPool {
320
339
  let drawableBindGroup = drawableBindGroups[hash];
321
340
  if (!drawableBindGroup) {
322
341
  const bindGroup = [
323
- RENDER_PASS_TYPE_FORWARD,
342
+ RENDER_PASS_TYPE_LIGHT,
324
343
  RENDER_PASS_TYPE_SHADOWMAP,
325
- RENDER_PASS_TYPE_DEPTH_ONLY
344
+ RENDER_PASS_TYPE_DEPTH
326
345
  ].map((k)=>{
327
346
  const program = Material._programMap[hash].programs[k];
328
347
  return program?.bindGroupLayouts[1] ? Application.instance.device.createBindGroup(program.bindGroupLayouts[1]) : null;
@@ -348,7 +367,7 @@ class InstanceBindGroupPool {
348
367
  const offset = Material._instanceBindGroupPool.apply(hash, index, ctx.instanceData.worldMatrices);
349
368
  const bindGroup = this.getDrawableBindGroup(ctx, hash).bindGroup?.[index];
350
369
  if (bindGroup) {
351
- bindGroup.setValue('instanceBufferOffset', offset);
370
+ bindGroup.setValue(ShaderHelper.getInstanceBufferOffsetUniformName(), offset);
352
371
  Application.instance.device.setBindGroup(1, bindGroup);
353
372
  } else {
354
373
  Application.instance.device.setBindGroup(1, null);
@@ -361,7 +380,7 @@ class InstanceBindGroupPool {
361
380
  if (drawableBindGroup.bindGroup) {
362
381
  const bindGroup = drawableBindGroup.bindGroup[index];
363
382
  if (drawableBindGroup.xformTag[index] < ctx.target.getXForm().getTag() || drawableBindGroup.bindGroupTag[index] !== bindGroup.cid) {
364
- bindGroup.setValue('worldMatrix', ctx.target.getXForm().worldMatrix);
383
+ bindGroup.setValue(ShaderHelper.getWorldMatrixUniformName(), ctx.target.getXForm().worldMatrix);
365
384
  drawableBindGroup.xformTag[index] = ctx.target.getXForm().getTag();
366
385
  drawableBindGroup.bindGroupTag[index] = bindGroup.cid;
367
386
  }
@@ -374,17 +393,25 @@ class InstanceBindGroupPool {
374
393
  mipFilter: 'none'
375
394
  });
376
395
  }
377
- bindGroup.setTexture('boneMatrices', boneMatrices);
378
- bindGroup.setValue('boneTextureSize', boneMatrices.width);
379
- bindGroup.setValue('invBindMatrix', ctx.target.getInvBindMatrix());
396
+ bindGroup.setTexture(ShaderHelper.getBoneMatricesUniformName(), boneMatrices);
397
+ bindGroup.setValue(ShaderHelper.getBoneTextureSizeUniformName(), boneMatrices.width);
398
+ bindGroup.setValue(ShaderHelper.getBoneInvBindMatrixUniformName(), ctx.target.getInvBindMatrix());
380
399
  }
381
400
  device.setBindGroup(1, bindGroup);
382
401
  } else {
383
402
  device.setBindGroup(1, null);
384
403
  }
404
+ device.setBindGroup(3, null);
405
+ }
406
+ /**
407
+ * Convert pass to hash
408
+ * @param pass - pass number
409
+ * @returns String hash
410
+ */ passToHash(pass) {
411
+ return String(pass);
385
412
  }
386
- /** @internal */ createHash(renderPassType) {
387
- return `${this.constructor.name}|${this._createHash(renderPassType)}`;
413
+ /** @internal */ createHash(renderPassType, pass) {
414
+ return `${this.constructor.name}|${this.passToHash(pass)}|${this._createHash(renderPassType)}`;
388
415
  }
389
416
  /** @internal */ clearBindGroupCache() {
390
417
  let n = 0;
@@ -425,9 +452,23 @@ class InstanceBindGroupPool {
425
452
  }
426
453
  this._materialIterators.set(material, this._materialLRU.append(material));
427
454
  }
428
- /** @internal */ createProgram(ctx) {
455
+ /**
456
+ * Draw primitve
457
+ *
458
+ * @param primitive - Primitive to be drawn
459
+ * @param ctx - Draw context
460
+ */ drawPrimitive(pass, primitive, ctx, numInstances) {
461
+ if (numInstances > 0) {
462
+ primitive.drawInstanced(numInstances);
463
+ } else if (ctx.instanceData?.worldMatrices.length > 1) {
464
+ primitive.drawInstanced(ctx.instanceData.worldMatrices.length);
465
+ } else {
466
+ primitive.draw();
467
+ }
468
+ }
469
+ /** @internal */ createProgram(ctx, pass) {
429
470
  const pb = new ProgramBuilder(Application.instance.device);
430
- return this._createProgram(pb, ctx);
471
+ return this._createProgram(pb, ctx, pass);
431
472
  }
432
473
  /** @internal */ createRenderStateSet() {
433
474
  return Application.instance.device.createRenderStateSet();
@@ -438,14 +479,14 @@ class InstanceBindGroupPool {
438
479
  * @param ctx - The drawing context
439
480
  * @param func - The material func
440
481
  * @returns The created shader program
441
- */ _createProgram(pb, ctx) {
482
+ */ _createProgram(pb, ctx, pass) {
442
483
  return null;
443
484
  }
444
485
  /**
445
486
  * Applies uniform values
446
487
  * @param bindGroup - The bind group
447
488
  * @param ctx - The drawing context
448
- */ _applyUniforms(bindGroup, ctx) {}
489
+ */ _applyUniforms(bindGroup, ctx, pass) {}
449
490
  /**
450
491
  * Calculates the hash code of the shader program
451
492
  * @returns The hash code
@@ -1 +1 @@
1
- {"version":3,"file":"material.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"material.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}