UNPKG

@chinhui/niivue

Version:

minimal webgl2 nifti image viewer

1,689 lines (1,686 loc) 3.87 MB
function Shader(gl, vertexSrc, fragmentSrc) { var self2 = this; this.program = compileShader(gl, vertexSrc, fragmentSrc); var regexUniform = /uniform[^;]+[ ](\w+);/g; var matchUniformName = /uniform[^;]+[ ](\w+);/; this.uniforms = {}; var vertexUnifs = vertexSrc.match(regexUniform); var fragUnifs = fragmentSrc.match(regexUniform); if (vertexUnifs) { vertexUnifs.forEach(function(unif2) { var m = unif2.match(matchUniformName); self2.uniforms[m[1]] = -1; }); } if (fragUnifs) { fragUnifs.forEach(function(unif2) { var m = unif2.match(matchUniformName); self2.uniforms[m[1]] = -1; }); } for (var unif in this.uniforms) { this.uniforms[unif] = gl.getUniformLocation(this.program, unif); } } Shader.prototype.use = function(gl) { gl.useProgram(this.program); }; var compileShader = function(gl, vert, frag) { var vs = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vs, vert); gl.compileShader(vs); if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) { alert("Vertex shader failed to compile, see console for log"); console.log(gl.getShaderInfoLog(vs)); return null; } var fs = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fs, frag); gl.compileShader(fs); if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) { alert("Fragment shader failed to compile, see console for log"); console.log(gl.getShaderInfoLog(fs)); return null; } var program = gl.createProgram(); gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { alert("Shader failed to link, see console for log"); console.log(gl.getProgramInfoLog(program)); return null; } return program; }; var ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array; if (!Math.hypot) Math.hypot = function() { var y = 0, i2 = arguments.length; while (i2--) { y += arguments[i2] * arguments[i2]; } return Math.sqrt(y); }; function create$3() { var out = new ARRAY_TYPE(9); if (ARRAY_TYPE != Float32Array) { out[1] = 0; out[2] = 0; out[3] = 0; out[5] = 0; out[6] = 0; out[7] = 0; } out[0] = 1; out[4] = 1; out[8] = 1; return out; } function fromValues$3(m00, m01, m02, m10, m11, m12, m20, m21, m22) { var out = new ARRAY_TYPE(9); out[0] = m00; out[1] = m01; out[2] = m02; out[3] = m10; out[4] = m11; out[5] = m12; out[6] = m20; out[7] = m21; out[8] = m22; return out; } function multiply$2(out, a, b) { var a00 = a[0], a01 = a[1], a02 = a[2]; var a10 = a[3], a11 = a[4], a12 = a[5]; var a20 = a[6], a21 = a[7], a22 = a[8]; var b00 = b[0], b01 = b[1], b02 = b[2]; var b10 = b[3], b11 = b[4], b12 = b[5]; var b20 = b[6], b21 = b[7], b22 = b[8]; out[0] = b00 * a00 + b01 * a10 + b02 * a20; out[1] = b00 * a01 + b01 * a11 + b02 * a21; out[2] = b00 * a02 + b01 * a12 + b02 * a22; out[3] = b10 * a00 + b11 * a10 + b12 * a20; out[4] = b10 * a01 + b11 * a11 + b12 * a21; out[5] = b10 * a02 + b11 * a12 + b12 * a22; out[6] = b20 * a00 + b21 * a10 + b22 * a20; out[7] = b20 * a01 + b21 * a11 + b22 * a21; out[8] = b20 * a02 + b21 * a12 + b22 * a22; return out; } function create$2() { var out = new ARRAY_TYPE(16); if (ARRAY_TYPE != Float32Array) { out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; } out[0] = 1; out[5] = 1; out[10] = 1; out[15] = 1; return out; } function clone$1(a) { var out = new ARRAY_TYPE(16); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; } function copy$1(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; } function fromValues$2(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { var out = new ARRAY_TYPE(16); out[0] = m00; out[1] = m01; out[2] = m02; out[3] = m03; out[4] = m10; out[5] = m11; out[6] = m12; out[7] = m13; out[8] = m20; out[9] = m21; out[10] = m22; out[11] = m23; out[12] = m30; out[13] = m31; out[14] = m32; out[15] = m33; return out; } function identity$1(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; } function transpose(out, a) { if (out === a) { var a01 = a[1], a02 = a[2], a03 = a[3]; var a12 = a[6], a13 = a[7]; var a23 = a[11]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a01; out[6] = a[9]; out[7] = a[13]; out[8] = a02; out[9] = a12; out[11] = a[14]; out[12] = a03; out[13] = a13; out[14] = a23; } else { out[0] = a[0]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a[1]; out[5] = a[5]; out[6] = a[9]; out[7] = a[13]; out[8] = a[2]; out[9] = a[6]; out[10] = a[10]; out[11] = a[14]; out[12] = a[3]; out[13] = a[7]; out[14] = a[11]; out[15] = a[15]; } return out; } function invert(out, a) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; var b00 = a00 * a11 - a01 * a10; var b01 = a00 * a12 - a02 * a10; var b02 = a00 * a13 - a03 * a10; var b03 = a01 * a12 - a02 * a11; var b04 = a01 * a13 - a03 * a11; var b05 = a02 * a13 - a03 * a12; var b06 = a20 * a31 - a21 * a30; var b07 = a20 * a32 - a22 * a30; var b08 = a20 * a33 - a23 * a30; var b09 = a21 * a32 - a22 * a31; var b10 = a21 * a33 - a23 * a31; var b11 = a22 * a33 - a23 * a32; var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; return out; } function multiply$1(out, a, b) { var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; var a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7]; var a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11]; var a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; var b0 = b[0], b1 = b[1], b22 = b[2], b3 = b[3]; out[0] = b0 * a00 + b1 * a10 + b22 * a20 + b3 * a30; out[1] = b0 * a01 + b1 * a11 + b22 * a21 + b3 * a31; out[2] = b0 * a02 + b1 * a12 + b22 * a22 + b3 * a32; out[3] = b0 * a03 + b1 * a13 + b22 * a23 + b3 * a33; b0 = b[4]; b1 = b[5]; b22 = b[6]; b3 = b[7]; out[4] = b0 * a00 + b1 * a10 + b22 * a20 + b3 * a30; out[5] = b0 * a01 + b1 * a11 + b22 * a21 + b3 * a31; out[6] = b0 * a02 + b1 * a12 + b22 * a22 + b3 * a32; out[7] = b0 * a03 + b1 * a13 + b22 * a23 + b3 * a33; b0 = b[8]; b1 = b[9]; b22 = b[10]; b3 = b[11]; out[8] = b0 * a00 + b1 * a10 + b22 * a20 + b3 * a30; out[9] = b0 * a01 + b1 * a11 + b22 * a21 + b3 * a31; out[10] = b0 * a02 + b1 * a12 + b22 * a22 + b3 * a32; out[11] = b0 * a03 + b1 * a13 + b22 * a23 + b3 * a33; b0 = b[12]; b1 = b[13]; b22 = b[14]; b3 = b[15]; out[12] = b0 * a00 + b1 * a10 + b22 * a20 + b3 * a30; out[13] = b0 * a01 + b1 * a11 + b22 * a21 + b3 * a31; out[14] = b0 * a02 + b1 * a12 + b22 * a22 + b3 * a32; out[15] = b0 * a03 + b1 * a13 + b22 * a23 + b3 * a33; return out; } function translate(out, a, v) { var x2 = v[0], y = v[1], z = v[2]; var a00, a01, a02, a03; var a10, a11, a12, a13; var a20, a21, a22, a23; if (a === out) { out[12] = a[0] * x2 + a[4] * y + a[8] * z + a[12]; out[13] = a[1] * x2 + a[5] * y + a[9] * z + a[13]; out[14] = a[2] * x2 + a[6] * y + a[10] * z + a[14]; out[15] = a[3] * x2 + a[7] * y + a[11] * z + a[15]; } else { a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; out[12] = a00 * x2 + a10 * y + a20 * z + a[12]; out[13] = a01 * x2 + a11 * y + a21 * z + a[13]; out[14] = a02 * x2 + a12 * y + a22 * z + a[14]; out[15] = a03 * x2 + a13 * y + a23 * z + a[15]; } return out; } function rotateX(out, a, rad) { var s = Math.sin(rad); var c2 = Math.cos(rad); var a10 = a[4]; var a11 = a[5]; var a12 = a[6]; var a13 = a[7]; var a20 = a[8]; var a21 = a[9]; var a22 = a[10]; var a23 = a[11]; if (a !== out) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } out[4] = a10 * c2 + a20 * s; out[5] = a11 * c2 + a21 * s; out[6] = a12 * c2 + a22 * s; out[7] = a13 * c2 + a23 * s; out[8] = a20 * c2 - a10 * s; out[9] = a21 * c2 - a11 * s; out[10] = a22 * c2 - a12 * s; out[11] = a23 * c2 - a13 * s; return out; } function rotateZ(out, a, rad) { var s = Math.sin(rad); var c2 = Math.cos(rad); var a00 = a[0]; var a01 = a[1]; var a02 = a[2]; var a03 = a[3]; var a10 = a[4]; var a11 = a[5]; var a12 = a[6]; var a13 = a[7]; if (a !== out) { out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } out[0] = a00 * c2 + a10 * s; out[1] = a01 * c2 + a11 * s; out[2] = a02 * c2 + a12 * s; out[3] = a03 * c2 + a13 * s; out[4] = a10 * c2 - a00 * s; out[5] = a11 * c2 - a01 * s; out[6] = a12 * c2 - a02 * s; out[7] = a13 * c2 - a03 * s; return out; } function orthoNO(out, left, right, bottom, top, near, far) { var lr = 1 / (left - right); var bt = 1 / (bottom - top); var nf = 1 / (near - far); out[0] = -2 * lr; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = -2 * bt; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 2 * nf; out[11] = 0; out[12] = (left + right) * lr; out[13] = (top + bottom) * bt; out[14] = (far + near) * nf; out[15] = 1; return out; } var ortho = orthoNO; function multiplyScalar(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; out[3] = a[3] * b; out[4] = a[4] * b; out[5] = a[5] * b; out[6] = a[6] * b; out[7] = a[7] * b; out[8] = a[8] * b; out[9] = a[9] * b; out[10] = a[10] * b; out[11] = a[11] * b; out[12] = a[12] * b; out[13] = a[13] * b; out[14] = a[14] * b; out[15] = a[15] * b; return out; } var mul$1 = multiply$1; function create$1() { var out = new ARRAY_TYPE(3); if (ARRAY_TYPE != Float32Array) { out[0] = 0; out[1] = 0; out[2] = 0; } return out; } function clone(a) { var out = new ARRAY_TYPE(3); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; return out; } function length(a) { var x2 = a[0]; var y = a[1]; var z = a[2]; return Math.hypot(x2, y, z); } function fromValues$1(x2, y, z) { var out = new ARRAY_TYPE(3); out[0] = x2; out[1] = y; out[2] = z; return out; } function copy(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; return out; } function add$1(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; return out; } function subtract(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; return out; } function min$Q(out, a, b) { out[0] = Math.min(a[0], b[0]); out[1] = Math.min(a[1], b[1]); out[2] = Math.min(a[2], b[2]); return out; } function max$R(out, a, b) { out[0] = Math.max(a[0], b[0]); out[1] = Math.max(a[1], b[1]); out[2] = Math.max(a[2], b[2]); return out; } function scale(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; return out; } function negate(out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; return out; } function normalize(out, a) { var x2 = a[0]; var y = a[1]; var z = a[2]; var len2 = x2 * x2 + y * y + z * z; if (len2 > 0) { len2 = 1 / Math.sqrt(len2); } out[0] = a[0] * len2; out[1] = a[1] * len2; out[2] = a[2] * len2; return out; } function dot(a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } function cross(out, a, b) { var ax = a[0], ay = a[1], az = a[2]; var bx = b[0], by = b[1], bz = b[2]; out[0] = ay * bz - az * by; out[1] = az * bx - ax * bz; out[2] = ax * by - ay * bx; return out; } function lerp(out, a, b, t) { var ax = a[0]; var ay = a[1]; var az = a[2]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); out[2] = az + t * (b[2] - az); return out; } function angle(a, b) { var ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2], mag1 = Math.sqrt(ax * ax + ay * ay + az * az), mag2 = Math.sqrt(bx * bx + by * by + bz * bz), mag = mag1 * mag2, cosine = mag && dot(a, b) / mag; return Math.acos(Math.min(Math.max(cosine, -1), 1)); } var len = length; (function() { var vec = create$1(); return function(a, stride, offset, count, fn, arg2) { var i2, l; if (!stride) { stride = 3; } if (!offset) { offset = 0; } if (count) { l = Math.min(count * stride + offset, a.length); } else { l = a.length; } for (i2 = offset; i2 < l; i2 += stride) { vec[0] = a[i2]; vec[1] = a[i2 + 1]; vec[2] = a[i2 + 2]; fn(vec, vec, arg2); a[i2] = vec[0]; a[i2 + 1] = vec[1]; a[i2 + 2] = vec[2]; } return a; }; })(); function create() { var out = new ARRAY_TYPE(4); if (ARRAY_TYPE != Float32Array) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; } return out; } function fromValues(x2, y, z, w) { var out = new ARRAY_TYPE(4); out[0] = x2; out[1] = y; out[2] = z; out[3] = w; return out; } function add(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; return out; } function multiply(out, a, b) { out[0] = a[0] * b[0]; out[1] = a[1] * b[1]; out[2] = a[2] * b[2]; out[3] = a[3] * b[3]; return out; } function transformMat4(out, a, m) { var x2 = a[0], y = a[1], z = a[2], w = a[3]; out[0] = m[0] * x2 + m[4] * y + m[8] * z + m[12] * w; out[1] = m[1] * x2 + m[5] * y + m[9] * z + m[13] * w; out[2] = m[2] * x2 + m[6] * y + m[10] * z + m[14] * w; out[3] = m[3] * x2 + m[7] * y + m[11] * z + m[15] * w; return out; } var mul = multiply; (function() { var vec = create(); return function(a, stride, offset, count, fn, arg2) { var i2, l; if (!stride) { stride = 4; } if (!offset) { offset = 0; } if (count) { l = Math.min(count * stride + offset, a.length); } else { l = a.length; } for (i2 = offset; i2 < l; i2 += stride) { vec[0] = a[i2]; vec[1] = a[i2 + 1]; vec[2] = a[i2 + 2]; vec[3] = a[i2 + 3]; fn(vec, vec, arg2); a[i2] = vec[0]; a[i2 + 1] = vec[1]; a[i2 + 2] = vec[2]; a[i2 + 3] = vec[3]; } return a; }; })(); var vertRenderShader = `#version 300 es #line 4 layout(location=0) in vec3 pos; layout(location=1) in vec3 texCoords; uniform mat4 mvpMtx; out vec3 vColor; void main(void) { gl_Position = mvpMtx * vec4(pos, 1.0); //vec4(2.0 * (pos.xyz - 0.5), 1.0); vColor = texCoords; }`; const kRenderFunc = `vec3 GetBackPosition(vec3 startPositionTex) { vec3 startPosition = startPositionTex * volScale; vec3 invR = 1.0 / rayDir; vec3 tbot = invR * (vec3(0.0)-startPosition); vec3 ttop = invR * (volScale-startPosition); vec3 tmax = max(ttop, tbot); vec2 t = min(tmax.xx, tmax.yz); vec3 endPosition = startPosition + (rayDir * min(t.x, t.y)); //convert world position back to texture position: endPosition = endPosition / volScale; return endPosition; } vec4 applyClip (vec3 dir, inout vec4 samplePos, inout float len, inout bool isClip) { float cdot = dot(dir,clipPlane.xyz); isClip = false; if ((clipPlane.a > 1.0) || (cdot == 0.0)) return samplePos; bool frontface = (cdot > 0.0); float clipThick = 2.0; float dis = (-clipPlane.a - dot(clipPlane.xyz, samplePos.xyz-0.5)) / cdot; float disBackFace = (-(clipPlane.a-clipThick) - dot(clipPlane.xyz, samplePos.xyz-0.5)) / cdot; if (((frontface) && (dis >= len)) || ((!frontface) && (dis <= 0.0))) { samplePos.a = len + 1.0; return samplePos; } if (frontface) { dis = max(0.0, dis); samplePos = vec4(samplePos.xyz+dir * dis, dis); if (dis > 0.0) isClip = true; len = min(disBackFace, len); } if (!frontface) { len = min(dis, len); disBackFace = max(0.0, disBackFace); if (len == dis) isClip = true; samplePos = vec4(samplePos.xyz+dir * disBackFace, disBackFace); } return samplePos; }`; var fragRenderShader = `#version 300 es #line 14 precision highp int; precision highp float; uniform vec3 rayDir; uniform vec3 texVox; uniform vec3 volScale; uniform vec4 clipPlane; uniform highp sampler3D volume, overlay; uniform float overlays; uniform float backOpacity; uniform mat4 mvpMtx; uniform mat4 matRAS; uniform vec4 clipPlaneColor; in vec3 vColor; out vec4 fColor; ` + kRenderFunc + ` float frac2ndc(vec3 frac) { //https://stackoverflow.com/questions/7777913/how-to-render-depth-linearly-in-modern-opengl-with-gl-fragcoord-z-in-fragment-sh vec4 pos = vec4(frac.xyz, 1.0); //fraction vec4 dim = vec4(vec3(textureSize(volume, 0)), 1.0); pos = pos * dim; vec4 shim = vec4(-0.5, -0.5, -0.5, 0.0); pos += shim; vec4 mm = transpose(matRAS) * pos; float z_ndc = (mvpMtx * vec4(mm.xyz, 1.0)).z; return (z_ndc + 1.0) / 2.0; } void main() { fColor = vec4(0.0,0.0,0.0,0.0); //fColor = vec4(vColor.rgb, 1.0); return; vec3 start = vColor; gl_FragDepth = 0.0; vec3 backPosition = GetBackPosition(start); // fColor = vec4(backPosition, 1.0); return; vec3 dir = backPosition - start; float len = length(dir); float lenVox = length((texVox * start) - (texVox * backPosition)); if ((lenVox < 0.5) || (len > 3.0)) { //length limit for parallel rays return; } float sliceSize = len / lenVox; //e.g. if ray length is 1.0 and traverses 50 voxels, each voxel is 0.02 in unit cube float stepSize = sliceSize; //quality: larger step is faster traversal, but fewer samples float opacityCorrection = stepSize/sliceSize; dir = normalize(dir); vec4 deltaDir = vec4(dir.xyz * stepSize, stepSize); vec4 samplePos = vec4(start.xyz, 0.0); //ray position float lenNoClip = len; bool isClip = false; vec4 clipPos = applyClip(dir, samplePos, len, isClip); //if ((clipPos.a != samplePos.a) && (len < 3.0)) { //start: OPTIONAL fast pass: rapid traversal until first hit float stepSizeFast = sliceSize * 1.9; vec4 deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast); while (samplePos.a <= len) { float val = texture(volume, samplePos.xyz).a; if (val > 0.01) break; samplePos += deltaDirFast; //advance ray position } if ((samplePos.a >= len) && (overlays < 1.0)) { if (isClip) fColor += clipPlaneColor; return; } fColor = vec4(1.0, 1.0, 1.0, 1.0); //gl_FragDepth = frac2ndc(samplePos.xyz); //crude due to fast pass resolution samplePos -= deltaDirFast; if (samplePos.a < 0.0) vec4 samplePos = vec4(start.xyz, 0.0); //ray position //end: fast pass vec4 colAcc = vec4(0.0,0.0,0.0,0.0); vec4 firstHit = vec4(0.0,0.0,0.0,2.0 * lenNoClip); const float earlyTermination = 0.95; float backNearest = len; //assume no hit float ran = fract(sin(gl_FragCoord.x * 12.9898 + gl_FragCoord.y * 78.233) * 43758.5453); samplePos += deltaDir * ran; //jitter ray while (samplePos.a <= len) { vec4 colorSample = texture(volume, samplePos.xyz); samplePos += deltaDir; //advance ray position if (colorSample.a < 0.01) continue; if (firstHit.a > lenNoClip) firstHit = samplePos; backNearest = min(backNearest, samplePos.a); colorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection); colorSample.rgb *= colorSample.a; colAcc= (1.0 - colAcc.a) * colorSample + colAcc; if ( colAcc.a > earlyTermination ) break; } if (firstHit.a < len) gl_FragDepth = frac2ndc(firstHit.xyz); colAcc.a = (colAcc.a / earlyTermination) * backOpacity; fColor = colAcc; if (isClip) //CR fColor.rgb = mix(fColor.rgb, clipPlaneColor.rgb, clipPlaneColor.a * 0.15); if (overlays < 1.0) return; //overlay pass len = lenNoClip; samplePos = vec4(start.xyz, 0.0); //ray position //start: OPTIONAL fast pass: rapid traversal until first hit stepSizeFast = sliceSize * 1.9; deltaDirFast = vec4(dir.xyz * stepSizeFast, stepSizeFast); while (samplePos.a <= len) { float val = texture(overlay, samplePos.xyz).a; if (val > 0.01) break; samplePos += deltaDirFast; //advance ray position } if (samplePos.a >= len) { if (isClip && (fColor.a == 0.0)) fColor += clipPlaneColor; return; } samplePos -= deltaDirFast; if (samplePos.a < 0.0) vec4 samplePos = vec4(start.xyz, 0.0); //ray position //end: fast pass float overFarthest = len; colAcc = vec4(0.0, 0.0, 0.0, 0.0); samplePos += deltaDir * ran; //jitter ray vec4 overFirstHit = vec4(0.0,0.0,0.0,2.0 * len); while (samplePos.a <= len) { vec4 colorSample = texture(overlay, samplePos.xyz); samplePos += deltaDir; //advance ray position if (colorSample.a < 0.01) continue; if (overFirstHit.a > len) overFirstHit = samplePos; colorSample.a = 1.0-pow((1.0 - colorSample.a), opacityCorrection); colorSample.rgb *= colorSample.a; colAcc= (1.0 - colAcc.a) * colorSample + colAcc; overFarthest = samplePos.a; if ( colAcc.a > earlyTermination ) break; } if (overFirstHit.a < firstHit.a) //if (overFirstHit.a < len) gl_FragDepth = frac2ndc(overFirstHit.xyz); float overMix = colAcc.a; float overlayDepth = 0.3; if (fColor.a <= 0.0) overMix = 1.0; else if (((overFarthest) > backNearest)) { float dx = (overFarthest - backNearest)/1.73; dx = fColor.a * pow(dx, overlayDepth); overMix *= 1.0 - dx; } fColor.rgb = mix(fColor.rgb, colAcc.rgb, overMix); fColor.a = max(fColor.a, colAcc.a); }`; var vertSliceShader = `#version 300 es #line 150 layout(location=0) in vec3 pos; uniform int axCorSag; uniform float slice; uniform vec2 canvasWidthHeight; uniform vec4 leftTopWidthHeight; out vec3 texPos; void main(void) { //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 vec2 frac; frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 frac = (frac * 2.0) - 1.0; gl_Position = vec4(frac, 0.0, 1.0); if (axCorSag == 1) texPos = vec3(pos.x, slice, pos.y); else if (axCorSag == 2) texPos = vec3(slice, pos.x, pos.y); else texPos = vec3(pos.xy, slice); }`; var fragSliceShader = `#version 300 es #line 228 precision highp int; precision highp float; uniform highp sampler3D volume, overlay; uniform float overlays; uniform float opacity; uniform float drawOpacity; uniform highp sampler3D drawing; in vec3 texPos; out vec4 color; void main() { color = vec4(texture(volume, texPos).rgb, opacity); vec4 ocolor = vec4(0.0); if (overlays < 1.0) { ocolor = vec4(0.0, 0.0, 0.0, 0.0); } else { ocolor = texture(overlay, texPos); } float draw = texture(drawing, texPos).r; if (draw > 0.0) { vec3 dcolor = vec3(0.0, 0.0, 0.0); if (draw >= (3.0/255.0)) dcolor.b = 1.0; else if (draw >= (2.0/255.0)) dcolor.g = 1.0; else dcolor.r = 1.0; color.rgb = mix(color.rgb, dcolor, drawOpacity); color.a = max(drawOpacity, color.a); } float aout = ocolor.a + (1.0 - ocolor.a) * color.a; if (aout <= 0.0) return; color.rgb = ((ocolor.rgb * ocolor.a) + (color.rgb * color.a * (1.0 - ocolor.a))) / aout; color.a = aout; }`; var fragLineShader = `#version 300 es #line 189 precision highp int; precision highp float; uniform vec4 lineColor; out vec4 color; void main() { color = lineColor; }`; var vertColorbarShader = `#version 300 es #line 200 layout(location=0) in vec3 pos; uniform vec2 canvasWidthHeight; uniform vec4 leftTopWidthHeight; out vec2 vColor; void main(void) { //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 vec2 frac; frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 frac = (frac * 2.0) - 1.0; gl_Position = vec4(frac, 0.0, 1.0); vColor = pos.xy; }`; var fragColorbarShader = `#version 300 es #line 217 precision highp int; precision highp float; uniform highp sampler2D colormap; in vec2 vColor; out vec4 color; void main() { color = vec4(texture(colormap, vColor).rgb, 1.0); }`; var vertLineShader = `#version 300 es #line 229 layout(location=0) in vec3 pos; uniform vec2 canvasWidthHeight; uniform vec4 leftTopWidthHeight; void main(void) { //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 vec2 frac; frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 frac = (frac * 2.0) - 1.0; gl_Position = vec4(frac, 0.0, 1.0); }`; var vertBmpShader = `#version 300 es #line 229 layout(location=0) in vec3 pos; uniform vec2 canvasWidthHeight; uniform vec4 leftTopWidthHeight; out vec2 vUV; void main(void) { //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 vec2 frac; frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 frac = (frac * 2.0) - 1.0; gl_Position = vec4(frac, 0.0, 1.0); vUV = vec2(pos.x, 1.0 - pos.y); }`; var fragBmpShader = `#version 300 es #line 262 precision highp int; precision highp float; uniform highp sampler2D bmpTexture; in vec2 vUV; out vec4 color; void main() { color = texture(bmpTexture, vUV); }`; var vertFontShader = `#version 300 es #line 244 layout(location=0) in vec3 pos; uniform vec2 canvasWidthHeight; uniform vec4 leftTopWidthHeight; uniform vec4 uvLeftTopWidthHeight; out vec2 vUV; void main(void) { //convert pixel x,y space 1..canvasWidth,1..canvasHeight to WebGL 1..-1,-1..1 vec2 frac; frac.x = (leftTopWidthHeight.x + (pos.x * leftTopWidthHeight.z)) / canvasWidthHeight.x; //0..1 frac.y = 1.0 - ((leftTopWidthHeight.y + ((1.0 - pos.y) * leftTopWidthHeight.w)) / canvasWidthHeight.y); //1..0 frac = (frac * 2.0) - 1.0; gl_Position = vec4(frac, 0.0, 1.0); vUV = vec2(uvLeftTopWidthHeight.x + (pos.x * uvLeftTopWidthHeight.z), uvLeftTopWidthHeight.y + ((1.0 - pos.y) * uvLeftTopWidthHeight.w) ); }`; var fragFontShader = `#version 300 es #line 262 precision highp int; precision highp float; uniform highp sampler2D fontTexture; uniform vec4 fontColor; uniform float screenPxRange; in vec2 vUV; out vec4 color; float median(float r, float g, float b) { return max(min(r, g), min(max(r, g), b)); } void main() { vec3 msd = texture(fontTexture, vUV).rgb; float sd = median(msd.r, msd.g, msd.b); float screenPxDistance = screenPxRange*(sd - 0.5); float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); color = vec4(fontColor.rgb , fontColor.a * opacity); }`; var vertOrientShader = `#version 300 es #line 283 precision highp int; precision highp float; in vec3 vPos; out vec2 TexCoord; void main() { TexCoord = vPos.xy; gl_Position = vec4( (vPos.xy-vec2(0.5,0.5)) * 2.0, 0.0, 1.0); }`; var fragOrientShaderU = `#version 300 es uniform highp usampler3D intensityVol; `; var fragOrientShaderI = `#version 300 es uniform highp isampler3D intensityVol; `; var fragOrientShaderF = `#version 300 es uniform highp sampler3D intensityVol; `; var fragOrientShaderAtlas = `#line 309 precision highp int; precision highp float; in vec2 TexCoord; out vec4 FragColor; uniform float coordZ; uniform float layer; uniform float numLayers; uniform highp sampler2D colormap; uniform lowp sampler3D blend3D; uniform float opacity; uniform vec3 xyzFrac; uniform mat4 mtx; void main(void) { vec4 vx = vec4(TexCoord.x, TexCoord.y, coordZ, 1.0) * mtx; uint idx = texture(intensityVol, vx.xyz).r; FragColor = vec4(0.0, 0.0, 0.0, 0.0); if (idx == uint(0)) return; if (xyzFrac.x > 0.0) { //outline vx = vec4(TexCoord.x+xyzFrac.x, TexCoord.y, coordZ, 1.0) * mtx; uint R = texture(intensityVol, vx.xyz).r; vx = vec4(TexCoord.x-xyzFrac.x, TexCoord.y, coordZ, 1.0) * mtx; uint L = texture(intensityVol, vx.xyz).r; vx = vec4(TexCoord.x, TexCoord.y+xyzFrac.y, coordZ, 1.0) * mtx; uint A = texture(intensityVol, vx.xyz).r; vx = vec4(TexCoord.x, TexCoord.y-xyzFrac.y, coordZ, 1.0) * mtx; uint P = texture(intensityVol, vx.xyz).r; vx = vec4(TexCoord.x, TexCoord.y, coordZ+xyzFrac.z, 1.0) * mtx; uint S = texture(intensityVol, vx.xyz).r; vx = vec4(TexCoord.x, TexCoord.y, coordZ-xyzFrac.z, 1.0) * mtx; uint I = texture(intensityVol, vx.xyz).r; if ((idx == R) && (idx == L) && (idx == A) && (idx == P) && (idx == S) && (idx == I)) return; } idx = ((idx - uint(1)) % uint(100))+uint(1); float fx = (float(idx)+0.5) / 256.0; float y = (2.0 * layer + 1.0)/(2.0 * numLayers); FragColor = texture(colormap, vec2(fx, y)).rgba; FragColor.a *= opacity; if (layer < 2.0) return; vec2 texXY = TexCoord.xy*0.5 +vec2(0.5,0.5); vec4 prevColor = texture(blend3D, vec3(texXY, coordZ)); // https://en.wikipedia.org/wiki/Alpha_compositing float aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a; if (aout <= 0.0) return; FragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout; FragColor.a = aout; }`; var fragOrientShader = `#line 309 precision highp int; precision highp float; in vec2 TexCoord; out vec4 FragColor; uniform float coordZ; uniform float layer; uniform float numLayers; uniform float scl_slope; uniform float scl_inter; uniform float cal_max; uniform float cal_min; uniform highp sampler2D colormap; uniform lowp sampler3D blend3D; uniform float opacity; uniform mat4 mtx; void main(void) { vec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx; float f = (scl_slope * float(texture(intensityVol, vx.xyz).r)) + scl_inter; float r = max(0.00001, abs(cal_max - cal_min)); float mn = min(cal_min, cal_max); f = mix(0.0, 1.0, (f - mn) / r); //float y = 1.0 / numLayers; //y = ((layer + 0.5) * y); //https://stackoverflow.com/questions/5879403/opengl-texture-coordinates-in-pixel-space float y = (2.0 * layer + 1.0)/(2.0 * numLayers); FragColor = texture(colormap, vec2(f, y)).rgba; FragColor.a *= opacity; if (layer < 2.0) return; vec2 texXY = TexCoord.xy*0.5 +vec2(0.5,0.5); vec4 prevColor = texture(blend3D, vec3(texXY, coordZ)); // https://en.wikipedia.org/wiki/Alpha_compositing float aout = FragColor.a + (1.0 - FragColor.a) * prevColor.a; if (aout <= 0.0) return; FragColor.rgb = ((FragColor.rgb * FragColor.a) + (prevColor.rgb * prevColor.a * (1.0 - FragColor.a))) / aout; FragColor.a = aout; }`; var fragRGBOrientShader = `#line 309 precision highp int; precision highp float; in vec2 TexCoord; out vec4 FragColor; uniform float coordZ; uniform float layer; uniform float numLayers; uniform float scl_slope; uniform float scl_inter; uniform float cal_max; uniform float cal_min; uniform highp sampler2D colormap; uniform lowp sampler3D blend3D; uniform float opacity; uniform mat4 mtx; uniform bool hasAlpha; void main(void) { vec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx; uvec4 aColor = texture(intensityVol, vx.xyz); FragColor = vec4(float(aColor.r) / 255.0, float(aColor.g) / 255.0, float(aColor.b) / 255.0, float(aColor.a) / 255.0); if (!hasAlpha) FragColor.a = (FragColor.r * 0.21 + FragColor.g * 0.72 + FragColor.b * 0.07); FragColor.a *= opacity; }`; var fragOrientShaderLookuptable = `#version 300 es uniform highp sampler3D intensityVol; precision highp int; precision highp float; in vec2 TexCoord; out vec4 FragColor; uniform float coordZ; uniform float layer; uniform float numLayers; uniform float scl_slope; uniform float scl_inter; uniform float cal_max; uniform float cal_min; uniform highp sampler2D colormap; uniform lowp sampler3D blend3D; uniform float opacity; uniform mat4 mtx; void main(void) { vec4 vx = vec4(TexCoord.xy, coordZ, 1.0) * mtx; float f = (scl_slope * float(texture(intensityVol, vx.xyz).r)) + scl_inter; // in 64bit fragOrientShaderF // raw value: int(texture(intensityVol, vx.xyz).r) E.g. // if(int(texture(intensityVol, vx.xyz).r) == 11116) { // FragColor.r = 145.0/255.0; // FragColor.g = 58.0/255.0; // FragColor.b = 113.0/255.0; //} // scl_slope=1; scl_inter=0 // f (0.0-1.0) = normalized value of raw value float r = max(0.00001, abs(cal_max - cal_min)); float mn = min(cal_min, cal_max); f = mix(0.0, 1.0, (f - mn) / r); //float y = 1.0 / numLayers; //y = ((layer + 0.5) * y); //https://stackoverflow.com/questions/5879403/opengl-texture-coordinates-in-pixel-space float y = (2.0 * layer + 1.0)/(2.0 * numLayers); FragColor = texture(colormap, vec2(f, y)).rgba; switch( int(texture(intensityVol, vx.xyz).r) ) { case 0: FragColor.r = 0.0/255.0; FragColor.g = 0.0/255.0; FragColor.b = 0.0/255.0; break; case 1: FragColor.r = 70.0/255.0; FragColor.g = 130.0/255.0; FragColor.b = 180.0/255.0; break; case 2: FragColor.r = 245.0/255.0; FragColor.g = 245.0/255.0; FragColor.b = 245.0/255.0; break; case 3: FragColor.r = 205.0/255.0; FragColor.g = 62.0/255.0; FragColor.b = 78.0/255.0; break; case 4: FragColor.r = 120.0/255.0; FragColor.g = 18.0/255.0; FragColor.b = 134.0/255.0; break; case 5: FragColor.r = 196.0/255.0; FragColor.g = 58.0/255.0; FragColor.b = 250.0/255.0; break; case 6: FragColor.r = 0.0/255.0; FragColor.g = 148.0/255.0; FragColor.b = 0.0/255.0; break; case 7: FragColor.r = 220.0/255.0; FragColor.g = 248.0/255.0; FragColor.b = 164.0/255.0; break; case 8: FragColor.r = 230.0/255.0; FragColor.g = 148.0/255.0; FragColor.b = 34.0/255.0; break; case 9: FragColor.r = 0.0/255.0; FragColor.g = 118.0/255.0; FragColor.b = 14.0/255.0; break; case 10: FragColor.r = 0.0/255.0; FragColor.g = 118.0/255.0; FragColor.b = 14.0/255.0; break; case 11: FragColor.r = 122.0/255.0; FragColor.g = 186.0/255.0; FragColor.b = 220.0/255.0; break; case 12: FragColor.r = 236.0/255.0; FragColor.g = 13.0/255.0; FragColor.b = 176.0/255.0; break; case 13: FragColor.r = 12.0/255.0; FragColor.g = 48.0/255.0; FragColor.b = 255.0/255.0; break; case 14: FragColor.r = 204.0/255.0; FragColor.g = 182.0/255.0; FragColor.b = 142.0/255.0; break; case 15: FragColor.r = 42.0/255.0; FragColor.g = 204.0/255.0; FragColor.b = 164.0/255.0; break; case 16: FragColor.r = 119.0/255.0; FragColor.g = 159.0/255.0; FragColor.b = 176.0/255.0; break; case 17: FragColor.r = 220.0/255.0; FragColor.g = 216.0/255.0; FragColor.b = 20.0/255.0; break; case 18: FragColor.r = 103.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 255.0/255.0; break; case 19: FragColor.r = 80.0/255.0; FragColor.g = 196.0/255.0; FragColor.b = 98.0/255.0; break; case 20: FragColor.r = 60.0/255.0; FragColor.g = 58.0/255.0; FragColor.b = 210.0/255.0; break; case 21: FragColor.r = 60.0/255.0; FragColor.g = 58.0/255.0; FragColor.b = 210.0/255.0; break; case 22: FragColor.r = 60.0/255.0; FragColor.g = 58.0/255.0; FragColor.b = 210.0/255.0; break; case 23: FragColor.r = 60.0/255.0; FragColor.g = 58.0/255.0; FragColor.b = 210.0/255.0; break; case 24: FragColor.r = 60.0/255.0; FragColor.g = 60.0/255.0; FragColor.b = 60.0/255.0; break; case 25: FragColor.r = 255.0/255.0; FragColor.g = 165.0/255.0; FragColor.b = 0.0/255.0; break; case 26: FragColor.r = 255.0/255.0; FragColor.g = 165.0/255.0; FragColor.b = 0.0/255.0; break; case 27: FragColor.r = 0.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 127.0/255.0; break; case 28: FragColor.r = 165.0/255.0; FragColor.g = 42.0/255.0; FragColor.b = 42.0/255.0; break; case 29: FragColor.r = 135.0/255.0; FragColor.g = 206.0/255.0; FragColor.b = 235.0/255.0; break; case 30: FragColor.r = 160.0/255.0; FragColor.g = 32.0/255.0; FragColor.b = 240.0/255.0; break; case 31: FragColor.r = 0.0/255.0; FragColor.g = 200.0/255.0; FragColor.b = 200.0/255.0; break; case 32: FragColor.r = 100.0/255.0; FragColor.g = 50.0/255.0; FragColor.b = 100.0/255.0; break; case 33: FragColor.r = 135.0/255.0; FragColor.g = 50.0/255.0; FragColor.b = 74.0/255.0; break; case 34: FragColor.r = 122.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 50.0/255.0; break; case 35: FragColor.r = 51.0/255.0; FragColor.g = 50.0/255.0; FragColor.b = 135.0/255.0; break; case 36: FragColor.r = 74.0/255.0; FragColor.g = 155.0/255.0; FragColor.b = 60.0/255.0; break; case 37: FragColor.r = 120.0/255.0; FragColor.g = 62.0/255.0; FragColor.b = 43.0/255.0; break; case 38: FragColor.r = 74.0/255.0; FragColor.g = 155.0/255.0; FragColor.b = 60.0/255.0; break; case 39: FragColor.r = 122.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 50.0/255.0; break; case 40: FragColor.r = 70.0/255.0; FragColor.g = 130.0/255.0; FragColor.b = 180.0/255.0; break; case 41: FragColor.r = 245.0/255.0; FragColor.g = 245.0/255.0; FragColor.b = 245.0/255.0; break; case 42: FragColor.r = 205.0/255.0; FragColor.g = 62.0/255.0; FragColor.b = 78.0/255.0; break; case 43: FragColor.r = 120.0/255.0; FragColor.g = 18.0/255.0; FragColor.b = 134.0/255.0; break; case 44: FragColor.r = 196.0/255.0; FragColor.g = 58.0/255.0; FragColor.b = 250.0/255.0; break; case 45: FragColor.r = 0.0/255.0; FragColor.g = 148.0/255.0; FragColor.b = 0.0/255.0; break; case 46: FragColor.r = 220.0/255.0; FragColor.g = 248.0/255.0; FragColor.b = 164.0/255.0; break; case 47: FragColor.r = 230.0/255.0; FragColor.g = 148.0/255.0; FragColor.b = 34.0/255.0; break; case 48: FragColor.r = 0.0/255.0; FragColor.g = 118.0/255.0; FragColor.b = 14.0/255.0; break; case 49: FragColor.r = 0.0/255.0; FragColor.g = 118.0/255.0; FragColor.b = 14.0/255.0; break; case 50: FragColor.r = 122.0/255.0; FragColor.g = 186.0/255.0; FragColor.b = 220.0/255.0; break; case 51: FragColor.r = 236.0/255.0; FragColor.g = 13.0/255.0; FragColor.b = 176.0/255.0; break; case 52: FragColor.r = 13.0/255.0; FragColor.g = 48.0/255.0; FragColor.b = 255.0/255.0; break; case 53: FragColor.r = 220.0/255.0; FragColor.g = 216.0/255.0; FragColor.b = 20.0/255.0; break; case 54: FragColor.r = 103.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 255.0/255.0; break; case 55: FragColor.r = 80.0/255.0; FragColor.g = 196.0/255.0; FragColor.b = 98.0/255.0; break; case 56: FragColor.r = 60.0/255.0; FragColor.g = 58.0/255.0; FragColor.b = 210.0/255.0; break; case 57: FragColor.r = 255.0/255.0; FragColor.g = 165.0/255.0; FragColor.b = 0.0/255.0; break; case 58: FragColor.r = 255.0/255.0; FragColor.g = 165.0/255.0; FragColor.b = 0.0/255.0; break; case 59: FragColor.r = 0.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 127.0/255.0; break; case 60: FragColor.r = 165.0/255.0; FragColor.g = 42.0/255.0; FragColor.b = 42.0/255.0; break; case 61: FragColor.r = 135.0/255.0; FragColor.g = 206.0/255.0; FragColor.b = 235.0/255.0; break; case 62: FragColor.r = 160.0/255.0; FragColor.g = 32.0/255.0; FragColor.b = 240.0/255.0; break; case 63: FragColor.r = 0.0/255.0; FragColor.g = 200.0/255.0; FragColor.b = 221.0/255.0; break; case 64: FragColor.r = 100.0/255.0; FragColor.g = 50.0/255.0; FragColor.b = 100.0/255.0; break; case 65: FragColor.r = 135.0/255.0; FragColor.g = 50.0/255.0; FragColor.b = 74.0/255.0; break; case 66: FragColor.r = 122.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 50.0/255.0; break; case 67: FragColor.r = 51.0/255.0; FragColor.g = 50.0/255.0; FragColor.b = 135.0/255.0; break; case 68: FragColor.r = 74.0/255.0; FragColor.g = 155.0/255.0; FragColor.b = 60.0/255.0; break; case 69: FragColor.r = 120.0/255.0; FragColor.g = 62.0/255.0; FragColor.b = 43.0/255.0; break; case 70: FragColor.r = 74.0/255.0; FragColor.g = 155.0/255.0; FragColor.b = 60.0/255.0; break; case 71: FragColor.r = 122.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 50.0/255.0; break; case 72: FragColor.r = 120.0/255.0; FragColor.g = 190.0/255.0; FragColor.b = 150.0/255.0; break; case 73: FragColor.r = 122.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 50.0/255.0; break; case 74: FragColor.r = 122.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 50.0/255.0; break; case 77: FragColor.r = 200.0/255.0; FragColor.g = 70.0/255.0; FragColor.b = 255.0/255.0; break; case 78: FragColor.r = 255.0/255.0; FragColor.g = 148.0/255.0; FragColor.b = 10.0/255.0; break; case 79: FragColor.r = 255.0/255.0; FragColor.g = 148.0/255.0; FragColor.b = 10.0/255.0; break; case 80: FragColor.r = 164.0/255.0; FragColor.g = 108.0/255.0; FragColor.b = 226.0/255.0; break; case 81: FragColor.r = 164.0/255.0; FragColor.g = 108.0/255.0; FragColor.b = 226.0/255.0; break; case 82: FragColor.r = 164.0/255.0; FragColor.g = 108.0/255.0; FragColor.b = 226.0/255.0; break; case 83: FragColor.r = 255.0/255.0; FragColor.g = 218.0/255.0; FragColor.b = 185.0/255.0; break; case 84: FragColor.r = 255.0/255.0; FragColor.g = 218.0/255.0; FragColor.b = 185.0/255.0; break; case 85: FragColor.r = 234.0/255.0; FragColor.g = 169.0/255.0; FragColor.b = 30.0/255.0; break; case 192: FragColor.r = 250.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 50.0/255.0; break; case 86: FragColor.r = 200.0/255.0; FragColor.g = 120.0/255.0; FragColor.b = 255.0/255.0; break; case 87: FragColor.r = 200.0/255.0; FragColor.g = 121.0/255.0; FragColor.b = 255.0/255.0; break; case 88: FragColor.r = 200.0/255.0; FragColor.g = 122.0/255.0; FragColor.b = 255.0/255.0; break; case 96: FragColor.r = 205.0/255.0; FragColor.g = 10.0/255.0; FragColor.b = 125.0/255.0; break; case 97: FragColor.r = 205.0/255.0; FragColor.g = 10.0/255.0; FragColor.b = 125.0/255.0; break; case 98: FragColor.r = 160.0/255.0; FragColor.g = 32.0/255.0; FragColor.b = 240.0/255.0; break; case 100: FragColor.r = 124.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 101: FragColor.r = 125.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 102: FragColor.r = 126.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 103: FragColor.r = 127.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 104: FragColor.r = 124.0/255.0; FragColor.g = 141.0/255.0; FragColor.b = 178.0/255.0; break; case 105: FragColor.r = 124.0/255.0; FragColor.g = 142.0/255.0; FragColor.b = 178.0/255.0; break; case 106: FragColor.r = 124.0/255.0; FragColor.g = 143.0/255.0; FragColor.b = 178.0/255.0; break; case 107: FragColor.r = 124.0/255.0; FragColor.g = 144.0/255.0; FragColor.b = 178.0/255.0; break; case 108: FragColor.r = 124.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 179.0/255.0; break; case 109: FragColor.r = 124.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 110: FragColor.r = 125.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 111: FragColor.r = 126.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 112: FragColor.r = 127.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 178.0/255.0; break; case 113: FragColor.r = 124.0/255.0; FragColor.g = 141.0/255.0; FragColor.b = 178.0/255.0; break; case 114: FragColor.r = 124.0/255.0; FragColor.g = 142.0/255.0; FragColor.b = 178.0/255.0; break; case 115: FragColor.r = 124.0/255.0; FragColor.g = 143.0/255.0; FragColor.b = 178.0/255.0; break; case 116: FragColor.r = 124.0/255.0; FragColor.g = 144.0/255.0; FragColor.b = 178.0/255.0; break; case 117: FragColor.r = 124.0/255.0; FragColor.g = 140.0/255.0; FragColor.b = 179.0/255.0; break; case 118: FragColor.r = 255.0/255.0; FragColor.g = 20.0/255.0; FragColor.b = 147.0/255.0; break; case 119: FragColor.r = 205.0/255.0; FragColor.g = 179.0/255.0; FragColor.b = 139.0/255.0; break; case 120: FragColor.r = 238.0/255.0; FragColor.g = 238.0/255.0; FragColor.b = 209.0/255.0; break; case 121: FragColor.r = 200.0/255.0; FragColor.g = 200.0/255.0; FragColor.b = 200.0/255.0; break; case 122: FragColor.r = 74.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 74.0/255.0; break; case 123: FragColor.r = 238.0/255.0; FragColor.g = 0.0/255.0; FragColor.b = 0.0/255.0; break; case 124: FragColor.r = 0.0/255.0; FragColor.g = 0.0/255.0; FragColor.b = 139.0/255.0; break; case 125: FragColor.r = 173.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 47.0/255.0; break; case 126: FragColor.r = 133.0/255.0; FragColor.g = 203.0/255.0; FragColor.b = 229.0/255.0; break; case 127: FragColor.r = 26.0/255.0; FragColor.g = 237.0/255.0; FragColor.b = 57.0/255.0; break; case 128: FragColor.r = 34.0/255.0; FragColor.g = 139.0/255.0; FragColor.b = 34.0/255.0; break; case 129: FragColor.r = 30.0/255.0; FragColor.g = 144.0/255.0; FragColor.b = 255.0/255.0; break; case 130: FragColor.r = 147.0/255.0; FragColor.g = 19.0/255.0; FragColor.b = 173.0/255.0; break; case 131: FragColor.r = 238.0/255.0; FragColor.g = 59.0/255.0; FragColor.b = 59.0/255.0; break; case 132: FragColor.r = 221.0/255.0; FragColor.g = 39.0/255.0; FragColor.b = 200.0/255.0; break; case 133: FragColor.r = 238.0/255.0; FragColor.g = 174.0/255.0; FragColor.b = 238.0/255.0; break; case 134: FragColor.r = 255.0/255.0; FragColor.g = 0.0/255.0; FragColor.b = 0.0/255.0; break; case 135: FragColor.r = 72.0/255.0; FragColor.g = 61.0/255.0; FragColor.b = 139.0/255.0; break; case 136: FragColor.r = 21.0/255.0; FragColor.g = 39.0/255.0; FragColor.b = 132.0/255.0; break; case 137: FragColor.r = 21.0/255.0; FragColor.g = 39.0/255.0; FragColor.b = 132.0/255.0; break; case 138: FragColor.r = 65.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 20.0/255.0; break; case 139: FragColor.r = 65.0/255.0; FragColor.g = 135.0/255.0; FragColor.b = 20.0/255.0; break; case 140: FragColor.r = 134.0/255.0; FragColor.g = 4.0/255.0; FragColor.b = 160.0/255.0; break; case 142: FragColor.r = 221.0/255.0; FragColor.g = 226.0/255.0; FragColor.b = 68.0/255.0; break; case 143: FragColor.r = 255.0/255.0; FragColor.g = 255.0/255.0; FragColor.b = 254.0/255.0; break; case 144: FragColor.r = 52.0/255.0; FragColor.g = 209.0/255.0; FragColor.b = 226.0/255.0; break; case 145: FragColor.r = 239.0/255.0; FragColor.g = 160.0/255.0; FragColor.b = 223.0/255.0; break; case 146: FragColor.r = 70.0/255.0; FragColor.g = 130.0/255.0; FragColor.b = 180.0/255.0; break; case 147: FragColor.r = 70.0/255.0; FragColor.g = 130.0/255.0; FragColor.b = 181.0/255.0; break; case 148: FragColor.r = 139.0/255.0; FragColor.g = 121.0/255.0; FragColor.b = 94.0/255.0; break; case 149: FragColor.r = 224.0/255.0; FragColor.g = 224.0/255.0; FragColor.b = 224.0/255.0; break; case 150: FragColor.r = 255.0/255.0; FragColor.g = 0.0/255.0; FragColor.b = 0.0/255.0; break; case 151: FragColor.r = 205.0/255.0; FragColor.g = 205.0/255.0; FragColor.b = 0.0/255.0; break; case 152: FragColor.r = 238.0/255.0; FragColor.g = 238.0/255.0; FragColor.b = 209.0/255.0; break; case 153: FragColor.r = 139.0/255.0; FragColor.g = 121.0/255.0; FragColor.b = 94.0/255.0; break; case 154: FragColor.r = 238.0/255.0; FragColor.g = 59.0/255.0; FragColor.b = 59.0/255.0; break; case 155: FragColor.r = 238.0/255.0; FragColor.g = 59.0/255.0; FragColor.b = 59.0/255.0; break; case 156: FragColor.r = 238.0/255.0; FragColor.g = 59.0/255.0; FragColor.b = 59.0/255.0; break; case 157: FragColor.r = 62.0/255.0; FragColor.g = 10.0/255.0; FragColor.b = 205.0/255.0; break; case 158: FragColor.r = 62.0/255.0; FragColor.g = 10.0/255.0; FragColor.b = 205.0/255.0; break; case 159: FragColor.r = 0.0/255.0; FragColor.g = 118.0/255.0; FragColor.b = 14.0/255.0; break; case 160: FragColor.r = 0.0/255.0; FragColor.g = 118.0/255.0; FragColor.b = 14.0/255.0; break; case 161: FragColor.r = 220.0/255.0; FragColor.g = 216.0/255.0; FragColor.b = 21.0/255.0; break; case 162: FragColor.r = 220.0/255.0; FragColor.g = 216.0/255.0; FragColor.b = 21.0/255.0; break; case 163: FragColor.r = 122.0/255.0; FragColor.g = 186.0/255.0; FragColor.b = 220.0/255.0; break; case 164: FragColor.r = 122.0/255.0; FragColor.g = 186.0/255.0; FragColor.b = 220.0/255.0; break; case 165: FragColor.r = 120.0/255.0; FragColor.g = 120.0/255.0; FragColor.b = 120.0/255.0; break; case 166: FragColor.r = 14.0/255.0; FragColor.g = 48.0/255.0; FragColor.b = 255.0/255.0; break; case 167: FragColor.r = 166.0/255.0; FragColor.g = 42.0/255.0; FragColor.b = 42.0/255.0; break; case 168: FragColor.r = 121.0/255.0; FragColor.g = 18.0/255.0; FragColor.b = 134.0/255.0; break; case 169: FragColor.r = 236.0/255.0; FragColor.g = 13.0/255.0; FragColor.b = 127.0/255.0; break; ca