{\r
namespace video\r
{\r
+ struct VertexAttribute {\r
+ enum class Mode {\r
+ Regular,\r
+ Normalized,\r
+ Integral,\r
+ };\r
+ int Index;\r
+ int ComponentCount;\r
+ GLenum ComponentType;\r
+ Mode mode;\r
+ int Offset;\r
+ };\r
+\r
+ struct VertexType {\r
+ int VertexSize;\r
+ int AttributeCount;\r
+ VertexAttribute Attributes[];\r
+\r
+ VertexType(const VertexType &) = delete;\r
+ VertexType &operator= (const VertexType &) = delete;\r
+ };\r
+\r
+ static const VertexAttribute *begin(const VertexType &type)\r
+ {\r
+ return type.Attributes;\r
+ }\r
+\r
+ static const VertexAttribute *end(const VertexType &type)\r
+ {\r
+ return type.Attributes + type.AttributeCount;\r
+ }\r
+\r
+ static constexpr VertexType vtStandard = {\r
+ sizeof(S3DVertex), 4, {\r
+ {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Pos)},\r
+ {EVA_NORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Normal)},\r
+ {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex, Color)},\r
+ {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, TCoords)},\r
+ },\r
+ };\r
+\r
+#pragma GCC diagnostic push\r
+#pragma GCC diagnostic ignored "-Winvalid-offsetof"\r
+\r
+ static constexpr VertexType vt2TCoords = {\r
+ sizeof(S3DVertex2TCoords), 5, {\r
+ {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, Pos)},\r
+ {EVA_NORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, Normal)},\r
+ {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex2TCoords, Color)},\r
+ {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, TCoords)},\r
+ {EVA_TCOORD1, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, TCoords2)},\r
+ },\r
+ };\r
+\r
+ static constexpr VertexType vtTangents = {\r
+ sizeof(S3DVertexTangents), 6, {\r
+ {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Pos)},\r
+ {EVA_NORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Normal)},\r
+ {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertexTangents, Color)},\r
+ {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, TCoords)},\r
+ {EVA_TANGENT, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Tangent)},\r
+ {EVA_BINORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Binormal)},\r
+ },\r
+ };\r
+\r
+#pragma GCC diagnostic pop\r
+\r
+ static const VertexType &getVertexTypeDescription(E_VERTEX_TYPE type)\r
+ {\r
+ switch (type) {\r
+ case EVT_STANDARD: return vtStandard;\r
+ case EVT_2TCOORDS: return vt2TCoords;\r
+ case EVT_TANGENTS: return vtTangents;\r
+ default: assert(false);\r
+ }\r
+ }\r
+\r
+ static constexpr VertexType vt2DImage = {\r
+ sizeof(S3DVertex), 3, {\r
+ {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Pos)},\r
+ {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex, Color)},\r
+ {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, TCoords)},\r
+ },\r
+ };\r
+\r
+ static constexpr VertexType vtPrimitive = {\r
+ sizeof(S3DVertex), 2, {\r
+ {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Pos)},\r
+ {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex, Color)},\r
+ },\r
+ };\r
+\r
\r
void APIENTRY COpenGL3Driver::debugCb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)\r
{\r
\r
setRenderStates3DMode();\r
\r
- glEnableVertexAttribArray(EVA_POSITION);\r
- glEnableVertexAttribArray(EVA_COLOR);\r
- glEnableVertexAttribArray(EVA_NORMAL);\r
- glEnableVertexAttribArray(EVA_TCOORD0);\r
-\r
- switch (vType)\r
- {\r
- case EVT_STANDARD:\r
- if (vertices)\r
- {\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Normal);\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);\r
- }\r
- else\r
- {\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), 0);\r
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex), buffer_offset(12));\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), buffer_offset(24));\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), buffer_offset(28));\r
- }\r
-\r
- break;\r
- case EVT_2TCOORDS:\r
- glEnableVertexAttribArray(EVA_TCOORD1);\r
-\r
- if (vertices)\r
- {\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Pos);\r
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Normal);\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Color);\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords);\r
- glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords2);\r
- }\r
- else\r
- {\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(0));\r
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(12));\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex2TCoords), buffer_offset(24));\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(28));\r
- glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(36));\r
- }\r
- break;\r
- case EVT_TANGENTS:\r
- glEnableVertexAttribArray(EVA_TANGENT);\r
- glEnableVertexAttribArray(EVA_BINORMAL);\r
-\r
- if (vertices)\r
- {\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos);\r
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Normal);\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color);\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords);\r
- glVertexAttribPointer(EVA_TANGENT, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Tangent);\r
- glVertexAttribPointer(EVA_BINORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Binormal);\r
- }\r
- else\r
- {\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(0));\r
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(12));\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertexTangents), buffer_offset(24));\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(28));\r
- glVertexAttribPointer(EVA_TANGENT, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(36));\r
- glVertexAttribPointer(EVA_BINORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(48));\r
- }\r
- break;\r
- }\r
-\r
+ auto &vTypeDesc = getVertexTypeDescription(vType);\r
+ beginDraw(vTypeDesc, reinterpret_cast<uintptr_t>(vertices));\r
GLenum indexSize = 0;\r
\r
switch (iType)\r
break;\r
}\r
\r
- switch (vType)\r
- {\r
- case EVT_2TCOORDS:\r
- glDisableVertexAttribArray(EVA_TCOORD1);\r
- break;\r
- case EVT_TANGENTS:\r
- glDisableVertexAttribArray(EVA_TANGENT);\r
- glDisableVertexAttribArray(EVA_BINORMAL);\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- glDisableVertexAttribArray(EVA_POSITION);\r
- glDisableVertexAttribArray(EVA_NORMAL);\r
- glDisableVertexAttribArray(EVA_COLOR);\r
- glDisableVertexAttribArray(EVA_TCOORD0);\r
+ endDraw(vTypeDesc);\r
}\r
\r
\r
vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
\r
- drawQuad(vertices, true);\r
+ drawQuad(vt2DImage, vertices);\r
\r
if (clipRect)\r
glDisable(GL_SCISSOR_TEST);\r
quad2DVertices[2].Color = SColor(0xFFFFFFFF);\r
quad2DVertices[3].Color = SColor(0xFFFFFFFF);\r
\r
- drawQuad(quad2DVertices, true);\r
+ drawQuad(vt2DImage, quad2DVertices);\r
}\r
\r
void COpenGL3Driver::draw2DImageBatch(const video::ITexture* texture,\r
}\r
\r
const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());\r
+ assert(6 * std::size_t(drawCount) <= QuadsIndices.size());\r
\r
core::array<S3DVertex> vtx(drawCount * 4);\r
\r
tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));\r
}\r
\r
- drawQuads(vtx.const_pointer(), drawCount, true);\r
+ drawElements(GL_TRIANGLES, vt2DImage, vtx.const_pointer(), QuadsIndices.data(), 6 * drawCount);\r
\r
if (clipRect)\r
glDisable(GL_SCISSOR_TEST);\r
vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, 0, 0);\r
vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, 0, 0);\r
\r
- drawQuad(vertices, false);\r
+ drawQuad(vtPrimitive, vertices);\r
}\r
\r
\r
vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, colorRightDown, 0, 0);\r
vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, colorLeftDown, 0, 0);\r
\r
- drawQuad(vertices, false);\r
+ drawQuad(vtPrimitive, vertices);\r
}\r
\r
\r
vertices[0] = S3DVertex(startX, startY, 0, 0, 0, 1, color, 0, 0);\r
vertices[1] = S3DVertex(endX, endY, 0, 0, 0, 1, color, 1, 1);\r
\r
- drawArrays(GL_LINES, vertices, 2, false);\r
+ drawArrays(GL_LINES, vtPrimitive, vertices, 2);\r
}\r
}\r
\r
S3DVertex vertices[1];\r
vertices[0] = S3DVertex(X, Y, 0, 0, 0, 1, color, 0, 0);\r
\r
- drawArrays(GL_POINTS, vertices, 1, false);\r
+ drawArrays(GL_POINTS, vtPrimitive, vertices, 1);\r
}\r
\r
- void COpenGL3Driver::drawQuads(const S3DVertex *vertices, int quad_count, bool textured)\r
+ void COpenGL3Driver::drawQuad(const VertexType &vertexType, const S3DVertex (&vertices)[4])\r
{\r
- assert(6 * std::size_t(quad_count) <= QuadsIndices.size());\r
- glEnableVertexAttribArray(EVA_POSITION);\r
- glEnableVertexAttribArray(EVA_COLOR);\r
- if (textured)\r
- glEnableVertexAttribArray(EVA_TCOORD0);\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);\r
- glDrawElements(GL_TRIANGLES, 6 * quad_count, GL_UNSIGNED_SHORT, QuadsIndices.data());\r
- glDisableVertexAttribArray(EVA_TCOORD0);\r
- glDisableVertexAttribArray(EVA_COLOR);\r
- glDisableVertexAttribArray(EVA_POSITION);\r
+ drawArrays(GL_TRIANGLE_FAN, vertexType, vertices, 4);\r
}\r
\r
- void COpenGL3Driver::drawArrays(GLenum type, const S3DVertex *vertices, int vertex_count, bool textured)\r
+ void COpenGL3Driver::drawArrays(GLenum primitiveType, const VertexType &vertexType, const void *vertices, int vertexCount)\r
{\r
- glEnableVertexAttribArray(EVA_POSITION);\r
- glEnableVertexAttribArray(EVA_COLOR);\r
- if (textured)\r
- glEnableVertexAttribArray(EVA_TCOORD0);\r
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);\r
- glDrawArrays(type, 0, vertex_count);\r
- glDisableVertexAttribArray(EVA_TCOORD0);\r
- glDisableVertexAttribArray(EVA_COLOR);\r
- glDisableVertexAttribArray(EVA_POSITION);\r
+ beginDraw(vertexType, reinterpret_cast<uintptr_t>(vertices));\r
+ glDrawArrays(primitiveType, 0, vertexCount);\r
+ endDraw(vertexType);\r
+ }\r
+\r
+ void COpenGL3Driver::drawElements(GLenum primitiveType, const VertexType &vertexType, const void *vertices, const u16 *indices, int indexCount)\r
+ {\r
+ beginDraw(vertexType, reinterpret_cast<uintptr_t>(vertices));\r
+ glDrawElements(primitiveType, indexCount, GL_UNSIGNED_SHORT, indices);\r
+ endDraw(vertexType);\r
+ }\r
+\r
+ void COpenGL3Driver::beginDraw(const VertexType &vertexType, uintptr_t verticesBase)\r
+ {\r
+ for (auto attr: vertexType) {\r
+ glEnableVertexAttribArray(attr.Index);\r
+ switch (attr.mode) {\r
+ case VertexAttribute::Mode::Regular: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_FALSE, vertexType.VertexSize, reinterpret_cast<void *>(verticesBase + attr.Offset)); break;\r
+ case VertexAttribute::Mode::Normalized: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_TRUE, vertexType.VertexSize, reinterpret_cast<void *>(verticesBase + attr.Offset)); break;\r
+ case VertexAttribute::Mode::Integral: glVertexAttribIPointer(attr.Index, attr.ComponentCount, attr.ComponentType, vertexType.VertexSize, reinterpret_cast<void *>(verticesBase + attr.Offset)); break;\r
+ }\r
+ }\r
}\r
\r
- void COpenGL3Driver::drawQuad(const S3DVertex (&vertices)[4], bool textured)\r
+ void COpenGL3Driver::endDraw(const VertexType &vertexType)\r
{\r
- drawQuads(vertices, 1, textured);\r
+ for (auto attr: vertexType)\r
+ glDisableVertexAttribArray(attr.Index);\r
}\r
\r
ITexture* COpenGL3Driver::createDeviceDependentTexture(const io::path& name, IImage* image)\r
vertices[0] = S3DVertex(start.X, start.Y, start.Z, 0, 0, 1, color, 0, 0);\r
vertices[1] = S3DVertex(end.X, end.Y, end.Z, 0, 0, 1, color, 0, 0);\r
\r
- drawArrays(GL_LINES, vertices, 2, false);\r
+ drawArrays(GL_LINES, vtPrimitive, vertices, 2);\r
}\r
\r
\r