1

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

在我的加载纹理中:

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

2 回答 2

6

已解决: Android OpenGL2.0 显示黑色纹理

需要向 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 的幂,则这是必需的。

于 2013-03-11T00:12:51.747 回答
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 中不太实用,但你需要它们

于 2013-12-01T02:29:00.750 回答