@zephyr3d/scene 0.1.2 → 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 +3 -3
@@ -1,139 +1,347 @@
1
- import { Material } from './material.js';
2
- import { forwardComputeLighting } from '../shaders/lighting.js';
3
- import { RENDER_PASS_TYPE_FORWARD, RENDER_PASS_TYPE_SHADOWMAP, RENDER_PASS_TYPE_DEPTH_ONLY } from '../values.js';
4
- import { ShaderFramework } from '../shaders/framework.js';
5
- import { encodeColorOutput, nonLinearDepthToLinearNormalized, encodeNormalizedFloatToRGBA } from '../shaders/misc.js';
1
+ import { applyMaterialMixins, MeshMaterial } from './meshmaterial.js';
2
+ import { mixinPBRMetallicRoughness } from './mixins/lightmodel/pbrmetallicroughness.js';
3
+ import { mixinLight } from './mixins/lit.js';
6
4
  import { Application } from '../app.js';
7
- import { TerrainLightModel } from './terrainlightmodel.js';
8
- import { MESH_MATERIAL } from '../shaders/builtins.js';
5
+ import { Vector4 } from '@zephyr3d/base';
6
+ import { drawFullscreenQuad } from '../render/fullscreenquad.js';
7
+ import { ShaderHelper } from './shader/helper.js';
9
8
 
10
- /** @internal */ const MAX_DETAIL_TEXTURE_LEVELS = 8;
11
- /**
12
- * The terrain material
13
- * @public
14
- */ class TerrainMaterial extends Material {
15
- /** @internal */ _lightModel;
16
- /** @internal */ _terrainInfo;
17
- /**
18
- * Creates an instance of TerrainMaterial
19
- */ constructor(options){
9
+ /**
10
+ * Terrain material class
11
+ * @public
12
+ */ class TerrainMaterial extends applyMaterialMixins(MeshMaterial, mixinLight, mixinPBRMetallicRoughness) {
13
+ static _metallicRoughnessGenerationProgram = null;
14
+ static _metallicRoughnessGenerationBindGroup = null;
15
+ _options;
16
+ _uvScales;
17
+ _numDetailMaps;
18
+ _terrainInfo;
19
+ constructor(options){
20
20
  super();
21
+ this.normalMapMode = 'object-space';
22
+ this._options = null;
23
+ this._numDetailMaps = 0;
24
+ this._uvScales = null;
21
25
  this._terrainInfo = null;
22
- this._lightModel = new TerrainLightModel(options);
23
- }
24
- get lightModel() {
25
- return this._lightModel;
26
+ if (options && options.splatMap && options.detailMaps && options.detailMaps.albedoTextures) {
27
+ this._options = Object.assign({}, options);
28
+ const albedoTextures = this._options.detailMaps.albedoTextures;
29
+ this._numDetailMaps = Array.isArray(albedoTextures) ? albedoTextures.length : albedoTextures.depth;
30
+ if (!this._numDetailMaps) {
31
+ throw new Error(`TerrainMaterial(): Invalid detail textures`);
32
+ }
33
+ if (this._numDetailMaps > 4) {
34
+ throw new Error(`TerrainMaterial(): The maximum detail levels is 4`);
35
+ }
36
+ if (!this._options.detailMaps.uvScale || this._options.detailMaps.uvScale.length !== this._numDetailMaps) {
37
+ throw new Error(`TerrainMaterial(): Invalid uv scale`);
38
+ }
39
+ this._uvScales = new Float32Array(this._numDetailMaps * 4);
40
+ for(let i = 0; i < this._numDetailMaps; i++){
41
+ this._uvScales[i * 4] = this._options.detailMaps.uvScale[i];
42
+ this._uvScales[i * 4 + 1] = 1;
43
+ this._uvScales[i * 4 + 2] = 0.01;
44
+ this._uvScales[i * 4 + 3] = 0.99;
45
+ }
46
+ if (this._options.detailMaps.metallic) {
47
+ if (this._options.detailMaps.metallic.length !== this._numDetailMaps) {
48
+ throw new Error(`TerrainMaterial(): Invalid metallic values`);
49
+ }
50
+ for(let i = 0; i < this._numDetailMaps; i++){
51
+ this._uvScales[i * 4 + 2] = this._options.detailMaps.metallic[i];
52
+ }
53
+ }
54
+ if (this._options.detailMaps.roughness) {
55
+ if (this._options.detailMaps.roughness.length !== this._numDetailMaps) {
56
+ throw new Error(`TerrainMaterial(): Invalid roughness values`);
57
+ }
58
+ for(let i = 0; i < this._numDetailMaps; i++){
59
+ this._uvScales[i * 4 + 3] = this._options.detailMaps.roughness[i];
60
+ }
61
+ }
62
+ const normalTextures = options.detailMaps.normalTextures;
63
+ if (normalTextures) {
64
+ const m = Array.isArray(normalTextures) ? normalTextures.length : normalTextures.depth;
65
+ if (m !== this._numDetailMaps) {
66
+ throw new Error(`TerrainMaterial(): The number of normal textures not match the number of albedo textures`);
67
+ }
68
+ if (options.detailMaps.normalScale) {
69
+ if (options.detailMaps.normalScale.length !== this._numDetailMaps) {
70
+ throw new Error(`TerrainMaterial(): Invalid normal scale`);
71
+ }
72
+ for(let i = 0; i < this._numDetailMaps; i++){
73
+ this._uvScales[i * 4 + 1] = options.detailMaps.normalScale[i];
74
+ }
75
+ }
76
+ }
77
+ this._options = Object.assign({}, options);
78
+ if (Array.isArray(albedoTextures)) {
79
+ for(let i = 0; i < albedoTextures.length; i++){
80
+ if (!albedoTextures[i]) {
81
+ throw new Error(`TerrainMaterial(): Invalid detail albedo texture`);
82
+ }
83
+ albedoTextures[i].samplerOptions = {
84
+ addressU: 'repeat',
85
+ addressV: 'repeat'
86
+ };
87
+ }
88
+ } else {
89
+ albedoTextures.samplerOptions = {
90
+ addressU: 'repeat',
91
+ addressV: 'repeat'
92
+ };
93
+ }
94
+ if (Array.isArray(normalTextures)) {
95
+ for(let i = 0; i < normalTextures.length; i++){
96
+ if (!normalTextures[i]) {
97
+ throw new Error(`TerrainMaterial(): Invalid detail normal texture`);
98
+ }
99
+ normalTextures[i].samplerOptions = {
100
+ addressU: 'repeat',
101
+ addressV: 'repeat'
102
+ };
103
+ }
104
+ } else if (normalTextures) {
105
+ normalTextures.samplerOptions = {
106
+ addressU: 'repeat',
107
+ addressV: 'repeat'
108
+ };
109
+ }
110
+ }
111
+ this.metallicRoughnessTexture = this.generateMetallicRoughnessMap();
112
+ this.metallicRoughnessTexCoordIndex = -1;
113
+ this.albedoTexCoordIndex = -1;
114
+ this.normalTexCoordIndex = -1;
26
115
  }
27
116
  get terrainInfo() {
28
117
  return this._terrainInfo;
29
118
  }
30
119
  set terrainInfo(val) {
31
120
  this._terrainInfo = val;
32
- this.optionChanged(false);
121
+ this.uniformChanged();
33
122
  }
34
- /**
35
- * {@inheritDoc Material.isTransparent}
36
- * @override
37
- */ isTransparent() {
123
+ /**
124
+ * {@inheritDoc MeshMaterial.isTransparentPass}
125
+ * @override
126
+ */ isTransparentPass(pass) {
38
127
  return false;
39
128
  }
40
- /**
41
- * {@inheritDoc Material.supportLighting}
42
- * @override
129
+ /**
130
+ * {@inheritDoc Material.supportLighting}
131
+ * @override
43
132
  */ supportLighting() {
44
- return this._lightModel.supportLighting();
133
+ return true;
45
134
  }
46
- /**
47
- * {@inheritDoc Material.applyUniforms}
48
- * @override
49
- */ applyUniforms(bindGroup, ctx, needUpdate) {
50
- super.applyUniforms(bindGroup, ctx, needUpdate);
51
- if (ctx.renderPass.type === RENDER_PASS_TYPE_FORWARD) {
52
- this._lightModel.applyUniformsIfOutdated(bindGroup, ctx);
53
- }
135
+ /**
136
+ * {@inheritDoc Material.isBatchable}
137
+ * @override
138
+ */ isBatchable() {
139
+ return false;
54
140
  }
55
- /**
56
- * {@inheritDoc Material._applyUniforms}
57
- * @override
58
- */ _applyUniforms(bindGroup, ctx) {
59
- if (ctx.renderPass.type === RENDER_PASS_TYPE_FORWARD) {
141
+ applyUniformValues(bindGroup, ctx, pass) {
142
+ super.applyUniformValues(bindGroup, ctx, pass);
143
+ if (this.needFragmentColor(ctx)) {
60
144
  bindGroup.setValue('terrainInfo', this._terrainInfo);
145
+ if (this._options) {
146
+ bindGroup.setValue('detailScales', this._uvScales);
147
+ bindGroup.setTexture('splatMap', this._options.splatMap);
148
+ if (Array.isArray(this._options.detailMaps.albedoTextures)) {
149
+ for(let i = 0; i < this._numDetailMaps; i++){
150
+ bindGroup.setTexture(`detailAlbedoMap${i}`, this._options.detailMaps.albedoTextures[i]);
151
+ }
152
+ } else {
153
+ bindGroup.setTexture('detailAlbedoMap', this._options.detailMaps.albedoTextures);
154
+ }
155
+ if (Array.isArray(this._options.detailMaps.normalTextures)) {
156
+ for(let i = 0; i < this._numDetailMaps; i++){
157
+ bindGroup.setTexture(`detailNormalMap${i}`, this._options.detailMaps.normalTextures[i]);
158
+ }
159
+ } else {
160
+ bindGroup.setTexture('detailNormalMap', this._options.detailMaps.normalTextures);
161
+ }
162
+ }
61
163
  }
62
164
  }
63
- /** @internal */ getHash(renderPassType) {
64
- if (this._hash[renderPassType] === void 0) {
65
- this._hash[renderPassType] = this.createHash(renderPassType);
66
- }
67
- return this._hash[renderPassType];
165
+ /** @ts-ignore */ getMetallicRoughnessTexCoord(scope) {
166
+ return scope.$inputs.mapUV;
68
167
  }
69
- /** @internal */ _createHash(renderPassType) {
70
- return renderPassType === RENDER_PASS_TYPE_FORWARD ? this._lightModel.getHash() : '';
168
+ /** @ts-ignore */ getNormalTexCoord(scope) {
169
+ return scope.$inputs.mapUV;
71
170
  }
72
- /** @internal */ _createProgram(pb, ctx) {
171
+ /** @ts-ignore */ getAlbedoTexCoord(scope) {
172
+ return scope.$inputs.mapUV;
173
+ }
174
+ calculateAlbedoColor(scope) {
175
+ if (!this._options) {
176
+ return super.calculateAlbedoColor(scope);
177
+ }
73
178
  const that = this;
74
- if (ctx.renderPass.type === RENDER_PASS_TYPE_SHADOWMAP) {
75
- const shadowMapParams = ctx.shadowMapInfo.get(ctx.renderPass.light);
76
- pb.emulateDepthClamp = !!shadowMapParams.depthClampEnabled;
179
+ const pb = scope.$builder;
180
+ const funcName = 'getTerrainAlbedo';
181
+ pb.func(funcName, [], function() {
182
+ this.$l.mask = pb.textureSample(this.splatMap, this.$inputs.mapUV);
183
+ this.$l.color = pb.vec3(0);
184
+ const useTextureArray = !Array.isArray(that._options.detailMaps.albedoTextures);
185
+ for(let i = 0; i < that._numDetailMaps; i++){
186
+ const uv = pb.mul(this.$inputs.mapUV, this.detailScales.at(i).x);
187
+ const sample = useTextureArray ? pb.textureArraySample(this.detailAlbedoMap, uv, i).rgb : pb.textureSample(this[`detailAlbedoMap${i}`], uv).rgb;
188
+ this.color = pb.add(this.color, pb.mul(sample, this.mask[i]));
189
+ }
190
+ this.$return(pb.vec4(this.color, 1));
191
+ });
192
+ return pb.getGlobalScope()[funcName]();
193
+ }
194
+ sampleDetailNormalMap(scope, tex, texCoord, normalScale, TBN) {
195
+ const pb = scope.$builder;
196
+ const pixel = pb.sub(pb.mul(pb.textureSample(tex, texCoord).rgb, 2), pb.vec3(1));
197
+ const normalTex = pb.mul(pixel, pb.vec3(pb.vec3(normalScale).xx, 1));
198
+ return pb.normalize(pb.mul(TBN, normalTex));
199
+ }
200
+ vertexShader(scope) {
201
+ super.vertexShader(scope);
202
+ const pb = scope.$builder;
203
+ scope.$l.oPos = ShaderHelper.resolveVertexPosition(scope);
204
+ scope.$outputs.worldPos = pb.mul(ShaderHelper.getWorldMatrix(scope), pb.vec4(scope.oPos, 1)).xyz;
205
+ ShaderHelper.setClipSpacePosition(scope, pb.mul(ShaderHelper.getViewProjectionMatrix(scope), pb.vec4(scope.$outputs.worldPos, 1)));
206
+ if (this.needFragmentColor()) {
207
+ scope.terrainInfo = pb.vec4().uniform(2);
208
+ scope.$l.oNorm = ShaderHelper.resolveVertexNormal(scope);
209
+ scope.$outputs.worldNorm = pb.mul(ShaderHelper.getNormalMatrix(scope), pb.vec4(scope.oNorm, 0)).xyz;
210
+ scope.$outputs.mapUV = pb.div(scope.oPos.xz, scope.terrainInfo.xy);
77
211
  }
78
- const program = pb.buildRenderProgram({
79
- vertex () {
80
- ShaderFramework.prepareVertexShader(pb, ctx);
81
- this.$inputs.pos = pb.vec3().attrib('position');
82
- if (ctx.renderPass.type === RENDER_PASS_TYPE_FORWARD) {
83
- this.terrainInfo = pb.vec4().uniform(2);
84
- this.$inputs.normal = pb.vec3().attrib('normal');
85
- that._lightModel.setupUniforms(this, ctx);
212
+ }
213
+ fragmentShader(scope) {
214
+ super.fragmentShader(scope);
215
+ const pb = scope.$builder;
216
+ const that = this;
217
+ if (this.needFragmentColor()) {
218
+ if (this._options) {
219
+ scope.detailScales = pb.vec4[this._numDetailMaps]().uniform(2);
220
+ scope.splatMap = pb.tex2D().uniform(2);
221
+ const useAlbedoTextureArray = !Array.isArray(that._options.detailMaps.albedoTextures);
222
+ if (useAlbedoTextureArray) {
223
+ scope.detailAlbedoMap = pb.tex2DArray().uniform(2);
224
+ } else {
225
+ for(let i = 0; i < that._numDetailMaps; i++){
226
+ scope[`detailAlbedoMap${i}`] = pb.tex2D().uniform(2);
227
+ }
86
228
  }
87
- pb.main(function() {
88
- ShaderFramework.ftransform(this);
89
- if (ctx.renderPass.type === RENDER_PASS_TYPE_FORWARD) {
90
- this.$l.uv = pb.div(this.$inputs.pos.xz, this.terrainInfo.xy);
91
- for(let i = 0; i < Application.instance.device.getDeviceCaps().miscCaps.maxTexCoordIndex; i++){
92
- if (that._lightModel?.isTexCoordIndexUsed(i)) {
93
- this.$outputs[`texcoord${i}`] = that._lightModel.calculateTexCoordNoInput(this, i, this.uv);
94
- }
95
- }
229
+ const useNormalTextureArray = !Array.isArray(that._options.detailMaps.normalTextures);
230
+ if (useNormalTextureArray) {
231
+ scope.detailNormalMap = pb.tex2DArray().uniform(2);
232
+ } else {
233
+ for(let i = 0; i < that._numDetailMaps; i++){
234
+ scope[`detailNormalMap${i}`] = pb.tex2D().uniform(2);
96
235
  }
97
- });
98
- },
99
- fragment () {
100
- ShaderFramework.prepareFragmentShader(pb, ctx);
101
- if (ctx.renderPass.type === RENDER_PASS_TYPE_FORWARD) {
102
- that._lightModel.setupUniforms(this, ctx);
103
- this.$outputs.outColor = pb.vec4();
104
- pb.main(function() {
105
- this.$l.litColor = forwardComputeLighting(this, that._lightModel, ctx);
106
- MESH_MATERIAL.DISCARD_IF_CLIPPED(this);
107
- this.$outputs.outColor = encodeColorOutput(this, this.litColor);
108
- });
109
- } else if (ctx.renderPass.type === RENDER_PASS_TYPE_DEPTH_ONLY) {
110
- this.$outputs.outColor = pb.vec4();
236
+ }
237
+ }
238
+ scope.$l.albedo = this.calculateAlbedoColor(scope);
239
+ scope.$l.normalInfo = this.calculateNormalAndTBN(scope, scope.$inputs.worldPos, scope.$inputs.worldNorm);
240
+ let calcNormal = false;
241
+ if (this._options && this._options.detailMaps.normalTextures) {
242
+ scope.$l.detailMask = pb.textureSample(scope.splatMap, scope.$inputs.mapUV);
243
+ if (Array.isArray(this._options.detailMaps.normalTextures)) {
244
+ for(let i = 0; i < this._options.detailMaps.normalTextures.length; i++){
245
+ const tex = scope[`detailNormalMap${i}`];
246
+ const scale = scope.detailScales.at(i).y;
247
+ const texCoord = pb.mul(scope.$inputs.mapUV, scope.detailScales.at(i).x);
248
+ scope.normalInfo.normal = pb.add(scope.normalInfo.normal, pb.mul(this.sampleDetailNormalMap(scope, tex, texCoord, scale, scope.normalInfo.TBN), scope.detailMask[i]));
249
+ calcNormal = true;
250
+ }
251
+ } else {
252
+ const tex = scope.detailNormalMap;
253
+ for(let i = 0; i < this._numDetailMaps; i++){
254
+ const scale = scope.detailScales.at(i).y;
255
+ const texCoord = pb.mul(scope.$inputs.mapUV, scope.detailScales.at(i).x);
256
+ const pixel = pb.sub(pb.mul(pb.textureArraySample(tex, texCoord, i).rgb, 2), pb.vec3(1));
257
+ const normalTex = pb.mul(pixel, pb.vec3(pb.vec3(scale).xx, 1));
258
+ const detailNormal = pb.normalize(pb.mul(scope.normalInfo.TBN, normalTex));
259
+ scope.normalInfo.normal = pb.add(scope.normalInfo.normal, pb.mul(detailNormal, scope.detailMask[i]));
260
+ calcNormal = true;
261
+ }
262
+ }
263
+ }
264
+ if (calcNormal) {
265
+ scope.normalInfo.normal = pb.normalize(scope.normalInfo.normal);
266
+ }
267
+ scope.$l.viewVec = this.calculateViewVector(scope, scope.$inputs.worldPos);
268
+ scope.$l.litColor = this.PBRLight(scope, scope.$inputs.worldPos, scope.normalInfo.normal, scope.viewVec, scope.albedo, scope.normalInfo.TBN);
269
+ this.outputFragmentColor(scope, scope.$inputs.worldPos, pb.vec4(scope.litColor, scope.albedo.a));
270
+ } else {
271
+ this.outputFragmentColor(scope, scope.$inputs.worldPos, null);
272
+ }
273
+ }
274
+ generateMetallicRoughnessMap() {
275
+ const device = Application.instance.device;
276
+ if (!this._options) {
277
+ const tex = device.createTexture2D('rgba8unorm', 1, 1, {
278
+ samplerOptions: {
279
+ mipFilter: 'none'
280
+ }
281
+ });
282
+ tex.update(new Uint8Array([
283
+ 0,
284
+ 1,
285
+ 0,
286
+ 0
287
+ ]), 0, 0, 1, 1);
288
+ tex.name = 'TerrainMetallicRoughnessMap';
289
+ return tex;
290
+ }
291
+ if (!TerrainMaterial._metallicRoughnessGenerationProgram) {
292
+ TerrainMaterial._metallicRoughnessGenerationProgram = device.buildRenderProgram({
293
+ vertex (pb) {
294
+ this.$inputs.pos = pb.vec2().attrib('position');
295
+ this.$outputs.uv = pb.vec2();
111
296
  pb.main(function() {
112
- MESH_MATERIAL.DISCARD_IF_CLIPPED(this);
113
- this.$l.depth = nonLinearDepthToLinearNormalized(this, this.$builtins.fragCoord.z);
114
- if (Application.instance.device.type === 'webgl') {
115
- this.$outputs.outColor = encodeNormalizedFloatToRGBA(this, this.depth);
116
- } else {
117
- this.$outputs.outColor = pb.vec4(this.depth, 0, 0, 1);
297
+ this.$builtins.position = pb.vec4(this.$inputs.pos, 0, 1);
298
+ this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));
299
+ if (device.type === 'webgpu') {
300
+ this.$builtins.position.y = pb.neg(this.$builtins.position.y);
118
301
  }
119
302
  });
120
- } else if (ctx.renderPass.type === RENDER_PASS_TYPE_SHADOWMAP) {
303
+ },
304
+ fragment (pb) {
121
305
  this.$outputs.outColor = pb.vec4();
306
+ this.roughness = pb.vec4().uniform(0);
307
+ this.metallic = pb.vec4().uniform(0);
308
+ this.splatMap = pb.tex2D().uniform(0);
122
309
  pb.main(function() {
123
- MESH_MATERIAL.DISCARD_IF_CLIPPED(this);
124
- const shadowMapParams = ctx.shadowMapInfo.get(ctx.renderPass.light);
125
- this.$outputs.outColor = shadowMapParams.impl.computeShadowMapDepth(shadowMapParams, this);
310
+ this.weights = pb.textureSample(this.splatMap, this.$inputs.uv);
311
+ this.roughnessValue = pb.dot(this.weights, this.roughness);
312
+ this.metallicValue = pb.dot(this.weights, this.metallic);
313
+ this.$outputs.outColor = pb.vec4(0, this.roughnessValue, this.metallicValue, 1);
126
314
  });
127
- } else {
128
- throw new Error(`unknown render pass type: ${ctx.renderPass.type}`);
129
315
  }
130
- }
131
- });
132
- // console.log(program?.getShaderSource('vertex'));
133
- // console.log(program?.getShaderSource('fragment'));
134
- return program;
316
+ });
317
+ TerrainMaterial._metallicRoughnessGenerationBindGroup = device.createBindGroup(TerrainMaterial._metallicRoughnessGenerationProgram.bindGroupLayouts[0]);
318
+ }
319
+ const roughnessValues = Vector4.one();
320
+ const metallicValues = Vector4.zero();
321
+ for(let i = 0; i < this._numDetailMaps; i++){
322
+ metallicValues[i] = this._uvScales[i * 4 + 2];
323
+ roughnessValues[i] = this._uvScales[i * 4 + 3];
324
+ }
325
+ const tex = device.createTexture2D('rgba8unorm', this._options.splatMap.width, this._options.splatMap.height);
326
+ tex.name = 'TerrainMetallicRoughnessMap';
327
+ const program = TerrainMaterial._metallicRoughnessGenerationProgram;
328
+ const bindgroup = TerrainMaterial._metallicRoughnessGenerationBindGroup;
329
+ bindgroup.setValue('roughness', roughnessValues);
330
+ bindgroup.setValue('metallic', metallicValues);
331
+ bindgroup.setTexture('splatMap', this._options.splatMap);
332
+ const fb = device.createFrameBuffer([
333
+ tex
334
+ ], null);
335
+ device.pushDeviceStates();
336
+ device.setFramebuffer(fb);
337
+ device.setProgram(program);
338
+ device.setBindGroup(0, bindgroup);
339
+ drawFullscreenQuad();
340
+ device.popDeviceStates();
341
+ fb.dispose();
342
+ return tex;
135
343
  }
136
344
  }
137
345
 
138
- export { MAX_DETAIL_TEXTURE_LEVELS, TerrainMaterial };
346
+ export { TerrainMaterial };
139
347
  //# sourceMappingURL=terrainmaterial.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"terrainmaterial.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"terrainmaterial.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,6 +1,7 @@
1
1
  import { applyMaterialMixins, MeshMaterial } from './meshmaterial.js';
2
2
  import { mixinAlbedoColor } from './mixins/albedocolor.js';
3
3
  import { mixinVertexColor } from './mixins/vertexcolor.js';
4
+ import { ShaderHelper } from './shader/helper.js';
4
5
 
5
6
  /**
6
7
  * Unlit material
@@ -10,18 +11,20 @@ import { mixinVertexColor } from './mixins/vertexcolor.js';
10
11
  constructor(){
11
12
  super();
12
13
  }
13
- vertexShader(scope, ctx) {
14
- super.vertexShader(scope, ctx);
15
- scope.$inputs.zPos = scope.$builder.vec3().attrib('position');
16
- this.transformVertexAndNormal(scope);
14
+ vertexShader(scope) {
15
+ super.vertexShader(scope);
16
+ const pb = scope.$builder;
17
+ scope.$l.oPos = ShaderHelper.resolveVertexPosition(scope);
18
+ scope.$outputs.worldPos = pb.mul(ShaderHelper.getWorldMatrix(scope), pb.vec4(scope.oPos, 1)).xyz;
19
+ ShaderHelper.setClipSpacePosition(scope, pb.mul(ShaderHelper.getViewProjectionMatrix(scope), pb.vec4(scope.$outputs.worldPos, 1)));
17
20
  }
18
- fragmentShader(scope, ctx) {
19
- super.fragmentShader(scope, ctx);
20
- let color = this.calculateAlbedoColor(scope, ctx);
21
+ fragmentShader(scope) {
22
+ super.fragmentShader(scope);
23
+ let color = this.calculateAlbedoColor(scope);
21
24
  if (this.vertexColor) {
22
- color = scope.$builder.mul(color, this.getVertexColor(scope, ctx));
25
+ color = scope.$builder.mul(color, this.getVertexColor(scope));
23
26
  }
24
- this.outputFragmentColor(scope, this.needFragmentColor(ctx) ? color : null, ctx);
27
+ this.outputFragmentColor(scope, scope.$inputs.worldPos, this.needFragmentColor() ? color : null);
25
28
  }
26
29
  }
27
30
 
@@ -1 +1 @@
1
- {"version":3,"file":"unlit.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"unlit.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,15 +2,17 @@ import { Application } from '../app.js';
2
2
  import { AbstractPostEffect } from './posteffect.js';
3
3
  import { Vector4, Vector2 } from '@zephyr3d/base';
4
4
  import '../scene/octree.js';
5
- import '../material/material.js';
6
- import '@zephyr3d/device';
7
- import '../shaders/framework.js';
8
- import '../render/scatteringlut.js';
5
+ import '../material/shader/helper.js';
9
6
  import '../material/lambert.js';
10
7
  import '../material/blinn.js';
11
8
  import '../material/unlit.js';
12
- import '../material/lightmodel.js';
13
- import '../render/forward.js';
9
+ import '../material/material.js';
10
+ import '../material/meshmaterial.js';
11
+ import '../material/grassmaterial.js';
12
+ import '../material/terrainmaterial.js';
13
+ import '../material/pbrmr.js';
14
+ import '../material/pbrsg.js';
15
+ import '../render/renderer.js';
14
16
  import '../render/sky.js';
15
17
  import '../render/clipmap.js';
16
18
  import { TemporalCache } from '../render/temporalcache.js';
@@ -1 +1 @@
1
- {"version":3,"file":"bloom.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"bloom.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,15 +2,17 @@ import { Application } from '../app.js';
2
2
  import { linearToGamma } from '../shaders/misc.js';
3
3
  import '@zephyr3d/base';
4
4
  import '../scene/octree.js';
5
- import '../material/material.js';
6
- import '@zephyr3d/device';
7
- import '../shaders/framework.js';
8
- import '../render/scatteringlut.js';
5
+ import '../material/shader/helper.js';
9
6
  import '../material/lambert.js';
10
7
  import '../material/blinn.js';
11
8
  import '../material/unlit.js';
12
- import '../material/lightmodel.js';
13
- import '../render/forward.js';
9
+ import '../material/material.js';
10
+ import '../material/meshmaterial.js';
11
+ import '../material/grassmaterial.js';
12
+ import '../material/terrainmaterial.js';
13
+ import '../material/pbrmr.js';
14
+ import '../material/pbrsg.js';
15
+ import '../render/renderer.js';
14
16
  import '../render/sky.js';
15
17
  import '../render/clipmap.js';
16
18
  import { TemporalCache } from '../render/temporalcache.js';
@@ -78,6 +80,12 @@ import '../render/watermesh.js';
78
80
  }
79
81
  }
80
82
  /**
83
+ * Removes all post effects
84
+ */ clear() {
85
+ this._postEffectsOpaque = [];
86
+ this._postEffectsTransparency = [];
87
+ }
88
+ /**
81
89
  * Gets all post effects
82
90
  */ getPostEffects() {
83
91
  return [
@@ -1 +1 @@
1
- {"version":3,"file":"compositor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"compositor.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { Application } from '../app.js';
2
- import { drawFullscreenQuad } from '../render/helper.js';
2
+ import { drawFullscreenQuad } from '../render/fullscreenquad.js';
3
3
 
4
4
  /**
5
5
  * Base class for any type of post effect
@@ -4,16 +4,19 @@ import { AbstractPostEffect } from './posteffect.js';
4
4
  import { decodeNormalizedFloatFromRGBA, encodeNormalizedFloatToRGBA } from '../shaders/misc.js';
5
5
  import { Vector2, Vector4, Matrix4x4 } from '@zephyr3d/base';
6
6
  import { AOBilateralBlurBlitter } from '../blitter/depthlimitedgaussion.js';
7
- import '../shaders/framework.js';
8
7
  import { CopyBlitter } from '../blitter/copy.js';
9
8
  import '../scene/octree.js';
10
- import '../material/material.js';
11
- import '../render/scatteringlut.js';
9
+ import '../material/shader/helper.js';
12
10
  import '../material/lambert.js';
13
11
  import '../material/blinn.js';
14
12
  import '../material/unlit.js';
15
- import '../material/lightmodel.js';
16
- import '../render/forward.js';
13
+ import '../material/material.js';
14
+ import '../material/meshmaterial.js';
15
+ import '../material/grassmaterial.js';
16
+ import '../material/terrainmaterial.js';
17
+ import '../material/pbrmr.js';
18
+ import '../material/pbrsg.js';
19
+ import '../render/renderer.js';
17
20
  import '../render/sky.js';
18
21
  import '../render/clipmap.js';
19
22
  import { TemporalCache } from '../render/temporalcache.js';
@@ -1 +1 @@
1
- {"version":3,"file":"sao.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"sao.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -68,12 +68,12 @@ import { linearToGamma } from '../shaders/misc.js';
68
68
  pb.vec3('v')
69
69
  ], function() {
70
70
  this.$l.a = pb.sub(pb.mul(this.v, pb.add(this.v, pb.vec3(0.0245786))), pb.vec3(0.000090537));
71
- this.$l.b = pb.add(pb.mul(this.v, pb.add(pb.mul(this.v, 0.983729), pb.vec3(0.4329510))), pb.vec3(0.238081));
71
+ this.$l.b = pb.add(pb.mul(this.v, pb.add(pb.mul(this.v, 0.983729), pb.vec3(0.432951))), pb.vec3(0.238081));
72
72
  this.$return(pb.div(this.a, this.b));
73
73
  });
74
74
  pb.main(function() {
75
75
  this.$l.vSample = pb.textureSample(this.tex, this.$inputs.uv);
76
- this.$l.ACESInputMat = pb.mat3(0.59719, 0.07600, 0.02840, 0.35458, 0.90834, 0.13383, 0.04823, 0.01566, 0.83777);
76
+ this.$l.ACESInputMat = pb.mat3(0.59719, 0.076, 0.0284, 0.35458, 0.90834, 0.13383, 0.04823, 0.01566, 0.83777);
77
77
  this.$l.ACESOutputMat = pb.mat3(1.60475, -0.10208, -0.00327, -0.53108, 1.10813, -0.07276, -0.07367, -0.00605, 1.07602);
78
78
  this.$l.color = pb.mul(this.vSample.rgb, pb.div(this.exposure, 0.6));
79
79
  this.color = pb.mul(this.ACESInputMat, this.color);