anchor.diff:  import 'dart:math' as Math;
   import "dart:async";
   
  +// Sketch shader based on:
  +// http://www.thomaseichhorn.de/npr-sketch-shader-vvvv/
  +// https://github.com/spite/npr-shading
  +
  +
   //
   // Final Shader
   //
   
   final ShaderObject instancedVertexShader = ShaderObject("finalV")
     ..AddAttributeVars([aPosition, aNormal, aTexUV])
  -  ..AddAttributeVars([iaRotation, iaTranslation, iaScale, iaColor])
  -  ..AddVaryingVars([vColor, vNormal, vTexUV])
  +  ..AddAttributeVars([iaRotation, iaTranslation, iaScale])
  +  ..AddVaryingVars([vColor, vNormal, vTexUV, vPosition])
     ..AddUniformVars([uPerspectiveViewMatrix, uModelMatrix, uTime])
     ..SetBody([
       """
  
positive.code: }
  
  void main(void) {
    
    // ${oFragColor} = vec4(${vColor}, 1.0);
    float edge = Edge(${uTexture}, ivec2(gl_FragCoord.xy));
    vec4 color;
    vec4 info = texelFetch(${uTexture}, ivec2(gl_FragCoord.xy), 0);
    if (edge > 0.5) {
      color.rgb = vec3(0.0); // vec3(edge / (100.0 * info.w));
    } else {
      color.rgb = texture(${uTexture2}, ${vTexUV}).rgb;
    }
    color.a = 1.0;
    ${oFragColor} = abs(color);
  }
    """
    ]);
  
  //
  
negative.code:   canvas.height = height;
    perspective.AdjustAspect(width, height);
  
    final RenderProgram progPreparation = RenderProgram(
        "preparation", cgl, preparationVertexShader, preparationFragmentShader);
  
    final RenderProgram progInstanced = RenderProgram(
        "instanced", cgl, instancedVertexShader, instancedFragmentShader);
  
    final MeshData cubes = ShapeCube(progInstanced, computeNormals: true);
    AddInstanceData(cubes, 80);
    print("instances: $cubes.GetNumInstances()}");
  
    final Phase prepare =
        Phase(progPreparation, cubes, MakePrepareFb(cgl, width, height))
          ..mat.SetUniform(uModelMatrix, VM.Matrix4.identity());
  
    final Phase render = Phase(progInstanced, cubes, Framebuffer.Screen(cgl))
      ..mat.SetUniform(uModelMatrix, VM.Matrix4.identity())
      ..mat.SetUniform(uShininess, 10.0)
      ..mat.SetUniform(uTexture, prepare.fb.colorTexture);
  
  /*
    // The lines show aliasing problems but the experiments below
    // did not help:
    final Phase render =
    Phase(progInstanced, cubes, Framebuffer.Default(cgl, width, height))
      ..mat.SetUniform(uModelMatrix, VM.Matrix4.identity())
      ..mat.SetUniform(uShininess, 10.0)
      ..mat.SetUniform(uTexture, prepare.fb.colorTexture);
  
  
    final RenderProgram blurProg =
    RenderProgram("blur", cgl, effectVertexShader, blur1DShader9);
    final MeshData unitQuad = ShapeQuad(blurProg, 1);
  
  
    final Phase horizontalBlur =
    Phase(blurProg, unitQuad, Framebuffer.Effect(cgl, width, height))
      ..mat.SetUniform(uTexture, render.fb.colorTexture)
      ..mat.SetUniform(uDirection, VM.Vector2(1.0, 0.0));
  
    final Phase verticalBlur = Phase(
        blurProg, unitQuad, Framebuffer.Screen(cgl))
      ..mat.SetUniform(uTexture, horizontalBlur.fb.colorTexture)
      ..mat.SetUniform(uDirection, VM.Vector2(0.0, 1.0));
  */
  
    double _lastTimeMs = 0.0;
    void animate(num timeMs) {
  