iPhone OpenGL ES 2.0 render to texture multiplies color values rather than adding them

94 views Asked by At

I am attempting to render to a texture on the iPhone using openGL ES 2.0.

To test, I am rendering a polygon (just a simple circle). The circle is supposed to render fully red (rgba color is (1, 0, 0, 1)) but for some reason, it's resulting color will be the multiplication of it's color with whatever I initialize the render texture as.

For example :

Texture init color :     (1,   1,   1,   1)
Circle color :           (1,   0,   0,   1)
Resulting circle color : (1,   0,   0,   1) //This is as expected

Texture init color :     (0.5, 0.5, 0.5, 1) 
Circle color :           (1,   0,   0,   1) 
Resulting circle color : (0.5, 0,   0,   1) //This is unexpected.  

The background color shouldn't be factored in at all.

If I render the circle with darker red (0.5, 0, 0, 1), the fact that it's multiplying the color rather than adding it is more evident.

Texture init color :     (1,   1,   1,   1)
Circle color :           (0.5, 0,   0,   1)
Resulting circle color : (0.5, 0,   0,   1) //This is as expected

Texture init color :     (0.5,  0.5, 0.5, 1)
Circle color :           (0.5,  0,   0,   1)
Resulting circle color : (0.25, 0,   0,   1) //This is unexpected.  

My intuition is saying this is a problem with the blend mode but the problem persists even if I set the glBlendFunc to (GL_ONE, GL_ZERO).

This could also be due to the fact that the rendering uses premultiplied values but again, I am using very simple values here and full alpha which should ignore this problem but I might be wrong.

Question : Why are the colors multiplying with the background color?


My RenderTexture setup :

glBindTexture(GL_TEXTURE_2D, 0);

glGenFramebuffers(1, &m_frameBuffer);
glGenTextures(1, &m_textureId);

glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
glBindTexture(GL_TEXTURE_2D, m_textureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MathUtil::NextPowerOf2(m_width), MathUtil::NextPowerOf2(m_height), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureId, 0);

glViewport(0, 0, m_width, m_height);

When I render an object, I call the following :

glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);

glDrawElements(GL_TRIANGLES, (GLsizei)(m_offset / 4) * 6, GL_UNSIGNED_SHORT, (void*)0);

Finally, I read the values from the render texture with glReadPixels (glGetTexImage isn't available for iPhone's openGL ES 2.0 I believe) to confirm these values.

glReadPixels(0, 0, MathUtil::NextPowerOf2(m_width), MathUtil::NextPowerOf2(m_height), GL_RGBA, GL_UNSIGNED_BYTE, m_data);
1

There are 1 answers

0
Godfather On

After a lot of testing, it was found that the problem occurred because of openGL settings that weren't properly reset between setting the render target from the screen to the texture (and vice versa).

My solution was to refresh all gl bindings and calls (like the shader program) after the target was setup.

Unfortunately, I don't know exactly which call or combination of calls was causing this odd behaviour.