android shadertoy效果 转换成 Android动态壁纸的写法

kotlin 复制代码
package com.example.wallpaper3d.shader

import android.content.Context
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.service.wallpaper.WallpaperService
import android.util.Log
import android.view.SurfaceHolder
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class ShaderWallpaperService : WallpaperService() {
    override fun onCreateEngine(): Engine {
        return ShaderEngine()
    }
    
    inner class ShaderEngine : Engine() {
        private lateinit var glSurfaceView: GLSurfaceView
        private lateinit var renderer: ShaderRenderer

        override fun onCreate(surfaceHolder: SurfaceHolder) {
            super.onCreate(surfaceHolder)
            glSurfaceView = MyGLSurfaceView(this@ShaderWallpaperService)
            renderer = ShaderRenderer(this@ShaderWallpaperService)
            glSurfaceView.setRenderer(renderer)
            glSurfaceView.renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
        }

        override fun onVisibilityChanged(visible: Boolean) {
            super.onVisibilityChanged(visible)
            if (visible) {
                glSurfaceView.onResume()
            } else {
                glSurfaceView.onPause()
            }
        }

        inner class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {
            init {
                setEGLContextClientVersion(2)
                holder.setFormat(android.graphics.PixelFormat.TRANSLUCENT)
                setZOrderOnTop(false)
            }

            override fun getHolder(): SurfaceHolder {
                return surfaceHolder // 使用壁纸引擎的 SurfaceHolder
            }
        }
    }
}

class ShaderRenderer(val context: Context) : GLSurfaceView.Renderer {
    // 顶点坐标(全屏四边形)
    private val vertexCoords = floatArrayOf(
        -1.0f, -1.0f, 0.0f,  // 左下
        1.0f, -1.0f, 0.0f,   // 右下
        -1.0f, 1.0f, 0.0f,   // 左上
        1.0f, 1.0f, 0.0f     // 右上
    )
    private val vertexBuffer: FloatBuffer

    // Shader 程序 ID
    private var programId: Int = 0
    // 时间和分辨率的 uniform 位置
    private var timeLoc: Int = 0
    private var resolutionLoc: Int = 0
    private var startTime: Long = 0

    init {
        // 初始化顶点缓冲
        vertexBuffer = ByteBuffer.allocateDirect(vertexCoords.size * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
            .put(vertexCoords)
        vertexBuffer.position(0)
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        // 编译并链接 shaders
        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)

        val  fragmentShaderCode = ShaderLoader.loadFromAssets(context,"shaders/shader_3.glsl")
        val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)
        programId = GLES20.glCreateProgram().apply {
            GLES20.glAttachShader(this, vertexShader)
            GLES20.glAttachShader(this, fragmentShader)
            GLES20.glLinkProgram(this)
        }
        GLES20.glUseProgram(programId)

        // 获取 uniform 变量位置
        timeLoc = GLES20.glGetUniformLocation(programId, "iTime")
        resolutionLoc = GLES20.glGetUniformLocation(programId, "iResolution")

        // 记录开始时间
        startTime = System.currentTimeMillis()
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height)
        // 传递分辨率给 shader
        GLES20.glUniform2f(resolutionLoc, width.toFloat(), height.toFloat())
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES20.glClearColor(0f, 0f, 0f, 1f)
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)

        // 计算运行时间(秒)
        val currentTime = (System.currentTimeMillis() - startTime) / 1000f
        GLES20.glUniform1f(timeLoc, currentTime)

        // 绑定顶点数据
        val positionLoc = GLES20.glGetAttribLocation(programId, "aPosition")
        GLES20.glEnableVertexAttribArray(positionLoc)
        GLES20.glVertexAttribPointer(
            positionLoc, 3, GLES20.GL_FLOAT, false,
            3 * 4, vertexBuffer
        )

        // 绘制全屏四边形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
        GLES20.glDisableVertexAttribArray(positionLoc)
    }

    // 加载并编译 shader
    private fun loadShader(type: Int, shaderCode: String): Int {
        Log.i("ccccccc", "shader_code===$shaderCode")
        return GLES20.glCreateShader(type).apply {
            GLES20.glShaderSource(this, shaderCode)
            GLES20.glCompileShader(this)
        }
    }

    // 顶点着色器(全屏四边形)
    private val vertexShaderCode = """
        attribute vec3 aPosition;
        void main() {
            gl_Position = vec4(aPosition, 1.0);
        }
    """.trimIndent()
    
}

shader_3.glsl内容

ini 复制代码
#version 100
precision mediump float;

uniform float iTime;
uniform vec2 iResolution;

// 旋转90度开关(注释掉可关闭旋转)
#define ROTATE_90

void main() {
    vec2 fragCoord = gl_FragCoord.xy;

    // 处理90度旋转:交换x/y坐标并修正方向
    #ifdef ROTATE_90
    // 交换x和y,实现旋转;反转x轴修正方向
    fragCoord = vec2(fragCoord.y, iResolution.x - fragCoord.x);
    // 旋转后重新计算分辨率比例(宽高互换)
    vec2 r = vec2(iResolution.y, iResolution.x);
    #else
    vec2 r = iResolution.xy;
    #endif

    vec3 c;
    float l, z = iTime;

    // 减少迭代次数(原3次→2次,提升性能)
    for(int i = 0; i < 2; i++) {
        vec2 uv, p = fragCoord.xy / r;
        uv = p;

        // 坐标中心化并适配宽高比
        p -= 0.5;
        p.x *= r.x / r.y;

        // 时间动画控制(略微降低速度,避免过度闪烁)
        z += 0.05;
        l = length(p);

        // 核心扭曲计算(保留原效果)
        uv += p / l * (sin(z) + 1.0) * abs(sin(l * 9.0 - z * 2.0));

        // 颜色计算(增强对比度)
        c[i] = 0.02 / length(mod(uv, 1.0) - 0.5);
    }

    // 补充第三通道颜色(保持三通道平衡)
    c[2] = 0.02 / length(mod((fragCoord.xy / r) + sin(z)*0.1, 1.0) - 0.5);

    // 输出颜色(调整透明度避免过亮)
    gl_FragColor = vec4(c / l, 1.0);
}

拷贝对应的效果代码 扔给ai 然后替换glsl文件内容。这里仅限于 变量只有 iTime iResolution 的效果。如果有其他变量 需要ai帮你把其他变量的设置 补充上

相关推荐
geovindu13 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构
知之则吱吱15 小时前
Android 开发者验证机制迎来新变化:核心要求、实施时间与开发者应对指南
android·google
墨天梦16 小时前
D09_Retrofit接口与数据转换
android·kotlin·retrofit
电商API_1800790524717 小时前
闲鱼商品列表API接口商品详情API接口请求示例(含一份真实响应数据示例)
android·数据挖掘·网络爬虫·跨境电商·反向海淘
我命由我1234517 小时前
Android 广播 - 组件通信
android·java·开发语言·android studio·android jetpack·android-studio·android runtime
阿俊-全栈开发17 小时前
LikeShop 单商户标准版商品管理二开:分类、SKU 规格与库存联动实现
android·likeshop·likeshop开源商城
用户21816970493020 小时前
Kotlin 语法二
android
妖星20 小时前
android 源码分析surfaceFinger是如何通过设置属性启动bootanim
android
JoyMonitor20 小时前
APK mmap 内存增长定位:pagemap 与 DEX 结构联合定位方法
android