Bản đồ họa tiết Android OpenGLES 2.0 không hoạt động (Android OpenGLES 2.0 Texture Mapping Does Not Work)


問題描述

Bản đồ họa tiết Android OpenGLES 2.0 không hoạt động (Android OpenGLES 2.0 Texture Mapping Does Not Work)

I'm trying to texture map some quads. I can render the quads with solid colors just fine. I've been following this page: http://www.learnopengles.com/android‑lesson‑four‑introducing‑basic‑texturing/

Everything compiles and runs, but the texture is simply not being applied. The only difference between my code and the page linked is that I do not do glBindAttribLocation, and I use glDrawElements instead of glDrawArrays.

EDIT: Converting my vertex and tex coord data to use glDrawArrays did not fix anything.

All of my shader handles seem correct. The problem must be in one of my draws. If anyone can help me debug this, that would be great. I've tried setting gl_FragColor = vec4(texCoord[0], texCoord[1], 1.0f, 1.0f) just to see if tex coordinates are making it to the shader but that crashes.

Initialization of vertex data:

static float squareCoords[] = { ‑0.5f,  0.5f, 0.0f,   // top left
                                ‑0.5f, ‑0.5f, 0.0f,   // bottom left
                                 0.5f, ‑0.5f, 0.0f,   // bottom right
                                 0.5f,  0.5f, 0.0f }; // top right
static float textureCoords[] = { 0.0f, 1.0f,  // top left
                                 0.0f, 0.0f,  // bottom left
                                 1.0f, 0.0f,  // bottom right
                                 1.0f, 1.0f}; // top right


    // initialize vertex byte buffer for shape coordinates
    ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); // (# of coordinate values * 4 bytes per float)
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(squareCoords);
    vertexBuffer.position(0);

    ByteBuffer tcbb = ByteBuffer.allocateDirect(textureCoords.length * 4);
    tcbb.order(ByteOrder.nativeOrder());
    texCoordBuffer = tcbb.asFloatBuffer();
    texCoordBuffer.put(textureCoords);
    texCoordBuffer.position(0);

    // initialize byte buffer for the draw list
    ByteBuffer dlb = ByteBuffer.allocateDirect(
    // (# of coordinate values * 2 bytes per short)
            drawOrder.length * 2);
    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer = dlb.asShortBuffer();
    drawListBuffer.put(drawOrder);
    drawListBuffer.position(0);

In my attach shader code:

    // get handle to texture coords
    mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "texCoord");
    MyGLRenderer.checkGlError("glGetAttribLocation");
    Log.i("TEXCOORD SHADER HANDLE", " " + mTexCoordHandle);

    //get handle to texture
    mTexHandle = GLES20.glGetUniformLocation(mProgram, "u_texture");
    MyGLRenderer.checkGlError("glGetUniformLocation");
    Log.i("TEX SHADER HANDLE", " " + mTexHandle);

In my main (ParticleEngine) draw:

    // Enable a handle to the triangle vertices
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                                 GLES20.GL_FLOAT, false,
                                 0, vertexBuffer);
    GLES20.glEnableVertexAttribArray(mTexCoordHandle);
    GLES20.glVertexAttribPointer(mTexCoordHandle, TEX_COORDS_PER_VERTEX,
                                 GLES20.GL_FLOAT, false,
                                 0, texCoordBuffer);

    // Set the active texture unit to texture unit 0.
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

    // Bind the texture to this unit.
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureDataHandle);

    // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
    GLES20.glUniform1i(mTexHandle, 0);  

    for (int t=0;t<mChildsCount;t++) {
        Particle child = (Particle)mChilds[t];
        child.draw(mVMatrix, mProjMatrix);
    }
    // Disable vertex array
    GLES20.glDisableVertexAttribArray(mPositionHandle);
    GLES20.glDisableVertexAttribArray(mTexCoordHandle);

In an individual particles draw:

//... calculate model‑view‑projection matrix, send to shader
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mPEngine.drawOrder.length,
                          GLES20.GL_UNSIGNED_SHORT, mPEngine.drawListBuffer);

In my load_texture:

public static int loadTexture(final Context context, final int resourceId)
{
    final int[] textureHandle = new int[1];

    GLES20.glGenTextures(1, textureHandle, 0);

    if (textureHandle[0] != 0)
    {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;   // No pre‑scaling

        // Read in the resource
        final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
        if (bitmap == null) {
            throw new RuntimeException("Error decoding bitmap");
        }
        // Bind to the texture in OpenGL
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);

        // Set filtering
        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);

        // Load the bitmap into the bound texture.
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

        // Recycle the bitmap, since its data has been loaded into OpenGL.
        bitmap.recycle();
    }

    if (textureHandle[0] == 0)
    {
        throw new RuntimeException("Error loading texture.");
    }

    return textureHandle[0];
}

In my shaders:

private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
    "uniform mat4 uMVPMatrix;" +
    "attribute vec4 vPosition;" +
    "attribute vec2 texCoord;" +
    "varying vec2 texCoordOut;" +
    "void main() {" +
    // the matrix must be included as a modifier of gl_Position
    "  texCoordOut = texCoord; \n" +
    "  gl_Position = uMVPMatrix * vPosition; \n" +
    "}";

private final String fragmentShaderCode =
    "precision mediump float;" +
    "varying vec2 texCoordOut;" +
    "uniform sampler2D u_texture;" +
    "void main() {" +
    " vec4 texColor = texture2D(u_texture, texCoordOut);\n" +
    "  gl_FragColor = texColor;" +
    "}";

參考解法

方法 1:

SOLVED: Android OpenGL2.0 showing black textures

NEEDED TO ADD 2 LINES TO LOAD_TEXTURE: GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);             GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

Turns out that is required if your texture sizes are not powers of 2.

方法 2:

For anyone who is coming here for the iOS side of this, the other answer provided here also applies. Only difference is the commands are like this:

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Also, make sure that you enable filtering:

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

which I didn't think was so practical in 2D, but you need them

(by jknightjknightSerguei Fedorov)

參考文件

  1. Android OpenGLES 2.0 Texture Mapping Does Not Work (CC BY‑SA 3.0/4.0)

#graphics #Android #opengl-es-2.0 #texture-mapping






相關問題

OpenGL等圖形庫的目的是什麼? (What is the purpose of a graphics library such as OpenGL?)

Blender: Kubus Mustahil (Blender: Impossible Cube)

隨機移動的圖像被屏幕的左上角吸引 (Randomly moving images are attracted by the top-left corner of the screen)

Bản đồ họa tiết Android OpenGLES 2.0 không hoạt động (Android OpenGLES 2.0 Texture Mapping Does Not Work)

用於顯示位圖和處理按鈕按下的簡單框架 (Simple Frameworks for Displaying Bitmaps and Handling Button Presses)

繪製後如何填充多邊形 (How to fill a polygon after drawing)

Java Swing/Graphics - repaint() 或 validate() 不起作用? (Java Swing/Graphics - repaint() or validate() doesn't work?)

繪製多邊形:找不到錯誤 (Drawing Polygon : unable to find error)

半透明 JButton:對像出現在背景中 (Semi-Transparent JButton: Objects appear in Background)

更改 BufferedImage 的 alpha 值? (Change the alpha value of a BufferedImage?)

圖像處理公式可生成類似通過 Mac 相機拍攝的照片的效果 (Image manipulation formula to generate effects like pictures taken via Mac's camera)

如何在 MATLAB 中為一組向量的旋轉設置動畫? (How do I animate the rotation of a set of vectors in MATLAB?)







留言討論