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

相关推荐
hjlgs2 小时前
framework修改快速验证
android
游戏开发爱好者83 小时前
iOS 开发者的安全加固工具,从源码到成品 IPA 的多层防护体系实践
android·安全·ios·小程序·uni-app·cocoa·iphone
安卓理事人3 小时前
安卓内存泄露排查LeakCanary
android
秃了也弱了。4 小时前
MySQL空间函数详解,MySQL记录经纬度并进行计算
android·数据库·mysql
.豆鲨包5 小时前
【Android】Binder机制浅析
android·binder
Nerve7 小时前
GooglePay: API 文档
android·google
Nerve7 小时前
GooglePay: 订阅商品购买流程
android·google
summerkissyou19877 小时前
Audio-触摸音-播放流程
android
Nerve7 小时前
GooglePay: 消耗商品购买流程
android·google
LiteHeaven7 小时前
Android 8.1 Unable to create application data 问题分析
android