Skip to content

Commit b728ac6

Browse files
committed
Proposal of VAO class built on Bindable template.
1 parent 13b7ac9 commit b728ac6

2 files changed

Lines changed: 168 additions & 0 deletions

File tree

src/Bindable.hpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#pragma once
2+
#include "glid.hpp"
3+
#include <boost/optional.hpp>
4+
5+
namespace gldr {
6+
7+
template<typename T>
8+
class ScopedBinder {
9+
boost::optional<GLuint> id;
10+
11+
public:
12+
ScopedBinder(GLuint rebId)
13+
: id(rebId)
14+
{ }
15+
ScopedBinder(ScopedBinder && rhs) {
16+
// workaround for lack of move constructor in boost::optional
17+
id.swap(rhs.id);
18+
}
19+
~ScopedBinder() {
20+
if (id) {
21+
T::bindObject(id.get());
22+
}
23+
}
24+
25+
private:
26+
ScopedBinder& operator=(ScopedBinder&) /* = delete*/;
27+
ScopedBinder& operator=(ScopedBinder&&) /* = delete*/;
28+
ScopedBinder(ScopedBinder&) /* = delete */;
29+
};
30+
31+
template<typename T>
32+
class Bindable {
33+
protected:
34+
Glid<T> id;
35+
36+
public:
37+
void bind() {
38+
T::bindObject(id.get());
39+
}
40+
41+
static void unbind() {
42+
T::bindObject(0);
43+
}
44+
45+
static ScopedBinder<T> createRebindToCurrent() {
46+
return ScopedBinder<T>(T::getCurrentlyBound());
47+
}
48+
49+
ScopedBinder<T> scopedBind() {
50+
auto current = T::getCurrentlyBound();
51+
bind();
52+
return ScopedBinder<T>(current);
53+
}
54+
55+
// For Visual Studio
56+
Bindable() {
57+
}
58+
Bindable(Bindable&& rhs)
59+
: id(std::move(rhs.id)) {
60+
}
61+
Bindable& operator=(Bindable && rhs) {
62+
id = std::move(rhs.id);
63+
}
64+
};
65+
66+
}

src/VertexAttributeArray.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#pragma once
2+
#include <utility>
3+
#include <stdexcept>
4+
5+
#include "Bindable.hpp"
6+
#include "VertexBuffer.h"
7+
8+
#define GLDR_HAS_DSA
9+
10+
namespace gldr {
11+
12+
enum class VertexAttributeType : GLenum {
13+
Float = gl::FLOAT,
14+
HalfFloat = gl::HALF_FLOAT,
15+
Byte = gl::BYTE,
16+
Short = gl::SHORT,
17+
UShort = gl::UNSIGNED_SHORT,
18+
Int = gl::INT,
19+
UInt = gl::UNSIGNED_INT,
20+
UByte = gl::UNSIGNED_BYTE
21+
};
22+
23+
enum class VertexAttributeIntegerType : GLenum {
24+
Byte = gl::BYTE,
25+
Short = gl::SHORT,
26+
UShort = gl::UNSIGNED_SHORT,
27+
Int = gl::INT,
28+
UInt = gl::UNSIGNED_INT,
29+
UByte = gl::UNSIGNED_BYTE
30+
};
31+
32+
class VertexAttributeArray : public Bindable<VertexAttributeArray> {
33+
34+
public:
35+
// creation and destruction
36+
static GLuint create() {
37+
GLuint id = 0;
38+
gl::GenVertexArrays(1, &id);
39+
if (!id)
40+
throw std::runtime_error("Problem creating a vertex array");
41+
return id;
42+
}
43+
44+
static void destroy(GLuint id) {
45+
gl::DeleteVertexArrays(1, &id);
46+
}
47+
48+
static void bindObject(GLuint id) {
49+
gl::BindVertexArray(id);
50+
}
51+
52+
static GLuint getCurrentlyBound() {
53+
GLint current;
54+
gl::GetIntegerv(gl::VERTEX_ARRAY_BINDING, &current);
55+
return current;
56+
}
57+
58+
void directVertexAttribOffset(unsigned buffer, unsigned index, int size, VertexAttributeType type, bool normalized, unsigned stride, int offset) {
59+
#ifdef GLDR_HAS_DSA
60+
gl::VertexArrayVertexAttribOffsetEXT(id.get(), buffer, index, size, static_cast<GLenum>(type), normalized, stride, offset);
61+
#else
62+
auto vaoScope = scopedBind();
63+
auto vboScope = VertexBuffer<VertexBufferType::ARRAY_BUFFER>::createRebindToCurrent();
64+
65+
gl::BindBuffer(gl::ARRAY_BUFFER, buffer);
66+
gl::VertexAttribPointer(index, size, static_cast<GLenum>(type), normalized, stride, reinterpret_cast<void*>(offset));
67+
#endif
68+
}
69+
70+
void directVertexAttribIntegerOffset(unsigned buffer, unsigned index, int size, VertexAttributeIntegerType type, unsigned stride, int offset) {
71+
#ifdef GLDR_HAS_DSA
72+
gl::VertexArrayVertexAttribIOffsetEXT(id.get(), buffer, index, size, static_cast<GLenum>(type), stride, offset);
73+
#else
74+
auto vaoScope = scopedBind();
75+
auto vboScope = VertexBuffer<VertexBufferType::ARRAY_BUFFER>::createRebindToCurrent();
76+
77+
gl::BindBuffer(gl::ARRAY_BUFFER, buffer);
78+
gl::VertexAttribIPointer(index, size, static_cast<GLenum>(type), stride, reinterpret_cast<void*>(offset));
79+
#endif
80+
}
81+
82+
void VertexAttributeArray::enableAttributeArray(unsigned index) {
83+
#ifdef GLDR_HAS_DSA
84+
gl::EnableVertexArrayAttribEXT(id.get(), index);
85+
#else
86+
auto scope = scopedBind();
87+
gl::EnableVertexAttribArray(index);
88+
#endif
89+
}
90+
91+
// static state queries
92+
// TODO: MAX_VERTEX_ATTRIB_BINDINGS is a part of buffer specification, not VAO?
93+
// Spec 4.3, 10.3.1-10.3.3
94+
// TODO: is this too much of utility?
95+
static unsigned getMaxVertexAttributes() {
96+
GLint count;
97+
gl::GetIntegerv(gl::MAX_VERTEX_ATTRIBS, &count);
98+
return count;
99+
}
100+
};
101+
102+
} // namespace gldr

0 commit comments

Comments
 (0)