/*
* Copyright (C) 2012 CyberAgent
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jp.co.cyberagent.android.gpuimage;
import android.graphics.PointF;
import android.opengl.GLES20;
public class GPUImageSphereRefractionFilter extends GPUImageFilter {
public static final String SPHERE_FRAGMENT_SHADER = "" +
"varying highp vec2 textureCoordinate;\n" +
"\n" +
"uniform sampler2D inputImageTexture;\n" +
"\n" +
"uniform highp vec2 center;\n" +
"uniform highp float radius;\n" +
"uniform highp float aspectRatio;\n" +
"uniform highp float refractiveIndex;\n" +
"\n" +
"void main()\n" +
"{\n" +
"highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio));\n" +
"highp float distanceFromCenter = distance(center, textureCoordinateToUse);\n" +
"lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius);\n" +
"\n" +
"distanceFromCenter = distanceFromCenter / radius;\n" +
"\n" +
"highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter);\n" +
"highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth));\n" +
"\n" +
"highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex);\n" +
"\n" +
"gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere; \n" +
"}\n";
private PointF mCenter;
private int mCenterLocation;
private float mRadius;
private int mRadiusLocation;
private float mAspectRatio;
private int mAspectRatioLocation;
private float mRefractiveIndex;
private int mRefractiveIndexLocation;
public GPUImageSphereRefractionFilter() {
this(new PointF(0.5f, 0.5f), 0.25f, 0.71f);
}
public GPUImageSphereRefractionFilter(PointF center, float radius, float refractiveIndex) {
super(NO_FILTER_VERTEX_SHADER, SPHERE_FRAGMENT_SHADER);
mCenter = center;
mRadius = radius;
mRefractiveIndex = refractiveIndex;
}
@Override
public void onInit() {
super.onInit();
mCenterLocation = GLES20.glGetUniformLocation(getProgram(), "center");
mRadiusLocation = GLES20.glGetUniformLocation(getProgram(), "radius");
mAspectRatioLocation = GLES20.glGetUniformLocation(getProgram(), "aspectRatio");
mRefractiveIndexLocation = GLES20.glGetUniformLocation(getProgram(), "refractiveIndex");
}
@Override
public void onInitialized() {
super.onInitialized();
setRadius(mRadius);
setCenter(mCenter);
setRefractiveIndex(mRefractiveIndex);
}
@Override
public void onOutputSizeChanged(int width, int height) {
mAspectRatio = (float) height / width;
setAspectRatio(mAspectRatio);
super.onOutputSizeChanged(width, height);
}
private void setAspectRatio(float aspectRatio) {
mAspectRatio = aspectRatio;
setFloat(mAspectRatioLocation, aspectRatio);
}
/**
* The index of refraction for the sphere, with a default of 0.71
*
* @param refractiveIndex default 0.71
*/
public void setRefractiveIndex(float refractiveIndex) {
mRefractiveIndex = refractiveIndex;
setFloat(mRefractiveIndexLocation, refractiveIndex);
}
/**
* The center about which to apply the distortion, with a default of (0.5, 0.5)
*
* @param center default (0.5, 0.5)
*/
public void setCenter(PointF center) {
mCenter = center;
setPoint(mCenterLocation, center);
}
/**
* The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25
*
* @param radius from 0.0 to 1.0, default 0.25
*/
public void setRadius(float radius) {
mRadius = radius;
setFloat(mRadiusLocation, radius);
}
}