Home | History | Annotate | Download | only in glowing
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
      5  * in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License
     10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
     11  * or implied. See the License for the specific language governing permissions and limitations under
     12  * the License.
     13  */
     14 #include "GlowingScene.h"
     15 #include "BlurMeshNode.h"
     16 
     17 #include <Trace.h>
     18 
     19 #include <graphics/PerspectiveMeshNode.h>
     20 #include <graphics/PerspectiveProgram.h>
     21 #include <graphics/Program.h>
     22 #include <graphics/GLUtils.h>
     23 #include <graphics/Mesh.h>
     24 #include <graphics/ProgramNode.h>
     25 #include <graphics/TransformationNode.h>
     26 
     27 GlowingScene::GlowingScene(int width, int height) :
     28         Scene(width, height), mFboId(0), mMainProgram(NULL), mBlurProgram(NULL) {
     29     mFboWidth = GLUtils::roundUpToSmallestPowerOf2(width);
     30     mFboHeight = GLUtils::roundUpToSmallestPowerOf2(height);
     31     mFboRatio = mFboWidth / mFboHeight;
     32     mFboModelMatrix = setUpModelMatrix();
     33     mFboViewMatrix = setUpViewMatrix();
     34     mFboProjectionMatrix = setUpProjectionMatrix(mFboWidth, mFboHeight);
     35 }
     36 
     37 bool GlowingScene::setUpContext() {
     38     if (!Scene::setUpContext()) {
     39         return false;
     40     }
     41     // Create a fbo
     42     glGenFramebuffers(1, &mFboId);
     43     return true;
     44 }
     45 
     46 bool GlowingScene::setUpPrograms() {
     47     // Main Program
     48     const char* vertex = GLUtils::openTextFile("vertex/perspective");
     49     const char* fragment = GLUtils::openTextFile("fragment/perspective");
     50     if (vertex == NULL || fragment == NULL) {
     51         return false;
     52     }
     53     GLuint programId = GLUtils::createProgram(&vertex, &fragment);
     54     delete[] vertex;
     55     delete[] fragment;
     56     if (programId == 0) {
     57         return false;
     58     }
     59     mMainProgram = new PerspectiveProgram(programId);
     60     // Blur Program
     61     vertex = GLUtils::openTextFile("vertex/blur");
     62     fragment = GLUtils::openTextFile("fragment/blur");
     63     if (vertex == NULL || fragment == NULL) {
     64         return false;
     65     }
     66     programId = GLUtils::createProgram(&vertex, &fragment);
     67     delete[] vertex;
     68     delete[] fragment;
     69     if (programId == 0) {
     70         return false;
     71     }
     72     mBlurProgram = new Program(programId);
     73     return true;
     74 }
     75 
     76 Matrix* GlowingScene::setUpModelMatrix() {
     77     return new Matrix();
     78 }
     79 
     80 Matrix* GlowingScene::setUpViewMatrix() {
     81     // Position the eye in front of the origin.
     82     float eyeX = 0.0f;
     83     float eyeY = 0.0f;
     84     float eyeZ = 10.0f;
     85 
     86     // Look at the origin
     87     float centerX = 0.0f;
     88     float centerY = 0.0f;
     89     float centerZ = 0.0f;
     90 
     91     // Set up vector.
     92     float upX = 0.0f;
     93     float upY = 1.0f;
     94     float upZ = 0.0f;
     95 
     96     // Set the view matrix.
     97     return Matrix::newLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
     98 }
     99 
    100 Matrix* GlowingScene::setUpProjectionMatrix(float width, float height) {
    101     // Create a new perspective projection matrix. The height will stay the same
    102     // while the width will vary as per aspect ratio.
    103     float ratio = width / height;
    104     float left = -ratio;
    105     float right = ratio;
    106     float bottom = -1.0f;
    107     float top = 1.0f;
    108     float near = 8.0f;
    109     float far = 12.0f;
    110 
    111     return Matrix::newFrustum(left, right, bottom, top, near, far);
    112 }
    113 
    114 bool GlowingScene::setUpTextures() {
    115     SCOPED_TRACE();
    116     mTextureIds.push_back(GLUtils::genTexture(mWidth, mHeight, 0)); // fbo
    117     mTextureIds.push_back(GLUtils::genTexture(mWidth, mHeight, 0)); // tmp1
    118     mTextureIds.push_back(GLUtils::genTexture(mWidth, mHeight, 0)); // tmp2
    119     mTextureIds.push_back(GLUtils::loadTexture("texture/arc.png"));
    120     return true;
    121 }
    122 
    123 bool GlowingScene::setUpMeshes() {
    124     SCOPED_TRACE();
    125     mMeshes.push_back(GLUtils::loadMesh("mesh/plane.cob"));
    126     mMeshes.push_back(GLUtils::loadMesh("mesh/arc.cob"));
    127     return true;
    128 }
    129 
    130 bool GlowingScene::tearDown() {
    131     SCOPED_TRACE();
    132     if (mMainProgram != NULL) {
    133         delete mMainProgram;
    134         mMainProgram = NULL;
    135     }
    136     if (mBlurProgram != NULL) {
    137         delete mBlurProgram;
    138         mBlurProgram = NULL;
    139     }
    140     if (mFboId != 0) {
    141         glDeleteFramebuffers(1, &mFboId);
    142         mFboId = 0;
    143     }
    144     delete mFboModelMatrix;
    145     mFboModelMatrix = NULL;
    146     delete mFboViewMatrix;
    147     mFboViewMatrix = NULL;
    148     delete mFboProjectionMatrix;
    149     mFboProjectionMatrix = NULL;
    150     return Scene::tearDown();
    151 }
    152 
    153 bool GlowingScene::updateSceneGraphs(int frame) {
    154     // To render the mesh to the FBO
    155     ProgramNode* lightSceneGraph = new ProgramNode(*mMainProgram);
    156     mSceneGraphs.push_back(lightSceneGraph);
    157     MeshNode* meshNode = new PerspectiveMeshNode(mMeshes[1], mTextureIds[3]);
    158     lightSceneGraph->addChild(meshNode);
    159 
    160     // To blur the image
    161     ProgramNode* blurSceneGraph = new ProgramNode(*mBlurProgram);
    162     mSceneGraphs.push_back(blurSceneGraph);
    163     meshNode = new BlurMeshNode(mMeshes[0], mTextureIds[0], mTextureIds[1], mTextureIds[2],
    164             mFboWidth, mFboHeight);
    165     blurSceneGraph->addChild(meshNode);
    166 
    167     // Blur To screen
    168     ProgramNode* glowSceneGraph = new ProgramNode(*mMainProgram);
    169     mSceneGraphs.push_back(glowSceneGraph);
    170     Matrix* transformMatrix = Matrix::newScale(mFboRatio, 1.0f, 1.0f);
    171     TransformationNode* transformNode = new TransformationNode(transformMatrix);
    172     glowSceneGraph->addChild(transformNode);
    173     meshNode = new PerspectiveMeshNode(mMeshes[0], mTextureIds[2]);
    174     transformNode->addChild(meshNode);
    175     return true;
    176 }
    177 
    178 bool GlowingScene::draw() {
    179     SCOPED_TRACE();
    180     glBindFramebuffer(GL_FRAMEBUFFER, mFboId); // Use FBO
    181     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureIds[0], 0);
    182     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
    183         return false;
    184     }
    185     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    186     glClear (GL_COLOR_BUFFER_BIT);
    187     glViewport(0, 0, mFboWidth, mFboHeight);
    188     mFboModelMatrix->identity();
    189     mSceneGraphs[0]->drawProgram(*mFboModelMatrix, *mFboViewMatrix, *mFboProjectionMatrix); // Mesh
    190     mFboModelMatrix->identity();
    191     mSceneGraphs[1]->drawProgram(*mFboModelMatrix, *mFboViewMatrix, *mFboProjectionMatrix); // Blur
    192 
    193     glBindFramebuffer(GL_FRAMEBUFFER, 0); // Use Screen
    194     glViewport(0, 0, mWidth, mHeight);
    195     Scene::drawSceneGraph(2); // Blur to Screen
    196     return true;
    197 }
    198