1 /* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //-------------------------------------------------------------------------------- 18 // TeapotRenderer.cpp 19 // Render a teapot 20 //-------------------------------------------------------------------------------- 21 //-------------------------------------------------------------------------------- 22 // Include files 23 //-------------------------------------------------------------------------------- 24 #include "TeapotRenderer.h" 25 26 //-------------------------------------------------------------------------------- 27 // Teapot model data 28 //-------------------------------------------------------------------------------- 29 #include "teapot.inl" 30 31 //-------------------------------------------------------------------------------- 32 // Ctor 33 //-------------------------------------------------------------------------------- 34 TeapotRenderer::TeapotRenderer() 35 { 36 37 } 38 39 //-------------------------------------------------------------------------------- 40 // Dtor 41 //-------------------------------------------------------------------------------- 42 TeapotRenderer::~TeapotRenderer() 43 { 44 Unload(); 45 } 46 47 void TeapotRenderer::Init() 48 { 49 //Settings 50 glFrontFace( GL_CCW ); 51 52 //Load shader 53 LoadShaders( &shader_param_, "Shaders/VS_ShaderPlain.vsh", 54 "Shaders/ShaderPlain.fsh" ); 55 56 //Create Index buffer 57 num_indices_ = sizeof(teapotIndices) / sizeof(teapotIndices[0]); 58 glGenBuffers( 1, &ibo_ ); 59 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo_ ); 60 glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(teapotIndices), teapotIndices, 61 GL_STATIC_DRAW ); 62 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); 63 64 //Create VBO 65 num_vertices_ = sizeof(teapotPositions) / sizeof(teapotPositions[0]) / 3; 66 int32_t iStride = sizeof(TEAPOT_VERTEX); 67 int32_t iIndex = 0; 68 TEAPOT_VERTEX* p = new TEAPOT_VERTEX[num_vertices_]; 69 for( int32_t i = 0; i < num_vertices_; ++i ) 70 { 71 p[i].pos[0] = teapotPositions[iIndex]; 72 p[i].pos[1] = teapotPositions[iIndex + 1]; 73 p[i].pos[2] = teapotPositions[iIndex + 2]; 74 75 p[i].normal[0] = teapotNormals[iIndex]; 76 p[i].normal[1] = teapotNormals[iIndex + 1]; 77 p[i].normal[2] = teapotNormals[iIndex + 2]; 78 iIndex += 3; 79 } 80 glGenBuffers( 1, &vbo_ ); 81 glBindBuffer( GL_ARRAY_BUFFER, vbo_ ); 82 glBufferData( GL_ARRAY_BUFFER, iStride * num_vertices_, p, GL_STATIC_DRAW ); 83 glBindBuffer( GL_ARRAY_BUFFER, 0 ); 84 85 delete[] p; 86 87 UpdateViewport(); 88 mat_model_ = ndk_helper::Mat4::Translation( 0, 0, -15.f ); 89 90 ndk_helper::Mat4 mat = ndk_helper::Mat4::RotationX( M_PI / 3 ); 91 mat_model_ = mat * mat_model_; 92 } 93 94 void TeapotRenderer::UpdateViewport() 95 { 96 //Init Projection matrices 97 int32_t viewport[4]; 98 glGetIntegerv( GL_VIEWPORT, viewport ); 99 float fAspect = (float) viewport[2] / (float) viewport[3]; 100 101 const float CAM_NEAR = 5.f; 102 const float CAM_FAR = 10000.f; 103 bool bRotate = false; 104 mat_projection_ = ndk_helper::Mat4::Perspective( fAspect, 1.f, CAM_NEAR, CAM_FAR ); 105 } 106 107 void TeapotRenderer::Unload() 108 { 109 if( vbo_ ) 110 { 111 glDeleteBuffers( 1, &vbo_ ); 112 vbo_ = 0; 113 } 114 115 if( ibo_ ) 116 { 117 glDeleteBuffers( 1, &ibo_ ); 118 ibo_ = 0; 119 } 120 121 if( shader_param_.program_ ) 122 { 123 glDeleteProgram( shader_param_.program_ ); 124 shader_param_.program_ = 0; 125 } 126 } 127 128 void TeapotRenderer::Update( float fTime ) 129 { 130 const float CAM_X = 0.f; 131 const float CAM_Y = 0.f; 132 const float CAM_Z = 700.f; 133 134 mat_view_ = ndk_helper::Mat4::LookAt( ndk_helper::Vec3( CAM_X, CAM_Y, CAM_Z ), 135 ndk_helper::Vec3( 0.f, 0.f, 0.f ), ndk_helper::Vec3( 0.f, 1.f, 0.f ) ); 136 137 if( camera_ ) 138 { 139 camera_->Update(); 140 mat_view_ = camera_->GetTransformMatrix() * mat_view_ 141 * camera_->GetRotationMatrix() * mat_model_; 142 } 143 else 144 { 145 mat_view_ = mat_view_ * mat_model_; 146 } 147 } 148 149 void TeapotRenderer::Render() 150 { 151 // 152 // Feed Projection and Model View matrices to the shaders 153 ndk_helper::Mat4 mat_vp = mat_projection_ * mat_view_; 154 155 // Bind the VBO 156 glBindBuffer( GL_ARRAY_BUFFER, vbo_ ); 157 158 int32_t iStride = sizeof(TEAPOT_VERTEX); 159 // Pass the vertex data 160 glVertexAttribPointer( ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, iStride, 161 BUFFER_OFFSET( 0 ) ); 162 glEnableVertexAttribArray( ATTRIB_VERTEX ); 163 164 glVertexAttribPointer( ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, iStride, 165 BUFFER_OFFSET( 3 * sizeof(GLfloat) ) ); 166 glEnableVertexAttribArray( ATTRIB_NORMAL ); 167 168 // Bind the IB 169 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo_ ); 170 171 glUseProgram( shader_param_.program_ ); 172 173 TEAPOT_MATERIALS material = { { 1.0f, 0.5f, 0.5f }, { 1.0f, 1.0f, 1.0f, 10.f }, { 174 0.1f, 0.1f, 0.1f }, }; 175 176 //Update uniforms 177 glUniform4f( shader_param_.material_diffuse_, material.diffuse_color[0], 178 material.diffuse_color[1], material.diffuse_color[2], 1.f ); 179 180 glUniform4f( shader_param_.material_specular_, material.specular_color[0], 181 material.specular_color[1], material.specular_color[2], 182 material.specular_color[3] ); 183 // 184 //using glUniform3fv here was troublesome 185 // 186 glUniform3f( shader_param_.material_ambient_, material.ambient_color[0], 187 material.ambient_color[1], material.ambient_color[2] ); 188 189 glUniformMatrix4fv( shader_param_.matrix_projection_, 1, GL_FALSE, mat_vp.Ptr() ); 190 glUniformMatrix4fv( shader_param_.matrix_view_, 1, GL_FALSE, mat_view_.Ptr() ); 191 glUniform3f( shader_param_.light0_, 100.f, -200.f, -600.f ); 192 193 glDrawElements( GL_TRIANGLES, num_indices_, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0) ); 194 195 glBindBuffer( GL_ARRAY_BUFFER, 0 ); 196 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); 197 } 198 199 bool TeapotRenderer::LoadShaders( SHADER_PARAMS* params, 200 const char* strVsh, 201 const char* strFsh ) 202 { 203 GLuint program; 204 GLuint vert_shader, frag_shader; 205 char *vert_shader_pathname, *frag_shader_pathname; 206 207 // Create shader program 208 program = glCreateProgram(); 209 LOGI( "Created Shader %d", program ); 210 211 // Create and compile vertex shader 212 if( !ndk_helper::shader::CompileShader( &vert_shader, GL_VERTEX_SHADER, strVsh ) ) 213 { 214 LOGI( "Failed to compile vertex shader" ); 215 glDeleteProgram( program ); 216 return false; 217 } 218 219 // Create and compile fragment shader 220 if( !ndk_helper::shader::CompileShader( &frag_shader, GL_FRAGMENT_SHADER, strFsh ) ) 221 { 222 LOGI( "Failed to compile fragment shader" ); 223 glDeleteProgram( program ); 224 return false; 225 } 226 227 // Attach vertex shader to program 228 glAttachShader( program, vert_shader ); 229 230 // Attach fragment shader to program 231 glAttachShader( program, frag_shader ); 232 233 // Bind attribute locations 234 // this needs to be done prior to linking 235 glBindAttribLocation( program, ATTRIB_VERTEX, "myVertex" ); 236 glBindAttribLocation( program, ATTRIB_NORMAL, "myNormal" ); 237 glBindAttribLocation( program, ATTRIB_UV, "myUV" ); 238 239 // Link program 240 if( !ndk_helper::shader::LinkProgram( program ) ) 241 { 242 LOGI( "Failed to link program: %d", program ); 243 244 if( vert_shader ) 245 { 246 glDeleteShader( vert_shader ); 247 vert_shader = 0; 248 } 249 if( frag_shader ) 250 { 251 glDeleteShader( frag_shader ); 252 frag_shader = 0; 253 } 254 if( program ) 255 { 256 glDeleteProgram( program ); 257 } 258 259 return false; 260 } 261 262 // Get uniform locations 263 params->matrix_projection_ = glGetUniformLocation( program, "uPMatrix" ); 264 params->matrix_view_ = glGetUniformLocation( program, "uMVMatrix" ); 265 266 params->light0_ = glGetUniformLocation( program, "vLight0" ); 267 params->material_diffuse_ = glGetUniformLocation( program, "vMaterialDiffuse" ); 268 params->material_ambient_ = glGetUniformLocation( program, "vMaterialAmbient" ); 269 params->material_specular_ = glGetUniformLocation( program, "vMaterialSpecular" ); 270 271 // Release vertex and fragment shaders 272 if( vert_shader ) 273 glDeleteShader( vert_shader ); 274 if( frag_shader ) 275 glDeleteShader( frag_shader ); 276 277 params->program_ = program; 278 return true; 279 } 280 281 bool TeapotRenderer::Bind( ndk_helper::TapCamera* camera ) 282 { 283 camera_ = camera; 284 return true; 285 } 286 287