From 8e9d872c2ba8dc633d29a673ba93adf38d262a5c Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 2 Sep 2012 21:11:56 +0300 Subject: [PATCH] Standard vertex components for tangent and binormal vectors This simplifies using normalmapped standard shaders, as the shader is ready to use without the need to declare tangent and binormal attribute indices. --- blender/io_mspgl/export_mesh.py | 6 +++--- demos/shaders.cpp | 10 ++-------- source/box.cpp | 14 ++++++++------ source/capsule.cpp | 9 +++++---- source/cylinder.cpp | 16 ++++++++-------- source/geometrybuilder.cpp | 13 +++---------- source/geometrybuilder.h | 6 ++---- source/grid.cpp | 9 +++++---- source/programbuilder.cpp | 7 +++++++ source/vertexarray.cpp | 4 +++- source/vertexbuilder.h | 19 +++++++++++++++++++ source/vertexformat.cpp | 4 ++++ source/vertexformat.h | 2 ++ 13 files changed, 71 insertions(+), 48 deletions(-) diff --git a/blender/io_mspgl/export_mesh.py b/blender/io_mspgl/export_mesh.py index 135ed109..3da09f9a 100644 --- a/blender/io_mspgl/export_mesh.py +++ b/blender/io_mspgl/export_mesh.py @@ -294,7 +294,7 @@ class MeshExporter: else: fmt.append("TEXCOORD2_%d"%u.unit) if self.tbn_vecs: - fmt += ["ATTRIB3_3", "ATTRIB3_4"] + fmt += ["TANGENT3", "BINORMAL3"] if self.export_groups: fmt.append("ATTRIB%d_5"%(self.max_groups*2)) fmt.append("VERTEX3") @@ -317,10 +317,10 @@ class MeshExporter: uvs[i] = v.uvs[i] if self.tbn_vecs: if v.tan!=tan: - out_file.write("attrib3", 3, *v.tan) + out_file.write("tangent3", *v.tan) tan = v.tan if v.bino!=bino: - out_file.write("attrib3", 4, *v.bino) + out_file.write("binormal3", *v.bino) bino = v.bino if self.export_groups: group_attr = [(group_index_map[g.group], g.weight*v.group_weight_scale) for g in v.groups[:self.max_groups]] diff --git a/demos/shaders.cpp b/demos/shaders.cpp index 73ae1b72..872c3c16 100644 --- a/demos/shaders.cpp +++ b/demos/shaders.cpp @@ -56,10 +56,10 @@ int main() tex2.image(0, GL::RGB, GL::UNSIGNED_BYTE, data); delete[] data; - GL::Mesh mesh((GL::VERTEX3, GL::NORMAL3, GL::TEXCOORD2, GL::COLOR4_UBYTE, GL::ATTRIB3,4, GL::ATTRIB3,5)); + GL::Mesh mesh((GL::VERTEX3, GL::NORMAL3, GL::TEXCOORD2, GL::COLOR4_UBYTE, GL::TANGENT3, GL::BINORMAL3)); GL::MeshBuilder bld(mesh); bld.color(0.5f, 1.0f, 0.0f); - GL::CapsuleBuilder(1, 0.72498, 32, 17).texture_fit(GL::GeometryBuilder::WRAP).tangent(4).binormal(5).build(bld); + GL::CapsuleBuilder(1, 0.72498, 32, 17).texture_fit(GL::GeometryBuilder::WRAP).tbn().build(bld); GL::Material mat; mat.set_diffuse(GL::Color(0.5, 1.0, 0.0)); mat.set_specular(GL::Color(0.45, 0.5, 0.4)); @@ -74,12 +74,6 @@ int main() feat.normalmap = i%4>1; feat.specular = i%4>2; programs.push_back(new GL::Program(feat)); - if(feat.normalmap) - { - programs.back()->bind_attribute(4, "tangent"); - programs.back()->bind_attribute(5, "binormal"); - programs.back()->link(); - } } GL::ProgramData progdata; diff --git a/source/box.cpp b/source/box.cpp index 0958d1b0..b20f0d04 100644 --- a/source/box.cpp +++ b/source/box.cpp @@ -36,15 +36,17 @@ void BoxBuilder::build(PrimitiveBuilder &builder) const void BoxBuilder::build_face(PrimitiveBuilder &builder, const Vector3 &o, const Vector3 &s1, const Vector3 &s2) const { float l1 = 1, l2 = 1; - if(tangent_attr>=0 || tex_fit!=STRETCH) + if(generate_tbn || tex_fit!=STRETCH) + { l1 = sqrt(s1.x*s1.x+s1.y*s1.y+s1.z*s1.z); - if(binormal_attr>=0 || tex_fit!=STRETCH) l2 = sqrt(s2.x*s2.x+s2.y*s2.y+s2.z*s2.z); + } - if(tangent_attr>=0) - builder.attrib(tangent_attr, s1.x/l1, s1.y/l1, s1.z/l1); - if(binormal_attr>=0) - builder.attrib(binormal_attr, s2.x/l2, s2.y/l2, s2.z/l2); + if(generate_tbn) + { + builder.tangent(s1.x/l1, s1.y/l1, s1.z/l1); + builder.binormal(s2.x/l2, s2.y/l2, s2.z/l2); + } float u_size = 1; float v_size = 1; diff --git a/source/capsule.cpp b/source/capsule.cpp index 9553edd3..f00f6ca2 100644 --- a/source/capsule.cpp +++ b/source/capsule.cpp @@ -42,10 +42,11 @@ void CapsuleBuilder::build(PrimitiveBuilder &builder) const float sc = cos(sa); float ss = sin(sa); builder.normal(rs*sc, rs*ss, -rc); - if(tangent_attr>=0) - builder.attrib(tangent_attr, -ss, sc, 0); - if(binormal_attr>=0) - builder.attrib(binormal_attr, rc*sc, rc*ss, rs); + if(generate_tbn) + { + builder.tangent(-ss, sc, 0); + builder.binormal(rc*sc, rc*ss, rs); + } builder.texcoord(j*u_scale, v); builder.vertex(rs*sc*radius, rs*ss*radius, cz-rc*radius); } diff --git a/source/cylinder.cpp b/source/cylinder.cpp index bbc536d7..5ea99723 100644 --- a/source/cylinder.cpp +++ b/source/cylinder.cpp @@ -18,15 +18,15 @@ CylinderBuilder::CylinderBuilder(float r, float l, unsigned s): void CylinderBuilder::build(PrimitiveBuilder &builder) const { - if(binormal_attr>=0) - builder.attrib(binormal_attr, 0, 1, 0); + if(generate_tbn) + builder.binormal(0, 1, 0); for(unsigned i=0; i<2; ++i) { float z = (i-0.5)*length; builder.normal(0, 0, i*2.0-1.0); builder.texcoord(0.5, 0.5); - if(tangent_attr>=0) - builder.attrib(tangent_attr, (i ? 1 : -1), 0, 0); + if(generate_tbn) + builder.tangent((i ? 1 : -1), 0, 0); builder.vertex(0, 0, z); for(unsigned j=0; j=0) - builder.attrib(binormal_attr, 0, 0, 1); + if(generate_tbn) + builder.binormal(0, 0, 1); for(unsigned i=0; i<2; ++i) { float z = (i-0.5)*length; @@ -54,8 +54,8 @@ void CylinderBuilder::build(PrimitiveBuilder &builder) const float s = sin(a); builder.normal(c, s, 0); builder.texcoord(j*u_scale, i*v_scale); - if(tangent_attr>=0) - builder.attrib(tangent_attr, -s, c, 0); + if(generate_tbn) + builder.tangent(-s, c, 0); builder.vertex(radius*c, radius*s, z); } } diff --git a/source/geometrybuilder.cpp b/source/geometrybuilder.cpp index ba3e8600..729b40fa 100644 --- a/source/geometrybuilder.cpp +++ b/source/geometrybuilder.cpp @@ -5,20 +5,13 @@ namespace Msp { namespace GL { GeometryBuilder::GeometryBuilder(): - tangent_attr(-1), - binormal_attr(-1), + generate_tbn(false), tex_fit(STRETCH) { } -GeometryBuilder &GeometryBuilder::tangent(unsigned t) +GeometryBuilder &GeometryBuilder::tbn(bool t) { - tangent_attr = t; - return *this; -} - -GeometryBuilder &GeometryBuilder::binormal(unsigned b) -{ - binormal_attr = b; + generate_tbn = t; return *this; } diff --git a/source/geometrybuilder.h b/source/geometrybuilder.h index 76c1ba2f..40bcd13e 100644 --- a/source/geometrybuilder.h +++ b/source/geometrybuilder.h @@ -18,15 +18,13 @@ public: }; protected: - int tangent_attr; - int binormal_attr; + bool generate_tbn; TextureFit tex_fit; GeometryBuilder(); public: - GeometryBuilder &tangent(unsigned); - GeometryBuilder &binormal(unsigned); + GeometryBuilder &tbn(bool = true); GeometryBuilder &texture_fit(TextureFit); protected: void adjust_texture_scale(float &, float &, float, float) const; diff --git a/source/grid.cpp b/source/grid.cpp index 2f1a2a1c..aaeada8a 100644 --- a/source/grid.cpp +++ b/source/grid.cpp @@ -88,10 +88,11 @@ void GridBuilder::build(PrimitiveBuilder &builder) const adjust_texture_scale(u_scale, v_scale, sqrt(l1_sq), l2); builder.normal(norm.x, norm.y, norm.z); - if(tangent_attr>=0) - builder.attrib(tangent_attr, side1.x, side1.y, side1.z); - if(binormal_attr>=0) - builder.attrib(tangent_attr, binorm.x, binorm.y, binorm.z); + if(generate_tbn) + { + builder.tangent(side1.x, side1.y, side1.z); + builder.binormal(binorm.x, binorm.y, binorm.z); + } for(unsigned j=0; j<=v_div; ++j) { diff --git a/source/programbuilder.cpp b/source/programbuilder.cpp index a24b5d56..4043fc44 100644 --- a/source/programbuilder.cpp +++ b/source/programbuilder.cpp @@ -3,6 +3,7 @@ #include "program.h" #include "programbuilder.h" #include "shader.h" +#include "vertexformat.h" using namespace std; @@ -182,6 +183,12 @@ void ProgramBuilder::add_shaders(Program &prog) const prog.attach_shader_owned(new VertexShader(create_source(resolved_vars, VERTEX))); prog.attach_shader_owned(new FragmentShader(create_source(resolved_vars, FRAGMENT))); + + if(features.normalmap) + { + prog.bind_attribute(get_component_type(TANGENT3), "tangent"); + prog.bind_attribute(get_component_type(BINORMAL3), "binormal"); + } } string ProgramBuilder::create_source(const list &variables, VariableScope scope) const diff --git a/source/vertexarray.cpp b/source/vertexarray.cpp index e91062bb..79d68231 100644 --- a/source/vertexarray.cpp +++ b/source/vertexarray.cpp @@ -34,7 +34,7 @@ void VertexArray::reset(const VertexFormat &f) { if(*c>=TEXCOORD1+4 && *c<=TEXCOORD4+12) has_multitex = true; - if(*c>=ATTRIB1) + if(*c==TANGENT3 || *c==BINORMAL3 || *c>=ATTRIB1) has_gen_attrs = true; } if(has_multitex) @@ -235,6 +235,8 @@ VertexArray::Loader::Loader(VertexArray &a): add("attrib2", static_cast(&Loader::attrib)); add("attrib3", static_cast(&Loader::attrib)); add("attrib4", static_cast(&Loader::attrib)); + add("tangent3", static_cast(&Loader::tangent)); + add("binormal3", static_cast(&Loader::binormal)); } } // namespace GL diff --git a/source/vertexbuilder.h b/source/vertexbuilder.h index 25eb0e76..7a1c943c 100644 --- a/source/vertexbuilder.h +++ b/source/vertexbuilder.h @@ -5,6 +5,7 @@ #include "color.h" #include "matrix.h" #include "vector.h" +#include "vertexformat.h" namespace Msp { namespace GL { @@ -60,6 +61,24 @@ public: nor = Vector3(tn.x, tn.y, tn.z); } + void tangent(float x, float y, float z) + { tangent(Vector3(x, y, z)); } + + void tangent(const Vector3 &t) + { + Vector4 tt = mtx.top()*Vector4(t.x, t.y, t.z, 0); + attrib(get_component_type(TANGENT3), tt); + } + + void binormal(float x, float y, float z) + { binormal(Vector3(x, y, z)); } + + void binormal(const Vector3 &b) + { + Vector4 tb = mtx.top()*Vector4(b.x, b.y, b.z, 0); + attrib(get_component_type(BINORMAL3), tb); + } + void texcoord(float s) { texcoord(s, 0, 0, 1); } diff --git a/source/vertexformat.cpp b/source/vertexformat.cpp index 1de43087..8cc0cec9 100644 --- a/source/vertexformat.cpp +++ b/source/vertexformat.cpp @@ -139,6 +139,10 @@ void operator>>(const LexicalConverter &conv, VertexComponent &c) c = static_cast(COLOR3_FLOAT+(str[5]-'3')); else if(str=="COLOR4_UBYTE") c = COLOR4_UBYTE; + else if(str=="TANGENT3") + c = TANGENT3; + else if(str=="BINORMAL3") + c = BINORMAL3; else if(str.size()>=9 && !str.compare(0, 8, "TEXCOORD") && str[8]>='1' && str[8]<='4') { if(str.size()==9) diff --git a/source/vertexformat.h b/source/vertexformat.h index 9be98160..4c343c99 100644 --- a/source/vertexformat.h +++ b/source/vertexformat.h @@ -18,6 +18,8 @@ enum VertexComponent COLOR4_UBYTE = 12, COLOR3_FLOAT = 14, COLOR4_FLOAT, + TANGENT3 = 18, + BINORMAL3 = 22, TEXCOORD1 = 32, TEXCOORD2, TEXCOORD3, -- 2.45.2