122 lines
3.8 KiB
Kotlin
122 lines
3.8 KiB
Kotlin
|
|
package com.xscm.moduleutil.widget
|
||
|
|
|
||
|
|
|
||
|
|
import android.graphics.SurfaceTexture
|
||
|
|
import android.opengl.GLES20
|
||
|
|
import android.opengl.Matrix
|
||
|
|
|
||
|
|
class ChannelSplitRenderer {
|
||
|
|
|
||
|
|
private val vertexShaderCode = """
|
||
|
|
attribute vec4 aPosition;
|
||
|
|
attribute vec2 aTexCoord;
|
||
|
|
varying vec2 vTexCoord;
|
||
|
|
void main() {
|
||
|
|
gl_Position = aPosition;
|
||
|
|
vTexCoord = aTexCoord;
|
||
|
|
}
|
||
|
|
"""
|
||
|
|
|
||
|
|
private val fragmentShaderCode = """
|
||
|
|
precision mediump float;
|
||
|
|
uniform sampler2D uTexture;
|
||
|
|
varying vec2 vTexCoord;
|
||
|
|
void main() {
|
||
|
|
// 只使用左半部分作为最终颜色
|
||
|
|
vec2 leftCoord = vec2(vTexCoord.x * 0.5, vTexCoord.y);
|
||
|
|
vec4 color = texture2D(uTexture, leftCoord);
|
||
|
|
|
||
|
|
// 设置 alpha 为 1.0 表示完全不透明,或根据需求设为 0.0 表示全透明
|
||
|
|
gl_FragColor = vec4(color.rgb, 0.0); // 左通道颜色 + 不透明
|
||
|
|
}"""
|
||
|
|
|
||
|
|
private var program = 0
|
||
|
|
private var positionHandle = 0
|
||
|
|
private var texCoordHandle = 0
|
||
|
|
private var textureHandle = 0
|
||
|
|
private val projectionMatrix = FloatArray(16)
|
||
|
|
private val modelMatrix = FloatArray(16)
|
||
|
|
|
||
|
|
fun onSurfaceCreated(surface: SurfaceTexture, width: Int, height: Int) {
|
||
|
|
// 初始化着色器
|
||
|
|
val vertexShader = ShaderUtils.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
|
||
|
|
val fragmentShader = ShaderUtils.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)
|
||
|
|
|
||
|
|
program = GLES20.glCreateProgram().also {
|
||
|
|
GLES20.glAttachShader(it, vertexShader)
|
||
|
|
GLES20.glAttachShader(it, fragmentShader)
|
||
|
|
GLES20.glLinkProgram(it)
|
||
|
|
}
|
||
|
|
|
||
|
|
positionHandle = GLES20.glGetAttribLocation(program, "aPosition")
|
||
|
|
texCoordHandle = GLES20.glGetAttribLocation(program, "aTexCoord")
|
||
|
|
textureHandle = GLES20.glGetUniformLocation(program, "uTexture")
|
||
|
|
|
||
|
|
// 初始化矩阵
|
||
|
|
Matrix.setIdentityM(projectionMatrix, 0)
|
||
|
|
Matrix.setIdentityM(modelMatrix, 0)
|
||
|
|
|
||
|
|
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
|
||
|
|
GLES20.glEnable(GLES20.GL_BLEND)
|
||
|
|
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA)
|
||
|
|
}
|
||
|
|
|
||
|
|
fun onSurfaceChanged(width: Int, height: Int) {
|
||
|
|
GLES20.glViewport(0, 0, width, height)
|
||
|
|
}
|
||
|
|
|
||
|
|
fun onDrawFrame(textureId: Int) {
|
||
|
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||
|
|
GLES20.glUseProgram(program)
|
||
|
|
|
||
|
|
// 定义顶点坐标(全屏)
|
||
|
|
val vertices = 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
|
||
|
|
)
|
||
|
|
|
||
|
|
// 修改纹理坐标,只映射左半部分视频内容到左侧屏幕
|
||
|
|
val texCoords = floatArrayOf(
|
||
|
|
0.0f, 1.0f, // 左下角
|
||
|
|
0.5f, 1.0f, // 右下角(对应视频中间)
|
||
|
|
0.0f, 0.0f, // 左上角
|
||
|
|
0.5f, 0.0f // 右上角
|
||
|
|
)
|
||
|
|
|
||
|
|
val vertexBuffer = ShaderUtils.createFloatBuffer(vertices)
|
||
|
|
val texBuffer = ShaderUtils.createFloatBuffer(texCoords)
|
||
|
|
|
||
|
|
GLES20.glEnableVertexAttribArray(positionHandle)
|
||
|
|
GLES20.glVertexAttribPointer(
|
||
|
|
positionHandle, 3,
|
||
|
|
GLES20.GL_FLOAT, false,
|
||
|
|
0, vertexBuffer
|
||
|
|
)
|
||
|
|
|
||
|
|
GLES20.glEnableVertexAttribArray(texCoordHandle)
|
||
|
|
GLES20.glVertexAttribPointer(
|
||
|
|
texCoordHandle, 2,
|
||
|
|
GLES20.GL_FLOAT, false,
|
||
|
|
0, texBuffer
|
||
|
|
)
|
||
|
|
|
||
|
|
// 绑定纹理
|
||
|
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
|
||
|
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
|
||
|
|
GLES20.glUniform1i(textureHandle, 0)
|
||
|
|
|
||
|
|
// 绘制
|
||
|
|
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
|
||
|
|
|
||
|
|
// 清理
|
||
|
|
GLES20.glDisableVertexAttribArray(positionHandle)
|
||
|
|
GLES20.glDisableVertexAttribArray(texCoordHandle)
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
fun release() {
|
||
|
|
GLES20.glDeleteProgram(program)
|
||
|
|
}
|
||
|
|
}
|