blob: 89186ba910e1ce5d0581e29db9fb6c84269ac6e1 [file] [log] [blame]
/*
* Copyright © 2008 Ben Smith
* Copyright © 2010-2011 Linaro Limited
*
* This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
*
* glmark2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* glmark2. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Ben Smith (original glmark benchmark)
* Alexandros Frantzis (glmark2)
*/
#include "scene.h"
#include "log.h"
#include "mat.h"
#include "stack.h"
#include <cmath>
SceneBuild::SceneBuild(Canvas &pCanvas) :
Scene(pCanvas, "build")
{
mOptions["use-vbo"] = Scene::Option("use-vbo", "true",
"Whether to use VBOs for rendering [true,false]");
mOptions["interleave"] = Scene::Option("interleave", "false",
"Whether to interleave vertex attribute data [true,false]");
}
SceneBuild::~SceneBuild()
{
}
int SceneBuild::load()
{
static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.vert");
static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.frag");
Model model;
if(!model.load_3ds(GLMARK_DATA_PATH"/models/horse.3ds"))
return 0;
model.calculate_normals();
/* Tell the converter that we only care about position and normal attributes */
std::vector<std::pair<Model::AttribType, int> > attribs;
attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypePosition, 3));
attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypeNormal, 3));
model.convert_to_mesh(mMesh, attribs);
if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename,
frg_shader_filename))
{
return 0;
}
std::vector<GLint> attrib_locations;
attrib_locations.push_back(mProgram.getAttribIndex("position"));
attrib_locations.push_back(mProgram.getAttribIndex("normal"));
mMesh.set_attrib_locations(attrib_locations);
mRotationSpeed = 36.0f;
mRunning = false;
return 1;
}
void SceneBuild::unload()
{
mMesh.reset();
mProgram.stop();
mProgram.release();
}
void SceneBuild::setup()
{
Scene::setup();
static const LibMatrix::vec4 lightAmbient(0.0f, 0.0f, 0.0f, 1.0f);
static const LibMatrix::vec4 lightDiffuse(0.8f, 0.8f, 0.8f, 1.0f);
static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
static const LibMatrix::vec4 materialColor(1.0f, 1.0f, 1.0f, 1.0f);
mUseVbo = (mOptions["use-vbo"].value == "true");
bool interleave = (mOptions["interleave"].value == "true");
if (mUseVbo)
mMesh.build_vbo(interleave);
else
mMesh.build_array(interleave);
mProgram.start();
// Load lighting and material uniforms
mProgram.loadUniformVector(lightAmbient, "LightSourceAmbient");
mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
mProgram.loadUniformVector(lightDiffuse, "LightSourceDiffuse");
mProgram.loadUniformVector(materialColor, "MaterialColor");
mCurrentFrame = 0;
mRotation = 0.0;
mRunning = true;
mStartTime = Scene::get_timestamp_us() / 1000000.0;
mLastUpdateTime = mStartTime;
}
void
SceneBuild::teardown()
{
mProgram.stop();
if (mUseVbo)
mMesh.delete_vbo();
else
mMesh.delete_array();
Scene::teardown();
}
void SceneBuild::update()
{
double current_time = Scene::get_timestamp_us() / 1000000.0;
double dt = current_time - mLastUpdateTime;
double elapsed_time = current_time - mStartTime;
mLastUpdateTime = current_time;
if (elapsed_time >= mDuration) {
mAverageFPS = mCurrentFrame / elapsed_time;
mRunning = false;
}
mRotation += mRotationSpeed * dt;
mCurrentFrame++;
}
void SceneBuild::draw()
{
LibMatrix::Stack4 model_view;
// Load the ModelViewProjectionMatrix uniform in the shader
LibMatrix::mat4 model_view_proj(mCanvas.projection());
model_view.translate(0.0f, 0.0f, -2.5f);
model_view.rotate(mRotation, 0.0f, 1.0f, 0.0f);
model_view_proj *= model_view.getCurrent();
mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
// Load the NormalMatrix uniform in the shader. The NormalMatrix is the
// inverse transpose of the model view matrix.
LibMatrix::mat4 normal_matrix(model_view.getCurrent());
normal_matrix.inverse().transpose();
mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
if (mUseVbo) {
mMesh.render_vbo();
}
else {
mMesh.render_array();
}
}
Scene::ValidationResult
SceneBuild::validate()
{
static const double radius_3d(std::sqrt(3.0));
if (mRotation != 0)
return Scene::ValidationUnknown;
Canvas::Pixel ref(0xcf, 0xcf, 0xcf, 0xff);
Canvas::Pixel pixel = mCanvas.read_pixel(mCanvas.width() / 2,
mCanvas.height() / 2);
double dist = pixel_value_distance(pixel, ref);
if (dist < radius_3d + 0.01) {
return Scene::ValidationSuccess;
}
else {
Log::debug("Validation failed! Expected: 0x%x Actual: 0x%x Distance: %f\n",
ref.to_le32(), pixel.to_le32(), dist);
return Scene::ValidationFailure;
}
}