如何"apply fragment shader to GLSurfaceView/TextureView"?

How to "apply fragment shader to GLSurfaceView/TextureView"?

我的目标是让 ExoPlayer 将彩色视频显示为黑白。

根据这个 this Github issue 我应该可以用 Open GL 实现这个:

ExoPlayer will render video to any Surface. You could use SurfaceTexture, at which point you'd have video rendered into an OpenGL ES texture. Once you have that you can do anything that OpenGL lets you do, including using a pixel shader to transform the video to black and white.

an older, but related, discussion in the Android Developers Google group 中,Romain Guy 给出了一些关于应该如何完成的细节:

  • Create an OpenGL context
  • Generate an OpenGL texture name
  • Create a SurfaceTexture with the texture name
  • Pass the SurfaceTexture to Camera
  • Listen for updates On SurfaceTexture update, draw the texture with OpenGL using the shader you want

Simple :)

并且通过尝试 Google's Cardboard example project 我确定像下面这样的片段着色器应该是正确的:

precision mediump float;
varying vec4 v_Color;

void main() {
    float grayscale = v_Color[0] * 0.3 + v_Color[1] * 0.59 + v_Color[2] * 0.11;
    gl_FragColor = vec4(grayscale, grayscale, grayscale, 0.1);
}

我还设法让 ExoPlayer 渲染成 TextureView 而不是通常的 SurfaceView:

mPlayer.sendMessage(
    videoRenderer,
    MediaCodecVideoTrackRenderer.MSG_SET_SURFACE,
    new Surface(mVideoTextureView.getSurfaceTexture())
);

现在,如何将所有内容连接在一起?

我在哪里可以"apply"着色器到TextureView?这甚至可能还是我应该使用 GLSurfaceView 代替?我需要在 Renderer 中做什么?

我之前将片段着色器应用于 ExoPlayer 播放的视频。最有效的方法似乎是在 GLSurfaceView 上播放视频,因为它们对自定义渲染器有很好的支持。

. It even has a greyscale fragment shader already as part of its effects library 提供了将 OpenGL 着色器应用于 GLSurfaceView 的工作示例。现有代码将需要一些小的重构,因为它使用 MediaPlayer 而不是 ExoPlayer.