1 #include "vertexLayout.h"
2 #include "text.h"
3 #include <sys/types.h>
4 
5 std::map<GLint, GLuint> VertexLayout::s_enabledAttribs = std::map<GLint, GLuint>();
6 
VertexLayout(std::vector<VertexAttrib> _attribs)7 VertexLayout::VertexLayout(std::vector<VertexAttrib> _attribs) : m_attribs(_attribs), m_stride(0), m_positionAttribIndex(-1), m_colorAttribIndex(-1), m_normalAttribIndex(-1), m_texCoordAttribIndex(-1) {
8 
9     m_stride = 0;
10     for (unsigned int i = 0; i < m_attribs.size(); i++) {
11 
12         // Set the offset of this vertex attribute: The stride at this point denotes the number
13         // of bytes into the vertex by which this attribute is offset, but we must cast the number
14         // as a void* to use with glVertexAttribPointer; We use reinterpret_cast to avoid warnings
15         m_attribs[i].offset = reinterpret_cast<void*>(m_stride);
16 
17         GLint byteSize = m_attribs[i].size;
18 
19         switch (m_attribs[i].type) {
20             case GL_FLOAT:
21             case GL_INT:
22             case GL_UNSIGNED_INT:
23                 byteSize *= 4; // 4 bytes for floats, ints, and uints
24                 break;
25             case GL_SHORT:
26             case GL_UNSIGNED_SHORT:
27                 byteSize *= 2; // 2 bytes for shorts and ushorts
28                 break;
29         }
30 
31         if ( m_attribs[i].attrType == POSITION_ATTRIBUTE ){
32             m_positionAttribIndex = i;
33         }
34         else if ( m_attribs[i].attrType == COLOR_ATTRIBUTE ){
35             m_colorAttribIndex = i;
36         }
37         else if ( m_attribs[i].attrType == NORMAL_ATTRIBUTE ){
38             m_normalAttribIndex = i;
39         }
40         else if ( m_attribs[i].attrType == TEXCOORD_ATTRIBUTE ){
41             m_texCoordAttribIndex = i;
42         }
43 
44         m_stride += byteSize;
45 
46         // TODO: Automatically add padding or warn if attributes are not byte-aligned
47     }
48 }
49 
~VertexLayout()50 VertexLayout::~VertexLayout() {
51     m_attribs.clear();
52 }
53 
enable(const Shader * _program)54 void VertexLayout::enable(const Shader* _program) {
55     GLuint glProgram = _program->getProgram();
56 
57     // Enable all attributes for this layout
58     for (unsigned int i = 0; i < m_attribs.size(); i++) {
59         const GLint location = _program->getAttribLocation("a_"+m_attribs[i].name);
60         if (location != -1) {
61             glEnableVertexAttribArray(location);
62             glVertexAttribPointer(location, m_attribs[i].size, m_attribs[i].type, m_attribs[i].normalized, m_stride, m_attribs[i].offset);
63             s_enabledAttribs[location] = glProgram; // Track currently enabled attribs by the program to which they are bound
64         }
65     }
66 
67     // Disable previously bound and now-unneeded attributes
68     for (std::map<GLint, GLuint>::iterator it=s_enabledAttribs.begin(); it!=s_enabledAttribs.end(); ++it){
69         const GLint& location = it->first;
70         GLuint& boundProgram = it->second;
71 
72         if (boundProgram != glProgram && boundProgram != 0) {
73             glDisableVertexAttribArray(location);
74             boundProgram = 0;
75         }
76     }
77 }
78 
getDefaultVertShader()79 std::string VertexLayout::getDefaultVertShader() {
80     std::string rta =
81 "#ifdef GL_ES\n"
82 "precision mediump float;\n"
83 "#endif\n"
84 "\n"
85 "uniform mat4 u_modelViewProjectionMatrix;\n"
86 "uniform mat4 u_modelMatrix;\n"
87 "uniform mat4 u_viewMatrix;\n"
88 "uniform mat4 u_projectionMatrix;\n"
89 "uniform mat4 u_normalMatrix;\n"
90 "\n"
91 "uniform float u_time;\n"
92 "uniform vec2 u_mouse;\n"
93 "uniform vec2 u_resolution;\n"
94 "\n";
95 
96     for (unsigned int i = 0; i < m_attribs.size(); i++) {
97         int size = m_attribs[i].size;
98         if (m_positionAttribIndex == int(i)) {
99             size = 4;
100         }
101         rta += "in vec" + toString(size) + " a_" + m_attribs[i].name + ";\n";
102         rta += "out vec" + toString(size) + " v_" + m_attribs[i].name + ";\n";
103     }
104 
105     rta += "\n"
106 "void main(void) {\n"
107 "\n";
108 
109     for (unsigned int i = 0; i < m_attribs.size(); i++) {
110         rta += "    v_" + m_attribs[i].name + " = a_" + m_attribs[i].name + ";\n";
111     }
112 
113     if (m_positionAttribIndex != -1 && m_positionAttribIndex < int(m_attribs.size())) {
114         rta += "    gl_Position = u_modelViewProjectionMatrix * v_" + m_attribs[m_positionAttribIndex].name + ";\n";
115     }
116 
117     rta +=  "}\n";
118 
119     return rta;
120 }
121 
getDefaultFragShader()122 std::string VertexLayout::getDefaultFragShader() {
123     std::string rta =
124 "#ifdef GL_ES\n"
125 "precision mediump float;\n"
126 "#endif\n"
127 "\n"
128 "uniform mat4 u_modelViewProjectionMatrix;\n"
129 "uniform mat4 u_modelMatrix;\n"
130 "uniform mat4 u_viewMatrix;\n"
131 "uniform mat4 u_projectionMatrix;\n"
132 "uniform mat4 u_normalMatrix;\n"
133 "\n"
134 "uniform float u_time;\n"
135 "uniform vec2 u_mouse;\n"
136 "uniform vec2 u_resolution;\n"
137 "\n";
138 
139     for (unsigned int i = 0; i < m_attribs.size(); i++) {
140         int size = m_attribs[i].size;
141         if (m_positionAttribIndex == int(i)) {
142             size = 4;
143         }
144         rta += "out vec" + toString(size) + " v_" + m_attribs[i].name + ";\n";
145     }
146 
147     rta += "\n"
148 "void main(void) {\n"
149 "\n";
150 
151     if (m_colorAttribIndex != -1) {
152         rta += "    gl_FragColor = v_" + m_attribs[m_colorAttribIndex].name + ";\n";
153     }
154     else if ( m_texCoordAttribIndex != -1 ){
155         rta += "    gl_FragColor = vec4(vec3(v_" + m_attribs[m_texCoordAttribIndex].name + ",1.0),1.0);\n";
156     }
157     else if ( m_normalAttribIndex != -1 ){
158         rta += "    gl_FragColor = vec4(0.5+v_" + m_attribs[m_normalAttribIndex].name + "*0.5,1.0);\n";
159     }
160     else {
161         rta += "    gl_FragColor = vec4(1.0);\n";
162     }
163 
164     rta +=  "}\n";
165 
166     return rta;
167 }
168