Note that there are some explanatory texts on larger screens.

plurals
  1. PORendering to texture on iOS OpenGL ES—works on simulator, but not on device
    primarykey
    data
    text
    <p>In order to improve the performance of my OpenGL ES application for the iPad, I was planning to draw a rarely updated but rendertime-heavy element to a texture, so I can just use the texture unless the element has to be redrawn. However, while the texture is mapped correctly on both the simulator and the device, only on the simulator is something actually rendered into the texture.</p> <p>The following is the code that I added to the project. While setting up the scene, I create the buffers and the texture needed:</p> <pre class="lang-cpp prettyprint-override"><code>int width = 768; int height = 270; // Prepare texture for off-screen rendering. glGenTextures(1, &amp;wTexture); glBindTexture(GL_TEXTURE_2D, wTexture); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); glClearColor(.9f, .3f, .6f, 1.0f); // DEBUG glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); // Depth attachment buffer, always needed. glGenRenderbuffersOES(1, &amp;wDepth); glBindRenderbufferOES(GL_RENDERBUFFER_OES, wDepth); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, width, height); glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0); // Create FBO for render-to-texture. glGenFramebuffersOES(1, &amp;wBuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, wBuffer); glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, wTexture, 0); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, wDepth); glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); </code></pre> <p>A <code>glFramebufferStatusOES</code> on the new FBO (before it is unbound of course) yields a 'framebuffer complete' return value on both the simulator and the device. Note that I set the pink clear colour for the texture in order to confirm that the texture is actually rendered, and the problem is in fact simply that the texture is never drawn into.</p> <p>Whenever the texture needs to be redrawn, I do this before rendering the element:</p> <pre class="lang-cpp prettyprint-override"><code>glBindFramebufferOES(GL_FRAMEBUFFER_OES, wBuffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, width, height); glMatrixMode(GL_MODELVIEW); glPushMatrix(); // ... </code></pre> <p>and the following after the actual rendering:</p> <pre class="lang-cpp prettyprint-override"><code>// ... glPopMatrix(); glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); </code></pre> <p>Finally, every time the screen is redrawn I map the texture to a quad at the appropriate position on the screen, like so:</p> <pre class="lang-cpp prettyprint-override"><code>float Vertices[] = { -65.0f, -100.0f, .0f, -65.0f, 100.0f, .0f, -10.0f, -100.0f, .0f, -10.0f, 100.0f, .0f}; float Texture[] = {.0f, .0f, 1.0f, .0f, .0f, 1.0f, 1.0f, 1.0f}; glEnable(GL_TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindTexture(GL_TEXTURE_2D, wTexture); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glVertexPointer(3, GL_FLOAT, 0, Vertices); glTexCoordPointer(2, GL_FLOAT, 0, Texture); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); </code></pre> <p>On the iPhone and iPad simulators (4.2, 4.3), the code works as expected. I see the dynamically rendered texture displayed at the respective position, of course with a pink instead of a transparent background due to my debugging statement. On my iPad 4.2 device, however, only the pink rectangle is rendered, not what should have been drawn into it during the render-to-texture step. Thus, the texture is rendered to the screen correctly, but for some reason, on the device the render-to-texture code fails to actually render anything to the texture.</p> <p>I suppose I am using some functionality that is not available on the device, or make an erroneus assumption somewhere, but I can't figure out what it is. I also tried running it through the OpenGL ES Analyzer, but it gives me nothing but some basic performance optimisation tips. Where do I need to look for the problem?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload