A Processing Grating Shader

We have been using Processing for displaying visual and auditory stimuli in the Lab for a while. Some of you have ask for examples of full-screen gratings using shaders. So this is not about Scanbox proper, but still useful for those of you studying sensory systems.

Below is one demonstration of a drifting sinusoidal grating shader. It shows a full field grating and you can change the orientation on the fly (using the ‘a’ and ‘s’ keys) or the spatial period (using ‘w’ and ‘q’) and see the grating change in real-time.

// Processing 2 Sinusoidal Grating Shader

PShader myshader;

void setup() {
 size(displayWidth, displayHeight, P2D);
 myshader = loadShader("sine.frag");
 myshader.set("resolution", float(displayWidth), float(displayHeight));
 noCursor();
}

float per = 200.0; //period in pixels
float th = 0.0; //orientation in radians
float c = 0.5; //contrast

void draw() {

 if (keyPressed)
 switch(key) {
 case 'a':
 th += PI/360.0; // rotate CW
 break;
 case 's':
 th -= PI/360.0; // rotate CCW
 break;
 case 'w':
 per = per*1.05; // increase period
 break;
 case 'q':
 per = per*0.95; // decrease period
 break;
 }

 myshader.set("th", th);
 myshader.set("sper", per);
 myshader.set("contrast", c);
 myshader.set("time", millis()/1000.0);
 shader(myshader);
 rect(0, 0, displayWidth, displayHeight);
}

boolean sketchFullScreen(){
 return true;
}

The code for shader itself, “sine.frag”, is more definitions than anything else:

#ifdef GL_ES
precision mediump float;
#endif

#define PROCESSING_COLOR_SHADER

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

uniform float mean;
uniform float contrast;
uniform float tper;
uniform float sper;
uniform float th;
uniform float th_speed;

const float PI = 3.1415926535;

void main( void ) {

float sth = sin(th);
float cth = cos(th);

float color = 0.5+contrast*sin(2.0*PI*((gl_FragCoord.x/sper*cth + gl_FragCoord.y/sper*sth)+time));

gl_FragColor = vec4( color, color, color, 1.0 );

}

Yup, that’s all…

Of course, there are many wonderful things you can do with shaders that make gratings somewhat boring… and are many places to share and test them. The one recommend is shader toy.

Processing also has some neat libraries to interface to other hardware that will make your life simpler when programming new experiments.  Here is an example controlling the shader’s parameters (orientation, spatial frequency and contrast) via a leap motion sensor running on my laptop.

We synchronize visual stimulation in Processing with Scanbox using an Arduino board.  Scanbox has two TTL inputs that timestamp either rising/falling/both edges of a TTL signal with the (frame,line) where it occurred.   Processing communicates with the firmware on the Arduino through the Serial library.  More about this later…

Another advantage of using Processing is that you can easily deploy the code on different target architectures.  Here is an example of a few transparent gratings running on both a Mac and my Android tablet.

A bunch of gratings running on my Mac and Android tablet.
A bunch of gratings running on my Mac and Android tablet.