Загрузить изображения в Google Картон

Я пытаюсь создать 3D-просмотрщик картинок, такой же, как в демонстрации Google Картон. Он считывает изображение с диска и отображает его по-разному для каждого глаза, чтобы достичь 3D-эффекта.

Я на первом этапе пытаюсь получить одно и то же изображение для обоих глаз. Из-за других ограничений я использую Google картон Android SDK вместо Unity SDK.

Я изменил код, основываясь на замечательном картонном прозрачном проекте камеры ( https://github.com/Sveder/CardboardPassthrough

Как показать 2 камеры предварительного просмотра рядом?[Для картонных приложений]

), которая передает данные с камеры на картон.

Во всяком случае, после изменения кода. Я не могу заставить изображения отображаться, хотя opengl и android не показывают никаких ошибок. Моя основная идея заключается в следующем:

  1. использовать Android BitmapFactory для чтения изображений, сохраненных в res / to bitmap.
  2. Для каждого кадра используйте GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0), чтобы привязать это изображение к текущей активной текстуре opengl GLES20.GL_TEXTURE0
  3. показать такое изображение

Поэтому в функции 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) {
    }
}

Опять же, я не вижу никаких ошибок. Экран просто черный, ничего не показывая.

0 ответов

Другие вопросы по тегам