/*!**************************************************************************** @Function RenderScene @Return bool true if no error occurred @Description Main rendering loop function of the program. The shell will call this function every frame. eglSwapBuffers() will be performed by PVRShell automatically. PVRShell will also manage important OS events. Will also manage relevant OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES2FilmTV::RenderScene() { // Use shader program glUseProgram(m_ShaderProgram.uiId); // Enable the vertex attribute arrays glEnableVertexAttribArray(VERTEX_ARRAY); glEnableVertexAttribArray(NORMAL_ARRAY); // Render everything from the mini-camera's point of view if we have the FBOs CalcMiniCameraView(); if(m_bFBOsCreated) { // Setup the Viewport to the dimensions of the texture glViewport(0, 0, m_i32TexSize, m_i32TexSize); glBindFramebuffer(GL_FRAMEBUFFER, m_uiFbo[m_i32CurrentFBO]); DrawPODScene(m_MiniCamViewProj, false); if(m_bDiscard) // Was GL_EXT_discard_framebuffer supported? { /* Give the drivers a hint that we don't want the depth and stencil information stored for future use. Note: This training course doesn't have any stencil information so the STENCIL_ATTACHMENT enum is used for demonstrations purposes only and will be ignored by the driver. */ const GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT }; m_Extensions.glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments); } glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFB); // Render everything // Setup the Viewport to the dimensions of the screen glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight)); } DrawPODScene(m_ViewProjection, true); // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools m_Print3D.DisplayDefaultTitle("FilmTV", "", ePVRTPrint3DSDKLogo); m_Print3D.Flush(); // Swap the FBO that we want to render to m_i32CurrentFBO = 1 - m_i32CurrentFBO; ++m_i32Frame; return true; }
/*!**************************************************************************** @Function InitView @Return bool true if no error occurred @Description Code in InitView() will be called by PVRShell upon initialization or after a change in the rendering context. Used to initialize variables that are dependant on the rendering context (e.g. textures, vertex buffers, etc.) ******************************************************************************/ bool OGLES2FilmTV::InitView() { CPVRTString ErrorStr; // Initialize VBO data if(!LoadVbos(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Load textures if(!LoadTextures(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Load and compile the shaders & link programs if(!LoadShaders(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Initialize Print3D bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } //Set OpenGL ES render states needed for this demo // Enable backface culling and depth test glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Find the largest square power of two texture that fits into the viewport m_i32TexSize = 1; int iSize = PVRT_MIN(PVRShellGet(prefWidth), PVRShellGet(prefHeight)); while (m_i32TexSize * 2 < iSize) m_i32TexSize *= 2; // Get the currently bound frame buffer object. On most platforms this just gives 0. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFB); for(int i = 0; i < 2; ++i) { // Create texture for the FBO glGenTextures(1, &m_uiTexture[i]); glBindTexture(GL_TEXTURE_2D, m_uiTexture[i]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_i32TexSize, m_i32TexSize, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); // Create FBO glGenFramebuffers(1, &m_uiFbo[i]); glBindFramebuffer(GL_FRAMEBUFFER, m_uiFbo[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_uiTexture[i], 0); glGenRenderbuffers(1, &m_uiDepthBuffer[i]); glBindRenderbuffer(GL_RENDERBUFFER, m_uiDepthBuffer[i]); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_i32TexSize, m_i32TexSize); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthBuffer[i]); // Check that our FBO creation was successful GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(uStatus != GL_FRAMEBUFFER_COMPLETE) { m_bFBOsCreated = false; PVRShellOutputDebug("ERROR: Failed to initialise FBO"); break; } // Clear the colour buffer for this FBO glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFB); // Setup the main camera PVRTVec3 vFrom, vTo(0.0f), vUp(0.0f, 1.0f, 0.0f); float fFOV; // Camera nodes are after the mesh and light nodes in the array int i32CamID = m_Scene.pNode[m_Scene.nNumMeshNode + m_Scene.nNumLight + g_ui32Camera].nIdx; // Get the camera position, target and field of view (fov) if(m_Scene.pCamera[i32CamID].nIdxTarget != -1) // Does the camera have a target? fFOV = m_Scene.GetCameraPos( vFrom, vTo, g_ui32Camera); // vTo is taken from the target node else fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, g_ui32Camera); // vTo is calculated from the rotation m_View = PVRTMat4::LookAtRH(vFrom, vTo, vUp); // Calculate the projection matrix PVRTMat4 mProjection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate); m_ViewProjection = mProjection * m_View; // Check to see if the GL_EXT_discard_framebuffer extension is supported if(m_bFBOsCreated && (m_bDiscard = CPVRTgles2Ext::IsGLExtensionSupported("GL_EXT_discard_framebuffer")) != false) { m_Extensions.LoadExtensions(); m_bDiscard = m_Extensions.glDiscardFramebufferEXT != 0; } return true; }
/*!**************************************************************************** @Function RenderScene @Return bool true if no error occured @Description Main rendering loop function of the program. The shell will call this function every frame. eglSwapBuffers() will be performed by PVRShell automatically. PVRShell will also manage important and relevant OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES2EdgeDetection::RenderScene() { // Declares world orientation variables. PVRTMat4 mWorld, mMVP; // Updates the current time. m_ulCurrentTime=PVRShellGetTime(); #ifdef SHOW_MAX_FPS //Updates and checks framerate. m_iFrameCount+=1; if (m_ulCurrentTime-m_ulPreviousTimeFPS>=1000) { m_fFPS=(GLfloat)m_iFrameCount/(GLfloat)(m_ulCurrentTime-m_ulPreviousTimeFPS)*1000.0f; m_ulPreviousTimeFPS=m_ulCurrentTime; m_iFrameCount=0; } // Display fps data m_Print3D.Print3D(2.0f, 10.0f, 0.75f, 0xff0000ff, "%i fps", (int)m_fFPS); #endif // Time dependant updates for the rotational velocity of the scene. m_fAngleY += 0.0002f*PVRT_PI*(m_ulCurrentTime-m_ulPreviousTimeAngle); m_ulPreviousTimeAngle=PVRShellGetTime(); // Render to our texture (bracketed for viewing convenience) { // Use the first shader program to perform the initial render of the mask. glUseProgram(m_PreShader.uiId); // Bind render-to-texture frame buffer and set the viewPort glBindFramebuffer(GL_FRAMEBUFFER, m_uiFramebufferObject); glViewport(0, 0, m_i32TexWidth, m_i32TexHeight); #if defined(__PALMPDK__) // Enable writing to the alpha channel again as usually it is disabled so // we don't blend with the video layer on webOS devices. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); #endif // Clear the color and depth buffer of our FBO glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Rotates the scene and sets the model-view-projection matrix mWorld = PVRTMat4::RotationY(m_fAngleY); mMVP = m_mR2TProjection * m_mR2TView * mWorld; // Send the view matrix information to the shader. glUniformMatrix4fv(m_PreShader.auiLoc[eMVPMatrix], 1, GL_FALSE, mMVP.f); // Enable vertex attribute array glEnableVertexAttribArray(eVERTEX_ARRAY); //Enable depth testing and culling. glEnable(GL_DEPTH_TEST); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // Draw our models by looping through each mesh as defined by nNumMesh. for (unsigned int i=0; i<m_Scene.nNumMeshNode; i++) { DrawMesh(i); } // Unbind the VBO and index buffer. glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); if(m_bDiscard) // Was GL_EXT_discard_framebuffer supported? { //Give the drivers a hint that we don't want stencil or depth information to be stored for later. const GLenum attachment = GL_DEPTH_ATTACHMENT; m_Extensions.glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment); } #if defined(__PALMPDK__) // Disable writing to the alpha channel again so we don't blend with the video layer on webOS devices glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); #endif } // Bind the original frame buffer to draw to screen and set the Viewport. glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFramebuffer); glViewport(0, 0, m_i32TexWidth, m_i32TexHeight); // Clear the color and depth buffers for the screen. glClear(GL_COLOR_BUFFER_BIT); // Uses PVRShell input handling to update the line width in the edge detection shaders. if (PVRShellIsKeyPressed(PVRShellKeyNameRIGHT)) { m_fLineWidth++; if (m_fLineWidth>10) m_fLineWidth=10; } if (PVRShellIsKeyPressed(PVRShellKeyNameLEFT)) { m_fLineWidth--; if (m_fLineWidth<1) m_fLineWidth=1; } // Uses PVRShell input to choose which post shader program to use for post processing. // Loops through all shaders defined in EPostShaders if (PVRShellIsKeyPressed(PVRShellKeyNameUP)) { if (m_uiShaderID==eNumPostShaders-1) m_uiShaderID=0; else m_uiShaderID++; } else if (PVRShellIsKeyPressed(PVRShellKeyNameDOWN)) { if (m_uiShaderID==0) m_uiShaderID=eNumPostShaders-1; else m_uiShaderID--; } // Sets the shader based on the shader ID value, and sets the line width each frame (as it can change); glUseProgram(m_PostShaders[m_uiShaderID].uiId); glUniform2f(m_PostShaders[m_uiShaderID].auiLoc[ePixelSize],m_fLineWidth/(float)m_i32TexWidth,m_fLineWidth/(float)m_i32TexHeight); /* Note: We do not need to pass any projection data to these shaders as they are used only to render a texture to a full screen quad which is parallel with the viewport. The model meshes have already been positioned in the previous shader and now only exist as a 2D image.*/ // Enable texture attribute array glEnableVertexAttribArray(eTEXCOORD_ARRAY); // Draw the fullscreen quad to render the screen to. DrawQuad(); // Disable the vertex and texture attribute arrays glDisableVertexAttribArray(eTEXCOORD_ARRAY); glDisableVertexAttribArray(eVERTEX_ARRAY); // Print the demo title, current post shader's name and the line width if applicable m_Print3D.DisplayDefaultTitle("Edge Detection", "", ePVRTPrint3DSDKLogo); m_Print3D.Print3D(5,80,1,0xff885500,g_aszPostShaderNames[m_uiShaderID]); if (!strcmp(c_aszPostShaderDefines[m_uiShaderID][0],"EDGE_DETECTION")) m_Print3D.Print3D(5,90,0.7f,0xff000055,"Line Width = %i", (int)m_fLineWidth); m_Print3D.Flush(); return true; }
/*!**************************************************************************** @Function InitView @Return bool true if no error occured @Description Code in InitView() will be called by PVRShell upon initialization or after a change in the rendering context. Used to initialize variables that are dependant on the rendering context (e.g. textures, vertex buffers, etc.) ******************************************************************************/ bool OGLES2EdgeDetection::InitView() { // Store width and height of the viewport. m_i32TexWidth = PVRShellGet(prefWidth); m_i32TexHeight = PVRShellGet(prefHeight); /* Get the current frame buffer object. As the program hasn't set it yet, this is the default buffer. On most platforms this just gives 0, but there are exceptions. */ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFramebuffer); // Create string for error codes. CPVRTString ErrorStr; // Checks to see if the screen is rotated or not. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); // Initialize VBO data if(!LoadVbos(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Initialise Print3D if(m_Print3D.SetTextures(0,m_i32TexWidth,m_i32TexHeight,bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Load external textures and create internal ones. if(!LoadTextures(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Load and compile the shaders & link programs if (!LoadShaders(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Check to see if the GL_EXT_discard_framebuffer extension is supported m_bDiscard = CPVRTgles2Ext::IsGLExtensionSupported("GL_EXT_discard_framebuffer"); if(m_bDiscard) { m_Extensions.LoadExtensions(); m_bDiscard = m_Extensions.glDiscardFramebufferEXT != 0; } // Creates and checks FBO creation if (!CreateFBO(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } SetupView(bRotate); return true; }
/*!**************************************************************************** @Function RenderScene @Return bool true if no error occured @Description Main rendering loop function of the program. The shell will call this function every frame. eglSwapBuffers() will be performed by PVRShell automatically. PVRShell will also manage important OS events. Will also manage relevent OS events. The user has access to these events through an abstraction layer provided by PVRShell. ******************************************************************************/ bool OGLES2Bloom::RenderScene() { HandleInput(); // Calculate the mask and light rotation based on the passed time static unsigned long ulPreviousTime = PVRShellGetTime(); unsigned long ulNowTime = PVRShellGetTime(); m_fRotation += PVRT_PI * (ulNowTime - ulPreviousTime) * 0.0002f; ulPreviousTime = ulNowTime; if (m_fRotation > (PVRT_PI * 2.0f)) m_fRotation -= PVRT_PI * 2.0f; // Calculate the model, view and projection matrix float fModelAngleY = m_fRotation; float fLightAngleY = -m_fRotation; PVRTMat4 mWorld = PVRTMat4::RotationY(fModelAngleY); PVRTMat4 mLight = PVRTMat4::RotationY(fLightAngleY); PVRTMat4 mView = PVRTMat4::LookAtRH(PVRTVec3(0, 0, 150), PVRTVec3(0, 0, 0), PVRTVec3(0, 1, 0)); bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); PVRTMat4 mProjection = PVRTMat4::PerspectiveFovRH(g_fCameraFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate); PVRTMat4 mMVP = mProjection * mView * mWorld; // Simple rotating directional light in model-space PVRTVec4 vMsLightPos = mWorld.inverse() * mLight * PVRTVec4(0.5f, -1, -0.5f, 0).normalize(); glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo); glClearColor(0.075f, 0.1f, 0.125f, 0.0f); glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Use simple shader program to render the mask glUseProgram(m_ShaderProgram.uiId); glUniformMatrix4fv(m_ShaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.f); glUniform3fv(m_ShaderProgram.uiLightDirLoc, 1, &vMsLightPos.x); // Draw the mesh glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_uiBaseTex); DrawMesh(0); if (m_bApplyBloom) { // First render the objects which shall have the bloom effect to a texture glBindFramebuffer(GL_FRAMEBUFFER, m_uiBlurFramebufferObjects[0]); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glViewport(0, 0, m_i32TexSize, m_i32TexSize); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(m_PreBloomShaderProgram.uiId); glUniformMatrix4fv(m_PreBloomShaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.f); glUniform3fv(m_PreBloomShaderProgram.uiLightDirLoc, 1, &vMsLightPos.x); glUniform1f(m_PreBloomShaderProgram.uiBloomIntensity, m_fBloomIntensity); // Draw the mesh glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_uiBloomMappingTexture); DrawMesh(0); if(m_bDiscard) // Was GL_EXT_discard_framebuffer supported? { //Give the drivers a hint that we don't want depth information to be stored for later. const GLenum attachment = GL_DEPTH_ATTACHMENT; m_Extensions.glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment); } /* Blur the generated image n-times */ for (unsigned int i=0; i < m_ui32BlurPasses; i++) { /* Apply horizontal blur */ glBindFramebuffer(GL_FRAMEBUFFER, m_uiBlurFramebufferObjects[1]); glViewport(0, 0, m_i32TexSize, m_i32TexSize); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_uiBlurTextures[0]); // Use the shader program for the scene glUseProgram(m_BlurShaderProgram.uiId); glUniform1f(m_BlurShaderProgram.uiTexelOffsetX, m_fTexelOffset); glUniform1f(m_BlurShaderProgram.uiTexelOffsetY, 0.0f); DrawAxisAlignedQuad(PVRTVec2(-1, -1), PVRTVec2(1, 1)); //No attachments we can invalidate here, as only color was used which is necessary. /* Apply vertical blur */ glBindFramebuffer(GL_FRAMEBUFFER, m_uiBlurFramebufferObjects[0]); glViewport(0, 0, m_i32TexSize, m_i32TexSize); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_uiBlurTextures[1]); // Use the shader program for the scene glUseProgram(m_BlurShaderProgram.uiId); glUniform1f(m_BlurShaderProgram.uiTexelOffsetX, 0.0f); glUniform1f(m_BlurShaderProgram.uiTexelOffsetY, m_fTexelOffset); DrawAxisAlignedQuad(PVRTVec2(-1, -1), PVRTVec2(1, 1)); if(m_bDiscard) // Was GL_EXT_discard_framebuffer supported? { //Give the drivers a hint that we don't want depth information to be stored for later. const GLenum attachment = GL_DEPTH_ATTACHMENT; m_Extensions.glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment); } } /* Draw scene with bloom */ glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo); glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight)); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_uiBlurTextures[0]); // Use the shader program for the scene glUseProgram(m_PostBloomShaderProgram.uiId); /* The following section will draw a quad on the screen where the post processing pixel shader shall be executed. Try to minimize the area by only drawing where the actual post processing should happen, as this is a very costly operation. */ if (PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen)) { DrawAxisAlignedQuad(PVRTVec2(-0.875f, -0.5f), PVRTVec2(0.0625f, 0.25f), PVRTVec2(0.8755f, 0.5f), PVRTVec2(0.9375f, 0.75f)); } else { DrawAxisAlignedQuad(PVRTVec2(-0.5f, -0.875f), PVRTVec2(0.25f, 0.0625f), PVRTVec2(0.5f, 0.875f), PVRTVec2(0.75f, 0.9375f)); } glDisable(GL_BLEND); } // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools m_Print3D.DisplayDefaultTitle("Bloom", NULL, ePVRTPrint3DSDKLogo); m_Print3D.Flush(); return true; }
/*!**************************************************************************** @Function InitView @Return bool true if no error occured @Description Code in InitView() will be called by PVRShell upon initialization or after a change in the rendering context. Used to initialize variables that are dependant on the rendering context (e.g. textures, vertex buffers, etc.) ******************************************************************************/ bool OGLES2Bloom::InitView() { CPVRTString ErrorStr; /* Initialize VBO data */ if(!LoadVbos(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } /* Load textures */ if(!LoadTextures(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } /* Load and compile the shaders & link programs */ if(!LoadShaders(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } // Check to see if the GL_EXT_discard_framebuffer extension is supported m_bDiscard = CPVRTgles2Ext::IsGLExtensionSupported("GL_EXT_discard_framebuffer"); if(m_bDiscard) { m_Extensions.LoadExtensions(); m_bDiscard = m_Extensions.glDiscardFramebufferEXT != 0; } /* Initialize Print3D */ bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } /* Get the currently bound frame buffer object. On most platforms this just gives 0. */ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // create a new depth render buffer glGenRenderbuffers(1, &m_uiDepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_uiDepthBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_i32TexSize, m_i32TexSize); /* Set OpenGL ES render states needed for this training course */ glGenFramebuffers(2, m_uiBlurFramebufferObjects); for (unsigned int i=0; i < 2; i++) { glBindFramebuffer(GL_FRAMEBUFFER, m_uiBlurFramebufferObjects[i]); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // The first render target needs a depth buffer, as we have to draw "blooming" 3d objects into it if (i==0) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiDepthBuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_uiBlurTextures[i], 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { PVRShellSet(prefExitMessage, "ERROR: Frame buffer not set up correctly\n"); return false; } } glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo); return true; }