【问题标题】:Android OpenGLES 2.0 Texture Mapping Does Not WorkAndroid OpenGLES 2.0 纹理映射不起作用
【发布时间】:2013-03-10 23:56:21
【问题描述】:

我正在尝试对一些四边形进行纹理贴图。我可以用纯色渲染四边形就好了。我一直在关注这个页面: 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);

在我的主要(粒子引擎)绘图中:

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

【问题讨论】:

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


    【解决方案1】:

    已解决: Android OpenGL2.0 showing black textures

    需要向 LOAD_TEXTURE 添加 2 行: 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 的幂,那么这是必需的。

    【讨论】:

    • 并非每个 GPU 都支持 NPOT 纹理。您必须检查 GL_ARB_texture_non_power_of_twoGL_OES_texture_npot 扩展才能安全地使用 NPOT 纹理。如果可能,请避免使用 NPOT 尺寸。
    【解决方案2】:

    对于来到这里的 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 中不太实用,但你需要它们

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 2017-11-26
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      相关资源
      最近更新 更多