function drawQuads(self, params, code, target) {
if (typeof params === 'string') {
[params, code, target] = [{}, params, code];
} else if (code === undefined) {
[params, code, target] = [{}, '', params];
}
const options={}, uniforms={}
for (const p in params) {
(OptNames.has(p)?options:uniforms)[p] = params[p];
}
const emptyShader = !code;
const useOwnTarget = isTargetSpec(target);
if (useOwnTarget) {
target.tag = target.tag || code;
target = prepareOwnTarget(self, target);
}
let targetTexture = target;
if (Array.isArray(target)) {
uniforms.Src = uniforms.Src || target[0];
target.unshift(target.pop());
targetTexture = target[0];
}
if (options.Clear === undefined && emptyShader) {
return target;
}
const gl = self.gl;
const targetSize = bindTarget(gl, targetTexture);
if (options.Clear !== undefined) {
let clear = options.Clear;
if (typeof clear === 'number') {
clear = [clear, clear, clear, clear];
}
gl.clearColor(...clear);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
// setup program
if (emptyShader) {
return target;
}
if (!(code in self.shaders)) {
self.shaders[code] = linkShader(gl, uniforms, code, self.include);
}
const prog = self.shaders[code];
gl.useProgram(prog);
// process options
if (options.Blend) {
const blend = parseBlend(options.Blend);
const {s, d, f}=blend;
gl.enable(gl.BLEND);
gl.blendFunc(s, d);
gl.blendEquation(f);
}
if (options.DepthTest) {
gl.enable(gl.DEPTH_TEST);
}
if (options.AlphaCoverage) {
gl.enable(gl.SAMPLE_ALPHA_TO_COVERAGE);
}
// View, Aspect, Perspective
let view = options.View || [0, 0, targetSize[0], targetSize[1]];
if (view.length == 2) {
view = [0, 0, view[0], view[1]]
}
gl.viewport(...view)
const width=view[2], height=view[3];
uniforms.View = view;
uniforms.Aspect = calcAspect(options.Aspect, width, height);
uniforms.Perspective = options.Perspective || 0.0;
// Grid, Mesh
uniforms.Grid = options.Grid || [1, 1]; // 1d, 3d
uniforms.Mesh = options.Mesh || [1, 1]; // 3d for cube?
const vertN = (uniforms.Mesh[0]*2+4)*uniforms.Mesh[1]-1;
const instN = uniforms.Grid[0]*uniforms.Grid[1];
ensureVertexArray(gl, Math.max(vertN, instN));
gl.bindVertexArray(gl._indexVA);
// setup uniforms and textures
for (const name in uniforms) {
const val = uniforms[name];
if (name in prog.setters) {
prog.setters[name](val);
}
}
for (let i=0; i<prog.samplers.length; ++i) {
const tex = uniforms[prog.samplers[i].name];
gl.activeTexture(gl.TEXTURE0+i);
gl.bindTexture(gl.TEXTURE_2D, tex); //TODO: array
//gl.bindSampler(i, null); //TODO: sampler
}
// draw
gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, vertN, instN);
// revert gl state
if (options.Blend) gl.disable(gl.BLEND);
if (options.DepthTest) gl.disable(gl.DEPTH_TEST);
if (options.AlphaCoverage) gl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE);
gl.bindVertexArray(null);
return target;
}