@bigmistqke/view.gl 0.1.6 → 0.1.8

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/test/tag.test.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { toID } from '../src'
2
3
  import { attribute, compile, glsl, interleave, uniform } from '../src/tag'
3
4
  import type { GL } from '../src/types'
4
5
  import { createMockGL } from './mocks/webgl'
@@ -628,13 +629,15 @@ void main() { gl_FragColor = vec4(0.5); }`
628
629
 
629
630
  compile(gl, glsl``, fragment)
630
631
 
631
- // Check that shaderSource was called with symbol aliases in template
632
+ const colorAlias = toID(color_symbol)
633
+
634
+ // Check that shaderSource was called with exact symbol alias
632
635
  const fragmentShaderSource = (gl.shaderSource as any).mock.calls.find(
633
- (call: any[]) => call[1].includes('vec3') && call[1].includes('VIEW_GL_ALIAS_')
636
+ (call: any[]) => call[1].includes(`vec3 ${colorAlias}`)
634
637
  )?.[1]
635
638
 
636
- expect(fragmentShaderSource).toMatch(/vec3 VIEW_GL_ALIAS_\d+ = vec3/)
637
- expect(fragmentShaderSource).toMatch(/vec4\(VIEW_GL_ALIAS_\d+, 1\.0\)/)
639
+ expect(fragmentShaderSource).toContain(`vec3 ${colorAlias} = vec3(1.0, 0.0, 0.0);`)
640
+ expect(fragmentShaderSource).toContain(`gl_FragColor = vec4(${colorAlias}, 1.0);`)
638
641
  })
639
642
  })
640
643
 
@@ -914,84 +917,6 @@ describe('glsl composition', () => {
914
917
  })
915
918
  })
916
919
 
917
- describe('compile with symbols', () => {
918
- let gl: GL
919
- let mockProgram: WebGLProgram
920
-
921
- beforeEach(() => {
922
- gl = createMockGL()
923
- mockProgram = gl.createProgram()!
924
-
925
- // Mock shader creation and compilation
926
- gl.createShader = vi.fn(type => ({ type } as WebGLShader))
927
- gl.shaderSource = vi.fn()
928
- gl.compileShader = vi.fn()
929
- gl.getShaderParameter = vi.fn(() => true)
930
- gl.attachShader = vi.fn()
931
- gl.linkProgram = vi.fn()
932
- gl.getProgramParameter = vi.fn(() => true)
933
- gl.createProgram = vi.fn(() => mockProgram)
934
- })
935
-
936
- it('should compile shaders with symbol keys', () => {
937
- const u_time_symbol = Symbol('u_time')
938
- const a_position_symbol = Symbol('a_position')
939
-
940
- const vertex = glsl`
941
- ${attribute.vec2(a_position_symbol)}
942
- ${uniform.float(u_time_symbol)}
943
-
944
- void main() {
945
- gl_Position = vec4(${a_position_symbol}, 0.0, 1.0);
946
- }`
947
-
948
- const fragment = glsl`
949
- precision mediump float;
950
-
951
- ${uniform.float(u_time_symbol)}
952
-
953
- void main() {
954
- gl_FragColor = vec4(${u_time_symbol}, 0.0, 0.0, 1.0);
955
- }`
956
-
957
- const { program, schema } = compile(gl, vertex, fragment)
958
-
959
- expect(program).toBe(mockProgram)
960
- expect(schema.uniforms[u_time_symbol]).toEqual({ kind: 'float' })
961
- expect(schema.attributes[a_position_symbol]).toEqual({ kind: 'vec2' })
962
- })
963
-
964
- it('should merge symbols from vertex and fragment shaders', () => {
965
- const u_shared_symbol = Symbol('u_shared')
966
- const u_vertex_only = Symbol('u_vertex_only')
967
- const u_fragment_only = Symbol('u_fragment_only')
968
-
969
- const vertex = glsl`
970
- ${uniform.float(u_shared_symbol)}
971
- ${uniform.vec2(u_vertex_only)}
972
-
973
- void main() {
974
- gl_Position = vec4(${u_vertex_only}, ${u_shared_symbol}, 1.0);
975
- }`
976
-
977
- const fragment = glsl`
978
- precision mediump float;
979
-
980
- ${uniform.float(u_shared_symbol)}
981
- ${uniform.vec3(u_fragment_only)}
982
-
983
- void main() {
984
- gl_FragColor = vec4(${u_fragment_only}, ${u_shared_symbol});
985
- }`
986
-
987
- const { schema } = compile(gl, vertex, fragment)
988
-
989
- expect(schema.uniforms[u_shared_symbol]).toEqual({ kind: 'float' })
990
- expect(schema.uniforms[u_vertex_only]).toEqual({ kind: 'vec2' })
991
- expect(schema.uniforms[u_fragment_only]).toEqual({ kind: 'vec3' })
992
- })
993
- })
994
-
995
920
  describe('glsl array interpolation', () => {
996
921
  let gl: GL
997
922
 
@@ -1505,4 +1430,642 @@ describe('compile', () => {
1505
1430
  expect(gl.linkProgram).toHaveBeenCalled()
1506
1431
  expect(gl.getProgramParameter).toHaveBeenCalled()
1507
1432
  })
1433
+
1434
+ it('should compile shaders with symbol keys', () => {
1435
+ const u_time_symbol = Symbol('u_time')
1436
+ const a_position_symbol = Symbol('a_position')
1437
+
1438
+ const vertex = glsl`
1439
+ ${attribute.vec2(a_position_symbol)}
1440
+ ${uniform.float(u_time_symbol)}
1441
+
1442
+ void main() {
1443
+ gl_Position = vec4(${a_position_symbol}, 0.0, 1.0);
1444
+ }`
1445
+
1446
+ const fragment = glsl`
1447
+ precision mediump float;
1448
+
1449
+ ${uniform.float(u_time_symbol)}
1450
+
1451
+ void main() {
1452
+ gl_FragColor = vec4(${u_time_symbol}, 0.0, 0.0, 1.0);
1453
+ }`
1454
+
1455
+ const { program, schema } = compile(gl, vertex, fragment)
1456
+
1457
+ expect(program).toBe(mockProgram)
1458
+ expect(schema.uniforms[u_time_symbol]).toEqual({ kind: 'float' })
1459
+ expect(schema.attributes[a_position_symbol]).toEqual({ kind: 'vec2' })
1460
+ })
1461
+
1462
+ it('should merge symbols from vertex and fragment shaders', () => {
1463
+ const u_shared_symbol = Symbol('u_shared')
1464
+ const u_vertex_only = Symbol('u_vertex_only')
1465
+ const u_fragment_only = Symbol('u_fragment_only')
1466
+
1467
+ const vertex = glsl`
1468
+ ${uniform.float(u_shared_symbol)}
1469
+ ${uniform.vec2(u_vertex_only)}
1470
+
1471
+ void main() {
1472
+ gl_Position = vec4(${u_vertex_only}, ${u_shared_symbol}, 1.0);
1473
+ }`
1474
+
1475
+ const fragment = glsl`
1476
+ precision mediump float;
1477
+
1478
+ ${uniform.float(u_shared_symbol)}
1479
+ ${uniform.vec3(u_fragment_only)}
1480
+
1481
+ void main() {
1482
+ gl_FragColor = vec4(${u_fragment_only}, ${u_shared_symbol});
1483
+ }`
1484
+
1485
+ const { schema } = compile(gl, vertex, fragment)
1486
+
1487
+ expect(schema.uniforms[u_shared_symbol]).toEqual({ kind: 'float' })
1488
+ expect(schema.uniforms[u_vertex_only]).toEqual({ kind: 'vec2' })
1489
+ expect(schema.uniforms[u_fragment_only]).toEqual({ kind: 'vec3' })
1490
+ })
1491
+
1492
+ it('should return compiled vertex and fragment shader strings', () => {
1493
+ const vertex = glsl`
1494
+ ${attribute.vec2('a_position')}
1495
+ ${uniform.mat4('u_mvpMatrix')}
1496
+
1497
+ void main() {
1498
+ gl_Position = u_mvpMatrix * vec4(a_position, 0.0, 1.0);
1499
+ }
1500
+ `
1501
+
1502
+ const fragment = glsl`
1503
+ precision mediump float;
1504
+ ${uniform.vec4('u_color')}
1505
+
1506
+ void main() {
1507
+ gl_FragColor = u_color;
1508
+ }
1509
+ `
1510
+
1511
+ const result = compile(gl, vertex, fragment)
1512
+
1513
+ // Check vertex shader string
1514
+ expect(result.vertex).toContain('attribute vec2 a_position;')
1515
+ expect(result.vertex).toContain('uniform mat4 u_mvpMatrix;')
1516
+ expect(result.vertex).toContain('gl_Position = u_mvpMatrix * vec4(a_position, 0.0, 1.0);')
1517
+
1518
+ // Check fragment shader string
1519
+ expect(result.fragment).toContain('precision mediump float;')
1520
+ expect(result.fragment).toContain('uniform vec4 u_color;')
1521
+ expect(result.fragment).toContain('gl_FragColor = u_color;')
1522
+ })
1523
+
1524
+ it('should return WebGL2 shader strings with proper syntax', () => {
1525
+ const vertex = glsl`#version 300 es
1526
+ ${attribute.vec3('a_position')}
1527
+ ${attribute.vec3('a_normal')}
1528
+ out vec3 v_normal;
1529
+
1530
+ void main() {
1531
+ v_normal = a_normal;
1532
+ gl_Position = vec4(a_position, 1.0);
1533
+ }
1534
+ `
1535
+
1536
+ const fragment = glsl`#version 300 es
1537
+ precision mediump float;
1538
+ ${uniform.vec3('u_lightDir')}
1539
+ in vec3 v_normal;
1540
+ out vec4 fragColor;
1541
+
1542
+ void main() {
1543
+ float light = dot(v_normal, u_lightDir);
1544
+ fragColor = vec4(vec3(light), 1.0);
1545
+ }
1546
+ `
1547
+
1548
+ const result = compile(gl, vertex, fragment)
1549
+
1550
+ // Check vertex uses 'in' for attributes in WebGL2
1551
+ expect(result.vertex).toContain('in vec3 a_position;')
1552
+ expect(result.vertex).toContain('in vec3 a_normal;')
1553
+ expect(result.vertex).toContain('out vec3 v_normal;')
1554
+
1555
+ // Check fragment shader WebGL2 syntax
1556
+ expect(result.fragment).toContain('#version 300 es')
1557
+ expect(result.fragment).toContain('in vec3 v_normal;')
1558
+ expect(result.fragment).toContain('out vec4 fragColor;')
1559
+ })
1560
+
1561
+ it('should return shader strings with resolved symbols', () => {
1562
+ const u_time_symbol = Symbol('u_time')
1563
+ const a_pos_symbol = Symbol('a_position')
1564
+
1565
+ const vertex = glsl`
1566
+ ${attribute.vec3(a_pos_symbol)}
1567
+ ${uniform.float(u_time_symbol)}
1568
+
1569
+ void main() {
1570
+ gl_Position = vec4(${a_pos_symbol}, ${u_time_symbol});
1571
+ }
1572
+ `
1573
+
1574
+ const fragment = glsl`
1575
+ precision mediump float;
1576
+ ${uniform.float(u_time_symbol)}
1577
+
1578
+ void main() {
1579
+ gl_FragColor = vec4(${u_time_symbol});
1580
+ }
1581
+ `
1582
+
1583
+ const result = compile(gl, vertex, fragment)
1584
+
1585
+ // Get exact symbol aliases
1586
+ const posAlias = toID(a_pos_symbol)
1587
+ const timeAlias = toID(u_time_symbol)
1588
+
1589
+ // Check vertex shader contains expected exact strings
1590
+ expect(result.vertex).toContain(`attribute vec3 ${posAlias};`)
1591
+ expect(result.vertex).toContain(`uniform float ${timeAlias};`)
1592
+ expect(result.vertex).toContain(`gl_Position = vec4(${posAlias}, ${timeAlias});`)
1593
+
1594
+ // Check fragment shader contains expected exact strings
1595
+ expect(result.fragment).toContain(`uniform float ${timeAlias};`)
1596
+ expect(result.fragment).toContain(`gl_FragColor = vec4(${timeAlias});`)
1597
+ expect(result.fragment).toContain('precision mediump float;')
1598
+ })
1599
+
1600
+ it('should return shader strings with interleaved attributes', () => {
1601
+ const vertex = glsl`
1602
+ ${interleave('vertexData', [
1603
+ attribute.vec3('a_position'),
1604
+ attribute.vec2('a_uv'),
1605
+ attribute.vec3('a_normal')
1606
+ ])}
1607
+
1608
+ void main() {
1609
+ gl_Position = vec4(a_position + a_normal, 0.0, 1.0);
1610
+ }
1611
+ `
1612
+
1613
+ const fragment = glsl`
1614
+ precision mediump float;
1615
+
1616
+ void main() {
1617
+ gl_FragColor = vec4(1.0);
1618
+ }
1619
+ `
1620
+
1621
+ const result = compile(gl, vertex, fragment)
1622
+
1623
+ // Check all interleaved attributes are expanded in vertex shader
1624
+ expect(result.vertex).toContain('attribute vec3 a_position;')
1625
+ expect(result.vertex).toContain('attribute vec2 a_uv;')
1626
+ expect(result.vertex).toContain('attribute vec3 a_normal;')
1627
+ expect(result.vertex).toContain('gl_Position = vec4(a_position + a_normal, 0.0, 1.0);')
1628
+
1629
+ // Fragment shader should be returned as-is
1630
+ expect(result.fragment).toContain('precision mediump float;')
1631
+ expect(result.fragment).toContain('gl_FragColor = vec4(1.0);')
1632
+ })
1633
+
1634
+ it('should return shader strings with composed GLSL fragments', () => {
1635
+ const sharedUniforms = glsl`
1636
+ ${uniform.float('u_time')}
1637
+ ${uniform.vec2('u_resolution')}
1638
+ `
1639
+
1640
+ const utils = glsl`
1641
+ float rand(vec2 co) {
1642
+ return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
1643
+ }
1644
+ `
1645
+
1646
+ const vertex = glsl`
1647
+ ${sharedUniforms}
1648
+ ${attribute.vec2('a_position')}
1649
+
1650
+ void main() {
1651
+ gl_Position = vec4(a_position * u_resolution, 0.0, 1.0);
1652
+ }
1653
+ `
1654
+
1655
+ const fragment = glsl`
1656
+ precision mediump float;
1657
+ ${sharedUniforms}
1658
+ ${utils}
1659
+
1660
+ void main() {
1661
+ float r = rand(gl_FragCoord.xy * u_time);
1662
+ gl_FragColor = vec4(r);
1663
+ }
1664
+ `
1665
+
1666
+ const result = compile(gl, vertex, fragment)
1667
+
1668
+ // Check vertex shader includes composed uniforms
1669
+ expect(result.vertex).toContain('uniform float u_time;')
1670
+ expect(result.vertex).toContain('uniform vec2 u_resolution;')
1671
+ expect(result.vertex).toContain('attribute vec2 a_position;')
1672
+
1673
+ // Check fragment shader includes both uniforms and utils
1674
+ expect(result.fragment).toContain('uniform float u_time;')
1675
+ expect(result.fragment).toContain('uniform vec2 u_resolution;')
1676
+ expect(result.fragment).toContain('float rand(vec2 co)')
1677
+ expect(result.fragment).toContain('return fract(sin(dot(co.xy')
1678
+ })
1679
+
1680
+ it('should return shader strings with array interpolations', () => {
1681
+ const vertex = glsl`
1682
+ ${[
1683
+ uniform.mat4('u_model'),
1684
+ uniform.mat4('u_view'),
1685
+ uniform.mat4('u_projection')
1686
+ ]}
1687
+ ${[attribute.vec3('a_position'), attribute.vec3('a_normal')]}
1688
+
1689
+ void main() {
1690
+ gl_Position = u_projection * u_view * u_model * vec4(a_position, 1.0);
1691
+ }
1692
+ `
1693
+
1694
+ const fragment = glsl`
1695
+ precision mediump float;
1696
+ ${[uniform.vec3('u_color'), uniform.float('u_alpha')]}
1697
+
1698
+ void main() {
1699
+ gl_FragColor = vec4(u_color, u_alpha);
1700
+ }
1701
+ `
1702
+
1703
+ const result = compile(gl, vertex, fragment)
1704
+
1705
+ // Check vertex shader has all uniforms and attributes from arrays
1706
+ expect(result.vertex).toContain('uniform mat4 u_model;')
1707
+ expect(result.vertex).toContain('uniform mat4 u_view;')
1708
+ expect(result.vertex).toContain('uniform mat4 u_projection;')
1709
+ expect(result.vertex).toContain('attribute vec3 a_position;')
1710
+ expect(result.vertex).toContain('attribute vec3 a_normal;')
1711
+
1712
+ // Check fragment shader
1713
+ expect(result.fragment).toContain('uniform vec3 u_color;')
1714
+ expect(result.fragment).toContain('uniform float u_alpha;')
1715
+ })
1716
+ })
1717
+
1718
+ describe('compile.toString', () => {
1719
+ it('should convert glsl tag to shader string', () => {
1720
+ const shader = glsl`
1721
+ ${uniform.float('u_time')}
1722
+ ${attribute.vec2('a_position')}
1723
+
1724
+ void main() {
1725
+ gl_Position = vec4(a_position, 0.0, 1.0);
1726
+ }`
1727
+
1728
+ const result = compile.toString(shader)
1729
+
1730
+ expect(result).toContain('uniform float u_time;')
1731
+ expect(result).toContain('attribute vec2 a_position;')
1732
+ expect(result).toContain('void main() {')
1733
+ expect(result).toContain('gl_Position = vec4(a_position, 0.0, 1.0);')
1734
+ })
1735
+
1736
+ it('should handle WebGL2 syntax', () => {
1737
+ const shader = glsl`#version 300 es
1738
+ ${uniform.float('u_time')}
1739
+ ${attribute.vec3('a_position')}
1740
+
1741
+ void main() {
1742
+ gl_Position = vec4(a_position, 1.0);
1743
+ }`
1744
+
1745
+ const result = compile.toString(shader)
1746
+
1747
+ expect(result).toContain('#version 300 es')
1748
+ expect(result).toContain('uniform float u_time;')
1749
+ expect(result).toContain('in vec3 a_position;')
1750
+ })
1751
+
1752
+ it('should handle arrays', () => {
1753
+ const shader = glsl`
1754
+ ${uniform.vec3('u_palette', { size: 5 })}
1755
+
1756
+ void main() {
1757
+ gl_FragColor = vec4(u_palette[0], 1.0);
1758
+ }`
1759
+
1760
+ const result = compile.toString(shader)
1761
+
1762
+ expect(result).toContain('uniform vec3 u_palette[5];')
1763
+ })
1764
+
1765
+ it('should handle symbols', () => {
1766
+ const u_time_symbol = Symbol('u_time')
1767
+ const shader = glsl`
1768
+ ${uniform.float(u_time_symbol)}
1769
+
1770
+ void main() {
1771
+ gl_FragColor = vec4(${u_time_symbol});
1772
+ }`
1773
+
1774
+ const result = compile.toString(shader)
1775
+ const timeAlias = toID(u_time_symbol)
1776
+
1777
+ expect(result).toContain(`uniform float ${timeAlias};`)
1778
+ expect(result).toContain(`gl_FragColor = vec4(${timeAlias});`)
1779
+ })
1780
+
1781
+ it('should handle interleaved attributes', () => {
1782
+ const shader = glsl`
1783
+ ${interleave('vertexData', [
1784
+ attribute.vec2('a_position'),
1785
+ attribute.vec4('a_color')
1786
+ ])}
1787
+
1788
+ void main() {
1789
+ gl_Position = vec4(a_position, 0.0, 1.0);
1790
+ }`
1791
+
1792
+ const result = compile.toString(shader)
1793
+
1794
+ expect(result).toContain('attribute vec2 a_position;')
1795
+ expect(result).toContain('attribute vec4 a_color;')
1796
+ })
1797
+
1798
+ it('should handle nested glsl tags', () => {
1799
+ const uniforms = glsl`${uniform.float('u_time')}`
1800
+ const shader = glsl`
1801
+ ${uniforms}
1802
+ ${attribute.vec2('a_position')}
1803
+
1804
+ void main() {
1805
+ gl_Position = vec4(a_position, u_time, 0.0, 1.0);
1806
+ }`
1807
+
1808
+ const result = compile.toString(shader)
1809
+
1810
+ expect(result).toContain('uniform float u_time;')
1811
+ expect(result).toContain('attribute vec2 a_position;')
1812
+ })
1813
+
1814
+ it('should handle arrays of resources', () => {
1815
+ const shader = glsl`
1816
+ ${[uniform.float('u_time'), uniform.vec2('u_resolution')]}
1817
+
1818
+ void main() {
1819
+ gl_Position = vec4(u_resolution * u_time, 0.0, 1.0);
1820
+ }`
1821
+
1822
+ const result = compile.toString(shader)
1823
+
1824
+ expect(result).toContain('uniform float u_time;')
1825
+ expect(result).toContain('uniform vec2 u_resolution;')
1826
+ })
1827
+
1828
+ it('should handle string interpolations', () => {
1829
+ const maxLights = 4
1830
+ const shader = glsl`
1831
+ #define MAX_LIGHTS ${maxLights}
1832
+ ${uniform.float('u_time')}
1833
+
1834
+ void main() {
1835
+ gl_Position = vec4(1.0);
1836
+ }`
1837
+
1838
+ const result = compile.toString(shader)
1839
+
1840
+ expect(result).toContain('#define MAX_LIGHTS 4')
1841
+ expect(result).toContain('uniform float u_time;')
1842
+ })
1843
+ })
1844
+
1845
+ describe('compile.toSchema', () => {
1846
+ it('should extract schema from glsl tag', () => {
1847
+ const shader = glsl`
1848
+ ${uniform.float('u_time')}
1849
+ ${uniform.vec3('u_color')}
1850
+ ${attribute.vec2('a_position')}
1851
+
1852
+ void main() {
1853
+ gl_Position = vec4(a_position, 0.0, 1.0);
1854
+ }`
1855
+
1856
+ const schema = compile.toSchema(shader)
1857
+
1858
+ expect(schema).toEqual({
1859
+ uniforms: {
1860
+ u_time: { kind: 'float' },
1861
+ u_color: { kind: 'vec3' }
1862
+ },
1863
+ attributes: {
1864
+ a_position: { kind: 'vec2' }
1865
+ },
1866
+ interleavedAttributes: {}
1867
+ })
1868
+ })
1869
+
1870
+ it('should handle arrays', () => {
1871
+ const shader = glsl`
1872
+ ${uniform.vec3('u_palette', { size: 5 })}
1873
+ ${uniform.mat4('u_matrices', { size: 10 })}
1874
+
1875
+ void main() {}`
1876
+
1877
+ const schema = compile.toSchema(shader)
1878
+
1879
+ expect(schema).toEqual({
1880
+ uniforms: {
1881
+ u_palette: { kind: 'vec3', size: 5 },
1882
+ u_matrices: { kind: 'mat4', size: 10 }
1883
+ },
1884
+ attributes: {},
1885
+ interleavedAttributes: {}
1886
+ })
1887
+ })
1888
+
1889
+ it('should handle symbols', () => {
1890
+ const u_time_symbol = Symbol('u_time')
1891
+ const a_pos_symbol = Symbol('a_position')
1892
+
1893
+ const shader = glsl`
1894
+ ${uniform.float(u_time_symbol)}
1895
+ ${attribute.vec3(a_pos_symbol)}
1896
+
1897
+ void main() {}`
1898
+
1899
+ const schema = compile.toSchema(shader)
1900
+
1901
+ expect(schema).toEqual({
1902
+ uniforms: {
1903
+ [u_time_symbol]: { kind: 'float' }
1904
+ },
1905
+ attributes: {
1906
+ [a_pos_symbol]: { kind: 'vec3' }
1907
+ },
1908
+ interleavedAttributes: {}
1909
+ })
1910
+ })
1911
+
1912
+ it('should handle interleaved attributes', () => {
1913
+ const shader = glsl`
1914
+ ${interleave('vertexData', [
1915
+ attribute.vec2('a_position'),
1916
+ attribute.vec4('a_color')
1917
+ ])}
1918
+ ${interleave('instanceData', [
1919
+ attribute.vec3('a_instancePos'),
1920
+ attribute.float('a_instanceScale')
1921
+ ], { instanced: true })}
1922
+
1923
+ void main() {}`
1924
+
1925
+ const schema = compile.toSchema(shader)
1926
+
1927
+ expect(schema).toEqual({
1928
+ uniforms: {},
1929
+ attributes: {},
1930
+ interleavedAttributes: {
1931
+ vertexData: {
1932
+ layout: [
1933
+ { key: 'a_position', kind: 'vec2' },
1934
+ { key: 'a_color', kind: 'vec4' }
1935
+ ],
1936
+ instanced: false
1937
+ },
1938
+ instanceData: {
1939
+ layout: [
1940
+ { key: 'a_instancePos', kind: 'vec3' },
1941
+ { key: 'a_instanceScale', kind: 'float' }
1942
+ ],
1943
+ instanced: true
1944
+ }
1945
+ }
1946
+ })
1947
+ })
1948
+
1949
+ it('should handle nested glsl tags', () => {
1950
+ const uniforms = glsl`
1951
+ ${uniform.float('u_time')}
1952
+ ${uniform.vec2('u_resolution')}
1953
+ `
1954
+
1955
+ const lighting = glsl`
1956
+ ${uniform.vec3('u_lightPos')}
1957
+ ${uniform.vec3('u_lightColor')}
1958
+ `
1959
+
1960
+ const shader = glsl`
1961
+ ${uniforms}
1962
+ ${lighting}
1963
+ ${attribute.vec3('a_position')}
1964
+
1965
+ void main() {}`
1966
+
1967
+ const schema = compile.toSchema(shader)
1968
+
1969
+ expect(schema).toEqual({
1970
+ uniforms: {
1971
+ u_time: { kind: 'float' },
1972
+ u_resolution: { kind: 'vec2' },
1973
+ u_lightPos: { kind: 'vec3' },
1974
+ u_lightColor: { kind: 'vec3' }
1975
+ },
1976
+ attributes: {
1977
+ a_position: { kind: 'vec3' }
1978
+ },
1979
+ interleavedAttributes: {}
1980
+ })
1981
+ })
1982
+
1983
+ it('should handle arrays of resources', () => {
1984
+ const shader = glsl`
1985
+ ${[
1986
+ uniform.float('u_time'),
1987
+ uniform.vec2('u_resolution'),
1988
+ attribute.vec3('a_position')
1989
+ ]}
1990
+ ${[
1991
+ interleave('data', [
1992
+ attribute.vec2('a_uv')
1993
+ ])
1994
+ ]}
1995
+
1996
+ void main() {}`
1997
+
1998
+ const schema = compile.toSchema(shader)
1999
+
2000
+ expect(schema).toEqual({
2001
+ uniforms: {
2002
+ u_time: { kind: 'float' },
2003
+ u_resolution: { kind: 'vec2' }
2004
+ },
2005
+ attributes: {
2006
+ a_position: { kind: 'vec3' }
2007
+ },
2008
+ interleavedAttributes: {
2009
+ data: {
2010
+ layout: [
2011
+ { key: 'a_uv', kind: 'vec2' }
2012
+ ],
2013
+ instanced: false
2014
+ }
2015
+ }
2016
+ })
2017
+ })
2018
+
2019
+ it('should ignore non-resource interpolations', () => {
2020
+ const shader = glsl`
2021
+ ${'// Comment'}
2022
+ ${42}
2023
+ ${uniform.float('u_time')}
2024
+ ${'precision highp float;'}
2025
+
2026
+ void main() {}`
2027
+
2028
+ const schema = compile.toSchema(shader)
2029
+
2030
+ expect(schema).toEqual({
2031
+ uniforms: {
2032
+ u_time: { kind: 'float' }
2033
+ },
2034
+ attributes: {},
2035
+ interleavedAttributes: {}
2036
+ })
2037
+ })
2038
+
2039
+ it('should handle empty glsl tag', () => {
2040
+ const shader = glsl`void main() {}`
2041
+
2042
+ const schema = compile.toSchema(shader)
2043
+
2044
+ expect(schema).toEqual({
2045
+ uniforms: {},
2046
+ attributes: {},
2047
+ interleavedAttributes: {}
2048
+ })
2049
+ })
2050
+
2051
+ it('should handle instanced attributes', () => {
2052
+ const shader = glsl`
2053
+ ${attribute.vec3('a_position')}
2054
+ ${attribute.vec4('a_color', { instanced: true })}
2055
+ ${attribute.mat4('a_instanceMatrix', { instanced: true })}
2056
+
2057
+ void main() {}`
2058
+
2059
+ const schema = compile.toSchema(shader)
2060
+
2061
+ expect(schema).toEqual({
2062
+ uniforms: {},
2063
+ attributes: {
2064
+ a_position: { kind: 'vec3' },
2065
+ a_color: { kind: 'vec4', instanced: true },
2066
+ a_instanceMatrix: { kind: 'mat4', instanced: true }
2067
+ },
2068
+ interleavedAttributes: {}
2069
+ })
2070
+ })
1508
2071
  })