GLSL with Processing: Deforming objects

Soumya
4 min readAug 7, 2022

Deformation, i.e. changing the shape, of an object can be done in the vertex shader.

Getting started

First, let’s create a Processing file. Here I’m using Processing 4. The code snippet below uses PeasyCam for a mouse-driven camera and draws a shape from a .obj file onto the screen.

.obj files and .glsl files should be in a data folder.

Before PeasyCam can be imported, it needs to be added by going to Sketch > Import Library > Add Library. It can then be imported by going to Sketch > Import Library > PeasyCam.

Deform.pde

import peasy.*;PeasyCam cam;PShape teapot;void setup() {
//set the dimensions of the display window and use the P3D renderer
size(640, 420, P3D);

//load teapot.obj
teapot = loadShape("teapot.obj");
//this particular shape is too small, so scale by a factor of 10
teapot.scale(10);

//create PeasyCam object
cam = new PeasyCam(this, 400);
}
void draw() {
//set background to a dark gray
background(50);
//draw the shape loaded from teapot.obj
shape(teapot);
}

The result is this.

After teapot.obj is loaded and drawn

Adding deformation

The vertex shader is used to displace the vertices of the object. Using different coordinate systems produces different effects. It is the model’s positions that are to be changed, so the calculations should occur in the object’s coordinate system. In this example, the displacement amount is calculated using the sine function and the vertex is displaced in the direction of the normal. This simple example can be adapted to make more complex deformations.

vert.glsl

//define the uniform, attribute and varying variables
uniform mat4 transform;
attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
varying vec4 vertColor;//take a point and return the sine of the y coordinate
float deformSinY(vec3 point) {
return sin(point.y);
}
void main(){
vertColor = color;

/*
calculate the new vertex position by adding the deformation amount to the original position
*/
vec3 deformedPosition = position.xyz + normal * deformSinY(position.xyz);
/*
set gl_Position to the screen space position of the new position
by multiplying it by the transform matrix
*/
gl_Position = transform * vec4(deformedPosition, 1.0);
}

frag.glsl

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
varying vec4 vertColor;void main() {
gl_FragColor = vertColor; //set the fragment color
}

Deform.pde needs to be changed to load and use the shaders.

Deform.pde

//...PShader myShader;void setup() {
//...

myShader = loadShader("frag.glsl", "vert.glsl");
}
void draw() {
background(50);
shader(myShader); shape(teapot);
}

The results is this.

After the shaders have been applied

Adding lighting

The results looks a little dull, so let’s add lighting. After adding lighting, the shaders look like this.

vert.glsl

uniform mat4 modelview;
uniform mat4 transform;
uniform mat4 projection;
uniform mat3 normalMatrix;
uniform vec4 lightPosition;
uniform vec3 lightNormal;
attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
varying vec4 vertColor;
varying vec3 ecNormal;
varying vec3 lightDir;
float deformSinY(vec3 point) {
return sin(point.y);
}
void main(){
//vertex position in eye coordinates
vec3 ecPosition = vec3(modelview * position);
//vertex normal in eye coordinates
ecNormal = normalize(normalMatrix * normal);
//calculate the direction from the vertex to the light
lightDir = normalize(lightPosition.xyz - ecPosition);
vertColor = color;
vec3 deformedPosition = position.xyz + normal * deformSinY(position.xyz);
gl_Position = transform * vec4(deformedPosition, 1.0);
}

frag.glsl

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
varying vec4 vertColor;
varying vec3 ecNormal;
varying vec3 lightDir;
void main() {
vec3 direction = normalize(lightDir);
vec3 normal = normalize(ecNormal);
/*
calculate the dot product of the light direction and the vertex normal. the result is the light intensity
*/
float intensity = max(0.0, dot(direction, normal));
/*
convert the intensity to a vector, then multiply it by the vertex color to get the lit color of the vertex
*/
gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;
}

The final result is this.

Final deformed object with lighting added to the scene

Feel free to reach out to me for a chat or if you have any questions/comments/suggestions :)

--

--

Soumya

Budding software developer passionate about all things mobile