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