# How to skip frames in RenderScene

**URL:** <https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030>\
**Category:** PowerVR Insider\
**Created:** [March 16, 2011, 4:27pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030 "2011-03-16T16:27:06Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [March 16, 2011, 4:27pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/1 "2011-03-16T16:27:06Z")

</div>

Hi there

  

I am trying to make a screen shot. But the setting is very different on this frame (different color compared with previous and next frames)&nbsp;when I make the screenshot. That is why I do not want to display this frame on the screen and there will be confusing content changing on the screen. 
  

&nbsp;
  

So, what is the best solution for this special application?
  

- Is there a switch I can use in the renderscene function so that the current frame will not be displayed?
  

- Or can I define an internal buffer which will not be used for displaying?
  

&nbsp;
  

Thank you for your suggestion,
  

&nbsp;
  

Renaissance
  

&nbsp;

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [March 21, 2011, 8:53pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/2 "2011-03-21T20:53:14Z")

</div>

Can anyone give me some help on this issue?

  

&nbsp;
  

Thanks a lot

---

<div class="post-metadata">

**Author:** ![JoeDavis](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.imgtec.com/joedavis/32/71_2.png) [@JoeDavis](https://forums.imgtec.com/u/JoeDavis)\
**Post date:** [March 22, 2011, 9:48am UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/3 "2011-03-22T09:48:00Z")

</div>

Hi Renaissance,  
  
  
  
  
  
I’m not entirely sure what your use case is here. Do you mean the frame that you want to take a screen-shot of has a different effect applied to it compared to your normal render, for example a post-processing effect?  
  
  
  
  
  
It sounds like render to texture will solve this, as you will be performing an off-screen render (see our RenderToTexture training course for an example use of this). You can perform a render pass for your “screen-shot” effect, then do a glReadPixels() to retrieve the rendered image (capture the screen-shot), then perform your normal render pass that will be rendered to the display.  
  
  
  
  
  
In our PVRShell, there is a function called PVRShellScreenSave(), which can be used to save a screen shot of the current render. If you are already using the shell, you can use this function as-is. Otherwise, you can read through the code to see how we’ve implemented this feature.  
  
  
  
  
  
You should be aware that there is a cost associated with glReadPixels() as it will remove the parallelism between the GPU and CPU (stalls will be introduced). For this reason, you should try to use this sparingly and should be aware of the performance hit you will taken when it is used.  
  
  
  
  
  
Thanks,  
  
  
Joe

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [March 22, 2011, 4:49pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/4 "2011-03-22T16:49:30Z")

</div>

Thank you so much, Joe.

&nbsp;
  

I just want to clarify what I need. Actually, I need a off-screen render, which will be captured as an extrenal image file. Here is a simple flow chart.
  

&nbsp;
  

Frame 1 (rendered to screen)
  

  

Frame&nbsp;2 (rendered to screen)
  

...
Frame i (The content of the frame is changed and it will not be rendered to screen, but will be saved to external image file)
  

  

Frame&nbsp;i+1 (The content of the frame is changed back to the status as frame i-1 and it will be rendered to screen)
  

  

Frame&nbsp;i+2 (rendered to screen)

  

..

  

&nbsp;
  

I have already read the code in the OGLES2RenderToTexture.cpp. Based on my understanding, the renderscene function is stil called very time for a specific frame. In order to get the screen shot of frame i, I still have to call this function. How can I do the off-screen render and save it to an external image file?
  

&nbsp;
  

Thank you very much,
  

&nbsp;
  

Renaissance
  

&nbsp;
  

&nbsp;

---

<div class="post-metadata">

**Author:** ![JoeDavis](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.imgtec.com/joedavis/32/71_2.png) [@JoeDavis](https://forums.imgtec.com/u/JoeDavis)\
**Post date:** [March 23, 2011, 10:26am UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/5 "2011-03-23T10:26:13Z")

</div>

Btw, which graphics API are you using? OGLES 1.x or 2.0?  
  
  
  
  
  
Unless I’ve misunderstood your use case and you have the need to display frame i-1 repeatly (e.g. frames i, i+1, i+2 render exactly the same image as frame i-1), then I think you should do the following  
  
  
  
  
  
…  
  
  
  
  
  
OffScreenRender(render off screen, then capture with glReadPixels()) Frame i (render the normal scene within the RenderScene() block to render it to the screen)  
  
  
  
  
  
Frame i+1(render to screen)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
  
  
  
  
  
Frame i+2(render to screen)  
  
  
  
  
  
…  
  
  
  
  
  
  
  
  
So, basically you will still call RenderScene to do your normal render, but will also perform an off-screen render at the start of this for the render that you want to save. I’ll give some pseudo code to explain this (based on our OGLES2 render to texture training course - all psuedo code would be implemented in RenderScene() function):  
  
  
  
  
  
  
  
/\* Bind FBO for offscreen render _/_  
   
_glBindFramebuffer(GL\_FRAMEBUFFER, m\_uFBO);_  
   
_…_  
   
_/_ Perform the off-screen render that you want to save _/_  
   
_…_  
   
_/_ Retrieve the rendered image - NOTE: this will stall the CPU as it has to wait for the GPU render to complete\*/  
  
glReadPixels();  
  
  
  
// We are done with rendering to our FBO so switch back to the back buffer.  
  
glBindFramebuffer(GL\_FRAMEBUFFER, m\_i32OriginalFbo);  
  
…  
  
/\* Perform normal render that you want to be visible on the screen \*/  
  
…  
  
[/CODE]`<br />
<br />/* Bind FBO for offscreen render */<br />
<br />glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO);<br />
<br />...<br />
<br />/* Perform the off-screen render that you want to save */<br />
<br />...<br />
<br />/* Retrieve the rendered image - NOTE: this will stall the CPU as it has to wait for the GPU render to complete*/<br />
<br />glReadPixels();<br />
<br /><br />
<br />// We are done with rendering to our FBO so switch back to the back buffer.<br />
<br />glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo);<br />
<br />...<br />
<br />/* Perform normal render that you want to be visible on the screen */<br />
<br />...<br />
<br />`

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [March 23, 2011, 9:58pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/6 "2011-03-23T21:58:02Z")

</div>

Once again, Joe, Thank you so much for your reply. Your suggestion is very helpful. Based on your feedback, I made a test in the OGLES2RenderToTexture example. In the following is the source code I used and you may just look at the part in red font. BTW, I am using OpenGL ES 2. The test I did is on PC windows.
  

&nbsp;
  

In general, I made the test based on your pseudo code. At one special frame, I called a different function which does the rendering. Then I bind the frame to a different FBO and dump out the data as external file.&nbsp; When the program runs to a different frame, only the original renderscene will be called. 
  

&nbsp;
  

I found that after I loaded the saved image data (off-screen shot), the content of the image is not what I expected. The 2D image is with a simple fixed value. 
  

&nbsp;
  

When I commented out the following line in my code, 
  

glBindFramebuffer(GL\_FRAMEBUFFER, m\_uFBO[0]); 
  

I did get the correct screenshot I expected. But of course, this image was rendered on the screen at the same time.
  

&nbsp;
  

I wondering if you can give a hint that there must be something else I should add to this program.
  

&nbsp;
  

Thank you very much,
  

&nbsp;
  

Renaissance
  

&nbsp;
  

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
  

&nbsp;@File&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OGLES2RenderToTexture.cpp
  

&nbsp;@Title&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RenderToTexture
  

&nbsp;@Version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  

&nbsp;@Copyright&nbsp;&nbsp;&nbsp; Copyright (C)&nbsp; Imagination Technologies Limited.
  

&nbsp;@Platform&nbsp;&nbsp;&nbsp;&nbsp; Independent
  

&nbsp;@Description&nbsp; Shows how to use a frame buffer object to render to a texture.
  

\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
#include \<math.h\>
  

#include "PVRShell.h"  
#include "OGLES2Tools.h"
  

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;shader attributes  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
// vertex attributes  
enum EVertexAttrib {  
&nbsp;VERTEX\_ARRAY, TEXCOORD\_ARRAY, eNumAttribs };  
const char\* g\_aszAttribNames[] = {  
&nbsp;"inVertex", "inTexCoord" };
  

// shader uniforms  
enum EUniform {  
&nbsp;eMVPMatrix, eNumUniforms };  
const char\* g\_aszUniformNames[] = {  
&nbsp;"MVPMatrix" };
  

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;Content file names  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
  

// Source and binary shaders  
const char c\_szFragShaderSrcFile[]&nbsp;= "FragShader.fsh";  
const char c\_szFragShaderBinFile[]&nbsp;= "FragShader.fsc";  
const char c\_szVertShaderSrcFile[]&nbsp;= "VertShader.vsh";  
const char c\_szVertShaderBinFile[]&nbsp;= "VertShader.vsc";
  

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;\*\* Class: OGLES2RenderToTexture  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
class OGLES2RenderToTexture : public PVRShell  
{  
&nbsp;// Print3D class used to display text  
&nbsp;CPVRTPrint3D&nbsp;m\_Print3D;
  

&nbsp;// OpenGL handles for shaders, textures, FBOs and VBOs  
&nbsp;GLuint&nbsp;m\_uiVertShader;  
&nbsp;GLuint&nbsp;m\_uiFragShader;  
&nbsp;GLuint&nbsp;m\_auiTexture[2];  
&nbsp;GLuint&nbsp; m\_uiTrunkTex;  
&nbsp;GLuint&nbsp; m\_uiVbo;  
&nbsp;GLuint&nbsp; m\_uFBO[1];  
&nbsp;&nbsp;&nbsp; GLuint&nbsp;m\_auiFbo[2];  
&nbsp;int&nbsp;&nbsp;m\_i32CurrentFbo;  
&nbsp;int&nbsp;&nbsp;m\_i32OriginalFbo;  
&nbsp;GLuint&nbsp;m\_auiDepthBuffer[2];  
&nbsp;GLubyte \*m\_pScreenBuf;
  

&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp; m\_framenumber;  
&nbsp;// Group shader programs and their uniform locations together  
&nbsp;struct  
&nbsp;{  
&nbsp;&nbsp;GLuint uiId;  
&nbsp;&nbsp;GLuint auiLoc[eNumUniforms];  
&nbsp;}  
&nbsp;m\_ShaderProgram;
  

&nbsp;int m\_i32TexSize;
  

&nbsp;float m\_fAngle;  
&nbsp;float m\_fAngle2;
  

&nbsp;unsigned int m\_ui32Framenum;  
&nbsp;unsigned int m\_ui32Time;
  

public:  
&nbsp;virtual bool InitApplication();  
&nbsp;virtual bool InitView();  
&nbsp;virtual bool ReleaseView();  
&nbsp;virtual bool QuitApplication();  
&nbsp;virtual bool RenderScene();
  

&nbsp;void LoadTextures();  
&nbsp;bool LoadShaders(CPVRTString\* pErrorStr);  
&nbsp;void LoadVbos();
  

&nbsp;bool DrawScreen();  
&nbsp;bool DrawScreen\_S();  
&nbsp;bool RenderFractal();  
};
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;LoadTextures  
&nbsp;@Description&nbsp;Loads the textures required for this training course  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
void OGLES2RenderToTexture::LoadTextures()  
{  
&nbsp;&nbsp;&nbsp; /\*  
&nbsp;&nbsp;Initialise the textures  
&nbsp;\*/
  

&nbsp;// Allocates one texture handle for the trunk texture  
&nbsp;glGenTextures(1, &m\_uiTrunkTex);
  

&nbsp;// Binds this texture handle so we can load the data into it  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiTrunkTex);
  

&nbsp;// Creates the data as a 32bits integer array (8bits per component)  
&nbsp;GLuint\* pTexData = new GLuint[32\*32];
  

&nbsp;// Create texture pattern  
&nbsp;for (int i=0; i\<32; i++)  
&nbsp;{  
&nbsp;&nbsp;for (int j=0; j\<32; j++)  
&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp;pTexData[i\*32+j] = 0xFF000000 + ((255 - (j-16)\*(j-15)) \<\< 8) + ((j \* 8) & 0xFF);  
&nbsp;&nbsp;}  
&nbsp;}
  

&nbsp;glTexImage2D(GL\_TEXTURE\_2D, 0, GL\_RGBA, 32, 32, 0, GL\_RGBA, GL\_UNSIGNED\_BYTE, pTexData);
  

&nbsp;&nbsp;&nbsp; /\* Destroy the array as it is no longer needed\*/  
&nbsp;&nbsp;&nbsp; delete [] pTexData;
  

&nbsp;glTexParameterf(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_LINEAR);  
&nbsp;glTexParameterf(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_LINEAR);
  

&nbsp;// Allocate two textures  
&nbsp;glGenTextures(2, m\_auiTexture);  
&nbsp;for (int i = 0; i \< 2; ++i)  
&nbsp;{  
&nbsp;&nbsp;// Binds this texture handle so we can load the data into it  
&nbsp;&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_auiTexture_);  
&nbsp;&nbsp;glTexImage2D(GL\_TEXTURE\_2D, 0, GL\_RGBA, m\_i32TexSize, m\_i32TexSize, 0, GL\_RGBA, GL\_UNSIGNED\_BYTE, 0);_
  

&nbsp;&nbsp;glTexParameterf(GL\_TEXTURE\_2D, GL\_TEXTURE\_MIN\_FILTER, GL\_LINEAR);  
&nbsp;&nbsp;glTexParameterf(GL\_TEXTURE\_2D, GL\_TEXTURE\_MAG\_FILTER, GL\_LINEAR);  
&nbsp;&nbsp;glTexParameterf(GL\_TEXTURE\_2D, GL\_TEXTURE\_WRAP\_S, GL\_CLAMP\_TO\_EDGE);  
&nbsp;&nbsp;glTexParameterf(GL\_TEXTURE\_2D, GL\_TEXTURE\_WRAP\_T, GL\_CLAMP\_TO\_EDGE);  
&nbsp;}  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;LoadShaders  
&nbsp;@Output&nbsp;&nbsp;pErrorStr&nbsp;&nbsp;A string describing the error on failure  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Loads and compiles the shaders and links the shader programs  
&nbsp;&nbsp;&nbsp;&nbsp;required for this training course  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLES2RenderToTexture::LoadShaders(CPVRTString\* pErrorStr)  
{  
&nbsp;/\*  
&nbsp;&nbsp;Load and compile the shaders from files.  
&nbsp;&nbsp;Binary shaders are tried first, source shaders  
&nbsp;&nbsp;are used as fallback.  
&nbsp;\*/  
&nbsp;if (PVRTShaderLoadFromFile(  
&nbsp;&nbsp;&nbsp;c\_szVertShaderBinFile, c\_szVertShaderSrcFile, GL\_VERTEX\_SHADER, GL\_SGX\_BINARY\_IMG, &m\_uiVertShader, pErrorStr) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;if (PVRTShaderLoadFromFile(  
&nbsp;&nbsp;&nbsp;c\_szFragShaderBinFile, c\_szFragShaderSrcFile, GL\_FRAGMENT\_SHADER, GL\_SGX\_BINARY\_IMG, &m\_uiFragShader, pErrorStr) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;/\*  
&nbsp;&nbsp;Set up and link the shader program  
&nbsp;\*/
  

&nbsp;if (PVRTCreateProgram(&m\_ShaderProgram.uiId, m\_uiVertShader, m\_uiFragShader, g\_aszAttribNames, eNumAttribs, pErrorStr) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, pErrorStr-\>c\_str());  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;// Store the location of uniforms for later use  
&nbsp;for (int i = 0; i \< eNumUniforms; ++i)  
&nbsp;{  
&nbsp;&nbsp;m\_ShaderProgram.auiLoc _= glGetUniformLocation(m\_ShaderProgram.uiId, g\_aszUniformNames);  
&nbsp;}_
  

&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;LoadVbos  
&nbsp;@Description&nbsp;Loads the vertex data required for this training course into a  
&nbsp;&nbsp;&nbsp;&nbsp;vertex buffer object  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
void OGLES2RenderToTexture::LoadVbos()  
{  
&nbsp;float afVertexData[] = {  
&nbsp;&nbsp;// trunk  
&nbsp;&nbsp;-0.1f,&nbsp;-1.0f, 0.5f,&nbsp; 0.0f, 1.0f,  
&nbsp;&nbsp; 0.1f,&nbsp;-1.0f, 0.5f,&nbsp; 1.0f, 1.0f,  
&nbsp;&nbsp;-0.08f,&nbsp;-0.4f, 0.5f,&nbsp; 0.0f, 0.2f,  
&nbsp;&nbsp; 0.08f,&nbsp;-0.4f, 0.5f,&nbsp; 1.0f, 0.2f,  
&nbsp;&nbsp; 0.0f,&nbsp;-0.3f, 0.5f,&nbsp; 0.5f, 0.0f,
  

&nbsp;&nbsp; // feedback quad  
&nbsp;&nbsp; -0.65f, 0.0f, 0.65f,&nbsp; 0.0f, 0.0f,  
&nbsp;&nbsp; -0.65f, 1.3f, 0.65f,&nbsp; 0.0f, 1.0f,  
&nbsp;&nbsp;&nbsp; 0.65f, 0.0f, 0.65f,&nbsp; 1.0f, 0.0f,  
&nbsp;&nbsp;&nbsp; 0.65f, 1.3f, 0.65f,&nbsp; 1.0f, 1.0f,  
&nbsp;};
  

&nbsp;glGenBuffers(1, &m\_uiVbo);  
&nbsp;glBindBuffer(GL\_ARRAY\_BUFFER, m\_uiVbo);  
&nbsp;glBufferData(GL\_ARRAY\_BUFFER, sizeof(afVertexData), afVertexData, GL\_STATIC\_DRAW);  
&nbsp;glBindBuffer(GL\_ARRAY\_BUFFER, 0);  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;InitApplication  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in InitApplication() will be called by PVRShell once per  
&nbsp;&nbsp;&nbsp;&nbsp;run, before the rendering context is created.  
&nbsp;&nbsp;&nbsp;&nbsp;Used to initialize variables that are not dependant on it  
&nbsp;&nbsp;&nbsp;&nbsp;(e.g. external modules, loading meshes, etc.)  
&nbsp;&nbsp;&nbsp;&nbsp;If the rendering context is lost, InitApplication() will  
&nbsp;&nbsp;&nbsp;&nbsp;not be called again.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLES2RenderToTexture::InitApplication()  
{  
&nbsp;// Get and set the read path for content files  
&nbsp;CPVRTResourceFile::SetReadPath((char\*)PVRShellGet(prefReadPath));  
&nbsp;  
&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;QuitApplication  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error&nbsp; occured  
&nbsp;@Description&nbsp;Code in QuitApplication() will be called by PVRShell once per  
&nbsp;&nbsp;&nbsp;&nbsp;run, just before exiting the program.  
&nbsp;&nbsp;&nbsp;&nbsp;If the rendering context is lost, QuitApplication() will  
&nbsp;&nbsp;&nbsp;&nbsp;not be called.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLES2RenderToTexture::QuitApplication()  
{  
&nbsp;&nbsp;&nbsp; return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;InitView  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no&nbsp; error occured  
&nbsp;@Description&nbsp;Code in InitView() will be called by PVRShell upon  
&nbsp;&nbsp;&nbsp;&nbsp;initialization or after a change in the rendering context.  
&nbsp;&nbsp;&nbsp;&nbsp;Used to initialize variables that are dependant on the rendering  
&nbsp;&nbsp;&nbsp;&nbsp;context (e.g. textures, vertex buffers, etc.)  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLES2RenderToTexture::InitView()  
{  
&nbsp;// Find the largest square power of two texture that fits into the viewport  
&nbsp;m\_i32TexSize = 1;  
&nbsp;int iSize = PVRT\_MIN(PVRShellGet(prefWidth), PVRShellGet(prefHeight));  
&nbsp;while (m\_i32TexSize \* 2 \< iSize) m\_i32TexSize \*= 2;
  

&nbsp;srand(PVRShellGetTime());  
&nbsp;m\_ui32Framenum = rand() % 5000;
  

&nbsp;m\_framenumber = 0;
  

&nbsp;// Get the initial time  
&nbsp;m\_ui32Time = PVRShellGetTime();
  

&nbsp;/\*  
&nbsp;&nbsp;Initialize VBO data and load textures  
&nbsp;\*/  
&nbsp;LoadVbos();  
&nbsp;LoadTextures();
  

&nbsp;/\*  
&nbsp;&nbsp;Load and compile the shaders & link programs  
&nbsp;\*/  
&nbsp;CPVRTString ErrorStr;  
&nbsp;if (!LoadShaders(&ErrorStr))  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, ErrorStr.c\_str());  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;// Set the sampler2D uniforms to corresponding texture units  
&nbsp;glUniform1i(glGetUniformLocation(m\_ShaderProgram.uiId, "sTexture"), 0);
  

&nbsp;/\*  
&nbsp;&nbsp;Initialize Print3D  
&nbsp;\*/
  

&nbsp;// Is the screen rotated?  
&nbsp;bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  

&nbsp;if(m\_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR\_SUCCESS)  
&nbsp;{  
&nbsp;&nbsp;PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3Dn");  
&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  
&nbsp;
  

&nbsp;glGenFramebuffers(1, m\_uFBO);
  

  
&nbsp;/\*  
&nbsp;&nbsp;Create two handles for a frame buffer object.  
&nbsp;\*/  
&nbsp;glGenFramebuffers(2, m\_auiFbo);  
&nbsp;m\_i32CurrentFbo = 1;
  

&nbsp;/\*  
&nbsp;&nbsp;Get the currently bound frame buffer object. On most platforms this just gives 0.  
&nbsp; \*/  
&nbsp;glGetIntegerv(GL\_FRAMEBUFFER\_BINDING, &m\_i32OriginalFbo);
  

&nbsp;/\*  
&nbsp;&nbsp;Attach the renderable objects (e.g. textures) to the frame buffer object now as   
&nbsp;&nbsp;they will stay attached to the frame buffer object even when it is not bound.  
&nbsp;\*/
  

&nbsp;// We have two FBOs so we're doing the same for each  
&nbsp;for(int i = 0; i \< 2; ++i)  
&nbsp;{  
&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Firstly, to do anything with a frame buffer object we need to bind it. In the case  
&nbsp;&nbsp;&nbsp;below we are binding our frame buffer object to the frame buffer.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;glBindFramebuffer(GL\_FRAMEBUFFER, m\_auiFbo_);_
  

&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;To render to a texture we need to attach it texture to the frame buffer object.  
&nbsp;&nbsp;&nbsp;GL\_COLOR\_ATTACHMENT0 tells it to attach the texture to the colour buffer, the 0 on the  
&nbsp;&nbsp;&nbsp;end refers to the colour buffer we want to attach it to as a frame buffer object can  
&nbsp;&nbsp;&nbsp;have more than one colour buffer.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;glFramebufferTexture2D(GL\_FRAMEBUFFER, GL\_COLOR\_ATTACHMENT0, GL\_TEXTURE\_2D, m\_auiTexture_, 0);_
  

&nbsp;&nbsp;// Clear the color buffer for this FBO  
&nbsp;&nbsp;glClear(GL\_COLOR\_BUFFER\_BIT);
  

&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Create and bind a depth buffer to the frame buffer object.
  

&nbsp;&nbsp;&nbsp;A depth buffer isn't needed for this training course but will likely be   
&nbsp;&nbsp;&nbsp;required for most uses of frame buffer objects so its attachment is being   
&nbsp;&nbsp;&nbsp;demonstrated here.  
&nbsp;&nbsp;\*/
  

&nbsp;&nbsp;// Generate and bind the handle for the render buffer (which will become our depth buffer)  
&nbsp;&nbsp;glGenRenderbuffers(1, &m\_auiDepthBuffer_);  
&nbsp;&nbsp;glBindRenderbuffer(GL\_RENDERBUFFER, m\_auiDepthBuffer);_
  

&nbsp;&nbsp;/\*   
&nbsp;&nbsp;&nbsp;Currently it is unknown to GL that we want our new render buffer to be a depth buffer.  
&nbsp;&nbsp;&nbsp;glRenderbufferStorage will fix this and in this case will allocate a depth buffer of  
&nbsp;&nbsp;&nbsp;m\_i32TexSize by m\_i32TexSize.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;glRenderbufferStorage(GL\_RENDERBUFFER, GL\_DEPTH\_COMPONENT16, m\_i32TexSize, m\_i32TexSize);
  

&nbsp;&nbsp;// Now we have our depth buffer attach it to our frame buffer object.  
&nbsp;&nbsp;glFramebufferRenderbuffer(GL\_FRAMEBUFFER, GL\_DEPTH\_ATTACHMENT, GL\_RENDERBUFFER, m\_auiDepthBuffer_);  
&nbsp;}_
  

&nbsp;/\*  
&nbsp;&nbsp;Unbind the frame buffer object so rendering returns back to the backbuffer.  
&nbsp;\*/  
&nbsp;glBindFramebuffer(GL\_FRAMEBUFFER, m\_i32OriginalFbo);
  

&nbsp;// Use a nice bright blue as clear colour  
&nbsp;glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
  

&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;ReleaseView  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Code in ReleaseView() will be called by PVRShell when the  
&nbsp;&nbsp;&nbsp;&nbsp;application quits or before a change in the rendering context.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLES2RenderToTexture::ReleaseView()  
{  
&nbsp;// Delete textures  
&nbsp;glDeleteTextures(2, m\_auiTexture);  
&nbsp;glDeleteTextures(1, &m\_uiTrunkTex);
  

&nbsp;// Delete program and shader objects  
&nbsp;glDeleteProgram(m\_ShaderProgram.uiId);
  

&nbsp;glDeleteShader(m\_uiVertShader);  
&nbsp;glDeleteShader(m\_uiFragShader);
  

&nbsp;// Delete buffer objects  
&nbsp;glDeleteBuffers(1, &m\_uiVbo);  
&nbsp;glDeleteFramebuffers(2, m\_auiFbo);
  

&nbsp;glDeleteFramebuffers(1, m\_uFBO);
  

&nbsp;// Delete our depth buffer render buffers  
&nbsp;glDeleteRenderbuffers(2, m\_auiDepthBuffer);
  

&nbsp;// Release Print3D Textures  
&nbsp;m\_Print3D.ReleaseTextures();
  

&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;RenderScene  
&nbsp;@Return&nbsp;&nbsp;bool&nbsp;&nbsp;true if no error occured  
&nbsp;@Description&nbsp;Main rendering loop function of the program. The shell will  
&nbsp;&nbsp;&nbsp;&nbsp;call this function every frame.  
&nbsp;&nbsp;&nbsp;&nbsp;eglSwapBuffers() will be performed by PVRShell automatically.  
&nbsp;&nbsp;&nbsp;&nbsp;PVRShell will also manage important OS events.  
&nbsp;&nbsp;&nbsp;&nbsp;Will also manage relevent OS events. The user has access to  
&nbsp;&nbsp;&nbsp;&nbsp;these events through an abstraction layer provided by PVRShell.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLES2RenderToTexture::RenderScene()  
{  
&nbsp;/\* vary the branch angles on the fractal sinusoidally \*/  
&nbsp;m\_fAngle = (float)(sin(0.25\*PVRT\_PIf\*(float)(m\_ui32Framenum)/256.0f))\* 70.0f;
  

&nbsp;/\* largeish prime number in the angular frequency here, so the motion's not obviously periodic \*/  
&nbsp;m\_fAngle2 = (float)(sin((79.0f/256.0f)\*2.0\*PVRT\_PIf\*(float)(m\_ui32Framenum)/256.0f))\*100.0f + 30.0f;
  

&nbsp;/\* Convert the angles to radians. \*/  
&nbsp;m\_fAngle&nbsp; \*= 0.017453f;  
&nbsp;m\_fAngle2 \*= 0.017453f;
  

&nbsp;/\* Increase the frame count \*/  
&nbsp;if(PVRShellGetTime() - m\_ui32Time \> 10)  
&nbsp;{  
&nbsp;&nbsp;m\_ui32Time = PVRShellGetTime();  
&nbsp;&nbsp;m\_ui32Framenum += 2;
  

&nbsp;&nbsp;if(m\_ui32Framenum \> 20000)  
&nbsp;&nbsp;&nbsp;m\_ui32Framenum = 0;  
&nbsp;}
  

&nbsp;m\_framenumber ++;
  

&nbsp;
  

&nbsp;// Disable depth test and culling as we don't need it  
&nbsp;glDisable(GL\_DEPTH\_TEST);  
&nbsp;glDisable(GL\_CULL\_FACE);
  

  
&nbsp;if (m\_framenumber == 5)  
&nbsp;{  
&nbsp;&nbsp;if(!DrawScreen\_S())  
&nbsp;&nbsp;&nbsp;return false;  
&nbsp;}
  

&nbsp;// Draw the RenderToTexture  
&nbsp;if(!DrawScreen())  
&nbsp;&nbsp;return false;
  

&nbsp;
  

  
&nbsp;// Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools  
&nbsp;m\_Print3D.DisplayDefaultTitle("Render to Texture", "Using FBO", ePVRTPrint3DLogoIMG);  
&nbsp;m\_Print3D.Flush();
  

&nbsp;return true;  
}
  

bool OGLES2RenderToTexture::DrawScreen()  
{  
&nbsp;/\*  
&nbsp;&nbsp;We're going to do the following steps to create the effect. Texture 1 refers to the texture  
&nbsp;&nbsp;attached to the first FBO. Texture 2 refers to the texture attached to the second FBO.
  

&nbsp;&nbsp;Frame 0
  

&nbsp;&nbsp;&nbsp;1.&nbsp;We bind the second frame buffer object so we can do things to it.  
&nbsp;&nbsp;&nbsp;2.&nbsp;We draw two quads with Texture 1 applied.  
&nbsp;&nbsp;&nbsp;3.&nbsp;We draw the trunk.  
&nbsp;&nbsp;&nbsp;4.&nbsp;We make the back buffer current.  
&nbsp;&nbsp;&nbsp;5.&nbsp;We draw 6 quads with Texture 2 applied.
  

&nbsp;&nbsp;Frame 1
  

&nbsp;&nbsp;&nbsp;6.&nbsp;We bind the first frame buffer object so we can do things to it.  
&nbsp;&nbsp;&nbsp;7.&nbsp;We draw two quads with Texture 2 applied. Texture 2 still contains  
&nbsp;&nbsp;&nbsp;&nbsp;the image from the last frame.  
&nbsp;&nbsp;&nbsp;8.&nbsp;We draw the trunk.  
&nbsp;&nbsp;&nbsp;9.&nbsp;We make the back buffer current.  
&nbsp;&nbsp;&nbsp;10.&nbsp;We draw 6 quads with Texture 1 applied.
  

&nbsp;&nbsp;Frame 2
  

&nbsp;&nbsp;&nbsp;11.&nbsp;We bind the second frame buffer object so we can do things to it.  
&nbsp;&nbsp;&nbsp;12.&nbsp;We draw two quads with Texture 1 applied. Texture 1 still contains  
&nbsp;&nbsp;&nbsp;&nbsp;the image from the last frame.  
&nbsp;&nbsp;&nbsp;13.&nbsp;We draw the trunk.  
&nbsp;&nbsp;&nbsp;14.&nbsp;We make the back buffer current.  
&nbsp;&nbsp;&nbsp;15.&nbsp;We draw 6 quads with Texture 2 applied.
  

&nbsp;&nbsp;&nbsp;16.&nbsp;We repeat steps 6 through to 16 for consecutive frames.  
&nbsp;\*/
  

&nbsp;/\* Use the program created with the fragment and vertex shaders. \*/  
&nbsp;glUseProgram(m\_ShaderProgram.uiId);  
&nbsp;glBindBuffer(GL\_ARRAY\_BUFFER, m\_uiVbo);  
&nbsp;glDisable(GL\_CULL\_FACE);
  

&nbsp;glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glEnableVertexAttribArray(TEXCOORD\_ARRAY);  
&nbsp;glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 5 \* sizeof(float), 0);  
&nbsp;glVertexAttribPointer(TEXCOORD\_ARRAY, 2, GL\_FLOAT, GL\_FALSE, 5 \* sizeof(float), (void\*)(3 \* sizeof(float)));
  

&nbsp;
  

&nbsp;/\*  
&nbsp;&nbsp;Draw the fractal onto the current m\_ui32Texture  
&nbsp;\*/  
&nbsp;if(!RenderFractal())  
&nbsp;&nbsp;return false;
  

&nbsp;PVRTMat4 fMatrix;  
&nbsp;fMatrix = PVRTMat4::Identity();
  

&nbsp;/\*  
&nbsp;&nbsp;Bind the projection model view matrix (PMVMatrix) to  
&nbsp;&nbsp;the associated uniform variable in the shader  
&nbsp;\*/  
&nbsp;glUniformMatrix4fv(m\_ShaderProgram.auiLoc[eMVPMatrix], 1, GL\_FALSE, fMatrix.ptr());
  

&nbsp;// Clear the color and depth buffer  
&nbsp;glClearColor(0.6f, 0.8f, 1.0f, 1.0f);  
&nbsp;glClear(GL\_COLOR\_BUFFER\_BIT | GL\_DEPTH\_BUFFER\_BIT);
  

&nbsp;/\*  
&nbsp;&nbsp;Set the viewport ot fill the screen.  
&nbsp;\*/  
&nbsp;glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight));
  

&nbsp;/\*&nbsp;Set up the matrix we are going to use to rotate and scale the 6 quads.&nbsp;\*/  
&nbsp;PVRTMat4 fRotZ;  
&nbsp;fMatrix = PVRTMat4::Scale(0.8f \*(float)PVRShellGet(prefHeight) / (float)PVRShellGet(prefWidth), 0.8f, 0.8f);  
&nbsp;fRotZ = PVRTMat4::RotationZ(1.047f);
  

//&nbsp;glEnable(GL\_BLEND);  
&nbsp;glBlendFunc(GL\_DST\_COLOR, GL\_ONE);
  

  
&nbsp;/\* Bind the texture that we have rendered too.\*/  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_auiTexture[m\_i32CurrentFbo]);
  

&nbsp;/\* Draws 6 rotated quads \*/  
&nbsp;for(int i = 0; i \< 6; ++i)  
&nbsp;{  
&nbsp;&nbsp;// Set the transformationh matrix  
&nbsp;&nbsp;glUniformMatrix4fv(m\_ShaderProgram.auiLoc[eMVPMatrix], 1, GL\_FALSE, fMatrix.ptr());
  

&nbsp;&nbsp;// Draw the quad  
&nbsp;&nbsp;glDrawArrays(GL\_TRIANGLE\_STRIP, 5, 4);
  

&nbsp;&nbsp;// Rotate the object by another 60 degrees.  
&nbsp;&nbsp;fMatrix = fMatrix \* fRotZ;  
&nbsp;}  
&nbsp;
  

&nbsp;// Swap the FBOs  
&nbsp;m\_i32CurrentFbo = 1 - m\_i32CurrentFbo;
  

&nbsp;
  

  
&nbsp;glBindBuffer(GL\_ARRAY\_BUFFER, 0);  
&nbsp;glDisableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glDisableVertexAttribArray(TEXCOORD\_ARRAY);
  

&nbsp;return true;  
}
  

**bool OGLES2RenderToTexture::DrawScreen\_S()  
{  
&nbsp;/\* Use the program created with the fragment and vertex shaders. \*/  
&nbsp;glUseProgram(m\_ShaderProgram.uiId);  
&nbsp;glBindBuffer(GL\_ARRAY\_BUFFER, m\_uiVbo);  
&nbsp;glDisable(GL\_CULL\_FACE);**
  

**&nbsp;glEnableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glEnableVertexAttribArray(TEXCOORD\_ARRAY);  
&nbsp;glVertexAttribPointer(VERTEX\_ARRAY, 3, GL\_FLOAT, GL\_FALSE, 5 \* sizeof(float), 0);  
&nbsp;glVertexAttribPointer(TEXCOORD\_ARRAY, 2, GL\_FLOAT, GL\_FALSE, 5 \* sizeof(float), (void\*)(3 \* sizeof(float)));**
  

&nbsp;
  

**&nbsp;/\*  
&nbsp;&nbsp;Draw the fractal onto the current m\_ui32Texture  
&nbsp;\*/  
&nbsp;if(!RenderFractal())  
&nbsp;&nbsp;return false;**
  

**&nbsp;PVRTMat4 fMatrix;  
&nbsp;fMatrix = PVRTMat4::Identity();**
  

**&nbsp;/\*  
&nbsp;&nbsp;Bind the projection model view matrix (PMVMatrix) to  
&nbsp;&nbsp;the associated uniform variable in the shader  
&nbsp;\*/  
&nbsp;glUniformMatrix4fv(m\_ShaderProgram.auiLoc[eMVPMatrix], 1, GL\_FALSE, fMatrix.ptr());**
  

**&nbsp;// Clear the color and depth buffer  
&nbsp;glClearColor(0.6f, 0.8f, 1.0f, 1.0f);  
&nbsp;glClear(GL\_COLOR\_BUFFER\_BIT | GL\_DEPTH\_BUFFER\_BIT);**
  

**&nbsp;/\*  
&nbsp;&nbsp;Set the viewport ot fill the screen.  
&nbsp;\*/  
&nbsp;glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight));**
  

**&nbsp;/\*&nbsp;Set up the matrix we are going to use to rotate and scale the 6 quads.&nbsp;\*/  
&nbsp;PVRTMat4 fRotZ;  
&nbsp;fMatrix = PVRTMat4::Scale(0.8f \*(float)PVRShellGet(prefHeight) / (float)PVRShellGet(prefWidth), 0.8f, 0.8f);  
&nbsp;fRotZ = PVRTMat4::RotationZ(1.047f);**
  

**//&nbsp;glEnable(GL\_BLEND);  
&nbsp;glBlendFunc(GL\_DST\_COLOR, GL\_ONE);**
  

  
**&nbsp;/\* Bind the texture that we have rendered too.\*/  
&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_auiTexture[m\_i32CurrentFbo]);**
  

**&nbsp;/\* Draws 6 rotated quads \*/  
&nbsp;for(int i = 0; i \< 6; ++i)  
&nbsp;{  
&nbsp;&nbsp;// Set the transformationh matrix  
&nbsp;&nbsp;glUniformMatrix4fv(m\_ShaderProgram.auiLoc[eMVPMatrix], 1, GL\_FALSE, fMatrix.ptr());**
  

**&nbsp;&nbsp;// Draw the quad  
&nbsp;&nbsp;glDrawArrays(GL\_TRIANGLE\_STRIP, 5, 4);**
  

**&nbsp;&nbsp;// Rotate the object by another 60 degrees.  
&nbsp;&nbsp;fMatrix = fMatrix \* fRotZ;  
&nbsp;}**
  

**&nbsp;m\_pScreenBuf = (GLubyte\*) malloc(800 \* 600 \* 3);**
  

**&nbsp;glBindFramebuffer(GL\_FRAMEBUFFER, m\_uFBO[0]);   
&nbsp;glReadPixels(0, 0, 800, 600,GL\_RGB,GL\_UNSIGNED\_BYTE,m\_pScreenBuf);** 
  

**&nbsp;FILE \*fp = fopen("ScreenShot.raw","w");**
  

**&nbsp;for(int j=599; j\>=0; j--)  
&nbsp;{  
&nbsp;&nbsp;for(int i=799; i\>=0; i--)  
&nbsp;&nbsp;{  
&nbsp;&nbsp;&nbsp; fprintf(fp,"%d ",m\_pScreenBuf[(j\*800+i)\*3+2]);  
&nbsp;&nbsp;&nbsp; fprintf(fp,"%d ",m\_pScreenBuf[(j\*800+i)\*3+1]);  
&nbsp;&nbsp;&nbsp; fprintf(fp,"%d ",m\_pScreenBuf[(j\*800+i)\*3+0]);  
&nbsp;&nbsp;}  
&nbsp;}**
  

**&nbsp;fclose(fp);  
&nbsp;free (m\_pScreenBuf);  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;  
&nbsp;// Swap the FBOs  
&nbsp;m\_i32CurrentFbo = 1 - m\_i32CurrentFbo;**
  

  
**&nbsp;glBindBuffer(GL\_ARRAY\_BUFFER, 0);  
&nbsp;glDisableVertexAttribArray(VERTEX\_ARRAY);  
&nbsp;glDisableVertexAttribArray(TEXCOORD\_ARRAY);**
  

**&nbsp;return true;  
}**
  

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;\* Function Name&nbsp; : RenderFractal  
&nbsp;\* Description&nbsp;&nbsp;&nbsp; : Draws the RenderToTexture  
&nbsp;\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
bool OGLES2RenderToTexture::RenderFractal()  
{  
&nbsp;&nbsp;&nbsp; /\*  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; To do anything with a frame buffer object we need to bind it. In the case  
&nbsp;&nbsp; below we are binding our frame buffer object to the frame buffer.  
&nbsp;&nbsp;&nbsp; \*/  
&nbsp;glBindFramebuffer(GL\_FRAMEBUFFER, m\_auiFbo[m\_i32CurrentFbo]);
  

&nbsp;&nbsp;&nbsp; /\*  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If everything went ok then we can render to the texture.  
&nbsp;&nbsp;&nbsp; \*/  
&nbsp;if(glCheckFramebufferStatus(GL\_FRAMEBUFFER) == GL\_FRAMEBUFFER\_COMPLETE)  
&nbsp;{  
&nbsp;&nbsp;PVRTMat4 fMatrix, fTrans, fRot;
  

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Setup the Viewport to the dimensions of the texture  
&nbsp;&nbsp;glViewport(0, 0, m\_i32TexSize, m\_i32TexSize);
  

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Clear the screen by this colour  
&nbsp;&nbsp;glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  
&nbsp;&nbsp;glClear(GL\_COLOR\_BUFFER\_BIT | GL\_DEPTH\_BUFFER\_BIT);
  

&nbsp;&nbsp;// Bind the texture used for rendering to for the previous frame  
&nbsp;&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_auiTexture[1 - m\_i32CurrentFbo]);
  

&nbsp;&nbsp;// Enable additive blend  
&nbsp;&nbsp;glEnable(GL\_BLEND);  
&nbsp;&nbsp;glBlendFunc(GL\_ONE, GL\_ONE);
  

&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Initialise the translation array that we are going to use to translate both of the  
&nbsp;&nbsp;&nbsp;the quads that we are going to render to.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;fTrans = PVRTMat4::Translation(0.0f, -0.4f, 0.0f);
  

&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Set up the rotation matrix that we are going to use to rotate the two quads  
&nbsp;&nbsp;&nbsp;that have the previous texture created for the previous frame bound  
&nbsp;&nbsp;&nbsp;to them.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;fRot = PVRTMat4::RotationZ(m\_fAngle + m\_fAngle2);  
&nbsp;&nbsp;fMatrix = fTrans \* fRot;  
&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Set the transformation matrix in the shader.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;glUniformMatrix4fv(m\_ShaderProgram.auiLoc[eMVPMatrix], 1, GL\_FALSE, fMatrix.ptr());  
&nbsp;&nbsp;glDrawArrays(GL\_TRIANGLE\_STRIP, 5, 4);
  

&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Rotate the second quad the other way.  
&nbsp;&nbsp;\*/  
&nbsp;&nbsp;fRot = PVRTMat4::RotationZ(m\_fAngle - m\_fAngle2);  
&nbsp;&nbsp;fMatrix = fTrans \* fRot;  
&nbsp;&nbsp;glUniformMatrix4fv(m\_ShaderProgram.auiLoc[eMVPMatrix], 1, GL\_FALSE, fMatrix.ptr());  
&nbsp;&nbsp;glDrawArrays(GL\_TRIANGLE\_STRIP, 5, 4);
  

&nbsp;&nbsp;/\*  
&nbsp;&nbsp;&nbsp;Now draw the trunk.  
&nbsp;&nbsp;&nbsp;&nbsp; \*/  
&nbsp;&nbsp;// Bind the trunk texture  
&nbsp;&nbsp;glBindTexture(GL\_TEXTURE\_2D, m\_uiTrunkTex);
  

&nbsp;&nbsp;fMatrix = PVRTMat4::Identity();  
&nbsp;&nbsp;glUniformMatrix4fv(m\_ShaderProgram.auiLoc[eMVPMatrix], 1, GL\_FALSE, fMatrix.ptr());
  

&nbsp;&nbsp;// Draw the trunk  
&nbsp;&nbsp;glDrawArrays(GL\_TRIANGLE\_STRIP, 0, 5);
  

&nbsp;}
  

&nbsp;/\*  
&nbsp;&nbsp;Unbind the frame buffer object so rendering returns back to the backbuffer.  
&nbsp;\*/  
&nbsp;glBindFramebuffer(GL\_FRAMEBUFFER, m\_i32OriginalFbo);  
&nbsp;return true;  
}
  

/\*!\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;@Function&nbsp;&nbsp;NewDemo  
&nbsp;@Return&nbsp;&nbsp;PVRShell\*&nbsp;&nbsp;The demo supplied by the user  
&nbsp;@Description&nbsp;This function must be implemented by the user of the shell.  
&nbsp;&nbsp;&nbsp;&nbsp;The user should return its PVRShell object defining the  
&nbsp;&nbsp;&nbsp;&nbsp;behaviour of the application.  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
PVRShell\* NewDemo()  
{  
&nbsp;return new OGLES2RenderToTexture();  
}
  

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
&nbsp;End of file (OGLES2RenderToTexture.cpp)  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
  

&nbsp;

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [March 24, 2011, 9:41pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/7 "2011-03-24T21:41:56Z")

</div>

Maybe I know the reason now. I should attach a Renderbuffer, GL\_DEPTH\_ATTACHMENT and just like what the original code does to the original buffer… Correct me if I am wrong.

&nbsp;
  

Actually, I found out even without using a separate framebuffer, I still can achieve my goal. I found that when I called glReadPixels, the current frame will not be displayed and I can do whatever I want.&nbsp; At least, this is true based on my test today. Is this what the opengel ES 2.0 will do when glReadPixels is called?&nbsp; 
  

&nbsp;
  

Thank you very much,
  

&nbsp;
  

Renaissance
  

&nbsp;
  

&nbsp;

---

<div class="post-metadata">

**Author:** ![dumbledore-2](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.imgtec.com/dumbledore-2/32/101_2.png) [@dumbledore-2](https://forums.imgtec.com/u/dumbledore-2)\
**Post date:** [March 25, 2011, 1:11pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/8 "2011-03-25T13:11:19Z")

</div>

No, glReadPixels just transfers the pixels from the currently bound FB on the GPU to the CPU/RAM. In order not to show the result, you need to render to an FBO, not the FB, i.e. 0.

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [April 12, 2011, 3:54pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/9 "2011-04-12T15:54:03Z")

</div>

Based on the above method, I can successfully make off-screen rendering and image saving in the frame work of one training course. The code is running well on the PC version. Then I re-compile the code and re-run it on OMAP system, I still can get the off-screen image saved. But the image content is all-zero. In other word, the image is all black.

  

The codes I used for these two cases are the same. Can anyone give me a hint why the OMAP version failed?  

&nbsp;
  

Thank you very much,
  

&nbsp;
  

Renaissance

---

<div class="post-metadata">

**Author:** ![renaissance](https://avatars.discourse-cdn.com/v4/letter/r/b19c9b/32.png) [@renaissance](https://forums.imgtec.com/u/renaissance)\
**Post date:** [May 4, 2011, 7:59pm UTC](https://forums.imgtec.com/t/how-to-skip-frames-in-renderscene/1030/10 "2011-05-04T19:59:35Z")

</div>

I just figure out that the reason is I called the glReadPixels() function wrong.

&nbsp;
  

I should use the following method
  

glReadPixels(0, 0, 800, 600,GL\_RGBA,GL\_UNSIGNED\_BYTE,m\_pScreenBuf); 
  

&nbsp;
  

Not the one I used in my previous version
  

**glReadPixels(0, 0, 800, 600,GL\_RGB,GL\_UNSIGNED\_BYTE,m\_pScreenBuf);** 
  

  

&nbsp;
  

Even though,&nbsp;when I move on to my code with this update, where I want to change the background color only for the frameshot (I do not want to see that on the screen), I noticed that during the pause when the data is being written to external file, on the display from the OMAP, I can see this modified frame.&nbsp; Since this is an off-screen rendering, why I still can see this on the screen? 
  

&nbsp;
  

The same code works well on the PC (windows version) and I do not see this frame on the screen while the modified frame is saved to external file.  

  

What caused this different effects?
  

&nbsp;
  

Thank you very much,
  

&nbsp;
  

Renaissance
