2016-09-15 17 views
6

Wie ich verstanden, von GLES30 gibt es nicht mehr gl_FragColor Puffer (ich sah es HERE)Wie mit glReadPixels Daten aus bestimmten Puffer zu lesen, basierend auf GLES30 auf Android

Da ich kein „Sondervariablen“ lesen , wie kann ich einen "out" buffer lesen?

Dies ist mein Code:

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"; 

Hier habe ich versucht, die Daten zu lesen:

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); 

Es gibt keine gl Fehler im Code.

Der Ausgang mPixelBuf ist nur Nullen. Wie kann ich sicherstellen, dass fragColor gelesen wird?

Dank

Update1- Voll 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); 
     } 
    } 
} 

Antwort

0

Ihr Code-Shader ist völlig irrelevant, was glReadPixels liest, und es hat nichts mit speziellen Variablennamen zu tun hat. Es liest vom aktuell gebundenen Lese-Framebuffer; d. h. glReadPixels in ES 3.0 funktioniert genauso wie früher in ES 2.0.

Die einzige Ausnahme ist die Unterstützung mehrerer Renderziele, aber das ist in diesem Fall nicht relevant.

Wie kann ich sicherstellen, dass FragColor liest?

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

In GLES 20 Ich habe die Daten von mp4-Datei laden zu "gl_FragColor" spezielle Variable und die gelesenen Daten durch GLES20.glReadPixels (startX, startY, Frame, frameHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, mPixelBuf) unter Verwendung von ; Da es nicht mehr "gl_FragColor" gibt, wie soll ich die Daten von der "out" -Variable lesen, die ich erstellt habe? – user2235615

+0

Wie gesagt, ist es egal, wie die Variable heißt. glReadPixels liest den aktuellen Framebuffer aus. Dein Shader kann einen * beliebigen * Variablennamen haben und funktioniert genauso, – solidpixel

+0

Also, warum bekomme ich nur Nullen? Ist die "Texture" -Funktion richtig implementiert, um 4 Farbarten (RGBA) zu lesen? – user2235615

0

Was ich gelernt habe ist, dass Ihr GLES30.glReadPixels Anruf vor eglSwapBuffers getan werden muss, weil glReadBuffer zunächst auf GL_BACK in doppelt gepufferten Konfigurationen nach Dokument von glReadBuffer eingestellt ist. Sobald ruft glReadPixels liest nichts zurück zum Hauptspeicher.

+0

Ich verwende nicht eglSwapBuffers, Ist es notwendig, es zu verwenden? Wenn ja, wie sollte ich es in GLES30 implementieren? – user2235615

Verwandte Themen