Skip to content

Instantly share code, notes, and snippets.

@companje
Last active February 20, 2024 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save companje/4d1de1624bfba9f98f613eb614885b74 to your computer and use it in GitHub Desktop.
Save companje/4d1de1624bfba9f98f613eb614885b74 to your computer and use it in GitHub Desktop.
Zoom shader for sphere
PShader shader;
PImage tex;
PShape sphere;
PVector lensCenter = new PVector(0,0,1);
float zoom = 2;
void setup() {
size(1169, 1169, P3D);
tex = loadImage("1539.jpg");
sphere = createShape(SPHERE, height/2);
sphere.rotateY(HALF_PI);
sphere.setTexture(tex);
sphere.setStroke(false);
}
void draw() {
ortho();
background(0);
translate(width/2, height/2);
try {
shader = loadShader("lens.glsl");
shader.set("lensCenter", lensCenter.x,lensCenter.y,lensCenter.z);
shader.set("zoom", zoom);
shader(shader);
shape(sphere);
resetShader();
}
catch (Exception e) {
println(e);
}
}
void mouseWheel(MouseEvent event) {
zoom += event.getCount() *.01;
zoom = constrain(zoom, 1, 4);
}
void mouseMoved() {
lensCenter = toSphere(.5-float(mouseX)/width, -.5+float(mouseY)/height);
}
PVector toSphere(float x, float y) { //-0.5 ... +0.5
PVector v = new PVector(x, y);
if (v.mag()<=1.0f) v.z = sqrt(1.0 - (v.x*v.x) - (v.y*v.y)); //USING (v.x*v.x) - (v.y*v.y) instead of v.mag() !!!
v.normalize();
return v;
}
uniform sampler2D texture;
uniform vec3 lensCenter;
uniform float zoom;
varying vec4 vertTexCoord;
float PI = 3.1415;
vec3 toSpherical(vec2 uv) {
float theta = uv.x * 2.0 * PI - PI/2;
float phi = (1.0 - uv.y) * PI;
return vec3(sin(phi) * cos(theta), cos(phi), sin(phi) * sin(theta));
}
vec2 fromSpherical(vec3 p) {
float theta = atan(p.z, p.x) + PI / 2.0;
float phi = acos(p.y);
return vec2(theta / (2.0 * PI), 1.0 - phi / PI);
}
vec3 mixedLens(vec3 lensCenter, vec3 dir, float dist, float lensRadius, float zoom) {
float mixStart = lensRadius-.05;
float w = smoothstep(mixStart, lensRadius, dist);
vec3 linearPart = dir * dist / zoom;
vec3 quadraticPart = dir * pow(dist / lensRadius, zoom) * lensRadius;
vec3 sphereCoords = lensCenter + mix(linearPart, quadraticPart, w);
return sphereCoords;
}
void main() {
vec3 sphereCoords = toSpherical(vertTexCoord.st);
float lensRadius = 0.35;
vec3 dir = sphereCoords - lensCenter;
float dist = length(dir);
if (abs(dist-lensRadius)<.005) {
gl_FragColor = vec4(0.,0.,0.,1.); //yellow border
} else if (dist < lensRadius) {
dir = normalize(dir);
sphereCoords = mixedLens(lensCenter, dir, dist, lensRadius, zoom);
vec2 uv = fromSpherical(sphereCoords);
gl_FragColor = texture2D(texture, uv);
}
else {
gl_FragColor = texture2D(texture, vertTexCoord.st); // * vec4(.6,.6,.6,1);
}
}
@companje
Copy link
Author

Lens-Effect.480.mov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment