[英]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.