Spying on Functions

2009-8-5-Spy_vs_Spy_9432

I’ve been working through a series of insightful coding tutorials. It’s a series of episodes that walk developers through creating Super Mario in JavaScript from scratch. They were created by Pontus Alexander and I highly recommend them.

So while working through the videos, Pontus demonstrated a really interesting JavaScript pattern in episode 5. Essentially we can spy on a given a function or method — and add custom logic every time it is called.

Let’s look at an example. We start with a simple class:

class Person {
  sayHi(name) {
    console.log(`Yo ${name}!`);
  }
}

A common use case is knowing how many times a function is called. It’s overly simplistic, but it clearly demonstrates what we’re doing. So let’s find out how many times sayHi is called.

Since functions/methods are just values, we can create reference to the original method and overwrite it.

let person = new Person();

// Save a reference to the original function
let sayHiOrig = Person.prototype.sayHi;

// Redefine sayHi. This allows us to add custom logic,
// at the same time leaving sayHi to do whatever it does.
let count = 0;
Person.prototype.sayHi = function(name) {
  console.log(`sayHi called ${++count} times.`);
  sayHiOrig.call(this, name);
};

We then call the function normally. From the perspective of the class, it is unaware of the spy and completely decoupled — which is super great.

person.sayHi('Pascal');
// > sayHi called 1 times.
// > Yo Pascal!
Advertisements

Normal Mapping using PShaders in Processing.js

Try my normal mapping PShader Demo:
normalMap

Last year I made a very simple normal map demo in Processing.js and I posted it on OpenProcessing. It was fun to write, but something that bothered me about it was that the performance was very slow. The reason for this was because it uses a 2D canvas–there’s no hardware acceleration.

Now, I have been working on adding PShader support into Processing.js on my spare time. So here and there i’ll make a few updates. After fixing a bug in my implementation recently, I had enough to port over my normal map demo to use shaders. So, instead of having the lighting calculations in the sketch code, I could have them in GLSL/Shader code. I figured this should increase the performance quite a bit.

Converting the demo from Processing/Java code to GLSL was pretty straightforward–except working out a couple of annoying bugs–I got the demo to resemble what I originally had a year ago, but now the performance is much, much, much better 🙂 I’m no longer limited to a tiny 256×256 canvas and I can use the full client area of the browser. Even with specular lighting, it runs at a solid 60 fps. yay!

If you’re interested in the code, here it is. It’s also posted on github.

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 iResolution;
uniform vec3 iCursor;

uniform sampler2D diffuseMap;
uniform sampler2D normalMap;

void main(){
	vec2 uv = vec2(gl_FragCoord.xy / 512.0);
	uv.y = 1.0 - uv.y;

	vec2 p = vec2(gl_FragCoord);
	float mx = p.x - iCursor.x;
	float my = p.y - (iResolution.y - iCursor.y);
	float mz = 500.0;

	vec3 rayOfLight = normalize(vec3(mx, my, mz));
	vec3 normal = vec3(texture2D(normalMap, uv)) - 0.5;
	normal = normalize(normal);

	float nDotL = max(0.0, dot(rayOfLight, normal));
	vec3 reflection = normal * (2.0 * (nDotL)) - rayOfLight;

	vec3 col = vec3(texture2D(diffuseMap, uv)) * nDotL;

	if(iCursor.z == 1.0){
		float specIntensity = max(0.0, dot(reflection, vec3(.0, .0, 1.)));
		float specRaised = pow(specIntensity, 20.0);
		vec3 specColor = specRaised * vec3(1.0, 0.5, 0.2);
		col += specColor;
	}

	gl_FragColor = vec4(col, 1.0);
}

Wibbles!

wibbles

I wanted to learn the basics of require.js and pixi.js, so I thought it would be fun to create a small game to experiment with these libraries. I decided to make a clone of a game I used to play: Nibbles. It was a QBASIC game that I played on my 80386.

Getting started with require.js was pretty daunting, there’s a bunch of documentation, but I found more of it confusing. Examples online helped some. Experimenting to see what worked and what didn’t helped me the most. On the other hand, pixi.js was very, very similar to Three.js….So much so, that I found myself guessing the API and I was for the most part right. It’s a fun 2D WebGL rending library that has a canvas fallback. It was overkill for what I was working on, but it was still a good learning experience.

Implementing PShader.set()

I was in the process of writing ref tests for my implementation of PShader.set() in Processing.js, when I ran into a nasty problem. PShader.set() can take on a variety of types including single floats and integers to set uniform shader variables. For example, we can have the following:

pShader.set("i", 1);
pShader.set("f", 1.0);

If the second argument is an integer, we must call uniform1i on the WebGL context, otherwise uniform1f needs to be called. But in JavaScript, we can’t distinguish between 1.0 and 1. I briefly considered modifying the the interface for this method, but knew there was a better solution. No, the last thing I wanted was to change the interface. So I just thought about it until I came up with an interesting solution. I figured, why not call both uniform1i and uniform1f right after each other? What would happen? It turns out, it works! It seems one will always fail and the other will succeed, leaving us with the proper uniform set!

Using WebGL readPixels? Turn on preserveDrawingBuffer

Since I’ve already written a few blogs about WebGL’s readPixels and because developers seem to find my page mostly by this keyword, I decided to help clarify a recent issue I found.

In some of my WebGL scripts I have a feature which allows users to convert 3D images to 2D (see here). The script does this simply by making a call to readPixels.

This used to work until browsers (namely WebKit and Chrome) began implementing the preserveDrawingBuffer option. This is an option set when the WebGL context is acquired and as its name suggests it preserves drawing buffers between frames.

What this means is if preserveDrawingBuffer is false/off (which it is by default) it will not save the depth and color buffers after each draw call. Trying to call readPixels in this state will result in an array of zero’ed out data.

If you’re planning on calling readPixels, you’ll need to turn on this option when you get your WebGL context.

var context = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});

The WebGL spec states that this may cause a performance hit on some machines so only enable it if you really need to.

Defenestrating WebGL Shader Concatenation

When I began writing the WebGL shaders for XB PointStream, I placed the vertex and fragment shaders together in their own .js file, separate from the library. In each file I declared the two necessary variables. So, for the cartoon shader it looked something like this:

// Fragment shader ...
var cartoonFrag = 
"#ifdef GL_ES\n" +
"  precision highp float;\n" +
"#endif\n" +

"varying vec4 frontColor;" +
"void main(void){" +
"  gl_FragColor = frontColor;" +
"}";

// Vertex shader ...
var cartoonVert = "..."

If users wanted to render their point clouds with a cartoon effect, they would include the .js resource in their HTML page and tell XB PointStream to create a program object:

// ps is an instance of XB PointStream
progObj = ps.createProgram(cartoonVert, cartoonFrag);

The problem with this approach is the GLSL code is very difficult to read and maintain. Yesterday I finally changed this. Instead of users including the shader resources, I decided users would call a function and pass in the path of the shader file. The function would then XHR the file and return a string with the file’s contents. I started with defining an interface:

var vertSrc = ps.getShaderStr("shaders/cartoon.vs");
var fragSrc = ps.getShaderStr("shaders/cartoon.fs");
cartoonProg = ps.createProgram(vertSrc, fragSrc);

I decided that would be simple enough. I then implemented the getShaderStr function:

this.getShaderStr = function(path){      
  var XHR = new XMLHttpRequest();
  XHR.open("GET", path, false);
  
  if(XHR.overrideMimeType){
    XHR.overrideMimeType("text/plain");
  }
  
  try{
    XHR.send(null);
  }catch(e){
    this.println('Error reading file "' + path + '"');
  }
  
  return XHR.responseText;
};

You’ll notice I made the request synchronous. I did this for a couple of reasons. First, it keeps things simple on the user’s end. They aren’t forced to create callbacks and figure out when they can begin setting shader uniforms. Second, the data sets I’m dealing with (3MB – 40 MB) significantly outweigh a tiny request of 118 bytes. If any performance improvements are to be made in the library, they won’t be made by asynchronously XHR’ing shader code. However, I’m still open to suggestions. Leave a comment if you think this can be done more elegantly.

With those changes:

// cartoon.fs file
#ifdef GL_ES
  precision highp float;
#endif

varying vec4 frontColor;
void main(void){
  gl_FragColor = frontColor;
}

Whew! Much, much cleaner! Notice I have not only removed the obtrusive quotations marks and plus signs, but I’ve also rid the fragment shader of newline characters for the necessary preprocessor definitions. Although this was a relatively small change in terms of the interface, it’s a huge win for the library.

Real-time debugging in Processing

Yesterday I saw one of my colleagues working on a real-time interactive graphical sketch in Processing. I noticed he was using Processing’s println() function to debug. println() is great, but not when the state of sprites are changing per frame.

I think a better solution is to develop a simple class which can handle frequent state changes and overlay those states directly on top of the visualization or game, sort of like a HUD. This is what I usually create when working on a larger Processing or Processing.js game. It only takes a few minutes to write up a simple but extremely useful debugger.

Let’s start with an interface:

cDebugger gDebugger;
boolean gIsDebugOn = true;
int gFontSize = 16;

void setup(){
  size(400, 400);

  // We'll obviously need to allow changing the text color.
  gDebugger = new cDebugger();
  gDebugger.setColor(color(100, 255, 100));
}

void draw(){
  background(0);

  // Update the sprite states.
  // ...

  // In every frame, we'll tell the debugger the current state
  // of some variables we think are important.
  gDebugger.add("FPS: " + frameRate);
  gDebugger.add("mouse: [" + mouseX + "," + mouseY + "]");
  gDebugger.add("last key: " + key);

  // Draw world, sprites, etc.
  // ...

  // Now render the states on top of everything.
  gDebugger.draw();
}

void keyPressed(){

  // We should be able to toggle the debugger so
  // it doesn't consume resources.
  if(key == 'd'){
    gIsDebugOn = !gIsDebugOn;
    gDebugger.setOn(gIsDebugOn);
  }

  // The debugging lines can add up quickly.
  // One way to keep everything on screen is to allow
  // the user to adjust the font size.
  if(key == '+'){
    gFontSize++;
  }

  if(key == '-'){
    gFontSize--;
    if(gFontSize == 0){
      gFontSize = 1;
    }
  }

  gDebugger.setFont("verdana", gFontSize);
}

I named the debugger instance gDebugger. I did this only because using ‘debugger‘ is a JavaScript keyword and will break Proecessing.js sketches. On that note, Processing developers should shy away from all JavaScript keywords to keep their sketches Processing.js compatible. If you’re interested how we’re planning on solving this tricky issue, take a look at our Lighthouse ticket.

Okay, now that we have a basic interface, we can focus on the implementation:

public class cDebugger{
  private ArrayList strings;
  private PFont font;
  private int fontSize;
  private color textColor;
  private boolean isOn;

  public cDebugger(){
    strings = new ArrayList();
    setFont("verdana", 16);
    setColor(color(255));
    isOn = true;
  }

  public void add(String s){
    if(isOn){
      strings.add(s);
    }
  }

  /*
    If off, the debugger will ignore calls to add() and draw().
  */
  public void setOn(boolean on){
    isOn = on;
  }

  public void setFont(String name, int size){
    fontSize = size <= 0 ? 1 : size;
    font = createFont(name, fontSize);
  }

  public void setColor(color c){
    textColor = c;
  }

  public void clear(){
    while(strings.size() > 0){
      strings.remove(0);
    }
  }

  public void draw(){
    if(isOn){
      pushStyle();
      fill(textColor);
      textFont(font);
      int y = fontSize;

      for(int i = 0; i < strings.size(); i++, y += fontSize){
        text((String)strings.get(i), 5, y);
      }
      popStyle();

      // Remove the strings since they have been rendered.
      clear();
    }
  }
}

That’s it!

It’s just a simple bare bones real-time debugger. You can easily extend it to add more useful features such as ‘pages’ users can flip through or sprite categories. I’m sure you can think of many more ideas : )