0
votes

I am really having nightmare to achieve what I required in OpenGles 2.0 Before posting the code reference, let me tell what I need.

I have 2D texture fragment shader. On top of the texture I want to draw red color line. I am able to draw the line but coloring to red is not working.

Shader declaration:

static const char s_v_shader[] =
    "attribute vec4 vPosition; \n"
    "attribute vec2 my_Texcoor;     \n"
    "uniform   mat4 u_TransMatrix;   \n"
    "varying vec2 vTexcoor;         \n"
    "void main() \n"
    "{ \n"
    "  vTexcoor = my_Texcoor;       \n"
    " gl_Position = u_TransMatrix*vPosition; \n"
    "} \n";

    static const char s_f_shader[] =
    "precision mediump float;\n"
    "uniform sampler2D my_Sampler;                    \n"
    "varying vec2 vTexcoor;                           \n"
    "void main() \n"
    "{ \n"
    " vec4 tex = texture2D(my_Sampler, vTexcoor);    \n"
    "  gl_FragColor = tex;                            \n"
    "} \n";

On top of texture I am rendering video frames from camera in infinite loop. Before rendering video, I am setting up co-ordinates of 2D texture with below code.

Now I will explain my code from main function

main()

    {
    const GLfloat vertices[][2] = {
        { -1.0f, -1.0f},
        {  1.0f, -1.0f},
        { -1.0f, 1.0f},
        {  1.0f,  1.0f}
    };

    const GLfloat texcoords[][2] = {
        { 0.0f, 1.0f},
        { 1.0f, 1.0f},
        { 0.0f, 0.0f},
        { 1.0f, 0.0f}
    };
    GLfloat transformMatrix[16] =
    {
        1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f
    };

        // setup OpenGl environment......
        Setup_coordinates()

    }

    Setup_coordinates()
    {
        LoadShaders(s_v_shader, s_f_shader);

 -- Complete function defined below 
        // By now I should be using  shader program.

        // Grab location of shader attributes.


    GLint locVertices = glGetAttribLocation(programHandle, "vPosition");
                GLint locTexcoord = glGetAttribLocation(programHandle, "my_Texcoor");

            // Transform Matrix is uniform for all vertices here.
                GLint locTransformMat = glGetUniformLocation(programHandle, "u_TransMatrix");
                GLint locSampler = glGetUniformLocation(programHandle, "my_Sampler");     

            /* Create the texture. */
                glGenTextures(1, &gTexObj);
                glBindTexture(GL_TEXTURE_2D, gTexObj);
                if (gTexObj == 0)
                {
                    printf("Could not load the texture \n");
                    return -1;
                }

                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    

                glUniformMatrix4fv(locTransformMat, 1, GL_FALSE, transformMatrix);

                glUniform1i(locSampler, 0);

                glClearColor(0.0f, 0.5f, 0.0f, 0.0f);
                glClear(GL_COLOR_BUFFER_BIT);


            while(1) -- Infinite loop to render video frames on 2D texture and draw red color line.
            {
              // enable vertex arrays to push the data.


    glEnableVertexAttribArray(locVertices);
                glEnableVertexAttribArray(locTexcoord);

                 // set data in the arrays.
                glVertexAttribPointer(locVertices, 2, GL_FLOAT, GL_FALSE, 0, &vertices[0][0]);
                glVertexAttribPointer(locTexcoord, 2, GL_FLOAT, GL_FALSE, 0, &texcoords[0][0]);

            Render video frames logic goes here...................................
            Each frame of video is abosultely rendering fine.

            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        Now comes the tricky part to draw the line and color it with red.



float red_left_1[] =
    {
        -0.85f, -0.9f, -0.6f, -0.5f,
    };
        glVertexAttribPointer ( 1, 2, GL_FLOAT, GL_FALSE, 0, red_left_1 );
        glEnableVertexAttribArray (1 );

        glDrawArrays ( GL_LINES , 0, 2 );
        glLineWidth( width_test );

        }

        }



void LoadShaders(const char * vShader, const char * pShader)
    {
        vertShaderNum = glCreateShader(GL_VERTEX_SHADER);
        pixelShaderNum = glCreateShader(GL_FRAGMENT_SHADER);

        if (CompileShader(vShader, vertShaderNum) == 0)
        {
            printf("%d: PS compile failed.\n", __LINE__);
            return;
        }

        if (CompileShader(pShader, pixelShaderNum) == 0)
        {
            printf("%d: VS compile failed.\n", __LINE__);
            return;
        }

        programHandle = glCreateProgram();

        glAttachShader(programHandle, vertShaderNum);
        glAttachShader(programHandle, pixelShaderNum);

        // Bind vPosition to attribute 0
        glBindAttribLocation ( programHandle, 0, "vPosition" );

        glLinkProgram(programHandle);
        // Check if linking succeeded.
        GLint linked = 0;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linked);
        if (!linked)
        {
            printf("%d: Link failed.\n", __LINE__);
            // Retrieve error buffer size.
            GLint errorBufSize, errorLength;
            glGetShaderiv(programHandle, GL_INFO_LOG_LENGTH, &errorBufSize);

            char * infoLog = (char*)malloc(errorBufSize * sizeof (char) + 1);
            if (infoLog)
            {
                // Retrieve error.
                glGetProgramInfoLog(programHandle, errorBufSize, &errorLength, infoLog);
                infoLog[errorBufSize + 1] = '\0';
                fprintf(stderr, "%s", infoLog);

                free(infoLog);
            }

            return;
        }
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glUseProgram(programHandle);
    }

Most of the genius peoples suggested to declare one more shader as above but replace uniform sampler2D my_Sampler with uniform vec4 color.

void main()
    {
    gl_FragColor = color
    }

Then switch between these shader programs while showing texture and drawing color lines using glUseProgram.

I tried and absolutely given up as switching to shader program for drawing lines is not working.

1
Have you considered generating a red texture (1x1 with a single red pixel), and switching to that when drawing the line?david
@David No I have not tried it. Can you please post code snippet to do that ?Mohan Kumar

1 Answers

0
votes

Here is code for generating a colored 1x1 texture that you can use for your line (goes in your main or Setup_coordinates). With this solution you won't need another shader.

GLuint lineTexture;
glGenTextures(1, &lineTexture);
unsigned char red[4] = { 255, 0, 0, 255};
glBindTexture(GL_TEXTURE_2D, lineTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, red);
glBindTexture(GL_TEXTURE_2D, 0);

Before calling glDrawArrays, use this to switch to the correct texture.

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <lineTexture or gTexObj>);
glUniform1i(locSampler, 0);

A more general solution (that I personally implement in my OpenGL projects) is to create a white texture, add a color uniform to your shader and multiply the uniform with the texture2D return value. With this method you can create different colored lines and graphics from the same white texture, only changing the color uniform. For the video frames, you would send in a white color and the pixels will remain unchanged. This will require very few changes to your code, I'm sure you can figure it out if you think it sounds better. :)