@zephyr3d/scene 0.1.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/animation/animation.js +173 -0
- package/dist/animation/animation.js.map +1 -0
- package/dist/animation/animationset.js +95 -0
- package/dist/animation/animationset.js.map +1 -0
- package/dist/animation/animationtrack.js +38 -0
- package/dist/animation/animationtrack.js.map +1 -0
- package/dist/animation/eulerrotationtrack.js +33 -0
- package/dist/animation/eulerrotationtrack.js.map +1 -0
- package/dist/animation/rotationtrack.js +37 -0
- package/dist/animation/rotationtrack.js.map +1 -0
- package/dist/animation/scaletrack.js +36 -0
- package/dist/animation/scaletrack.js.map +1 -0
- package/dist/animation/skeleton.js +97 -0
- package/dist/animation/skeleton.js.map +1 -0
- package/dist/animation/translationtrack.js +36 -0
- package/dist/animation/translationtrack.js.map +1 -0
- package/dist/animation/usertrack.js +47 -0
- package/dist/animation/usertrack.js.map +1 -0
- package/dist/app.js +173 -0
- package/dist/app.js.map +1 -0
- package/dist/asset/assetmanager.js +476 -0
- package/dist/asset/assetmanager.js.map +1 -0
- package/dist/asset/builtin.js +373 -0
- package/dist/asset/builtin.js.map +1 -0
- package/dist/asset/loaders/dds/dds.js +472 -0
- package/dist/asset/loaders/dds/dds.js.map +1 -0
- package/dist/asset/loaders/dds/dds_loader.js +38 -0
- package/dist/asset/loaders/dds/dds_loader.js.map +1 -0
- package/dist/asset/loaders/gltf/gltf_loader.js +981 -0
- package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -0
- package/dist/asset/loaders/gltf/helpers.js +314 -0
- package/dist/asset/loaders/gltf/helpers.js.map +1 -0
- package/dist/asset/loaders/hdr/hdr.js +175 -0
- package/dist/asset/loaders/hdr/hdr.js.map +1 -0
- package/dist/asset/loaders/image/tga_Loader.js +117 -0
- package/dist/asset/loaders/image/tga_Loader.js.map +1 -0
- package/dist/asset/loaders/image/webimage_loader.js +50 -0
- package/dist/asset/loaders/image/webimage_loader.js.map +1 -0
- package/dist/asset/loaders/loader.js +45 -0
- package/dist/asset/loaders/loader.js.map +1 -0
- package/dist/asset/model.js +264 -0
- package/dist/asset/model.js.map +1 -0
- package/dist/blitter/blitter.js +389 -0
- package/dist/blitter/blitter.js.map +1 -0
- package/dist/blitter/box.js +118 -0
- package/dist/blitter/box.js.map +1 -0
- package/dist/blitter/copy.js +22 -0
- package/dist/blitter/copy.js.map +1 -0
- package/dist/blitter/depthlimitedgaussion.js +166 -0
- package/dist/blitter/depthlimitedgaussion.js.map +1 -0
- package/dist/blitter/gaussianblur.js +229 -0
- package/dist/blitter/gaussianblur.js.map +1 -0
- package/dist/camera/base.js +90 -0
- package/dist/camera/base.js.map +1 -0
- package/dist/camera/camera.js +358 -0
- package/dist/camera/camera.js.map +1 -0
- package/dist/camera/fps.js +246 -0
- package/dist/camera/fps.js.map +1 -0
- package/dist/camera/orbit.js +157 -0
- package/dist/camera/orbit.js.map +1 -0
- package/dist/camera/orthocamera.js +126 -0
- package/dist/camera/orthocamera.js.map +1 -0
- package/dist/camera/perspectivecamera.js +133 -0
- package/dist/camera/perspectivecamera.js.map +1 -0
- package/dist/index.d.ts +8402 -0
- package/dist/index.js +87 -0
- package/dist/index.js.map +1 -0
- package/dist/input/inputmgr.js +242 -0
- package/dist/input/inputmgr.js.map +1 -0
- package/dist/material/blinn.js +75 -0
- package/dist/material/blinn.js.map +1 -0
- package/dist/material/grassmaterial.js +221 -0
- package/dist/material/grassmaterial.js.map +1 -0
- package/dist/material/lambert.js +52 -0
- package/dist/material/lambert.js.map +1 -0
- package/dist/material/lightmodel.js +2074 -0
- package/dist/material/lightmodel.js.map +1 -0
- package/dist/material/lit.js +578 -0
- package/dist/material/lit.js.map +1 -0
- package/dist/material/material.js +458 -0
- package/dist/material/material.js.map +1 -0
- package/dist/material/meshmaterial.js +311 -0
- package/dist/material/meshmaterial.js.map +1 -0
- package/dist/material/mixins/albedocolor.js +130 -0
- package/dist/material/mixins/albedocolor.js.map +1 -0
- package/dist/material/mixins/texture.js +110 -0
- package/dist/material/mixins/texture.js.map +1 -0
- package/dist/material/mixins/vertexcolor.js +45 -0
- package/dist/material/mixins/vertexcolor.js.map +1 -0
- package/dist/material/pbr.js +27 -0
- package/dist/material/pbr.js.map +1 -0
- package/dist/material/standard.js +282 -0
- package/dist/material/standard.js.map +1 -0
- package/dist/material/terrainlightmodel.js +259 -0
- package/dist/material/terrainlightmodel.js.map +1 -0
- package/dist/material/terrainmaterial.js +139 -0
- package/dist/material/terrainmaterial.js.map +1 -0
- package/dist/material/unlit.js +29 -0
- package/dist/material/unlit.js.map +1 -0
- package/dist/posteffect/bloom.js +398 -0
- package/dist/posteffect/bloom.js.map +1 -0
- package/dist/posteffect/compositor.js +264 -0
- package/dist/posteffect/compositor.js.map +1 -0
- package/dist/posteffect/fxaa.js +291 -0
- package/dist/posteffect/fxaa.js.map +1 -0
- package/dist/posteffect/grayscale.js +87 -0
- package/dist/posteffect/grayscale.js.map +1 -0
- package/dist/posteffect/posteffect.js +165 -0
- package/dist/posteffect/posteffect.js.map +1 -0
- package/dist/posteffect/sao.js +327 -0
- package/dist/posteffect/sao.js.map +1 -0
- package/dist/posteffect/tonemap.js +112 -0
- package/dist/posteffect/tonemap.js.map +1 -0
- package/dist/posteffect/water.js +535 -0
- package/dist/posteffect/water.js.map +1 -0
- package/dist/render/clipmap.js +462 -0
- package/dist/render/clipmap.js.map +1 -0
- package/dist/render/cluster_light.js +329 -0
- package/dist/render/cluster_light.js.map +1 -0
- package/dist/render/cull_visitor.js +124 -0
- package/dist/render/cull_visitor.js.map +1 -0
- package/dist/render/depth_pass.js +47 -0
- package/dist/render/depth_pass.js.map +1 -0
- package/dist/render/envlight.js +282 -0
- package/dist/render/envlight.js.map +1 -0
- package/dist/render/forward.js +186 -0
- package/dist/render/forward.js.map +1 -0
- package/dist/render/forward_pass.js +137 -0
- package/dist/render/forward_pass.js.map +1 -0
- package/dist/render/helper.js +38 -0
- package/dist/render/helper.js.map +1 -0
- package/dist/render/primitive.js +246 -0
- package/dist/render/primitive.js.map +1 -0
- package/dist/render/render_queue.js +163 -0
- package/dist/render/render_queue.js.map +1 -0
- package/dist/render/renderpass.js +151 -0
- package/dist/render/renderpass.js.map +1 -0
- package/dist/render/renderscheme.js +61 -0
- package/dist/render/renderscheme.js.map +1 -0
- package/dist/render/scatteringlut.js +634 -0
- package/dist/render/scatteringlut.js.map +1 -0
- package/dist/render/shadowmap_pass.js +70 -0
- package/dist/render/shadowmap_pass.js.map +1 -0
- package/dist/render/sky.js +881 -0
- package/dist/render/sky.js.map +1 -0
- package/dist/render/temporalcache.js +222 -0
- package/dist/render/temporalcache.js.map +1 -0
- package/dist/render/watermesh.js +835 -0
- package/dist/render/watermesh.js.map +1 -0
- package/dist/scene/environment.js +146 -0
- package/dist/scene/environment.js.map +1 -0
- package/dist/scene/graph_node.js +69 -0
- package/dist/scene/graph_node.js.map +1 -0
- package/dist/scene/light.js +436 -0
- package/dist/scene/light.js.map +1 -0
- package/dist/scene/mesh.js +215 -0
- package/dist/scene/mesh.js.map +1 -0
- package/dist/scene/model.js +111 -0
- package/dist/scene/model.js.map +1 -0
- package/dist/scene/octree.js +651 -0
- package/dist/scene/octree.js.map +1 -0
- package/dist/scene/octree_update_visitor.js +16 -0
- package/dist/scene/octree_update_visitor.js.map +1 -0
- package/dist/scene/raycast_visitor.js +72 -0
- package/dist/scene/raycast_visitor.js.map +1 -0
- package/dist/scene/scene.js +225 -0
- package/dist/scene/scene.js.map +1 -0
- package/dist/scene/scene_node.js +299 -0
- package/dist/scene/scene_node.js.map +1 -0
- package/dist/scene/terrain/grass.js +277 -0
- package/dist/scene/terrain/grass.js.map +1 -0
- package/dist/scene/terrain/heightfield.js +391 -0
- package/dist/scene/terrain/heightfield.js.map +1 -0
- package/dist/scene/terrain/patch.js +530 -0
- package/dist/scene/terrain/patch.js.map +1 -0
- package/dist/scene/terrain/quadtree.js +430 -0
- package/dist/scene/terrain/quadtree.js.map +1 -0
- package/dist/scene/terrain/terrain.js +258 -0
- package/dist/scene/terrain/terrain.js.map +1 -0
- package/dist/scene/xform.js +224 -0
- package/dist/scene/xform.js.map +1 -0
- package/dist/shaders/builtins.js +110 -0
- package/dist/shaders/builtins.js.map +1 -0
- package/dist/shaders/framework.js +709 -0
- package/dist/shaders/framework.js.map +1 -0
- package/dist/shaders/lighting.js +335 -0
- package/dist/shaders/lighting.js.map +1 -0
- package/dist/shaders/misc.js +405 -0
- package/dist/shaders/misc.js.map +1 -0
- package/dist/shaders/noise.js +157 -0
- package/dist/shaders/noise.js.map +1 -0
- package/dist/shaders/pbr.js +132 -0
- package/dist/shaders/pbr.js.map +1 -0
- package/dist/shaders/shadow.js +642 -0
- package/dist/shaders/shadow.js.map +1 -0
- package/dist/shaders/water.js +630 -0
- package/dist/shaders/water.js.map +1 -0
- package/dist/shadow/esm.js +235 -0
- package/dist/shadow/esm.js.map +1 -0
- package/dist/shadow/pcf_opt.js +182 -0
- package/dist/shadow/pcf_opt.js.map +1 -0
- package/dist/shadow/pcf_pd.js +190 -0
- package/dist/shadow/pcf_pd.js.map +1 -0
- package/dist/shadow/shadow_impl.js +15 -0
- package/dist/shadow/shadow_impl.js.map +1 -0
- package/dist/shadow/shadowmapper.js +709 -0
- package/dist/shadow/shadowmapper.js.map +1 -0
- package/dist/shadow/ssm.js +194 -0
- package/dist/shadow/ssm.js.map +1 -0
- package/dist/shadow/vsm.js +298 -0
- package/dist/shadow/vsm.js.map +1 -0
- package/dist/shapes/box.js +313 -0
- package/dist/shapes/box.js.map +1 -0
- package/dist/shapes/cylinder.js +74 -0
- package/dist/shapes/cylinder.js.map +1 -0
- package/dist/shapes/plane.js +48 -0
- package/dist/shapes/plane.js.map +1 -0
- package/dist/shapes/shape.js +33 -0
- package/dist/shapes/shape.js.map +1 -0
- package/dist/shapes/sphere.js +91 -0
- package/dist/shapes/sphere.js.map +1 -0
- package/dist/shapes/torus.js +100 -0
- package/dist/shapes/torus.js.map +1 -0
- package/dist/utility/aabbtree.js +390 -0
- package/dist/utility/aabbtree.js.map +1 -0
- package/dist/utility/bounding_volume.js +78 -0
- package/dist/utility/bounding_volume.js.map +1 -0
- package/dist/utility/panorama.js +163 -0
- package/dist/utility/panorama.js.map +1 -0
- package/dist/utility/pmrem.js +345 -0
- package/dist/utility/pmrem.js.map +1 -0
- package/dist/utility/shprojection.js +448 -0
- package/dist/utility/shprojection.js.map +1 -0
- package/dist/values.js +48 -0
- package/dist/values.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
import { Application } from '../app.js';
|
|
2
|
+
import { Vector3 } from '@zephyr3d/base';
|
|
3
|
+
|
|
4
|
+
class ScatteringLut {
|
|
5
|
+
static _groundAlbedo = 1.0;
|
|
6
|
+
static _groundRadiusMM = 6.36;
|
|
7
|
+
static _atmosphereRadiusMM = 6.46;
|
|
8
|
+
static _scatteringSteps = 32;
|
|
9
|
+
static _sunTransmittanceSteps = 40;
|
|
10
|
+
static _rayleighScatteringBase = [
|
|
11
|
+
5.802,
|
|
12
|
+
13.558,
|
|
13
|
+
33.1
|
|
14
|
+
];
|
|
15
|
+
static _rayleighAbsorptionBase = 0;
|
|
16
|
+
static _mieScatteringBase = 3.996;
|
|
17
|
+
static _mieAbsorptionBase = 4.4;
|
|
18
|
+
static _ozoneAbsorptionBase = [
|
|
19
|
+
0.65,
|
|
20
|
+
1.881,
|
|
21
|
+
0.085
|
|
22
|
+
];
|
|
23
|
+
static _multiScatteringSteps = 20;
|
|
24
|
+
static _sqrtSamples = 8;
|
|
25
|
+
static _transmittanceLutWidth = 256;
|
|
26
|
+
static _transmittanceLutHeight = 64;
|
|
27
|
+
static _multiScatteringLutWidth = 32;
|
|
28
|
+
static _multiScatteringLutHeight = 32;
|
|
29
|
+
static _skyViewLutWidth = 256;
|
|
30
|
+
static _skyViewLutHeight = 256;
|
|
31
|
+
static _vertexLayout = null;
|
|
32
|
+
static _renderStates = null;
|
|
33
|
+
static _programTransmittanceLut = null;
|
|
34
|
+
static _bindgroupTransmittanceLut = null;
|
|
35
|
+
static _programMultiScatteringLut = null;
|
|
36
|
+
static _bindgroupMultiScatteringLut = null;
|
|
37
|
+
static _programSkyViewLut = null;
|
|
38
|
+
static _bindgroupSkyViewLut = null;
|
|
39
|
+
static _transmittanceLut = null;
|
|
40
|
+
static _multiScatteringLut = null;
|
|
41
|
+
static _skyViewFramebuffer = null;
|
|
42
|
+
static _programAerialPerspectiveLut = null;
|
|
43
|
+
static _bindgroupAerialPerspectiveLut = null;
|
|
44
|
+
static _aerialPerspectiveLut = null;
|
|
45
|
+
static _currentSkyViewSunAltitude = 0;
|
|
46
|
+
static _currentAerialPerspectiveAltitude = 0;
|
|
47
|
+
static _currentMaxAerialPerspectiveDistance = 800;
|
|
48
|
+
static _aerialPerspectiveSliceX = 32;
|
|
49
|
+
static _aerialPerspectiveSliceY = 32;
|
|
50
|
+
static _aerialPerspectiveSliceZ = 32;
|
|
51
|
+
static _aerialPerspectiveTextureWidth = this._aerialPerspectiveSliceX * this._aerialPerspectiveSliceZ;
|
|
52
|
+
static _aerialPerspectiveTextureHeight = this._aerialPerspectiveSliceY;
|
|
53
|
+
static _viewPos = new Vector3(0.0, this._groundRadiusMM + 0.00005, 0.0);
|
|
54
|
+
static get aerialPerspectiveSliceZ() {
|
|
55
|
+
return this._aerialPerspectiveSliceZ;
|
|
56
|
+
}
|
|
57
|
+
static get groundRadius() {
|
|
58
|
+
return this._groundRadiusMM;
|
|
59
|
+
}
|
|
60
|
+
static get atmosphereRadius() {
|
|
61
|
+
return this._atmosphereRadiusMM;
|
|
62
|
+
}
|
|
63
|
+
static get viewPosition() {
|
|
64
|
+
return this._viewPos;
|
|
65
|
+
}
|
|
66
|
+
static getMultiScatteringLut() {
|
|
67
|
+
const device = Application.instance.device;
|
|
68
|
+
if (!this._multiScatteringLut) {
|
|
69
|
+
this.prepare(device);
|
|
70
|
+
const format = device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? 'rgba16f' : 'rgba8unorm';
|
|
71
|
+
this._multiScatteringLut = device.createTexture2D(format, this._multiScatteringLutWidth, this._multiScatteringLutHeight, {
|
|
72
|
+
samplerOptions: {
|
|
73
|
+
mipFilter: 'none'
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
this._multiScatteringLut.name = 'MultiScatteringLUT';
|
|
77
|
+
const tLut = this.getTransmittanceLut();
|
|
78
|
+
const tempFramebuffer = device.createFrameBuffer([
|
|
79
|
+
this._multiScatteringLut
|
|
80
|
+
], null);
|
|
81
|
+
device.pushDeviceStates();
|
|
82
|
+
device.setFramebuffer(tempFramebuffer);
|
|
83
|
+
device.setProgram(this._programMultiScatteringLut);
|
|
84
|
+
device.setBindGroup(0, this._bindgroupMultiScatteringLut);
|
|
85
|
+
this._bindgroupMultiScatteringLut.setValue('flip', device.type === 'webgpu' ? 1 : 0);
|
|
86
|
+
this._bindgroupMultiScatteringLut.setTexture('tLut', tLut);
|
|
87
|
+
this.drawQuad(device);
|
|
88
|
+
device.popDeviceStates();
|
|
89
|
+
tempFramebuffer.dispose();
|
|
90
|
+
}
|
|
91
|
+
return this._multiScatteringLut;
|
|
92
|
+
}
|
|
93
|
+
static getAerialPerspectiveLut(sunAltitude, maxDistance) {
|
|
94
|
+
const device = Application.instance.device;
|
|
95
|
+
if (sunAltitude !== this._currentAerialPerspectiveAltitude || maxDistance !== this._currentMaxAerialPerspectiveDistance || !this._aerialPerspectiveLut) {
|
|
96
|
+
if (!this._aerialPerspectiveLut) {
|
|
97
|
+
const format = device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? 'rgba16f' : 'rgba8unorm';
|
|
98
|
+
if (!this._aerialPerspectiveLut) {
|
|
99
|
+
this._aerialPerspectiveLut = device.createTexture2D(format, this._aerialPerspectiveTextureWidth, this._aerialPerspectiveTextureHeight, {
|
|
100
|
+
samplerOptions: {
|
|
101
|
+
mipFilter: 'none'
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
this._aerialPerspectiveLut.name = 'AerialPerspectiveLUT';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const fb = device.createFrameBuffer([
|
|
108
|
+
this._aerialPerspectiveLut
|
|
109
|
+
], null);
|
|
110
|
+
const tLut = this.getTransmittanceLut();
|
|
111
|
+
const msLut = this.getMultiScatteringLut();
|
|
112
|
+
this._currentAerialPerspectiveAltitude = sunAltitude;
|
|
113
|
+
this._currentMaxAerialPerspectiveDistance = maxDistance;
|
|
114
|
+
device.pushDeviceStates();
|
|
115
|
+
device.setFramebuffer(fb);
|
|
116
|
+
device.setProgram(this._programAerialPerspectiveLut);
|
|
117
|
+
device.setBindGroup(0, this._bindgroupAerialPerspectiveLut);
|
|
118
|
+
this._bindgroupAerialPerspectiveLut.setValue('flip', device.type === 'webgpu' ? 1 : 0);
|
|
119
|
+
this._bindgroupAerialPerspectiveLut.setValue('sunAltitude', this._currentAerialPerspectiveAltitude);
|
|
120
|
+
this._bindgroupAerialPerspectiveLut.setValue('maxDistance', this._currentMaxAerialPerspectiveDistance);
|
|
121
|
+
this._bindgroupAerialPerspectiveLut.setTexture('tLut', tLut);
|
|
122
|
+
this._bindgroupAerialPerspectiveLut.setTexture('msLut', msLut);
|
|
123
|
+
this.drawQuad(device);
|
|
124
|
+
device.popDeviceStates();
|
|
125
|
+
fb.dispose();
|
|
126
|
+
}
|
|
127
|
+
return this._aerialPerspectiveLut;
|
|
128
|
+
}
|
|
129
|
+
static getSkyViewLut(sunAltitude) {
|
|
130
|
+
const device = Application.instance.device;
|
|
131
|
+
if (sunAltitude !== this._currentSkyViewSunAltitude || !this._skyViewFramebuffer) {
|
|
132
|
+
if (!this._skyViewFramebuffer) {
|
|
133
|
+
const format = device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? 'rgba16f' : 'rgba8unorm';
|
|
134
|
+
const skyViewLut = device.createTexture2D(format, this._skyViewLutWidth, this._skyViewLutHeight, {
|
|
135
|
+
samplerOptions: {
|
|
136
|
+
mipFilter: 'none'
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
skyViewLut.name = 'SkyViewLut';
|
|
140
|
+
this._skyViewFramebuffer = device.createFrameBuffer([
|
|
141
|
+
skyViewLut
|
|
142
|
+
], null);
|
|
143
|
+
}
|
|
144
|
+
const tLut = this.getTransmittanceLut();
|
|
145
|
+
const msLut = this.getMultiScatteringLut();
|
|
146
|
+
this._currentSkyViewSunAltitude = sunAltitude;
|
|
147
|
+
device.pushDeviceStates();
|
|
148
|
+
device.setFramebuffer(this._skyViewFramebuffer);
|
|
149
|
+
device.setProgram(this._programSkyViewLut);
|
|
150
|
+
device.setBindGroup(0, this._bindgroupSkyViewLut);
|
|
151
|
+
this._bindgroupSkyViewLut.setValue('flip', device.type === 'webgpu' ? 1 : 0);
|
|
152
|
+
this._bindgroupSkyViewLut.setValue('sunAltitude', this._currentSkyViewSunAltitude);
|
|
153
|
+
this._bindgroupSkyViewLut.setTexture('tLut', tLut);
|
|
154
|
+
this._bindgroupSkyViewLut.setTexture('msLut', msLut);
|
|
155
|
+
this.drawQuad(device);
|
|
156
|
+
device.popDeviceStates();
|
|
157
|
+
}
|
|
158
|
+
return this._skyViewFramebuffer.getColorAttachments()[0];
|
|
159
|
+
}
|
|
160
|
+
static getTransmittanceLut() {
|
|
161
|
+
const device = Application.instance.device;
|
|
162
|
+
if (!this._transmittanceLut) {
|
|
163
|
+
this.prepare(device);
|
|
164
|
+
const format = device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? 'rgba16f' : 'rgba8unorm';
|
|
165
|
+
this._transmittanceLut = device.createTexture2D(format, this._transmittanceLutWidth, this._transmittanceLutHeight, {
|
|
166
|
+
samplerOptions: {
|
|
167
|
+
mipFilter: 'none'
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
this._transmittanceLut.name = 'TransmittanceLUT';
|
|
171
|
+
const tempFramebuffer = device.createFrameBuffer([
|
|
172
|
+
this._transmittanceLut
|
|
173
|
+
], null);
|
|
174
|
+
device.pushDeviceStates();
|
|
175
|
+
device.setFramebuffer(tempFramebuffer);
|
|
176
|
+
device.setProgram(this._programTransmittanceLut);
|
|
177
|
+
device.setBindGroup(0, this._bindgroupTransmittanceLut);
|
|
178
|
+
this._bindgroupTransmittanceLut.setValue('flip', device.type === 'webgpu' ? 1 : 0);
|
|
179
|
+
this.drawQuad(device);
|
|
180
|
+
device.popDeviceStates();
|
|
181
|
+
tempFramebuffer.dispose();
|
|
182
|
+
}
|
|
183
|
+
return this._transmittanceLut;
|
|
184
|
+
}
|
|
185
|
+
static drawQuad(device) {
|
|
186
|
+
const lastRenderState = device.getRenderStates();
|
|
187
|
+
device.setRenderStates(this._renderStates);
|
|
188
|
+
device.setVertexLayout(this._vertexLayout);
|
|
189
|
+
device.draw('triangle-strip', 0, 4);
|
|
190
|
+
device.setRenderStates(lastRenderState);
|
|
191
|
+
}
|
|
192
|
+
static commonVertexShader() {
|
|
193
|
+
const pb = this.$builder;
|
|
194
|
+
this.flip = pb.int().uniform(0);
|
|
195
|
+
this.$inputs.pos = pb.vec2().attrib('position');
|
|
196
|
+
this.$outputs.uv = pb.vec2();
|
|
197
|
+
pb.main(function() {
|
|
198
|
+
this.$builtins.position = pb.vec4(this.$inputs.pos, 0, 1);
|
|
199
|
+
this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));
|
|
200
|
+
this.$if(pb.notEqual(this.flip, 0), function() {
|
|
201
|
+
this.$builtins.position.y = pb.neg(this.$builtins.position.y);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
static commonFunctions() {
|
|
206
|
+
const pb = this.$builder;
|
|
207
|
+
this.viewPos = pb.vec3(ScatteringLut._viewPos.x, ScatteringLut._viewPos.y, ScatteringLut._viewPos.z);
|
|
208
|
+
pb.func('getMiePhase', [
|
|
209
|
+
pb.float('cosTheta')
|
|
210
|
+
], function() {
|
|
211
|
+
this.$l.g = pb.float(0.8);
|
|
212
|
+
this.$l.scale = pb.float(3 / (Math.PI * 8));
|
|
213
|
+
this.$l.gg = pb.mul(this.g, this.g);
|
|
214
|
+
this.$l.num = pb.mul(pb.sub(1, this.gg), pb.add(pb.mul(this.cosTheta, this.cosTheta), 1));
|
|
215
|
+
this.$l.denom = pb.mul(pb.add(2, this.gg), pb.pow(pb.sub(pb.add(1, this.gg), pb.mul(this.g, this.cosTheta, 2)), 1.5));
|
|
216
|
+
this.$return(pb.div(pb.mul(this.scale, this.num), this.denom));
|
|
217
|
+
});
|
|
218
|
+
pb.func('getRayleighPhase', [
|
|
219
|
+
pb.float('cosTheta')
|
|
220
|
+
], function() {
|
|
221
|
+
this.$l.k = pb.float(3 / (Math.PI * 16));
|
|
222
|
+
this.$return(pb.mul(this.k, pb.add(1, pb.mul(this.cosTheta, this.cosTheta))));
|
|
223
|
+
});
|
|
224
|
+
pb.func('rayIntersectSphere', [
|
|
225
|
+
pb.vec3('ro'),
|
|
226
|
+
pb.vec3('rd'),
|
|
227
|
+
pb.float('rad')
|
|
228
|
+
], function() {
|
|
229
|
+
this.$l.b = pb.dot(this.ro, this.rd);
|
|
230
|
+
this.$l.c = pb.sub(pb.dot(this.ro, this.ro), pb.mul(this.rad, this.rad));
|
|
231
|
+
this.$if(pb.and(pb.greaterThan(this.c, 0), pb.greaterThan(this.b, 0)), function() {
|
|
232
|
+
this.$return(pb.float(-1));
|
|
233
|
+
});
|
|
234
|
+
this.$l.bb = pb.mul(this.b, this.b);
|
|
235
|
+
this.$l.discr = pb.sub(this.bb, this.c);
|
|
236
|
+
this.$if(pb.lessThan(this.discr, 0), function() {
|
|
237
|
+
this.$return(pb.float(-1));
|
|
238
|
+
});
|
|
239
|
+
this.$if(pb.greaterThan(this.discr, this.bb), function() {
|
|
240
|
+
this.$return(pb.sub(pb.sqrt(this.discr), this.b));
|
|
241
|
+
});
|
|
242
|
+
this.$return(pb.sub(pb.neg(pb.sqrt(this.discr)), this.b));
|
|
243
|
+
});
|
|
244
|
+
pb.func('getScatteringValues', [
|
|
245
|
+
pb.vec3('pos'),
|
|
246
|
+
pb.vec3('rayleighScattering').out(),
|
|
247
|
+
pb.float('mieScattering').out(),
|
|
248
|
+
pb.vec3('extinction').out()
|
|
249
|
+
], function() {
|
|
250
|
+
this.$l.altitudeKM = pb.mul(pb.sub(pb.length(this.pos), ScatteringLut._groundRadiusMM), 1000);
|
|
251
|
+
this.$l.rayleighDensity = pb.exp(pb.div(this.altitudeKM, -8));
|
|
252
|
+
this.$l.mieDensity = pb.exp(pb.div(this.altitudeKM, -1.2));
|
|
253
|
+
this.rayleighScattering = pb.mul(pb.vec3(...ScatteringLut._rayleighScatteringBase), this.rayleighDensity);
|
|
254
|
+
this.$l.rayleighAbsorption = pb.mul(ScatteringLut._rayleighAbsorptionBase, this.rayleighDensity);
|
|
255
|
+
this.mieScattering = pb.mul(ScatteringLut._mieScatteringBase, this.mieDensity);
|
|
256
|
+
this.$l.mieAbsorption = pb.mul(ScatteringLut._mieAbsorptionBase, this.mieDensity);
|
|
257
|
+
this.$l.ozoneAbsorption = pb.mul(pb.vec3(...ScatteringLut._ozoneAbsorptionBase), pb.max(0, pb.sub(1, pb.div(pb.abs(pb.sub(this.altitudeKM, 25)), 15))));
|
|
258
|
+
this.extinction = pb.add(this.rayleighScattering, pb.vec3(this.rayleighAbsorption), pb.vec3(this.mieScattering), pb.vec3(this.mieAbsorption), this.ozoneAbsorption);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
static prepare(device) {
|
|
262
|
+
const that = this;
|
|
263
|
+
if (!this._vertexLayout) {
|
|
264
|
+
this._vertexLayout = device.createVertexLayout({
|
|
265
|
+
vertexBuffers: [
|
|
266
|
+
{
|
|
267
|
+
buffer: device.createVertexBuffer('position_f32x2', new Float32Array([
|
|
268
|
+
-1,
|
|
269
|
+
-1,
|
|
270
|
+
1,
|
|
271
|
+
-1,
|
|
272
|
+
-1,
|
|
273
|
+
1,
|
|
274
|
+
1,
|
|
275
|
+
1
|
|
276
|
+
]))
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
if (!this._renderStates) {
|
|
282
|
+
this._renderStates = device.createRenderStateSet();
|
|
283
|
+
this._renderStates.useRasterizerState().setCullMode('none');
|
|
284
|
+
this._renderStates.useDepthState().enableTest(false).enableWrite(false);
|
|
285
|
+
}
|
|
286
|
+
if (!this._programAerialPerspectiveLut) {
|
|
287
|
+
this._programAerialPerspectiveLut = device.buildRenderProgram({
|
|
288
|
+
vertex (pb) {
|
|
289
|
+
that.commonVertexShader.call(this);
|
|
290
|
+
},
|
|
291
|
+
fragment (pb) {
|
|
292
|
+
this.$outputs.outColor = pb.vec4();
|
|
293
|
+
this.sunAltitude = pb.float().uniform(0);
|
|
294
|
+
this.tLut = pb.tex2D().uniform(0);
|
|
295
|
+
this.msLut = pb.tex2D().uniform(0);
|
|
296
|
+
this.maxDistance = pb.float().uniform(0);
|
|
297
|
+
that.commonFunctions.call(this);
|
|
298
|
+
pb.func('getValFromTLUT', [
|
|
299
|
+
pb.vec3('pos'),
|
|
300
|
+
pb.vec3('sunDir')
|
|
301
|
+
], function() {
|
|
302
|
+
this.$l.height = pb.length(this.pos);
|
|
303
|
+
this.$l.up = pb.div(this.pos, this.height);
|
|
304
|
+
this.$l.sunCosZenithAngle = pb.dot(this.sunDir, this.up);
|
|
305
|
+
this.$l.uv = pb.vec2(pb.clamp(pb.add(0.5, pb.mul(this.sunCosZenithAngle, 0.5)), 0, 1), pb.max(0, pb.min(1, pb.div(pb.sub(this.height, that._groundRadiusMM), pb.sub(that._atmosphereRadiusMM, that._groundRadiusMM)))));
|
|
306
|
+
this.$return(pb.textureSampleLevel(this.tLut, this.uv, 0).rgb);
|
|
307
|
+
});
|
|
308
|
+
pb.func('getValFromMSLUT', [
|
|
309
|
+
pb.vec3('pos'),
|
|
310
|
+
pb.vec3('sunDir')
|
|
311
|
+
], function() {
|
|
312
|
+
this.$l.height = pb.length(this.pos);
|
|
313
|
+
this.$l.up = pb.div(this.pos, this.height);
|
|
314
|
+
this.$l.sunCosZenithAngle = pb.dot(this.sunDir, this.up);
|
|
315
|
+
this.$l.uv = pb.vec2(pb.clamp(pb.add(0.5, pb.mul(this.sunCosZenithAngle, 0.5)), 0, 1), pb.max(0, pb.min(1, pb.div(pb.sub(this.height, that._groundRadiusMM), pb.sub(that._atmosphereRadiusMM, that._groundRadiusMM)))));
|
|
316
|
+
this.$return(pb.textureSampleLevel(this.msLut, this.uv, 0).rgb);
|
|
317
|
+
});
|
|
318
|
+
pb.func('raymarchScattering', [
|
|
319
|
+
pb.vec3('pos'),
|
|
320
|
+
pb.vec3('rayDir'),
|
|
321
|
+
pb.vec3('sunDir'),
|
|
322
|
+
pb.float('tMax')
|
|
323
|
+
], function() {
|
|
324
|
+
this.$l.cosTheta = pb.dot(this.rayDir, this.sunDir);
|
|
325
|
+
this.$l.miePhaseValue = this.getMiePhase(this.cosTheta);
|
|
326
|
+
this.$l.rayleighPhaseValue = this.getRayleighPhase(pb.neg(this.cosTheta));
|
|
327
|
+
this.$l.lum = pb.vec3(0);
|
|
328
|
+
this.$l.transmittance = pb.vec3(1);
|
|
329
|
+
this.$l.t = pb.float(0);
|
|
330
|
+
this.$for(pb.int('i'), 0, that._scatteringSteps, function() {
|
|
331
|
+
this.$l.newT = pb.mul(pb.div(pb.add(pb.float(this.i), 0.3), that._scatteringSteps), this.tMax);
|
|
332
|
+
this.$l.dt = pb.sub(this.newT, this.t);
|
|
333
|
+
this.t = this.newT;
|
|
334
|
+
this.$l.newPos = pb.add(this.pos, pb.mul(this.rayDir, this.t));
|
|
335
|
+
this.$l.rayleighScattering = pb.vec3();
|
|
336
|
+
this.$l.extinction = pb.vec3();
|
|
337
|
+
this.$l.mieScattering = pb.float();
|
|
338
|
+
this.getScatteringValues(this.newPos, this.rayleighScattering, this.mieScattering, this.extinction);
|
|
339
|
+
this.$l.sampleTransmittance = pb.exp(pb.mul(pb.neg(this.dt), this.extinction));
|
|
340
|
+
this.$l.sunTransmittance = this.getValFromTLUT(this.newPos, this.sunDir);
|
|
341
|
+
this.$l.psiMS = this.getValFromMSLUT(this.newPos, this.sunDir);
|
|
342
|
+
this.$l.rayleighInScattering = pb.mul(this.rayleighScattering, pb.add(pb.mul(this.sunTransmittance, this.rayleighPhaseValue), this.psiMS));
|
|
343
|
+
this.$l.mieInScattering = pb.mul(pb.add(pb.mul(this.sunTransmittance, this.miePhaseValue), this.psiMS), this.mieScattering);
|
|
344
|
+
this.$l.inScattering = pb.add(this.rayleighInScattering, this.mieInScattering);
|
|
345
|
+
this.$l.scatteringIntegral = pb.div(pb.sub(this.inScattering, pb.mul(this.inScattering, this.sampleTransmittance)), this.extinction);
|
|
346
|
+
this.lum = pb.add(this.lum, pb.mul(this.scatteringIntegral, this.transmittance));
|
|
347
|
+
this.transmittance = pb.mul(this.transmittance, this.sampleTransmittance);
|
|
348
|
+
});
|
|
349
|
+
this.$return(this.lum);
|
|
350
|
+
});
|
|
351
|
+
pb.main(function() {
|
|
352
|
+
this.$l.slice = pb.clamp(pb.floor(pb.div(this.$inputs.uv.x, 1 / ScatteringLut._aerialPerspectiveSliceZ)), 0, pb.sub(ScatteringLut._aerialPerspectiveSliceZ, 1));
|
|
353
|
+
this.$l.sliceU = pb.clamp(pb.div(pb.sub(this.$inputs.uv.x, pb.mul(this.slice, 1 / ScatteringLut._aerialPerspectiveSliceZ)), 1 / ScatteringLut._aerialPerspectiveSliceZ), 0, 1);
|
|
354
|
+
this.$l.horizonAngle = pb.sub(pb.mul(this.sliceU, Math.PI * 2), Math.PI);
|
|
355
|
+
this.$l.zenithAngle = pb.mul(this.$inputs.uv.y, Math.PI / 2);
|
|
356
|
+
/*
|
|
357
|
+
this.$l.rayDir = pb.vec3(pb.mul(this.cosAltitude, pb.sin(this.azimuthAngle)), pb.sin(this.altitudeAngle), pb.mul(pb.neg(this.cosAltitude), pb.cos(this.azimuthAngle)));
|
|
358
|
+
this.$l.sunDir = pb.vec3(0, pb.sin(this.sunAltitude), pb.neg(pb.cos(this.sunAltitude)));
|
|
359
|
+
*/ this.$l.rayDir = pb.vec3(pb.mul(pb.cos(this.zenithAngle), pb.sin(this.horizonAngle)), pb.sin(this.zenithAngle), pb.mul(pb.neg(pb.cos(this.zenithAngle)), pb.cos(this.horizonAngle)));
|
|
360
|
+
this.$l.atmoDist = this.rayIntersectSphere(this.viewPos, this.rayDir, ScatteringLut._atmosphereRadiusMM);
|
|
361
|
+
this.$l.groundDist = this.rayIntersectSphere(this.viewPos, this.rayDir, ScatteringLut._groundRadiusMM);
|
|
362
|
+
this.$l.tMax = pb.float();
|
|
363
|
+
this.$if(pb.lessThan(this.groundDist, 0), function() {
|
|
364
|
+
this.tMax = this.atmoDist;
|
|
365
|
+
}).$else(function() {
|
|
366
|
+
this.tMax = this.groundDist;
|
|
367
|
+
});
|
|
368
|
+
this.tMax = this.atmoDist;
|
|
369
|
+
this.$l.maxDistanceMM = pb.mul(this.maxDistance, 1e-6);
|
|
370
|
+
this.$l.sliceDist = pb.mul(this.maxDistanceMM, pb.div(this.slice, ScatteringLut._aerialPerspectiveSliceZ));
|
|
371
|
+
this.tMax = pb.min(this.tMax, this.sliceDist);
|
|
372
|
+
this.$l.sunDir = pb.vec3(0, pb.sin(this.sunAltitude), pb.neg(pb.cos(this.sunAltitude)));
|
|
373
|
+
this.$l.lum = this.raymarchScattering(this.viewPos, this.rayDir, this.sunDir, this.tMax);
|
|
374
|
+
const heightKM = (that._viewPos.y - that._groundRadiusMM) * 1000;
|
|
375
|
+
const rayleighDensity = Math.exp(-heightKM / 8);
|
|
376
|
+
const mieDensity = Math.exp(-heightKM / 1.2);
|
|
377
|
+
this.$l.extinction = pb.vec3(-((that._rayleighScatteringBase[0] + that._rayleighAbsorptionBase) * rayleighDensity + (that._mieScatteringBase + that._mieAbsorptionBase) * mieDensity), -((that._rayleighScatteringBase[1] + that._rayleighAbsorptionBase) * rayleighDensity + (that._mieScatteringBase + that._mieAbsorptionBase) * mieDensity), -((that._rayleighScatteringBase[2] + that._rayleighAbsorptionBase) * rayleighDensity + (that._mieScatteringBase + that._mieAbsorptionBase) * mieDensity));
|
|
378
|
+
this.$l.t = pb.exp(pb.mul(this.extinction, this.tMax));
|
|
379
|
+
this.$outputs.outColor = pb.vec4(this.lum, pb.dot(this.t, pb.vec3(1 / 3, 1 / 3, 1 / 3)));
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
this._bindgroupAerialPerspectiveLut = device.createBindGroup(this._programAerialPerspectiveLut.bindGroupLayouts[0]);
|
|
384
|
+
}
|
|
385
|
+
if (!this._programSkyViewLut) {
|
|
386
|
+
this._programSkyViewLut = device.buildRenderProgram({
|
|
387
|
+
vertex (pb) {
|
|
388
|
+
that.commonVertexShader.call(this);
|
|
389
|
+
},
|
|
390
|
+
fragment (pb) {
|
|
391
|
+
this.$outputs.outColor = pb.vec4();
|
|
392
|
+
this.sunAltitude = pb.float().uniform(0);
|
|
393
|
+
this.tLut = pb.tex2D().uniform(0);
|
|
394
|
+
this.msLut = pb.tex2D().uniform(0);
|
|
395
|
+
that.commonFunctions.call(this);
|
|
396
|
+
pb.func('getValFromTLUT', [
|
|
397
|
+
pb.vec3('pos'),
|
|
398
|
+
pb.vec3('sunDir')
|
|
399
|
+
], function() {
|
|
400
|
+
this.$l.height = pb.length(this.pos);
|
|
401
|
+
this.$l.up = pb.div(this.pos, this.height);
|
|
402
|
+
this.$l.sunCosZenithAngle = pb.dot(this.sunDir, this.up);
|
|
403
|
+
this.$l.uv = pb.vec2(pb.clamp(pb.add(0.5, pb.mul(this.sunCosZenithAngle, 0.5)), 0, 1), pb.max(0, pb.min(1, pb.div(pb.sub(this.height, that._groundRadiusMM), pb.sub(that._atmosphereRadiusMM, that._groundRadiusMM)))));
|
|
404
|
+
this.$return(pb.textureSampleLevel(this.tLut, this.uv, 0).rgb);
|
|
405
|
+
});
|
|
406
|
+
pb.func('getValFromMSLUT', [
|
|
407
|
+
pb.vec3('pos'),
|
|
408
|
+
pb.vec3('sunDir')
|
|
409
|
+
], function() {
|
|
410
|
+
this.$l.height = pb.length(this.pos);
|
|
411
|
+
this.$l.up = pb.div(this.pos, this.height);
|
|
412
|
+
this.$l.sunCosZenithAngle = pb.dot(this.sunDir, this.up);
|
|
413
|
+
this.$l.uv = pb.vec2(pb.clamp(pb.add(0.5, pb.mul(this.sunCosZenithAngle, 0.5)), 0, 1), pb.max(0, pb.min(1, pb.div(pb.sub(this.height, that._groundRadiusMM), pb.sub(that._atmosphereRadiusMM, that._groundRadiusMM)))));
|
|
414
|
+
this.$return(pb.textureSampleLevel(this.msLut, this.uv, 0).rgb);
|
|
415
|
+
});
|
|
416
|
+
pb.func('raymarchScattering', [
|
|
417
|
+
pb.vec3('pos'),
|
|
418
|
+
pb.vec3('rayDir'),
|
|
419
|
+
pb.vec3('sunDir'),
|
|
420
|
+
pb.float('tMax')
|
|
421
|
+
], function() {
|
|
422
|
+
this.$l.cosTheta = pb.dot(this.rayDir, this.sunDir);
|
|
423
|
+
this.$l.miePhaseValue = this.getMiePhase(this.cosTheta);
|
|
424
|
+
this.$l.rayleighPhaseValue = this.getRayleighPhase(pb.neg(this.cosTheta));
|
|
425
|
+
this.$l.lum = pb.vec3(0);
|
|
426
|
+
this.$l.transmittance = pb.vec3(1);
|
|
427
|
+
this.$l.t = pb.float(0);
|
|
428
|
+
this.$for(pb.int('i'), 0, that._scatteringSteps, function() {
|
|
429
|
+
this.$l.newT = pb.mul(pb.div(pb.add(pb.float(this.i), 0.3), that._scatteringSteps), this.tMax);
|
|
430
|
+
this.$l.dt = pb.sub(this.newT, this.t);
|
|
431
|
+
this.t = this.newT;
|
|
432
|
+
this.$l.newPos = pb.add(this.pos, pb.mul(this.rayDir, this.t));
|
|
433
|
+
this.$l.rayleighScattering = pb.vec3();
|
|
434
|
+
this.$l.extinction = pb.vec3();
|
|
435
|
+
this.$l.mieScattering = pb.float();
|
|
436
|
+
this.getScatteringValues(this.newPos, this.rayleighScattering, this.mieScattering, this.extinction);
|
|
437
|
+
this.$l.sampleTransmittance = pb.exp(pb.mul(pb.neg(this.dt), this.extinction));
|
|
438
|
+
this.$l.sunTransmittance = this.getValFromTLUT(this.newPos, this.sunDir);
|
|
439
|
+
this.$l.psiMS = this.getValFromMSLUT(this.newPos, this.sunDir);
|
|
440
|
+
this.$l.rayleighInScattering = pb.mul(this.rayleighScattering, pb.add(pb.mul(this.sunTransmittance, this.rayleighPhaseValue), this.psiMS));
|
|
441
|
+
this.$l.mieInScattering = pb.mul(pb.add(pb.mul(this.sunTransmittance, this.miePhaseValue), this.psiMS), this.mieScattering);
|
|
442
|
+
this.$l.inScattering = pb.add(this.rayleighInScattering, this.mieInScattering);
|
|
443
|
+
this.$l.scatteringIntegral = pb.div(pb.sub(this.inScattering, pb.mul(this.inScattering, this.sampleTransmittance)), this.extinction);
|
|
444
|
+
this.lum = pb.add(this.lum, pb.mul(this.scatteringIntegral, this.transmittance));
|
|
445
|
+
this.transmittance = pb.mul(this.transmittance, this.sampleTransmittance);
|
|
446
|
+
});
|
|
447
|
+
this.$return(this.lum);
|
|
448
|
+
});
|
|
449
|
+
pb.main(function() {
|
|
450
|
+
this.$l.azimuthAngle = pb.mul(pb.sub(this.$inputs.uv.x, 0.5), 2 * Math.PI);
|
|
451
|
+
this.$l.adjV = pb.float();
|
|
452
|
+
this.$if(pb.lessThan(this.$inputs.uv.y, 0.5), function() {
|
|
453
|
+
this.$l.coord = pb.sub(1, pb.mul(this.$inputs.uv.y, 2));
|
|
454
|
+
this.adjV = pb.neg(pb.mul(this.coord, this.coord));
|
|
455
|
+
}).$else(function() {
|
|
456
|
+
this.$l.coord = pb.sub(pb.mul(this.$inputs.uv.y, 2), 1);
|
|
457
|
+
this.adjV = pb.mul(this.coord, this.coord);
|
|
458
|
+
});
|
|
459
|
+
this.$l.height = pb.length(this.viewPos);
|
|
460
|
+
this.$l.up = pb.div(this.viewPos, this.height);
|
|
461
|
+
this.$l.horizonAngle = pb.sub(pb.acos(pb.clamp(pb.div(pb.sqrt(pb.sub(pb.mul(this.height, this.height), pb.mul(that._groundRadiusMM, that._groundRadiusMM))), this.height), -1, 1)), Math.PI * 0.5);
|
|
462
|
+
this.$l.altitudeAngle = pb.sub(pb.mul(this.adjV, Math.PI * 0.5), this.horizonAngle);
|
|
463
|
+
this.$l.cosAltitude = pb.cos(this.altitudeAngle);
|
|
464
|
+
this.$l.rayDir = pb.vec3(pb.mul(this.cosAltitude, pb.sin(this.azimuthAngle)), pb.sin(this.altitudeAngle), pb.mul(pb.neg(this.cosAltitude), pb.cos(this.azimuthAngle)));
|
|
465
|
+
this.$l.sunDir = pb.vec3(0, pb.sin(this.sunAltitude), pb.neg(pb.cos(this.sunAltitude)));
|
|
466
|
+
this.$l.atmoDist = this.rayIntersectSphere(this.viewPos, this.rayDir, that._atmosphereRadiusMM);
|
|
467
|
+
this.$l.groundDist = this.rayIntersectSphere(this.viewPos, this.rayDir, that._groundRadiusMM);
|
|
468
|
+
this.$l.tMax = pb.float();
|
|
469
|
+
this.$if(pb.lessThan(this.groundDist, 0), function() {
|
|
470
|
+
this.tMax = this.atmoDist;
|
|
471
|
+
}).$else(function() {
|
|
472
|
+
this.tMax = this.groundDist;
|
|
473
|
+
});
|
|
474
|
+
this.$l.lum = this.raymarchScattering(this.viewPos, this.rayDir, this.sunDir, this.tMax);
|
|
475
|
+
this.$outputs.outColor = pb.vec4(this.lum, 1);
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
this._bindgroupSkyViewLut = device.createBindGroup(this._programSkyViewLut.bindGroupLayouts[0]);
|
|
480
|
+
}
|
|
481
|
+
if (!this._programMultiScatteringLut) {
|
|
482
|
+
this._programMultiScatteringLut = device.buildRenderProgram({
|
|
483
|
+
vertex (pb) {
|
|
484
|
+
that.commonVertexShader.call(this);
|
|
485
|
+
},
|
|
486
|
+
fragment (pb) {
|
|
487
|
+
this.$outputs.outColor = pb.vec4();
|
|
488
|
+
this.tLut = pb.tex2D().uniform(0);
|
|
489
|
+
that.commonFunctions.call(this);
|
|
490
|
+
pb.func('getValFromTLUT', [
|
|
491
|
+
pb.vec3('pos'),
|
|
492
|
+
pb.vec3('sunDir')
|
|
493
|
+
], function() {
|
|
494
|
+
this.$l.height = pb.length(this.pos);
|
|
495
|
+
this.$l.up = pb.div(this.pos, this.height);
|
|
496
|
+
this.$l.sunCosZenithAngle = pb.dot(this.sunDir, this.up);
|
|
497
|
+
this.$l.uv = pb.vec2(pb.clamp(pb.add(0.5, pb.mul(this.sunCosZenithAngle, 0.5)), 0, 1), pb.max(0, pb.min(1, pb.div(pb.sub(this.height, that._groundRadiusMM), pb.sub(that._atmosphereRadiusMM, that._groundRadiusMM)))));
|
|
498
|
+
this.$return(pb.textureSampleLevel(this.tLut, this.uv, 0).rgb);
|
|
499
|
+
});
|
|
500
|
+
pb.func('getSphericalDir', [
|
|
501
|
+
pb.float('theta'),
|
|
502
|
+
pb.float('phi')
|
|
503
|
+
], function() {
|
|
504
|
+
this.$l.cosPhi = pb.cos(this.phi);
|
|
505
|
+
this.$l.sinPhi = pb.sin(this.phi);
|
|
506
|
+
this.$l.cosTheta = pb.cos(this.theta);
|
|
507
|
+
this.$l.sinTheta = pb.sin(this.theta);
|
|
508
|
+
this.$return(pb.vec3(pb.mul(this.sinPhi, this.sinTheta), this.cosPhi, pb.mul(this.sinPhi, this.cosTheta)));
|
|
509
|
+
});
|
|
510
|
+
pb.func('getMultiScatteringValues', [
|
|
511
|
+
pb.vec3('pos'),
|
|
512
|
+
pb.vec3('sunDir'),
|
|
513
|
+
pb.vec3('lumTotal').out(),
|
|
514
|
+
pb.vec3('fms').out()
|
|
515
|
+
], function() {
|
|
516
|
+
this.lumTotal = pb.vec3(0);
|
|
517
|
+
this.fms = pb.vec3(0);
|
|
518
|
+
this.$l.invSamples = pb.div(pb.float(1), pb.mul(that._sqrtSamples, that._sqrtSamples));
|
|
519
|
+
this.$for(pb.int('i'), 0, that._sqrtSamples, function() {
|
|
520
|
+
this.$for(pb.int('j'), 0, that._sqrtSamples, function() {
|
|
521
|
+
this.$l.theta = pb.div(pb.mul(pb.add(pb.float(this.i), 0.5), Math.PI), that._sqrtSamples);
|
|
522
|
+
this.$l.c = pb.sub(1, pb.div(pb.mul(pb.add(pb.float(this.j), 0.5), 2), that._sqrtSamples));
|
|
523
|
+
this.$l.phi = pb.acos(pb.clamp(this.c, -1, 1));
|
|
524
|
+
this.$l.rayDir = this.getSphericalDir(this.theta, this.phi);
|
|
525
|
+
this.$l.atmoDist = this.rayIntersectSphere(this.pos, this.rayDir, that._atmosphereRadiusMM);
|
|
526
|
+
this.$l.groundDist = this.rayIntersectSphere(this.pos, this.rayDir, that._groundRadiusMM);
|
|
527
|
+
this.$l.tMax = this.atmoDist;
|
|
528
|
+
this.$if(pb.greaterThan(this.groundDist, 0), function() {
|
|
529
|
+
this.tMax = this.groundDist;
|
|
530
|
+
});
|
|
531
|
+
this.$l.cosTheta = pb.dot(this.rayDir, this.sunDir);
|
|
532
|
+
this.$l.miePhaseValue = this.getMiePhase(this.cosTheta);
|
|
533
|
+
this.$l.rayleighPhaseValue = this.getRayleighPhase(pb.neg(this.cosTheta));
|
|
534
|
+
this.$l.lum = pb.vec3(0);
|
|
535
|
+
this.$l.lumFactor = pb.vec3(0);
|
|
536
|
+
this.$l.transmittance = pb.vec3(1);
|
|
537
|
+
this.$l.t = pb.float(0);
|
|
538
|
+
this.$for(pb.int('stepI'), 0, that._multiScatteringSteps, function() {
|
|
539
|
+
this.$l.newT = pb.mul(pb.div(pb.add(pb.float(this.stepI), 0.3), that._multiScatteringSteps), this.tMax);
|
|
540
|
+
this.$l.dt = pb.sub(this.newT, this.t);
|
|
541
|
+
this.t = this.newT;
|
|
542
|
+
this.$l.newPos = pb.add(this.pos, pb.mul(this.rayDir, this.t));
|
|
543
|
+
this.$l.rayleighScattering = pb.vec3();
|
|
544
|
+
this.$l.extinction = pb.vec3();
|
|
545
|
+
this.$l.mieScattering = pb.float();
|
|
546
|
+
this.getScatteringValues(this.newPos, this.rayleighScattering, this.mieScattering, this.extinction);
|
|
547
|
+
this.$l.sampleTransmittance = pb.exp(pb.mul(pb.neg(this.dt), this.extinction));
|
|
548
|
+
this.$l.scatteringNoPhase = pb.add(this.rayleighScattering, pb.vec3(this.mieScattering));
|
|
549
|
+
this.$l.scatteringF = pb.div(pb.sub(this.scatteringNoPhase, pb.mul(this.scatteringNoPhase, this.sampleTransmittance)), this.extinction);
|
|
550
|
+
this.lumFactor = pb.add(this.lumFactor, pb.mul(this.transmittance, this.scatteringF));
|
|
551
|
+
this.$l.sunTransmittance = this.getValFromTLUT(this.newPos, this.sunDir);
|
|
552
|
+
this.$l.rayleighInscattering = pb.mul(this.rayleighScattering, this.rayleighPhaseValue);
|
|
553
|
+
this.$l.mieInscattering = pb.mul(this.mieScattering, this.miePhaseValue);
|
|
554
|
+
this.$l.inscattering = pb.mul(pb.add(this.rayleighInscattering, pb.vec3(this.mieInscattering)), this.sunTransmittance);
|
|
555
|
+
this.$l.scatteringIntegral = pb.div(pb.sub(this.inscattering, pb.mul(this.inscattering, this.sampleTransmittance)), this.extinction);
|
|
556
|
+
this.lum = pb.add(this.lum, pb.mul(this.scatteringIntegral, this.transmittance));
|
|
557
|
+
this.transmittance = pb.mul(this.transmittance, this.sampleTransmittance);
|
|
558
|
+
});
|
|
559
|
+
this.$if(pb.greaterThan(this.groundDist, 0), function() {
|
|
560
|
+
this.$l.hitPos = pb.add(this.pos, pb.mul(this.rayDir, this.groundDist));
|
|
561
|
+
this.$if(pb.greaterThan(pb.dot(this.pos, this.sunDir), 0), function() {
|
|
562
|
+
this.hitPos = pb.mul(pb.normalize(this.hitPos), that._groundRadiusMM);
|
|
563
|
+
this.lum = pb.add(this.lum, pb.mul(this.transmittance, pb.vec3(that._groundAlbedo), this.getValFromTLUT(this.hitPos, this.sunDir)));
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
this.fms = pb.add(this.fms, pb.mul(this.lumFactor, this.invSamples));
|
|
567
|
+
this.lumTotal = pb.add(this.lumTotal, pb.mul(this.lum, this.invSamples));
|
|
568
|
+
});
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
pb.main(function() {
|
|
572
|
+
this.$l.sunCosTheta = pb.sub(pb.mul(this.$inputs.uv.x, 2), 1);
|
|
573
|
+
this.$l.sunTheta = pb.acos(pb.clamp(this.sunCosTheta, -1, 1));
|
|
574
|
+
this.$l.height = pb.mix(that._groundRadiusMM, that._atmosphereRadiusMM, this.$inputs.uv.y);
|
|
575
|
+
this.$l.pos = pb.vec3(0, this.height, 0);
|
|
576
|
+
this.$l.sunDir = pb.normalize(pb.vec3(0, this.sunCosTheta, pb.neg(pb.sin(this.sunTheta))));
|
|
577
|
+
this.$l.lum = pb.vec3();
|
|
578
|
+
this.$l.fms = pb.vec3();
|
|
579
|
+
this.getMultiScatteringValues(this.pos, this.sunDir, this.lum, this.fms);
|
|
580
|
+
this.$l.psi = pb.div(this.lum, pb.sub(1, this.fms));
|
|
581
|
+
this.$outputs.outColor = pb.vec4(this.psi, 1);
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
this._bindgroupMultiScatteringLut = device.createBindGroup(this._programMultiScatteringLut.bindGroupLayouts[0]);
|
|
587
|
+
if (!this._programTransmittanceLut) {
|
|
588
|
+
this._programTransmittanceLut = device.buildRenderProgram({
|
|
589
|
+
vertex (pb) {
|
|
590
|
+
that.commonVertexShader.call(this);
|
|
591
|
+
},
|
|
592
|
+
fragment (pb) {
|
|
593
|
+
this.$outputs.outColor = pb.vec4();
|
|
594
|
+
that.commonFunctions.call(this);
|
|
595
|
+
pb.func('getSunTransmittance', [
|
|
596
|
+
pb.vec3('pos'),
|
|
597
|
+
pb.vec3('sunDir')
|
|
598
|
+
], function() {
|
|
599
|
+
this.$if(pb.greaterThan(this.rayIntersectSphere(this.pos, this.sunDir, that._groundRadiusMM), 0), function() {
|
|
600
|
+
this.$return(pb.vec3(0));
|
|
601
|
+
});
|
|
602
|
+
this.$l.atmoDist = this.rayIntersectSphere(this.pos, this.sunDir, that._atmosphereRadiusMM);
|
|
603
|
+
this.$l.t = pb.float(0);
|
|
604
|
+
this.$l.transmittance = pb.vec3(1);
|
|
605
|
+
this.$for(pb.int('i'), 0, that._sunTransmittanceSteps, function() {
|
|
606
|
+
this.$l.newT = pb.mul(pb.div(pb.add(pb.float(this.i), 0.3), that._sunTransmittanceSteps), this.atmoDist);
|
|
607
|
+
this.$l.dt = pb.sub(this.newT, this.t);
|
|
608
|
+
this.t = this.newT;
|
|
609
|
+
this.$l.newPos = pb.add(this.pos, pb.mul(this.sunDir, this.t));
|
|
610
|
+
this.$l.rayleighScattering = pb.vec3();
|
|
611
|
+
this.$l.extinction = pb.vec3();
|
|
612
|
+
this.$l.mieScattering = pb.float();
|
|
613
|
+
this.getScatteringValues(this.newPos, this.rayleighScattering, this.mieScattering, this.extinction);
|
|
614
|
+
this.transmittance = pb.mul(this.transmittance, pb.exp(pb.mul(this.extinction, pb.neg(this.dt))));
|
|
615
|
+
});
|
|
616
|
+
this.$return(this.transmittance);
|
|
617
|
+
});
|
|
618
|
+
pb.main(function() {
|
|
619
|
+
this.$l.sunCosTheta = pb.sub(pb.mul(this.$inputs.uv.x, 2), 1);
|
|
620
|
+
this.$l.sunTheta = pb.acos(pb.clamp(this.sunCosTheta, -1, 1));
|
|
621
|
+
this.$l.height = pb.mix(that._groundRadiusMM, that._atmosphereRadiusMM, this.$inputs.uv.y);
|
|
622
|
+
this.$l.pos = pb.vec3(0, this.height, 0);
|
|
623
|
+
this.$l.sunDir = pb.normalize(pb.vec3(0, this.sunCosTheta, pb.neg(pb.sin(this.sunTheta))));
|
|
624
|
+
this.$outputs.outColor = pb.vec4(this.getSunTransmittance(this.pos, this.sunDir), 1);
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
this._bindgroupTransmittanceLut = device.createBindGroup(this._programTransmittanceLut.bindGroupLayouts[0]);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export { ScatteringLut };
|
|
634
|
+
//# sourceMappingURL=scatteringlut.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scatteringlut.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|