So I am following one of the simplest examples I could find on transform feedback, here, and converting it to Android/Java, but Android seems to be missing the glGetBufferSubData
function available in OpenGL ES 3.0.
I've tried searching the Android Source to see if this method is used when calling another method under the JNI, but I am not sure I am even looking in the correct place for that.
If this function doesn't exist how can I read the data out from the transform feedback? I've looked at glGetTransformfeedbackVarying
, glGetBufferPointerv
and glReadBuffer
but none seem to do what I want.
Here is my code:
import com.harmonicprocesses.penelopefree.openGL.MyGLRenderer;
import android.opengl.GLES30;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
/**
* Created by izzy on 6/24/15.
*/
public class TransformFeedback {
// Vertex shader
private final String vertexShaderSrc =
"in float inValue;\n" +
"out float outValue;\n" +
"void main() {\n" +
" outValue = sqrt(inValue);\n" +
"}\n";
private final int mProgram;
public TransformFeedback{
// Compile shader
int vertexShader = MyGLRenderer.loadShader(GLES30.GL_VERTEX_SHADER,
vertexShaderSrc);
// Create program and specify transform feedback variables
mProgram = GLES30.glCreateProgram();
GLES30.glAttachShader(mProgram, vertexShader);
//const GLchar* feedbackVaryings[] = { "outValue" };
GLES30.glTransformFeedbackVaryings(mProgram, 1, {"outValue"}, GLES30.GL_INTERLEAVED_ATTRIBS);
GLES30.glLinkProgram(mProgram);
GLES30.glUseProgram(mProgram);
// Create VAO
int[] vao = new int[1];
GLES30.glGenVertexArrays(1, vao, 0);
GLES30.glBindVertexArray(vao[0]);
// Create input VBO and vertex format
int bufferLength = 5 * 4; //5 floats 4 bytes each
ByteBuffer bb = ByteBuffer.allocateDirect(bufferLength);
FloatBuffer data = bb.asFloatBuffer();
float[] floatData = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
data.put(floatData);
data.position(0);
int[] vbo = new int[1];
GLES30.glGenBuffers(1, vbo, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, bufferLength, data, GLES30.GL_STATIC_DRAW);
int inputAttrib = GLES30.glGetAttribLocation(mProgram, "inValue");
GLES30.glEnableVertexAttribArray(inputAttrib);
GLES30.glVertexAttribPointer(inputAttrib, 1, GLES30.GL_FLOAT, false, 0, 0);
// Create transform feedback buffer
int[] tbo = new int[1];
GLES30.glGenBuffers(1, tbo, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, tbo[0]);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, bufferLength, null, GLES30.GL_STATIC_READ);
// Perform feedback transform
GLES30.glEnable(GLES30.GL_RASTERIZER_DISCARD);
GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo[0]);
GLES30.glBeginTransformFeedback(GLES30.GL_POINTS);
GLES30.glDrawArrays(GLES30.GL_POINTS, 0, 5);
GLES30.glEndTransformFeedback();
GLES30.glDisable(GLES30.GL_RASTERIZER_DISCARD);
GLES30.glFlush();
// Fetch and print results
float feedback[] = new float[5];
GLES30.glGetBufferSubData(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, bufferLength, feedback);
Log.e("TransformFeedback", String.format("%f %f %f %f %f\n", feedback[0], feedback[1], feedback[2], feedback[3], feedback[4]));
}
My final implementation won't need to read the data out necessarily, just use it in the shader on the next pass(feedback). But this really is the first step.