WebGL GLSL Zooming in on a 2D graph

398 Views Asked by At

I'm creating a 2D WebGL example that plots complex functions using graph coloring. I've got it working, and the user can pan the graph around by clicking and dragging the cursor.

I'd also like the user to zoom in and out using the mouse wheel. I've got a basic zoom function working in GLSL (in my main function), but it zooms in at the center of the graph, regardless of the current pan offset.

How can I modify my GLSL main function to always zoom in at the center of the canvas/screen?

My fragment shader looks like this, (func is a specific complex function and does not change the panning or zoom):

#version 100
precision mediump float;

#define PI 3.14159265359
#define SAT_RATIO 0.0625
const vec2 R = vec2(1.0, 0.0);
const vec2 I = vec2(0.0, 1.0);

uniform vec2 uMouse;
uniform vec2 uOffset;
uniform float uZoom;
uniform float uTime;
uniform vec2 uResolution;

...

void main(void) {
  vec2 center = uResolution*0.5;
  vec2 z = gl_FragCoord.xy - center + uOffset;
  float computedZoom = pow(2.0, uZoom);
  float ratio = 0.1*min(uResolution.x, uResolution.y);
  vec2 z1 = (z*computedZoom)/ratio;
  vec2 o = func(z1);
  gl_FragColor = vec4(getColor(o), 1.0);
}

My projection and uniforms in JavaScript are defined as follows, with the mouse position starting at the bottom-left corner:

const projectionMatrix = mat4.create();
mat4.perspective(
  projectionMatrix,
  45 * Math.PI / 180,
  canvas.clientWidth / canvas.clientHeight,
  0.1,
  100
);
const modelViewMatrix = mat4.create();
mat4.translate(
  modelViewMatrix,
  modelViewMatrix,
  [0.0, 0.0, -1.0]
);

...

gl.uniform2f(locations.uMouse, mouse.x, canvas.clientHeight - mouse.y);
gl.uniform2f(locations.uOffset, -offset.x, offset.y);
gl.uniform1f(locations.uZoom, zoom);
gl.uniform1f(locations.uTime, elapsed);
gl.uniform2f(locations.uResolution, canvas.clientWidth, canvas.clientHeight);
gl.uniformMatrix4fv(locations.uProjection, false, projectionMatrix);
gl.uniformMatrix4fv(locations.uModelView, false, modelViewMatrix);

And my vertex shader is pretty simple as it simply renders a flat 2D surface:

#version 100
precision mediump float;

attribute vec4 aPosition;
uniform mat4 uModelView;
uniform mat4 uProjection;
void main(void) {
  gl_Position = uProjection * uModelView * aPosition;
}

The complete code can be found here, and the working demo is here.

0

There are 0 best solutions below