// cv = CachedValue // v = value // ud = uniformData // uv = uniformValue // l = loaction const GLSL_TO_SINGLE_SETTERS_CACHED = { float: ` if(cv !== v) { cv.v = v; gl.uniform1f(location, v) }`, vec2: ` if(cv[0] !== v[0] || cv[1] !== v[1]) { cv[0] = v[0]; cv[1] = v[1]; gl.uniform2f(location, v[0], v[1]) }`, vec3: ` if(cv[0] !== v[0] || cv[1] !== v[1] || cv[2] !== v[2]) { cv[0] = v[0]; cv[1] = v[1]; cv[2] = v[2]; gl.uniform3f(location, v[0], v[1], v[2]) }`, vec4: 'gl.uniform4f(location, v[0], v[1], v[2], v[3])', int: 'gl.uniform1i(location, v)', ivec2: 'gl.uniform2i(location, v[0], v[1])', ivec3: 'gl.uniform3i(location, v[0], v[1], v[2])', ivec4: 'gl.uniform4i(location, v[0], v[1], v[2], v[3])', bool: 'gl.uniform1i(location, v)', bvec2: 'gl.uniform2i(location, v[0], v[1])', bvec3: 'gl.uniform3i(location, v[0], v[1], v[2])', bvec4: 'gl.uniform4i(location, v[0], v[1], v[2], v[3])', mat2: 'gl.uniformMatrix2fv(location, false, v)', mat3: 'gl.uniformMatrix3fv(location, false, v)', mat4: 'gl.uniformMatrix4fv(location, false, v)', sampler2D: 'gl.uniform1i(location, v)', samplerCube: 'gl.uniform1i(location, v)', sampler2DArray: 'gl.uniform1i(location, v)', }; const GLSL_TO_ARRAY_SETTERS = { float: `gl.uniform1fv(location, v)`, vec2: `gl.uniform2fv(location, v)`, vec3: `gl.uniform3fv(location, v)`, vec4: 'gl.uniform4fv(location, v)', mat4: 'gl.uniformMatrix4fv(location, false, v)', mat3: 'gl.uniformMatrix3fv(location, false, v)', mat2: 'gl.uniformMatrix2fv(location, false, v)', int: 'gl.uniform1iv(location, v)', ivec2: 'gl.uniform2iv(location, v)', ivec3: 'gl.uniform3iv(location, v)', ivec4: 'gl.uniform4iv(location, v)', bool: 'gl.uniform1iv(location, v)', bvec2: 'gl.uniform2iv(location, v)', bvec3: 'gl.uniform3iv(location, v)', bvec4: 'gl.uniform4iv(location, v)', sampler2D: 'gl.uniform1iv(location, v)', samplerCube: 'gl.uniform1iv(location, v)', sampler2DArray: 'gl.uniform1iv(location, v)', }; export default function generateUniformsSync(group, uniformData) { let textureCount = 0; let func = `var v = null; var cv = null var gl = renderer.gl`; for (const i in group.uniforms) { const data = uniformData[i]; if (!data) { if (group.uniforms[i].group) { func += ` renderer.shader.syncUniformGroup(uv.${i}); `; } continue; } // TODO && uniformData[i].value !== 0 <-- do we still need this? if (data.type === 'float' && data.size === 1) { func += ` if(uv.${i} !== ud.${i}.value) { ud.${i}.value = uv.${i} gl.uniform1f(ud.${i}.location, uv.${i}) }\n`; } /* eslint-disable max-len */ else if ((data.type === 'sampler2D' || data.type === 'samplerCube' || data.type === 'sampler2DArray') && data.size === 1 && !data.isArray) /* eslint-disable max-len */ { func += ` renderer.texture.bind(uv.${i}, ${textureCount}); if(ud.${i}.value !== ${textureCount}) { ud.${i}.value = ${textureCount}; gl.uniform1i(ud.${i}.location, ${textureCount});\n; // eslint-disable-line max-len }\n`; textureCount++; } else if (data.type === 'mat3' && data.size === 1) { if (group.uniforms[i].a !== undefined) { // TODO and some smart caching dirty ids here! func += ` gl.uniformMatrix3fv(ud.${i}.location, false, uv.${i}.toArray(true)); \n`; } else { func += ` gl.uniformMatrix3fv(ud.${i}.location, false, uv.${i}); \n`; } } else if (data.type === 'vec2' && data.size === 1) { // TODO - do we need both here? // maybe we can get away with only using points? if (group.uniforms[i].x !== undefined) { func += ` cv = ud.${i}.value; v = uv.${i}; if(cv[0] !== v.x || cv[1] !== v.y) { cv[0] = v.x; cv[1] = v.y; gl.uniform2f(ud.${i}.location, v.x, v.y); }\n`; } else { func += ` cv = ud.${i}.value; v = uv.${i}; if(cv[0] !== v[0] || cv[1] !== v[1]) { cv[0] = v[0]; cv[1] = v[1]; gl.uniform2f(ud.${i}.location, v[0], v[1]); } \n`; } } else { const templateType = (data.size === 1) ? GLSL_TO_SINGLE_SETTERS_CACHED : GLSL_TO_ARRAY_SETTERS; const template = templateType[data.type].replace('location', `ud.${i}.location`); func += ` cv = ud.${i}.value; v = uv.${i}; ${template};\n`; } } // console.log(' --------------- ') // console.log(func); return new Function('ud', 'uv', 'renderer', func); // eslint-disable-line no-new-func }