【问题标题】:Android OpenGL ES 2.0 black texturesAndroid OpenGL ES 2.0 黑色纹理
【发布时间】:2013-04-13 18:52:43
【问题描述】:

我正在 Android 上学习 gles2.0(我是新手 :)),我想画一个有纹理的正方形,但我做不到。我google了很多,但我找不到答案,我只得到一个黑色方块。

我设置了一个 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);
    }

}

精灵类:

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);它正在工作。

感谢您的帮助!

【问题讨论】:

    标签: android opengl-es textures


    【解决方案1】:

    我已经找到答案了:

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

    我添加了 TextureLoader.loadTexture 一个 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[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);
    ...
    

    现在可以了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多