Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save robertleeplummerjr/4996efb7f17e74d1b07e27f60c3e0b5d to your computer and use it in GitHub Desktop.
Save robertleeplummerjr/4996efb7f17e74d1b07e27f60c3e0b5d to your computer and use it in GitHub Desktop.
function kernel(settings) {
const { context, constants } = settings;
const gl = context;
const glVariables0 = gl.getExtension('OES_texture_float');
const glVariables1 = gl.getExtension('OES_texture_float_linear');
const glVariables2 = gl.getExtension('OES_element_index_uint');
const glVariables3 = gl.getExtension('WEBGL_draw_buffers');
const glVariables4 = gl.getExtension('WEBGL_color_buffer_float');
gl.enable(gl.SCISSOR_TEST);
gl.viewport(0, 0, 1, 1);
const glVariable5 = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(glVariable5, `precision lowp float;
precision lowp int;
precision lowp sampler2D;
attribute vec2 aPos;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
uniform vec2 ratio;
void main(void) {
gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);
vTexCoord = aTexCoord;
}`);
gl.compileShader(glVariable5);
const glVariable6 = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(glVariable6, `#extension GL_EXT_draw_buffers : require
precision lowp float;
precision lowp int;
precision lowp sampler2D;
const int LOOP_MAX = 1000;
ivec3 uOutputDim = ivec3(1, 1, 1);
ivec2 uTexSize = ivec2(1, 1);
varying vec2 vTexCoord;
vec4 round(vec4 x) {
return floor(x + 0.5);
}
float round(float x) {
return floor(x + 0.5);
}
const int BIT_COUNT = 32;
int modi(int x, int y) {
return x - y * (x / y);
}
int bitwiseOr(int a, int b) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 || b > 0)) {
break;
}
}
return result;
}
int bitwiseXOR(int a, int b) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 || b > 0)) {
break;
}
}
return result;
}
int bitwiseAnd(int a, int b) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {
result += n;
}
a = a / 2;
b = b / 2;
n = n * 2;
if(!(a > 0 && b > 0)) {
break;
}
}
return result;
}
int bitwiseNot(int a) {
int result = 0;
int n = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (modi(a, 2) == 0) {
result += n;
}
a = a / 2;
n = n * 2;
}
return result;
}
int bitwiseZeroFillLeftShift(int n, int shift) {
int maxBytes = BIT_COUNT;
for (int i = 0; i < BIT_COUNT; i++) {
if (maxBytes >= n) {
break;
}
maxBytes *= 2;
}
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= shift) {
break;
}
n *= 2;
}
int result = 0;
int byteVal = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= maxBytes) break;
if (modi(n, 2) > 0) { result += byteVal; }
n = int(n / 2);
byteVal *= 2;
}
return result;
}
int bitwiseSignedRightShift(int num, int shifts) {
return int(floor(float(num) / pow(2.0, float(shifts))));
}
int bitwiseZeroFillRightShift(int n, int shift) {
int maxBytes = BIT_COUNT;
for (int i = 0; i < BIT_COUNT; i++) {
if (maxBytes >= n) {
break;
}
maxBytes *= 2;
}
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= shift) {
break;
}
n /= 2;
}
int result = 0;
int byteVal = 1;
for (int i = 0; i < BIT_COUNT; i++) {
if (i >= maxBytes) break;
if (modi(n, 2) > 0) { result += byteVal; }
n = int(n / 2);
byteVal *= 2;
}
return result;
}
vec2 integerMod(vec2 x, float y) {
vec2 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}
vec3 integerMod(vec3 x, float y) {
vec3 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}
vec4 integerMod(vec4 x, vec4 y) {
vec4 res = floor(mod(x, y));
return res * step(1.0 - floor(y), -res);
}
float integerMod(float x, float y) {
float res = floor(mod(x, y));
return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);
}
int integerMod(int x, int y) {
return x - (y * int(x / y));
}
float div_with_int_check(float x, float y) {
if (floor(x) == x && floor(y) == y && integerMod(x, y) == 0.0) {
return float(int(x)/int(y));
}
return x / y;
}
// Here be dragons!
// DO NOT OPTIMIZE THIS CODE
// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE
// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME
const vec2 MAGIC_VEC = vec2(1.0, -256.0);
const vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);
const vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536
float decode32(vec4 texel) {
texel *= 255.0;
vec2 gte128;
gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;
gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;
float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);
float res = exp2(round(exponent));
texel.b = texel.b - 128.0 * gte128.x;
res = dot(texel, SCALE_FACTOR) * exp2(round(exponent-23.0)) + res;
res *= gte128.y * -2.0 + 1.0;
return res;
}
float decode16(vec4 texel, int index) {
int channel = integerMod(index, 2);
if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0;
if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0;
return 0.0;
}
float decode8(vec4 texel, int index) {
int channel = integerMod(index, 4);
if (channel == 0) return texel.r * 255.0;
if (channel == 1) return texel.g * 255.0;
if (channel == 2) return texel.b * 255.0;
if (channel == 3) return texel.a * 255.0;
return 0.0;
}
vec4 legacyEncode32(float f) {
float F = abs(f);
float sign = f < 0.0 ? 1.0 : 0.0;
float exponent = floor(log2(F));
float mantissa = (exp2(-exponent) * F);
// exponent += floor(log2(mantissa));
vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;
texel.rg = integerMod(texel.rg, 256.0);
texel.b = integerMod(texel.b, 128.0);
texel.a = exponent*0.5 + 63.5;
texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;
texel = floor(texel);
texel *= 0.003921569; // 1/255
return texel;
}
// https://github.com/gpujs/gpu.js/wiki/Encoder-details
vec4 encode32(float value) {
if (value == 0.0) return vec4(0, 0, 0, 0);
float exponent;
float mantissa;
vec4 result;
float sgn;
sgn = step(0.0, -value);
value = abs(value);
exponent = floor(log2(value));
mantissa = value*pow(2.0, -exponent)-1.0;
exponent = exponent+127.0;
result = vec4(0,0,0,0);
result.a = floor(exponent/2.0);
exponent = exponent - result.a*2.0;
result.a = result.a + 128.0*sgn;
result.b = floor(mantissa * 128.0);
mantissa = mantissa - result.b / 128.0;
result.b = result.b + exponent*128.0;
result.g = floor(mantissa*32768.0);
mantissa = mantissa - result.g/32768.0;
result.r = floor(mantissa*8388608.0);
return result/255.0;
}
// Dragons end here
int index;
ivec3 threadId;
ivec3 indexTo3D(int idx, ivec3 texDim) {
int z = int(idx / (texDim.x * texDim.y));
idx -= z * int(texDim.x * texDim.y);
int y = int(idx / texDim.x);
int x = int(integerMod(idx, texDim.x));
return ivec3(x, y, z);
}
float get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
return decode32(texel);
}
float get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x * 2;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y));
return decode16(texel, index);
}
float get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x * 4;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y));
return decode8(texel, index);
}
float getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int channel = integerMod(index, 4);
index = index / 4;
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
if (channel == 0) return texel.r;
if (channel == 1) return texel.g;
if (channel == 2) return texel.b;
if (channel == 3) return texel.a;
return 0.0;
}
vec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
return texture2D(tex, st / vec2(texSize));
}
float getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return result[0];
}
vec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return vec2(result[0], result[1]);
}
vec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + (texDim.x * (y + (texDim.y * z)));
int channel = integerMod(index, 2);
index = index / 2;
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
if (channel == 0) return vec2(texel.r, texel.g);
if (channel == 1) return vec2(texel.b, texel.a);
return vec2(0.0, 0.0);
}
vec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
vec4 result = getImage2D(tex, texSize, texDim, z, y, x);
return vec3(result[0], result[1], result[2]);
}
vec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));
int vectorIndex = fieldIndex / 4;
int vectorOffset = fieldIndex - vectorIndex * 4;
int readY = vectorIndex / texSize.x;
int readX = vectorIndex - readY * texSize.x;
vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));
if (vectorOffset == 0) {
return tex1.xyz;
} else if (vectorOffset == 1) {
return tex1.yzw;
} else {
readX++;
if (readX >= texSize.x) {
readX = 0;
readY++;
}
vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize));
if (vectorOffset == 2) {
return vec3(tex1.z, tex1.w, tex2.x);
} else {
return vec3(tex1.w, tex2.x, tex2.y);
}
}
}
vec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
return getImage2D(tex, texSize, texDim, z, y, x);
}
vec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {
int index = x + texDim.x * (y + texDim.y * z);
int channel = integerMod(index, 2);
int w = texSize.x;
vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;
vec4 texel = texture2D(tex, st / vec2(texSize));
return vec4(texel.r, texel.g, texel.b, texel.a);
}
vec4 actualColor;
void color(float r, float g, float b, float a) {
actualColor = vec4(r,g,b,a);
}
void color(float r, float g, float b) {
color(r,g,b,1.0);
}
void color(sampler2D image) {
actualColor = texture2D(image, vTexCoord);
}
uniform sampler2D user_value1;
ivec2 user_value1Size = ivec2(1, 1);
ivec3 user_value1Dim = ivec3(1, 1, 1);
uniform sampler2D user_value2;
ivec2 user_value2Size = ivec2(1, 1);
ivec3 user_value2Dim = ivec3(1, 1, 1);
float kernelResult;
float subKernelResult_oneOff = 0.0;
float oneOff(float user_value) {
subKernelResult_oneOff = user_value;return subKernelResult_oneOff;
}
void kernel() {
oneOff((getFloatFromSampler2D(user_value2, user_value2Size, user_value2Dim, 0, 0, 0)-1.0));
kernelResult = (getFloatFromSampler2D(user_value1, user_value1Size, user_value1Dim, 0, 0, 0)+1.0);return;
}
void main(void) {
index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;
threadId = indexTo3D(index, uOutputDim);
kernel();
gl_FragData[0][0] = kernelResult;
gl_FragData[1][0] = subKernelResult_oneOff;
}`);
gl.compileShader(glVariable6);
const glVariable7 = gl.getShaderParameter(glVariable5, gl.COMPILE_STATUS);
const glVariable8 = gl.getShaderParameter(glVariable6, gl.COMPILE_STATUS);
const glVariable9 = gl.createProgram();
gl.attachShader(glVariable9, glVariable5);
gl.attachShader(glVariable9, glVariable6);
gl.linkProgram(glVariable9);
const glVariable10 = gl.createFramebuffer();
const glVariable11 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glVariable11);
gl.bufferData(gl.ARRAY_BUFFER, 64, gl.STATIC_DRAW);
const glVariable12 = new Float32Array([-1,-1,1,-1,-1,1,1,1]);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, glVariable12);
const glVariable13 = new Float32Array([0,0,1,0,0,1,1,1]);
gl.bufferSubData(gl.ARRAY_BUFFER, 32, glVariable13);
const glVariable14 = gl.getAttribLocation(glVariable9, 'aPos');
gl.enableVertexAttribArray(glVariable14);
gl.vertexAttribPointer(glVariable14, 2, gl.FLOAT, false, 0, 0);
const glVariable15 = gl.getAttribLocation(glVariable9, 'aTexCoord');
gl.enableVertexAttribArray(glVariable15);
gl.vertexAttribPointer(glVariable15, 2, gl.FLOAT, false, 0, 32);
gl.bindFramebuffer(gl.FRAMEBUFFER, glVariable10);
gl.useProgram(glVariable9);
const glVariable16 = gl.createTexture();
gl.activeTexture(33986);
gl.bindTexture(gl.TEXTURE_2D, glVariable16);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glVariable16, 0);
const glVariable17 = gl.createTexture();
gl.activeTexture(33986);
gl.bindTexture(gl.TEXTURE_2D, glVariable17);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, 36065, gl.TEXTURE_2D, glVariable17, 0);
/** start of injected functions **/
function flattenTo(array, target) {
if (/*utils.*/isArray(array[0])) {
if (/*utils.*/isArray(array[0][0])) {
if (/*utils.*/isArray(array[0][0][0])) {
/*utils.*/flatten4dArrayTo(array, target);
} else {
/*utils.*/flatten3dArrayTo(array, target);
}
} else {
/*utils.*/flatten2dArrayTo(array, target);
}
} else {
target.set(array);
}
}
function flatten2dArrayTo(array, target) {
let offset = 0;
for (let y = 0; y < array.length; y++) {
target.set(array[y], offset);
offset += array[y].length;
}
}
function flatten3dArrayTo(array, target) {
let offset = 0;
for (let z = 0; z < array.length; z++) {
for (let y = 0; y < array[z].length; y++) {
target.set(array[z][y], offset);
offset += array[z][y].length;
}
}
}
function flatten4dArrayTo(array, target) {
let offset = 0;
for (let l = 0; l < array.length; l++) {
for (let z = 0; z < array[l].length; z++) {
for (let y = 0; y < array[l][z].length; y++) {
target.set(array[l][z][y], offset);
offset += array[l][z][y].length;
}
}
}
}
function isArray(array) {
return !isNaN(array.length);
}
/** end of injected functions **/
const innerKernel = function (value1, value2) {
/** start setup uploads for kernel values **/
const uploadValue_value1 = value1.texture;
const uploadValue_value2 = value2.texture;
/** end setup uploads for kernel values **/
gl.useProgram(glVariable9);
gl.scissor(0, 0, 1, 1);
const glVariable18 = gl.getUniformLocation(glVariable9, 'ratio');
gl.uniform2f(glVariable18, 1, 1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, uploadValue_value1);
const glVariable19 = gl.getUniformLocation(glVariable9, 'user_value1');
gl.uniform1i(glVariable19, 0);
gl.activeTexture(33985);
gl.bindTexture(gl.TEXTURE_2D, uploadValue_value2);
const glVariable20 = gl.getUniformLocation(glVariable9, 'user_value2');
gl.uniform1i(glVariable20, 1);
gl.bindFramebuffer(gl.FRAMEBUFFER, glVariable10);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glVariable16, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, 36065, gl.TEXTURE_2D, glVariable17, 0);
glVariables3.drawBuffersWEBGL([gl.COLOR_ATTACHMENT0, 36065]);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
gl.getError();
return {
result: {
texture: glVariable16,
type: 'ArrayTexture(1)',
toArray: () => {
const erectFloat = (array, width) => {
const xResults = new Float32Array(width);
let i = 0;
for (let x = 0;(x<width);x++) {
xResults[x]=array[i];
i+=4;
};
return xResults;
};
function renderRawOutput() {
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glVariable16, 0);
const result = new Float32Array((({"0":1,"1":1}[0]*{"0":1,"1":1}[1])*4));
gl.readPixels(0, 0, {"0":1,"1":1}[0], {"0":1,"1":1}[1], gl.RGBA, gl.FLOAT, result);
return result;
}
function renderValues() {
if (false) return null;
return renderRawOutput();
}
function toArray() {
return erectFloat(renderValues(), [1][0]);
}
return toArray();
}
},
oneOffValue: {
texture: glVariable17,
type: 'ArrayTexture(1)',
toArray: () => {
const erectFloat = (array, width) => {
const xResults = new Float32Array(width);
let i = 0;
for (let x = 0;(x<width);x++) {
xResults[x]=array[i];
i+=4;
};
return xResults;
};
function renderRawOutput() {
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glVariable17, 0);
const result = new Float32Array((({"0":1,"1":1}[0]*{"0":1,"1":1}[1])*4));
gl.readPixels(0, 0, {"0":1,"1":1}[0], {"0":1,"1":1}[1], gl.RGBA, gl.FLOAT, result);
return result;
}
function renderValues() {
if (false) return null;
return renderRawOutput();
}
function toArray() {
return erectFloat(renderValues(), [1][0]);
}
return toArray();
}
},
};
};
return innerKernel;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment