Android 将图像加载到谷歌硬纸板中

Android 将图像加载到谷歌硬纸板中,android,image,opengl-es,google-cardboard,Android,Image,Opengl Es,Google Cardboard,我正试图建立一个3D图片查看器,就像谷歌纸板演示一样。它从磁盘读取图像,并对每只眼睛进行稍微不同的显示,以实现3D效果 我正处于尝试让同一个图像出现在双眼的第一步。由于其他限制,我使用谷歌纸板android SDK而不是unity SDK 我根据一个很棒的纸板相机透视项目修改了代码( ),将相机数据流式传输到硬纸板 无论如何,在修改代码之后。虽然opengl和android没有显示任何错误,但我无法显示图像。我的基本想法如下: 使用android BitmapFactory将存储在res/中

我正试图建立一个3D图片查看器,就像谷歌纸板演示一样。它从磁盘读取图像,并对每只眼睛进行稍微不同的显示,以实现3D效果

我正处于尝试让同一个图像出现在双眼的第一步。由于其他限制,我使用谷歌纸板android SDK而不是unity SDK

我根据一个很棒的纸板相机透视项目修改了代码(

),将相机数据流式传输到硬纸板

无论如何,在修改代码之后。虽然opengl和android没有显示任何错误,但我无法显示图像。我的基本想法如下:

  • 使用android BitmapFactory将存储在res/中的图像读取为位图
  • 对于每个帧,使用GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,img,0)将该图像绑定到当前opengl活动纹理GLES20.GL_TEXTURE0
  • 显示这样的图像
  • 所以在函数onDrawEye中,我将当前活动纹理设置为GL_TEXTURE0,然后将图像纹理绑定到GL_texture_2D。 onDrawEye代码:

        public void onDrawEye(EyeTransform transform) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        // Bind the texture to this unit.
        bindBitmap2D(texture);
        checkGLError("bind bit map 2d");
    
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "position");
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
                false, vertexStride, vertexBuffer);
    
        mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
        GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
        GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
                false, vertexStride, textureVerticesBuffer);
    
        mColorHandle = GLES20.glGetAttribLocation(mProgram, "s_texture");
    }
    
    函数bindBitmap2D:

        public void bindBitmap2D(int texture) {
        //must be GL_TEXTUREi
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        checkGLError("glActiveTexture");
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
        checkGLError("glbindtexture");
        // 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);
    
        Bitmap img = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        //convert bitmap to texture and bind the texture to GL_TEXTURE_2D
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
    }
    
    我的片段着色器:

    private final String fragmentShaderCode2D =
            "precision mediump float;\n" +
                    "varying vec2 textureCoordinate;                            \n" +
                    "uniform sampler2D s_texture;               \n" +
                    "void main(void) {" +
                    "  gl_FragColor = texture2D( s_texture, textureCoordinate );\n" +
                    "}";
    
    以下是我的完整代码:

    package com.sveder.cardboardpassthrough;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.SurfaceTexture;
    import android.graphics.SurfaceTexture.OnFrameAvailableListener;
    import android.opengl.GLES20;
    import android.opengl.GLUtils;
    import android.os.Bundle;
    import android.util.Log;
    
    import com.google.vrtoolkit.cardboard.*;
    
    import javax.microedition.khronos.egl.EGLConfig;
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.FloatBuffer;
    import java.nio.ShortBuffer;
    
    public class MainActivity extends CardboardActivity
            implements CardboardView.StereoRenderer, OnFrameAvailableListener {
    
        private static final String TAG = "MainActivity";
    
        private final String vertexShaderCode =
                "attribute vec4 position;" +
                        "attribute vec2 inputTextureCoordinate;" +
                        "varying vec2 textureCoordinate;" +
                        "void main()" +
                        "{" +
                        "gl_Position = position;" +
                        "textureCoordinate = inputTextureCoordinate;" +
                        "}";
    
        //TODO vec4 maybe? sampler 2d?
        // pandora box
        private final String fragmentShaderCode2D =
                "precision mediump float;\n" +
                        "varying vec2 textureCoordinate;                            \n" +
                        "uniform sampler2D s_texture;               \n" +
                        "void main(void) {" +
                        "  gl_FragColor = texture2D( s_texture, textureCoordinate );\n" +
                        "}";
    
        private FloatBuffer vertexBuffer, textureVerticesBuffer, vertexBuffer2;
        private ShortBuffer drawListBuffer, buf2;
        private int mProgram;
        private int mPositionHandle, mPositionHandle2;
        private int mColorHandle;
        private int mTextureCoordHandle;
    
    
        // number of coordinates per vertex in this array
        static final int COORDS_PER_VERTEX = 2;
        static float squareVertices[] = { // in counterclockwise order:
                -1.0f, -1.0f,   // 0.left - mid
                1.0f, -1.0f,   // 1. right - mid
                -1.0f, 1.0f,   // 2. left - top
                1.0f, 1.0f,   // 3. right - top
        };
    
        private short drawOrder[] = {0, 2, 1, 1, 2, 3}; // order to draw vertices
    
        static float textureVertices[] = {
                0.0f, 1.0f,  // A. left-bottom
                1.0f, 1.0f,  // B. right-bottom
                0.0f, 0.0f,  // C. left-top
                1.0f, 0.0f   // D. right-top
        };
    
        private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
    
        private ByteBuffer indexBuffer;    // Buffer for index-array
    
        private int texture;
    
        private CardboardOverlayView mOverlayView;
    
        private CardboardView cardboardView;
        private SurfaceTexture surface;
        private float[] mView;
    
        public void bindBitmap2D(int texture) {
            //must be GL_TEXTUREi
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            checkGLError("glActiveTexture");
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
            checkGLError("glbindtexture");
            // 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);
    
            Bitmap img = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
            //convert bitmap to texture and bind the texture to GL_TEXTURE_2D
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
        }
    
        private int createTexture2D() {
            int[] texture = new int[1];
            GLES20.glGenTextures(1, texture, 0);
            return texture[0];
        }
    
    
        /**
         * Converts a raw text file, saved as a resource, into an OpenGL ES shader
         *
         * @param type  The type of shader we will be creating.
         * @param resId The resource ID of the raw text file about to be turned into a shader.
         * @return
         */
        private int loadGLShader(int type, String code) {
            int shader = GLES20.glCreateShader(type);
            GLES20.glShaderSource(shader, code);
            GLES20.glCompileShader(shader);
            // Get the compilation status.
            final int[] compileStatus = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
    
            // If the compilation failed, delete the shader.
            if (compileStatus[0] == 0) {
                Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shader));
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
            if (shader == 0) {
                throw new RuntimeException("Error creating shader.");
            }
            return shader;
        }
    
        private static void checkGLError(String func) {
            int error;
            while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
                Log.e(TAG, func + ": glError " + error);
                throw new RuntimeException(func + ": glError " + error);
            }
        }
    
        /**
         * Sets the view to our CardboardView and initializes the transformation matrices we will use
         * to render our scene.
         *
         * @param savedInstanceState
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.common_ui);
            cardboardView = (CardboardView) findViewById(R.id.cardboard_view);
            cardboardView.setRenderer(this);
            setCardboardView(cardboardView);
    
            mView = new float[16];
            mOverlayView = (CardboardOverlayView) findViewById(R.id.overlay);
            mOverlayView.show3DToast("test");
        }
    
        @Override
        public void onRendererShutdown() {
            Log.i(TAG, "onRendererShutdown");
        }
    
        @Override
        public void onSurfaceChanged(int width, int height) {
            Log.i(TAG, "onSurfaceChanged");
        }
    
        /**
         * Creates the buffers we use to store information about the 3D world. OpenGL doesn't use Java
         * arrays, but rather needs data in a format it can understand. Hence we use ByteBuffers.
         *
         * @param config The EGL configuration used when creating the surface.
         */
        @Override
        public void onSurfaceCreated(EGLConfig config) {
            Log.i(TAG, "onSurfaceCreated");
            GLES20.glClearColor(0.1f, 0.1f, 0.1f, 0.5f); // Dark background so text shows up well
    
            ByteBuffer bb = ByteBuffer.allocateDirect(squareVertices.length * 4);
            bb.order(ByteOrder.nativeOrder());
            vertexBuffer = bb.asFloatBuffer();
            vertexBuffer.put(squareVertices);
            vertexBuffer.position(0);
    
            ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
            dlb.order(ByteOrder.nativeOrder());
            drawListBuffer = dlb.asShortBuffer();
            drawListBuffer.put(drawOrder);
            drawListBuffer.position(0);
    
            ByteBuffer bb2 = ByteBuffer.allocateDirect(textureVertices.length * 4);
            bb2.order(ByteOrder.nativeOrder());
            textureVerticesBuffer = bb2.asFloatBuffer();
            textureVerticesBuffer.put(textureVertices);
            textureVerticesBuffer.position(0);
    
            // use shader to process and load images
            int vertexShader = loadGLShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
            int fragmentShader = loadGLShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode2D);
    
            mProgram = GLES20.glCreateProgram();             // create empty OpenGL ES Program
            GLES20.glAttachShader(mProgram, vertexShader);   // add the vertex shader to program
            GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
            GLES20.glLinkProgram(mProgram);
    
            Log.d(TAG, "start binding picture");
            texture = createTexture2D();
            System.out.println("texture id: " + texture);
            bindBitmap2D(texture);
            checkGLError("onsurfacecreated");
        }
    
        /**
         * Prepares OpenGL ES before we draw a frame.
         *
         * @param headTransform The head transformation in the new frame.
         */
        @Override
        public void onNewFrame(HeadTransform headTransform) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            bindBitmap2D(texture);
            GLES20.glUseProgram(mProgram);
        }
    
        @Override
        public void onFrameAvailable(SurfaceTexture arg0) {
            this.cardboardView.requestRender();
        }
    
        /**
         * Draws a frame for an eye. The transformation for that eye (from the camera) is passed in as
         * a parameter.
         *
         * @param transform The transformations to apply to render this eye.
         */
        @Override
        public void onDrawEye(EyeTransform transform) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            // Bind the texture to this unit.
            bindBitmap2D(texture);
            checkGLError("bind bit map 2d");
    
            mPositionHandle = GLES20.glGetAttribLocation(mProgram, "position");
            GLES20.glEnableVertexAttribArray(mPositionHandle);
            GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
                    false, vertexStride, vertexBuffer);
    
            mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
            GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
            GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
                    false, vertexStride, textureVerticesBuffer);
    
            mColorHandle = GLES20.glGetAttribLocation(mProgram, "s_texture");
        }
    
        @Override
        public void onFinishFrame(Viewport viewport) {
        }
    }
    
    再说一次,我没有看到任何错误。屏幕是黑色的,没有显示任何内容