/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ #include "GlowingScene.h" #include "BlurMeshNode.h" #include #include #include #include #include #include #include #include GlowingScene::GlowingScene(int width, int height) : Scene(width, height), mFboId(0), mMainProgram(NULL), mBlurProgram(NULL) { mFboWidth = GLUtils::roundUpToSmallestPowerOf2(width); mFboHeight = GLUtils::roundUpToSmallestPowerOf2(height); mFboRatio = mFboWidth / mFboHeight; mFboModelMatrix = setUpModelMatrix(); mFboViewMatrix = setUpViewMatrix(); mFboProjectionMatrix = setUpProjectionMatrix(mFboWidth, mFboHeight); } bool GlowingScene::setUpContext() { if (!Scene::setUpContext()) { return false; } // Create a fbo glGenFramebuffers(1, &mFboId); return true; } bool GlowingScene::setUpPrograms() { // Main Program const char* vertex = GLUtils::openTextFile("vertex/perspective"); const char* fragment = GLUtils::openTextFile("fragment/perspective"); if (vertex == NULL || fragment == NULL) { return false; } GLuint programId = GLUtils::createProgram(&vertex, &fragment); delete[] vertex; delete[] fragment; if (programId == 0) { return false; } mMainProgram = new PerspectiveProgram(programId); // Blur Program vertex = GLUtils::openTextFile("vertex/blur"); fragment = GLUtils::openTextFile("fragment/blur"); if (vertex == NULL || fragment == NULL) { return false; } programId = GLUtils::createProgram(&vertex, &fragment); delete[] vertex; delete[] fragment; if (programId == 0) { return false; } mBlurProgram = new Program(programId); return true; } Matrix* GlowingScene::setUpModelMatrix() { return new Matrix(); } Matrix* GlowingScene::setUpViewMatrix() { // Position the eye in front of the origin. float eyeX = 0.0f; float eyeY = 0.0f; float eyeZ = 10.0f; // Look at the origin float centerX = 0.0f; float centerY = 0.0f; float centerZ = 0.0f; // Set up vector. float upX = 0.0f; float upY = 1.0f; float upZ = 0.0f; // Set the view matrix. return Matrix::newLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); } Matrix* GlowingScene::setUpProjectionMatrix(float width, float height) { // Create a new perspective projection matrix. The height will stay the same // while the width will vary as per aspect ratio. float ratio = width / height; float left = -ratio; float right = ratio; float bottom = -1.0f; float top = 1.0f; float near = 8.0f; float far = 12.0f; return Matrix::newFrustum(left, right, bottom, top, near, far); } bool GlowingScene::setUpTextures() { SCOPED_TRACE(); mTextureIds.push_back(GLUtils::genTexture(mWidth, mHeight, 0)); // fbo mTextureIds.push_back(GLUtils::genTexture(mWidth, mHeight, 0)); // tmp1 mTextureIds.push_back(GLUtils::genTexture(mWidth, mHeight, 0)); // tmp2 mTextureIds.push_back(GLUtils::loadTexture("texture/arc.png")); return true; } bool GlowingScene::setUpMeshes() { SCOPED_TRACE(); mMeshes.push_back(GLUtils::loadMesh("mesh/plane.cob")); mMeshes.push_back(GLUtils::loadMesh("mesh/arc.cob")); return true; } bool GlowingScene::tearDown() { SCOPED_TRACE(); if (mMainProgram != NULL) { delete mMainProgram; mMainProgram = NULL; } if (mBlurProgram != NULL) { delete mBlurProgram; mBlurProgram = NULL; } if (mFboId != 0) { glDeleteFramebuffers(1, &mFboId); mFboId = 0; } delete mFboModelMatrix; mFboModelMatrix = NULL; delete mFboViewMatrix; mFboViewMatrix = NULL; delete mFboProjectionMatrix; mFboProjectionMatrix = NULL; return Scene::tearDown(); } bool GlowingScene::updateSceneGraphs(int frame) { // To render the mesh to the FBO ProgramNode* lightSceneGraph = new ProgramNode(*mMainProgram); mSceneGraphs.push_back(lightSceneGraph); MeshNode* meshNode = new PerspectiveMeshNode(mMeshes[1], mTextureIds[3]); lightSceneGraph->addChild(meshNode); // To blur the image ProgramNode* blurSceneGraph = new ProgramNode(*mBlurProgram); mSceneGraphs.push_back(blurSceneGraph); meshNode = new BlurMeshNode(mMeshes[0], mTextureIds[0], mTextureIds[1], mTextureIds[2], mFboWidth, mFboHeight); blurSceneGraph->addChild(meshNode); // Blur To screen ProgramNode* glowSceneGraph = new ProgramNode(*mMainProgram); mSceneGraphs.push_back(glowSceneGraph); Matrix* transformMatrix = Matrix::newScale(mFboRatio, 1.0f, 1.0f); TransformationNode* transformNode = new TransformationNode(transformMatrix); glowSceneGraph->addChild(transformNode); meshNode = new PerspectiveMeshNode(mMeshes[0], mTextureIds[2]); transformNode->addChild(meshNode); return true; } bool GlowingScene::draw() { SCOPED_TRACE(); glBindFramebuffer(GL_FRAMEBUFFER, mFboId); // Use FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureIds[0], 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return false; } glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear (GL_COLOR_BUFFER_BIT); glViewport(0, 0, mFboWidth, mFboHeight); mFboModelMatrix->identity(); mSceneGraphs[0]->drawProgram(*mFboModelMatrix, *mFboViewMatrix, *mFboProjectionMatrix); // Mesh mFboModelMatrix->identity(); mSceneGraphs[1]->drawProgram(*mFboModelMatrix, *mFboViewMatrix, *mFboProjectionMatrix); // Blur glBindFramebuffer(GL_FRAMEBUFFER, 0); // Use Screen glViewport(0, 0, mWidth, mHeight); Scene::drawSceneGraph(2); // Blur to Screen return true; }