@@ -1363,6 +1363,69 @@ function vtkOpenGLTexture(publicAPI, model) {
1363
1363
1364
1364
publicAPI . create2DFromRaw ( width , height , numComps , dataType , data ) ;
1365
1365
} ;
1366
+
1367
+ publicAPI . updateVolumeScaleForOpenGL = ( dataType , numComps ) => {
1368
+ let isScalingApplied = false ;
1369
+
1370
+ // Initialize volume info if it doesn't exist
1371
+ if ( ! model . volumeInfo ?. scale || ! model . volumeInfo ?. offset ) {
1372
+ model . volumeInfo = {
1373
+ scale : new Array ( numComps ) ,
1374
+ offset : new Array ( numComps ) ,
1375
+ } ;
1376
+ }
1377
+
1378
+ // Default scaling and offset
1379
+ for ( let c = 0 ; c < numComps ; ++ c ) {
1380
+ model . volumeInfo . scale [ c ] = 1.0 ;
1381
+ model . volumeInfo . offset [ c ] = 0.0 ;
1382
+ }
1383
+
1384
+ // Handle SHORT data type with EXT_texture_norm16 extension
1385
+ if (
1386
+ model . oglNorm16Ext &&
1387
+ ! model . useHalfFloat &&
1388
+ dataType === VtkDataTypes . SHORT
1389
+ ) {
1390
+ for ( let c = 0 ; c < numComps ; ++ c ) {
1391
+ model . volumeInfo . scale [ c ] = 32767.0 ; // Scale to [-1, 1] range
1392
+ }
1393
+ isScalingApplied = true ;
1394
+ }
1395
+
1396
+ // Handle UNSIGNED_SHORT data type with EXT_texture_norm16 extension
1397
+ if (
1398
+ model . oglNorm16Ext &&
1399
+ ! model . useHalfFloat &&
1400
+ dataType === VtkDataTypes . UNSIGNED_SHORT
1401
+ ) {
1402
+ for ( let c = 0 ; c < numComps ; ++ c ) {
1403
+ model . volumeInfo . scale [ c ] = 65535.0 ; // Scale to [0, 1] range
1404
+ }
1405
+ isScalingApplied = true ;
1406
+ }
1407
+
1408
+ // Handle UNSIGNED_CHAR data type
1409
+ if ( dataType === VtkDataTypes . UNSIGNED_CHAR ) {
1410
+ for ( let c = 0 ; c < numComps ; ++ c ) {
1411
+ model . volumeInfo . scale [ c ] = 255.0 ; // Scale to [0, 1] range
1412
+ }
1413
+ isScalingApplied = true ;
1414
+ }
1415
+
1416
+ // No scaling needed for FLOAT or HalfFloat (SHORT/UNSIGNED_SHORT)
1417
+ if (
1418
+ dataType === VtkDataTypes . FLOAT ||
1419
+ ( model . useHalfFloat &&
1420
+ ( dataType === VtkDataTypes . SHORT ||
1421
+ dataType === VtkDataTypes . UNSIGNED_SHORT ) )
1422
+ ) {
1423
+ isScalingApplied = true ;
1424
+ }
1425
+
1426
+ return isScalingApplied ;
1427
+ } ;
1428
+
1366
1429
//----------------------------------------------------------------------------
1367
1430
publicAPI . create3DFromRaw = (
1368
1431
width ,
@@ -1372,12 +1435,37 @@ function vtkOpenGLTexture(publicAPI, model) {
1372
1435
dataType ,
1373
1436
data
1374
1437
) => {
1438
+ let dataTypeToUse = dataType ;
1439
+ let dataToUse = data ;
1440
+
1441
+ if ( ! publicAPI . updateVolumeScaleForOpenGL ( dataTypeToUse , numComps ) ) {
1442
+ const numPixelsIn = width * height * depth ;
1443
+ const scaleOffsetsCopy = structuredClone ( model . volumeInfo ) ;
1444
+ // otherwise convert to float
1445
+ const newArray = new Float32Array ( numPixelsIn * numComps ) ;
1446
+ // use computed scale and offset
1447
+ model . volumeInfo . offset = scaleOffsetsCopy . offset ;
1448
+ model . volumeInfo . scale = scaleOffsetsCopy . scale ;
1449
+ let count = 0 ;
1450
+ const scaleInverse = scaleOffsetsCopy . scale . map ( ( s ) => 1 / s ) ;
1451
+ for ( let i = 0 ; i < numPixelsIn ; i ++ ) {
1452
+ for ( let nc = 0 ; nc < numComps ; nc ++ ) {
1453
+ newArray [ count ] =
1454
+ ( dataToUse [ count ] - scaleOffsetsCopy . offset [ nc ] ) * scaleInverse [ nc ] ;
1455
+ count ++ ;
1456
+ }
1457
+ }
1458
+
1459
+ dataTypeToUse = VtkDataTypes . FLOAT ;
1460
+ dataToUse = newArray ;
1461
+ }
1462
+
1375
1463
// Permit OpenGLDataType to be half float, if applicable, for 3D
1376
- publicAPI . getOpenGLDataType ( dataType ) ;
1464
+ publicAPI . getOpenGLDataType ( dataTypeToUse ) ;
1377
1465
1378
1466
// Now determine the texture parameters using the arguments.
1379
- publicAPI . getInternalFormat ( dataType , numComps ) ;
1380
- publicAPI . getFormat ( dataType , numComps ) ;
1467
+ publicAPI . getInternalFormat ( dataTypeToUse , numComps ) ;
1468
+ publicAPI . getFormat ( dataTypeToUse , numComps ) ;
1381
1469
1382
1470
if ( ! model . internalFormat || ! model . format || ! model . openGLDataType ) {
1383
1471
vtkErrorMacro ( 'Failed to determine texture parameters.' ) ;
@@ -1394,9 +1482,9 @@ function vtkOpenGLTexture(publicAPI, model) {
1394
1482
publicAPI . createTexture ( ) ;
1395
1483
publicAPI . bind ( ) ;
1396
1484
// Create an array of texture with one texture
1397
- const dataArray = [ data ] ;
1485
+ const dataArray = [ dataToUse ] ;
1398
1486
const is3DArray = true ;
1399
- const pixData = updateArrayDataType ( dataType , dataArray , is3DArray ) ;
1487
+ const pixData = updateArrayDataType ( dataTypeToUse , dataArray , is3DArray ) ;
1400
1488
const scaledData = scaleTextureToHighestPowerOfTwo ( pixData ) ;
1401
1489
1402
1490
// Source texture data from the PBO.
@@ -1405,7 +1493,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1405
1493
1406
1494
// openGLDataType
1407
1495
1408
- if ( useTexStorage ( dataType ) ) {
1496
+ if ( useTexStorage ( dataTypeToUse ) ) {
1409
1497
model . context . texStorage3D (
1410
1498
model . target ,
1411
1499
1 ,
@@ -1454,7 +1542,7 @@ function vtkOpenGLTexture(publicAPI, model) {
1454
1542
model . depth *
1455
1543
model . components *
1456
1544
model . _openGLRenderWindow . getDefaultTextureByteSize (
1457
- dataType ,
1545
+ dataTypeToUse ,
1458
1546
model . oglNorm16Ext ,
1459
1547
model . useHalfFloat
1460
1548
) ;
@@ -1501,8 +1589,6 @@ function vtkOpenGLTexture(publicAPI, model) {
1501
1589
preferSizeOverAccuracy
1502
1590
) ;
1503
1591
1504
- const numPixelsIn = width * height * depth ;
1505
-
1506
1592
const offset = [ ] ;
1507
1593
const scale = [ ] ;
1508
1594
for ( let c = 0 ; c < numComps ; ++ c ) {
@@ -1528,96 +1614,22 @@ function vtkOpenGLTexture(publicAPI, model) {
1528
1614
// Create a copy of scale and offset to avoid aliasing issues
1529
1615
// Original is read only, copy is read/write
1530
1616
// Use the copy as volumeInfo.scale and volumeInfo.offset
1531
- const scaleOffsetsCopy = structuredClone ( scaleOffsets ) ;
1532
1617
1533
1618
// WebGL2 path, we have 3d textures etc
1534
1619
if ( model . _openGLRenderWindow . getWebgl2 ( ) ) {
1535
- if (
1536
- model . oglNorm16Ext &&
1537
- ! model . useHalfFloat &&
1538
- dataType === VtkDataTypes . SHORT
1539
- ) {
1540
- for ( let c = 0 ; c < numComps ; ++ c ) {
1541
- model . volumeInfo . scale [ c ] = 32767.0 ;
1542
- }
1543
- return publicAPI . create3DFromRaw (
1544
- width ,
1545
- height ,
1546
- depth ,
1547
- numComps ,
1548
- dataType ,
1549
- data
1550
- ) ;
1551
- }
1552
- if (
1553
- model . oglNorm16Ext &&
1554
- ! model . useHalfFloat &&
1555
- dataType === VtkDataTypes . UNSIGNED_SHORT
1556
- ) {
1557
- for ( let c = 0 ; c < numComps ; ++ c ) {
1558
- model . volumeInfo . scale [ c ] = 65535.0 ;
1559
- }
1560
- return publicAPI . create3DFromRaw (
1561
- width ,
1562
- height ,
1563
- depth ,
1564
- numComps ,
1565
- dataType ,
1566
- data
1567
- ) ;
1568
- }
1569
- if (
1570
- dataType === VtkDataTypes . FLOAT ||
1571
- ( model . useHalfFloat &&
1572
- ( dataType === VtkDataTypes . SHORT ||
1573
- dataType === VtkDataTypes . UNSIGNED_SHORT ) )
1574
- ) {
1575
- return publicAPI . create3DFromRaw (
1576
- width ,
1577
- height ,
1578
- depth ,
1579
- numComps ,
1580
- dataType ,
1581
- data
1582
- ) ;
1583
- }
1584
- if ( dataType === VtkDataTypes . UNSIGNED_CHAR ) {
1585
- for ( let c = 0 ; c < numComps ; ++ c ) {
1586
- model . volumeInfo . scale [ c ] = 255.0 ;
1587
- }
1588
- return publicAPI . create3DFromRaw (
1589
- width ,
1590
- height ,
1591
- depth ,
1592
- numComps ,
1593
- dataType ,
1594
- data
1595
- ) ;
1596
- }
1597
- // otherwise convert to float
1598
- const newArray = new Float32Array ( numPixelsIn * numComps ) ;
1599
- // use computed scale and offset
1600
- model . volumeInfo . offset = scaleOffsetsCopy . offset ;
1601
- model . volumeInfo . scale = scaleOffsetsCopy . scale ;
1602
- let count = 0 ;
1603
- const scaleInverse = scaleOffsetsCopy . scale . map ( ( s ) => 1 / s ) ;
1604
- for ( let i = 0 ; i < numPixelsIn ; i ++ ) {
1605
- for ( let nc = 0 ; nc < numComps ; nc ++ ) {
1606
- newArray [ count ] =
1607
- ( data [ count ] - scaleOffsetsCopy . offset [ nc ] ) * scaleInverse [ nc ] ;
1608
- count ++ ;
1609
- }
1610
- }
1611
1620
return publicAPI . create3DFromRaw (
1612
1621
width ,
1613
1622
height ,
1614
1623
depth ,
1615
1624
numComps ,
1616
- VtkDataTypes . FLOAT ,
1617
- newArray
1625
+ dataType ,
1626
+ data
1618
1627
) ;
1619
1628
}
1620
1629
1630
+ const numPixelsIn = width * height * depth ;
1631
+ const scaleOffsetsCopy = structuredClone ( scaleOffsets ) ;
1632
+
1621
1633
// not webgl2, deal with webgl1, no 3d textures
1622
1634
// and maybe no float textures
1623
1635
0 commit comments