8

我正在尝试通过传输到 OpenGL ES 2.0 着色器的 SurfaceTexture 在 GLSurfaceView 中显示相机流。

我从这篇文章中获得了灵感。

图像是完整的,但在我的平板电脑上没有正确显示。屏幕似乎分为 2x2 部分。图像显示在左上角,而其他三个部分是黑色的。

我怀疑问题来自我对此处记录的序列返回的转换矩阵的使用

updateTexImage();
getTransformMatrix(...);

我在顶点着色器中传输这个矩阵来为片段着色器生成纹理坐标。

顶点着色器:

attribute vec3 aPosition;
uniform mat4 uMvpTransform;
// Matrix retrieved by getTransformMatrix(...);
uniform mat4 uTexMatTransform;
varying vec2 vTexCoord;

void main(void)
{
  gl_Position = uMvpTransform *vec4(aPosition.xyz, 1);
  vec4 l_tex =  uTexMatTransform*vec4(aPosition.xyz, 1);
  vTexCoord=l_tex.xy;
}

片段着色器:

#extension GL_OES_EGL_image_external : require
varying mediump vec2 vTexCoord;
uniform samplerExternalOES uSampler; 

void main(void) 
{ 
    mediump vec4 l_tex = texture2D(uSampler, vTexCoord);
    gl_FragColor=l_tex;
}

纹理附加到以下正方形:

 // Image container
 GLfloat l_vertices[] = {
  -1.0f, 1.0f,  0.0f,
  -1.0f, -1.0f,  0.0f,
  1.0f,  -1.0f,  0.0f,
  1.0f,  1.0f,  0.0f };

有没有人取得类似的成就?

2012 年 11 月 3 日编辑:

顶点着色器的修正:

attribute vec3 aPosition;
attribute vec2 aTexCoord;
uniform mat4 uMvpTransform;
// Matrix retrieved by getTransformMatrix(...);
uniform mat4 uTexMatTransform;
varying vec2 vTexCoord;

void main(void)
{
  gl_Position = uMvpTransform *vec4(aPosition.xyz, 1);
  vec4 l_tex =  uTexMatTransform*vec4(aTexCoord.xy,0, 1);
  vTexCoord=l_tex.xy;
}

和:

// Texture
GLfloat l_texCoord[] = {
   0.0f, 1.0f,
   0.0f, 0.0f,
   1.0f,  0.0f,
   1.0f,  1.0f

};

4

2 回答 2

4

我已成功使用 SurfaceTexture 在自定义 opengl 纹理上绘制相机帧,而无需使用 android 提供的转换矩阵。

只需尝试按照正常纹理绘制的方式定义索引顶点和纹理。比如像这样。

const GLfloat Vertices[] = {0.5, -0.5, 0,
                            0.5, 0.5, 0,
                           -0.5, 0.5, 0,
                           -0.5, -0.5, 0};

const GLubyte Indices[] = { 0, 1, 2,
                            2, 3, 0 };

const GLfloat Textures[] = { 1.,0.,
                             0.,0.,
                             0.,1.,
                             1.,1. };

您应该能够像使用普通纹理一样使用表面纹理。

如果您想执行某种 3D 投影,这是一篇关于如何生成适当 MVP 矩阵的好文章。您可以使用它与顶点着色器中的位置相乘。

于 2012-11-03T03:46:18.773 回答
3

由于我有同样的问题,即使这个问题有点老了,可能值得详细说明一下“为什么使用转换矩阵”

转换矩阵将 SurfaceTexture 使用的特定坐标集(或者更有可能 是当前视频源流 到 SurfaceTexture...)映射到标准 OpenGL 纹理坐标。

绝对应该使用它的原因是,尽管 Startibartfast 答案适用于一个或多个特定设置,并且可能很容易实现,但当同一程序在不同设备上运行时,它可能会产生奇怪的可视化错误,例如关于每个平台的视频驱动程序实现。

例如,在我的情况下,变换矩阵只是将内容颠倒过来(我在 Nexus 7 上将 SurfaceTexture 与 MediaPlayer 结合使用),而不是 Fabien R 指出的结果。

在2012 年 11 月 3 日的 Fabien R 编辑中指出了使用矩阵的正确方法,我报告了一些小修饰(例如使用 st 索引) ,并对 int/float 不匹配进行了小幅修正:

attribute   vec2 uv;
varying     vec2 vTexCoord;
uniform     mat4 transformMatrix;

vTexCoord = (transformMatrix * vec4(uv, 0.0, 1.0)).st;

希望能帮助到你

于 2014-09-21T21:47:08.780 回答