当前位置: 首页 > 知识库问答 >
问题:

Android OpenGL ES 2.0黑色纹理

冀耀
2023-03-14

我在学《欢乐合唱团》。0(我是一个新手:))在Android上,我想画一个有纹理的正方形,但我做不到。我在谷歌上搜索了很多,但我想不出答案,我只得到了一个黑色的正方形。

我设置了一个GLSurfaceView,然后是一个渲染器:

public class MySurfaceRenderer implements GLSurfaceView.Renderer {

    private Context context;
    private Sprite sprite1;

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        sprite1.Draw();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,GLES20.GL_ONE_MINUS_SRC_ALPHA);
        GLES20.glClearColor(0.0f, 0.3f, 0.0f, 1.0f);
        sprite1 = new Sprite(context, R.drawable.test);
    }

}

雪碧类:

java prettyprint-override">public class Sprite {

    private static String TAG = "SpriteRender";

    private Context context;

    private FloatBuffer databuffer;
    private FloatBuffer texturebuffer;
    // x, y,
    float data[] =  {-0.5f,  -0.5f,
                     -0.5f, 0.5f,
                     0.5f, 0.5f,
                     0.5f, -0.5f};
    // u,v 
    float texturedata[] =   {0.0f, 0.0f,
                            0.0f, 1.0f,
                            1.0f, 1.0f,
                            1.0f, 0.0f};
    private int mProgram;
    private int vertexShader;
    private int fragmentShader;
    private int texture;
    private int positionHandler;
    private int texCoordHandler;
    private int textureHandler;

    public Sprite(Context context, int textureid){
        this.context = context;

        ByteBuffer bb_data = ByteBuffer.allocateDirect(data.length * 4);
        bb_data.order(ByteOrder.nativeOrder());
        ByteBuffer bb_texture = ByteBuffer.allocateDirect(texturedata.length * 4);
        bb_texture.order(ByteOrder.nativeOrder());

        databuffer = bb_data.asFloatBuffer();
        databuffer.put(data);
        databuffer.position(0);
        texturebuffer = bb_texture.asFloatBuffer();
        texturebuffer.put(texturedata);
        texturebuffer.position(0);

        vertexShader = ShaderLoader.loadShader(GLES20.GL_VERTEX_SHADER, ShaderLoader.readFromAssert(context, R.raw.tvs));
        fragmentShader = ShaderLoader.loadShader(GLES20.GL_FRAGMENT_SHADER, ShaderLoader.readFromAssert(context, R.raw.tfs));

        mProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(mProgram, fragmentShader);
        GLES20.glAttachShader(mProgram, vertexShader);
        GLES20.glLinkProgram(mProgram);

        int[] linkStatus = new int[1];
        GLES20.glGetProgramiv(mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);

        if (linkStatus[0] == 0){
            // Displays error message
        }
        positionHandler     = GLES20.glGetAttribLocation(mProgram, "a_Position");
        texCoordHandler     = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate");
        textureHandler      = GLES20.glGetUniformLocation(mProgram, "u_Texture");

        texture = TextureLoader.loadTexture(context, textureid);
    }

    public void Draw(){
        GLES20.glUseProgram(mProgram);
        databuffer.position(0);
        texturebuffer.position(0);  

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);

        GLES20.glUniform1i(textureHandler, 0);

        GLES20.glEnableVertexAttribArray(texCoordHandler);
        GLES20.glEnableVertexAttribArray(positionHandler);

        GLES20.glVertexAttribPointer(positionHandler, 2, GLES20.GL_FLOAT, false, 8, databuffer);
        GLES20.glVertexAttribPointer(texCoordHandler, 2, GLES20.GL_FLOAT, false, 8, texturebuffer);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
    }

}

ShaderLoader。loadShader从文件(以res/raw格式)TextureLoader加载着色器。loadTexture从资源中加载纹理:

public static int loadTexture(Context context, int resource){
    int[] texture = new int[1];

    GLES20.glGenTextures(1, texture, 0);

    BitmapFactory.Options bo = new BitmapFactory.Options();
    bo.inScaled = false;
    Bitmap tex = BitmapFactory.decodeResource(context.getResources(), resource, bo);

    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, tex, 0);
    tex.recycle();

    if(texture[0] == 0){
        // Displays error
    }

    return texture[0];

}

顶点着色器:

attribute vec4 a_Position;
attribute vec2 a_TexCoordinate;
varying vec2 v_TexCoordinate;

void main() {
  v_TexCoordinate = a_TexCoordinate;
  gl_Position = a_Position;
}

片段着色器:

precision mediump float;
varying vec2 v_TexCoordinate;
uniform sampler2D u_Texture;

void main() {
  gl_FragColor = texture2D(u_Texture, v_TexCoordinate);
}

我看了一些东西:

  • 使用png、jpg、bmp(565)测试,分辨率:32x32和64x64
  • 在绘制函数中,所有行glGetError()返回0
  • 加载纹理时,Sprite.texture不是0(约为70001)
  • 如果我将片段着色器更改为gl_FragColor=vec4(1.0, 0.0, 0.0, 0.5);它正在工作。

谢谢你的帮助!

共有1个答案

齐涛
2023-03-14

我已经找到了答案:

加载纹理时,我没有正确地将其传递给OpenGL。

我添加了TextureLoader。loada GLES20。glBindTexture(GLES20.GL_TEXTURE_2D,纹理[0]);像这样的线条:

...
Bitmap tex = BitmapFactory.decodeResource(context.getResources(), resource, bo);    
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
...

现在它开始工作了。

 类似资料:
  • 我有一个非常简单的OpenGL应用程序,只渲染一个带纹理的四边形。这是我的代码,效果很好(带纹理的四边形看起来很好): 然后我想介绍一个简单的着色器。所以我稍微修改了我的代码: 顶点着色器: 片段着色器: 现在我得到的只是一个黑色的四边形:-( 我已经尝试并测试了很多东西: 着色器编译良好(无错误) 有人知道为什么我在使用着色器时看不到我的纹理吗?

  • 这是代码中唯一可能有错误的部分: 你能在这段代码中看到什么错误吗?启用glEnable(GL_TEXTURE_2D)并没有什么不同。纹理坐标是正确的,片段和顶点着色器肯定是正确的。 解决了这不是问题,我仍在使用glGenerateMipmap(…)在glTexImage2D(…)之前。真正的问题是,当我的图像是GL_RGB格式时,我通过了格式GL_RGBA。另外我的t-

  • 不太确定问题发生在哪里。我在Blender有一个模型看起来是这样的: 我有它所有的UV贴图和这样的 ,蓝色高亮的边缘是从一个透明的.png纹理。下面是节点编辑器: 现在,当我按照LibGDX建议导出到.fbx时,我使用以下设置: 但当我通过fbx-convert运行它并生成我的g3dj文件时,材料显示如下: 没有图像纹理在视线内(即使当不透明度更改为1.0)。是不是有什么其他的东西我应该做,将使它

  • 我正在尝试在Android中上传pkm纹理。我能够读取图像并获得其宽度、高度 纹理加载功能: 我正在使用类似的Rajawali的ETC2Util类(https://github.com/Rajawali/Rajawali/blob/master/rajawali/src/main/java/org/rajawali3d/materials/textures/utils/ETC2Util.java)

  • 如何在平面上滚动纹理?所以我有一个平面有一个纹理,我可以使用一个着色器滚动左从右(无限)的纹理上?

  • 我有一个纹理和OpenGL的小问题。我做了个小的。obj加载器(带纹理加载)但是所有东西都是蓝色的。示例: 我加载一个纹理。我将纹理与GL11.glBindTexture(GL11.GL_TEXTURE_2D,texureId)绑定。如果我这样做了: 它画了一个白色的四边形...但是如果我这样做: 它画了一个蓝色的四边形,其他的都是蓝色的。 也许有人知道解决方案?