Back to shaders
Shader test bench
Circle Wrap Distortion.fs
runnable fragment
Complete GLSL fragment shader. Stronghold runs it directly when the browser can compile it.
Code
uniform sampler2D inputImage;
uniform float inputAngle;
uniform float inputRadius;
uniform vec2 inputCenter;
uniform int mirror;
uniform int correctAspect;
precision mediump float;
/*
{
"CATEGORIES" : [
"Distortion Effect"
],
"DESCRIPTION" : "Wraps the video into a circular shape",
"ISFVSN" : "2",
"INPUTS" : [
{
"NAME" : "inputImage",
"TYPE" : "image"
},
{
"NAME" : "inputAngle",
"TYPE" : "float",
"MAX" : 1,
"DEFAULT" : 0.5,
"MIN" : 0
},
{
"NAME" : "inputRadius",
"TYPE" : "float",
"MAX" : 2,
"DEFAULT" : 1,
"MIN" : 0
},
{
"NAME" : "inputCenter",
"TYPE" : "point2D",
"MAX" : [
1,
1
],
"DEFAULT" : [
0.5,
0.5
],
"MIN" : [
0,
0
]
},
{
"NAME" : "mirror",
"TYPE" : "bool",
"DEFAULT" : false
},
{
"NAME" : "correctAspect",
"TYPE" : "bool",
"DEFAULT" : true
}
],
"CREDIT" : "VIDVOX"
}
*/
const float tau = 6.28318530718;
const float pi = 3.14159265359;
const float halfpi = 1.57079632679;
void main() {
vec4 inputPixelColor;
if (inputRadius > 0.0) {
vec2 loc = (gl_FragCoord.xy / u_resolution.xy).xy;
vec2 center = inputCenter;
// account for aspect ratio so we stay circle
if (correctAspect) {
loc.x = loc.x * u_resolution.x/u_resolution.y;
center.x = center.x * u_resolution.x/u_resolution.y;
}
// translate from polar coords back to cart for this point
// the effect translates (x,y) to (r,theta)
float r = distance(loc,center);
float theta = (inputAngle * tau + pi + atan(loc.x-center.x,loc.y-center.y))/tau;
theta = mod(theta, 1.0);
//loc = vec2((r * 2.0)/inputRadius, theta / pi);
loc = vec2(theta, (r * 2.0)/inputRadius);
if ((loc.x < 0.0)||(loc.x > 1.0)||(loc.y < 0.0)||(loc.y > 1.0))
inputPixelColor = vec4(0.0);
else {
loc.y = 1.0 - loc.y;
if (mirror) {
loc.x = (loc.x < 0.5) ? loc.x * 2.0 : 2.0 - loc.x * 2.0;
}
inputPixelColor = texture2D(inputImage, loc);
}
}
gl_FragColor = inputPixelColor;
}