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帮你把其他变量的设置 补充上

相关推荐
Bryce李小白4 小时前
Kotlin Flow 的使用
android·开发语言·kotlin
氦客6 小时前
Android Compose 状态的概念
android·compose·重组·状态·组合·mutablestate·mutablestateof
Jerry6 小时前
Compose 约束条件和修饰符顺序
android
千里马学框架7 小时前
安卓系统中线程优先级Priority查看方式汇总
android·framework·线程·安卓framework开发·优先级·priority
沐怡旸7 小时前
【Android】Handler/Looper机制相关的类图和流程图
android
生莫甲鲁浪戴7 小时前
Android Studio新手开发第二十一天
android·ide·android studio
生莫甲鲁浪戴8 小时前
Android Studio新手开发第二十二天
android·ide·android studio
用户41659673693558 小时前
Jetpack Compose 中实现带圆角边框的单词级富文本效果(分词与布局实践)
android
顾林海8 小时前
Android UI优化:让你的APP从“卡顿掉帧”到“丝滑如德芙”
android·面试·性能优化