@woosh/meep-engine 2.33.62 → 2.33.67
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/core/FilePath.js +28 -2
- package/core/binary/BinaryBuffer.js +13 -0
- package/core/geom/2d/quad-tree/QuadTreeNode.js +3 -2
- package/ecs/grid/pick.js +44 -0
- package/editor/tools/GridPaintTool.js +1 -1
- package/editor/tools/paint/TerrainPaintTool.js +1 -1
- package/editor/view/GridPickCoordinateView.js +1 -1
- package/engine/asset/AssetManager.js +1 -1
- package/engine/asset/AssetTransformer.js +2 -1
- package/engine/asset/loaders/GLTFAssetLoader.js +5 -21
- package/engine/asset/loaders/async_traverse_three_object.js +24 -0
- package/engine/ecs/attachment/AttachmentSystem.js +3 -51
- package/engine/ecs/fow/FogOfWarRevealerSystem.js +1 -1
- package/engine/ecs/fow/shader/screenSpaceFogOfWarShader.js +2 -10
- package/engine/ecs/grid/NormalMap2AOMap.js +10 -13
- package/engine/ecs/team/Team.js +82 -0
- package/engine/ecs/terrain/ecs/BuildLightTexture.js +106 -0
- package/engine/ecs/terrain/ecs/PromiseSamplerHeight.js +59 -0
- package/engine/ecs/terrain/ecs/Terrain.js +14 -153
- package/engine/ecs/tooltip/TooltipComponentSystem.js +1 -1
- package/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +10 -0
- package/engine/graphics/filter/ImageFilter.js +6 -2
- package/engine/graphics/geometry/AttributeSpec.d.ts +8 -0
- package/engine/graphics/geometry/VertexDataSpec.d.ts +15 -0
- package/engine/graphics/geometry/buffered/deinterleaveBufferAttribute.js +39 -0
- package/engine/graphics/geometry/buffered/deinterleaveBufferGeometry.js +50 -0
- package/engine/graphics/micron/MICRON_GEOMETRY_FIELD.js +1 -0
- package/engine/graphics/micron/MICRON_URI_FIELD.js +1 -0
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +10 -7
- package/engine/graphics/micron/convert_three_object_to_micron.js +31 -5
- package/engine/graphics/micron/format/MicronGeometry.d.ts +4 -0
- package/engine/graphics/micron/format/MicronGeometry.js +6 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +110 -6
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +4 -2
- package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/engine/graphics/render/webgpu/sample/MeshInstance.js +21 -0
- package/engine/graphics/render/webgpu/sample/main.js +2 -2
- package/engine/graphics/shaders/AmbientOcclusionShader.js +57 -77
- package/engine/graphics/shaders/DenoiseShader.js +119 -0
- package/engine/graphics/texture/noise_octaves.js +33 -0
- package/engine/graphics/texture/sampler/Sampler2D2Texture.js +7 -18
- package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +8 -5
- package/engine/graphics/texture/sampler/sampler2DToFloat32Texture.js +10 -3
- package/engine/graphics/util/modelHitTest.js +63 -0
- package/generation/example/filters/SampleGroundMoistureFilter.js +2 -1
- package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +29 -13
- package/generation/grid/GridData.js +17 -2
- package/package.json +1 -1
|
@@ -13,6 +13,13 @@ import { AsyncRemoteHashMap } from "../../../../core/collection/map/AsyncRemoteH
|
|
|
13
13
|
import { BufferGeometrySerializationAdapter } from "./serialization/BufferGeometrySerializationAdapter.js";
|
|
14
14
|
import { MicronGeometryBinarySerializationAdapter } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
|
|
15
15
|
import { AsyncMapWrapper } from "../../../../core/collection/map/AsyncMapWrapper.js";
|
|
16
|
+
import { async_traverse_three_object } from "../../../asset/loaders/async_traverse_three_object.js";
|
|
17
|
+
import { computePathDirectory } from "../../../../core/FilePath.js";
|
|
18
|
+
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
19
|
+
import { MicronGeometry } from "../format/MicronGeometry.js";
|
|
20
|
+
import { ArrayBufferLoader } from "../../../asset/loaders/ArrayBufferLoader.js";
|
|
21
|
+
import { MICRON_URI_FIELD } from "../MICRON_URI_FIELD.js";
|
|
22
|
+
import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
|
|
16
23
|
|
|
17
24
|
/**
|
|
18
25
|
*
|
|
@@ -20,6 +27,7 @@ import { AsyncMapWrapper } from "../../../../core/collection/map/AsyncMapWrapper
|
|
|
20
27
|
*/
|
|
21
28
|
const STORAGE_KEY = '@plugin/virtual-geometry-micron/geometry-cache';
|
|
22
29
|
|
|
30
|
+
const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
|
|
23
31
|
|
|
24
32
|
class GLTFAssetTransformer extends AssetTransformer {
|
|
25
33
|
/**
|
|
@@ -35,17 +43,100 @@ class GLTFAssetTransformer extends AssetTransformer {
|
|
|
35
43
|
* @private
|
|
36
44
|
*/
|
|
37
45
|
this.__cache = cache;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @type {AssetManager|null}
|
|
50
|
+
* @private
|
|
51
|
+
*/
|
|
52
|
+
this.__am = null;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @type {MicronGeometryBinarySerializationAdapter}
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
this.__serde = new MicronGeometryBinarySerializationAdapter();
|
|
38
60
|
}
|
|
39
61
|
|
|
40
|
-
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @param {AssetManager|null} am
|
|
65
|
+
*/
|
|
66
|
+
set assetManager(am) {
|
|
67
|
+
this.__am = am;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {THREE.Object3D} object
|
|
73
|
+
* @param {{asset:AssetDescription}} ctx
|
|
74
|
+
* @return {Promise<void>}
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
async __visitObjectToLoadMicron(object, ctx) {
|
|
78
|
+
if (!object.isMesh) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @type {THREE.BufferGeometry}
|
|
84
|
+
*/
|
|
85
|
+
const geometry = object.geometry;
|
|
86
|
+
|
|
87
|
+
const micron_uri = geometry.userData[MICRON_URI_FIELD];
|
|
88
|
+
|
|
89
|
+
if (typeof micron_uri !== "string") {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @type {AssetDescription}
|
|
96
|
+
*/
|
|
97
|
+
const ad = ctx.asset;
|
|
98
|
+
|
|
99
|
+
const base = computePathDirectory(ad.path);
|
|
100
|
+
|
|
101
|
+
const micron_data = await this.__am.promise(`${base}/${micron_uri}`, ASSET_TYPE_ARRAY_BUFFER);
|
|
102
|
+
|
|
103
|
+
// deserialize micron data
|
|
104
|
+
const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
|
|
105
|
+
const micron_geometry = new MicronGeometry();
|
|
106
|
+
|
|
107
|
+
this.__serde.deserialize(buffer, micron_geometry);
|
|
108
|
+
|
|
109
|
+
// set proxy for raycasting
|
|
110
|
+
micron_geometry.proxy = geometry;
|
|
111
|
+
|
|
112
|
+
geometry[MICRON_GEOMETRY_FIELD] = micron_geometry;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @param {Asset} source
|
|
119
|
+
* @param asset_description
|
|
120
|
+
* @return {Promise<Asset>}
|
|
121
|
+
*/
|
|
122
|
+
async transform(source, asset_description) {
|
|
41
123
|
const animationClips = source.animations;
|
|
124
|
+
|
|
42
125
|
if (animationClips !== undefined && animationClips.length > 0) {
|
|
43
126
|
// not suitable
|
|
44
127
|
return source;
|
|
45
128
|
}
|
|
46
129
|
|
|
130
|
+
/**
|
|
131
|
+
* @type {THREE.Object3D}
|
|
132
|
+
*/
|
|
47
133
|
const root = source.create();
|
|
48
134
|
|
|
135
|
+
// attempt to load existing micron geometries
|
|
136
|
+
await async_traverse_three_object(root, this.__visitObjectToLoadMicron, this, {
|
|
137
|
+
asset: asset_description
|
|
138
|
+
});
|
|
139
|
+
|
|
49
140
|
const micron_root = await convert_three_object_to_micron(root.clone(), this.__cache);
|
|
50
141
|
micron_root.boundingSphere = root.boundingSphere;
|
|
51
142
|
|
|
@@ -117,7 +208,7 @@ export class MicronRenderPlugin extends EnginePlugin {
|
|
|
117
208
|
|
|
118
209
|
/**
|
|
119
210
|
*
|
|
120
|
-
* @type {
|
|
211
|
+
* @type {GLTFAssetTransformer}
|
|
121
212
|
* @private
|
|
122
213
|
*/
|
|
123
214
|
this.__asset_transformer = new GLTFAssetTransformer(this.__cache);
|
|
@@ -180,8 +271,17 @@ export class MicronRenderPlugin extends EnginePlugin {
|
|
|
180
271
|
|
|
181
272
|
const engine = this.engine;
|
|
182
273
|
|
|
183
|
-
engine.assetManager
|
|
184
|
-
|
|
274
|
+
const am = engine.assetManager;
|
|
275
|
+
|
|
276
|
+
// ensure that "arraybuffer" asset loader is present
|
|
277
|
+
if (am.getLoaderByType(ASSET_TYPE_ARRAY_BUFFER) === undefined) {
|
|
278
|
+
am.registerLoader(ASSET_TYPE_ARRAY_BUFFER, new ArrayBufferLoader());
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
this.__asset_transformer.assetManager = am;
|
|
282
|
+
|
|
283
|
+
am.registerTransformer("model/gltf", this.__asset_transformer);
|
|
284
|
+
am.registerTransformer("model/gltf+json", this.__asset_transformer);
|
|
185
285
|
|
|
186
286
|
/**
|
|
187
287
|
*
|
|
@@ -207,8 +307,12 @@ export class MicronRenderPlugin extends EnginePlugin {
|
|
|
207
307
|
|
|
208
308
|
this.__persisted_geometry.detach_storage();
|
|
209
309
|
|
|
210
|
-
engine.assetManager
|
|
211
|
-
|
|
310
|
+
const am = engine.assetManager;
|
|
311
|
+
|
|
312
|
+
am.unregisterTransformer("model/gltf", this.__asset_transformer);
|
|
313
|
+
am.unregisterTransformer("model/gltf+json", this.__asset_transformer);
|
|
314
|
+
|
|
315
|
+
this.__asset_transformer.assetManager = null;
|
|
212
316
|
|
|
213
317
|
const ge = engine.graphics;
|
|
214
318
|
|
|
@@ -42,7 +42,6 @@ import { RepeatBehavior } from "../../../../../../intelligence/behavior/decorato
|
|
|
42
42
|
import { ActionBehavior } from "../../../../../../intelligence/behavior/primitive/ActionBehavior.js";
|
|
43
43
|
import { pingpong } from "../../../../../../../core/math/pingpong.js";
|
|
44
44
|
import { ParameterLookupTable } from "../../parameter/ParameterLookupTable.js";
|
|
45
|
-
import { pick } from "../../../../../../../../model/game/util/ScreenGridPicker.js";
|
|
46
45
|
import GUIElement from "../../../../../../ecs/gui/GUIElement.js";
|
|
47
46
|
import EmptyView from "../../../../../../../view/elements/EmptyView.js";
|
|
48
47
|
import HeadsUpDisplay from "../../../../../../ecs/gui/hud/HeadsUpDisplay.js";
|
|
@@ -77,6 +76,7 @@ import TopDownCameraController from "../../../../../ecs/camera/topdown/TopDownCa
|
|
|
77
76
|
import { randomFloatBetween } from "../../../../../../../core/math/random/randomFloatBetween.js";
|
|
78
77
|
import { MicronRenderPlugin } from "../../../../../micron/plugin/MicronRenderPlugin.js";
|
|
79
78
|
import { obtainTerrain } from "../../../../../../ecs/terrain/util/obtainTerrain.js";
|
|
79
|
+
import { pick } from "../../../../../../../ecs/grid/pick.js";
|
|
80
80
|
|
|
81
81
|
const engineHarness = new EngineHarness();
|
|
82
82
|
|
|
@@ -433,7 +433,9 @@ async function sample_scene_nam(engine) {
|
|
|
433
433
|
"distanceMax": 1000
|
|
434
434
|
});
|
|
435
435
|
|
|
436
|
-
load_model('moicon/20_Dec_2021_Nammo/with_assets(for_alex)/model.gltf', ecd)
|
|
436
|
+
// load_model('moicon/20_Dec_2021_Nammo/with_assets(for_alex)/model.gltf', ecd)
|
|
437
|
+
load_model('moicon/20_Dec_2021_Nammo/with_assets_micron_conveted/model.gltf', ecd)
|
|
438
|
+
// load_model('moicon/micron_container/model.gltf', ecd)
|
|
437
439
|
|
|
438
440
|
const P_SIZE_SMALL = 0.15;
|
|
439
441
|
const P_SIZE_MEDIUM = 0.6;
|
|
@@ -80,7 +80,7 @@ import { ParticleEmitterSystem } from "../../../particles/ecs/ParticleEmitterSys
|
|
|
80
80
|
import { ShadedGeometrySystem } from "../../../ecs/mesh-v2/ShadedGeometrySystem.js";
|
|
81
81
|
import { FogOfWar } from "../../../../ecs/fow/FogOfWar.js";
|
|
82
82
|
import { FogOfWarRevealer } from "../../../../ecs/fow/FogOfWarRevealer.js";
|
|
83
|
-
import Team from "
|
|
83
|
+
import Team from "../../../../ecs/team/Team.js";
|
|
84
84
|
import { AmbientOcclusionPostProcessEffect } from "../../buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js";
|
|
85
85
|
import { obtainTerrain } from "../../../../ecs/terrain/util/obtainTerrain.js";
|
|
86
86
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { array_copy } from "../../../../../core/collection/array/copyArray.js";
|
|
2
2
|
|
|
3
|
+
const BIND_GROUP_MATERIAL = 1;
|
|
4
|
+
|
|
3
5
|
export class MeshInstance {
|
|
4
6
|
constructor() {
|
|
5
7
|
|
|
@@ -9,6 +11,12 @@ export class MeshInstance {
|
|
|
9
11
|
*/
|
|
10
12
|
this.geometry = null;
|
|
11
13
|
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {null}
|
|
17
|
+
*/
|
|
18
|
+
this.material = null;
|
|
19
|
+
|
|
12
20
|
/**
|
|
13
21
|
*
|
|
14
22
|
* @type {GPUBuffer|null}
|
|
@@ -75,13 +83,26 @@ export class MeshInstance {
|
|
|
75
83
|
|
|
76
84
|
}
|
|
77
85
|
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param {GPURenderPassEncoder} pass
|
|
89
|
+
*/
|
|
90
|
+
preparePass(pass) {
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
78
94
|
/**
|
|
79
95
|
*
|
|
80
96
|
* @param {GPURenderPassEncoder} pass
|
|
81
97
|
*/
|
|
82
98
|
draw(pass) {
|
|
99
|
+
// set material bindings
|
|
100
|
+
|
|
101
|
+
// pass.setBindGroup(BIND_GROUP_MATERIAL, {});
|
|
102
|
+
|
|
83
103
|
pass.setVertexBuffer(0, this.vertex_buffer);
|
|
84
104
|
pass.setIndexBuffer(this.index_buffer, 'uint32');
|
|
105
|
+
|
|
85
106
|
pass.drawIndexed(this.geometry.getIndex().array.length);
|
|
86
107
|
}
|
|
87
108
|
}
|
|
@@ -323,7 +323,7 @@ const init = async ({ canvasRef, gui }) => {
|
|
|
323
323
|
};
|
|
324
324
|
const settings = {
|
|
325
325
|
mode: 'rendering',
|
|
326
|
-
numLights:
|
|
326
|
+
numLights:1,
|
|
327
327
|
};
|
|
328
328
|
const configUniformBuffer = (() => {
|
|
329
329
|
const buffer = device.createBuffer({
|
|
@@ -541,7 +541,7 @@ const init = async ({ canvasRef, gui }) => {
|
|
|
541
541
|
gBufferPass.setPipeline(writeGBuffersPipeline);
|
|
542
542
|
gBufferPass.setBindGroup(0, sceneUniformBindGroup);
|
|
543
543
|
|
|
544
|
-
|
|
544
|
+
m_instance.draw(gBufferPass);
|
|
545
545
|
|
|
546
546
|
gBufferPass.endPass();
|
|
547
547
|
}
|
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Vector2 } from "three";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const samplesPerPixel = 37;
|
|
8
|
-
|
|
9
6
|
const AmbientOcclusionShader = function () {
|
|
10
7
|
return {
|
|
11
8
|
|
|
@@ -13,11 +10,16 @@ const AmbientOcclusionShader = function () {
|
|
|
13
10
|
|
|
14
11
|
"normalMap": { type: "t", value: null },
|
|
15
12
|
"heightMap": { type: "t", value: null },
|
|
16
|
-
"
|
|
13
|
+
"world_size": { type: "v2", value: new Vector2(512, 512) },
|
|
17
14
|
"rayLength": { type: 'f', value: 17 }
|
|
18
15
|
|
|
19
16
|
},
|
|
20
17
|
|
|
18
|
+
defines: {
|
|
19
|
+
'NUM_SAMPLES': 64,
|
|
20
|
+
'NUM_RINGS': 7,
|
|
21
|
+
},
|
|
22
|
+
|
|
21
23
|
vertexShader: [
|
|
22
24
|
|
|
23
25
|
"varying vec2 vUv;",
|
|
@@ -33,17 +35,17 @@ const AmbientOcclusionShader = function () {
|
|
|
33
35
|
|
|
34
36
|
fragmentShader: [
|
|
35
37
|
`
|
|
36
|
-
uniform vec2 resolution;
|
|
37
38
|
uniform sampler2D normalMap;
|
|
38
39
|
uniform sampler2D heightMap;
|
|
39
40
|
uniform float rayLength;
|
|
41
|
+
uniform vec2 world_size;
|
|
40
42
|
|
|
41
43
|
varying vec2 vUv;
|
|
42
44
|
|
|
43
45
|
vec3 get(float x, float y){
|
|
44
|
-
vec2 _uv = vUv.xy + vec2(x,y)/
|
|
46
|
+
vec2 _uv = vUv.xy + vec2(x,y) / world_size;
|
|
45
47
|
float h = texture2D(heightMap, _uv).x;
|
|
46
|
-
return vec3(_uv.x, h, _uv.y);
|
|
48
|
+
return vec3( _uv.x * world_size.x, h, _uv.y * world_size.y );
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
float hash1( float n )
|
|
@@ -56,92 +58,70 @@ const AmbientOcclusionShader = function () {
|
|
|
56
58
|
p = 50.0*fract( p*0.3183099 );
|
|
57
59
|
return fract( p.x*p.y*(p.x+p.y) );
|
|
58
60
|
}
|
|
59
|
-
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
float a = hash1(p+vec2(0,0));
|
|
68
|
-
float b = hash1(p+vec2(1,0));
|
|
69
|
-
float c = hash1(p+vec2(0,1));
|
|
70
|
-
float d = hash1(p+vec2(1,1));
|
|
71
|
-
|
|
72
|
-
return -1.0+2.0*( a + (b-a)*u.x + (c-a)*u.y + (a - b - c + d)*u.x*u.y );
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
float noise_01(in vec2 x){
|
|
76
|
-
return (noise(x) + 1.0)*0.5;
|
|
62
|
+
// Non-sin based hash function, fast and has good randomness
|
|
63
|
+
float hash12(vec2 p){
|
|
64
|
+
vec3 p3 = fract(vec3(p.xyx) * .1031);
|
|
65
|
+
p3 += dot(p3, p3.yzx + 33.33);
|
|
66
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
77
67
|
}
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
float random_0 = noise_01( seed + vec2(1.123, 3.1) );
|
|
81
|
-
float random_1 = noise_01( seed + vec2(3.123, 7.8913) );
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
float angleCosine = cos(angle);
|
|
85
|
-
|
|
86
|
-
float z = random_0 * (1.0 - angleCosine) + angleCosine;
|
|
69
|
+
const float bias = 0.001;
|
|
87
70
|
|
|
88
|
-
|
|
71
|
+
float pow2(float x){
|
|
72
|
+
return x*x;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
float getOcclusion(vec3 origin, vec3 normal, vec3 hit_position){
|
|
76
|
+
vec3 viewDelta = hit_position - origin;
|
|
89
77
|
|
|
90
|
-
float
|
|
78
|
+
float viewDistance = length( viewDelta );
|
|
91
79
|
|
|
92
|
-
float
|
|
80
|
+
float vn = dot( normal, viewDelta );
|
|
81
|
+
float a2 = (vn) / viewDistance - bias;
|
|
82
|
+
float a1 = (1.0 + pow2( viewDistance ) );
|
|
93
83
|
|
|
94
|
-
|
|
95
|
-
|
|
84
|
+
return max(0.0, a2) / a1;
|
|
85
|
+
}
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
87
|
+
const float PI2 = 6.28318530717958;
|
|
88
|
+
const float kernelRadius = 100.0;
|
|
89
|
+
|
|
90
|
+
const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );
|
|
91
|
+
const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );
|
|
92
|
+
|
|
93
|
+
float getAmbientOcclusion(vec3 world_position, vec3 world_normal){
|
|
94
|
+
// jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/
|
|
95
|
+
float angle = hash12( vUv ) * PI2;
|
|
96
|
+
vec2 radius = vec2( rayLength * INV_NUM_SAMPLES );
|
|
100
97
|
|
|
101
|
-
float
|
|
102
|
-
|
|
103
|
-
float c = dZ;
|
|
104
|
-
float s = sin(rot);
|
|
105
|
-
float t = 1.0 - c;
|
|
106
|
-
float tx = -t * dY;
|
|
107
|
-
float ty = t * dX;
|
|
98
|
+
float occlusionSum = 0.0;
|
|
99
|
+
float weightSum = 0.0;
|
|
108
100
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
101
|
+
for( int i = 0; i < NUM_SAMPLES; i ++ ) {
|
|
102
|
+
vec2 sampleUv = vec2( cos( angle ), sin( angle ) ) * radius * float(i+1);
|
|
103
|
+
|
|
104
|
+
angle += ANGLE_STEP;
|
|
105
|
+
|
|
106
|
+
vec3 sample_pos = get(sampleUv.x, sampleUv.y);
|
|
114
107
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
108
|
+
occlusionSum += getOcclusion(world_position, world_normal, sample_pos);
|
|
109
|
+
weightSum += 1.0;
|
|
110
|
+
}
|
|
118
111
|
|
|
119
|
-
return
|
|
112
|
+
return occlusionSum/weightSum;
|
|
120
113
|
}
|
|
121
|
-
|
|
114
|
+
|
|
122
115
|
void main() {
|
|
123
|
-
float occlusion = 0.0;
|
|
124
116
|
vec3 pos = get(0.0, 0.0);
|
|
125
|
-
vec3 normal = texture2D( normalMap, vUv ).xyz;
|
|
126
|
-
|
|
127
|
-
for(int i=1; i< ${samplesPerPixel}; i++){
|
|
128
|
-
float s = float(i)/${samplesPerPixel - 1}.0;
|
|
129
|
-
float a = sqrt(s*512.0);
|
|
130
|
-
float b = sqrt(s)*rayLength;
|
|
131
|
-
float x = sin(a)*b;
|
|
132
|
-
float y = cos(a)*b;
|
|
133
|
-
|
|
134
|
-
vec3 sample_pos = get(x, y);
|
|
135
|
-
|
|
136
|
-
vec3 sample_dir = normalize(sample_pos - pos);
|
|
137
|
-
float vDot = dot(normal, sample_dir);
|
|
138
|
-
float lambert = clamp(vDot, 0.0, 1.0);
|
|
139
|
-
float dist_factor = 0.23/sqrt(length(sample_pos - pos));
|
|
140
|
-
occlusion += dist_factor*lambert;
|
|
141
|
-
}
|
|
142
117
|
|
|
143
|
-
|
|
144
|
-
|
|
118
|
+
vec3 normal = texture2D( normalMap, vUv ).xzy;
|
|
119
|
+
|
|
120
|
+
float occlusion = getAmbientOcclusion(pos, normal);
|
|
121
|
+
|
|
122
|
+
float incident = 1.0 - occlusion;
|
|
123
|
+
|
|
124
|
+
gl_FragColor = vec4(pow(incident,10.0), 0.0, 0.0, 1.0);
|
|
145
125
|
}
|
|
146
126
|
`
|
|
147
127
|
].join('\n')
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Vector2 } from "three";
|
|
2
|
+
|
|
3
|
+
const KERNEL_SIZE = 15;
|
|
4
|
+
|
|
5
|
+
const fragment = `
|
|
6
|
+
// bilateral filter, based on https://www.shadertoy.com/view/4dfGDH# and
|
|
7
|
+
// http://people.csail.mit.edu/sparis/bf_course/course_notes.pdf
|
|
8
|
+
// A bilateral filter is a non-linear, edge-preserving, and noise-reducing smoothing filter for images.
|
|
9
|
+
// It replaces the intensity of each pixel with a weighted average of intensity values from nearby pixels.
|
|
10
|
+
// This weight can be based on a Gaussian distribution. Crucially, the weights depend not only on
|
|
11
|
+
// Euclidean distance of pixels, but also on the radiometric differences (e.g., range differences, such
|
|
12
|
+
// as color intensity, depth distance, etc.). This preserves sharp edges.
|
|
13
|
+
|
|
14
|
+
float normpdf3(in vec3 v, in float sigma) {
|
|
15
|
+
return 0.39894 * exp(-0.5 * dot(v, v) / (sigma * sigma)) / sigma;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// filter size
|
|
19
|
+
#define MSIZE ${KERNEL_SIZE}
|
|
20
|
+
varying vec2 vUv;
|
|
21
|
+
uniform sampler2D source;
|
|
22
|
+
uniform vec2 pixelOffset;
|
|
23
|
+
uniform vec2 sigmas;
|
|
24
|
+
uniform float bZnorm;
|
|
25
|
+
uniform float kernel[MSIZE];
|
|
26
|
+
|
|
27
|
+
void main(void) {
|
|
28
|
+
|
|
29
|
+
// range sigma - controls blurriness based on a pixel distance
|
|
30
|
+
float sigma = sigmas.x;
|
|
31
|
+
|
|
32
|
+
// domain sigma - controls blurriness based on a pixel similarity (to preserve edges)
|
|
33
|
+
float bSigma = sigmas.y;
|
|
34
|
+
vec4 pixel = texture2D(source, vUv);
|
|
35
|
+
vec4 accumulatedColor = vec4(0.0);
|
|
36
|
+
float accumulatedFactor = 0.0;
|
|
37
|
+
|
|
38
|
+
// read out the texels
|
|
39
|
+
const int kSize = (MSIZE-1)/2;
|
|
40
|
+
|
|
41
|
+
for (int i = -kSize; i <= kSize; ++i) {
|
|
42
|
+
for (int j = -kSize; j <= kSize; ++j) {
|
|
43
|
+
|
|
44
|
+
// sample the pixel with offset
|
|
45
|
+
vec2 coord = vUv + vec2(float(i), float(j)) * pixelOffset;
|
|
46
|
+
vec4 rgba = texture2D(source, coord);
|
|
47
|
+
|
|
48
|
+
// bilateral factors
|
|
49
|
+
float factor = kernel[kSize + j] * kernel[kSize + i];
|
|
50
|
+
factor *= normpdf3(rgba.rgb - pixel.rgb, bSigma) * bZnorm;
|
|
51
|
+
|
|
52
|
+
// accumulate
|
|
53
|
+
accumulatedColor += factor * rgba;
|
|
54
|
+
accumulatedFactor += factor;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
gl_FragColor = accumulatedColor / accumulatedFactor;
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @param {number} x
|
|
65
|
+
* @param {number} sigma
|
|
66
|
+
* @return {number}
|
|
67
|
+
*/
|
|
68
|
+
function normpdf(x, sigma) {
|
|
69
|
+
return 0.39894 * Math.exp(-0.5 * x * x / (sigma * sigma)) / sigma;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
*
|
|
74
|
+
* @param {number} sigma
|
|
75
|
+
* @param {number} filterSmoothness
|
|
76
|
+
* @constructor
|
|
77
|
+
*/
|
|
78
|
+
export function DenoiseShader(sigma = 10, filterSmoothness = 0.2) {
|
|
79
|
+
// compute zNorm
|
|
80
|
+
const zNorm = 1 / normpdf(0, filterSmoothness);
|
|
81
|
+
|
|
82
|
+
// build kernel
|
|
83
|
+
const kernel = new Float32Array(KERNEL_SIZE);
|
|
84
|
+
const kSize = Math.floor((KERNEL_SIZE - 1) / 2);
|
|
85
|
+
for (let i = 0; i <= kSize; i++) {
|
|
86
|
+
const v = normpdf(i, sigma);
|
|
87
|
+
|
|
88
|
+
kernel[kSize + i] = v;
|
|
89
|
+
kernel[kSize - i] = v;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
uniforms: {
|
|
94
|
+
source: {
|
|
95
|
+
type: 't',
|
|
96
|
+
value: null
|
|
97
|
+
},
|
|
98
|
+
pixelOffset: {
|
|
99
|
+
type: 'v2',
|
|
100
|
+
/**
|
|
101
|
+
* Holds single pixel size in UV space ( 1 / texture_size )
|
|
102
|
+
*/
|
|
103
|
+
value: new Vector2(1, 1)
|
|
104
|
+
},
|
|
105
|
+
sigmas: {
|
|
106
|
+
type: "v2", value: new Vector2(sigma, sigma)
|
|
107
|
+
},
|
|
108
|
+
bZnorm: {
|
|
109
|
+
type: 'f',
|
|
110
|
+
value: zNorm
|
|
111
|
+
},
|
|
112
|
+
kernel: {
|
|
113
|
+
type: 'f',
|
|
114
|
+
value: kernel
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
fragmentShader: fragment
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function noise_octaves(
|
|
2
|
+
noise,
|
|
3
|
+
noise_ctx,
|
|
4
|
+
x, y, z,
|
|
5
|
+
octaves,
|
|
6
|
+
persistence = 0.5,
|
|
7
|
+
lacunarity = 2
|
|
8
|
+
) {
|
|
9
|
+
let total = 0;
|
|
10
|
+
let frequency = 1;
|
|
11
|
+
let amplitude = 1;
|
|
12
|
+
|
|
13
|
+
let totalAmplitude = 0; // Used for normalizing result to 0.0 - 1.0
|
|
14
|
+
let i = 0;
|
|
15
|
+
|
|
16
|
+
for (; i < octaves; i++) {
|
|
17
|
+
|
|
18
|
+
const noise_value = noise.call(noise_ctx,
|
|
19
|
+
x * frequency,
|
|
20
|
+
y * frequency,
|
|
21
|
+
z * frequency
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
total += noise_value * amplitude;
|
|
25
|
+
|
|
26
|
+
totalAmplitude += amplitude;
|
|
27
|
+
amplitude *= persistence;
|
|
28
|
+
frequency *= lacunarity;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return total / totalAmplitude;
|
|
32
|
+
}
|
|
33
|
+
|
|
@@ -3,43 +3,32 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { ClampToEdgeWrapping, DataTexture, RGBAFormat, UnsignedByteType } from 'three';
|
|
5
5
|
import { assert } from "../../../../core/assert.js";
|
|
6
|
+
import { copy_Sampler2D_channel_data } from "./copy_Sampler2D_channel_data.js";
|
|
7
|
+
import { Sampler2D } from "./Sampler2D.js";
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
*
|
|
10
12
|
* @param {Sampler2D} sampler
|
|
11
|
-
* @param {Number} scale
|
|
12
|
-
* @param {Number} offset
|
|
13
13
|
* @return {DataTexture}
|
|
14
14
|
*/
|
|
15
|
-
function sampler2D2Texture(sampler
|
|
15
|
+
function sampler2D2Texture(sampler) {
|
|
16
16
|
assert.notEqual(sampler, undefined, 'sampler is undefined');
|
|
17
|
-
assert.equal(typeof scale, "number", `scale must be a number, instead was '${typeof scale}'`);
|
|
18
|
-
assert.equal(typeof offset, "number", `scale must be a number, instead was '${typeof offset}'`);
|
|
19
17
|
|
|
20
18
|
const result = new DataTexture();
|
|
21
19
|
result.format = RGBAFormat;
|
|
22
20
|
|
|
23
21
|
let data;
|
|
24
22
|
|
|
25
|
-
if (
|
|
23
|
+
if (sampler.itemSize === 4) {
|
|
26
24
|
//no transformation, use a direct reference
|
|
27
25
|
data = sampler.data;
|
|
28
26
|
|
|
29
27
|
} else {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const arrayFiller = sampler.makeArrayFiller(scale, offset);
|
|
28
|
+
const dest = Sampler2D.uint8(4, sampler.width, sampler.height);
|
|
29
|
+
copy_Sampler2D_channel_data(sampler, dest);
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
let x, y;
|
|
36
|
-
|
|
37
|
-
for (y = 0; y < sampler.height; y++) {
|
|
38
|
-
for (x = 0; x < sampler.width; x++) {
|
|
39
|
-
arrayFiller(index, data, x, y);
|
|
40
|
-
index += 4;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
31
|
+
data = dest.data;
|
|
43
32
|
}
|
|
44
33
|
|
|
45
34
|
result.type = UnsignedByteType;
|