纹理的android示例

时间:2017-02-17 10:13:43

标签: opengl-es

我正在研究OpenGLES,并尝试在我的项目上添加纹理方块。 我设计了一个简单的纹理方形类,我尝试显示它。我的三角形在Rendered类中调用。目前,TexturedSquare类只显示一个空位图。

package com.example.nativecpp;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

public class TexturedSquare {

    private static int[] textureHandle;

    private final String vertexShaderCode =
    "uniform mat4 uMVPMatrix;\n" +
            "attribute vec2 aPosition;\n" +
            "attribute vec2 aTexPos;\n" +
            "varying vec2 vTexPos;\n" +
            "void main() {\n" +
            "  vTexPos = aTexPos;\n" +
            "  gl_Position = uMVPMatrix * vec4(aPosition.xy, 0.0, 1.0);\n" +
            "}";

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

    private final FloatBuffer vertexBuffer;
    private final ShortBuffer drawListBuffer;
    private final int mProgram;
    private int mPositionHandle;
    private int mTexturePosHandle;
    private int mColorHandle;
    private int mMVPMatrixHandle;


    // number of coordinates per vertex in this array
    final int COORDS_PER_VERTEX = 4;
    float squareCoords[] = {
            -1.0f,-1.0f,        0.0f, 0.0f, // vertex 3
            -1.0f, 1.0f,        0.0f, 1.0f, // vertex 1
            1.0f,-1.0f,        1.0f, 0.0f, // vertex 2
            1.0f, 1.0f,        1.0f, 1.0f, // vertex 0
    }; // top right

    private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices

    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    float color[] = { 0.2f, 0.709803922f, 0.898039216f, 1.0f };

    /**
     * Sets up the drawing object data for use in an OpenGL ES context.
     */
    public TexturedSquare() {
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
        // (# of coordinate values * 4 bytes per float)
                squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.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);

        // prepare shaders and OpenGL program
        int vertexShader = MyGLRenderer.loadShader(
                GLES20.GL_VERTEX_SHADER,
                vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(
                GLES20.GL_FRAGMENT_SHADER,
                fragmentShaderCode);

        mProgram = GLES20.glCreateProgram();             // create empty OpenGL Program
        GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
        GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
        GLES20.glLinkProgram(mProgram);                  // create OpenGL program executables


    }


    public  int loadTexture()
    {
        textureHandle = new int[1];
if (textureHandle[0] != -1)
{
            GLES20.glGenTextures(1, textureHandle, 0);

            int uTexture = GLES20.glGetAttribLocation(mProgram, "uTexture");

            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false;   // No pre-scaling

            // Read in the resource
            Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
            Bitmap bitmap = Bitmap.createBitmap(640, 480, conf); // this creates a MUTABLE 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);

            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
            GLES20.glUniform1i(uTexture, 0);

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

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

        return textureHandle[0];
    }


    /**
     * Encapsulates the OpenGL ES instructions for drawing this shape.
     *
     * @param mvpMatrix - The Model View Project matrix in which to draw
     * this shape.
     */
    public void draw(float[] mvpMatrix) {

        // Add program to OpenGL environment
        GLES20.glUseProgram(mProgram);

        // get handle to vertex shader's vPosition member
        mPositionHandle     = GLES20.glGetAttribLocation(mProgram, "aPosition");
        mTexturePosHandle   = GLES20.glGetAttribLocation(mProgram, "aTexPos");

        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        MyGLRenderer.checkGlError("glGetUniformLocation");

        // Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer(
                mPositionHandle, 2,
                GLES20.GL_FLOAT, false,
                vertexStride, vertexBuffer);

        GLES20.glEnableVertexAttribArray(mTexturePosHandle);

        GLES20.glVertexAttribPointer(
                mPositionHandle, 2,
                GLES20.GL_FLOAT, false,
                vertexStride, (vertexBuffer.position(2)));

        // get handle to shape's transformation matrix
        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        MyGLRenderer.checkGlError("glGetUniformLocation");

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
        MyGLRenderer.checkGlError("glUniformMatrix4fv");

        // Draw the square
        GLES20.glDrawElements(
                GLES20.GL_TRIANGLES, drawOrder.length,
                GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

}

我的程序因该错误而崩溃:

FATAL EXCEPTION: GLThread 6633
                                                                                  Process: com.example.nativecpp, PID: 3281
                                                                           java.lang.RuntimeException: glGetUniformLocation: glError 1282
                                                                                     at com.example.nativecpp.MyGLRenderer.checkGlError(MyGLRenderer.java:198)
                                                                                      at com.example.nativecpp.TexturedSquare.draw(TexturedSquare.java:179)
                                                                                      at com.example.nativecpp.MyGLRenderer.onDrawFrame(MyGLRenderer.java:118)
                                                                                      at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1553)
                                                                                      at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1253)

我的顶点位置索引似乎有误,但我无法解决。

编辑: 我仍然有同样的错误:

MyGLRenderer: glGetUniformLocation: glError 1282

之后出现错误:

GLES20.glVertexAttribPointer(
        mPositionHandle, 2,
        GLES20.GL_FLOAT, false,
        vertexStride, vertexBuffer);

GLES20.glEnableVertexAttribArray(mPositionHandle);
MyGLRenderer.checkGlError("glGetUniformLocation"); ####ERROR!!!

编辑2: 在那一行:       uTexture = GLES20.glGetAttribLocation(mProgram," uTexture"); uTexture = -1我不认为这是正常的...所以我把它改成

int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture");

现在uTexture等于1,但程序仍然停留在GLES20.glUniform1i(uTexture, 0); //glGetUniformLocation: glError 1282

编辑3: 当我将这些行放在绘图函数中时:

   int uTexture = GLES20.glGetUniformLocation(mProgram, "uTexture");
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
            MyGLRenderer.checkGlError("glGetUniformLocation");
            GLES20.glUniform1i(uTexture, 0);
            MyGLRenderer.checkGlError("glGetUniformLocation");

            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
            // Draw the square

没有错误......为什么? GPU没有时间将数据存入内存?

1 个答案:

答案 0 :(得分:0)

您不小心加载了position属性中的纹理坐标。改变

    GLES20.glVertexAttribPointer(
            mPositionHandle, 2,
            GLES20.GL_FLOAT, false,
            vertexStride, (vertexBuffer.position(2)));

    GLES20.glVertexAttribPointer(
            mTexturePosHandle, 2,
            GLES20.GL_FLOAT, false,
            vertexStride, (vertexBuffer.position(2)));

几个值得注意的“错误”:

你应该只获得一次属性位置,每帧一次,因为它是一个costy函数。

你没有对纹理做任何事情,如果它具有标识0,虽然它仍然有效,你应该检查标识-1

链接着色器程序时可能会出现问题。应该检查链接状态是否错误,并记录glGetProgramInfoLog的输出。