【发布时间】:2014-01-16 18:58:19
【问题描述】:
我想使用 Android NDK 在带有 OpenGL ES 2.0 的四边形上将图像显示为纹理。
我有以下简单的顶点和片段着色器:
#define DISP_SHADER_V_SRC "\
attribute vec4 aPos;\
attribute vec2 aTexCoord;\
varying vec2 vTexCoord;\
void main() {\
gl_Position = aPos;\
vTexCoord = aTexCoord;\
}"
#define DISP_SHADER_F_SRC "\
precision mediump float;\n\
varying vec2 vTexCoord;\n\
uniform sampler2D sTexture;\n\
void main() {\n\
gl_FragColor = texture2D(sTexture, vTexCoord);\n\
}"
首先,在创建 GLSurfaceView 时会调用原生的“create”方法。它设置清晰的颜色,构建着色器并使用glGenTextures 为我获取纹理ID。 “resize”方法设置当前视图大小。另一种方法是这样设置纹理数据:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
我不相信那里有什么问题。重要的应该是“绘制”方法。在 glClear、glViewport 和 glUseProgram 之后,我执行以下操作:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId);
glEnableVertexAttribArray(shAPos);
glVertexAttribPointer(shAPos, 3, GL_FLOAT, false, 0, quadVertices);
glVertexAttribPointer(shATexCoord, 2, GL_FLOAT, false, 0, quadTexCoordsStd);
glEnableVertexAttribArray(shATexCoord);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// now glDisableVertex...
我可以确认着色器基本上可以工作,因为gl_FragColor=vec4(1.0); 会导致白屏。当我加载纹理时它只是不起作用。我尝试使用memset 将像素数据设置为“全白”,只是为了确认问题与我的图像数据无关,但屏幕仍然保持黑色。我错过了什么?
【问题讨论】:
-
由于您可以使用修改后的着色器进行绘制,因此采样器似乎只是在纹理图像中寻找零点。您能否确认您在拨打
glTexImage2D之前拨打了glBindTexture(GL_TEXTURE_2D, texId)?纹理是否使用二次幂大小? -
我可以确认。我打电话给
glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texId);,然后我设置GL_CLAMP_TO_EDGE并生成mipmap。我还通过设置gl_FragColor = vec4(vTexCoord.s, vTexCoord.t, 1.0, 1.0)检查了vTexCoord是否具有有效值。除了绘制该死的纹理之外,这一切都做了它应该做的事情:( -
哇,这花了一些时间......好吧,我不完全确定问题是什么,但我这样解决了:我注意到绘制纹理有效当我通过 JNI 直接在
onSurfaceCreated内部调用纹理加载函数时。但是,我希望在触摸视图时纹理会发生变化。我猜它与调用线程有关。所以我将调用纹理加载函数的代码从OnClickListener直接移到了实现GLSurfaceView.Renderer的类中。现在它起作用了。棘手的事情,因为没有抛出任何错误:( -
听起来您将其移至不同的线程(UI 线程与 GLSurfaceView 渲染线程)。您是否同时在两个线程中拥有相同的 EGL 上下文?
-
我没有看到任何代码行将制服的值:
sTexture设置为 0。
标签: android opengl-es android-ndk textures opengl-es-2.0