Mirror: A frag-canvas custom element to apply Shadertoy fragment shaders to a canvas or image/video element
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: Fix GLSL 300 ES transformation (#2)

* Fix 300 ES transformation

* Add changeset

authored by

Phil Pluckthun and committed by
GitHub
62729e65 98b43994

+37 -24
+5
.changeset/fair-cooks-jam.md
··· 1 + --- 2 + 'frag-canvas': patch 3 + --- 4 + 5 + Fix GLSL 300 ES (WebGL2) transformation
+32 -24
src/frag-canvas-element.ts
··· 25 25 return [year, month, day, time] as const; 26 26 }; 27 27 28 - const preprocessShader = (source: string, isES300: boolean) => { 28 + const preprocessShader = (source: string) => { 29 29 let header = ''; 30 - let output = source; 31 - 30 + let output = source.trim(); 31 + let isES300 = false; 32 32 if (output.startsWith(VERSION_300)) { 33 + isES300 = true; 33 34 output = output.slice(VERSION_300.length + 1); 34 35 header += `${VERSION_300}\n`; 35 36 } 36 37 37 38 if (!/^\s*precision /.test(output)) header += 'precision highp float;\n'; 38 39 40 + if (!/main\s*\(/.test(output)) { 41 + const ioRe = /\(\s*out\s+vec4\s+(\S+)\s*,\s*in\s+vec2\s+(\S+)\s*\)/g; 42 + const io = ioRe.exec(source); 43 + output = output.replace(/mainImage\s*\(/, 'main(').replace(ioRe, '()'); 44 + if (isES300 && io) { 45 + header += `out vec4 ${io[1]};\n`; 46 + if (io[2] !== 'gl_FragCoord') 47 + header += `#define ${io[2]} gl_FragCoord.xy\n`; 48 + } else if (io) { 49 + if (io[1] !== 'gl_FragColor') header += `#define ${io[1]} gl_FragColor\n`; 50 + if (io[2] !== 'gl_FragCoord') 51 + header += `#define ${io[2]} gl_FragCoord.xy\n`; 52 + } 53 + } 54 + 55 + if (isES300 && output.includes('gl_FragColor')) { 56 + header += 'out vec4 aFragColor;\n'; 57 + header += '#define glFragColor aFragColor.xy\n'; 58 + } 59 + 39 60 if (output.includes('iChannel0')) header += 'uniform sampler2D iChannel0;\n'; 40 61 if (output.includes('iResolution')) header += 'uniform vec2 iResolution;\n'; 41 62 if (output.includes('iChannelResolution')) ··· 46 67 if (output.includes('iChannel')) header += 'uniform float iChannel;\n'; 47 68 if (output.includes('iDate')) header += 'uniform vec4 iDate;\n'; 48 69 49 - if (isES300 && output.includes('gl_FragColor')) 50 - header += 'out vec4 gl_FragColor;\n'; 51 - if (isES300 && output.includes('gl_FragCoord')) 52 - header += 'in vec2 gl_FragCoord;\n'; 53 - 54 - if (!/main\s*\(/.test(output)) { 55 - const ioRe = /\(\s*out\s+vec4\s+(\S+)\s*,\s*in\s+vec2\s+(\S+)\s*\)/g; 56 - const io = ioRe.exec(source); 57 - output = output.replace(/mainImage\s*\(/, 'main(').replace(ioRe, '()'); 58 - if (io && io[1] !== 'gl_FragColor') 59 - header += `#define ${io[1]} gl_FragColor\n`; 60 - if (io && io[2] !== 'gl_FragCoord') 61 - header += `#define ${io[2]} gl_FragCoord.xy\n`; 62 - } 63 - 64 - if (!isES300) output = output.replace(/texture\s+\(/g, 'texture2D('); 70 + if (isES300) output = output.replace(/texture2D\s*\(/g, 'texture('); 65 71 66 - return `${header}\n${output}`; 72 + return { 73 + source: `${header}\n${output}`, 74 + isES300, 75 + }; 67 76 }; 68 77 69 78 interface InitState { ··· 158 167 }, 159 168 160 169 updateFragShader(fragSource: string) { 161 - fragSource = fragSource.trim(); 162 - const isES300 = /\s+#version 300/i.test(fragSource); 163 - gl.shaderSource(fragShader, preprocessShader(fragSource, isES300)); 170 + const preprocessed = preprocessShader(fragSource); 171 + gl.shaderSource(fragShader, preprocessed.source); 164 172 gl.compileShader(fragShader); 165 - const vertShader = isES300 ? vertShader300 : vertShader100; 173 + const vertShader = preprocessed.isES300 ? vertShader300 : vertShader100; 166 174 gl.attachShader(program, vertShader); 167 175 gl.attachShader(program, fragShader); 168 176