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