| 109 | } |
| 110 | |
| 111 | bool VertexBufferGL33::Init(const Shape& src, VBType type) |
| 112 | { |
| 113 | if (src.NVertex() <= 0) |
| 114 | { |
| 115 | LOG_DEBUG(Graphics, "GL33: Empty vertices."); |
| 116 | return false; |
| 117 | } |
| 118 | |
| 119 | _dynamic = (type == VBDynamic || type == VBSmallDiscardable); |
| 120 | _vertexCount = src.NVertex(); |
| 121 | |
| 122 | // Core profile requires a non-zero VAO bound before any |
| 123 | // GL_ELEMENT_ARRAY_BUFFER bind (the IBO binding is part of VAO state). |
| 124 | // Create + bind the VAO first, then bind buffers inside it. |
| 125 | glGenVertexArrays(1, &_vao); |
| 126 | GL33Bind::Vao(_vao); |
| 127 | |
| 128 | // Create and fill VBO |
| 129 | GLenum vbUsage = _dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; |
| 130 | glGenBuffers(1, &_vbo); |
| 131 | glBindBuffer(GL_ARRAY_BUFFER, _vbo); |
| 132 | glBufferData(GL_ARRAY_BUFFER, _vertexCount * sizeof(SVertex), nullptr, vbUsage); |
| 133 | CopyVertices(src); |
| 134 | |
| 135 | // Count total indices (fan triangulation: N-gon → N-2 triangles) |
| 136 | int indices = 0; |
| 137 | for (Offset o = src.BeginFaces(); o < src.EndFaces(); src.NextFace(o)) |
| 138 | { |
| 139 | const Poly& poly = src.Face(o); |
| 140 | PoseidonAssert(poly.N() >= 3); |
| 141 | indices += (poly.N() - 2) * 3; |
| 142 | } |
| 143 | _indexCount = indices; |
| 144 | |
| 145 | if (indices > 0) |
| 146 | { |
| 147 | // IBO bind goes into the VAO state we just bound above. |
| 148 | glGenBuffers(1, &_ibo); |
| 149 | Poseidon::render::ibo::BindOnActiveVao(_ibo); |
| 150 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * sizeof(VertexIndex), nullptr, GL_STATIC_DRAW); |
| 151 | // IBO is GL_STATIC_DRAW — `MapStaticWriteOnce` is the only |
| 152 | // legal map helper for it. Using `MapDynamicWriteInvalidate` |
| 153 | // here would re-introduce B-028; the helper API doesn't expose |
| 154 | // that combination. |
| 155 | VertexIndex* iData = static_cast<VertexIndex*>(Poseidon::render::buf::MapStaticWriteOnce(GL_ELEMENT_ARRAY_BUFFER)); |
| 156 | if (!iData) |
| 157 | { |
| 158 | LOG_ERROR(Graphics, "GL33: IBO map failed"); |
| 159 | return false; |
| 160 | } |
| 161 | |
| 162 | for (Offset o = src.BeginFaces(); o < src.EndFaces(); src.NextFace(o)) |
| 163 | { |
| 164 | const Poly& poly = src.Face(o); |
| 165 | for (int i = 2; i < poly.N(); i++) |
| 166 | { |
| 167 | *iData++ = poly.GetVertex(0); |
| 168 | *iData++ = poly.GetVertex(i - 1); |
no test coverage detected