11
11
var glslify = require ( 'glslify' ) ;
12
12
var c = require ( './constants' ) ;
13
13
var vertexShaderSource = glslify ( './shaders/vertex.glsl' ) ;
14
+ var contextShaderSource = glslify ( './shaders/context_vertex.glsl' ) ;
14
15
var pickVertexShaderSource = glslify ( './shaders/pick_vertex.glsl' ) ;
15
16
var fragmentShaderSource = glslify ( './shaders/fragment.glsl' ) ;
16
17
@@ -19,6 +20,8 @@ var depthLimitEpsilon = 1e-6; // don't change; otherwise near/far plane lines ar
19
20
var gpuDimensionCount = 64 ;
20
21
var sectionVertexCount = 2 ;
21
22
var vec4NumberCount = 4 ;
23
+ var bitsPerByte = 8 ;
24
+ var channelCount = gpuDimensionCount / bitsPerByte ; // == 8 bytes needed to have 64 bits
22
25
23
26
var contextColor = [ 119 , 119 , 119 ] ; // middle gray to not drawn the focus; looks good on a black or white background
24
27
@@ -165,7 +168,7 @@ function valid(i, offset, panelCount) {
165
168
return i + offset <= panelCount ;
166
169
}
167
170
168
- module . exports = function ( canvasGL , d , scatter ) {
171
+ module . exports = function ( canvasGL , d ) {
169
172
var model = d . model ,
170
173
vm = d . viewModel ,
171
174
domain = model . domain ;
@@ -263,7 +266,7 @@ module.exports = function(canvasGL, d, scatter) {
263
266
264
267
dither : false ,
265
268
266
- vert : pick ? pickVertexShaderSource : vertexShaderSource ,
269
+ vert : pick ? pickVertexShaderSource : context ? contextShaderSource : vertexShaderSource ,
267
270
268
271
frag : fragmentShaderSource ,
269
272
@@ -291,8 +294,8 @@ module.exports = function(canvasGL, d, scatter) {
291
294
loD : regl . prop ( 'loD' ) ,
292
295
hiD : regl . prop ( 'hiD' ) ,
293
296
palette : paletteTexture ,
294
- colorClamp : regl . prop ( 'colorClamp ' ) ,
295
- scatter : regl . prop ( 'scatter ' )
297
+ mask : regl . prop ( 'maskTexture ' ) ,
298
+ colorClamp : regl . prop ( 'colorClamp ' )
296
299
} ,
297
300
offset : regl . prop ( 'offset' ) ,
298
301
count : regl . prop ( 'count' )
@@ -307,7 +310,7 @@ module.exports = function(canvasGL, d, scatter) {
307
310
308
311
var previousAxisOrder = [ ] ;
309
312
310
- function makeItem ( i , ii , x , y , panelSizeX , canvasPanelSizeY , crossfilterDimensionIndex , scatter , I , leftmost , rightmost ) {
313
+ function makeItem ( i , ii , x , y , panelSizeX , canvasPanelSizeY , crossfilterDimensionIndex , I , leftmost , rightmost ) {
311
314
var loHi , abcd , d , index ;
312
315
var leftRight = [ i , ii ] ;
313
316
var filterEpsilon = c . verticalPadding / canvasPanelSizeY ;
@@ -321,12 +324,16 @@ module.exports = function(canvasGL, d, scatter) {
321
324
for ( d = 0 ; d < 16 ; d ++ ) {
322
325
var dimP = d + 16 * abcd ;
323
326
dims [ loHi ] [ abcd ] [ d ] = d + 16 * abcd === index ? 1 : 0 ;
324
- lims [ loHi ] [ abcd ] [ d ] = ( ! context && valid ( d , 16 * abcd , panelCount ) ? initialDims [ dimP === 0 ? 0 : 1 + ( ( dimP - 1 ) % ( initialDims . length - 1 ) ) ] . brush . filter . getBounds ( ) [ loHi ] : loHi ) + ( 2 * loHi - 1 ) * filterEpsilon ;
327
+ if ( ! context ) {
328
+ lims [ loHi ] [ abcd ] [ d ] = ( valid ( d , 16 * abcd , panelCount ) ? initialDims [ dimP === 0 ? 0 : 1 + ( ( dimP - 1 ) % ( initialDims . length - 1 ) ) ] . brush . filter . getBounds ( ) [ loHi ] : loHi ) + ( 2 * loHi - 1 ) * filterEpsilon ;
329
+ }
325
330
}
326
331
}
327
332
}
328
333
329
- return {
334
+ var mask , maskTexture ;
335
+
336
+ var vm = {
330
337
key : crossfilterDimensionIndex ,
331
338
resolution : [ canvasWidth , canvasHeight ] ,
332
339
viewBoxPosition : [ x + overdrag , y ] ,
@@ -343,17 +350,7 @@ module.exports = function(canvasGL, d, scatter) {
343
350
dim2C : dims [ 1 ] [ 2 ] ,
344
351
dim2D : dims [ 1 ] [ 3 ] ,
345
352
346
- loA : lims [ 0 ] [ 0 ] ,
347
- loB : lims [ 0 ] [ 1 ] ,
348
- loC : lims [ 0 ] [ 2 ] ,
349
- loD : lims [ 0 ] [ 3 ] ,
350
- hiA : lims [ 1 ] [ 0 ] ,
351
- hiB : lims [ 1 ] [ 1 ] ,
352
- hiC : lims [ 1 ] [ 2 ] ,
353
- hiD : lims [ 1 ] [ 3 ] ,
354
-
355
353
colorClamp : colorClamp ,
356
- scatter : scatter || 0 ,
357
354
358
355
scissorX : ( I === leftmost ? 0 : x + overdrag ) + ( model . pad . l - overdrag ) + model . layoutWidth * domain . x [ 0 ] ,
359
356
scissorWidth : ( I === rightmost ? canvasWidth - x + overdrag : panelSizeX + 0.5 ) + ( I === leftmost ? x + overdrag : 0 ) ,
@@ -365,6 +362,54 @@ module.exports = function(canvasGL, d, scatter) {
365
362
viewportWidth : canvasWidth ,
366
363
viewportHeight : canvasHeight
367
364
} ;
365
+
366
+ if ( ! context ) {
367
+ mask = Array . apply ( null , new Array ( canvasHeight * channelCount ) ) . map ( function ( ) {
368
+ return 255 ;
369
+ } ) ;
370
+ for ( var dimIndex = 0 ; dimIndex < dimensionCount ; dimIndex ++ ) {
371
+ var bitIndex = dimIndex % bitsPerByte ;
372
+ var byteIndex = ( dimIndex - bitIndex ) / bitsPerByte ;
373
+ var bitMask = Math . pow ( 2 , bitIndex ) ;
374
+ var dim = initialDims [ dimIndex ] ;
375
+ var ranges = dim . brush . filter . get ( ) ;
376
+ if ( ranges . length < 2 ) continue ; // bail if the bounding box based filter is sufficient
377
+ var pi , pixelRange ;
378
+ var boundingBox = dim . brush . filter . getBounds ( ) ;
379
+ pixelRange = boundingBox . map ( dim . unitScaleInOrder ) ;
380
+ for ( pi = Math . max ( 0 , Math . floor ( pixelRange [ 0 ] ) ) ; pi <= Math . min ( canvasHeight - 1 , Math . ceil ( pixelRange [ 1 ] ) ) ; pi ++ ) {
381
+ mask [ pi * channelCount + byteIndex ] &= ~ bitMask ; // clear bits
382
+ }
383
+ for ( var r = 0 ; r < ranges . length ; r ++ ) {
384
+ pixelRange = ranges [ r ] . map ( dim . unitScaleInOrder ) ;
385
+ for ( pi = Math . max ( 0 , Math . floor ( pixelRange [ 0 ] ) ) ; pi <= Math . min ( canvasHeight - 1 , Math . ceil ( pixelRange [ 1 ] ) ) ; pi ++ ) {
386
+ mask [ pi * channelCount + byteIndex ] |= bitMask ;
387
+ }
388
+ }
389
+ }
390
+
391
+ maskTexture = regl . texture ( {
392
+ shape : [ channelCount , canvasHeight ] , // 8 units x 8 bits = 64 bits, just sufficient for the almost 64 dimensions we support
393
+ format : 'alpha' ,
394
+ type : 'uint8' ,
395
+ mag : 'nearest' ,
396
+ min : 'nearest' ,
397
+ data : mask
398
+ } ) ;
399
+
400
+ vm . maskTexture = maskTexture ;
401
+
402
+ vm . loA = lims [ 0 ] [ 0 ] ;
403
+ vm . loB = lims [ 0 ] [ 1 ] ;
404
+ vm . loC = lims [ 0 ] [ 2 ] ;
405
+ vm . loD = lims [ 0 ] [ 3 ] ;
406
+ vm . hiA = lims [ 1 ] [ 0 ] ;
407
+ vm . hiB = lims [ 1 ] [ 1 ] ;
408
+ vm . hiC = lims [ 1 ] [ 2 ] ;
409
+ vm . hiD = lims [ 1 ] [ 3 ] ;
410
+ }
411
+
412
+ return vm ;
368
413
}
369
414
370
415
function renderGLParcoords ( panels , setChanged , clearOnly ) {
@@ -402,7 +447,7 @@ module.exports = function(canvasGL, d, scatter) {
402
447
var xTo = x + panelSizeX ;
403
448
if ( setChanged || ! previousAxisOrder [ i ] || previousAxisOrder [ i ] [ 0 ] !== x || previousAxisOrder [ i ] [ 1 ] !== xTo ) {
404
449
previousAxisOrder [ i ] = [ x , xTo ] ;
405
- var item = makeItem ( i , ii , x , y , panelSizeX , panelSizeY , dim1 . crossfilterDimensionIndex , scatter || dim1 . scatter ? 1 : 0 , I , leftmost , rightmost ) ;
450
+ var item = makeItem ( i , ii , x , y , panelSizeX , panelSizeY , dim1 . crossfilterDimensionIndex , I , leftmost , rightmost ) ;
406
451
renderState . clearOnly = clearOnly ;
407
452
renderBlock ( regl , glAes , renderState , setChanged ? lines . blockLineCount : sampleCount , sampleCount , item ) ;
408
453
}
@@ -435,6 +480,7 @@ module.exports = function(canvasGL, d, scatter) {
435
480
function destroy ( ) {
436
481
canvasGL . style [ 'pointer-events' ] = 'none' ;
437
482
paletteTexture . destroy ( ) ;
483
+ maskTexture . destroy ( ) ;
438
484
}
439
485
440
486
return {
0 commit comments