0
votes

I am currently programming an application for image processing. To achieve the needed performance, I have to use the GPU to compute the camera input, more specifically use OpenGL ES 2.0. With the help of this project (https://github.com/yulu/ShaderCam) I achieved to pass the image to the pipeline and do simple operations with the fragment shader (like inverting colors etc).

My knowledge of GLSL, fragment shaders and vertex shaders is fairly limited but I am aware of pipeline constraints and what the two shaders do in the pipeline. So - formulating the problem - I would like to calculate the average color of a row in my received image and return it (per row) to my application. I read here https://stackoverflow.com/a/13866636/8038866 that this is generally possible, however I can't seem to find out the following things:

1 (edit: SOLVED by simply passing the w and h of my texture to the vertex and fragment shader): Knowing where the row ends (and having that information in the fragment shader). For this I assume that I would have to pass the width of the picture to the vertex shader and from there to the fragment shader, right?

2.: How to calculate the average the color values of each row in the fragment shader and then pass them to the application. If I understand it correctly - the fragment shader only excutes the code per pixel, so I am not sure how to achieve this.

Here are the two very basic shaders vertex shader:

uniform mat4 uTransformM;
uniform mat4 uOrientationM;
uniform vec2 ratios;
attribute vec2 aPosition;

varying vec2 vTextureCoord;

void main(){
    gl_Position = vec4(aPosition, 0.0, 1.0);
    vTextureCoord = (uTransformM * ((uOrientationM * gl_Position + 1.0)*0.5)).xy;
    gl_Position.xy *= ratios;
}

fragment shader:

#extension GL_OES_EGL_image_external : require

precision mediump float;

uniform samplerExternalOES sTexture;
varying vec2 vTextureCoord;

void main(){
    gl_FragColor = texture2D(sTexture, vTextureCoord);
    //calc mean per row and pass it back
}

I am very thankful for every advice or help you can provide.

1

1 Answers

1
votes

I found a way that does the trick for me. The idea is to calculate the mean for only one row of pixels and then later in the application to get this line with

glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * data);

Here is my fragment shader (notice that the width of the surface is required as well):

#extension GL_OES_EGL_image_external : require

precision mediump float;

uniform samplerExternalOES sTexture;
varying float width;
varying vec2 vTextureCoord;

void main(){
    vec4 accumulatedRGB = texture2D(sTexture, vec2(0,vTextureCoord.y));
    if(vTextureCoord.x < 0.50 && vTextureCoord.x > 0.499){ //small enough to only cover one line
        for(float i=1.0;i<=width;++i)
        {
            float xPosOnTexture = i/width;
            vec4 current =  texture2D(sTexture, vec2(xPosOnTexture,vTextureCoord.y));
            accumulatedRGB += current;
        }
        vec4 mean = accumulatedRGB/width;

        gl_FragColor = vec4(mean.rgb , mean.a);//avg color for one line
    }
    else{
        gl_FragColor = vec4(0.0,0.0,0.0,0.0);//rest of the screen
    }
}