简体   繁体   English

如何使用基于Android上GLES30的glreadpixels从特定缓冲区读取数据

[英]How to read data from specific buffer with glreadpixels based on GLES30 on Android

As I understood, from GLES30 there is no more gl_FragColor buffer (I saw it HERE ) 据我所知,从GLES30开始,没有更多的gl_FragColor缓冲区(我在这里看到它)

Since I can't read a "Special Variables ", how can I read an "out" buffer? 由于我无法读取“特殊变量”,如何读取“out”缓冲区?

This is my 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";

Here I tried to read the data: 在这里,我尝试读取数据:

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

There are no gl errors in the code. 代码中没有gl错误。

The output mPixelBuf only zeroes. 输出mPixelBuf仅为零。

How can I make sure that fragColor is reading? 我怎样才能确保fragColor正在阅读?

Thanks 谢谢

Update1- Full Texture Render Code: Update1-全纹理渲染代码:

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

Your shader code is totally irrelevant to what glReadPixels reads, and it has nothing to do with special variable names. 您的着色器代码与glReadPixels读取的内容完全无关,它与特殊变量名称无关。 It reads from the currently bound read framebuffer; 它从当前绑定的读取帧缓冲区读取; ie glReadPixels in ES 3.0 works in exactly the same way as it used to work in ES 2.0. 即ES 3.0中的glReadPixels工作方式与ES 2.0中的工作方式完全相同。

The only exception is multiple render target support, but that's not relevant in this case. 唯一的例外是多个渲染目标支持,但在这种情况下不相关。

How can I make sure that fragColor is reading? 我怎样才能确保fragColor正在阅读?

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

What I have learned is that your GLES30.glReadPixels call needs to be done before eglSwapBuffers because glReadBuffer is initially set to GL_BACK in double-buffered configurations according to document of glReadBuffer . 我学到的是你的GLES30.glReadPixels调用需要在eglSwapBuffers之前完成,因为glReadBuffer最初根据glReadBuffer文件在双缓冲配置中设置为GL_BACK Once eglSwapBuffers calls glReadPixels reads nothing back to main memory. 一旦eglSwapBuffers调用glReadPixels eglSwapBuffers任何内容读回主内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用glReadPixels从前端缓冲区读取数据? - How to read from front buffer using glReadPixels? 如何使用GLES 3从android屏幕读取像素数据 - HOW to read pixel data from screen in android using GLES 3 OpenGLES,为什么 glReadPixels() 无法从 FBO 的 Renderbuffer 的颜色缓冲区中读取数据? - OpenGLES , why glReadPixels() can't read data from FBO's Renderbuffer's color buffer? GLES30.glGetBufferSubData 在哪里? opengles 3.0 如何读取变换反馈数据 - Where is GLES30.glGetBufferSubData? how to read transform feedback data opengles 3.0 在android上使用GLES20.glReadPixels时,它返回的数据与生动预览不完全相同 - When using GLES20.glReadPixels on android, the data returned by it is not exactly the same with the living preview 如何在Android的单独线程上运行GLES20.glReadPixels? - How can i run GLES20.glReadPixels on separate thread in android? GLES20.glReadPixels在android中全部为零 - GLES20.glReadPixels gets all zero in android Android:从缓冲区读取,直到收到特定的字符串或字符串 - Android : read from a buffer until a specific char or string is recieved Android:如何将此应用程序从 GLES1 移植到 GLES3 - Android: How can I port this app from GLES1 to GLES3 Android源代码无效,通过glReadPixels读取帧缓冲区 - Android source code not working, reading frame buffer through glReadPixels
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM