From patchwork Tue Nov 15 10:23:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 5143 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 B26A223E0F for ; Tue, 15 Nov 2011 10:23:16 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id 9C3B2A18530 for ; Tue, 15 Nov 2011 10:23:16 +0000 (UTC) Received: by faaa26 with SMTP id a26so264548faa.11 for ; Tue, 15 Nov 2011 02:23:16 -0800 (PST) Received: by 10.152.105.226 with SMTP id gp2mr16567468lab.28.1321352595810; Tue, 15 Nov 2011 02:23:15 -0800 (PST) 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.152.41.198 with SMTP id h6cs32303lal; Tue, 15 Nov 2011 02:23:15 -0800 (PST) Received: by 10.180.81.73 with SMTP id y9mr29611496wix.37.1321352594081; Tue, 15 Nov 2011 02:23:14 -0800 (PST) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id k56si4747461wed.32.2011.11.15.02.23.13 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 15 Nov 2011 02:23:14 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1RQGAb-0001WY-Fb for ; Tue, 15 Nov 2011 10:23:13 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 49301E0100 for ; Tue, 15 Nov 2011 10:23:13 +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: 168 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 168: SceneBump: Implement bump mapping using a tangent space normal map and a height map. Message-Id: <20111115102313.14433.94981.launchpad@ackee.canonical.com> Date: Tue, 15 Nov 2011 10:23:13 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14291"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: c442b9e5817f3287939fb7336b51e5d88b09599a Merge authors: Alexandros Frantzis (afrantzis) Related merge proposals: https://code.launchpad.net/~glmark2-dev/glmark2/bump-height-map/+merge/82141 proposed by: Alexandros Frantzis (afrantzis) review: Approve - Jesse Barker (jesse-barker) ------------------------------------------------------------ revno: 168 [merge] committer: Alexandros Frantzis branch nick: trunk timestamp: Tue 2011-11-15 12:20:53 +0200 message: SceneBump: Implement bump mapping using a tangent space normal map and a height map. added: data/shaders/bump-height.frag data/shaders/bump-height.vert data/shaders/bump-normals-tangent.frag data/shaders/bump-normals-tangent.vert data/textures/asteroid-height-map.png data/textures/asteroid-normal-map-tangent.png modified: src/default-benchmarks.h src/model.cpp src/model.h src/scene-bump.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/shaders/bump-height.frag' --- data/shaders/bump-height.frag 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-height.frag 2011-11-15 10:15:41 +0000 @@ -0,0 +1,56 @@ +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D HeightMap; + +varying vec2 TextureCoord; +varying vec3 NormalEye; +varying vec3 TangentEye; +varying vec3 BitangentEye; + +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; + const float height_factor = 13.0; + + // Get the data from the height map + float height0 = texture2D(HeightMap, TextureCoord).x; + float heightX = texture2D(HeightMap, TextureCoord + vec2(TextureStepX, 0.0)).x; + float heightY = texture2D(HeightMap, TextureCoord + vec2(0.0, TextureStepY)).x; + vec2 dh = vec2(heightX - height0, heightY - height0); + + // Adjust the normal based on the height map data + vec3 N = NormalEye - height_factor * dh.x * TangentEye - + height_factor * dh.y * BitangentEye; + N = normalize(N); + + // 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; + + //gl_FragColor = vec4(height_diff_raw.xy, 0.0, 1.0); + //gl_FragColor = vec4(height_diff_scaled.xy, 0.0, 1.0); + //gl_FragColor = vec4(Tangent, 1.0); +} === added file 'data/shaders/bump-height.vert' --- data/shaders/bump-height.vert 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-height.vert 2011-11-14 11:36:26 +0000 @@ -0,0 +1,28 @@ +attribute vec3 position; +attribute vec2 texcoord; +attribute vec3 normal; +attribute vec3 tangent; + +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 NormalMatrix; + +varying vec2 TextureCoord; +varying vec3 NormalEye; +varying vec3 TangentEye; +varying vec3 BitangentEye; + +void main(void) +{ + TextureCoord = texcoord; + + // Transform normal, tangent and bitangent to eye space, keeping + // all of them perpendicular to the Normal. That is why we use + // NormalMatrix, instead of ModelView, to transform the tangent and + // bitangent. + NormalEye = normalize(vec3(NormalMatrix * vec4(normal, 1.0))); + TangentEye = normalize(vec3(NormalMatrix * vec4(tangent, 1.0))); + BitangentEye = normalize(vec3(NormalMatrix * vec4(cross(normal, tangent), 1.0))); + + // Transform the position to clip coordinates + gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0); +} === added file 'data/shaders/bump-normals-tangent.frag' --- data/shaders/bump-normals-tangent.frag 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-normals-tangent.frag 2011-11-11 14:40:29 +0000 @@ -0,0 +1,49 @@ +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D NormalMap; + +varying vec2 TextureCoord; +varying mat4 TangentToEyeMatrix; + +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; + + // The normal data is in tangent space, convert it to eye space so that + // lighting calculations can work (light information is in eye space). + vec3 N = normalize(vec3(TangentToEyeMatrix * 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; + //gl_FragColor = vec4(N, 1.0); +} === added file 'data/shaders/bump-normals-tangent.vert' --- data/shaders/bump-normals-tangent.vert 1970-01-01 00:00:00 +0000 +++ data/shaders/bump-normals-tangent.vert 2011-11-11 14:40:29 +0000 @@ -0,0 +1,39 @@ +attribute vec3 position; +attribute vec2 texcoord; +attribute vec3 normal; +attribute vec3 tangent; + +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 NormalMatrix; + +varying vec2 TextureCoord; +varying mat4 TangentToEyeMatrix; + +void main(void) +{ + TextureCoord = texcoord; + + // Calculate bitangent + vec3 bitangent = normalize(cross(normal, tangent)); + + // Calculate tangent space to eye space transformation matrix. + // We need this matrix in the fragment shader to transform the data + // from the normal map, which is in tangent space, to eye space, + // so that we can perform meaningful lighting calculations. Alternatively, + // we could have used an EyeToTangentMatrix, to convert light direction etc + // to tangent space. + + // First calculate a tangent space to object space transformation matrix. + mat4 TangentToObject = mat4(tangent.x, tangent.y, tangent.z, 0.0, + bitangent.x, bitangent.y, bitangent.z, 0.0, + normal.x, normal.y, normal.z, 0.0, + 0.0, 0.0, 0.0, 1.0); + + // Multiply with the NormalMatrix to further transform from object + // space to eye space (we are manipulating normals, so we can't use + // the ModelView matrix for this step!). + TangentToEyeMatrix = NormalMatrix * TangentToObject; + + // Transform the position to clip coordinates + gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0); +} === added file 'data/textures/asteroid-height-map.png' Binary files data/textures/asteroid-height-map.png 1970-01-01 00:00:00 +0000 and data/textures/asteroid-height-map.png 2011-11-14 18:01:44 +0000 differ === added file 'data/textures/asteroid-normal-map-tangent.png' Binary files data/textures/asteroid-normal-map-tangent.png 1970-01-01 00:00:00 +0000 and data/textures/asteroid-normal-map-tangent.png 2011-11-11 14:40:29 +0000 differ === modified file 'src/default-benchmarks.h' --- src/default-benchmarks.h 2011-11-08 20:20:02 +0000 +++ src/default-benchmarks.h 2011-11-14 12:39:08 +0000 @@ -51,6 +51,7 @@ benchmarks.push_back("shading:shading=phong"); benchmarks.push_back("bump:bump-render=high-poly"); benchmarks.push_back("bump:bump-render=normals"); + benchmarks.push_back("bump:bump-render=height"); benchmarks.push_back("effect2d:kernel=0,1,0;1,-4,1;0,1,0;"); benchmarks.push_back("effect2d:kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;"); benchmarks.push_back("pulsar:quads=5:texture=false:light=false"); === modified file 'src/model.cpp' --- src/model.cpp 2011-11-09 10:41:52 +0000 +++ src/model.cpp 2011-11-11 14:38:08 +0000 @@ -105,7 +105,8 @@ */ void Model::append_object_to_mesh(const Object &object, Mesh &mesh, - int p_pos, int n_pos, int t_pos) + int p_pos, int n_pos, int t_pos, + int nt_pos, int nb_pos) { size_t face_count = object.faces.size(); @@ -123,6 +124,10 @@ mesh.set_attrib(n_pos, a.n); if (t_pos >= 0) mesh.set_attrib(t_pos, a.t); + if (nt_pos >= 0) + mesh.set_attrib(nt_pos, a.nt); + if (nb_pos >= 0) + mesh.set_attrib(nb_pos, a.nb); mesh.next_vertex(); if (p_pos >= 0) @@ -131,6 +136,10 @@ mesh.set_attrib(n_pos, b.n); if (t_pos >= 0) mesh.set_attrib(t_pos, b.t); + if (nt_pos >= 0) + mesh.set_attrib(nt_pos, b.nt); + if (nb_pos >= 0) + mesh.set_attrib(nb_pos, b.nb); mesh.next_vertex(); if (p_pos >= 0) @@ -139,8 +148,11 @@ mesh.set_attrib(n_pos, c.n); if (t_pos >= 0) mesh.set_attrib(t_pos, c.t); + if (nt_pos >= 0) + mesh.set_attrib(nt_pos, c.nt); + if (nb_pos >= 0) + mesh.set_attrib(nb_pos, c.nb); } - } /** @@ -178,6 +190,8 @@ int p_pos = -1; int n_pos = -1; int t_pos = -1; + int nt_pos = -1; + int nb_pos = -1; mesh.reset(); @@ -192,6 +206,10 @@ n_pos = ai - attribs.begin(); else if (ai->first == AttribTypeTexcoord) t_pos = ai - attribs.begin(); + else if (ai->first == AttribTypeTangent) + nt_pos = ai - attribs.begin(); + else if (ai->first == AttribTypeBitangent) + nb_pos = ai - attribs.begin(); } mesh.set_vertex_format(format); @@ -200,7 +218,7 @@ iter != objects_.end(); iter++) { - append_object_to_mesh(*iter, mesh, p_pos, n_pos, t_pos); + append_object_to_mesh(*iter, mesh, p_pos, n_pos, t_pos, nt_pos, nb_pos); } } @@ -217,25 +235,62 @@ iter++) { Object &object = *iter; - size_t face_count = object.faces.size(); - size_t vertex_count = object.vertices.size(); - for(unsigned i = 0; i < face_count; i++) + for (vector::const_iterator f_iter = object.faces.begin(); + f_iter != object.faces.end(); + f_iter++) { - const Face &face = object.faces[i]; + const Face &face = *f_iter; Vertex &a = object.vertices[face.a]; Vertex &b = object.vertices[face.b]; Vertex &c = object.vertices[face.c]; + /* Calculate normal */ n = LibMatrix::vec3::cross(b.v - a.v, c.v - a.v); n.normalize(); a.n += n; b.n += n; c.n += n; - } - - for(unsigned i = 0; i < vertex_count; i++) - object.vertices[i].n.normalize(); + + LibMatrix::vec3 q1(b.v - a.v); + LibMatrix::vec3 q2(c.v - a.v); + LibMatrix::vec2 u1(b.t - a.t); + LibMatrix::vec2 u2(c.t - a.t); + float det = (u1.x() * u2.y() - u2.x() * u1.y()); + + /* Calculate tangent */ + LibMatrix::vec3 nt; + nt.x(det * (u2.y() * q1.x() - u1.y() * q2.x())); + nt.y(det * (u2.y() * q1.y() - u1.y() * q2.y())); + nt.z(det * (u2.y() * q1.z() - u1.y() * q2.z())); + nt.normalize(); + a.nt += nt; + b.nt += nt; + c.nt += nt; + + /* Calculate bitangent */ + LibMatrix::vec3 nb; + nb.x(det * (u1.x() * q2.x() - u2.x() * q1.x())); + nb.y(det * (u1.x() * q2.y() - u2.x() * q1.y())); + nb.z(det * (u1.x() * q2.z() - u2.x() * q1.z())); + nb.normalize(); + a.nb += nb; + b.nb += nb; + c.nb += nb; + } + + for (vector::iterator v_iter = object.vertices.begin(); + v_iter != object.vertices.end(); + v_iter++) + { + Vertex &v = *v_iter; + /* Orthogonalize */ + v.nt = (v.nt - v.n * LibMatrix::vec3::dot(v.nt, v.n)); + v.n.normalize(); + v.nt.normalize(); + v.nb.normalize(); + } + } } === modified file 'src/model.h' --- src/model.h 2011-11-09 10:34:35 +0000 +++ src/model.h 2011-11-11 14:38:08 +0000 @@ -70,9 +70,11 @@ typedef enum { AttribTypePosition = 1, - AttribTypeNormal = 2, - AttribTypeTexcoord = 4, - AttribTypeCustom = 8 + AttribTypeNormal, + AttribTypeTexcoord, + AttribTypeTangent, + AttribTypeBitangent, + AttribTypeCustom } AttribType; Model() {} @@ -97,6 +99,8 @@ LibMatrix::vec3 v; LibMatrix::vec3 n; LibMatrix::vec2 t; + LibMatrix::vec3 nt; + LibMatrix::vec3 nb; }; struct Object { @@ -107,7 +111,8 @@ }; void append_object_to_mesh(const Object &object, Mesh &mesh, - int p_pos, int n_pos, int t_pos); + int p_pos, int n_pos, int t_pos, + int nt_pos, int nb_pos); bool load_3ds(const std::string &filename); bool load_obj(const std::string &filename); === modified file 'src/scene-bump.cpp' --- src/scene-bump.cpp 2011-11-11 11:07:15 +0000 +++ src/scene-bump.cpp 2011-11-15 10:15:41 +0000 @@ -35,7 +35,7 @@ texture_(0), rotation_(0.0f), rotationSpeed_(0.0f) { options_["bump-render"] = Scene::Option("bump-render", "off", - "How to render bumps [off, normals, high-poly]"); + "How to render bumps [off, normals, normals-tangent, height, high-poly]"); } SceneBump::~SceneBump() @@ -159,6 +159,112 @@ } void +SceneBump::setup_model_normals_tangent() +{ + static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/bump-normals-tangent.vert"); + static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-normals-tangent.frag"); + static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f); + Model model; + + if(!model.load("asteroid-low")) + return; + + model.calculate_normals(); + + /* Calculate 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(); + + std::vector > attribs; + attribs.push_back(std::pair(Model::AttribTypePosition, 3)); + attribs.push_back(std::pair(Model::AttribTypeNormal, 3)); + attribs.push_back(std::pair(Model::AttribTypeTexcoord, 2)); + attribs.push_back(std::pair(Model::AttribTypeTangent, 3)); + + model.convert_to_mesh(mesh_, attribs); + + /* Load shaders */ + ShaderSource vtx_source(vtx_shader_filename); + ShaderSource frg_source(frg_shader_filename); + + /* Add constants to shaders */ + frg_source.add_const("LightSourcePosition", lightPosition); + frg_source.add_const("LightSourceHalfVector", halfVector); + + if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), + frg_source.str())) + { + return; + } + + std::vector attrib_locations; + attrib_locations.push_back(program_["position"].location()); + attrib_locations.push_back(program_["normal"].location()); + attrib_locations.push_back(program_["texcoord"].location()); + attrib_locations.push_back(program_["tangent"].location()); + mesh_.set_attrib_locations(attrib_locations); + + Texture::load(GLMARK_DATA_PATH"/textures/asteroid-normal-map-tangent.png", &texture_, + GL_NEAREST, GL_NEAREST, 0); +} + +void +SceneBump::setup_model_height() +{ + static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/bump-height.vert"); + static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-height.frag"); + static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f); + Model model; + + if(!model.load("asteroid-low")) + return; + + model.calculate_normals(); + + /* Calculate 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(); + + std::vector > attribs; + attribs.push_back(std::pair(Model::AttribTypePosition, 3)); + attribs.push_back(std::pair(Model::AttribTypeNormal, 3)); + attribs.push_back(std::pair(Model::AttribTypeTexcoord, 2)); + attribs.push_back(std::pair(Model::AttribTypeTangent, 3)); + + model.convert_to_mesh(mesh_, attribs); + + /* Load shaders */ + ShaderSource vtx_source(vtx_shader_filename); + ShaderSource frg_source(frg_shader_filename); + + /* Add constants to shaders */ + frg_source.add_const("LightSourcePosition", lightPosition); + frg_source.add_const("LightSourceHalfVector", halfVector); + frg_source.add_const("TextureStepX", 1.0 / 1024.0); + frg_source.add_const("TextureStepY", 1.0 / 1024.0); + + if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), + frg_source.str())) + { + return; + } + + std::vector attrib_locations; + attrib_locations.push_back(program_["position"].location()); + attrib_locations.push_back(program_["normal"].location()); + attrib_locations.push_back(program_["texcoord"].location()); + attrib_locations.push_back(program_["tangent"].location()); + mesh_.set_attrib_locations(attrib_locations); + + Texture::load(GLMARK_DATA_PATH"/textures/asteroid-height-map.png", &texture_, + GL_NEAREST, GL_NEAREST, 0); +} + +void SceneBump::setup() { Scene::setup(); @@ -168,6 +274,10 @@ Model::find_models(); if (bump_render == "normals") setup_model_normals(); + else if (bump_render == "normals-tangent") + setup_model_normals_tangent(); + else if (bump_render == "height") + setup_model_height(); else if (bump_render == "off" || bump_render == "high-poly") setup_model_plain(bump_render); @@ -178,6 +288,7 @@ // Load texture sampler value program_["NormalMap"] = 0; + program_["HeightMap"] = 0; currentFrame_ = 0; rotation_ = 0.0; @@ -239,6 +350,9 @@ normal_matrix.inverse().transpose(); program_["NormalMatrix"] = normal_matrix; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture_); + mesh_.render_vbo(); } @@ -263,6 +377,10 @@ ref = Canvas::Pixel(0x9c, 0x9c, 0x9c, 0xff); else if (bump_render == "normals") ref = Canvas::Pixel(0xa4, 0xa4, 0xa4, 0xff); + else if (bump_render == "normals-tangent") + ref = Canvas::Pixel(0x99, 0x99, 0x99, 0xff); + else if (bump_render == "height") + ref = Canvas::Pixel(0x9d, 0x9d, 0x9d, 0xff); else return Scene::ValidationUnknown; === modified file 'src/scene.h' --- src/scene.h 2011-11-11 11:07:15 +0000 +++ src/scene.h 2011-11-14 11:36:26 +0000 @@ -380,6 +380,8 @@ private: void setup_model_plain(const std::string &type); void setup_model_normals(); + void setup_model_normals_tangent(); + void setup_model_height(); }; class SceneEffect2D : public Scene