2016-09-15 16 views
6

Như tôi hiểu, từ GLES30 không có nhiều gl_FragColor đệm (tôi thấy nó HERE)Làm thế nào để đọc dữ liệu từ bộ đệm cụ thể với glreadpixels dựa trên GLES30 trên Android

Vì tôi không thể đọc được một "biến đặc biệt" , làm thế nào tôi có thể đọc một bộ đệm "ra"?

Đây là mã của tôi:

private static final String FRAGMENT_SHADER = 
     "#version 300 es\n"+ 
     "#extension GL_OES_EGL_image_external_essl3 : require\n" + 
     "precision mediump float;\n" +  // highp here doesn't seem to matter 
     "in vec2 vTextureCoord;\n" + 
     "uniform sampler2D sTexture;\n" + 
     "out vec4 fragColor ;\n" + 
     "void main() {\n" + 
     " vec4 tc = texture(sTexture, vTextureCoord);\n" + 
     " fragColor.r = tc.r * 0.3 + tc.g * 0.59 + tc.b * 0.11;\n" + 
     " fragColor.g = tc.r * 0.3 + tc.g * 0.59 + tc.b * 0.11;\n" + 
     " fragColor.b = tc.r * 0.3 + tc.g * 0.59 + tc.b * 0.11;\n" + 
     "}\n"; 

Ở đây tôi đã cố gắng để đọc dữ liệu:

ByteBuffer mPixelBuf = ByteBuffer.allocateDirect(mWidth * mHeight * 4); 
      mPixelBuf.order(ByteOrder.LITTLE_ENDIAN); 

GLES30.glReadPixels(startX, startY, frameWidth, frameHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, mPixelBuf); 

Không có lỗi gl trong các mã.

Đầu ra mPixelBuf chỉ số 0.

Làm cách nào để đảm bảo rằng fragColor đang đọc?

Cảm ơn

Update1- Full Texture Render Code:

package com.MES.YOtm.AnalyzingAdapter; 

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

import android.graphics.SurfaceTexture; 
import android.opengl.GLES11Ext; 
import android.opengl.GLES30; 
import android.opengl.Matrix; 
import android.util.Log; 

/** 
* Code for rendering a texture onto a surface using OpenGL ES 2.0. 
*/ 
public class STextureRender { 

    private static final String TAG = "Myopengl"; 
    private int zoom; 
    private static final int FLOAT_SIZE_BYTES = 4; 
    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 
    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 
    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 
    private final float[] mTriangleVerticesData = { 
      // X, Y, Z, U, V 
      -1.0f, -1.0f, 0, 0.f, 0.f, 
      1.0f, -1.0f, 0, 1.f, 0.f, 
      -1.0f, 1.0f, 0, 0.f, 1.f, 
      1.0f, 1.0f, 0, 1.f, 1.f, 
    }; 

    private FloatBuffer mTriangleVertices; 


    private static final String VERTEX_SHADER = 
      "#version 300 es\n"+ 
      "uniform mat4 uMVPMatrix;\n" + 
      "uniform mat4 uSTMatrix;\n" + 
      "in vec4 aPosition;\n" + 
      "in vec4 aTextureCoord;\n" + 
      "out vec2 vTextureCoord;\n" + 
      "void main() {\n" + 
      " gl_Position = uMVPMatrix * aPosition;\n" + 
      " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" + 
      "}\n"; 
//Smapler2D 
    private static final String FRAGMENT_SHADER = 
      "#version 300 es\n"+ 
      "#extension GL_OES_EGL_image_external_essl3 : require\n" + 
      "precision mediump float;\n" +  // highp here doesn't seem to matter 
      "in vec2 vTextureCoord;\n" + 
      "uniform mediump sampler2D sTexture;\n" + 
      "layout(location = 0) out mediump vec4 fragColor ;\n" + 
      "void main() {\n" + 
      " vec4 tc = texture(sTexture, vTextureCoord);\n" + 
      " fragColor.r = tc.r * 0.3 + tc.g * 0.59 + tc.b * 0.11;\n" + 
      " fragColor.g = tc.r * 0.3 + tc.g * 0.59 + tc.b * 0.11;\n" + 
      " fragColor.b = tc.r * 0.3 + tc.g * 0.59 + tc.b * 0.11;\n" + 
      "}\n"; 



    private float[] mMVPMatrix = new float[16]; 
    private float[] mSTMatrix = new float[16]; 

    private int mProgram; 
    private int mTextureID = -12345; 
    private int muMVPMatrixHandle; 
    private int muSTMatrixHandle; 
    private int maPositionHandle; 
    private int maTextureHandle; 

    public STextureRender(int _zoom) { 
     Log.v("My Error", "Start STextureRender constructor"); 
     try 
     { 

      mTriangleVertices = ByteBuffer.allocateDirect(
        mTriangleVerticesData.length * FLOAT_SIZE_BYTES) 
        .order(ByteOrder.nativeOrder()).asFloatBuffer(); 
      mTriangleVertices.put(mTriangleVerticesData).position(0); 

      Matrix.setIdentityM(mSTMatrix, 0); 
      zoom = _zoom; 
     } 
     catch(Exception ex) 
     { 
      Log.v("My Error", "STextureRender Error = " + ex.toString()); 
     } 
     Log.v("My Error", "End STextureRender constructor"); 
    } 

    public int getTextureId() { 
     return mTextureID; 
    } 

    /** 
    * Draws the external texture in SurfaceTexture onto the current EGL surface. 
    */ 
    public void drawFrame(SurfaceTexture st, boolean invert) { 
     checkGlError("onDrawFrame start"); 
     try 
     { 
      st.getTransformMatrix(mSTMatrix); 
      if (invert) { 
       mSTMatrix[5] = -mSTMatrix[5]; 
       mSTMatrix[13] = 1.0f - mSTMatrix[13]; 
      } 

      GLES30.glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 
      GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT); 

      GLES30.glUseProgram(mProgram); 
      checkGlError("glUseProgram"); 

      GLES30.glActiveTexture(GLES30.GL_TEXTURE0); 
      GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID); 

      mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 
      GLES30.glVertexAttribPointer(maPositionHandle, 3, GLES30.GL_FLOAT, false, 
        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
      checkGlError("glVertexAttribPointer maPosition"); 
      GLES30.glEnableVertexAttribArray(maPositionHandle); 
      checkGlError("glEnableVertexAttribArray maPositionHandle"); 

      mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
      GLES30.glVertexAttribPointer(maTextureHandle, 2, GLES30.GL_FLOAT, false, 
        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 
      checkGlError("glVertexAttribPointer maTextureHandle"); 
      GLES30.glEnableVertexAttribArray(maTextureHandle); 
      checkGlError("glEnableVertexAttribArray maTextureHandle"); 

      Matrix.setIdentityM(mMVPMatrix, 0); 
      GLES30.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
      GLES30.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0); 

      GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4); 
      checkGlError("glDrawArrays"); 
     } 
     catch(Exception ex) 
     { 
      Log.v("My Error", "drawFrame Error = " + ex.toString()); 
     } 
    } 

    /** 
    * Initializes GL state. Call this after the EGL surface has been created and made current. 
    */ 
    public void surfaceCreated() { 
     try 
     { 
      mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER); 
      if (mProgram == 0) { 
       throw new RuntimeException("failed creating program"); 
      } 
      maPositionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition"); 
      checkGlError("glGetAttribLocation aPosition"); 
      if (maPositionHandle == -1) { 
       throw new RuntimeException("Could not get attrib location for aPosition"); 
      } 
      maTextureHandle = GLES30.glGetAttribLocation(mProgram, "aTextureCoord"); 
      checkGlError("glGetAttribLocation aTextureCoord"); 
      if (maTextureHandle == -1) { 
       throw new RuntimeException("Could not get attrib location for aTextureCoord"); 
      } 

      muMVPMatrixHandle = GLES30.glGetUniformLocation(mProgram, "uMVPMatrix"); 
      checkGlError("glGetUniformLocation uMVPMatrix"); 
      if (muMVPMatrixHandle == -1) { 
       throw new RuntimeException("Could not get attrib location for uMVPMatrix"); 
      } 

      muSTMatrixHandle = GLES30.glGetUniformLocation(mProgram, "uSTMatrix"); 
      checkGlError("glGetUniformLocation uSTMatrix"); 
      if (muSTMatrixHandle == -1) { 
       throw new RuntimeException("Could not get attrib location for uSTMatrix"); 
      } 

      int[] textures = new int[1]; 
      GLES30.glGenTextures(1, textures, 0); 

      mTextureID = textures[0]; 
      GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID); 
      checkGlError("glBindTexture mTextureID"); 

      GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MIN_FILTER, 
        GLES30.GL_NEAREST); 
      GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MAG_FILTER, 
        GLES30.GL_LINEAR); 
      GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_S, 
        GLES30.GL_CLAMP_TO_EDGE); 
      GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_T, 
        GLES30.GL_CLAMP_TO_EDGE); 
      checkGlError("glTexParameter"); 
     } 
     catch(Exception ex) 
     { 
      Log.v("My Error", "surfaceCreated Error = " + ex.toString()); 
     } 
    } 

    /** 
    * Replaces the fragment shader. Pass in null to reset to default. 
    */ 
    public void changementShader(String fragmentShader) { 
     try 
     { 
     if (fragmentShader == null) { 
      fragmentShader = FRAGMENT_SHADER; 
     } 
     GLES30.glDeleteProgram(mProgram); 
     mProgram = createProgram(VERTEX_SHADER, fragmentShader); 
     if (mProgram == 0) { 
      Log.v("My Error", "failed creating program"); 
      throw new RuntimeException("failed creating program"); 
     } 
     } 
     catch(Exception ex) 
     { 
      Log.v("My Error", " changementShader Error = " + ex.toString()); 
     } 
    } 

    private int loadShader(int shaderType, String source) { 
     try 
     { 
      int shader = GLES30.glCreateShader(shaderType); 
      checkGlError("glCreateShader type=" + shaderType); 

      GLES30.glShaderSource(shader, source); 
      GLES30.glCompileShader(shader); 
      int[] compiled = new int[1]; 
      GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, compiled, 0); 
      if (compiled[0] == 0) { 
       Log.e(TAG, "Could not compile shader " + shaderType + ":"); 
       Log.e(TAG, " " + GLES30.glGetShaderInfoLog(shader)); 
       GLES30.glDeleteShader(shader); 
       shader = 0; 
      } 

      return shader; 
     } 
     catch(Exception ex) 
     { 
      Log.v("My Error", "loadShader Error = " + ex.toString()); 
      return 0; 
     } 
    } 

    private int createProgram(String vertexSource, String fragmentSource) { 
     try 
     { 
      int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexSource); 
      if (vertexShader == 0) { 
       return 0; 
      } 
      int pixelShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentSource); 
      if (pixelShader == 0) { 
       return 0; 
      } 

      int program = GLES30.glCreateProgram(); 
      checkGlError("glCreateProgram"); 
      if (program == 0) { 
       Log.e(TAG, "Could not create program"); 
      } 
      GLES30.glAttachShader(program, vertexShader); 
      checkGlError("glAttachShader"); 
      GLES30.glAttachShader(program, pixelShader); 
      checkGlError("glAttachShader"); 
      GLES30.glLinkProgram(program); 
      int[] linkStatus = new int[1]; 
      GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linkStatus, 0); 
      if (linkStatus[0] != GLES30.GL_TRUE) { 
       Log.e(TAG, "Could not link program: "); 
       Log.e(TAG, GLES30.glGetProgramInfoLog(program)); 
       GLES30.glDeleteProgram(program); 
       program = 0; 
      } 
      return program; 
     } 
     catch(Exception ex) 
     { 
      Log.v("My Error", "createProgram Error = " + ex.toString()); 
      return 0; 
     } 
    } 

    public void checkGlError(String op) { 
     int error; 
     while ((error = GLES30.glGetError()) != GLES30.GL_NO_ERROR) { 
      Log.e(TAG, op + ": glError " + error); 
      throw new RuntimeException(op + ": glError " + error); 
     } 
    } 
} 

Trả lời

0

đang đổ bóng của bạn là hoàn toàn không liên quan đến những gì glReadPixels đọc, và nó không có gì để làm với tên biến đặc biệt. Nó đọc từ framebuffer đọc bị ràng buộc hiện tại; tức là glReadPixels trong ES 3.0 hoạt động giống hệt như cách được sử dụng để hoạt động trong ES 2.0.

Ngoại lệ duy nhất là hỗ trợ nhiều mục tiêu hiển thị, nhưng điều đó không có liên quan trong trường hợp này.

Làm cách nào để đảm bảo rằng màu của bạn đang đọc?

glClearColor(some interesting color) 
glClear(COLOR_BUFFER_BIT) 
glReadPixels() 
assert color == some interesting color 
+0

Trong GLES 20 tôi đã tải dữ liệu từ tệp mp4 sang biến đặc biệt "gl_FragColor" và dữ liệu được đọc bằng GLES20.glReadPixels (startX, startY, frameWidth, frameHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, mPixelBuf) ; Vì không có thêm "gl_FragColor", tôi nên đọc dữ liệu từ biến "out" mà tôi đã tạo ra như thế nào? – user2235615

+0

Như đã nói, không quan trọng biến được gọi là gì. glReadPixels đọc từ framebuffer đọc hiện tại. Trình đổ bóng của bạn có thể có * bất kỳ tên biến * nào và nó sẽ hoạt động chính xác theo cùng một cách, – solidpixel

+0

Vì vậy, Tại sao tôi chỉ nhận được số không? Chức năng "Texture" có được thực thi ngay để đọc 4 loại màu (RGBA) không? – user2235615

0

Những gì tôi đã học được là gọi GLES30.glReadPixels của bạn cần phải được thực hiện trước eglSwapBuffers vì glReadBuffer ban đầu được thiết lập để GL_BACK trong các cấu hình đôi đệm theo tài liệu của glReadBuffer. Sau khi gọi eglSwapBuffers, hãy gọi glReadPixels không đọc gì về bộ nhớ chính.

+0

Tôi không sử dụng eglSwapBuffers, Có cần thiết để sử dụng nó? Nếu có, tôi nên thực hiện nó như thế nào trong GLES30? – user2235615

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