@ccp-nc/crystvis-js 0.4.13
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/.eslintrc.json +16 -0
- package/.github/workflows/test-mocha.yml +30 -0
- package/.vscode/settings.json +4 -0
- package/LICENSE +21 -0
- package/README.html +1127 -0
- package/README.md +76 -0
- package/demo/demo.css +30 -0
- package/demo/index.html +76 -0
- package/demo/main.js +143 -0
- package/docs/.nojekyll +0 -0
- package/docs-tutorials/Events.md +57 -0
- package/docs-tutorials/Queries.md +50 -0
- package/fonts/Rubik/OFL.txt +93 -0
- package/fonts/Rubik/README.txt +77 -0
- package/fonts/Rubik/Rubik-Italic-VariableFont_wght.ttf +0 -0
- package/fonts/Rubik/Rubik-VariableFont_wght.ttf +0 -0
- package/fonts/Rubik/static/Rubik-Black.ttf +0 -0
- package/fonts/Rubik/static/Rubik-BlackItalic.ttf +0 -0
- package/fonts/Rubik/static/Rubik-Bold.ttf +0 -0
- package/fonts/Rubik/static/Rubik-BoldItalic.ttf +0 -0
- package/fonts/Rubik/static/Rubik-ExtraBold.ttf +0 -0
- package/fonts/Rubik/static/Rubik-ExtraBoldItalic.ttf +0 -0
- package/fonts/Rubik/static/Rubik-Italic.ttf +0 -0
- package/fonts/Rubik/static/Rubik-Light.ttf +0 -0
- package/fonts/Rubik/static/Rubik-LightItalic.ttf +0 -0
- package/fonts/Rubik/static/Rubik-Medium.ttf +0 -0
- package/fonts/Rubik/static/Rubik-MediumItalic.ttf +0 -0
- package/fonts/Rubik/static/Rubik-Regular.ttf +0 -0
- package/fonts/Rubik/static/Rubik-SemiBold.ttf +0 -0
- package/fonts/Rubik/static/Rubik-SemiBoldItalic.ttf +0 -0
- package/index.html +25 -0
- package/index.js +11 -0
- package/jsconf.json +14 -0
- package/lib/assets/fonts/Rubik-Medium.fnt +297 -0
- package/lib/assets/fonts/Rubik-Medium.png +0 -0
- package/lib/assets/fonts/bmpfonts.in.js +16 -0
- package/lib/assets/fonts/bmpfonts.js +9 -0
- package/lib/assets/fonts/font.js +82 -0
- package/lib/assets/fonts/index.js +14 -0
- package/lib/assets/fonts/threebmfont.js +28 -0
- package/lib/data.js +125 -0
- package/lib/formats/cell.js +114 -0
- package/lib/formats/cif.js +22 -0
- package/lib/formats/magres.js +337 -0
- package/lib/formats/xyz.js +124 -0
- package/lib/loader.js +87 -0
- package/lib/model.js +2076 -0
- package/lib/modelview.js +382 -0
- package/lib/nmrdata.js +2898 -0
- package/lib/orbit.js +1233 -0
- package/lib/primitives/atoms.js +261 -0
- package/lib/primitives/cell.js +160 -0
- package/lib/primitives/dither.js +156 -0
- package/lib/primitives/ellipsoid.js +183 -0
- package/lib/primitives/geometries.js +20 -0
- package/lib/primitives/index.js +48 -0
- package/lib/primitives/isosurface.js +171 -0
- package/lib/primitives/shapes.js +100 -0
- package/lib/primitives/sprites.js +172 -0
- package/lib/query.js +158 -0
- package/lib/render.js +440 -0
- package/lib/selbox.js +361 -0
- package/lib/shaders/aura.frag +26 -0
- package/lib/shaders/aura.vert +37 -0
- package/lib/shaders/dither.frag +42 -0
- package/lib/shaders/dither.vert +8 -0
- package/lib/shaders/index.in.js +17 -0
- package/lib/shaders/index.js +25 -0
- package/lib/shaders/msdf300.frag +25 -0
- package/lib/shaders/msdf300.vert +45 -0
- package/lib/tensor.js +227 -0
- package/lib/utils.js +168 -0
- package/lib/visualizer.js +480 -0
- package/package.json +106 -0
- package/scripts/build-bundle.js +17 -0
- package/scripts/build-fonts.js +43 -0
- package/scripts/build-resources.js +46 -0
- package/scripts/plugins-shim.js +10 -0
- package/test/chemdata.js +69 -0
- package/test/data/CHA.cif +74 -0
- package/test/data/H2O.xyz +8 -0
- package/test/data/H2_bound.xyz +4 -0
- package/test/data/ethanol.cell +25 -0
- package/test/data/ethanol.magres +238 -0
- package/test/data/example_single.cif +789 -0
- package/test/data/frac.cell +8 -0
- package/test/data/org.cif +427 -0
- package/test/data/pyridine.xyz +13 -0
- package/test/data/si8.xyz +10 -0
- package/test/loader.js +107 -0
- package/test/model.js +368 -0
- package/test/query.js +135 -0
- package/test/tensor.js +133 -0
- package/test/test-html/examples.js +1485 -0
- package/test/test-html/index.html +33 -0
- package/test/test-html/index.js +279 -0
- package/tools/compile_colors.py +120 -0
- package/tools/compile_periodic.py +96 -0
- package/tools/ptable.json +497 -0
- package/tools/test +5844 -0
package/lib/selbox.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Selection box handling for the renderer. Taken from the THREE
|
|
5
|
+
* example files in
|
|
6
|
+
*
|
|
7
|
+
* 'three/examples/jsm/interactive/SelectionBox.js'
|
|
8
|
+
* 'three/examples/jsm/interactive/SelectionHelper.js'
|
|
9
|
+
*
|
|
10
|
+
* but slightly customised for the specific needs of this app.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
Frustum,
|
|
17
|
+
Vector3,
|
|
18
|
+
Vector2
|
|
19
|
+
} from 'three';
|
|
20
|
+
import $ from 'jquery';
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
AtomMesh
|
|
24
|
+
} from './primitives/index.js';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* This is a class to check whether objects are in a selection area in 3D space
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
var SelectionBox = (function() {
|
|
31
|
+
|
|
32
|
+
var frustum = new Frustum();
|
|
33
|
+
var center = new Vector3();
|
|
34
|
+
|
|
35
|
+
var tmpPoint = new Vector3();
|
|
36
|
+
|
|
37
|
+
var vecNear = new Vector3();
|
|
38
|
+
var vecTopLeft = new Vector3();
|
|
39
|
+
var vecTopRight = new Vector3();
|
|
40
|
+
var vecDownRight = new Vector3();
|
|
41
|
+
var vecDownLeft = new Vector3();
|
|
42
|
+
|
|
43
|
+
var vecFarTopLeft = new Vector3();
|
|
44
|
+
var vecFarTopRight = new Vector3();
|
|
45
|
+
var vecFarDownRight = new Vector3();
|
|
46
|
+
var vecFarDownLeft = new Vector3();
|
|
47
|
+
|
|
48
|
+
var vectemp1 = new Vector3();
|
|
49
|
+
var vectemp2 = new Vector3();
|
|
50
|
+
var vectemp3 = new Vector3();
|
|
51
|
+
|
|
52
|
+
function SelectionBox(camera, scene, deep) {
|
|
53
|
+
|
|
54
|
+
this.camera = camera;
|
|
55
|
+
this.scene = scene;
|
|
56
|
+
this.startPoint = new Vector3();
|
|
57
|
+
this.endPoint = new Vector3();
|
|
58
|
+
this.collection = [];
|
|
59
|
+
this.deep = deep || Number.MAX_VALUE;
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
SelectionBox.prototype.select = function(startPoint, endPoint, target = null) {
|
|
64
|
+
|
|
65
|
+
this.startPoint = startPoint || this.startPoint;
|
|
66
|
+
this.endPoint = endPoint || this.endPoint;
|
|
67
|
+
this.collection = [];
|
|
68
|
+
|
|
69
|
+
target = target || this.scene;
|
|
70
|
+
|
|
71
|
+
this.updateFrustum(this.startPoint, this.endPoint);
|
|
72
|
+
this.searchChildInFrustum(frustum, target);
|
|
73
|
+
|
|
74
|
+
return this.collection;
|
|
75
|
+
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
SelectionBox.prototype.updateFrustum = function(startPoint, endPoint) {
|
|
79
|
+
|
|
80
|
+
startPoint = startPoint || this.startPoint;
|
|
81
|
+
endPoint = endPoint || this.endPoint;
|
|
82
|
+
|
|
83
|
+
// Avoid invalid frustum
|
|
84
|
+
|
|
85
|
+
if (startPoint.x === endPoint.x) {
|
|
86
|
+
|
|
87
|
+
endPoint.x += Number.EPSILON;
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (startPoint.y === endPoint.y) {
|
|
92
|
+
|
|
93
|
+
endPoint.y += Number.EPSILON;
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.camera.updateProjectionMatrix();
|
|
98
|
+
this.camera.updateMatrixWorld();
|
|
99
|
+
|
|
100
|
+
if (this.camera.isPerspectiveCamera) {
|
|
101
|
+
|
|
102
|
+
tmpPoint.copy(startPoint);
|
|
103
|
+
tmpPoint.x = Math.min(startPoint.x, endPoint.x);
|
|
104
|
+
tmpPoint.y = Math.max(startPoint.y, endPoint.y);
|
|
105
|
+
endPoint.x = Math.max(startPoint.x, endPoint.x);
|
|
106
|
+
endPoint.y = Math.min(startPoint.y, endPoint.y);
|
|
107
|
+
|
|
108
|
+
vecNear.setFromMatrixPosition(this.camera.matrixWorld);
|
|
109
|
+
vecTopLeft.copy(tmpPoint);
|
|
110
|
+
vecTopRight.set(endPoint.x, tmpPoint.y, 0);
|
|
111
|
+
vecDownRight.copy(endPoint);
|
|
112
|
+
vecDownLeft.set(tmpPoint.x, endPoint.y, 0);
|
|
113
|
+
|
|
114
|
+
vecTopLeft.unproject(this.camera);
|
|
115
|
+
vecTopRight.unproject(this.camera);
|
|
116
|
+
vecDownRight.unproject(this.camera);
|
|
117
|
+
vecDownLeft.unproject(this.camera);
|
|
118
|
+
|
|
119
|
+
vectemp1.copy(vecTopLeft).sub(vecNear);
|
|
120
|
+
vectemp2.copy(vecTopRight).sub(vecNear);
|
|
121
|
+
vectemp3.copy(vecDownRight).sub(vecNear);
|
|
122
|
+
vectemp1.normalize();
|
|
123
|
+
vectemp2.normalize();
|
|
124
|
+
vectemp3.normalize();
|
|
125
|
+
|
|
126
|
+
vectemp1.multiplyScalar(this.deep);
|
|
127
|
+
vectemp2.multiplyScalar(this.deep);
|
|
128
|
+
vectemp3.multiplyScalar(this.deep);
|
|
129
|
+
vectemp1.add(vecNear);
|
|
130
|
+
vectemp2.add(vecNear);
|
|
131
|
+
vectemp3.add(vecNear);
|
|
132
|
+
|
|
133
|
+
let planes = frustum.planes;
|
|
134
|
+
|
|
135
|
+
planes[0].setFromCoplanarPoints(vecNear, vecTopLeft, vecTopRight);
|
|
136
|
+
planes[1].setFromCoplanarPoints(vecNear, vecTopRight, vecDownRight);
|
|
137
|
+
planes[2].setFromCoplanarPoints(vecDownRight, vecDownLeft, vecNear);
|
|
138
|
+
planes[3].setFromCoplanarPoints(vecDownLeft, vecTopLeft, vecNear);
|
|
139
|
+
planes[4].setFromCoplanarPoints(vecTopRight, vecDownRight, vecDownLeft);
|
|
140
|
+
planes[5].setFromCoplanarPoints(vectemp3, vectemp2, vectemp1);
|
|
141
|
+
planes[5].normal.multiplyScalar(-1);
|
|
142
|
+
|
|
143
|
+
} else if (this.camera.isOrthographicCamera) {
|
|
144
|
+
|
|
145
|
+
var left = Math.min(startPoint.x, endPoint.x);
|
|
146
|
+
var top = Math.max(startPoint.y, endPoint.y);
|
|
147
|
+
var right = Math.max(startPoint.x, endPoint.x);
|
|
148
|
+
var down = Math.min(startPoint.y, endPoint.y);
|
|
149
|
+
|
|
150
|
+
vecTopLeft.set(left, top, -1);
|
|
151
|
+
vecTopRight.set(right, top, -1);
|
|
152
|
+
vecDownRight.set(right, down, -1);
|
|
153
|
+
vecDownLeft.set(left, down, -1);
|
|
154
|
+
|
|
155
|
+
vecFarTopLeft.set(left, top, 1);
|
|
156
|
+
vecFarTopRight.set(right, top, 1);
|
|
157
|
+
vecFarDownRight.set(right, down, 1);
|
|
158
|
+
vecFarDownLeft.set(left, down, 1);
|
|
159
|
+
|
|
160
|
+
vecTopLeft.unproject(this.camera);
|
|
161
|
+
vecTopRight.unproject(this.camera);
|
|
162
|
+
vecDownRight.unproject(this.camera);
|
|
163
|
+
vecDownLeft.unproject(this.camera);
|
|
164
|
+
|
|
165
|
+
vecFarTopLeft.unproject(this.camera);
|
|
166
|
+
vecFarTopRight.unproject(this.camera);
|
|
167
|
+
vecFarDownRight.unproject(this.camera);
|
|
168
|
+
vecFarDownLeft.unproject(this.camera);
|
|
169
|
+
|
|
170
|
+
let planes = frustum.planes;
|
|
171
|
+
|
|
172
|
+
planes[0].setFromCoplanarPoints(vecTopLeft, vecFarTopLeft, vecFarTopRight);
|
|
173
|
+
planes[1].setFromCoplanarPoints(vecTopRight, vecFarTopRight, vecFarDownRight);
|
|
174
|
+
planes[2].setFromCoplanarPoints(vecFarDownRight, vecFarDownLeft, vecDownLeft);
|
|
175
|
+
planes[3].setFromCoplanarPoints(vecFarDownLeft, vecFarTopLeft, vecTopLeft);
|
|
176
|
+
planes[4].setFromCoplanarPoints(vecTopRight, vecDownRight, vecDownLeft);
|
|
177
|
+
planes[5].setFromCoplanarPoints(vecFarDownRight, vecFarTopRight, vecFarTopLeft);
|
|
178
|
+
planes[5].normal.multiplyScalar(-1);
|
|
179
|
+
|
|
180
|
+
} else {
|
|
181
|
+
|
|
182
|
+
console.error('THREE.SelectionBox: Unsupported camera type.');
|
|
183
|
+
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
SelectionBox.prototype.searchChildInFrustum = function(frustum, object) {
|
|
189
|
+
|
|
190
|
+
if (object instanceof AtomMesh) {
|
|
191
|
+
|
|
192
|
+
if (object.material !== undefined) {
|
|
193
|
+
|
|
194
|
+
if (object.geometry.boundingSphere === null) object.geometry.computeBoundingSphere();
|
|
195
|
+
|
|
196
|
+
center.copy(object.geometry.boundingSphere.center);
|
|
197
|
+
|
|
198
|
+
center.applyMatrix4(object.matrixWorld);
|
|
199
|
+
|
|
200
|
+
if (frustum.containsPoint(center)) {
|
|
201
|
+
|
|
202
|
+
this.collection.push(object);
|
|
203
|
+
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (object.children.length > 0) {
|
|
211
|
+
|
|
212
|
+
for (var x = 0; x < object.children.length; x++) {
|
|
213
|
+
|
|
214
|
+
this.searchChildInFrustum(frustum, object.children[x]);
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return SelectionBox;
|
|
223
|
+
|
|
224
|
+
})();
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
var SelectionHelper = (function() {
|
|
228
|
+
|
|
229
|
+
function SelectionHelper(selectionBox, renderer, cssClassName) {
|
|
230
|
+
|
|
231
|
+
this.element = $('<div>');
|
|
232
|
+
this.element.addClass(cssClassName);
|
|
233
|
+
|
|
234
|
+
this.element.css({
|
|
235
|
+
'position': 'fixed',
|
|
236
|
+
'pointerEvents': 'none',
|
|
237
|
+
'display': 'none',
|
|
238
|
+
'border-width': '1px',
|
|
239
|
+
'border-style': 'solid',
|
|
240
|
+
'background-color': 'rgb(255, 0, 0)', // Default style
|
|
241
|
+
'opacity': 0.5
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
this.minBoxSize = 10.0;
|
|
245
|
+
|
|
246
|
+
this.renderer = renderer;
|
|
247
|
+
this.domElement = this.renderer._r.domElement;
|
|
248
|
+
this.domElement.parentElement.appendChild(this.element.get(0));
|
|
249
|
+
|
|
250
|
+
this.selBox = selectionBox;
|
|
251
|
+
|
|
252
|
+
this.startPoint = new Vector2();
|
|
253
|
+
this.pointTopLeft = new Vector2();
|
|
254
|
+
this.pointBottomRight = new Vector2();
|
|
255
|
+
|
|
256
|
+
this.isDown = false;
|
|
257
|
+
this.selectOverCallback = null;
|
|
258
|
+
|
|
259
|
+
this.domElement.addEventListener('pointerdown', function(event) {
|
|
260
|
+
|
|
261
|
+
if (event.shiftKey) {
|
|
262
|
+
this.isDown = true;
|
|
263
|
+
this.onSelectStart(event);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
}.bind(this), false);
|
|
267
|
+
|
|
268
|
+
this.domElement.addEventListener('pointermove', function(event) {
|
|
269
|
+
|
|
270
|
+
if (this.isDown && event.shiftKey) {
|
|
271
|
+
|
|
272
|
+
this.onSelectMove(event);
|
|
273
|
+
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
}.bind(this), false);
|
|
277
|
+
|
|
278
|
+
this.domElement.addEventListener('pointerup', function(event) {
|
|
279
|
+
|
|
280
|
+
if (this.isDown && event.shiftKey) {
|
|
281
|
+
this.isDown = false;
|
|
282
|
+
this.onSelectOver(event);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
}.bind(this), false);
|
|
286
|
+
|
|
287
|
+
this.domElement.addEventListener('keyup', function(event) {
|
|
288
|
+
|
|
289
|
+
if (event.key == 'Shift' && this.isDown) {
|
|
290
|
+
this.isDown = false;
|
|
291
|
+
this.onSelectOver(event);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
}.bind(this), false);
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
SelectionHelper.prototype.onSelectStart = function(event) {
|
|
299
|
+
|
|
300
|
+
this.element.css({
|
|
301
|
+
'display': 'block',
|
|
302
|
+
'left': event.clientX + 'px',
|
|
303
|
+
'top': event.clientY + 'px',
|
|
304
|
+
'width': '0px',
|
|
305
|
+
'height': '0px'
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
this.startPoint.x = event.clientX;
|
|
309
|
+
this.startPoint.y = event.clientY;
|
|
310
|
+
|
|
311
|
+
this.pointBottomRight.x = this.startPoint.x;
|
|
312
|
+
this.pointBottomRight.y = this.startPoint.y;
|
|
313
|
+
this.pointTopLeft.x = this.startPoint.x;
|
|
314
|
+
this.pointTopLeft.y = this.startPoint.y;
|
|
315
|
+
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
SelectionHelper.prototype.onSelectMove = function(event) {
|
|
319
|
+
|
|
320
|
+
this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX);
|
|
321
|
+
this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY);
|
|
322
|
+
this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX);
|
|
323
|
+
this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY);
|
|
324
|
+
|
|
325
|
+
this.element.css({
|
|
326
|
+
'left': this.pointTopLeft.x + 'px',
|
|
327
|
+
'top': this.pointTopLeft.y + 'px',
|
|
328
|
+
'width': (this.pointBottomRight.x - this.pointTopLeft.x) + 'px',
|
|
329
|
+
'height': (this.pointBottomRight.y - this.pointTopLeft.y) + 'px'
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
SelectionHelper.prototype.onSelectOver = function() {
|
|
335
|
+
|
|
336
|
+
this.element.css('display', 'none');
|
|
337
|
+
|
|
338
|
+
if (this.selectOverCallback) {
|
|
339
|
+
|
|
340
|
+
var p1 = this.renderer.documentToWorld(this.pointBottomRight.x, this.pointBottomRight.y);
|
|
341
|
+
var p2 = this.renderer.documentToWorld(this.pointTopLeft.x, this.pointTopLeft.y);
|
|
342
|
+
|
|
343
|
+
// Skip if they're too close
|
|
344
|
+
var boxSize = Math.abs(this.pointBottomRight.x - this.pointTopLeft.x) +
|
|
345
|
+
Math.abs(this.pointBottomRight.y - this.pointTopLeft.y);
|
|
346
|
+
|
|
347
|
+
if (boxSize > this.minBoxSize)
|
|
348
|
+
this.selectOverCallback(p1, p2);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
return SelectionHelper;
|
|
354
|
+
|
|
355
|
+
})();
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
export {
|
|
359
|
+
SelectionBox,
|
|
360
|
+
SelectionHelper
|
|
361
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#version 300 es
|
|
2
|
+
|
|
3
|
+
precision highp float;
|
|
4
|
+
|
|
5
|
+
uniform float opacity;
|
|
6
|
+
uniform vec3 fill;
|
|
7
|
+
uniform vec3 border;
|
|
8
|
+
uniform float border_f;
|
|
9
|
+
in vec2 vUv;
|
|
10
|
+
out vec4 myOutputColor;
|
|
11
|
+
|
|
12
|
+
void main() {
|
|
13
|
+
|
|
14
|
+
vec2 r = vUv-vec2(0.5, 0.5);
|
|
15
|
+
float rnorm = sqrt(r.x*r.x+r.y*r.y)*2.0;
|
|
16
|
+
|
|
17
|
+
if (rnorm > 1.0-border_f) {
|
|
18
|
+
myOutputColor.rgb = border;
|
|
19
|
+
myOutputColor.a = 1.0;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
myOutputColor.rgb = fill;
|
|
23
|
+
myOutputColor.a = opacity;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#version 300 es
|
|
2
|
+
|
|
3
|
+
in vec2 uv;
|
|
4
|
+
in vec4 position;
|
|
5
|
+
uniform mat4 projectionMatrix;
|
|
6
|
+
uniform mat4 modelViewMatrix;
|
|
7
|
+
uniform float targScale;
|
|
8
|
+
uniform float targRadius;
|
|
9
|
+
out vec2 vUv;
|
|
10
|
+
|
|
11
|
+
float smax( float a, float b, float k )
|
|
12
|
+
{
|
|
13
|
+
float h = clamp( 0.5+0.5*(a-b)/k, 0.0, 1.0 );
|
|
14
|
+
return k*h*(1.0-h)+mix( b, a, h );
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void main() {
|
|
18
|
+
vUv = uv;
|
|
19
|
+
|
|
20
|
+
mat4 mView = modelViewMatrix;
|
|
21
|
+
float s = targScale;
|
|
22
|
+
float h = 2.0/projectionMatrix[1][1];
|
|
23
|
+
// We use a smooth maximum to make it so that the aura is as big as
|
|
24
|
+
// targScale times the height of the screen in the zoom out limit, but also
|
|
25
|
+
// always slightly bigger than the size of the atom itself.
|
|
26
|
+
s = smax(s*h, 1.1*targRadius, targRadius);
|
|
27
|
+
|
|
28
|
+
for (int i = 0; i < 3; ++i) {
|
|
29
|
+
for (int j = 0; j < 3; ++j) {
|
|
30
|
+
|
|
31
|
+
mView[i][j] = (i == j)? s : 0.0;
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
gl_Position = projectionMatrix * mView * position;
|
|
37
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
uniform vec3 color;
|
|
2
|
+
uniform float opacity;
|
|
3
|
+
uniform float illum;
|
|
4
|
+
uniform vec2 shift;
|
|
5
|
+
uniform float ditherN;
|
|
6
|
+
uniform bool netting;
|
|
7
|
+
uniform float netScale;
|
|
8
|
+
uniform sampler2D ditherTex;
|
|
9
|
+
|
|
10
|
+
varying vec3 vNormal;
|
|
11
|
+
varying highp vec2 vUv;
|
|
12
|
+
|
|
13
|
+
void main() {
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
// This shader simply checks the coordinates on screen of the pixel to be drawn
|
|
17
|
+
// and discards it based on the dithering matrix and alpha value if it has to be transparent.
|
|
18
|
+
// In this way we go round all the complexities of intersecting transparent solids with much greater efficiency.
|
|
19
|
+
// Check Wikipedias article on ordered dithering for further reference.
|
|
20
|
+
vec2 ditherCoords;
|
|
21
|
+
if (netting) {
|
|
22
|
+
ditherCoords = vUv*ditherN*netScale;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
ditherCoords = gl_FragCoord.xy;
|
|
26
|
+
}
|
|
27
|
+
float iN = mod(ditherCoords.x+shift.x, ditherN)/ditherN;
|
|
28
|
+
float jN = mod(ditherCoords.y+shift.y, ditherN)/ditherN;
|
|
29
|
+
vec4 ditherCol = texture2D(ditherTex, vec2(iN, jN));
|
|
30
|
+
|
|
31
|
+
if (ditherCol.r > opacity)
|
|
32
|
+
discard;
|
|
33
|
+
// Lighting is also handled very simply, just a fraction of front illumination + ambient light.
|
|
34
|
+
// This mostly because for some reason I cant get it to work with proper lighting (possibly a bug in THREE.js).
|
|
35
|
+
vec3 light = cameraPosition;
|
|
36
|
+
light = normalize(light);
|
|
37
|
+
float dProd = max(0., dot(light, vNormal));
|
|
38
|
+
// We combine everything in the final color
|
|
39
|
+
|
|
40
|
+
gl_FragColor = vec4(color*((dProd-1.)*illum+1.), 1.);
|
|
41
|
+
|
|
42
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import ditherFragShader from './dither.frag';
|
|
4
|
+
import ditherVertShader from './dither.vert';
|
|
5
|
+
import msdfFragShader from './msdf300.frag';
|
|
6
|
+
import msdfVertShader from './msdf300.vert';
|
|
7
|
+
import auraFragShader from './aura.frag';
|
|
8
|
+
import auraVertShader from './aura.vert';
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
ditherFragShader,
|
|
12
|
+
ditherVertShader,
|
|
13
|
+
msdfFragShader,
|
|
14
|
+
msdfVertShader,
|
|
15
|
+
auraFragShader,
|
|
16
|
+
auraVertShader
|
|
17
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// lib/shaders/dither.frag
|
|
2
|
+
var dither_default = "uniform vec3 color;\nuniform float opacity;\nuniform float illum;\nuniform vec2 shift;\nuniform float ditherN;\nuniform bool netting;\nuniform float netScale;\nuniform sampler2D ditherTex;\n\nvarying vec3 vNormal;\nvarying highp vec2 vUv;\n\nvoid main() {\n\n\n// This shader simply checks the coordinates on screen of the pixel to be drawn\n// and discards it based on the dithering matrix and alpha value if it has to be transparent.\n// In this way we go round all the complexities of intersecting transparent solids with much greater efficiency.\n// Check Wikipedias article on ordered dithering for further reference.\n vec2 ditherCoords;\n if (netting) {\n ditherCoords = vUv*ditherN*netScale;\n }\n else {\n ditherCoords = gl_FragCoord.xy;\n }\n float iN = mod(ditherCoords.x+shift.x, ditherN)/ditherN;\n float jN = mod(ditherCoords.y+shift.y, ditherN)/ditherN;\n vec4 ditherCol = texture2D(ditherTex, vec2(iN, jN));\n\n if (ditherCol.r > opacity)\n discard;\n// Lighting is also handled very simply, just a fraction of front illumination + ambient light.\n// This mostly because for some reason I cant get it to work with proper lighting (possibly a bug in THREE.js).\n vec3 light = cameraPosition;\n light = normalize(light);\n float dProd = max(0., dot(light, vNormal));\n// We combine everything in the final color\n\n gl_FragColor = vec4(color*((dProd-1.)*illum+1.), 1.);\n\n}";
|
|
3
|
+
|
|
4
|
+
// lib/shaders/dither.vert
|
|
5
|
+
var dither_default2 = "varying vec3 vNormal;\nvarying highp vec2 vUv;\n\nvoid main() {\n vNormal = normal;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);\n vUv = uv;\n}";
|
|
6
|
+
|
|
7
|
+
// lib/shaders/msdf300.frag
|
|
8
|
+
var msdf300_default = "#version 300 es\n\n// GLSL 3.0 compliant version of the MSDF shader from three-bmfont-text\n// Taken from https://github.com/Jam3/three-bmfont-text/issues/38\n\nprecision highp float;\n\nuniform float opacity;\nuniform vec3 color;\nuniform sampler2D map;\nin vec2 vUv;\nout vec4 myOutputColor;\n\nfloat median(float r, float g, float b) {\n return max(min(r, g), min(max(r, g), b));\n}\n\nvoid main() {\n vec3 s = texture(map, vUv).rgb;\n float sigDist = median(s.r, s.g, s.b) - 0.5;\n float alpha = clamp(sigDist/fwidth(sigDist) + 0.5, 0.0, 1.0);\n \n myOutputColor = vec4(color.xyz, alpha * opacity);\n if (myOutputColor.a < 0.0001) discard;\n}";
|
|
9
|
+
|
|
10
|
+
// lib/shaders/msdf300.vert
|
|
11
|
+
var msdf300_default2 = "#version 300 es\n\n// GLSL 3.0 compliant version of the MSDF shader from three-bmfont-text\n// Taken from https://github.com/Jam3/three-bmfont-text/issues/38\n\nin vec2 uv;\nin vec4 position;\nuniform mat4 projectionMatrix;\nuniform mat4 modelViewMatrix;\nuniform float targScale;\nuniform bool fixRotation;\nuniform bool fixScale;\nuniform vec3 shift;\nout vec2 vUv;\n\nvoid main() {\n vUv = uv;\n\n mat4 mView = modelViewMatrix;\n float s = targScale;\n\n // When the scale is fixed, we make sure s and projection matrix cancel each other out\n s = fixScale? s*2.0/projectionMatrix[1][1] : s;\n\n // If rotation is fixed, the modelView matrix is made to contain scaling only\n if (fixRotation) {\n for (int i = 0; i < 3; ++i) {\n for (int j = 0; j < 3; ++j) {\n\n mView[i][j] = (i == j)? s : 0.0;\n\n if (i == 1) {\n mView[i][j] = -mView[i][j];\n }\n }\n }\n }\n\n vec4 shift4 = vec4(0.,0.,0.,0.);\n // The shift is scaled so that it follows the camera's zoom\n vec4 pMshift = vec4(projectionMatrix[0][0], projectionMatrix[1][1], projectionMatrix[2][2], 1);\n shift4.xyz = shift;\n\n gl_Position = projectionMatrix * mView * position + shift4 * pMshift;\n}";
|
|
12
|
+
|
|
13
|
+
// lib/shaders/aura.frag
|
|
14
|
+
var aura_default = "#version 300 es\n\nprecision highp float;\n\nuniform float opacity;\nuniform vec3 fill;\nuniform vec3 border;\nuniform float border_f;\nin vec2 vUv;\nout vec4 myOutputColor;\n\nvoid main() {\n \n vec2 r = vUv-vec2(0.5, 0.5);\n float rnorm = sqrt(r.x*r.x+r.y*r.y)*2.0;\n\n if (rnorm > 1.0-border_f) {\n myOutputColor.rgb = border;\n myOutputColor.a = 1.0;\n }\n else {\n myOutputColor.rgb = fill;\n myOutputColor.a = opacity;\n }\n\n}";
|
|
15
|
+
|
|
16
|
+
// lib/shaders/aura.vert
|
|
17
|
+
var aura_default2 = "#version 300 es\n\nin vec2 uv;\nin vec4 position;\nuniform mat4 projectionMatrix;\nuniform mat4 modelViewMatrix;\nuniform float targScale;\nuniform float targRadius;\nout vec2 vUv;\n\nfloat smax( float a, float b, float k )\n{\n float h = clamp( 0.5+0.5*(a-b)/k, 0.0, 1.0 );\n return k*h*(1.0-h)+mix( b, a, h );\n}\n\nvoid main() {\n vUv = uv;\n\n mat4 mView = modelViewMatrix;\n float s = targScale;\n float h = 2.0/projectionMatrix[1][1];\n // We use a smooth maximum to make it so that the aura is as big as\n // targScale times the height of the screen in the zoom out limit, but also\n // always slightly bigger than the size of the atom itself.\n s = smax(s*h, 1.1*targRadius, targRadius);\n\n for (int i = 0; i < 3; ++i) {\n for (int j = 0; j < 3; ++j) {\n\n mView[i][j] = (i == j)? s : 0.0;\n\n }\n }\n\n gl_Position = projectionMatrix * mView * position;\n}";
|
|
18
|
+
export {
|
|
19
|
+
aura_default as auraFragShader,
|
|
20
|
+
aura_default2 as auraVertShader,
|
|
21
|
+
dither_default as ditherFragShader,
|
|
22
|
+
dither_default2 as ditherVertShader,
|
|
23
|
+
msdf300_default as msdfFragShader,
|
|
24
|
+
msdf300_default2 as msdfVertShader
|
|
25
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#version 300 es
|
|
2
|
+
|
|
3
|
+
// GLSL 3.0 compliant version of the MSDF shader from three-bmfont-text
|
|
4
|
+
// Taken from https://github.com/Jam3/three-bmfont-text/issues/38
|
|
5
|
+
|
|
6
|
+
precision highp float;
|
|
7
|
+
|
|
8
|
+
uniform float opacity;
|
|
9
|
+
uniform vec3 color;
|
|
10
|
+
uniform sampler2D map;
|
|
11
|
+
in vec2 vUv;
|
|
12
|
+
out vec4 myOutputColor;
|
|
13
|
+
|
|
14
|
+
float median(float r, float g, float b) {
|
|
15
|
+
return max(min(r, g), min(max(r, g), b));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void main() {
|
|
19
|
+
vec3 s = texture(map, vUv).rgb;
|
|
20
|
+
float sigDist = median(s.r, s.g, s.b) - 0.5;
|
|
21
|
+
float alpha = clamp(sigDist/fwidth(sigDist) + 0.5, 0.0, 1.0);
|
|
22
|
+
|
|
23
|
+
myOutputColor = vec4(color.xyz, alpha * opacity);
|
|
24
|
+
if (myOutputColor.a < 0.0001) discard;
|
|
25
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#version 300 es
|
|
2
|
+
|
|
3
|
+
// GLSL 3.0 compliant version of the MSDF shader from three-bmfont-text
|
|
4
|
+
// Taken from https://github.com/Jam3/three-bmfont-text/issues/38
|
|
5
|
+
|
|
6
|
+
in vec2 uv;
|
|
7
|
+
in vec4 position;
|
|
8
|
+
uniform mat4 projectionMatrix;
|
|
9
|
+
uniform mat4 modelViewMatrix;
|
|
10
|
+
uniform float targScale;
|
|
11
|
+
uniform bool fixRotation;
|
|
12
|
+
uniform bool fixScale;
|
|
13
|
+
uniform vec3 shift;
|
|
14
|
+
out vec2 vUv;
|
|
15
|
+
|
|
16
|
+
void main() {
|
|
17
|
+
vUv = uv;
|
|
18
|
+
|
|
19
|
+
mat4 mView = modelViewMatrix;
|
|
20
|
+
float s = targScale;
|
|
21
|
+
|
|
22
|
+
// When the scale is fixed, we make sure s and projection matrix cancel each other out
|
|
23
|
+
s = fixScale? s*2.0/projectionMatrix[1][1] : s;
|
|
24
|
+
|
|
25
|
+
// If rotation is fixed, the modelView matrix is made to contain scaling only
|
|
26
|
+
if (fixRotation) {
|
|
27
|
+
for (int i = 0; i < 3; ++i) {
|
|
28
|
+
for (int j = 0; j < 3; ++j) {
|
|
29
|
+
|
|
30
|
+
mView[i][j] = (i == j)? s : 0.0;
|
|
31
|
+
|
|
32
|
+
if (i == 1) {
|
|
33
|
+
mView[i][j] = -mView[i][j];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
vec4 shift4 = vec4(0.,0.,0.,0.);
|
|
40
|
+
// The shift is scaled so that it follows the camera's zoom
|
|
41
|
+
vec4 pMshift = vec4(projectionMatrix[0][0], projectionMatrix[1][1], projectionMatrix[2][2], 1);
|
|
42
|
+
shift4.xyz = shift;
|
|
43
|
+
|
|
44
|
+
gl_Position = projectionMatrix * mView * position + shift4 * pMshift;
|
|
45
|
+
}
|