- Now they are in ndkHelper:: name space - Changed module name to ndk_helper - Changed some static members to class var or stand alone function - Added syncronization for JNIHelper.cpp - For a documentation, I will work with doc writer for future improvement Change-Id: I0055061a4f53b1904cde2e0339550ee277b35fc5 Addressed most of feedbacks, - Switched coding standard to Chrome style - Update JNI helper, and documented - Fixed other issues that is pointed out Change-Id: Icc729a55ed8dd613759f34a3fc35cb4949d2d205
287 lines
8.7 KiB
C++
287 lines
8.7 KiB
C++
/*
|
|
* Copyright 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// TeapotRenderer.cpp
|
|
// Render a teapot
|
|
//--------------------------------------------------------------------------------
|
|
//--------------------------------------------------------------------------------
|
|
// Include files
|
|
//--------------------------------------------------------------------------------
|
|
#include "TeapotRenderer.h"
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// Teapot model data
|
|
//--------------------------------------------------------------------------------
|
|
#include "teapot.inl"
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// Ctor
|
|
//--------------------------------------------------------------------------------
|
|
TeapotRenderer::TeapotRenderer()
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// Dtor
|
|
//--------------------------------------------------------------------------------
|
|
TeapotRenderer::~TeapotRenderer()
|
|
{
|
|
Unload();
|
|
}
|
|
|
|
void TeapotRenderer::Init()
|
|
{
|
|
//Settings
|
|
glFrontFace( GL_CCW );
|
|
|
|
//Load shader
|
|
LoadShaders( &shader_param_, "Shaders/VS_ShaderPlain.vsh",
|
|
"Shaders/ShaderPlain.fsh" );
|
|
|
|
//Create Index buffer
|
|
num_indices_ = sizeof(teapotIndices) / sizeof(teapotIndices[0]);
|
|
glGenBuffers( 1, &ibo_ );
|
|
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo_ );
|
|
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(teapotIndices), teapotIndices,
|
|
GL_STATIC_DRAW );
|
|
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
|
|
|
//Create VBO
|
|
num_vertices_ = sizeof(teapotPositions) / sizeof(teapotPositions[0]) / 3;
|
|
int32_t iStride = sizeof(TEAPOT_VERTEX);
|
|
int32_t iIndex = 0;
|
|
TEAPOT_VERTEX* p = new TEAPOT_VERTEX[num_vertices_];
|
|
for( int32_t i = 0; i < num_vertices_; ++i )
|
|
{
|
|
p[i].pos[0] = teapotPositions[iIndex];
|
|
p[i].pos[1] = teapotPositions[iIndex + 1];
|
|
p[i].pos[2] = teapotPositions[iIndex + 2];
|
|
|
|
p[i].normal[0] = teapotNormals[iIndex];
|
|
p[i].normal[1] = teapotNormals[iIndex + 1];
|
|
p[i].normal[2] = teapotNormals[iIndex + 2];
|
|
iIndex += 3;
|
|
}
|
|
glGenBuffers( 1, &vbo_ );
|
|
glBindBuffer( GL_ARRAY_BUFFER, vbo_ );
|
|
glBufferData( GL_ARRAY_BUFFER, iStride * num_vertices_, p, GL_STATIC_DRAW );
|
|
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
|
|
|
delete[] p;
|
|
|
|
UpdateViewport();
|
|
mat_model_ = ndk_helper::Mat4::Translation( 0, 0, -15.f );
|
|
|
|
ndk_helper::Mat4 mat = ndk_helper::Mat4::RotationX( M_PI / 3 );
|
|
mat_model_ = mat * mat_model_;
|
|
}
|
|
|
|
void TeapotRenderer::UpdateViewport()
|
|
{
|
|
//Init Projection matrices
|
|
int32_t viewport[4];
|
|
glGetIntegerv( GL_VIEWPORT, viewport );
|
|
float fAspect = (float) viewport[2] / (float) viewport[3];
|
|
|
|
const float CAM_NEAR = 5.f;
|
|
const float CAM_FAR = 10000.f;
|
|
bool bRotate = false;
|
|
mat_projection_ = ndk_helper::Mat4::Perspective( fAspect, 1.f, CAM_NEAR, CAM_FAR );
|
|
}
|
|
|
|
void TeapotRenderer::Unload()
|
|
{
|
|
if( vbo_ )
|
|
{
|
|
glDeleteBuffers( 1, &vbo_ );
|
|
vbo_ = 0;
|
|
}
|
|
|
|
if( ibo_ )
|
|
{
|
|
glDeleteBuffers( 1, &ibo_ );
|
|
ibo_ = 0;
|
|
}
|
|
|
|
if( shader_param_.program_ )
|
|
{
|
|
glDeleteProgram( shader_param_.program_ );
|
|
shader_param_.program_ = 0;
|
|
}
|
|
}
|
|
|
|
void TeapotRenderer::Update( float fTime )
|
|
{
|
|
const float CAM_X = 0.f;
|
|
const float CAM_Y = 0.f;
|
|
const float CAM_Z = 700.f;
|
|
|
|
mat_view_ = ndk_helper::Mat4::LookAt( ndk_helper::Vec3( CAM_X, CAM_Y, CAM_Z ),
|
|
ndk_helper::Vec3( 0.f, 0.f, 0.f ), ndk_helper::Vec3( 0.f, 1.f, 0.f ) );
|
|
|
|
if( camera_ )
|
|
{
|
|
camera_->Update();
|
|
mat_view_ = camera_->GetTransformMatrix() * mat_view_
|
|
* camera_->GetRotationMatrix() * mat_model_;
|
|
}
|
|
else
|
|
{
|
|
mat_view_ = mat_view_ * mat_model_;
|
|
}
|
|
}
|
|
|
|
void TeapotRenderer::Render()
|
|
{
|
|
//
|
|
// Feed Projection and Model View matrices to the shaders
|
|
ndk_helper::Mat4 mat_vp = mat_projection_ * mat_view_;
|
|
|
|
// Bind the VBO
|
|
glBindBuffer( GL_ARRAY_BUFFER, vbo_ );
|
|
|
|
int32_t iStride = sizeof(TEAPOT_VERTEX);
|
|
// Pass the vertex data
|
|
glVertexAttribPointer( ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, iStride,
|
|
BUFFER_OFFSET( 0 ) );
|
|
glEnableVertexAttribArray( ATTRIB_VERTEX );
|
|
|
|
glVertexAttribPointer( ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, iStride,
|
|
BUFFER_OFFSET( 3 * sizeof(GLfloat) ) );
|
|
glEnableVertexAttribArray( ATTRIB_NORMAL );
|
|
|
|
// Bind the IB
|
|
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo_ );
|
|
|
|
glUseProgram( shader_param_.program_ );
|
|
|
|
TEAPOT_MATERIALS material = { { 1.0f, 0.5f, 0.5f }, { 1.0f, 1.0f, 1.0f, 10.f }, {
|
|
0.1f, 0.1f, 0.1f }, };
|
|
|
|
//Update uniforms
|
|
glUniform4f( shader_param_.material_diffuse_, material.diffuse_color[0],
|
|
material.diffuse_color[1], material.diffuse_color[2], 1.f );
|
|
|
|
glUniform4f( shader_param_.material_specular_, material.specular_color[0],
|
|
material.specular_color[1], material.specular_color[2],
|
|
material.specular_color[3] );
|
|
//
|
|
//using glUniform3fv here was troublesome
|
|
//
|
|
glUniform3f( shader_param_.material_ambient_, material.ambient_color[0],
|
|
material.ambient_color[1], material.ambient_color[2] );
|
|
|
|
glUniformMatrix4fv( shader_param_.matrix_projection_, 1, GL_FALSE, mat_vp.Ptr() );
|
|
glUniformMatrix4fv( shader_param_.matrix_view_, 1, GL_FALSE, mat_view_.Ptr() );
|
|
glUniform3f( shader_param_.light0_, 100.f, -200.f, -600.f );
|
|
|
|
glDrawElements( GL_TRIANGLES, num_indices_, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0) );
|
|
|
|
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
|
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
|
}
|
|
|
|
bool TeapotRenderer::LoadShaders( SHADER_PARAMS* params,
|
|
const char* strVsh,
|
|
const char* strFsh )
|
|
{
|
|
GLuint program;
|
|
GLuint vert_shader, frag_shader;
|
|
char *vert_shader_pathname, *frag_shader_pathname;
|
|
|
|
// Create shader program
|
|
program = glCreateProgram();
|
|
LOGI( "Created Shader %d", program );
|
|
|
|
// Create and compile vertex shader
|
|
if( !ndk_helper::shader::CompileShader( &vert_shader, GL_VERTEX_SHADER, strVsh ) )
|
|
{
|
|
LOGI( "Failed to compile vertex shader" );
|
|
glDeleteProgram( program );
|
|
return false;
|
|
}
|
|
|
|
// Create and compile fragment shader
|
|
if( !ndk_helper::shader::CompileShader( &frag_shader, GL_FRAGMENT_SHADER, strFsh ) )
|
|
{
|
|
LOGI( "Failed to compile fragment shader" );
|
|
glDeleteProgram( program );
|
|
return false;
|
|
}
|
|
|
|
// Attach vertex shader to program
|
|
glAttachShader( program, vert_shader );
|
|
|
|
// Attach fragment shader to program
|
|
glAttachShader( program, frag_shader );
|
|
|
|
// Bind attribute locations
|
|
// this needs to be done prior to linking
|
|
glBindAttribLocation( program, ATTRIB_VERTEX, "myVertex" );
|
|
glBindAttribLocation( program, ATTRIB_NORMAL, "myNormal" );
|
|
glBindAttribLocation( program, ATTRIB_UV, "myUV" );
|
|
|
|
// Link program
|
|
if( !ndk_helper::shader::LinkProgram( program ) )
|
|
{
|
|
LOGI( "Failed to link program: %d", program );
|
|
|
|
if( vert_shader )
|
|
{
|
|
glDeleteShader( vert_shader );
|
|
vert_shader = 0;
|
|
}
|
|
if( frag_shader )
|
|
{
|
|
glDeleteShader( frag_shader );
|
|
frag_shader = 0;
|
|
}
|
|
if( program )
|
|
{
|
|
glDeleteProgram( program );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Get uniform locations
|
|
params->matrix_projection_ = glGetUniformLocation( program, "uPMatrix" );
|
|
params->matrix_view_ = glGetUniformLocation( program, "uMVMatrix" );
|
|
|
|
params->light0_ = glGetUniformLocation( program, "vLight0" );
|
|
params->material_diffuse_ = glGetUniformLocation( program, "vMaterialDiffuse" );
|
|
params->material_ambient_ = glGetUniformLocation( program, "vMaterialAmbient" );
|
|
params->material_specular_ = glGetUniformLocation( program, "vMaterialSpecular" );
|
|
|
|
// Release vertex and fragment shaders
|
|
if( vert_shader )
|
|
glDeleteShader( vert_shader );
|
|
if( frag_shader )
|
|
glDeleteShader( frag_shader );
|
|
|
|
params->program_ = program;
|
|
return true;
|
|
}
|
|
|
|
bool TeapotRenderer::Bind( ndk_helper::TapCamera* camera )
|
|
{
|
|
camera_ = camera;
|
|
return true;
|
|
}
|
|
|