Intereting Posts
Android TextUtils isEmpty vs String.isEmpty Как получить ссылку на LocationManager внутри фрагмента Facebook, setReadPermissions и setPublishPermissions Как найти использование памяти моего приложения для Android, написанного на C ++, с использованием NDK Как установить разрешение камеры в Android с OpenCV? Как воспроизвести звук родной камеры на Android Android Gradle Не удалось зарезервировать достаточно места для кучи объектов Как печатать PDF с помощью платформы Android 4.4 Активность Android в диалоге, но без заголовка Ошибка получения родительского элемента для элемента: ресурс не найден, который соответствует указанному имени после обновления до AppCompat v23 Получение контекста в AsyncTask Менеджер пакетов умер Android Как добавить собственный XML-файл в res / values ​​и как зарегистрировать customvalues.xml с помощью системы Записанное видео на 90 градусов повернуто после загрузки в Интернет Android-загрузчики, путь?

Использование видеопотока как открытая текстура GL ES 2.0

Я пытаюсь захватить видео и отобразить его на экране, установив текстуру Open GL ES на surfaceTexture Android. Я не могу использовать TextureView и реализовать SurfaceTextureListener в соответствии с этим руководством, поскольку я использую Google Cardboard.

Я следил за документацией Android о том, как инициализировать Open GL ES 2.0 и использовать его, а также этот учебник по текстурированию.

Поместив 2 вместе, я получаю пустой экран и иногда получаю <core_glBindTexture:572>: GL_INVALID_OPERATION в окне консоли.

Я не знаю, чего не знаю, но я не могу отлаживать или просто понимать, можно ли использовать этот подход. Вот мой код чертежа, он инициализируется в onSurfaceCreated() класса MainActivity и сделан из onEyeDraw() который является функцией onEyeDraw() Cardboard.

 package com.example.rich.test3; import android.hardware.Camera; import android.opengl.GLES20; import android.view.TextureView; import java.nio.ShortBuffer; import java.nio.FloatBuffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * Created by rich on 03/05/2015. */ public class Square { private java.nio.FloatBuffer vertexBuffer; private java.nio.ShortBuffer drawListBuffer; private final java.nio.FloatBuffer mCubeTextureCoordinates; float color[] = { 1.f, 1.f, 1.f, 1.0f }; private final String vertexShaderCode = "attribute vec4 vPosition;" + "attribute vec2 a_TexCoordinate;" + "varying vec2 v_TexCoordinate;" + "void main() {" + " gl_Position = vPosition;" + " v_TexCoordinate = a_TexCoordinate;" + "}"; private final String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "uniform sampler2D u_Texture;" + "varying vec2 v_TexCoordinate;" + "void main() {" + "gl_FragColor = (texture2D(u_Texture, v_TexCoordinate));" + "}"; // number of coordinates per vertex in this array static final int COORDS_PER_VERTEX = 3; static float squareCoords[] = { -0.5f, -0.5f, 0.0f, // bottom left 0.5f, -0.5f, 0.0f, // bottom right -0.5f, 0.5f, 0.0f, // top left 0.5f, 0.5f, 0.0f}; // top right private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices private int mProgram; private int mPositionHandle; private int mColorHandle; private int mTextureUniformHandle; private int mTextureCoordinateHandle; private final int mTextureCoordinateDataSize = 2; private final int vertexCount = squareCoords.length / COORDS_PER_VERTEX; private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex private int mTextureDataHandle; float textureCoordinates[] = {0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; Camera _camera; TextureView _textureView; int[] textures; android.graphics.SurfaceTexture _surface; public Square() { 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); mCubeTextureCoordinates = ByteBuffer.allocateDirect(textureCoordinates.length * 4) .order(ByteOrder.nativeOrder()).asFloatBuffer(); mCubeTextureCoordinates.put(textureCoordinates).position(0); // create empty OpenGL ES Program mProgram = GLES20.glCreateProgram(); textures = new int[1]; GLES20.glGenTextures(1, textures, 0); _surface = new android.graphics.SurfaceTexture(textures[0]); _camera = Camera.open(); Camera.Size previewSize = _camera.getParameters().getPreviewSize(); try { _camera.setPreviewTexture(_surface); } catch (java.io.IOException ex) { // Console.writeLine (ex.Message); } final int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); GLES20.glShaderSource(vertexShaderHandle, vertexShaderCode); GLES20.glCompileShader(vertexShaderHandle); final int[] compileStatus = new int[1]; GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0); if (compileStatus[0] == 0) { //do check here } final int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); GLES20.glShaderSource(fragmentShaderHandle, fragmentShaderCode); GLES20.glCompileShader(fragmentShaderHandle); GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0); if (compileStatus[0] == 0) { //do check here } GLES20.glAttachShader(mProgram, vertexShaderHandle); GLES20.glAttachShader(mProgram, fragmentShaderHandle); GLES20.glBindAttribLocation(mProgram, 0, "a_Position"); GLES20.glBindAttribLocation(mProgram, 0, "a_TexCoordinate"); GLES20.glLinkProgram(mProgram); final int[] linkStatus = new int[1]; GLES20.glGetProgramiv(mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0); if (linkStatus[0] == 0) { //do check here } GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]); mTextureDataHandle = textures[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); } public void draw() { _surface.updateTexImage(); GLES20.glUseProgram(mProgram); mTextureUniformHandle = GLES20.glGetUniformLocation(mProgram, "u_Texture"); mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position"); mColorHandle = GLES20.glGetAttribLocation(mProgram, "a_Color"); mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoordinate"); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle); GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates); GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); GLES20.glEnableVertexAttribArray(mPositionHandle); GLES20.glUniform1i(mTextureUniformHandle, 0); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount); GLES20.glDisableVertexAttribArray(mPositionHandle); } } 

Solutions Collecting From Web of "Использование видеопотока как открытая текстура GL ES 2.0"

При визуализации объекта текстуры SurfaceTexture вам нужно использовать GL_TEXTURE_EXTERNAL_OES текстуры GL_TEXTURE_EXTERNAL_OES :

Объект текстуры использует объект текстуры GL_TEXTURE_EXTERNAL_OES, который определяется GL_OES_EGL_image_external расширением OpenGL ES. Это ограничивает использование текстуры. Каждый раз, когда текстура привязана, она должна быть привязана к цели GL_TEXTURE_EXTERNAL_OES, а не к цели GL_TEXTURE_2D. Кроме того, любой шейдер OpenGL ES 2.0, который образцы из текстуры должны объявить о своем использовании этого расширения, используя, например, директиву #extension GL_OES_EGL_image_external: require. Такие шейдеры также должны получить доступ к текстуре с помощью пробоотборника samplerExternalOES GLSL.

Таким образом, вам нужно изменить свой шейдер фрагмента следующим образом, добавив объявление #extension и объявив свою форму текстуры как samplerExternalOES :

 private final String fragmentShaderCode = "#extension GL_OES_EGL_image_external : require\n" + "precision mediump float;" + "uniform vec4 vColor;" + "uniform samplerExternalOES u_Texture;" + "varying vec2 v_TexCoordinate;" + "void main() {" + "gl_FragColor = (texture2D(u_Texture, v_TexCoordinate));" + "}"; 

Также в вашей функции draw() привяжите текстуру следующим образом:

 GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureDataHandle); 

Вы не можете использовать обычную текстуру для рендеринга камеры или видео, вы должны использовать расширение GL_TEXTURE_EXTERNAL_OES . У меня была такая же проблема, и я нашел полное рабочее решение для github. Название проекта – android_instacam.

Здесь вы найдете исходный код для изучения. Если вы хотите увидеть его в действии прямо на вашем устройстве, просто зайдите в магазин игр здесь .