Alfredo Tostón
Alfredo Tostón

Reputation: 377

Is there a way to extract aggregated data from a OpenGL ES 2.0 shader?

Is there any way to do simple aggregated calculations over intermediate results in an OpenGL ES 2.0 shader?

For example, I have a vertex shader:

precision highp float;
attribute vec2 vTexPosition;
attribute vec3 vPosition;
varying vec2 fTexPosition;

void main() {
    fTexPosition = vTexPosition;
    gl_Position = vec4(vPosition, 1);
}

And a fragment shader:

precision highp float;
uniform float maxSomeHardToCalculateValue;
varying vec2 fTexPosition;

void main() {
    float someHardToCalculateValue = someHeavyFunction(fTexPosition);
    gl_FragColor = vec4(hsl2rgb(0, 0.6, someHardToCalculateValue / maxSomeHardToCalculateValue), 1);
}

I'm calling them from Android with something like this:

private void draw(float maxValue) {
    int maxValueLocation = GLES20.glGetUniformLocation(programId, "maxSomeHardToCalculateValue");
    GLES20.glUniform1f(maxValueLocation, maxValue);

    int positionHandle = GLES20.glGetAttribLocation(programId, "vPosition");
    int texPositionHandle = GLES20.glGetAttribLocation(programId, "vTexPosition");

    GLES20.glEnableVertexAttribArray(positionHandle);
    GLES20.glEnableVertexAttribArray(texPositionHandle);

    GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4, vertexBuffer);
    GLES20.glVertexAttribPointer(texPositionHandle, TEX_COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, TEX_COORDS_PER_VERTEX * 4, textureBuffer);
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, orderBuffer.capacity(), GLES20.GL_UNSIGNED_SHORT, orderBuffer);

    GLES20.glDisableVertexAttribArray(texPositionHandle);
    GLES20.glDisableVertexAttribArray(positionHandle);
}

And then

setupProgram();
setupFramebuffer();

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferId);
draw(1f);
float maxValue = getMaxValueSomehow();
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
draw(maxValue);

In this example, I need a way to extract the max of the calculated someHardToCalculateValue. I'm currently getting pixel info from the framebuffer with GLES20.glReadPixels and calculating the max, but it's giving me 8-bit precission, which is not enough.

I've thought of accessing some kind of writable atomic uniform directly from the shader and put the max there too, but after reading the Internet and do some tests with atomic counters I'm beginning to think it's not possible, at least in Android.

Upvotes: 0

Views: 40

Answers (0)

Related Questions