draw_range_elements(type, min_index, max_index, indices.size(), &indices[0]);
}
+void Batch::draw_with_buffer(unsigned offset) const
+{
+ draw_range_elements(type, min_index, max_index, indices.size(), (unsigned *)0+offset);
+}
+
Batch::Loader::Loader(Batch &b):
batch(b)
void indices(const std::vector<uint> &);
};
- Batch(PrimitiveType t);
- Batch &append(uint);
- void append(const std::vector<uint> &);
- void draw() const;
private:
PrimitiveType type;
std::vector<uint> indices;
uint min_index;
uint max_index;
+
+public:
+ Batch(PrimitiveType t);
+ Batch &append(uint);
+ void append(const std::vector<uint> &);
+ unsigned size() const { return indices.size(); }
+ const std::vector<uint> &get_indices() const { return indices; }
+ void draw() const;
+ void draw_with_buffer(unsigned) const;
};
} // namespace GL
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include "arb_vertex_buffer_object.h"
+#include "extension.h"
+#include "buffer.h"
+
+namespace Msp {
+namespace GL {
+
+Buffer::Buffer(BufferType t):
+ type(t),
+ usage(STATIC_DRAW)
+{
+ static RequireExtension _req_vbo("GL_ARB_vertex_buffer_object");
+ if(type==PIXEL_PACK_BUFFER || type==PIXEL_UNPACK_BUFFER)
+ static RequireExtension _req_pbo("GL_ARB_pixel_buffer_object");
+
+ glGenBuffersARB(1, &id);
+}
+
+Buffer::~Buffer()
+{
+ glDeleteBuffersARB(1, &id);
+}
+
+void Buffer::bind(BufferType t) const
+{
+ glBindBufferARB(t, id);
+ binding(t)=this;
+}
+
+void Buffer::maybe_bind() const
+{
+ if(binding(type)!=this)
+ bind();
+}
+
+void Buffer::set_usage(BufferUsage u)
+{
+ usage=u;
+}
+
+void Buffer::data(unsigned size, const void *d)
+{
+ maybe_bind();
+ glBufferDataARB(type, size, d, usage);
+}
+
+void Buffer::sub_data(unsigned offset, unsigned size, const void *d)
+{
+ maybe_bind();
+ glBufferSubDataARB(type, offset, size, d);
+}
+
+void Buffer::unbind(BufferType type)
+{
+ const Buffer *&ptr=binding(type);
+ if(ptr)
+ {
+ glBindBufferARB(type, 0);
+ ptr=0;
+ }
+}
+
+const Buffer *&Buffer::binding(BufferType type)
+{
+ switch(type)
+ {
+ case ARRAY_BUFFER: return bound[0];
+ case ELEMENT_ARRAY_BUFFER: return bound[1];
+ case PIXEL_PACK_BUFFER: return bound[2];
+ case PIXEL_UNPACK_BUFFER: return bound[3];
+ default: throw InvalidParameterValue("Invalid buffer type");
+ }
+}
+
+const Buffer *Buffer::bound[4]={ 0, 0, 0, 0 };
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_BUFFER_H_
+#define MSP_GL_BUFFER_H_
+
+#include "types.h"
+
+namespace Msp {
+namespace GL {
+
+enum BufferType
+{
+ ARRAY_BUFFER = GL_ARRAY_BUFFER_ARB,
+ ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER_ARB,
+ PIXEL_PACK_BUFFER = GL_PIXEL_PACK_BUFFER_ARB,
+ PIXEL_UNPACK_BUFFER = GL_PIXEL_UNPACK_BUFFER_ARB
+};
+
+enum BufferUsage
+{
+ STREAM_DRAW = GL_STREAM_DRAW_ARB,
+ STREAM_READ = GL_STREAM_READ_ARB,
+ STREAM_COPY = GL_STREAM_COPY_ARB,
+ STATIC_DRAW = GL_STATIC_DRAW_ARB,
+ STATIC_READ = GL_STATIC_READ_ARB,
+ STATIC_COPY = GL_STATIC_COPY_ARB,
+ DYNAMIC_DRAW = GL_DYNAMIC_DRAW_ARB,
+ DYNAMIC_READ = GL_DYNAMIC_READ_ARB,
+ DYNAMIC_COPY = GL_DYNAMIC_COPY_ARB
+};
+
+/**
+A buffer for storing data in GL memory. Putting vertex and index data in
+buffers can improve rendering performance. The VertexArray and Mesh classes
+contain built-in support for buffers.
+*/
+class Buffer
+{
+private:
+ BufferType type;
+ BufferUsage usage;
+ unsigned id;
+
+ static const Buffer *bound[4];
+
+public:
+ Buffer(BufferType);
+ ~Buffer();
+
+ /** Binds the buffer in its default slot. */
+ void bind() const { bind(type); }
+
+ /** Binds the buffer in an alternate slot. */
+ void bind(BufferType) const;
+
+private:
+ void maybe_bind() const;
+
+public:
+ /** Unbinds the buffer from its default slot. */
+ void unbind() const { unbind(type); }
+
+ /** Sets the usage hint of the buffer. It will take effect the next time
+ the buffer's contents are defined. */
+ void set_usage(BufferUsage);
+
+ /** Uploads data into the buffer, completely replacing any previous
+ contents. */
+ void data(unsigned, const void *);
+
+ /** Overwrites part of the buffer data with new data. The buffer size can
+ not be changed with this call. */
+ void sub_data(unsigned, unsigned, const void *);
+
+ static void unbind(BufferType);
+private:
+ static const Buffer *&binding(BufferType);
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
array(f)
{ }
+void Immediate::reset()
+{
+ if(in_batch)
+ throw InvalidState("Can't reset Immediate between begin() and end()");
+
+ array.clear();
+ indices.clear();
+}
+
void Immediate::end_()
{
array.apply();
draw_elements(type, indices.size(), &indices[0]);
- array.clear();
indices.clear();
}
public:
Immediate(VertexFormat);
+ void reset();
private:
virtual void begin_() { }
virtual void end_();
Distributed under the LGPL
*/
+#include "buffer.h"
#include "mesh.h"
using namespace std;
namespace GL {
Mesh::Mesh():
- vertices(VERTEX3)
+ vertices(VERTEX3),
+ ibuf(0)
{ }
-Mesh::Mesh(VertexFormat f):
- vertices(f)
+Mesh::Mesh(const VertexFormat &f):
+ vertices(f),
+ ibuf(0)
{ }
void Mesh::use_vertex_buffer(bool b)
{
if(b)
+ {
vertices.use_vertex_buffer();
+ if(!ibuf)
+ ibuf=new Buffer(ELEMENT_ARRAY_BUFFER);
+ update_index_buffer();
+ }
else
+ {
vertices.use_vertex_buffer(0);
+ delete ibuf;
+ ibuf=0;
+ }
+}
+
+float *Mesh::get_vertex(unsigned i)
+{
+ return vertices[i];
}
void Mesh::add_batch(const Batch &b)
{
batches.push_back(b);
+ update_index_buffer();
}
void Mesh::clear()
void Mesh::draw() const
{
vertices.apply();
+ if(ibuf)
+ {
+ ibuf->bind();
+ unsigned offset=0;
+ for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
+ {
+ i->draw_with_buffer(offset);
+ offset+=i->size();
+ }
+ ibuf->unbind();
+ }
+ else
+ {
+ for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
+ i->draw();
+ }
+}
+
+void Mesh::update_index_buffer()
+{
+ if(!ibuf)
+ return;
+
+ unsigned total=0;
+ for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
+ total+=i->size();
+
+ ibuf->data(total*sizeof(unsigned), 0);
+ unsigned offset=0;
for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
- i->draw();
+ {
+ ibuf->sub_data(offset*sizeof(unsigned), i->size()*sizeof(unsigned), &i->get_indices()[0]);
+ offset+=i->size();
+ }
+ ibuf->unbind();
}
namespace Msp {
namespace GL {
+class Buffer;
+
class Mesh
{
friend class MeshBuilder;
private:
VertexArray vertices;
std::list<Batch> batches;
+ Buffer *ibuf;
public:
Mesh();
- Mesh(VertexFormat f);
+ Mesh(const VertexFormat &f);
void use_vertex_buffer(bool);
const VertexArray &get_vertices() const { return vertices; }
+ float *get_vertex(unsigned);
void add_batch(const Batch &b);
const std::list<Batch> &get_batches() { return batches; }
void clear();
void draw() const;
+private:
+ void update_index_buffer();
};
} // namespace GL
void get(GLenum, int &);
int get_i(GLenum);
+class Bind
+{
+private:
+ struct Base
+ {
+ virtual ~Base() { }
+ };
+
+ template<typename T>
+ struct Binder: Base
+ {
+ const T &obj;
+
+ Binder(const T &o): obj(o) { obj.bind(); }
+ ~Binder() { obj.unbind(); }
+ };
+
+ Base *binder;
+
+public:
+ template<typename T>
+ Bind(const T &o): binder(new Binder<T>(o)) { }
+ ~Bind() { delete binder; }
+};
+
} // namespace GL
} // namespace Msp
return string(log, len);
}
-void Program::bind()
+void Program::bind() const
{
if(!linked)
throw InvalidState("Program is not linked");
bind();
}
-Program *Program::cur_prog=0;
+const Program *Program::cur_prog=0;
Program::Loader::Loader(Program &p):
bool del_shaders;
bool linked;
- static Program *cur_prog;
+ static const Program *cur_prog;
public:
class Loader: public DataFile::Loader
int get_param(GLenum param) const;
bool get_linked() const { return linked; }
std::string get_info_log() const;
- void bind();
+ void bind() const;
int get_uniform_location(const std::string &) const;
static void unbind();
if(vbuf && own_vbuf)
return;
- vbuf=new VertexBuffer();
+ vbuf=new Buffer(ARRAY_BUFFER);
own_vbuf=true;
update_data();
}
-void VertexArray::use_vertex_buffer(VertexBuffer *b)
+void VertexArray::use_vertex_buffer(Buffer *b)
{
if(own_vbuf)
delete vbuf;
set_array(i-4, (found>>i)&1, 1<<i);
if(vbuf)
- VertexBuffer::unbind();
+ vbuf->unbind();
}
/**
if(vbuf)
{
vbuf->data(data.size()*sizeof(float), &data[0]);
- VertexBuffer::unbind();
+ vbuf->unbind();
}
}
namespace Msp {
namespace GL {
-class VertexBuffer;
+class Buffer;
class VertexArray
{
VertexFormat format;
std::vector<float> data;
uint stride;
- VertexBuffer *vbuf;
+ Buffer *vbuf;
bool own_vbuf;
VertexArray(const VertexArray &);
const VertexFormat &get_format() const { return format; }
const std::vector<float> &get_data() const { return data; }
void use_vertex_buffer();
- void use_vertex_buffer(VertexBuffer *);
+ void use_vertex_buffer(Buffer *);
void reserve(unsigned);
unsigned size() const { return data.size()/stride; }
void clear();
+++ /dev/null
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include "arb_vertex_buffer_object.h"
-#include "extension.h"
-#include "vertexbuffer.h"
-
-namespace Msp {
-namespace GL {
-
-VertexBuffer::VertexBuffer()
-{
- static RequireExtension _ext("GL_ARB_vertex_buffer_object");
-
- glGenBuffersARB(1, &id);
-}
-
-void VertexBuffer::bind() const
-{
- glBindBufferARB(GL_ARRAY_BUFFER, id);
- bound=this;
-}
-
-void VertexBuffer::data(sizei size, void *d)
-{
- if(bound!=this) bind();
-
- glBufferDataARB(GL_ARRAY_BUFFER, size, d, GL_STATIC_DRAW);
-}
-
-VertexBuffer::~VertexBuffer()
-{
- glDeleteBuffersARB(1, &id);
-}
-
-void VertexBuffer::unbind()
-{
- if(bound)
- {
- glBindBufferARB(GL_ARRAY_BUFFER, 0);
- bound=0;
- }
-}
-
-const VertexBuffer *VertexBuffer::bound=0;
-
-} // namespace GL
-} // namespace Msp
#ifndef MSP_GL_VERTEXBUFFER_H_
#define MSP_GL_VERTEXBUFFER_H_
-#include "types.h"
+#include "buffer.h"
namespace Msp {
namespace GL {
-class VertexBuffer
+/**
+Deprecated. Equivalent to Buffer of type ARRAY_BUFFER. Retained for backwards
+compatibility only.
+*/
+class VertexBuffer: public Buffer
{
public:
- VertexBuffer();
- void bind() const;
- void data(sizei, void *);
- ~VertexBuffer();
-
- static void unbind();
-private:
- uint id;
+ VertexBuffer(): Buffer(ARRAY_BUFFER) { }
- static const VertexBuffer *bound;
+ static void unbind() { Buffer::unbind(ARRAY_BUFFER); }
};
} // namespace GL