src/shaders/shaders.localizer.fragment.js

Summary

Maintainability
A
2 hrs
Test Coverage
/**
 * Localizer fragment shader
 */
export default class {
  /**
   *
   */
  constructor(uniforms) {
    this._uniforms = uniforms;
    this._functions = {};
    this._main = '';
  }

  /**
   *
   */
  functions() {
    if (this._main === '') {
      // if main is empty, functions can not have been computed
      this.main();
    }

    let content = '';
    for (let property in this._functions) {
      content += this._functions[property] + '\n';
    }

    return content;
  }

  /**
   *
   */
  uniforms() {
    let content = '';
    for (let property in this._uniforms) {
      let uniform = this._uniforms[property];
      content += `uniform ${uniform.typeGLSL} ${property}`;

      if (uniform && uniform.length) {
        content += `[${uniform.length}]`;
      }

      content += ';\n';
    }

    return content;
  }

  /**
   *
   */
  main() {
    // need to pre-call main to fill up the functions list
    this._main = `
void intersectionProjection(
  in vec4 plane,
  in vec4 slice,
  out vec3 intersectionProjection){

      vec3 intersectionDirection = normalize(cross(plane.xyz, slice.xyz));
      vec3 intersectionPoint = 
        cross(intersectionDirection,slice.xyz) * plane.w +
        cross(plane.xyz, intersectionDirection) * slice.w;

      intersectionProjection =
        intersectionPoint.xyz +
        (dot(vPos.xyz - intersectionPoint, intersectionDirection)
          * intersectionDirection);

}

void main(void) {
      vec4 c1 = vec4(0., 0., 0., 0.);
      vec4 c2 = vec4(0., 0., 0., 0.);
      vec4 c3 = vec4(0., 0., 0., 0.);

      // localizer #1
      // must be normalized!
      if(length(uPlane1.xyz) > 0.5) {
        vec3 projection1 = vec3(1.);
        intersectionProjection(
          uPlane1,
          uSlice,
          projection1
        );

        vec4 projInter1 = (vProjectionViewMatrix * vec4(projection1, 1.));
        vec3 ndc1 = projInter1.xyz / projInter1.w;
        vec2 screenSpace1 = (ndc1.xy * .5 + .5) * vec2(uCanvasWidth, uCanvasHeight);

        float d1 = distance(gl_FragCoord.xy, screenSpace1.xy);
        c1 = vec4(uPlaneColor1, 1. - smoothstep(.5, .7, d1));
      }

      // localizer #2
      if(length(uPlane2.xyz) > 0.5) {
        vec3 projection2 = vec3(1.);
        intersectionProjection(
          uPlane2,
          uSlice,
          projection2
        );

        vec4 projInter2 = (vProjectionViewMatrix * vec4(projection2, 1.));
        vec3 ndc2 = projInter2.xyz / projInter2.w;
        vec2 screenSpace2 = (ndc2.xy * .5 + .5) * vec2(uCanvasWidth, uCanvasHeight);

        float d2 = distance(gl_FragCoord.xy, screenSpace2.xy);
        c2 = vec4(uPlaneColor2, 1. - smoothstep(.5, .7, d2));
      }

      // localizer #3
      if(length(uPlane3.xyz) > 0.5) {
        vec3 projection3 = vec3(1.);
        intersectionProjection(
          uPlane3,
          uSlice,
          projection3
        );

        vec4 projInter3 = (vProjectionViewMatrix * vec4(projection3, 1.));
        vec3 ndc3 = projInter3.xyz / projInter3.w;
        vec2 screenSpace3 = (ndc3.xy * .5 + .5) * vec2(uCanvasWidth, uCanvasHeight);

        float d3 = distance(gl_FragCoord.xy, screenSpace3.xy);
        c3 = vec4(uPlaneColor3, 1. - smoothstep(.5, .7, d3));
      }

      // float uBorderDashLength = 10.0;
      // float uBorderWidth = 2.0;
      // float valueX = mod(gl_FragCoord.x, 2. * uBorderDashLength);
      // float valueY = mod(gl_FragCoord.y, 2. * uBorderDashLength);
      // if( valueX < uBorderDashLength || valueY < uBorderDashLength ){
        vec3 colorMix = c1.xyz*c1.w + c2.xyz*c2.w + c3.xyz*c3.w;
        gl_FragColor = vec4(colorMix, max(max(c1.w, c2.w),c3.w)*0.5);
        return;
      // }
      
      // gl_FragColor = vec4(0., 0., 0., 0.);
      // return;
}
   `;
  }

  /**
   *
   */
  compute() {
    return `
// uniforms
${this.uniforms()}

// varying (should fetch it from vertex directly)
varying vec4 vPos;
varying mat4 vProjectionViewMatrix;

// tailored functions
${this.functions()}

// main loop
${this._main}
      `;
  }
}