Android OpenGLES 2.0纹理映射不起作用

时间:2013-03-10 23:56:21

标签: android graphics opengl-es-2.0 texture-mapping

我正在尝试将一些四边形纹理贴图。我可以用纯色渲染四边形。我一直在关注这个页面: http://www.learnopengles.com/android-lesson-four-introducing-basic-texturing/

所有内容都会编译并运行,但纹理根本就没有应用。 我的代码和链接页面之间的唯一区别是我不做glBindAttribLocation,而是使用glDrawElements而不是glDrawArrays。

编辑:转换我的顶点和tex坐标数据以使用glDrawArrays没有修复任何东西。

我的所有着色器手柄似乎都是正确的。问题必须出在我的一个平局中。如果有人可以帮我调试这个,那就太好了。我试过设置gl_FragColor = vec4(texCoord [0],texCoord [1],1.0f,1.0f)只是为了看看tex坐标是否正在进入着色器但是崩溃了。

顶点数据的初始化:

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

在我的附加着色器代码中:

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

在我的主要(ParticleEngine)画中:

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

在单个粒子绘制中:

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

在我的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];
}

在我的着色器中:

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;" +
    "}";

2 个答案:

答案 0 :(得分:6)

解决: Android OpenGL2.0 showing black textures

需要添加2条线来加载_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);

如果纹理大小不是2的幂,则需要这样做。

答案 1 :(得分:0)

对于任何来到iOS的人来说,这里提供的其他答案也适用。唯一不同的是命令是这样的:

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

另外,请确保启用过滤:

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

我认为在2D中没那么实用,但你需要它们