st.append(Token("TANGENT3"))
st.append(Token("BINORMAL3"))
if mesh.vertex_groups:
- st.append(Token("ATTRIB{}_5".format(mesh.max_groups_per_vertex*2)))
+ st.append(Token("GENERIC{}_0".format(mesh.max_groups_per_vertex*2)))
st.append(Token("VERTEX3"))
normal = None
group_attr.append((0, 0.0))
group_attr = list(itertools.chain(*group_attr))
if group_attr!=group:
- st.sub.append(Statement("attrib", 5, *group_attr))
+ st.sub.append(Statement("generic", 0, *group_attr))
group = group_attr
st.sub.append(Statement("vertex", *v.co))
#pragma MSP stage(vertex)
layout(location=0) in vec4 vertex;
-layout(location=8) in vec4 texcoord;
-layout(location=3) in vec4 color;
+layout(location=1) in vec4 color;
layout(location=2) in vec3 normal;
-layout(location=4) in vec3 tangent;
-layout(location=5) in vec3 binormal;
-layout(location=12) in vec4 instance_transform[3];
+layout(location=3) in vec3 tangent;
+layout(location=4) in vec3 binormal;
+layout(location=7) in vec4 texcoord;
+layout(location=8) in vec4 texcoord1;
+layout(location=9) in vec4 texcoord2;
+layout(location=10) in vec4 texcoord3;
+layout(location=13) in vec4 instance_transform[3];
#pragma MSP stage(fragment)
layout(location=0) out vec4 frag_color;
void color(const Color &c)
{ attrib(get_attribute_semantic(COLOR4_FLOAT), Vector4(c.r, c.g, c.b, c.a)); }
- void attrib(unsigned i, float x)
- { attrib(i, x, 0, 0, 1); }
+ void generic(unsigned i, float x)
+ { generic(i, x, 0, 0, 1); }
- void attrib(unsigned i, float x, float y)
- { attrib(i, x, y, 0, 1); }
+ void generic(unsigned i, float x, float y)
+ { generic(i, x, y, 0, 1); }
- void attrib(unsigned i, float x, float y, float z)
- { attrib(i, x, y, z, 1); }
+ void generic(unsigned i, float x, float y, float z)
+ { generic(i, x, y, z, 1); }
- void attrib(unsigned i, float x, float y, float z, float w)
- { attrib(i, Vector4(x, y, z, w)); }
+ void generic(unsigned i, float x, float y, float z, float w)
+ { generic(i, Vector4(x, y, z, w)); }
+
+ void generic(unsigned i, const Vector4 &a)
+ { attrib(get_attribute_semantic(GENERIC4)+i, a); }
};
} // namespace GL
add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
add("color", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
add("color", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
- add("attrib", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
- add("attrib", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
- add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
- add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
+ add("generic", static_cast<void (Loader::*)(unsigned, float)>(&Loader::generic));
+ add("generic", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::generic));
+ add("generic", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::generic));
+ add("generic", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::generic));
add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
add("color3", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
add("color4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
- add("attrib1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
- 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("generic1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::generic));
+ add("generic2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::generic));
+ add("generic3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::generic));
+ add("generic4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::generic));
add("tangent3", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
}
#include <msp/strings/lexicalcast.h>
#include <msp/strings/utils.h>
#include "error.h"
+#include "misc.h"
#include "vertexformat.h"
+#include <msp/gl/extensions/arb_vertex_shader.h>
using namespace std;
VertexAttribute make_indexed_attribute(VertexAttribute attr, unsigned index)
{
+ unsigned base = attr;
if(attr>=TEXCOORD1 && attr<=TEXCOORD4)
{
if(index>=4)
throw out_of_range("make_indexed_attribute");
}
- else if(attr>=ATTRIB1 && attr<=ATTRIB4)
- {
- if(index>=24)
- throw out_of_range("make_indexed_attribute");
- }
- else
+ else if(attr>=RAW_ATTRIB1 && attr<=RAW_ATTRIB4)
+ base &= 7;
+ else if(attr<GENERIC1 || attr>GENERIC4)
throw invalid_argument("make_indexed_attribute");
- return static_cast<VertexAttribute>(attr+index*4);
+
+ static int max_attribs = -1;
+ if(max_attribs<0)
+ max_attribs = get_i(GL_MAX_VERTEX_ATTRIBS);
+
+ if(static_cast<int>((base>>3)+index)>=max_attribs)
+ throw out_of_range("make_indexed_attribute");
+
+ return static_cast<VertexAttribute>(base+index*8);
}
void operator>>(const LexicalConverter &conv, VertexAttribute &a)
{
if(str.size()==9)
a = static_cast<VertexAttribute>(TEXCOORD1+(str[8]-'1'));
- else if(str.size()==11 && str[9]=='_' && str[10]>='0' && str[10]<='7')
- a = static_cast<VertexAttribute>(TEXCOORD1+(str[8]-'1')+(str[10]-'0')*4);
+ else if(str.size()==11 && str[9]=='_' && str[10]>='0' && str[10]<='3')
+ a = make_indexed_attribute(static_cast<VertexAttribute>(TEXCOORD1+(str[8]-'1')), str[10]-'0');
else
throw lexical_error(format("conversion of '%s' to VertexAttribute", str));
}
- else if(str.size()>=9 && !str.compare(0, 6, "ATTRIB") && str[6]>='1' && str[6]<='4' && str[7]=='_')
+ else if(str.size()>=10 && !str.compare(0, 6, "GENERIC") && str[7]>='1' && str[7]<='4' && str[8]=='_')
{
unsigned n;
try
{
- n = lexical_cast<unsigned>(str.substr(8));
+ n = lexical_cast<unsigned>(str.substr(9));
}
catch(const lexical_error &)
{
throw lexical_error(format("conversion of '%s' to VertexAttribute", str));
}
- a = static_cast<VertexAttribute>(ATTRIB1+(str[6]-'1')+n*4);
+ a = make_indexed_attribute(static_cast<VertexAttribute>(GENERIC1+(str[7]-'1')), n);
}
else
throw lexical_error(format("conversion of '%s' to VertexAttribute", str));
namespace Msp {
namespace GL {
-/** A single vertex component. Symbolic names are provided for commonly used
-attributes. These are aliased with with generic attributes, so be careful when
-picking your attribute indices. */
+/** A single vertex attribute. Commonly used attributes are named by their
+semantical meaning in the standard shaders. Texture coordinates and generic
+attributes can additionally be given an index. There are four texture
+coordinate attributes available. The number of available generic attributes
+depends on implementation limits, but is at least five.
+
+RAW_ATTRIB is handled in a special way; creating an indexed attribute based on
+it uses the index as raw attribute number. Only use it if you know what you
+are doing. */
enum VertexAttribute
{
VERTEX2 = 1,
VERTEX3,
VERTEX4,
- NORMAL3 = 10,
- COLOR4_UBYTE = 12,
- COLOR3_FLOAT = 14,
+ COLOR4_UBYTE = 8,
+ COLOR3_FLOAT = 10,
COLOR4_FLOAT,
- TANGENT3 = 18,
- BINORMAL3 = 22,
- TEXCOORD1 = 32,
+ NORMAL3 = 18,
+ TANGENT3 = 26,
+ BINORMAL3 = 34,
+ // Attributes 5 and 6 reserved for vertex groups and weights
+ TEXCOORD1 = 56,
TEXCOORD2,
TEXCOORD3,
TEXCOORD4,
- ATTRIB1 = 64,
- ATTRIB2,
- ATTRIB3,
- ATTRIB4
+ GENERIC1 = 88,
+ GENERIC2,
+ GENERIC3,
+ GENERIC4,
+ RAW_ATTRIB1 = 248,
+ RAW_ATTRIB2,
+ RAW_ATTRIB3,
+ RAW_ATTRIB4
};
DEPRECATED typedef VertexAttribute VertexComponent;
{ return make_indexed_attribute(a, i); }
inline unsigned get_attribute_semantic(unsigned char a)
-{ return a>>2; }
+{ return a>>3; }
inline unsigned get_attribute_size(unsigned char a)
{ return (a&3)+1; }
{
unsigned mask = 0;
for(const unsigned char *a=fmt.begin(); a!=fmt.end(); ++a)
- {
- unsigned sem = get_attribute_semantic(*a);
- if(sem>=get_attribute_semantic(ATTRIB1))
- sem -= get_attribute_semantic(ATTRIB1);
- mask |= 1<<sem;
- }
+ mask |= 1<<get_attribute_semantic(*a);
return mask;
}
for(const unsigned char *a=fmt.begin(); a!=fmt.end(); ++a)
{
unsigned sem = get_attribute_semantic(*a);
- if(sem>=get_attribute_semantic(ATTRIB1))
- sem -= get_attribute_semantic(ATTRIB1);
unsigned sz = get_attribute_size(*a);
if(direct)
{
if(ARB_vertex_array_object && ARB_instanced_arrays && ARB_draw_instanced)
{
- instance_data = new VertexArray((ATTRIB4,matrix_location, ATTRIB4,matrix_location+1, ATTRIB4,matrix_location+2));
+ instance_data = new VertexArray((RAW_ATTRIB4,matrix_location, RAW_ATTRIB4,matrix_location+1, RAW_ATTRIB4,matrix_location+2));
const VertexFormat &fmt = instance_data->get_format();
- matrix_offset = fmt.offset(make_indexed_attribute(ATTRIB4, matrix_location));
+ matrix_offset = fmt.offset(make_indexed_attribute(RAW_ATTRIB4, matrix_location));
instance_buffer = new Buffer(ARRAY_BUFFER);
instance_data->use_buffer(instance_buffer);