GlUniform1i导致均匀和位图纹理错误

时间:2015-07-02 09:24:06

标签: android opengl-es-2.0

我在OpenGL ES 2.0上使用Android为视频添加效果。一切正常,直到我添加另一个纹理。

我尝试过的事情:

  • 使用Texture2D代替外部(EOS) - >外部源(视频文件)不可能
  • 使用检查GPU是否支持2的非幂的方法后,将纹理更改为2的幂 - >没有变化
  • 按照GLES20方法的时间顺序播放 - >执行行为没有明显变化
  • 使用不同索引逻辑的绑定纹理 - >没有变化

尚未尝试:

  • 使用其他位图格式,但加载位图的GLUtils方法应该处理格式
  • 使用'遗产'从位图加载纹理的方法(GLES而不是GLUtils)
  • 使用像素数组而不是位图。

但是在这一点上我会放弃关于位图并将包含我的像素的Uniform Buffer发送到着色器......

当我的表面被创建时,我这样做:

var vertexShader = _videoView.Filtering.Shaders.Item1;
var fragmentShader = _videoView.Filtering.Shaders.Item2;
var progExists = glPrograms.ContainsKey (vertexShader + fragmentShader);
if (!progExists) {
    var prog = createProgram (vertexShader, fragmentShader);
    glPrograms.Add (vertexShader + fragmentShader, prog);
}
_glProgram = glPrograms [vertexShader + fragmentShader];

if (_glProgram == 0) {
    // Should compile with default shaders from GlFilter.
    throw new System.Exception ("Can't create GL Program. There is something wrong with EGL on this device.");
}

我也加载了纹理:

_aPositionHandle = GLES20.GlGetAttribLocation(_glProgram, "aPosition");
checkGlError("glGetAttribLocation aPosition");
if (_aPositionHandle == -1) {
    throw new RuntimeException(
        "Could not get attrib location for aPosition");
}

_aTextureCoord = GLES20.GlGetAttribLocation(_glProgram,
    "aTextureCoord");
checkGlError("glGetAttribLocation aTextureCoord");
if (_aTextureCoord == -1) {
    throw new RuntimeException (
        "Could not get attrib location for aTextureCoord");
}

_uMVPMatrixHandle = GLES20.GlGetUniformLocation(_glProgram,
    "uMVPMatrix");
checkGlError("glGetUniformLocation uMVPMatrix");
if (_uMVPMatrixHandle == -1) {
    throw new RuntimeException(
        "Could not get attrib location for uMVPMatrix");
}

_uSTMatrixHandle = GLES20.GlGetUniformLocation(_glProgram,
    "uSTMatrix");
checkGlError("glGetUniformLocation uSTMatrix");
if (_uSTMatrixHandle == -1) {
    throw new RuntimeException(
        "Could not get attrib location for uSTMatrix");
}

_texelWidthOffsetUniform = GLES20.GlGetUniformLocation(_glProgram,
    "texelWidthOffset");
checkGlError("glGetUniformLocation texelWidthOffset");
if (_texelWidthOffsetUniform == -1) {
    throw new RuntimeException(
        "Could not get attrib location for texelWidthOffset");
}


_texelHeightOffsetUniform = GLES20.GlGetUniformLocation(_glProgram,
    "texelHeightOffset");
checkGlError("glGetUniformLocation texelHeightOffset");
if (_texelHeightOffsetUniform == -1) {
    throw new RuntimeException(
        "Could not get attrib location for texelHeightOffset");
}

_sTexture2Uniform = GLES20.GlGetUniformLocation(_glProgram,
    "sTexture2");
checkGlError("glGetUniformLocation sTexture2Uniform");
if (_sTexture2Uniform == -1) {
    throw new RuntimeException(
        "Could not get attrib location for sTexture2");
}

int[] textures = new int[1];
GLES20.GlGenTextures(1, textures, 0);
_textureID = textures[0];
GLES20.GlBindTexture(GL_TEXTURE_EXTERNAL_OES, _textureID);
checkGlError("glBindTexture _textureID");
GLES20.GlTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GlTextureMinFilter, GLES20.GlNearest);
GLES20.GlTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GlTextureMagFilter, GLES20.GlLinear);

仍然在Surface Created事件中,我通过上传Bitmap

添加纹理
source = Bitmap.CreateBitmap(256, 256, Bitmap.Config.Argb8888);
source.EraseColor(Color.Pink.ToArgb());

for (int x = 0; x < 256; x++)
    for (int y = 0; y < 256; y++) {
        var cof = (int)(System.Math.Cos ((double)x / (double)256) * 255);
        var sif = (int)(System.Math.Sin ((double)y / (double)256) * 255);
        var p = (double)x / (double)256 * 360d;
        var q = (double)y / (double)256 * 360d;
        var c = (int)(((System.Math.Sin (p * q) / 2d) + 0.5d) * 255d);
        source.SetPixel (x, y, Color.Argb (255, c, (c + cof) / 2, (c + sif) / 2));
    }

int[] textures = new int[1];

GLES20.GlGenTextures(1, textures, 0);

_texture2Id = textures[0];

GLUtils.TexImage2D(GLES20.GlTexture2d, 0, source, 0);
source.Recycle ();

GLES20.GlBindTexture(GLES20.GlTexture2d, _texture2Id);

GLES20.GlTexParameterf(GLES20.GlTexture2d, GLES20.GlTextureWrapS, GLES20.GlClampToEdge);
GLES20.GlTexParameterf(GLES20.GlTexture2d, GLES20.GlTextureWrapT, GLES20.GlClampToEdge);
GLES20.GlTexParameterf(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlLinear);
GLES20.GlTexParameterf(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlLinear);

_surfaceTexture = new SurfaceTexture(_textureID);
_surfaceTexture.FrameAvailable += _surfaceTexture_FrameAvailable;
_mediaPlayer = new MediaPlayer();

然后在OnDraw中:

var fragment = _videoView.Filtering.Shaders.Item2;
var vertex = _videoView.Filtering.Shaders.Item1;

var progExists = glPrograms.ContainsKey (vertex + fragment);
if (!progExists) {
    var prog = createProgram (vertex, fragment);
    glPrograms.Add (vertex + fragment, prog);
}
var progToUse = glPrograms [vertex + fragment];

GLES20.GlClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.GlClear(GLES20.GlColorBufferBit);

lock (syncLock) {
    _surfaceTexture.UpdateTexImage ();
    _surfaceTexture.GetTransformMatrix (_STMatrix);
    updateSurface = false;
}

GLES20.GlViewport(0, 0, _surfaceWidth, _surfaceHeight);

if (progToUse != _glProgram) {
    GLES20.GlUseProgram (progToUse);
}

_glProgram = progToUse;

GLES20.GlUniform1i(_sTexture2Uniform, 1);

GLES20.GlActiveTexture (GLES20.GlTexture0);
GLES20.GlBindTexture (GL_TEXTURE_EXTERNAL_OES, _textureID);

GLES20.GlActiveTexture (GLES20.GlTexture1);
GLES20.GlBindTexture (GLES20.GlTexture2d, _texture2Id);

_triangleVertices.Position (TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.GlVertexAttribPointer (_aPositionHandle, 3, GLES20.GlFloat, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, _triangleVertices);
GLES20.GlEnableVertexAttribArray (_aPositionHandle);

_textureVertices.Position (TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.GlVertexAttribPointer (_aTextureCoord, 2, GLES20.GlFloat, false, TEXTURE_VERTICES_DATA_STRIDE_BYTES, _textureVertices);
GLES20.GlEnableVertexAttribArray (_aTextureCoord);

Android.Opengl.Matrix.SetIdentityM (_MVPMatrix, 0);

GLES20.GlUniformMatrix4fv (_uMVPMatrixHandle, 1, false, _MVPMatrix, 0);
GLES20.GlUniformMatrix4fv (_uSTMatrixHandle, 1, false, _STMatrix, 0);

GLES20.GlDrawArrays(GLES20.GlTriangleStrip, 0, 4);  


The problem is when I hit this line `GLES20.GlUniform1i(_sTexture2Uniform, 1);`

我一直收到此错误,然后在OnDraw中设置我的位图纹理。

[Adreno200-ES20] <__load_uniform_float:539>: GL_INVALID_OPERATION

我得到的两个错误是:

[SurfaceTexture] [unnamed-22096-0] updateTexImage: clearing GL error: 0x502
[Adreno200-ES20] <__load_uniform_int:305>: GL_INVALID_OPERATION

Vertex看起来像:

uniform mat4 uMVPMatrix;
uniform mat4 uSTMatrix;
uniform highp float texelWidthOffset;
uniform highp float texelHeightOffset;
attribute vec4 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord;
void main() {
    highp float useTX = texelWidthOffset;
    highp float useTY = texelHeightOffset;
    gl_Position = uMVPMatrix * aPosition;
    vTextureCoord = (uSTMatrix * aTextureCoord).xy;
}

片段看起来像:

#version 150
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform sampler2D sTexture2;
uniform samplerExternalOES sTexture;
varying vec2 vTextureCoord;
varying float texelWidthOffset;
varying float texelHeightOffset;
void main() {
    highp float useTX = texelWidthOffset;
    highp float useTY = texelHeightOffset;
    lowp vec4 inputColor0 = texture2D(sTexture,vTextureCoord);
    lowp vec4 someColor = mix(inputColor0, texture2D(sTexture2,vTextureCoord), useTY);
    lowp vec4 outputColor0 = mix(inputColor0, texture2D(sTexture,vTextureCoord), useTX);
    gl_FragColor=outputColor0;
}

我不知道该说什么,除了&#34;帮助!&#34;,因为我可能会尝试按照100多个教程来修复此GL_INVALID_OPERATION错误。 在将OES外部源(电影文件)与位图纹理混合时,我所做的任何尝试都没有产生任何彩色像素。

[编辑]

确定。在上面的代码中,我将_glProgram设置为正确创建的程序ID,然后在使用程序之前,我说:&#34; _glProgram是否等于正确创建的程序id?如果是,那么请不要来useProgram。&#34;所以我从来没有使用过正确的程序。所以现在没有一个OpenGL错误,但屏幕是黑色的,如零。这是一个好消息。我知道我的位图纹理中的像素是正确的。 (随机编写了一个三角算法,碰巧形成了可爱的波尔卡四孔按钮。)所以我正在修改我的OpenGL ES代码。

[编辑2]

我觉得我遇到了this问题。

1 个答案:

答案 0 :(得分:1)

您的代码中存在一个非常明显的问题。在此调用序列中:

GLES20.GlGenTextures(1, textures, 0);
_texture2Id = textures[0];

GLUtils.TexImage2D(GLES20.GlTexture2d, 0, source, 0);
source.Recycle ();

GLES20.GlBindTexture(GLES20.GlTexture2d, _texture2Id);

您需要在调用GLUtils.texImage2D()之前绑定纹理。该方法将纹理数据加载到当前绑定的纹理中。正确的顺序是:

GLES20.GlGenTextures(1, textures, 0);
_texture2Id = textures[0];
GLES20.GlBindTexture(GLES20.GlTexture2d, _texture2Id);

GLUtils.TexImage2D(GLES20.GlTexture2d, 0, source, 0);
source.Recycle ();

但这并不能解释来自glUniform1i()电话的错误。由于以下原因,它可能会出现GL_INVALID_OPERATION错误:

  1. 没有程序受约束。
  2. 该位置对当前绑定的程序无效。
  3. 用于调用的类型/大小与着色器中统一的类型/大小不匹配。
  4. 我们可以排除选项1,或者至少你应该能够快速检查你刚绑定的程序是否有效。

    这会留下位置无效的选项或错误制服的位置。除非我错过了您发布的相对冗长的代码,否则唯一合乎逻辑的解释是,用于检索着色器位置的程序与您在onDraw()中设置制服所绑定的程序不同。

    我注意到您正在使用某种着色器缓存来重用着色器。虽然这看起来相当简单,但我会加倍(并且三倍,四倍)检查它是否真的按预期工作。比较在设置期间使用的程序ID,其中您获得统一位置与准备绘制时使用的位置。并确保没有破坏和重新创建着色器。而且一切都发生在同一个线程/上下文中。