ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android OpenGL ES 2.0黑色纹理

2019-10-29 05:26:19  阅读:244  来源: 互联网

标签:opengl-es textures android opengl-es-2-0


以此作为开头:是的,我已经看了之前在此站点上提出的大量“ Android OpenGL ES 2.0黑色纹理”问题.不,他们都不对我的情况有所帮助.不,我不确定是否可以用适当数量的字符更好地表达标题.

我遵循了许多教程,并能够建立一个非常简单的渲染器类,以正确加载和渲染纹理(项目A).然后,我尝试在游戏引擎(项目B)中实现这个非常简单的渲染系统.一切工作完全相同,除了texture2D()由于某种原因返回黑色.我尝试了很多调试工作,并且进行了很多谷歌搜索,但都无济于事.因此,我寻求帮助.

我的顶点和片段着色器.他们在项目A中工作得很好,所以我认为这不是问题的根源,只是为了完整起见.

private static final String VERTEX_SHADER_SOURCE =
...
"attribute vec2 a_TexCoord;" +
"varying vec2 v_TexCoord;" +

"void main() {" +
"   v_TexCoord = a_TexCoord;" +
...
"}";


private static final String FRAGMENT_SHADER_SOURCE =
"precision mediump float;" +
"uniform sampler2D u_Texture;" +
"varying vec2 v_TexCoord;" +

"void main() {" +
"   gl_FragColor = texture2D(u_Texture, v_TexCoord);" +
"}";

我创建,编译这些着色器,并将它们附加到程序中,没有错误.此后,我相应地设置了句柄-我还将u_Texture设置为指向纹理单元0,因为这不会改变:

...
sTexUniformHandle = GLES20.glGetUniformLocation(sProgramHandle, "u_Texture");
sMVPHandle = GLES20.glGetUniformLocation(sProgramHandle, "u_MVPMatrix");
sPositionHandle = GLES20.glGetAttribLocation(sProgramHandle, "a_Position");
sTexCoordHandle = GLES20.glGetAttribLocation(sProgramHandle, "a_TexCoord");

GLES20.glUseProgram(sProgramHandle);
GLES20.glUniform1i(sTexUniformHandle, 0);
GLES20.glUseProgram(0);
...

然后加载纹理:

...
int[] texData = Utils.createTexture(context, resId);
mTexDataHandle = texData[0];
...
public static int[] createTexture(Context context, int resId) { // returns {textureHandle, width, height}
    int width = -1;
    int height = -1;

    int[] texHandle = new int[1];
    GLES20.glGenTextures(1, texHandle, 0);

    if (texHandle[0] != 0) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inScaled = false;

        final Bitmap bm = BitmapFactory.decodeResource(context.getResources(), resId, opts);
        width = bm.getWidth();
        height = bm.getHeight();

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texHandle[0]);

        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);
        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);

        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bm, 0);

        bm.recycle();
    }

    if (texHandle[0] == 0) {
        throw new RuntimeException("texture load error");
    }

    return new int[]{texHandle[0], width, height};
}

即使我的纹理是32 x 19,我也不需要在项目A中设置纹理包裹.我将纹理更改为32 x 32并设置纹理包裹以夹紧,以防万一,所以没有人会告诉我这是我的错误.位图正在加载-我写了宽度,高度和一些要调试的选择像素,然后就可以找到它们了.

在我的draw方法中,启用a_TexCoord属性并将其指向数据:

...
GLES20.glEnableVertexAttribArray(sTexCoordHandle);
...
GLES20.glVertexAttribPointer(sTexCoordHandle, mTexCoordDataSize, GLES20.GL_FLOAT, false, 0, mTexCoordBuffer);
...

我将整个mTexCoordBuffer写出到调试消息中,并正确加载了纹理坐标数据.

最后,我将活动纹理单元设置为0,将其纹理数据绑定到该单元,然后绘制:

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

GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
...

对于整个图形库我还是很陌生,但是我已经竭尽全力去理解这里实际发生的事情.我以为我了解全部,但是事实显然并非如此.据我所知,着色器正常工作-黑色矩形正好出现在应有的位置(在项目A中也是如此).我传入的纹理坐标数据与项目A中的数据完全相同,并且我对它的加载方式没有任何更改.这将实际的纹理数据留给主要怀疑者,但是我尝试像在项目A中一样进行设置,这似乎是正确的.如果有人比我更有能力指出我的错误,我将不胜感激.

解决方法:

las,我知道这将是值得面对的事情.尽管我想我应该尽快发现错误,并且确实理解了我正在使用的GLES代码,但我对此感到很高兴.另一方面,我显然不了解Java的基础知识.

无论如何,事实证明,我当时正在Renderer和GameState类的构造函数中做很多事情,这些事情我当时不应该做.我在GameState中创建了一个allocateGameState()方法,并在我的渲染器的onSurfaceCreated()中对其进行了调用;问题解决了.

我仍然感到困惑的部分是:我发现这是我的错误,方法是返回项目A并更改代码,直到它模仿项目B.最后,我很幸运,并且犯了同样的错误,即滥用渲染器的构造函数以实例化纹理/着色器/程序数据.但是,这一次,我为以下错误所困扰:“在没有当前上下文的情况下调用OpenGl ES API”.我很快解决了这个问题,并对项目B应用了相同的修复程序,但是这让我想知道为什么我在项目B中没有遇到相同的错误.

标签:opengl-es,textures,android,opengl-es-2-0
来源: https://codeday.me/bug/20191029/1957816.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有