@geastack/native-webgl-angle 0.1.12 → 0.1.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/geatsc-plugin-readback.mjs +21 -0
- package/geatsc-plugin-uniforms.mjs +214 -59
- package/geatsc-plugin-uploads.mjs +7 -2
- package/geatsc-plugin.mjs +912 -67
- package/native/angle_webgl_host.mm +217 -22
- package/package.json +1 -1
- package/src/inflate.ts +1 -1
- package/src/nativeWebGL.ts +67 -13
- package/src/nativeWebGLHost.ts +19 -0
|
@@ -22,4 +22,25 @@ template <typename... T> inline void gea_three_webgl_read_pixels_native(double x
|
|
|
22
22
|
double format, double type, const std::variant<T...>& destination, double offset) {
|
|
23
23
|
std::visit([&](const auto& view) { gea_three_webgl_read_pixels_native(x,y,width,height,format,type,view,offset); }, destination);
|
|
24
24
|
}`
|
|
25
|
+
], [
|
|
26
|
+
// getBufferSubData writes a pack buffer's bytes into the caller's view, in place.
|
|
27
|
+
'threeWebGLGetBufferSubData', 'gea_three_webgl_get_buffer_sub_data_native', 'void', `
|
|
28
|
+
#include <variant>
|
|
29
|
+
extern "C" void gea_three_webgl_get_buffer_sub_data_bytes(double target, double srcOffset, void* bytes, double byteLength);
|
|
30
|
+
template <typename T> inline void gea_three_webgl_get_buffer_sub_data_native(double target, double srcOffset,
|
|
31
|
+
const gea::Ref<gea::TypedArray<T>>& destination, double dstOffset, double length) {
|
|
32
|
+
if (!destination || !std::isfinite(dstOffset) || dstOffset < 0 || std::floor(dstOffset) != dstOffset || dstOffset > destination->size() ||
|
|
33
|
+
!std::isfinite(length) || length < 0 || std::floor(length) != length) {
|
|
34
|
+
gea_three_webgl_get_buffer_sub_data_bytes(target, srcOffset, nullptr, -1); return;
|
|
35
|
+
}
|
|
36
|
+
const auto start = static_cast<std::size_t>(dstOffset);
|
|
37
|
+
const auto count = length == 0 ? destination->size() - start : static_cast<std::size_t>(length);
|
|
38
|
+
if (count > destination->size() - start) { gea_three_webgl_get_buffer_sub_data_bytes(target, srcOffset, nullptr, -1); return; }
|
|
39
|
+
auto* data = destination->data();
|
|
40
|
+
gea_three_webgl_get_buffer_sub_data_bytes(target, srcOffset, data ? data + start : nullptr, static_cast<double>(count * sizeof(T)));
|
|
41
|
+
}
|
|
42
|
+
template <typename... T> inline void gea_three_webgl_get_buffer_sub_data_native(double target, double srcOffset,
|
|
43
|
+
const std::variant<T...>& destination, double dstOffset, double length) {
|
|
44
|
+
std::visit([&](const auto& view) { gea_three_webgl_get_buffer_sub_data_native(target, srcOffset, view, dstOffset, length); }, destination);
|
|
45
|
+
}`
|
|
25
46
|
]];
|
|
@@ -654,11 +654,15 @@ function ${name}( gl, v, textures ) {
|
|
|
654
654
|
|
|
655
655
|
\tif ( v instanceof ${ctorName} ) {
|
|
656
656
|
|
|
657
|
-
\t\
|
|
657
|
+
\t\t// One narrowing and one read per component: each \`v.x\` re-narrowed the union value.
|
|
658
|
+
\t\tconst vector = v;
|
|
659
|
+
${fields.map((field) => `\t\tconst ${field} = vector.${field};`).join('\n')}
|
|
658
660
|
|
|
659
|
-
\t\
|
|
661
|
+
\t\tif ( ${fields.map((field, index) => `cache[ ${index} ] !== ${field}`).join(' || ')} ) {
|
|
660
662
|
|
|
661
|
-
|
|
663
|
+
\t\t\tgl.${glScalar}( this.addr, ${fields.join(', ')} );
|
|
664
|
+
|
|
665
|
+
${fields.map((field, index) => `\t\t\tcache[ ${index} ] = ${field};`).join('\n')}
|
|
662
666
|
|
|
663
667
|
\t\t}
|
|
664
668
|
|
|
@@ -761,20 +765,34 @@ ${
|
|
|
761
765
|
}
|
|
762
766
|
}`
|
|
763
767
|
|
|
768
|
+
// Arrays compare against the program's cached copy like single values do: uniform state is
|
|
769
|
+
// per program, and an unchanged write still dirtied the program's whole uniform block.
|
|
764
770
|
const flatArraySetter = (name, glArray, requireArray) => `${setterHeader('PureArrayUniform')}
|
|
765
771
|
function ${name}( gl, v, textures ) {
|
|
766
772
|
|
|
767
|
-
\
|
|
773
|
+
\tconst cache = this.cache;
|
|
774
|
+
\tconst data = ${requireArray}( v );
|
|
775
|
+
|
|
776
|
+
\tif ( arraysEqual( cache, data ) ) return;
|
|
777
|
+
|
|
778
|
+
\tgl.${glArray}( this.addr, data );
|
|
779
|
+
|
|
780
|
+
\tcopyArray( cache, data );
|
|
768
781
|
|
|
769
782
|
}`
|
|
770
783
|
|
|
771
784
|
const flattenedArraySetter = (name, blockSize, glArray, matrix) => `${setterHeader('PureArrayUniform')}
|
|
772
785
|
function ${name}( gl, v, textures ) {
|
|
773
786
|
|
|
787
|
+
\tconst cache = this.cache;
|
|
774
788
|
\tconst data = flatten( v, this.size, ${blockSize} );
|
|
775
789
|
|
|
790
|
+
\tif ( arraysEqual( cache, data ) ) return;
|
|
791
|
+
|
|
776
792
|
\tgl.${glArray}( this.addr, ${matrix ? 'false, ' : ''}data );
|
|
777
793
|
|
|
794
|
+
\tcopyArray( cache, data );
|
|
795
|
+
|
|
778
796
|
}`
|
|
779
797
|
|
|
780
798
|
const textureArraySetter = (name, setter, empty, shadowAware) => `${setterHeader('PureArrayUniform')}
|
|
@@ -906,6 +924,8 @@ export const nativeFixedUniforms = [
|
|
|
906
924
|
['modelMatrix', 'Matrix4'],
|
|
907
925
|
['toneMappingExposure', 'number'],
|
|
908
926
|
['cameraPosition', 'Vector3'],
|
|
927
|
+
['receiveShadow', 'boolean'],
|
|
928
|
+
['isOrthographic', 'boolean'],
|
|
909
929
|
...(nativeUniformBindingsEnabled ? [
|
|
910
930
|
['directionalShadowMap', 'Array<Texture|null>', true],
|
|
911
931
|
['spotShadowMap', 'Array<Texture|null>', true],
|
|
@@ -917,13 +937,17 @@ const fixedUniformMethods = nativeFixedUniforms.map(([name, type, textures]) =>
|
|
|
917
937
|
return `
|
|
918
938
|
/** @param {${glContext}} gl @param {${type}} value ${textures ? '@param {NativeTextures|undefined} textures' : ''} */
|
|
919
939
|
set_${name}( gl, value${textures ? ', textures' : ''} ) {
|
|
920
|
-
const uniform = this.
|
|
940
|
+
const uniform = this.fixed_${name};
|
|
921
941
|
if ( uniform === undefined ) return;
|
|
922
942
|
${matrix ? `if ( ! ( uniform instanceof SingleUniform ) ) throw new Error( 'THREE.WebGLUniforms: ${type} fast path requires a single uniform.' );
|
|
923
943
|
setNative${type}UniformValue( uniform, gl, value );` : `setNativeUniformValue( uniform, gl, value, ${textures ? 'textures' : 'undefined'} );`}
|
|
924
944
|
}
|
|
925
945
|
`
|
|
926
946
|
}).join('\n')
|
|
947
|
+
// The fixed uniforms are resolved once when the program's uniforms are parsed; each
|
|
948
|
+
// per-draw setter then reads a field instead of hashing its name into `map` twice.
|
|
949
|
+
const fixedUniformFields = nativeFixedUniforms.map(([name]) =>
|
|
950
|
+
`\t\t/** @type {NativeUniform|undefined} */\n\t\tthis.fixed_${name} = this.map.${name};\n`).join('')
|
|
927
951
|
|
|
928
952
|
|
|
929
953
|
// Uniform nodes belong to the linked program: id/type/location remain fixed
|
|
@@ -1273,25 +1297,31 @@ function setValueV3f( gl, v, textures ) {
|
|
|
1273
1297
|
|
|
1274
1298
|
\tif ( v instanceof Vector3 ) {
|
|
1275
1299
|
|
|
1276
|
-
\t\
|
|
1300
|
+
\t\tconst vector = v;
|
|
1301
|
+
\t\tconst x = vector.x, y = vector.y, z = vector.z;
|
|
1302
|
+
|
|
1303
|
+
\t\tif ( cache[ 0 ] !== x || cache[ 1 ] !== y || cache[ 2 ] !== z ) {
|
|
1277
1304
|
|
|
1278
|
-
\t\t\tgl.uniform3f( this.addr,
|
|
1305
|
+
\t\t\tgl.uniform3f( this.addr, x, y, z );
|
|
1279
1306
|
|
|
1280
|
-
\t\t\tcache[ 0 ] =
|
|
1281
|
-
\t\t\tcache[ 1 ] =
|
|
1282
|
-
\t\t\tcache[ 2 ] =
|
|
1307
|
+
\t\t\tcache[ 0 ] = x;
|
|
1308
|
+
\t\t\tcache[ 1 ] = y;
|
|
1309
|
+
\t\t\tcache[ 2 ] = z;
|
|
1283
1310
|
|
|
1284
1311
|
\t\t}
|
|
1285
1312
|
|
|
1286
1313
|
\t} else if ( v instanceof Color ) {
|
|
1287
1314
|
|
|
1288
|
-
\t\
|
|
1315
|
+
\t\tconst color = v;
|
|
1316
|
+
\t\tconst r = color.r, g = color.g, b = color.b;
|
|
1289
1317
|
|
|
1290
|
-
\t\
|
|
1318
|
+
\t\tif ( cache[ 0 ] !== r || cache[ 1 ] !== g || cache[ 2 ] !== b ) {
|
|
1291
1319
|
|
|
1292
|
-
\t\t\
|
|
1293
|
-
|
|
1294
|
-
\t\t\tcache[
|
|
1320
|
+
\t\t\tgl.uniform3f( this.addr, r, g, b );
|
|
1321
|
+
|
|
1322
|
+
\t\t\tcache[ 0 ] = r;
|
|
1323
|
+
\t\t\tcache[ 1 ] = g;
|
|
1324
|
+
\t\t\tcache[ 2 ] = b;
|
|
1295
1325
|
|
|
1296
1326
|
\t\t}
|
|
1297
1327
|
|
|
@@ -1484,69 +1514,115 @@ ${nativeUniformBindingsEnabled ? '\t\tthis.nativeBindingSlot = nativeUniformBind
|
|
|
1484
1514
|
|
|
1485
1515
|
}
|
|
1486
1516
|
|
|
1517
|
+
/**
|
|
1518
|
+
* Member codes for a structured uniform's steps, resolved once when the program's
|
|
1519
|
+
* uniforms are parsed: an array step's code is its index; a light-record field's
|
|
1520
|
+
* code is a negative constant, so the per-draw read switches on a number instead
|
|
1521
|
+
* of comparing field names and parsing index strings.
|
|
1522
|
+
* @param {string} id @return {number}
|
|
1523
|
+
*/
|
|
1524
|
+
function structuredUniformMemberCode( id ) {
|
|
1525
|
+
|
|
1526
|
+
\tif ( id === 'direction' ) return -1;
|
|
1527
|
+
\tif ( id === 'color' ) return -2;
|
|
1528
|
+
\tif ( id === 'position' ) return -3;
|
|
1529
|
+
\tif ( id === 'distance' ) return -4;
|
|
1530
|
+
\tif ( id === 'coneCos' ) return -5;
|
|
1531
|
+
\tif ( id === 'penumbraCos' ) return -6;
|
|
1532
|
+
\tif ( id === 'decay' ) return -7;
|
|
1533
|
+
\tif ( id === 'skyColor' ) return -8;
|
|
1534
|
+
\tif ( id === 'groundColor' ) return -9;
|
|
1535
|
+
\tif ( id === 'halfWidth' ) return -10;
|
|
1536
|
+
\tif ( id === 'halfHeight' ) return -11;
|
|
1537
|
+
\tif ( id === 'shadowIntensity' ) return -12;
|
|
1538
|
+
\tif ( id === 'shadowBias' ) return -13;
|
|
1539
|
+
\tif ( id === 'shadowNormalBias' ) return -14;
|
|
1540
|
+
\tif ( id === 'shadowRadius' ) return -15;
|
|
1541
|
+
\tif ( id === 'shadowMapSize' ) return -16;
|
|
1542
|
+
\tif ( id === 'shadowCameraNear' ) return -17;
|
|
1543
|
+
\tif ( id === 'shadowCameraFar' ) return -18;
|
|
1544
|
+
\tconst index = Number( id );
|
|
1545
|
+
\treturn Number.isInteger( index ) && index >= 0 ? index : - 1000;
|
|
1546
|
+
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1487
1549
|
/**
|
|
1488
1550
|
* The member a structured uniform's step reads: three writes \`value[ u.id ]\`,
|
|
1489
|
-
* where the value is an array (
|
|
1490
|
-
* (
|
|
1551
|
+
* where the value is an array (member is the index) or a light-uniform record
|
|
1552
|
+
* (member is the field's code). The light records are classes, so the read is a
|
|
1491
1553
|
* narrowed field read; an array indexes whichever arm it is.
|
|
1492
|
-
* @param {NativeUniformValue} value @param {string} id @return {NativeUniformValue}
|
|
1554
|
+
* @param {NativeUniformValue} value @param {number} member @param {string} id @return {NativeUniformValue}
|
|
1493
1555
|
*/
|
|
1494
|
-
function structuredUniformMember( value, id ) {
|
|
1556
|
+
function structuredUniformMember( value, member, id ) {
|
|
1495
1557
|
|
|
1496
|
-
\tif ( Array.isArray( value ) ) return value[
|
|
1558
|
+
\tif ( Array.isArray( value ) ) return value[ member ];
|
|
1497
1559
|
|
|
1498
1560
|
\tif ( value instanceof NativeDirectionalLightUniform ) {
|
|
1499
1561
|
|
|
1500
|
-
\t\
|
|
1501
|
-
\t\
|
|
1562
|
+
\t\tswitch ( member ) {
|
|
1563
|
+
\t\t\tcase -1: return value.direction;
|
|
1564
|
+
\t\t\tcase -2: return value.color;
|
|
1565
|
+
\t\t}
|
|
1502
1566
|
|
|
1503
1567
|
\t} else if ( value instanceof NativeSpotLightUniform ) {
|
|
1504
1568
|
|
|
1505
|
-
\t\
|
|
1506
|
-
\t\
|
|
1507
|
-
\t\
|
|
1508
|
-
\t\
|
|
1509
|
-
\t\
|
|
1510
|
-
\t\
|
|
1511
|
-
\t\
|
|
1569
|
+
\t\tswitch ( member ) {
|
|
1570
|
+
\t\t\tcase -3: return value.position;
|
|
1571
|
+
\t\t\tcase -1: return value.direction;
|
|
1572
|
+
\t\t\tcase -2: return value.color;
|
|
1573
|
+
\t\t\tcase -4: return value.distance;
|
|
1574
|
+
\t\t\tcase -5: return value.coneCos;
|
|
1575
|
+
\t\t\tcase -6: return value.penumbraCos;
|
|
1576
|
+
\t\t\tcase -7: return value.decay;
|
|
1577
|
+
\t\t}
|
|
1512
1578
|
|
|
1513
1579
|
\t} else if ( value instanceof NativePointLightUniform ) {
|
|
1514
1580
|
|
|
1515
|
-
\t\
|
|
1516
|
-
\t\
|
|
1517
|
-
\t\
|
|
1518
|
-
\t\
|
|
1581
|
+
\t\tswitch ( member ) {
|
|
1582
|
+
\t\t\tcase -3: return value.position;
|
|
1583
|
+
\t\t\tcase -2: return value.color;
|
|
1584
|
+
\t\t\tcase -4: return value.distance;
|
|
1585
|
+
\t\t\tcase -7: return value.decay;
|
|
1586
|
+
\t\t}
|
|
1519
1587
|
|
|
1520
1588
|
\t} else if ( value instanceof NativeHemisphereLightUniform ) {
|
|
1521
1589
|
|
|
1522
|
-
\t\
|
|
1523
|
-
\t\
|
|
1524
|
-
\t\
|
|
1590
|
+
\t\tswitch ( member ) {
|
|
1591
|
+
\t\t\tcase -1: return value.direction;
|
|
1592
|
+
\t\t\tcase -8: return value.skyColor;
|
|
1593
|
+
\t\t\tcase -9: return value.groundColor;
|
|
1594
|
+
\t\t}
|
|
1525
1595
|
|
|
1526
1596
|
\t} else if ( value instanceof NativeRectAreaLightUniform ) {
|
|
1527
1597
|
|
|
1528
|
-
\t\
|
|
1529
|
-
\t\
|
|
1530
|
-
\t\
|
|
1531
|
-
\t\
|
|
1598
|
+
\t\tswitch ( member ) {
|
|
1599
|
+
\t\t\tcase -2: return value.color;
|
|
1600
|
+
\t\t\tcase -3: return value.position;
|
|
1601
|
+
\t\t\tcase -10: return value.halfWidth;
|
|
1602
|
+
\t\t\tcase -11: return value.halfHeight;
|
|
1603
|
+
\t\t}
|
|
1532
1604
|
|
|
1533
1605
|
\t} else if ( value instanceof NativeShadowUniform ) {
|
|
1534
1606
|
|
|
1535
|
-
\t\
|
|
1536
|
-
\t\
|
|
1537
|
-
\t\
|
|
1538
|
-
\t\
|
|
1539
|
-
\t\
|
|
1607
|
+
\t\tswitch ( member ) {
|
|
1608
|
+
\t\t\tcase -12: return value.shadowIntensity;
|
|
1609
|
+
\t\t\tcase -13: return value.shadowBias;
|
|
1610
|
+
\t\t\tcase -14: return value.shadowNormalBias;
|
|
1611
|
+
\t\t\tcase -15: return value.shadowRadius;
|
|
1612
|
+
\t\t\tcase -16: return value.shadowMapSize;
|
|
1613
|
+
\t\t}
|
|
1540
1614
|
|
|
1541
1615
|
\t} else if ( value instanceof NativePointShadowUniform ) {
|
|
1542
1616
|
|
|
1543
|
-
\t\
|
|
1544
|
-
\t\
|
|
1545
|
-
\t\
|
|
1546
|
-
\t\
|
|
1547
|
-
\t\
|
|
1548
|
-
\t\
|
|
1549
|
-
\t\
|
|
1617
|
+
\t\tswitch ( member ) {
|
|
1618
|
+
\t\t\tcase -12: return value.shadowIntensity;
|
|
1619
|
+
\t\t\tcase -13: return value.shadowBias;
|
|
1620
|
+
\t\t\tcase -14: return value.shadowNormalBias;
|
|
1621
|
+
\t\t\tcase -15: return value.shadowRadius;
|
|
1622
|
+
\t\t\tcase -16: return value.shadowMapSize;
|
|
1623
|
+
\t\t\tcase -17: return value.shadowCameraNear;
|
|
1624
|
+
\t\t\tcase -18: return value.shadowCameraFar;
|
|
1625
|
+
\t\t}
|
|
1550
1626
|
|
|
1551
1627
|
\t}
|
|
1552
1628
|
|
|
@@ -1566,18 +1642,20 @@ ${nativeUniformBindingsEnabled ? '\t\tthis.nativeBindingSlot = nativeUniformBind
|
|
|
1566
1642
|
\t\tthis.seq = [];
|
|
1567
1643
|
\t\t/** @type {Record<string, NativeUniform>} */
|
|
1568
1644
|
\t\tthis.map = {};
|
|
1645
|
+
\t\t/** @type {number[]} member code of each seq entry */
|
|
1646
|
+
\t\tthis.members = [];
|
|
1569
1647
|
|
|
1570
1648
|
\t}
|
|
1571
1649
|
|
|
1572
1650
|
\t/** @param {${glContext}} gl @param {NativeUniformValue} value @param {NativeTextures|undefined} textures @return {void} */
|
|
1573
1651
|
\tsetValue( gl, value, textures ) {
|
|
1574
1652
|
|
|
1575
|
-
\t\tconst seq = this.seq;
|
|
1653
|
+
\t\tconst seq = this.seq, members = this.members;
|
|
1576
1654
|
|
|
1577
1655
|
\t\tfor ( let i = 0, n = seq.length; i !== n; ++ i ) {
|
|
1578
1656
|
|
|
1579
1657
|
\t\t\tconst u = seq[ i ];
|
|
1580
|
-
\t\t\tsetNativeUniformValue( u, gl, structuredUniformMember( value, u.id ), textures );
|
|
1658
|
+
\t\t\tsetNativeUniformValue( u, gl, structuredUniformMember( value, members[ i ], u.id ), textures );
|
|
1581
1659
|
|
|
1582
1660
|
\t\t}
|
|
1583
1661
|
|
|
@@ -1619,6 +1697,7 @@ function addUniform( container, uniformObject ) {
|
|
|
1619
1697
|
|
|
1620
1698
|
\tcontainer.seq.push( uniformObject );
|
|
1621
1699
|
\tcontainer.map[ uniformObject.id ] = uniformObject;
|
|
1700
|
+
\tif ( container instanceof StructuredUniform ) container.members.push( structuredUniformMemberCode( uniformObject.id ) );
|
|
1622
1701
|
|
|
1623
1702
|
}
|
|
1624
1703
|
|
|
@@ -1754,6 +1833,7 @@ class WebGLUniforms {
|
|
|
1754
1833
|
|
|
1755
1834
|
\t\t}
|
|
1756
1835
|
|
|
1836
|
+
${fixedUniformFields}
|
|
1757
1837
|
\t}
|
|
1758
1838
|
|
|
1759
1839
|
${fixedUniformMethods}
|
|
@@ -1805,8 +1885,8 @@ ${fixedUniformMethods}
|
|
|
1805
1885
|
\t// direct, typed uploads (\`setMatrix4Value\` for the bind matrices; the
|
|
1806
1886
|
\t// batching textures upload their own value on the line below each).
|
|
1807
1887
|
|
|
1808
|
-
\t/** @param {${glContext}} gl @param {NativeUniform[]} seq @param {NativeUniforms} values @param {NativeTextures|undefined} textures @param {NativeClippingUniform|undefined} clippingPlanes */
|
|
1809
|
-
\tstatic upload( gl, seq, values, textures, clippingPlanes ) {
|
|
1888
|
+
\t/** @param {${glContext}} gl @param {NativeUniform[]} seq @param {NativeUniforms} values @param {NativeTextures|undefined} textures @param {NativeClippingUniform|undefined} clippingPlanes @param {Array<import('../shaders/UniformsLib.js').NativeUniformSlot|undefined>|undefined} [slots] */
|
|
1889
|
+
\tstatic upload( gl, seq, values, textures, clippingPlanes, slots ) {
|
|
1810
1890
|
|
|
1811
1891
|
\t\tfor ( let i = 0, n = seq.length; i !== n; ++ i ) {
|
|
1812
1892
|
|
|
@@ -1819,7 +1899,9 @@ ${fixedUniformMethods}
|
|
|
1819
1899
|
|
|
1820
1900
|
\t\t\t}
|
|
1821
1901
|
|
|
1822
|
-
\t\t\
|
|
1902
|
+
\t\t\t// The cell resolved with this list (see slotsOf), else a lookup by name.
|
|
1903
|
+
\t\t\tconst cached = slots !== undefined && i < slots.length ? slots[ i ] : undefined;
|
|
1904
|
+
\t\t\tconst v = cached !== undefined ? cached : ${nativeUniformBindingsEnabled ? 'nativeUniformBindingValue( values, u )' : 'values[ u.id ]'};
|
|
1823
1905
|
|
|
1824
1906
|
\t\t\tif ( v.needsUpdate !== false ) {
|
|
1825
1907
|
|
|
@@ -1832,6 +1914,23 @@ ${fixedUniformMethods}
|
|
|
1832
1914
|
|
|
1833
1915
|
\t}
|
|
1834
1916
|
|
|
1917
|
+
\t/** @param {NativeUniform[]} seq @param {NativeUniforms} values @return {Array<import('../shaders/UniformsLib.js').NativeUniformSlot|undefined>} */
|
|
1918
|
+
\tstatic slotsOf( seq, values ) {
|
|
1919
|
+
|
|
1920
|
+
\t\t/** @type {Array<import('../shaders/UniformsLib.js').NativeUniformSlot|undefined>} */
|
|
1921
|
+
\t\tconst r = [];
|
|
1922
|
+
|
|
1923
|
+
\t\tfor ( let i = 0, n = seq.length; i !== n; ++ i ) {
|
|
1924
|
+
|
|
1925
|
+
\t\t\tconst u = seq[ i ];
|
|
1926
|
+
\t\t\tr.push( ${nativeUniformBindingsEnabled ? 'u.nativeBindingSlot === -1 ? undefined : nativeUniformBindingValue( values, u )' : "u.id === 'clippingPlanes' ? undefined : values[ u.id ]"} );
|
|
1927
|
+
|
|
1928
|
+
\t\t}
|
|
1929
|
+
|
|
1930
|
+
\t\treturn r;
|
|
1931
|
+
|
|
1932
|
+
\t}
|
|
1933
|
+
|
|
1835
1934
|
\t/** @param {NativeUniform[]} seq @param {NativeUniforms} values @param {NativeClippingUniform|undefined} clippingPlanes @return {NativeUniform[]} */
|
|
1836
1935
|
\tstatic seqWithValue( seq, values, clippingPlanes ) {
|
|
1837
1936
|
|
|
@@ -1863,8 +1962,64 @@ export { WebGLUniforms };
|
|
|
1863
1962
|
`
|
|
1864
1963
|
|
|
1865
1964
|
|
|
1866
|
-
|
|
1867
|
-
|
|
1965
|
+
|
|
1966
|
+
/**
|
|
1967
|
+
* Setters as direct calls. three stores each uniform's setter in a \`setValue\`
|
|
1968
|
+
* field; natively that is a callable-object call, which takes the large
|
|
1969
|
+
* \`NativeUniformValue\` union by value -- a copy and its reference counting on
|
|
1970
|
+
* every uniform of every draw. Here each setter takes its uniform as the first
|
|
1971
|
+
* parameter, and \`setNativeUniformValue\` switches on the uniform's GL type to
|
|
1972
|
+
* call it directly, so the value is passed by reference. Same setters, same
|
|
1973
|
+
* caches, same GL calls.
|
|
1974
|
+
* @param {string} source @return {string}
|
|
1975
|
+
*/
|
|
1976
|
+
function directUniformSetters( source ) {
|
|
1977
|
+
|
|
1978
|
+
let out = source.replace(
|
|
1979
|
+
/\/\*\* @this \{(SingleUniform|PureArrayUniform)\} (@param [^\n]*?)\*\/\nfunction (setValue\w+)\( gl, v, textures \) \{\n([\s\S]*?)\n\}\n/g,
|
|
1980
|
+
(_match, receiver, params, name, body) =>
|
|
1981
|
+
'/** @param {' + receiver + '} uniform ' + params + '*/\nfunction ' + name + '( uniform, gl, v, textures ) {\n' +
|
|
1982
|
+
body.replace(/\bthis\b/g, 'uniform') + '\n}\n',
|
|
1983
|
+
);
|
|
1984
|
+
if ( /@this \{(SingleUniform|PureArrayUniform)\}/.test( out ) ) throw new Error( 'directUniformSetters: a setter kept @this' );
|
|
1985
|
+
|
|
1986
|
+
const dispatch = ( selector, receiver, name ) => {
|
|
1987
|
+
const start = out.indexOf( 'function ' + selector + '( type ) {' );
|
|
1988
|
+
const end = out.indexOf( '\n}\n', start );
|
|
1989
|
+
if ( start < 0 || end < 0 ) throw new Error( 'directUniformSetters: ' + selector + ' not found' );
|
|
1990
|
+
const body = out.slice( start, end );
|
|
1991
|
+
const cases = body.slice( body.indexOf( 'switch ( type ) {' ) + 'switch ( type ) {'.length, body.lastIndexOf( '}' ) );
|
|
1992
|
+
if ( ! /return setValue\w+;/.test( cases ) ) throw new Error( 'directUniformSetters: no cases in ' + selector );
|
|
1993
|
+
const direct = '/** @param {' + receiver + '} uniform @param {' + 'GL' + '} gl @param {NativeUniformValue} v @param {NativeTextures|undefined} textures @return {void} */\n' +
|
|
1994
|
+
'function ' + name + '( uniform, gl, v, textures ) {\n\n\tswitch ( uniform.type ) {\n' +
|
|
1995
|
+
cases.replace( /return (setValue\w+);/g, '$1( uniform, gl, v, textures ); return;' ) +
|
|
1996
|
+
'\n\t}\n\n\tthrow new Error( \'THREE.WebGLUniforms: Unsupported uniform type.\' );\n\n}\n';
|
|
1997
|
+
// The selector now only validates the type at program link.
|
|
1998
|
+
const validating = body.replace( /return setValue\w+;/g, 'return true;' );
|
|
1999
|
+
out = out.slice( 0, start ) + validating + out.slice( end ) ;
|
|
2000
|
+
return direct;
|
|
2001
|
+
};
|
|
2002
|
+
const glType = out.match( /@param \{([^}]+)\} gl @param \{NativeUniformValue\} v/ );
|
|
2003
|
+
if ( ! glType ) throw new Error( 'directUniformSetters: gl type not found' );
|
|
2004
|
+
const singular = dispatch( 'getSingularSetter', 'SingleUniform', 'callSingularSetter' ).replace( '{GL}', '{' + glType[ 1 ] + '}' );
|
|
2005
|
+
const array = dispatch( 'getPureArraySetter', 'PureArrayUniform', 'callPureArraySetter' ).replace( '{GL}', '{' + glType[ 1 ] + '}' );
|
|
2006
|
+
const replaceOnce = ( from, to ) => {
|
|
2007
|
+
if ( out.split( from ).length !== 2 ) throw new Error( 'directUniformSetters: expected one ' + from );
|
|
2008
|
+
out = out.replace( from, to );
|
|
2009
|
+
};
|
|
2010
|
+
replaceOnce( '/** @param {number} type @return {NativeSingularUniformSetter} */', '/** @param {number} type @return {boolean} */' );
|
|
2011
|
+
replaceOnce( '/** @param {number} type @return {NativeArrayUniformSetter} */', '/** @param {number} type @return {boolean} */' );
|
|
2012
|
+
replaceOnce( '\t\tthis.setValue = getSingularSetter( activeInfo.type );', '\t\tgetSingularSetter( activeInfo.type );' );
|
|
2013
|
+
replaceOnce( '\t\tthis.setValue = getPureArraySetter( activeInfo.type );', '\t\tgetPureArraySetter( activeInfo.type );' );
|
|
2014
|
+
replaceOnce( '\tif ( uniform instanceof SingleUniform ) uniform.setValue( gl, value, textures );\n\telse if ( uniform instanceof PureArrayUniform ) uniform.setValue( gl, value, textures );',
|
|
2015
|
+
'\tif ( uniform instanceof SingleUniform ) callSingularSetter( uniform, gl, value, textures );\n\telse if ( uniform instanceof PureArrayUniform ) callPureArraySetter( uniform, gl, value, textures );' );
|
|
2016
|
+
replaceOnce( '// --- Uniform Classes ---', singular + '\n' + array + '\n// --- Uniform Classes ---' );
|
|
2017
|
+
return out;
|
|
2018
|
+
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
export const nativeWebGLUniformsSource = directUniformSetters( nativeUniformNamesEnabled ? optimizedNativeWebGLUniformsSource
|
|
2022
|
+
: optimizedNativeWebGLUniformsSource.replace(fixedUniformMethods, '') )
|
|
1868
2023
|
|
|
1869
2024
|
/**
|
|
1870
2025
|
* `UniformsLib.js`: the light classes and the typedefs go in above the table,
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
// The host owns the physical upload format. The compiler only preserves the
|
|
2
2
|
// native carriers at these explicitly registered synchronous boundaries.
|
|
3
|
+
// Element type of the client pixels, by GL type: half floats travel as their
|
|
4
|
+
// 16-bit patterns, never widened to float32.
|
|
5
|
+
const pixelKind = '(type == 0x1403 || type == 0x140B || type == 0x8D61 ? 2 : type == 0x1405 ? 3 : type == 0x1401 ? 4 : type == 0x1400 ? 5 : type == 0x1402 ? 6 : type == 0x1404 ? 7 : 1)';
|
|
3
6
|
export const nativeUploadFunctions = [
|
|
4
7
|
['threeWebGLBufferData', 'gea_three_webgl_buffer_data_native', ['target', 'usage', 'typeCode'], 'gea_three_webgl_buffer_data_bytes', ['target', 'usage'], 'typeCode'],
|
|
5
8
|
['threeWebGLBufferSubData', 'gea_three_webgl_buffer_sub_data_native', ['target', 'offset', 'typeCode'], 'gea_three_webgl_buffer_sub_data_bytes', ['target', 'offset'], 'typeCode'],
|
|
6
9
|
['threeWebGLBufferSubDataRange', 'gea_three_webgl_buffer_sub_data_range_native', ['target', 'offset', 'typeCode'], 'gea_three_webgl_buffer_sub_data_bytes', ['target', 'offset'], 'typeCode', true],
|
|
7
|
-
['threeWebGLTexImage2D', 'gea_three_webgl_tex_image_2d_native', ['target', 'level', 'internalFormat', 'width', 'height', 'format', 'type'], 'gea_three_webgl_tex_image_2d_bytes', ['target', 'level', 'internalFormat', 'width', 'height', 'format', 'type'],
|
|
8
|
-
['
|
|
10
|
+
['threeWebGLTexImage2D', 'gea_three_webgl_tex_image_2d_native', ['target', 'level', 'internalFormat', 'width', 'height', 'format', 'type'], 'gea_three_webgl_tex_image_2d_bytes', ['target', 'level', 'internalFormat', 'width', 'height', 'format', 'type'], pixelKind],
|
|
11
|
+
['threeWebGLTexImage3D', 'gea_three_webgl_tex_image_3d_native', ['target', 'level', 'internalFormat', 'width', 'height', 'depth', 'format', 'type'], 'gea_three_webgl_tex_image_3d_bytes', ['target', 'level', 'internalFormat', 'width', 'height', 'depth', 'format', 'type'], pixelKind],
|
|
12
|
+
['threeWebGLTexSubImage3D', 'gea_three_webgl_tex_sub_image_3d_native', ['target', 'level', 'xoffset', 'yoffset', 'zoffset', 'width', 'height', 'depth', 'format', 'type'], 'gea_three_webgl_tex_sub_image_3d_bytes', ['target', 'level', 'xoffset', 'yoffset', 'zoffset', 'width', 'height', 'depth', 'format', 'type'], pixelKind],
|
|
13
|
+
['threeWebGLTexSubImage2D', 'gea_three_webgl_tex_sub_image_2d_native', ['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format', 'type'], 'gea_three_webgl_tex_sub_image_2d_bytes', ['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format', 'type'], pixelKind],
|
|
9
14
|
].map(([name, binding, parameters, raw, rawParameters, kind, range]) => {
|
|
10
15
|
const declaration = `extern "C" void ${raw}(${rawParameters.map(p => `double ${p}`).join(', ')}, const void* bytes, double byteLength);
|
|
11
16
|
template <typename Source> inline void ${binding}(${parameters.map(p => `double ${p}`).join(', ')}, const Source& values${range ? ', double sourceOffset, double length' : ''}) {
|