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 
GlowingScene(int width,int height)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 
setUpContext()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 
setUpPrograms()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 
setUpModelMatrix()76 Matrix* GlowingScene::setUpModelMatrix() {
77     return new Matrix();
78 }
79 
setUpViewMatrix()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 
setUpProjectionMatrix(float width,float height)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 
setUpTextures()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 
setUpMeshes()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 
tearDown()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 
updateSceneGraphs(int frame)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 
draw()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