2 Textures, 1 Shader - OpenGL ES 2.0

11,170

Solution 1

Ok, so as I mentioned in the comment above, I eventually found the answer here: http://www.opentk.com/node/2559. As mentioned by the user "Profet" on that forum, one way to re-use the fragment shader is to move the glUniform1i() calls down to the render function, i.e. call glUniform1i() to pass the first texture to the shader, call glDraw (draw your texture), then call glUniform1i() and pass the second texture to the shader (and draw). So now my initialise() code is as follows:

//LEFT IMAGE
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &m_uiTexture_left);                                    
glBindTexture(GL_TEXTURE_2D, m_uiTexture_left);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pwr2Width, pwr2Height,0, GL_RGB, GL_UNSIGNED_BYTE, xImageL); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLfloat afVertices[30] = {0.0};
genVertices(afVertices);
glGenBuffers(1, &m_ui32Vbo_leftimage);                                  
m_ui32VertexStride = 5 * sizeof(GLfloat); // 3 floats for the pos, 2 for the UVs
glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo_leftimage);
glBufferData(GL_ARRAY_BUFFER, 6 * m_ui32VertexStride, afVertices, GL_STATIC_DRAW);  
glBindBuffer(GL_ARRAY_BUFFER, 0);

//RIGHT IMAGE
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &m_uiTexture_right);                                   
glBindTexture(GL_TEXTURE_2D, m_uiTexture_right);   
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pwr2Width, pwr2Height,0, GL_RGB, GL_UNSIGNED_BYTE, xImageR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glGenBuffers(1, &m_ui32Vbo_rightimage);                     
m_ui32VertexStride = 5 * sizeof(GLfloat); // 3 floats for the pos, 2 for the UVs
glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo_rightimage);
glBufferData(GL_ARRAY_BUFFER, 6 * m_ui32VertexStride, afVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

And my render() code goes like:

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&  LEFT IMAGE &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 1); //draw on uneven lines only
glUniform1i(glGetUniformLocation(m_uiProgramObject, "sampler2d"), 0); //pass texture unit 0 to shader
glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo_leftimage);     // unbound this near the end of initView, so need to re-bind it
glEnableVertexAttribArray(VERTEX_ARRAY);
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, m_ui32VertexStride, 0);
glEnableVertexAttribArray(TEXCOORD_ARRAY);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, m_ui32VertexStride, (void*) (3 * sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&  RIGHT IMAGE  &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, 1);  //draw on even lines only
glUniform1i(glGetUniformLocation(m_uiProgramObject, "sampler2d"), 1);
glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo_rightimage);
glEnableVertexAttribArray(VERTEX_ARRAY);
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, m_ui32VertexStride, 0);
glEnableVertexAttribArray(TEXCOORD_ARRAY);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, m_ui32VertexStride, (void*) (3 * sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);

Hope this helps someone someday! :)

Solution 2

The right way is when you send what texture you want to what texture unit you want: http://www.opengl.org/wiki/Sampler_(GLSL)#Binding_textures_to_samplers

Share:
11,170
Stereoscopic
Author by

Stereoscopic

Updated on June 04, 2022

Comments

  • Stereoscopic
    Stereoscopic about 2 years

    ES 2.0 newbie here. I'm currently trying to make some 3D interlaced images from stereo images with ES 2.0 and the PowerVR SDK. I can output one image texture fine, but when I try to output the second one, I seem to be overwriting the first. So, my question is, given the fragment shader below, can I use it to draw two textures, or can the sampler2d uniform only be bound to one texture unit? Here's the fragment shader (taken from the PowerVR "training course" sample programs):

        uniform sampler2D sampler2d;\
        varying mediump vec2    myTexCoord;\
        void main (void)\
        {\
            gl_FragColor = texture2D(sampler2d,myTexCoord);\
        }";
    

    And here's how I am loading the image textures into the shader:

    //LEFT IMAGE
    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &m_uiTexture_left);                                    
    glBindTexture(GL_TEXTURE_2D, m_uiTexture_left);
    glUniform1i(glGetUniformLocation(m_uiProgramObject, "sampler2d"), 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pwr2Width, pwr2Height,0, GL_RGB, GL_UNSIGNED_BYTE, xImageL); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    GLfloat afVertices[30] = {0.0};
    genVertices(afVertices);
    glGenBuffers(1, &m_ui32Vbo_leftimage);                                  
    m_ui32VertexStride = 5 * sizeof(GLfloat); // 3 floats for the pos, 2 for the UVs
    glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo_leftimage);
    glBufferData(GL_ARRAY_BUFFER, 6 * m_ui32VertexStride, afVertices, GL_STATIC_DRAW);  
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    //RIGHT IMAGE
    glActiveTexture(GL_TEXTURE1);
    glGenTextures(1, &m_uiTexture_right);                                   
    glBindTexture(GL_TEXTURE_2D, m_uiTexture_right);
    glUniform1i(glGetUniformLocation(m_uiProgramObject, "sampler2d"), 1);   
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pwr2Width, pwr2Height,0, GL_RGB, GL_UNSIGNED_BYTE, xImageR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glGenBuffers(1, &m_ui32Vbo_rightimage);                     
    m_ui32VertexStride = 5 * sizeof(GLfloat); // 3 floats for the pos, 2 for the UVs
    glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo_rightimage);
    glBufferData(GL_ARRAY_BUFFER, 6 * m_ui32VertexStride, afVertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    

    So, is this code just overwriting the sampler2d uniform? Do I need another uniform or shader for the second image?

  • Jubei
    Jubei over 11 years
    doing glGetUniformLocation before EVERY single draw call is a waste of resources. You must do glGetUniformLocation once after you Link the shader then just refer to that location.