我在OpenGL ES 2.0
上使用Android
为视频添加效果。一切正常,直到我添加另一个纹理。
我尝试过的事情:
尚未尝试:
但是在这一点上我会放弃关于位图并将包含我的像素的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问题。
答案 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,或者至少你应该能够快速检查你刚绑定的程序是否有效。
这会留下位置无效的选项或错误制服的位置。除非我错过了您发布的相对冗长的代码,否则唯一合乎逻辑的解释是,用于检索着色器位置的程序与您在onDraw()
中设置制服所绑定的程序不同。
我注意到您正在使用某种着色器缓存来重用着色器。虽然这看起来相当简单,但我会加倍(并且三倍,四倍)检查它是否真的按预期工作。比较在设置期间使用的程序ID,其中您获得统一位置与准备绘制时使用的位置。并确保没有破坏和重新创建着色器。而且一切都发生在同一个线程/上下文中。