Android GLES 球形折射

效果图

screenshot.png

思路

利用内置的refract函数,因为要画的是球形,所以有球心和半径,利用distance函数计算距离,如果和球心的距离小于半径就利用refract函数实现折射,如果不是就显示原图。

Shader

顶点shader

attribute vec4 position;
attribute vec4 textureCoord;
varying vec4 textureCoordinate;

uniform mat4 cameraTransform;

void main() {
    textureCoordinate =  cameraTransform * textureCoord;
    gl_Position = position;
}

其中cameraTransform是使用Android Camera的时候系统会返回给我们的矩阵。

片段shader

#extension GL_OES_EGL_image_external : require
varying highp vec4 textureCoordinate;
uniform samplerExternalOES inputImageTexture;
uniform highp float u_radius;
uniform highp float u_refractiveIndex;
uniform highp float u_aspectRatio;
uniform highp vec2 u_center;
void main(){
    highp vec2 textureCoordinateToUse = textureCoordinate.xy;
    textureCoordinateToUse.y = textureCoordinateToUse.y * 2.0 - 1.0;
    textureCoordinateToUse.y = textureCoordinateToUse.y * u_aspectRatio;
    textureCoordinateToUse.y = (textureCoordinateToUse.y + 1.0 ) * 0.5;
    highp float distanceFromCenter = distance(u_center, textureCoordinateToUse);
    highp float distance1 = distanceFromCenter / u_radius;
    highp float normalizedDepth = u_radius * sqrt(1.0 - distance1 * distance1);
    highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - u_center, normalizedDepth));
    highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, u_refractiveIndex);
    if( distanceFromCenter > u_radius ) gl_FragColor = texture2D(inputImageTexture, textureCoordinate.xy);
    else { 
    highp vec2 texCoord = vec2(-refractedVector.x, -refractedVector.y);
    texCoord = (texCoord + 1.0) * 0.5;
    gl_FragColor = texture2D(inputImageTexture, texCoord); 
}
  • u_aspectRatio :显示view宽高比 width/height
    textureCoordinateToUse.y = textureCoordinateToUse.y * u_aspectRatio;
    如果没有这一行代码,就会变成椭圆形

  • u_refractiveIndex:折射率 0.7

Github项目代码下载

https://github.com/larry-kof/BallShaderDemo

你可能感兴趣的:(Android GLES 球形折射)