Skip to content

Commit c695bde

Browse files
committed
Replace deprecated GL client arrays with VAO + glVertexAttribPointer
1 parent 6ec63e9 commit c695bde

9 files changed

Lines changed: 102 additions & 48 deletions

File tree

src/fea/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@ qt_add_executable(fea
6565
src/gl_element_group.cpp
6666
src/gl_entity.cpp
6767
src/gl_entity_list.cpp
68+
src/gl_list.cpp
6869
src/gl_functions.cpp
6970
src/gl_frustum.cpp
7071
src/gl_shader_program.cpp
7172
src/gl_grid.cpp
7273
src/gl_interpolated_element.cpp
7374
src/gl_interpolated_entity.cpp
7475
src/gl_line.cpp
75-
src/gl_list.cpp
7676
src/gl_model_list.cpp
7777
src/gl_node.cpp
7878
src/gl_object.cpp
@@ -244,12 +244,12 @@ qt_add_executable(fea
244244
src/gl_element_group.h
245245
src/gl_entity.h
246246
src/gl_entity_list.h
247+
src/gl_list.h
247248
src/gl_functions.h
248249
src/gl_grid.h
249250
src/gl_interpolated_element.h
250251
src/gl_interpolated_entity.h
251252
src/gl_line.h
252-
src/gl_list.h
253253
src/gl_model_list.h
254254
src/gl_node.h
255255
src/gl_object.h

src/fea/src/gl_element_group.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,12 +398,10 @@ void GLElementGroup::draw()
398398
{
399399
if (pGlEntityList->getUseVBO())
400400
{
401-
// Render VBO
402401
pGlEntityList->getVBO(GL_ENTITY_LIST_ITEM_NORMAL).render();
403402
}
404403
else
405404
{
406-
// Render display list
407405
pGlEntityList->callList(GL_ENTITY_LIST_ITEM_NORMAL);
408406
}
409407
}

src/fea/src/gl_shader_program.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ bool GLShaderProgram::load(const QString &vertexPath, const QString &fragmentPat
2929
return false;
3030
}
3131

32+
// Bind standard vertex attribute locations before linking.
33+
// These match the glVertexAttribPointer calls in GLVertexBuffer::uploadToGPU().
34+
// GLSL 1.30 does not support layout(location=N), so explicit binding is required.
35+
this->program.bindAttributeLocation("aPosition", 0);
36+
this->program.bindAttributeLocation("aNormal", 1);
37+
this->program.bindAttributeLocation("aColor", 2);
38+
this->program.bindAttributeLocation("aTexCoord", 3);
39+
3240
if (!this->program.link())
3341
{
3442
RLogger::error("GLShaderProgram: link failed: %s\n",

src/fea/src/gl_state_cache.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ void GLStateCache::setTexture1D(GLboolean enabled)
134134
this->texture1D = enabled;
135135
GL_SAFE_CALL(enabled ? glEnable(GL_TEXTURE_1D) : glDisable(GL_TEXTURE_1D));
136136
}
137+
// Keep the shader uniform in sync (mirrors setLighting() pattern).
138+
// Guard against VBO recording: during recording the enable/disable is per-element
139+
// and the uniform is a single value for the whole draw call, so skip the sync
140+
// and let the caller set uUseTexture explicitly before VBO.render().
141+
if (this->shaderProgram && !GLFunctions::isRecordingVBO())
142+
{
143+
this->shaderProgram->setUniformBool("uUseTexture", enabled == GL_TRUE);
144+
}
137145
}
138146

139147
void GLStateCache::setTexture2D(GLboolean enabled)

src/fea/src/gl_vertex_buffer.cpp

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#include <cstddef>
22

3+
#ifdef __APPLE__
4+
#define GL_SILENCE_DEPRECATION
5+
#endif
6+
7+
#include <QOpenGLExtraFunctions>
38
#include <QOpenGLFunctions>
49
#include <QOpenGLContext>
510

@@ -11,6 +16,7 @@
1116
void GLVertexBuffer::_init(const GLVertexBuffer *pBuffer)
1217
{
1318
this->vboId = 0;
19+
this->vaoId = 0;
1420
this->vertexCount = 0;
1521
this->valid = false;
1622
this->recording = false;
@@ -110,6 +116,7 @@ void GLVertexBuffer::uploadToGPU()
110116

111117
QOpenGLContext *ctx = QOpenGLContext::currentContext();
112118
QOpenGLFunctions *f = ctx->functions();
119+
QOpenGLExtraFunctions *ef = ctx->extraFunctions();
113120

114121
// Generate VBO if needed (reuse existing handle if present).
115122
if (this->vboId == 0)
@@ -123,6 +130,36 @@ void GLVertexBuffer::uploadToGPU()
123130
GLsizeiptr(this->vertices.size() * sizeof(GLVertexData)),
124131
this->vertices.data(),
125132
GL_STATIC_DRAW));
133+
134+
// Create the VAO (or recreate it after a reset) and record the attribute layout
135+
// while the VBO is still bound so the VAO captures the binding.
136+
if (this->vaoId == 0)
137+
{
138+
GL_SAFE_CALL(ef->glGenVertexArrays(1, &this->vaoId));
139+
}
140+
GL_SAFE_CALL(ef->glBindVertexArray(this->vaoId));
141+
142+
// aPosition — location 0
143+
GL_SAFE_CALL(f->glEnableVertexAttribArray(0));
144+
GL_SAFE_CALL(f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLVertexData),
145+
reinterpret_cast<const void*>(offsetof(GLVertexData, position))));
146+
147+
// aNormal — location 1
148+
GL_SAFE_CALL(f->glEnableVertexAttribArray(1));
149+
GL_SAFE_CALL(f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLVertexData),
150+
reinterpret_cast<const void*>(offsetof(GLVertexData, normal))));
151+
152+
// aColor — location 2 (UNSIGNED_BYTE normalised to [0,1] in shader)
153+
GL_SAFE_CALL(f->glEnableVertexAttribArray(2));
154+
GL_SAFE_CALL(f->glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GLVertexData),
155+
reinterpret_cast<const void*>(offsetof(GLVertexData, color))));
156+
157+
// aTexCoord — location 3
158+
GL_SAFE_CALL(f->glEnableVertexAttribArray(3));
159+
GL_SAFE_CALL(f->glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(GLVertexData),
160+
reinterpret_cast<const void*>(offsetof(GLVertexData, texCoord))));
161+
162+
GL_SAFE_CALL(ef->glBindVertexArray(0));
126163
GL_SAFE_CALL(f->glBindBuffer(GL_ARRAY_BUFFER, 0));
127164

128165
this->vertexCount = GLsizei(this->vertices.size());
@@ -178,43 +215,23 @@ void GLVertexBuffer::addVertex(GLfloat x, GLfloat y, GLfloat z)
178215

179216
void GLVertexBuffer::render() const
180217
{
181-
if (!this->valid || this->vboId == 0 || this->batches.empty())
218+
if (!this->valid || this->vaoId == 0 || this->batches.empty())
182219
{
183220
return;
184221
}
185222

186-
QOpenGLContext *ctx = QOpenGLContext::currentContext();
187-
QOpenGLFunctions *f = ctx->functions();
188-
189-
// Bind VBO — with a VBO bound, the pointer offsets below are byte offsets
190-
// from the start of the buffer (fixed-function VBO path, OpenGL 1.5+).
191-
f->glBindBuffer(GL_ARRAY_BUFFER, this->vboId);
223+
// The VAO already encapsulates the VBO binding and all attribute pointers
224+
// recorded in uploadToGPU(). Just bind it and draw.
225+
QOpenGLExtraFunctions *ef = QOpenGLContext::currentContext()->extraFunctions();
192226

193-
glEnableClientState(GL_VERTEX_ARRAY);
194-
glEnableClientState(GL_NORMAL_ARRAY);
195-
glEnableClientState(GL_COLOR_ARRAY);
196-
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
197-
198-
glVertexPointer(3, GL_FLOAT, sizeof(GLVertexData),
199-
reinterpret_cast<const void*>(offsetof(GLVertexData, position)));
200-
glNormalPointer(GL_FLOAT, sizeof(GLVertexData),
201-
reinterpret_cast<const void*>(offsetof(GLVertexData, normal)));
202-
glTexCoordPointer(1, GL_FLOAT, sizeof(GLVertexData),
203-
reinterpret_cast<const void*>(offsetof(GLVertexData, texCoord)));
204-
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GLVertexData),
205-
reinterpret_cast<const void*>(offsetof(GLVertexData, color)));
227+
GL_SAFE_CALL(ef->glBindVertexArray(this->vaoId));
206228

207229
for (const Batch &batch : this->batches)
208230
{
209231
glDrawArrays(batch.primitiveType, batch.start, batch.count);
210232
}
211233

212-
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
213-
glDisableClientState(GL_COLOR_ARRAY);
214-
glDisableClientState(GL_NORMAL_ARRAY);
215-
glDisableClientState(GL_VERTEX_ARRAY);
216-
217-
f->glBindBuffer(GL_ARRAY_BUFFER, 0);
234+
GL_SAFE_CALL(ef->glBindVertexArray(0));
218235
}
219236

220237
void GLVertexBuffer::release()
@@ -223,6 +240,12 @@ void GLVertexBuffer::release()
223240
if (ctx)
224241
{
225242
QOpenGLFunctions *f = ctx->functions();
243+
QOpenGLExtraFunctions *ef = ctx->extraFunctions();
244+
if (this->vaoId != 0)
245+
{
246+
GL_SAFE_CALL(ef->glDeleteVertexArrays(1, &this->vaoId));
247+
this->vaoId = 0;
248+
}
226249
if (this->vboId != 0)
227250
{
228251
GL_SAFE_CALL(f->glDeleteBuffers(1, &this->vboId));

src/fea/src/gl_vertex_buffer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class GLVertexBuffer
5151

5252
//! VBO handle for vertex data.
5353
GLuint vboId;
54+
//! VAO that records the attribute layout (created once in uploadToGPU).
55+
GLuint vaoId;
5456
//! Total uploaded vertex count (valid after uploadToGPU).
5557
GLsizei vertexCount;
5658
//! Whether the VBO is valid and ready for rendering.

src/fea/src/gl_widget.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,6 @@ void GLWidget::drawModel()
291291

292292
GL_SAFE_CALL(glClear(GL_DEPTH_BUFFER_BIT));
293293

294-
if (this->clippingPlaneEnabled)
295-
{
296-
RLogger::trace("Clipping plane\n");
297-
const GLdouble clippingPlane[4] = { 0.0, 0.0, -1.0, - GLdouble(this->scale) + 2.0 * this->clippingPlaneDistance * GLdouble(this->scale) };
298-
GL_SAFE_CALL(glClipPlane(GL_CLIP_PLANE0,clippingPlane));
299-
}
300-
301294
// Only update lights when they change (cached lighting setup)
302295
GL_SAFE_CALL(glEnable(GL_LIGHTING));
303296
if (this->lightsNeedUpdate || this->cachedNLights != this->displayProperties.getNLights())
@@ -413,6 +406,12 @@ void GLWidget::drawModel()
413406
this->mainShaderProgram.setUniformBool("uUseLighting", true);
414407
this->mainShaderProgram.setUniformBool("uUseTexture", false);
415408
this->mainShaderProgram.setUniformInt("uColorMap", 0);
409+
410+
// Upload clip plane — replaces glClipPlane(GL_CLIP_PLANE0, ...).
411+
QVector4D clipPlane(0.0f, 0.0f, -1.0f,
412+
float(-this->scale + 2.0 * this->clippingPlaneDistance * this->scale));
413+
this->mainShaderProgram.setUniformBool("uClipEnabled", this->clippingPlaneEnabled);
414+
this->mainShaderProgram.setUniformVector4D("uClipPlane", clipPlane);
416415
}
417416

418417
if (Application::instance()->getSession()->getModel(this->getModelID()).glDrawTrylock())
@@ -2139,7 +2138,8 @@ void GLWidget::qglColor(const QColor &color)
21392138
{
21402139
R_LOG_TRACE_IN;
21412140
this->currentGLColor = color;
2142-
GL_SAFE_CALL(glColor4d(color.redF(),color.greenF(),color.blueF(),color.alphaF()));
2141+
// Route through GLFunctions so the colour is captured during VBO recording.
2142+
GLFunctions::color4ub(GLubyte(color.red()), GLubyte(color.green()), GLubyte(color.blue()), GLubyte(color.alpha()));
21432143
R_LOG_TRACE_OUT;
21442144
}
21452145

src/fea/src/shaders/flat.vert

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@
44
uniform mat4 uProjection;
55
uniform mat4 uModelView;
66

7+
// Vertex attributes — fed by glVertexAttribPointer (replaces deprecated client arrays).
8+
in vec3 aPosition; // layout location 0
9+
in vec4 aColor; // layout location 2 — UNSIGNED_BYTE normalised to [0,1]
10+
in float aTexCoord; // layout location 3
11+
712
out vec4 vColor;
813
out float vTexCoord;
914

1015
void main()
1116
{
12-
gl_Position = uProjection * uModelView * gl_Vertex;
13-
vColor = gl_Color;
14-
vTexCoord = gl_MultiTexCoord0.s;
17+
gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
18+
vColor = aColor;
19+
vTexCoord = aTexCoord;
1520
}

src/fea/src/shaders/main.vert

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@
55
uniform mat4 uProjection;
66
uniform mat4 uModelView;
77

8+
// Clip plane — replaces deprecated glClipPlane() / GL_CLIP_PLANE0.
9+
uniform vec4 uClipPlane; // Eye-space clip plane equation (xyz=normal, w=offset).
10+
uniform bool uClipEnabled; // Whether clipping is active.
11+
12+
// Vertex attributes — fed by glVertexAttribPointer (replaces deprecated client arrays).
13+
in vec3 aPosition; // layout location 0
14+
in vec3 aNormal; // layout location 1
15+
in vec4 aColor; // layout location 2 — UNSIGNED_BYTE normalised to [0,1]
16+
in float aTexCoord; // layout location 3
17+
818
// Per-fragment outputs
919
out vec4 vColor;
1020
out vec3 vNormal;
@@ -13,14 +23,14 @@ out float vTexCoord;
1323

1424
void main()
1525
{
16-
// gl_Vertex / gl_Normal / gl_Color / gl_MultiTexCoord0 are the legacy
17-
// built-in attribute aliases fed by glVertexPointer / glNormalPointer /
18-
// glColorPointer / glTexCoordPointer (OpenGL compatibility profile).
19-
vec4 worldPos = uModelView * gl_Vertex;
26+
vec4 worldPos = uModelView * vec4(aPosition, 1.0);
2027
gl_Position = uProjection * worldPos;
2128

29+
// Write clip distance — positive = inside, negative = clipped.
30+
gl_ClipDistance[0] = uClipEnabled ? dot(worldPos, uClipPlane) : 1.0;
31+
2232
vFragPos = worldPos.xyz;
23-
vNormal = mat3(transpose(inverse(mat3(uModelView)))) * gl_Normal;
24-
vColor = gl_Color;
25-
vTexCoord = gl_MultiTexCoord0.s;
33+
vNormal = mat3(transpose(inverse(mat3(uModelView)))) * aNormal;
34+
vColor = aColor;
35+
vTexCoord = aTexCoord;
2636
}

0 commit comments

Comments
 (0)