您当前的位置:首页 > 计算机 > 编程开发 > Kotlin

安卓液态玻璃效果初步实现

时间:07-06来源:作者:点击数:
城东书院 www.cdsy.xyz

安卓液态玻璃效果初步实现

AGSL shader代码如下

uniform float3 iResolution; 
uniform float  iTime; 
uniform float4 iMouse; 
uniform float3 iImageResolution; 
uniform shader iImage1;
uniform float  useCircle; float2 R;
const float PI = 3.14159265;
 
// 创建旋转矩阵
float2x2 Rot(float a) {
    float c = cos(a);
    float s = sin(a);
    return float2x2(c, -s, s, c);
}
 
// 像素归一化处理
float PX(float a) {
    return a / R.y;
}
 
// 矩形距离场
float Box(float2 p, float2 b) {
    float2 d = abs(p) - b;
    return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}
 
// 圆形距离场
float Circle(float2 p, float r) {
    return length(p) - r;
}
 
// 根据 useCircle 选择形状(圆形或圆角矩形)
float Shape(float2 p, float2 b, float r) {
    return useCircle > 0.5 ? Circle(p, r) : Box(p, b);
}
 
// 液体玻璃效果
float4 LiquidGlass(float2 uv, float direction, float quality, float size) {
    float2 radius = size / R;
    float4 color = iImage1.eval(uv * iImageResolution.xy);
 
    float d_step = PI / direction; // 方向步长,direction = 10.0
    float i_step = 1.0 / quality;  // 质量步长,quality = 10.0
    float d = 0.0;
    for (int j = 0; j < 10; j++) { // 固定10次迭代(direction = 10.0)
        float i = i_step;
        for (int k = 0; k < 10; k++) { // 固定10次迭代(quality = 10.0)
            color += iImage1.eval((uv + float2(cos(d), sin(d)) * radius * i) * iImageResolution.xy);
            i += i_step;
        }
        d += d_step;
    }
 
    color /= quality * direction; // 归一化,10.0 * 10.0 = 100.0
    return color;
}
 
// 形状扭曲效果
float4 Distortion(float2 uv) {
    float shape = Shape(uv, float2(PX(50.0)), PX(50.0));
    float shapeShape = smoothstep(PX(1.5), 0.0, shape - PX(50.0)); // 形状平滑过渡
    float shapeDisp = smoothstep(PX(75.0), 0.0, shape - PX(25.0)); // 边框宽度
    float shapeLight = shapeShape * smoothstep(0.0, PX(20.0), shape - PX(40.0)); // 光照强度
    return float4(shapeShape, shapeDisp, shapeLight, 0.0);
}
 
float4 main(float2 I) {
    R = iResolution.xy;
    float2 uv = I / R; // 归一化UV坐标
    float2 st = (I - 0.5 * R) / R.y; // 屏幕空间坐标
    float2 M = iMouse.xy == float2(0.0) ? float2(0.0) : (iMouse.xy - 0.5 * R) / R.y; // 鼠标位置
 
    float4 dist = Distortion(st - M); // 计算扭曲效果
 
    float2 uv2 = uv - iMouse.xy / R; // 为了适配shaders.skia.org的调试
    uv2 *= 0.5 + 0.5 * smoothstep(0.5, 1.0, dist.y); // 缩放UV
    uv2 += iMouse.xy / R;
 
    float3 col = mix(float3(0.0), // 透明黑色背景
                     0.2 + LiquidGlass(uv2, 10.0, 10.0, 5.0).rgb * 0.7, // 应用液体玻璃效果
                     dist.x); // 根据图标形状混合
    col += dist.z * 0.9 + dist.w; // 添加图标光照和图案
 
    // 使用 dist.x 控制透明度:图标区域不透明,其他区域透明
    float alpha = dist.x > 0.0 ? 1.0 : 0.0;
 
    // 应用阴影效果,保持透明度
    col *= 1.0 - 0.2 * smoothstep(PX(80.0), 0.0, Shape(st - M + float2(0.0, PX(40.0)), float2(PX(50.0)), PX(50.0)));
 
    return float4(col, alpha); // 返回最终颜色和透明度
}

在kotlin中新声明一个继承于View的类,然后应用这个Shader即可

init {
        val shaderCode = context.resources.openRawResource(R.raw.lens_shader)
            .bufferedReader().use { it.readText() }
        runtimeShader = RuntimeShader(shaderCode)
    }

效果如下:

城东书院 www.cdsy.xyz
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
上一篇:令人惊喜的 Kotlin 特性 下一篇:很抱歉没有了
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐