2015-05-04 13 views
13

Tôi đang cố gắng để nắm bắt video và hiển thị nó lên màn ảnh bằng cách thiết lập một kết cấu Open GL ES đến một android surfaceTexture. Tôi không thể sử dụng số TextureView và triển khai SurfaceTextureListener theo this tutorial vì tôi đang sử dụng Google Cardboard.Sử dụng dòng video như mở GL ES 2.0 texture

Tôi đã theo dõi the Android documentation về cách khởi chạy Open GL ES 2.0 và sử dụng nó, đồng thời cũng this tutorial về kết cấu.

Đưa 2 cùng tôi nhận được một màn hình trống và thỉnh thoảng nhận được <core_glBindTexture:572>: GL_INVALID_OPERATION trong cửa sổ giao diện điều khiển.

choáng ngợp bởi rất nhiều khái niệm mới mà tôi không biết, tôi không thể để gỡ lỗi hoặc chỉ cần hiểu nếu tiếp cận hai có thể được sử dụng như thế này. Đây là mã vẽ của tôi, nó được khởi tạo trong các lớp onSurfaceCreated() của lớp MainActivity và được vẽ từ onEyeDraw() là chức năng vẽ của 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); 
} 

} 
+0

Bạn đã tìm thấy https://github.com/google/grafika chưa? Hoạt động "kết cấu từ máy ảnh" có thể thực hiện hầu hết những gì bạn muốn. – fadden

Trả lời

7

Khi vẽ một đối tượng SurfaceTexture kết cấu, bạn cần phải sử dụng các mục tiêu GL_TEXTURE_EXTERNAL_OES kết cấu:

Đối tượng kết cấu sử dụng kết cấu mục tiêu GL_TEXTURE_EXTERNAL_OES, được định nghĩa bởi phần mở rộng GL_OES_EGL_image_external OpenGL ES. Điều này giới hạn cách kết cấu có thể được sử dụng. Mỗi lần kết cấu bị ràng buộc, nó phải được gắn với mục tiêu GL_TEXTURE_EXTERNAL_OES thay vì mục tiêu GL_TEXTURE_2D. Ngoài ra, bất kỳ trình đổ bóng OpenGL ES 2.0 nào lấy mẫu từ kết cấu phải khai báo việc sử dụng phần mở rộng này bằng cách sử dụng, ví dụ như chỉ thị "#extension GL_OES_EGL_image_external: require". Các trình đổ bóng như vậy cũng phải truy cập kết cấu bằng cách sử dụng kiểu lấy mẫu samplerExternalOES GLSL.

Vì vậy, bạn cần phải thay đổi shader mảnh của bạn như thế này, thêm việc kê khai #extension và tuyên bố thống nhất kết cấu của bạn như 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));" + 
    "}"; 

Cũng trong chức năng draw() của bạn, liên kết kết cấu như thế này:

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

chỉ có một cơ hội để thử nó và nhận được W/Adreno-ES20: : GL_INVALID_OPERATION –

+1

Bạn có thể nhận được lỗi rằng nếu bạn liên kết với các mục tiêu khác nhau: https://www.khronos.org/opengles/sdk/ docs/man/xhtml/glBindTexture.xml bạn đang gọi glBindTexture trong hàm tạo cũng như trong draw(), thay đổi điều đó để sử dụng GLES11Ext.GL_TEXTURE_EXTERNAL_OES cũng như được phát hiện rõ ràng là – samgak

+0

. Bây giờ tôi nhận được lỗi này W/Adreno-ES20 ﹕ : GL_INVALID_VALUE. google không đến với bất cứ điều gì. bạn có thể thấy bất cứ điều gì có thể gây ra điều này không? –

3

Bạn không thể sử dụng kết cấu bình thường để hiển thị xem trước máy ảnh hoặc video, bạn phải sử dụng tiện ích mở rộng GL_TEXTURE_EXTERNAL_OES. Tôi đã có cùng một vấn đề và tôi tìm thấy một giải pháp làm việc hoàn chỉnh trên github. Tên của dự án là android_instacam.

Here bạn sẽ tìm thấy mã nguồn để nghiên cứu. Nếu bạn muốn nhìn thấy nó trong hành động trực tiếp trên thiết bị của bạn chỉ cần đi vào cửa hàng chơi here.

+0

nhờ liên kết, trông rất giống với những gì tôi đang làm. –

Các vấn đề liên quan