@bigmistqke/view.gl 0.1.8 → 0.1.9
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/.claude/settings.local.json +2 -1
- package/README.md +30 -0
- package/dev/src/examples/bezier.ts +3 -2
- package/dev/src/examples/game-of-life.ts +13 -30
- package/dev/src/examples/glsl-composition.ts +3 -3
- package/dev/src/examples/grid.ts +20 -14
- package/dev/src/examples/pix-sim.ts +29 -22
- package/dev/src/examples/ray-casting.ts +455 -0
- package/dev/src/examples/sdf.ts +98 -0
- package/dev/src/examples/symbol.ts +2 -2
- package/dev/src/index.ts +12 -11
- package/dev/src/utils.ts +18 -4
- package/dist/index.d.mts +2 -2
- package/dist/tag.d.mts +21 -4
- package/dist/tag.mjs +78 -39
- package/dist/tag.mjs.map +1 -1
- package/dist/{types-Bp9VAVe3.d.mts → types-DaV9McmR.d.mts} +18 -14
- package/package.json +1 -1
- package/src/tag.ts +111 -44
- package/src/types.ts +36 -22
- package/test/tag.test.ts +462 -0
package/test/tag.test.ts
CHANGED
|
@@ -1715,6 +1715,468 @@ describe('compile', () => {
|
|
|
1715
1715
|
})
|
|
1716
1716
|
})
|
|
1717
1717
|
|
|
1718
|
+
describe('compile.toQuad', () => {
|
|
1719
|
+
let gl: GL
|
|
1720
|
+
let mockProgram: WebGLProgram
|
|
1721
|
+
|
|
1722
|
+
beforeEach(() => {
|
|
1723
|
+
gl = createMockGL()
|
|
1724
|
+
mockProgram = gl.createProgram()!
|
|
1725
|
+
|
|
1726
|
+
// Mock shader creation and compilation
|
|
1727
|
+
gl.createShader = vi.fn(type => ({ type } as WebGLShader))
|
|
1728
|
+
gl.shaderSource = vi.fn()
|
|
1729
|
+
gl.compileShader = vi.fn()
|
|
1730
|
+
gl.getShaderParameter = vi.fn(() => true)
|
|
1731
|
+
gl.attachShader = vi.fn()
|
|
1732
|
+
gl.linkProgram = vi.fn()
|
|
1733
|
+
gl.getProgramParameter = vi.fn(() => true)
|
|
1734
|
+
gl.createProgram = vi.fn(() => mockProgram)
|
|
1735
|
+
gl.createBuffer = vi.fn(() => ({} as WebGLBuffer))
|
|
1736
|
+
gl.bindBuffer = vi.fn()
|
|
1737
|
+
gl.bufferData = vi.fn()
|
|
1738
|
+
})
|
|
1739
|
+
|
|
1740
|
+
it('should create a quad with fragment shader only', () => {
|
|
1741
|
+
const fragment = glsl`
|
|
1742
|
+
precision mediump float;
|
|
1743
|
+
${uniform.float('u_time')}
|
|
1744
|
+
${uniform.vec2('u_resolution')}
|
|
1745
|
+
|
|
1746
|
+
in vec2 uv;
|
|
1747
|
+
out vec4 fragColor;
|
|
1748
|
+
|
|
1749
|
+
void main() {
|
|
1750
|
+
vec2 pos = uv * u_resolution;
|
|
1751
|
+
float pattern = sin(pos.x * 0.01 + u_time) * sin(pos.y * 0.01 + u_time);
|
|
1752
|
+
fragColor = vec4(vec3(pattern), 1.0);
|
|
1753
|
+
}
|
|
1754
|
+
`
|
|
1755
|
+
|
|
1756
|
+
const result = compile.toQuad(gl, fragment)
|
|
1757
|
+
|
|
1758
|
+
expect(result.program).toBe(mockProgram)
|
|
1759
|
+
|
|
1760
|
+
// Should have quad attribute in schema
|
|
1761
|
+
expect(result.schema.attributes).toEqual({
|
|
1762
|
+
a_quad: { kind: 'vec2', buffer: expect.any(Object) }
|
|
1763
|
+
})
|
|
1764
|
+
|
|
1765
|
+
// Should have fragment uniforms
|
|
1766
|
+
expect(result.schema.uniforms).toEqual({
|
|
1767
|
+
u_time: { kind: 'float' },
|
|
1768
|
+
u_resolution: { kind: 'vec2' }
|
|
1769
|
+
})
|
|
1770
|
+
})
|
|
1771
|
+
|
|
1772
|
+
it('should generate vertex shader with correct uv output', () => {
|
|
1773
|
+
const fragment = glsl`#version 300 es
|
|
1774
|
+
precision mediump float;
|
|
1775
|
+
${uniform.vec3('u_color')}
|
|
1776
|
+
|
|
1777
|
+
in vec2 v_uv;
|
|
1778
|
+
out vec4 fragColor;
|
|
1779
|
+
|
|
1780
|
+
void main() {
|
|
1781
|
+
fragColor = vec4(u_color * v_uv.x, 1.0);
|
|
1782
|
+
}
|
|
1783
|
+
`
|
|
1784
|
+
|
|
1785
|
+
const result = compile.toQuad(gl, fragment)
|
|
1786
|
+
|
|
1787
|
+
// Check that vertex shader contains expected content
|
|
1788
|
+
expect(result.vertex).toContain('#version 300 es')
|
|
1789
|
+
expect(result.vertex).toContain('in vec2 a_quad;')
|
|
1790
|
+
expect(result.vertex).toContain('out vec2 v_uv;')
|
|
1791
|
+
expect(result.vertex).toContain('v_uv = a_quad;')
|
|
1792
|
+
expect(result.vertex).toContain('gl_Position = vec4(v_uv, 0.0, 1.0);')
|
|
1793
|
+
})
|
|
1794
|
+
|
|
1795
|
+
it('should handle fragment shader with multiple uniforms', () => {
|
|
1796
|
+
const fragment = glsl`#version 300 es
|
|
1797
|
+
precision mediump float;
|
|
1798
|
+
|
|
1799
|
+
${uniform.float('u_time')}
|
|
1800
|
+
${uniform.vec2('u_resolution')}
|
|
1801
|
+
${uniform.vec3('u_color')}
|
|
1802
|
+
${uniform.sampler2D('u_texture')}
|
|
1803
|
+
|
|
1804
|
+
in vec2 uv;
|
|
1805
|
+
out vec4 fragColor;
|
|
1806
|
+
|
|
1807
|
+
void main() {
|
|
1808
|
+
vec2 pos = uv * u_resolution + u_time;
|
|
1809
|
+
vec4 tex = texture(u_texture, pos);
|
|
1810
|
+
fragColor = vec4(u_color * tex.rgb, 1.0);
|
|
1811
|
+
}
|
|
1812
|
+
`
|
|
1813
|
+
|
|
1814
|
+
const result = compile.toQuad(gl, fragment)
|
|
1815
|
+
|
|
1816
|
+
expect(result.schema.uniforms).toEqual({
|
|
1817
|
+
u_time: { kind: 'float' },
|
|
1818
|
+
u_resolution: { kind: 'vec2' },
|
|
1819
|
+
u_color: { kind: 'vec3' },
|
|
1820
|
+
u_texture: { kind: 'sampler2D' }
|
|
1821
|
+
})
|
|
1822
|
+
|
|
1823
|
+
expect(result.schema.attributes).toEqual({
|
|
1824
|
+
a_quad: { kind: 'vec2', buffer: expect.any(Object) }
|
|
1825
|
+
})
|
|
1826
|
+
})
|
|
1827
|
+
|
|
1828
|
+
it('should automatically set up quad buffer data', () => {
|
|
1829
|
+
const fragment = glsl`
|
|
1830
|
+
precision mediump float;
|
|
1831
|
+
void main() { gl_FragColor = vec4(1.0); }
|
|
1832
|
+
`
|
|
1833
|
+
|
|
1834
|
+
const result = compile.toQuad(gl, fragment)
|
|
1835
|
+
|
|
1836
|
+
// Check that buffer was created and data was set
|
|
1837
|
+
expect(gl.createBuffer).toHaveBeenCalled()
|
|
1838
|
+
expect(gl.bindBuffer).toHaveBeenCalled()
|
|
1839
|
+
expect(gl.bufferData).toHaveBeenCalled()
|
|
1840
|
+
|
|
1841
|
+
// Verify the quad data contains correct triangle vertices
|
|
1842
|
+
const bufferDataCall = (gl.bufferData as any).mock.calls[0]
|
|
1843
|
+
const quadData = bufferDataCall[1] as Float32Array
|
|
1844
|
+
|
|
1845
|
+
// Should contain 6 vertices for 2 triangles forming a quad
|
|
1846
|
+
expect(quadData.length).toBe(12) // 6 vertices * 2 components
|
|
1847
|
+
expect(Array.from(quadData)).toEqual([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1])
|
|
1848
|
+
})
|
|
1849
|
+
|
|
1850
|
+
it('should work with ray-marching fragment shader', () => {
|
|
1851
|
+
const fragment = glsl`#version 300 es
|
|
1852
|
+
precision mediump float;
|
|
1853
|
+
|
|
1854
|
+
${uniform.float('u_time')}
|
|
1855
|
+
${uniform.vec2('u_resolution')}
|
|
1856
|
+
${uniform.vec3('u_cameraPos')}
|
|
1857
|
+
|
|
1858
|
+
in vec2 uv;
|
|
1859
|
+
out vec4 fragColor;
|
|
1860
|
+
|
|
1861
|
+
float sdSphere(vec3 pos, float radius) {
|
|
1862
|
+
return length(pos) - radius;
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
void main() {
|
|
1866
|
+
vec2 screenPos = uv * u_resolution;
|
|
1867
|
+
vec3 rayDir = normalize(vec3(screenPos, -1.0));
|
|
1868
|
+
|
|
1869
|
+
float dist = sdSphere(u_cameraPos, 1.0);
|
|
1870
|
+
vec3 color = vec3(smoothstep(0.0, 0.1, dist));
|
|
1871
|
+
|
|
1872
|
+
fragColor = vec4(color, 1.0);
|
|
1873
|
+
}
|
|
1874
|
+
`
|
|
1875
|
+
|
|
1876
|
+
const result = compile.toQuad(gl, fragment)
|
|
1877
|
+
|
|
1878
|
+
expect(result.schema.uniforms).toEqual({
|
|
1879
|
+
u_time: { kind: 'float' },
|
|
1880
|
+
u_resolution: { kind: 'vec2' },
|
|
1881
|
+
u_cameraPos: { kind: 'vec3' }
|
|
1882
|
+
})
|
|
1883
|
+
|
|
1884
|
+
// Should compile without errors
|
|
1885
|
+
expect(result.program).toBe(mockProgram)
|
|
1886
|
+
expect(result.vertex).toContain('in vec2 a_quad;')
|
|
1887
|
+
expect(result.fragment).toContain('float sdSphere')
|
|
1888
|
+
})
|
|
1889
|
+
|
|
1890
|
+
it('should support options parameter', () => {
|
|
1891
|
+
const fragment = glsl`
|
|
1892
|
+
precision mediump float;
|
|
1893
|
+
${uniform.float('u_time')}
|
|
1894
|
+
void main() { gl_FragColor = vec4(1.0); }
|
|
1895
|
+
`
|
|
1896
|
+
|
|
1897
|
+
const options = {
|
|
1898
|
+
schema: {
|
|
1899
|
+
uniforms: {
|
|
1900
|
+
u_customUniform: { kind: 'vec3' as const }
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
const result = compile.toQuad(gl, fragment, options)
|
|
1906
|
+
|
|
1907
|
+
// Should merge the custom schema
|
|
1908
|
+
expect(result.schema.uniforms).toEqual({
|
|
1909
|
+
u_time: { kind: 'float' },
|
|
1910
|
+
u_customUniform: { kind: 'vec3' }
|
|
1911
|
+
})
|
|
1912
|
+
})
|
|
1913
|
+
|
|
1914
|
+
it('should handle fragment shader with symbol uniforms', () => {
|
|
1915
|
+
const u_time_symbol = Symbol('u_time')
|
|
1916
|
+
const u_color_symbol = Symbol('u_color')
|
|
1917
|
+
|
|
1918
|
+
const fragment = glsl`
|
|
1919
|
+
precision mediump float;
|
|
1920
|
+
|
|
1921
|
+
${uniform.float(u_time_symbol)}
|
|
1922
|
+
${uniform.vec3(u_color_symbol)}
|
|
1923
|
+
|
|
1924
|
+
in vec2 uv;
|
|
1925
|
+
out vec4 fragColor;
|
|
1926
|
+
|
|
1927
|
+
void main() {
|
|
1928
|
+
float wave = sin(${u_time_symbol} + uv.x * 10.0);
|
|
1929
|
+
fragColor = vec4(${u_color_symbol} * wave, 1.0);
|
|
1930
|
+
}
|
|
1931
|
+
`
|
|
1932
|
+
|
|
1933
|
+
const result = compile.toQuad(gl, fragment)
|
|
1934
|
+
|
|
1935
|
+
expect(result.schema.uniforms).toEqual({
|
|
1936
|
+
[u_time_symbol]: { kind: 'float' },
|
|
1937
|
+
[u_color_symbol]: { kind: 'vec3' }
|
|
1938
|
+
})
|
|
1939
|
+
})
|
|
1940
|
+
|
|
1941
|
+
it('should handle fragment shader with composed GLSL', () => {
|
|
1942
|
+
const commonUniforms = glsl`
|
|
1943
|
+
${uniform.float('u_time')}
|
|
1944
|
+
${uniform.vec2('u_resolution')}
|
|
1945
|
+
`
|
|
1946
|
+
|
|
1947
|
+
const noiseCode = glsl`
|
|
1948
|
+
float random(vec2 st) {
|
|
1949
|
+
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
|
|
1950
|
+
}
|
|
1951
|
+
`
|
|
1952
|
+
|
|
1953
|
+
const fragment = glsl`
|
|
1954
|
+
precision mediump float;
|
|
1955
|
+
|
|
1956
|
+
${commonUniforms}
|
|
1957
|
+
${noiseCode}
|
|
1958
|
+
|
|
1959
|
+
in vec2 uv;
|
|
1960
|
+
out vec4 fragColor;
|
|
1961
|
+
|
|
1962
|
+
void main() {
|
|
1963
|
+
float noise = random(uv * u_resolution + u_time);
|
|
1964
|
+
fragColor = vec4(vec3(noise), 1.0);
|
|
1965
|
+
}
|
|
1966
|
+
`
|
|
1967
|
+
|
|
1968
|
+
const result = compile.toQuad(gl, fragment)
|
|
1969
|
+
|
|
1970
|
+
expect(result.schema.uniforms).toEqual({
|
|
1971
|
+
u_time: { kind: 'float' },
|
|
1972
|
+
u_resolution: { kind: 'vec2' }
|
|
1973
|
+
})
|
|
1974
|
+
|
|
1975
|
+
expect(result.fragment).toContain('float random(vec2 st)')
|
|
1976
|
+
})
|
|
1977
|
+
|
|
1978
|
+
it('should work with empty fragment shader', () => {
|
|
1979
|
+
const fragment = glsl`
|
|
1980
|
+
precision mediump float;
|
|
1981
|
+
void main() {
|
|
1982
|
+
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
|
1983
|
+
}
|
|
1984
|
+
`
|
|
1985
|
+
|
|
1986
|
+
const result = compile.toQuad(gl, fragment)
|
|
1987
|
+
|
|
1988
|
+
expect(result.schema.uniforms).toEqual({})
|
|
1989
|
+
expect(result.schema.attributes).toEqual({
|
|
1990
|
+
a_quad: { kind: 'vec2', buffer: expect.any(Object) }
|
|
1991
|
+
})
|
|
1992
|
+
expect(result.program).toBe(mockProgram)
|
|
1993
|
+
})
|
|
1994
|
+
|
|
1995
|
+
it('should reuse buffers across multiple calls', () => {
|
|
1996
|
+
const fragment1 = glsl`void main() { gl_FragColor = vec4(1.0); }`
|
|
1997
|
+
const fragment2 = glsl`void main() { gl_FragColor = vec4(0.5); }`
|
|
1998
|
+
|
|
1999
|
+
compile.toQuad(gl, fragment1)
|
|
2000
|
+
compile.toQuad(gl, fragment2)
|
|
2001
|
+
|
|
2002
|
+
// Buffer should only be created once (reused)
|
|
2003
|
+
expect(gl.createBuffer).toHaveBeenCalledTimes(1)
|
|
2004
|
+
})
|
|
2005
|
+
|
|
2006
|
+
it('should expose quad attribute in view for binding', () => {
|
|
2007
|
+
const fragment = glsl`
|
|
2008
|
+
precision mediump float;
|
|
2009
|
+
void main() { gl_FragColor = vec4(1.0); }
|
|
2010
|
+
`
|
|
2011
|
+
|
|
2012
|
+
const result = compile.toQuad(gl, fragment)
|
|
2013
|
+
|
|
2014
|
+
// The view should have the a_quad attribute available
|
|
2015
|
+
expect('a_quad' in result.view.attributes).toBe(true)
|
|
2016
|
+
})
|
|
2017
|
+
|
|
2018
|
+
describe('WebGL version detection', () => {
|
|
2019
|
+
it('should generate WebGL1 vertex shader for fragment without version directive', () => {
|
|
2020
|
+
const fragment = glsl`
|
|
2021
|
+
precision mediump float;
|
|
2022
|
+
${uniform.float('u_time')}
|
|
2023
|
+
|
|
2024
|
+
varying vec2 v_uv;
|
|
2025
|
+
|
|
2026
|
+
void main() {
|
|
2027
|
+
gl_FragColor = vec4(v_uv, u_time, 1.0);
|
|
2028
|
+
}
|
|
2029
|
+
`
|
|
2030
|
+
|
|
2031
|
+
const result = compile.toQuad(gl, fragment)
|
|
2032
|
+
|
|
2033
|
+
// Should generate WebGL1 vertex shader
|
|
2034
|
+
expect(result.vertex).not.toContain('#version 300 es')
|
|
2035
|
+
expect(result.vertex).toContain('attribute vec2 a_quad;')
|
|
2036
|
+
expect(result.vertex).toContain('varying vec2 v_uv;')
|
|
2037
|
+
expect(result.vertex).not.toContain('in vec2 a_quad;')
|
|
2038
|
+
expect(result.vertex).not.toContain('out vec2 v_uv;')
|
|
2039
|
+
})
|
|
2040
|
+
|
|
2041
|
+
it('should generate WebGL2 vertex shader for fragment with #version 300 es', () => {
|
|
2042
|
+
const fragment = glsl`#version 300 es
|
|
2043
|
+
precision mediump float;
|
|
2044
|
+
${uniform.float('u_time')}
|
|
2045
|
+
|
|
2046
|
+
in vec2 v_uv;
|
|
2047
|
+
out vec4 fragColor;
|
|
2048
|
+
|
|
2049
|
+
void main() {
|
|
2050
|
+
fragColor = vec4(v_uv, u_time, 1.0);
|
|
2051
|
+
}
|
|
2052
|
+
`
|
|
2053
|
+
|
|
2054
|
+
const result = compile.toQuad(gl, fragment)
|
|
2055
|
+
|
|
2056
|
+
// Should generate WebGL2 vertex shader
|
|
2057
|
+
expect(result.vertex).toContain('#version 300 es')
|
|
2058
|
+
expect(result.vertex).toContain('in vec2 a_quad;')
|
|
2059
|
+
expect(result.vertex).toContain('out vec2 v_uv;')
|
|
2060
|
+
expect(result.vertex).not.toContain('attribute vec2 a_quad;')
|
|
2061
|
+
expect(result.vertex).not.toContain('varying vec2 v_uv;')
|
|
2062
|
+
})
|
|
2063
|
+
|
|
2064
|
+
it('should respect explicit webgl2 option over fragment version detection', () => {
|
|
2065
|
+
const fragment = glsl`
|
|
2066
|
+
precision mediump float;
|
|
2067
|
+
${uniform.float('u_time')}
|
|
2068
|
+
|
|
2069
|
+
void main() {
|
|
2070
|
+
gl_FragColor = vec4(u_time);
|
|
2071
|
+
}
|
|
2072
|
+
`
|
|
2073
|
+
|
|
2074
|
+
// Force WebGL2 despite no version directive in fragment
|
|
2075
|
+
const result = compile.toQuad(gl, fragment, { webgl2: true })
|
|
2076
|
+
|
|
2077
|
+
// Should generate WebGL2 vertex shader
|
|
2078
|
+
expect(result.vertex).toContain('#version 300 es')
|
|
2079
|
+
expect(result.vertex).toContain('in vec2 a_quad;')
|
|
2080
|
+
expect(result.vertex).toContain('out vec2 v_uv;')
|
|
2081
|
+
})
|
|
2082
|
+
|
|
2083
|
+
it('should respect explicit webgl2: false option over fragment version detection', () => {
|
|
2084
|
+
const fragment = glsl`#version 300 es
|
|
2085
|
+
precision mediump float;
|
|
2086
|
+
${uniform.float('u_time')}
|
|
2087
|
+
|
|
2088
|
+
in vec2 v_uv;
|
|
2089
|
+
out vec4 fragColor;
|
|
2090
|
+
|
|
2091
|
+
void main() {
|
|
2092
|
+
fragColor = vec4(u_time);
|
|
2093
|
+
}
|
|
2094
|
+
`
|
|
2095
|
+
|
|
2096
|
+
// Force WebGL1 despite version directive in fragment
|
|
2097
|
+
const result = compile.toQuad(gl, fragment, { webgl2: false })
|
|
2098
|
+
|
|
2099
|
+
// Should generate WebGL1 vertex shader
|
|
2100
|
+
expect(result.vertex).not.toContain('#version 300 es')
|
|
2101
|
+
expect(result.vertex).toContain('attribute vec2 a_quad;')
|
|
2102
|
+
expect(result.vertex).toContain('varying vec2 v_uv;')
|
|
2103
|
+
})
|
|
2104
|
+
|
|
2105
|
+
it('should handle fragment with mixed content and version detection', () => {
|
|
2106
|
+
const commonUniforms = glsl`
|
|
2107
|
+
${uniform.float('u_time')}
|
|
2108
|
+
${uniform.vec2('u_resolution')}
|
|
2109
|
+
`
|
|
2110
|
+
|
|
2111
|
+
const fragment = glsl`#version 300 es
|
|
2112
|
+
precision mediump float;
|
|
2113
|
+
|
|
2114
|
+
${commonUniforms}
|
|
2115
|
+
|
|
2116
|
+
in vec2 v_uv;
|
|
2117
|
+
out vec4 fragColor;
|
|
2118
|
+
|
|
2119
|
+
void main() {
|
|
2120
|
+
vec2 uv = v_uv * u_resolution;
|
|
2121
|
+
fragColor = vec4(sin(uv.x + u_time), cos(uv.y + u_time), 0.5, 1.0);
|
|
2122
|
+
}
|
|
2123
|
+
`
|
|
2124
|
+
|
|
2125
|
+
const result = compile.toQuad(gl, fragment)
|
|
2126
|
+
|
|
2127
|
+
// Should detect WebGL2 from version directive
|
|
2128
|
+
expect(result.vertex).toContain('#version 300 es')
|
|
2129
|
+
expect(result.vertex).toContain('in vec2 a_quad;')
|
|
2130
|
+
expect(result.vertex).toContain('out vec2 v_uv;')
|
|
2131
|
+
|
|
2132
|
+
// Should preserve fragment uniforms
|
|
2133
|
+
expect(result.schema.uniforms).toEqual({
|
|
2134
|
+
u_time: { kind: 'float' },
|
|
2135
|
+
u_resolution: { kind: 'vec2' }
|
|
2136
|
+
})
|
|
2137
|
+
})
|
|
2138
|
+
|
|
2139
|
+
it('should work with WebGL1 fragment containing complex shader logic', () => {
|
|
2140
|
+
const lightingCode = glsl`
|
|
2141
|
+
vec3 calculateLighting(vec3 normal, vec3 lightDir) {
|
|
2142
|
+
return max(dot(normal, lightDir), 0.0) * vec3(1.0);
|
|
2143
|
+
}
|
|
2144
|
+
`
|
|
2145
|
+
|
|
2146
|
+
const fragment = glsl`
|
|
2147
|
+
precision mediump float;
|
|
2148
|
+
|
|
2149
|
+
${uniform.vec3('u_lightPos')}
|
|
2150
|
+
${uniform.vec3('u_color')}
|
|
2151
|
+
${lightingCode}
|
|
2152
|
+
|
|
2153
|
+
varying vec2 v_uv;
|
|
2154
|
+
|
|
2155
|
+
void main() {
|
|
2156
|
+
vec3 normal = normalize(vec3(v_uv, 1.0));
|
|
2157
|
+
vec3 lightDir = normalize(u_lightPos);
|
|
2158
|
+
vec3 lighting = calculateLighting(normal, lightDir);
|
|
2159
|
+
gl_FragColor = vec4(u_color * lighting, 1.0);
|
|
2160
|
+
}
|
|
2161
|
+
`
|
|
2162
|
+
|
|
2163
|
+
const result = compile.toQuad(gl, fragment)
|
|
2164
|
+
|
|
2165
|
+
// Should generate WebGL1 vertex shader
|
|
2166
|
+
expect(result.vertex).not.toContain('#version 300 es')
|
|
2167
|
+
expect(result.vertex).toContain('attribute vec2 a_quad;')
|
|
2168
|
+
expect(result.vertex).toContain('varying vec2 v_uv;')
|
|
2169
|
+
|
|
2170
|
+
// Should preserve composed GLSL and uniforms
|
|
2171
|
+
expect(result.fragment).toContain('calculateLighting')
|
|
2172
|
+
expect(result.schema.uniforms).toEqual({
|
|
2173
|
+
u_lightPos: { kind: 'vec3' },
|
|
2174
|
+
u_color: { kind: 'vec3' }
|
|
2175
|
+
})
|
|
2176
|
+
})
|
|
2177
|
+
})
|
|
2178
|
+
})
|
|
2179
|
+
|
|
1718
2180
|
describe('compile.toString', () => {
|
|
1719
2181
|
it('should convert glsl tag to shader string', () => {
|
|
1720
2182
|
const shader = glsl`
|