I just got an implementation of this working using OpenGL ES 2.0 on iOS:
While this is on iOS, the fragment shader I used can be brought straight across to Android. The spherical refraction portion is accomplished using the following fragment shader:
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform highp vec2 center;
uniform highp float radius;
uniform highp float aspectRatio;
uniform highp float refractiveIndex;
void main()
{
highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
highp float distanceFromCenter = distance(center, textureCoordinateToUse);
lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius);
distanceFromCenter = distanceFromCenter / radius;
highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter);
highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth));
highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex);
gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere;
}
The center
is a normalized coordinate for the center of the sphere (from a space of 0.0 - 1.0 in both dimensions), the radius
is the normalized radius, the refractiveIndex
is the air / material index of your sphere, and the aspectRatio
is the aspect ratio of the image (for making sure the sphere is round and not elliptical in the normalized coordinate space).
This calculates the surface normals for a sphere with the supplied center and radius, and uses the GLSL refract()
function to refract an incoming vector and provide lookup coordinates in the image texture.
The background is blurred using a separable Gaussian blur that I describe in this answer.
This filter is fast enough to filter live video in real time on an iPhone, so it should be fairly performant on most Android devices. The source code for it can be found within the GPUImageSphereRefractionFilter in my open source GPUImage framework.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…