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")
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]]
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));
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;
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;
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);
}
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<segments; ++j)
{
float v_scale = 1;
adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, length);
- if(binormal_attr>=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;
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);
}
}
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;
}
};
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;
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)
{
#include "program.h"
#include "programbuilder.h"
#include "shader.h"
+#include "vertexformat.h"
using namespace std;
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<ShaderVariable *> &variables, VariableScope scope) const
{
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)
add("attrib2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
add("attrib3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
add("attrib4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
+ add("tangent3", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
+ add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
}
} // namespace GL
#include "color.h"
#include "matrix.h"
#include "vector.h"
+#include "vertexformat.h"
namespace Msp {
namespace GL {
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); }
c = static_cast<VertexComponent>(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)
COLOR4_UBYTE = 12,
COLOR3_FLOAT = 14,
COLOR4_FLOAT,
+ TANGENT3 = 18,
+ BINORMAL3 = 22,
TEXCOORD1 = 32,
TEXCOORD2,
TEXCOORD3,