Egloo 高级用法

Egloo 高级用法

自定义图形和着色器

1. 自定义形状

通过继承Gl2dDrawableGl3dDrawable类,你可以创建自定义的图形:

kotlin 复制代码
class CustomShape : Gl2dDrawable() {
    override fun getVertexArray(): FloatArray {
        return floatArrayOf(
            // 自定义顶点数据
            -0.5f, -0.5f,  // 左下
             0.5f, -0.5f,  // 右下
             0.0f,  0.5f   // 顶部
        )
    }
    
    override fun draw() {
        // 自定义绘制逻辑
        super.draw()
    }
}

2. 自定义着色器程序

创建自定义着色器程序,实现特殊的视觉效果:

kotlin 复制代码
class CustomProgram : GlProgram() {
    override fun getVertexShader(): String {
        return """
            attribute vec4 aPosition;
            void main() {
                gl_Position = aPosition;
            }
        """.trimIndent()
    }

    override fun getFragmentShader(): String {
        return """
            precision mediump float;
            void main() {
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }
        """.trimIndent()
    }
}

3. 添加自定义Uniform变量

kotlin 复制代码
class ShaderWithUniforms : GlProgram() {
    private var timeLocation = -1
    
    override fun onCreate() {
        super.onCreate()
        timeLocation = getUniformLocation("uTime")
    }
    
    fun setTime(time: Float) {
        GLES20.glUniform1f(timeLocation, time)
    }
    
    override fun getFragmentShader(): String {
        return """
            precision mediump float;
            uniform float uTime;
            
            void main() {
                float r = sin(uTime) * 0.5 + 0.5;
                float g = cos(uTime) * 0.5 + 0.5;
                gl_FragColor = vec4(r, g, 0.3, 1.0);
            }
        """.trimIndent()
    }
}

变换和动画

1. 矩阵变换

kotlin 复制代码
// 创建变换矩阵
val modelMatrix = FloatArray(16)
val viewMatrix = FloatArray(16)
val projectionMatrix = FloatArray(16)
val mvpMatrix = FloatArray(16)

// 设置模型矩阵(旋转)
Matrix.setIdentityM(modelMatrix, 0)
Matrix.rotateM(modelMatrix, 0, angle, 0f, 0f, 1f)

// 设置视图矩阵
Matrix.setLookAtM(viewMatrix, 0,
    0f, 0f, 3f,  // 相机位置
    0f, 0f, 0f,  // 观察点
    0f, 1f, 0f   // 上方向
)

// 设置投影矩阵
Matrix.frustumM(projectionMatrix, 0,
    -ratio, ratio, -1f, 1f, 1f, 10f
)

// 计算最终的MVP矩阵
Matrix.multiplyMM(mvpMatrix, 0, viewMatrix, 0, modelMatrix, 0)
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, mvpMatrix, 0)

// 应用到着色器程序
program.setMvpMatrix(mvpMatrix)

2. 动画实现

kotlin 复制代码
class AnimatedRenderer : Renderer {
    private var lastFrameTime = System.nanoTime()
    private var angle = 0f
    
    override fun onDrawFrame(gl: GL10) {
        // 计算帧间隔时间
        val currentTime = System.nanoTime()
        val deltaTime = (currentTime - lastFrameTime) / 1_000_000_000f
        lastFrameTime = currentTime
        
        // 更新旋转角度
        angle += 90f * deltaTime // 每秒旋转90度
        
        // 应用旋转
        val matrix = FloatArray(16)
        Matrix.setRotateM(matrix, 0, angle, 0f, 0f, 1f)
        drawable.setTransformMatrix(matrix)
        
        // 绘制
        drawable.draw()
    }
}

高级纹理技术

1. 多重纹理

kotlin 复制代码
class MultiTextureProgram : GlProgram() {
    private var texture1Location = -1
    private var texture2Location = -1
    private var mixValueLocation = -1
    
    override fun onCreate() {
        super.onCreate()
        texture1Location = getUniformLocation("uTexture1")
        texture2Location = getUniformLocation("uTexture2")
        mixValueLocation = getUniformLocation("uMixValue")
    }
    
    fun setTextures(texture1: Int, texture2: Int, mixValue: Float) {
        // 激活并绑定第一个纹理
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture1)
        GLES20.glUniform1i(texture1Location, 0)
        
        // 激活并绑定第二个纹理
        GLES20.glActiveTexture(GLES20.GL_TEXTURE1)
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture2)
        GLES20.glUniform1i(texture2Location, 1)
        
        // 设置混合值
        GLES20.glUniform1f(mixValueLocation, mixValue)
    }
    
    override fun getFragmentShader(): String {
        return """
            precision mediump float;
            uniform sampler2D uTexture1;
            uniform sampler2D uTexture2;
            uniform float uMixValue;
            varying vec2 vTextureCoord;
            
            void main() {
                vec4 color1 = texture2D(uTexture1, vTextureCoord);
                vec4 color2 = texture2D(uTexture2, vTextureCoord);
                gl_FragColor = mix(color1, color2, uMixValue);
            }
        """.trimIndent()
    }
}

2. 帧缓冲区后处理效果

kotlin 复制代码
// 创建帧缓冲区和纹理
val framebuffer = GlFramebuffer()
val texture = GlTexture()

// 设置帧缓冲区
framebuffer.bind()
texture.bind()
texture.configure(width, height, null)
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
                             GLES20.GL_TEXTURE_2D, texture.id, 0)

// 渲染到帧缓冲区
scene.draw()

// 解绑帧缓冲区
framebuffer.unbind()

// 使用后处理着色器渲染到屏幕
postProcessingProgram.use()
postProcessingProgram.setTexture(texture.id)
screenQuad.draw()

性能优化技术

1. 顶点缓冲对象(VBO)和索引缓冲对象(IBO)

kotlin 复制代码
// 创建VBO
val vbo = IntArray(1)
GLES20.glGenBuffers(1, vbo, 0)
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0])
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 
                   vertices.size * 4, 
                   vertexBuffer, 
                   GLES20.GL_STATIC_DRAW)

// 创建IBO
val ibo = IntArray(1)
GLES20.glGenBuffers(1, ibo, 0)
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0])
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, 
                   indices.size * 2, 
                   indexBuffer, 
                   GLES20.GL_STATIC_DRAW)

// 绘制
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.size, 
                     GLES20.GL_UNSIGNED_SHORT, 0)

2. 实例化渲染

kotlin 复制代码
class InstancedProgram : GlProgram() {
    private var instancePositionLocation = -1
    
    override fun onCreate() {
        super.onCreate()
        instancePositionLocation = getAttribLocation("aInstancePosition")
    }
    
    override fun getVertexShader(): String {
        return """
            attribute vec4 aPosition;
            attribute vec2 aInstancePosition;
            
            void main() {
                vec4 pos = aPosition;
                pos.xy += aInstancePosition;
                gl_Position = pos;
            }
        """.trimIndent()
    }
    
    // 设置实例数据
    fun setInstanceData(buffer: FloatBuffer, count: Int) {
        GLES20.glEnableVertexAttribArray(instancePositionLocation)
        GLES20.glVertexAttribPointer(instancePositionLocation, 2, 
                                    GLES20.GL_FLOAT, false, 0, buffer)
        GLES20.glVertexAttribDivisor(instancePositionLocation, 1)
        
        // 绘制多个实例
        GLES20.glDrawArraysInstanced(GLES20.GL_TRIANGLES, 0, 
                                    vertexCount, count)
    }
}

3. 着色器计算优化

kotlin 复制代码
// 优化前
float result = pow(base, exponent); // 计算开销大

// 优化后
float result = exp(log(base) * exponent); // 更高效

调试和分析

1. 性能分析

kotlin 复制代码
class PerformanceMonitor {
    private var frameCount = 0
    private var lastTime = System.nanoTime()
    private var totalTime = 0L
    
    fun beginFrame() {
        lastTime = System.nanoTime()
    }
    
    fun endFrame() {
        val currentTime = System.nanoTime()
        val frameTime = currentTime - lastTime
        totalTime += frameTime
        frameCount++
        
        // 每秒输出一次统计信息
        if (totalTime >= 1_000_000_000L) {
            val fps = frameCount * 1_000_000_000L / totalTime
            val avgFrameTime = totalTime / frameCount / 1_000_000f
            Log.d("Egloo", "FPS: $fps, Avg frame time: $avgFrameTime ms")
            
            frameCount = 0
            totalTime = 0
        }
    }
}

2. 着色器调试

kotlin 复制代码
// 检查着色器编译状态
val compiled = IntArray(1)
GLES20.glGetShaderiv(shaderId, GLES20.GL_COMPILE_STATUS, compiled, 0)
if (compiled[0] == 0) {
    val log = GLES20.glGetShaderInfoLog(shaderId)
    Log.e("Egloo", "Shader compilation failed: $log")
}

与其他框架集成

1. 与Camera2 API集成

kotlin 复制代码
// 创建SurfaceTexture
val texture = GlTexture()
texture.bind()
val surfaceTexture = SurfaceTexture(texture.id)

// 设置缓冲区大小
surfaceTexture.setDefaultBufferSize(width, height)

// 创建Surface
val surface = Surface(surfaceTexture)

// 配置Camera2
val captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
captureRequestBuilder.addTarget(surface)

// 设置SurfaceTexture回调
surfaceTexture.setOnFrameAvailableListener { 
    // 当新帧可用时更新纹理
    surfaceTexture.updateTexImage()
    
    // 获取变换矩阵
    val matrix = FloatArray(16)
    surfaceTexture.getTransformMatrix(matrix)
    
    // 绘制
    render()
}

2. 与MediaCodec集成

kotlin 复制代码
// 创建编码器
val encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC)
val format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height)
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate)
format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate)
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)

// 配置编码器
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)

// 创建输入Surface
val inputSurface = encoder.createInputSurface()

// 创建EGL窗口表面
val encoderSurface = EglWindowSurface(eglCore, inputSurface)

// 渲染到编码器Surface
encoderSurface.makeCurrent()
// 绘制...
encoderSurface.swapBuffers()

高级场景管理

kotlin 复制代码
class Scene {
    private val drawables = mutableListOf<GlDrawable>()
    private val lights = mutableListOf<Light>()
    private val camera = Camera()
    
    fun addDrawable(drawable: GlDrawable) {
        drawables.add(drawable)
    }
    
    fun addLight(light: Light) {
        lights.add(light)
    }
    
    fun setCamera(position: FloatArray, target: FloatArray, up: FloatArray) {
        camera.position = position
        camera.target = target
        camera.up = up
    }
    
    fun render() {
        // 计算视图和投影矩阵
        val viewMatrix = camera.getViewMatrix()
        val projectionMatrix = camera.getProjectionMatrix(aspect)
        
        // 设置光照
        for (light in lights) {
            light.apply()
        }
        
        // 绘制所有对象
        for (drawable in drawables) {
            val program = drawable.program
            program.use()
            
            // 设置矩阵
            program.setViewMatrix(viewMatrix)
            program.setProjectionMatrix(projectionMatrix)
            
            // 绘制对象
            drawable.draw()
        }
    }
}

多线程渲染

1. 创建专用渲染线程

kotlin 复制代码
class RenderThread : Thread() {
    private val handler: Handler by lazy {
        Looper.prepare()
        val handler = Handler()
        Looper.loop()
        handler
    }
    
    fun queueEvent(runnable: Runnable) {
        handler.post(runnable)
    }
    
    fun quit() {
        handler.looper.quit()
    }
}

// 使用
val renderThread = RenderThread()
renderThread.start()

// 在渲染线程上执行OpenGL操作
renderThread.queueEvent {
    // OpenGL操作
    eglCore.makeCurrent(surface)
    program.use()
    drawable.draw()
    surface.swapBuffers()
}

2. 线程间共享EGL上下文

kotlin 复制代码
// 主线程:创建共享上下文
val sharedEglCore = EglCore(null, EglCore.FLAG_TRY_GLES3)

// 渲染线程:使用共享上下文
val renderEglCore = EglCore(sharedEglCore.eglContext, EglCore.FLAG_TRY_GLES3)

// 资源加载线程:使用共享上下文
val resourceEglCore = EglCore(sharedEglCore.eglContext, EglCore.FLAG_TRY_GLES3)

高级特效

1. 粒子系统

kotlin 复制代码
class ParticleSystem(private val maxParticles: Int) {
    private val positions = FloatArray(maxParticles * 3)
    private val velocities = FloatArray(maxParticles * 3)
    private val colors = FloatArray(maxParticles * 4)
    private val lifetimes = FloatArray(maxParticles)
    
    fun update(deltaTime: Float) {
        for (i in 0 until maxParticles) {
            // 更新生命周期
            lifetimes[i] -= deltaTime
            
            // 跳过已死亡的粒子
            if (lifetimes[i] <= 0f) {
                resetParticle(i)
                continue
            }
            
            // 更新位置
            val idx = i * 3
            positions[idx] += velocities[idx] * deltaTime
            positions[idx + 1] += velocities[idx + 1] * deltaTime
            positions[idx + 2] += velocities[idx + 2] * deltaTime
            
            // 应用重力
            velocities[idx + 1] -= 9.8f * deltaTime
        }
    }
    
    private fun resetParticle(index: Int) {
        // 重置粒子位置、速度、颜色和生命周期
        val idx = index * 3
        positions[idx] = 0f
        positions[idx + 1] = 0f
        positions[idx + 2] = 0f
        
        // 随机速度
        val angle = Math.random().toFloat() * 2f * Math.PI.toFloat()
        val speed = 1f + Math.random().toFloat() * 2f
        velocities[idx] = Math.cos(angle.toDouble()).toFloat() * speed
        velocities[idx + 1] = Math.sin(angle.toDouble()).toFloat() * speed
        velocities[idx + 2] = (Math.random().toFloat() - 0.5f) * speed
        
        // 随机颜色
        val colorIdx = index * 4
        colors[colorIdx] = Math.random().toFloat()
        colors[colorIdx + 1] = Math.random().toFloat()
        colors[colorIdx + 2] = Math.random().toFloat()
        colors[colorIdx + 3] = 1f
        
        // 随机生命周期
        lifetimes[index] = 1f + Math.random().toFloat() * 3f
    }
    
    fun draw(program: ParticleProgram) {
        program.use()
        program.setParticleData(positions, colors, lifetimes, maxParticles)
        GLES20.glDrawArrays(GLES20.GL_POINTS, 0, maxParticles)
    }
}

2. 阴影映射

kotlin 复制代码
// 创建阴影贴图
val shadowMapSize = 1024
val shadowMap = GlTexture()
val shadowFramebuffer = GlFramebuffer()

// 配置阴影贴图
shadowMap.bind()
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_DEPTH_COMPONENT,
                   shadowMapSize, shadowMapSize, 0, GLES20.GL_DEPTH_COMPONENT,
                   GLES20.GL_UNSIGNED_INT, null)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST)

// 配置阴影帧缓冲区
shadowFramebuffer.bind()
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
                             GLES20.GL_TEXTURE_2D, shadowMap.id, 0)
GLES20.glDrawBuffers(0, IntArray(0), 0) // 不需要颜色缓冲区

// 从光源视角渲染阴影贴图
shadowFramebuffer.bind()
GLES20.glViewport(0, 0, shadowMapSize, shadowMapSize)
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT)

val lightViewMatrix = calculateLightViewMatrix()
val lightProjectionMatrix = calculateLightProjectionMatrix()

shadowProgram.use()
shadowProgram.setViewMatrix(lightViewMatrix)
shadowProgram.setProjectionMatrix(lightProjectionMatrix)

// 渲染场景到阴影贴图
for (drawable in drawables) {
    drawable.drawShadow(shadowProgram)
}

// 正常渲染场景,使用阴影贴图
defaultFramebuffer.bind()
GLES20.glViewport(0, 0, width, height)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)

mainProgram.use()
mainProgram.setViewMatrix(camera.viewMatrix)
mainProgram.setProjectionMatrix(camera.projectionMatrix)
mainProgram.setLightViewMatrix(lightViewMatrix)
mainProgram.setLightProjectionMatrix(lightProjectionMatrix)
mainProgram.setShadowMap(shadowMap.id)

// 渲染场景
for (drawable in drawables) {
    drawable.draw(mainProgram)
}

结语

本文档介绍了Egloo框架的高级用法,包括自定义图形和着色器、变换和动画、高级纹理技术、性能优化、调试和分析、与其他框架集成、高级场景管理、多线程渲染以及高级特效等内容。通过这些高级技术,你可以充分发挥Egloo框架的潜力,创建复杂、高效的OpenGL ES应用程序。

如果你有任何问题或需要进一步的帮助,请参考API文档或在GitHub上提交issue。

相关推荐
一只柠檬新3 小时前
Web和Android的渐变角度区别
android
志旭3 小时前
从0到 1实现BufferQueue GraphicBuffer fence HWC surfaceflinger
android
_一条咸鱼_3 小时前
Android Runtime堆内存架构设计(47)
android·面试·android jetpack
用户2018792831673 小时前
WMS(WindowManagerService的诞生
android
用户2018792831673 小时前
通俗易懂的讲解:Android窗口属性全解析
android
openinstall3 小时前
A/B测试如何借力openinstall实现用户价值深挖?
android·ios·html
二流小码农3 小时前
鸿蒙开发:资讯项目实战之项目初始化搭建
android·ios·harmonyos
志旭4 小时前
android15 vsync源码分析
android
志旭4 小时前
Android 14 HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia
android