From patchwork Tue Jul 19 13:32:31 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 2756 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 1987523F41 for ; Tue, 19 Jul 2011 13:32:41 +0000 (UTC) Received: from mail-qy0-f173.google.com (mail-qy0-f173.google.com [209.85.216.173]) by fiordland.canonical.com (Postfix) with ESMTP id AA3E0A183E5 for ; Tue, 19 Jul 2011 13:32:40 +0000 (UTC) Received: by qyk10 with SMTP id 10so2540859qyk.11 for ; Tue, 19 Jul 2011 06:32:40 -0700 (PDT) Received: by 10.229.217.3 with SMTP id hk3mr6600882qcb.38.1311082360123; Tue, 19 Jul 2011 06:32:40 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.217.78 with SMTP id hl14cs84660qcb; Tue, 19 Jul 2011 06:32:39 -0700 (PDT) Received: by 10.227.198.80 with SMTP id en16mr6898152wbb.58.1311082358932; Tue, 19 Jul 2011 06:32:38 -0700 (PDT) Received: from adelie.canonical.com (adelie.canonical.com [91.189.90.139]) by mx.google.com with ESMTP id 8si9888907wbx.107.2011.07.19.06.32.38; Tue, 19 Jul 2011 06:32:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) client-ip=91.189.90.139; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) smtp.mail=bounces@canonical.com Received: from loganberry.canonical.com ([91.189.90.37]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1QjAPc-0007u3-NX for ; Tue, 19 Jul 2011 13:32:36 +0000 Received: from loganberry.canonical.com (localhost [127.0.0.1]) by loganberry.canonical.com (Postfix) with ESMTP id 9B12B2EAB62 for ; Tue, 19 Jul 2011 13:32:31 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 111 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 111: Merge SceneBump implementation. Message-Id: <20110719133231.3251.68230.launchpad@loganberry.canonical.com> Date: Tue, 19 Jul 2011 13:32:31 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="13405"; Instance="initZopeless config overlay" X-Launchpad-Hash: f5102322809ea90b29691b0909fc2a4071905cca Merge authors: Alexandros Frantzis (afrantzis) ------------------------------------------------------------ revno: 111 [merge] committer: Alexandros Frantzis branch nick: trunk timestamp: Tue 2011-07-19 15:23:28 +0300 message: Merge SceneBump implementation. added: data/models/asteroid-high.3ds data/models/asteroid-low.3ds data/shaders/bump-normals.frag data/shaders/bump-normals.vert data/shaders/bump-poly.frag data/shaders/bump-poly.vert data/textures/asteroid-normal-map.png src/scene-bump.cpp modified: src/main.cpp src/scene.h --- lp:glmark2 https://code.launchpad.net/~glmark2-dev/glmark2/trunk You are subscribed to branch lp:glmark2. To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription === added file 'data/models/asteroid-high.3ds' Binary files data/models/asteroid-high.3ds 1970-01-01 00:00:00 +0000 and data/models/asteroid-high.3ds 2011-07-14 11:25:43 +0000 differ === added file 'data/models/asteroid-low.3ds' Binary files data/models/asteroid-low.3ds 1970-01-01 00:00:00 +0000 and data/models/asteroid-low.3ds 2011-07-14 11:25:43 +0000 differ === added file 'data/shaders/bump-normals.frag' --- data/shaders/bump-normals.frag 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-normals.frag 2011-07-19 10:09:30 +0000 @@ -0,0 +1,50 @@ +#ifdef GL_ES +precision mediump float; +#endif + +uniform vec4 LightSourcePosition; +uniform vec3 LightSourceHalfVector; +uniform sampler2D NormalMap; +uniform mat4 NormalMatrix; + +varying vec2 TextureCoord; + +void main(void) +{ + const vec4 LightSourceAmbient = vec4(0.1, 0.1, 0.1, 1.0); + const vec4 LightSourceDiffuse = vec4(0.8, 0.8, 0.8, 1.0); + const vec4 LightSourceSpecular = vec4(0.8, 0.8, 0.8, 1.0); + const vec4 MaterialAmbient = vec4(1.0, 1.0, 1.0, 1.0); + const vec4 MaterialDiffuse = vec4(1.0, 1.0, 1.0, 1.0); + const vec4 MaterialSpecular = vec4(0.2, 0.2, 0.2, 1.0); + const float MaterialShininess = 100.0; + + // Get the raw normal XYZ data from the normal map + vec3 normal_raw = texture2D(NormalMap, TextureCoord).xyz; + // Map "color" range [0, 1.0] to normal range [-1.0, 1.0] + vec3 normal_scaled = normal_raw * 2.0 - 1.0; + + // Convert the normal to eye coordinates. Note that the normal map + // we are using is using object coordinates (not tangent!) for the + // normals, so we can multiply by the NormalMatrix as usual. + vec3 N = normalize(vec3(NormalMatrix * vec4(normal_scaled, 1.0))); + + // In the lighting model we are using here (Blinn-Phong with light at + // infinity, viewer at infinity), the light position/direction and the + // half vector is constant for the all the fragments. + vec3 L = normalize(LightSourcePosition.xyz); + vec3 H = normalize(LightSourceHalfVector); + + // Calculate the diffuse color according to Lambertian reflectance + vec4 diffuse = MaterialDiffuse * LightSourceDiffuse * max(dot(N, L), 0.0); + + // Calculate the ambient color + vec4 ambient = MaterialAmbient * LightSourceAmbient; + + // Calculate the specular color according to the Blinn-Phong model + vec4 specular = MaterialSpecular * LightSourceSpecular * + pow(max(dot(N,H), 0.0), MaterialShininess); + + // Calculate the final color + gl_FragColor = ambient + specular + diffuse; +} === added file 'data/shaders/bump-normals.vert' --- data/shaders/bump-normals.vert 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-normals.vert 2011-07-19 10:09:30 +0000 @@ -0,0 +1,14 @@ +attribute vec3 position; +attribute vec2 texcoord; + +uniform mat4 ModelViewProjectionMatrix; + +varying vec2 TextureCoord; + +void main(void) +{ + TextureCoord = texcoord; + + // Transform the position to clip coordinates + gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0); +} === added file 'data/shaders/bump-poly.frag' --- data/shaders/bump-poly.frag 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-poly.frag 2011-07-19 10:09:30 +0000 @@ -0,0 +1,40 @@ +#ifdef GL_ES +precision mediump float; +#endif + +uniform vec4 LightSourcePosition; +uniform vec3 LightSourceHalfVector; + +varying vec3 Normal; + +void main(void) +{ + const vec4 LightSourceAmbient = vec4(0.1, 0.1, 0.1, 1.0); + const vec4 LightSourceDiffuse = vec4(0.8, 0.8, 0.8, 1.0); + const vec4 LightSourceSpecular = vec4(0.8, 0.8, 0.8, 1.0); + const vec4 MaterialAmbient = vec4(1.0, 1.0, 1.0, 1.0); + const vec4 MaterialDiffuse = vec4(1.0, 1.0, 1.0, 1.0); + const vec4 MaterialSpecular = vec4(0.2, 0.2, 0.2, 1.0); + const float MaterialShininess = 100.0; + + vec3 N = normalize(Normal); + + // In the lighting model we are using here (Blinn-Phong with light at + // infinity, viewer at infinity), the light position/direction and the + // half vector is constant for the all the fragments. + vec3 L = normalize(LightSourcePosition.xyz); + vec3 H = normalize(LightSourceHalfVector); + + // Calculate the diffuse color according to Lambertian reflectance + vec4 diffuse = MaterialDiffuse * LightSourceDiffuse * max(dot(N, L), 0.0); + + // Calculate the ambient color + vec4 ambient = MaterialAmbient * LightSourceAmbient; + + // Calculate the specular color according to the Blinn-Phong model + vec4 specular = MaterialSpecular * LightSourceSpecular * + pow(max(dot(N,H), 0.0), MaterialShininess); + + // Calculate the final color + gl_FragColor = ambient + specular + diffuse; +} === added file 'data/shaders/bump-poly.vert' --- data/shaders/bump-poly.vert 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-poly.vert 2011-07-19 10:09:30 +0000 @@ -0,0 +1,16 @@ +attribute vec3 position; +attribute vec3 normal; + +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 NormalMatrix; + +varying vec3 Normal; + +void main(void) +{ + // Transform the normal to eye coordinates + Normal = normalize(vec3(NormalMatrix * vec4(normal, 1.0))); + + // Transform the position to clip coordinates + gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0); +} === added file 'data/textures/asteroid-normal-map.png' Binary files data/textures/asteroid-normal-map.png 1970-01-01 00:00:00 +0000 and data/textures/asteroid-normal-map.png 2011-07-14 11:25:43 +0000 differ === modified file 'src/main.cpp' --- src/main.cpp 2011-07-12 17:53:10 +0000 +++ src/main.cpp 2011-07-19 10:18:35 +0000 @@ -48,6 +48,8 @@ "shading:shading=gouraud", "shading:shading=blinn-phong-inf", "shading:shading=phong", + "bump:bump-render=high-poly", + "bump:bump-render=normals", "conditionals:vertex-steps=0:fragment-steps=0", "conditionals:vertex-steps=0:fragment-steps=5", "conditionals:vertex-steps=5:fragment-steps=0", @@ -218,6 +220,7 @@ Benchmark::register_scene(*new SceneConditionals(canvas)); Benchmark::register_scene(*new SceneFunction(canvas)); Benchmark::register_scene(*new SceneLoop(canvas)); + Benchmark::register_scene(*new SceneBump(canvas)); if (Options::list_scenes) { list_scenes(); === added file 'src/scene-bump.cpp' --- src/scene-bump.cpp 1970-01-01 00:00:00 +0000 +++ src/scene-bump.cpp 2011-07-19 11:57:20 +0000 @@ -0,0 +1,247 @@ +/* + * 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 . + * + * Authors: + * Alexandros Frantzis (glmark2) + */ +#include "scene.h" +#include "log.h" +#include "mat.h" +#include "stack.h" +#include + +SceneBump::SceneBump(Canvas &pCanvas) : + Scene(pCanvas, "bump") +{ + mOptions["bump-render"] = Scene::Option("bump-render", "off", + "How to render bumps [off, normals, high-poly]"); +} + +SceneBump::~SceneBump() +{ +} + +int SceneBump::load() +{ + mRotationSpeed = 36.0f; + + mRunning = false; + + return 1; +} + +void SceneBump::unload() +{ +} + +void +SceneBump::setup_model_plain(const std::string &type) +{ + static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/bump-poly.vert"); + static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-poly.frag"); + static const std::string low_poly_filename(GLMARK_DATA_PATH"/models/asteroid-low.3ds"); + static const std::string high_poly_filename(GLMARK_DATA_PATH"/models/asteroid-high.3ds"); + Model model; + + std::string poly_filename = type == "high-poly" ? + high_poly_filename : low_poly_filename; + + if(!model.load_3ds(poly_filename)) + return; + + model.calculate_normals(); + + /* Tell the converter that we only care about position and normal attributes */ + std::vector > attribs; + attribs.push_back(std::pair(Model::AttribTypePosition, 3)); + attribs.push_back(std::pair(Model::AttribTypeNormal, 3)); + + model.convert_to_mesh(mMesh, attribs); + + if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename, + frg_shader_filename)) + { + return; + } + + std::vector attrib_locations; + attrib_locations.push_back(mProgram.getAttribIndex("position")); + attrib_locations.push_back(mProgram.getAttribIndex("normal")); + mMesh.set_attrib_locations(attrib_locations); +} + +void +SceneBump::setup_model_normals() +{ + static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/bump-normals.vert"); + static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-normals.frag"); + Model model; + + if(!model.load_3ds(GLMARK_DATA_PATH"/models/asteroid-low.3ds")) + return; + + /* + * We don't care about the vertex normals. We are using a per-fragment + * normal map (in object space coordinates). + */ + std::vector > attribs; + attribs.push_back(std::pair(Model::AttribTypePosition, 3)); + attribs.push_back(std::pair(Model::AttribTypeTexcoord, 2)); + + model.convert_to_mesh(mMesh, attribs); + + if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename, + frg_shader_filename)) + { + return; + } + + std::vector attrib_locations; + attrib_locations.push_back(mProgram.getAttribIndex("position")); + attrib_locations.push_back(mProgram.getAttribIndex("texcoord")); + mMesh.set_attrib_locations(attrib_locations); + + Texture::load(GLMARK_DATA_PATH"/textures/asteroid-normal-map.png", &mTexture, + GL_NEAREST, GL_NEAREST, 0); +} + +void SceneBump::setup() +{ + Scene::setup(); + + const std::string &bump_render = mOptions["bump-render"].value; + + if (bump_render == "normals") + setup_model_normals(); + else if (bump_render == "off" || bump_render == "high-poly") + setup_model_plain(bump_render); + + static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f); + + mMesh.build_vbo(); + + mProgram.start(); + + // Load lighting and material uniforms + mProgram.loadUniformVector(lightPosition, "LightSourcePosition"); + + // Calculate and load the half vector + LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z()); + halfVector.normalize(); + halfVector += LibMatrix::vec3(0.0, 0.0, 1.0); + halfVector.normalize(); + mProgram.loadUniformVector(halfVector, "LightSourceHalfVector"); + + // Load texture sampler value + mProgram.loadUniformScalar(0, "NormalMap"); + + mCurrentFrame = 0; + mRotation = 0.0; + mRunning = true; + mStartTime = Scene::get_timestamp_us() / 1000000.0; + mLastUpdateTime = mStartTime; +} + +void +SceneBump::teardown() +{ + mMesh.reset(); + + mProgram.stop(); + mProgram.release(); + + glDeleteTextures(1, &mTexture); + + Scene::teardown(); +} + +void SceneBump::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 SceneBump::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, -3.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"); + + mMesh.render_vbo(); +} + +Scene::ValidationResult +SceneBump::validate() +{ + static const double radius_3d(std::sqrt(3.0)); + + if (mRotation != 0) + return Scene::ValidationUnknown; + + Canvas::Pixel ref; + + Canvas::Pixel pixel = mCanvas.read_pixel(mCanvas.width() / 2, + mCanvas.height() / 2); + + const std::string &bump_render = mOptions["bump-render"].value; + + if (bump_render == "off") + ref = Canvas::Pixel(0x81, 0x81, 0x81, 0xff); + else if (bump_render == "high-poly") + ref = Canvas::Pixel(0x9c, 0x9c, 0x9c, 0xff); + else if (bump_render == "normals") + ref = Canvas::Pixel(0xa4, 0xa4, 0xa4, 0xff); + else + return Scene::ValidationUnknown; + + 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; + } +} === modified file 'src/scene.h' --- src/scene.h 2011-07-08 12:48:36 +0000 +++ src/scene.h 2011-07-19 10:09:30 +0000 @@ -253,4 +253,31 @@ ~SceneLoop(); }; + +class SceneBump : public Scene +{ +public: + SceneBump(Canvas &pCanvas); + int load(); + void unload(); + void setup(); + void teardown(); + void update(); + void draw(); + ValidationResult validate(); + + ~SceneBump(); + +protected: + Program mProgram; + + Mesh mMesh; + GLuint mTexture; + float mRotation; + float mRotationSpeed; +private: + void setup_model_plain(const std::string &type); + void setup_model_normals(); +}; + #endif