Mercurial > hg > orthanc-stone
comparison Framework/Scene2D/Internals/OpenGLLinesProgram.cpp @ 947:1091b2adeb5a toa2019081001
Fixed animation frame stopping when returning false + big work on the OpenGL
objects to make them lost context-safe + debug code to forcefully tag a
context as lost + debug macros
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Sat, 10 Aug 2019 13:07:31 +0200 |
parents | 61ba4b504e9a |
children | a7351ad54960 |
comparison
equal
deleted
inserted
replaced
946:dbe3e1e47019 | 947:1091b2adeb5a |
---|---|
261 const PolylineSceneLayer& layer) : | 261 const PolylineSceneLayer& layer) : |
262 context_(context), | 262 context_(context), |
263 verticesCount_(0), | 263 verticesCount_(0), |
264 thickness_(static_cast<float>(layer.GetThickness())) | 264 thickness_(static_cast<float>(layer.GetThickness())) |
265 { | 265 { |
266 // High-level reference: | 266 if (!context_.IsContextLost()) |
267 // https://mattdesl.svbtle.com/drawing-lines-is-hard | 267 { |
268 // https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader | 268 // High-level reference: |
269 | 269 // https://mattdesl.svbtle.com/drawing-lines-is-hard |
270 size_t countVertices = 0; | 270 // https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader |
271 for (size_t i = 0; i < layer.GetChainsCount(); i++) | 271 |
272 { | 272 size_t countVertices = 0; |
273 size_t countSegments = layer.GetChain(i).size() - 1; | 273 for (size_t i = 0; i < layer.GetChainsCount(); i++) |
274 | 274 { |
275 if (layer.IsClosedChain(i)) | 275 size_t countSegments = layer.GetChain(i).size() - 1; |
276 { | |
277 countSegments++; | |
278 } | |
279 | |
280 // Each segment is made of 2 triangles. One triangle is | |
281 // defined by 3 points in 2D => 6 vertices per segment. | |
282 countVertices += countSegments * 2 * 3; | |
283 } | |
284 | |
285 std::vector<float> coords, colors, miterDirections; | |
286 coords.reserve(countVertices * COMPONENTS_POSITION); | |
287 colors.reserve(countVertices * COMPONENTS_COLOR); | |
288 miterDirections.reserve(countVertices * COMPONENTS_MITER); | |
289 | |
290 for (size_t i = 0; i < layer.GetChainsCount(); i++) | |
291 { | |
292 const PolylineSceneLayer::Chain& chain = layer.GetChain(i); | |
293 | |
294 if (chain.size() > 1) | |
295 { | |
296 std::vector<Segment> segments; | |
297 for (size_t j = 1; j < chain.size(); j++) | |
298 { | |
299 segments.push_back(Segment(chain, j - 1, j)); | |
300 } | |
301 | 276 |
302 if (layer.IsClosedChain(i)) | 277 if (layer.IsClosedChain(i)) |
303 { | 278 { |
304 segments.push_back(Segment(chain, chain.size() - 1, 0)); | 279 countSegments++; |
305 } | 280 } |
306 | 281 |
307 // Try and create nice miters | 282 // Each segment is made of 2 triangles. One triangle is |
308 for (size_t j = 1; j < segments.size(); j++) | 283 // defined by 3 points in 2D => 6 vertices per segment. |
309 { | 284 countVertices += countSegments * 2 * 3; |
310 Segment::CreateMiter(segments[j - 1], segments[j]); | 285 } |
311 } | 286 |
312 | 287 std::vector<float> coords, colors, miterDirections; |
313 if (layer.IsClosedChain(i)) | 288 coords.reserve(countVertices * COMPONENTS_POSITION); |
314 { | 289 colors.reserve(countVertices * COMPONENTS_COLOR); |
315 Segment::CreateMiter(segments.back(), segments.front()); | 290 miterDirections.reserve(countVertices * COMPONENTS_MITER); |
316 } | 291 |
317 | 292 for (size_t i = 0; i < layer.GetChainsCount(); i++) |
318 for (size_t j = 0; j < segments.size(); j++) | 293 { |
319 { | 294 const PolylineSceneLayer::Chain& chain = layer.GetChain(i); |
320 if (!segments[j].IsEmpty()) | 295 |
296 if (chain.size() > 1) | |
297 { | |
298 std::vector<Segment> segments; | |
299 for (size_t j = 1; j < chain.size(); j++) | |
321 { | 300 { |
322 segments[j].AddTriangles(coords, miterDirections, colors, layer.GetColor(i)); | 301 segments.push_back(Segment(chain, j - 1, j)); |
323 } | 302 } |
324 } | 303 |
325 } | 304 if (layer.IsClosedChain(i)) |
326 } | 305 { |
327 | 306 segments.push_back(Segment(chain, chain.size() - 1, 0)); |
328 assert(coords.size() == colors.size()); | 307 } |
329 | 308 |
330 if (!coords.empty()) | 309 // Try and create nice miters |
331 { | 310 for (size_t j = 1; j < segments.size(); j++) |
332 verticesCount_ = coords.size() / COMPONENTS_POSITION; | 311 { |
333 | 312 Segment::CreateMiter(segments[j - 1], segments[j]); |
334 context_.MakeCurrent(); | 313 } |
335 glGenBuffers(3, buffers_); | 314 |
336 | 315 if (layer.IsClosedChain(i)) |
337 glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]); | 316 { |
338 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * coords.size(), &coords[0], GL_STATIC_DRAW); | 317 Segment::CreateMiter(segments.back(), segments.front()); |
339 | 318 } |
340 glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]); | 319 |
341 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * miterDirections.size(), &miterDirections[0], GL_STATIC_DRAW); | 320 for (size_t j = 0; j < segments.size(); j++) |
342 | 321 { |
343 glBindBuffer(GL_ARRAY_BUFFER, buffers_[2]); | 322 if (!segments[j].IsEmpty()) |
344 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size(), &colors[0], GL_STATIC_DRAW); | 323 { |
324 segments[j].AddTriangles(coords, miterDirections, colors, layer.GetColor(i)); | |
325 } | |
326 } | |
327 } | |
328 } | |
329 | |
330 assert(coords.size() == colors.size()); | |
331 | |
332 if (!coords.empty()) | |
333 { | |
334 verticesCount_ = coords.size() / COMPONENTS_POSITION; | |
335 | |
336 context_.MakeCurrent(); | |
337 glGenBuffers(3, buffers_); | |
338 | |
339 glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]); | |
340 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * coords.size(), &coords[0], GL_STATIC_DRAW); | |
341 | |
342 glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]); | |
343 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * miterDirections.size(), &miterDirections[0], GL_STATIC_DRAW); | |
344 | |
345 glBindBuffer(GL_ARRAY_BUFFER, buffers_[2]); | |
346 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size(), &colors[0], GL_STATIC_DRAW); | |
347 } | |
345 } | 348 } |
346 } | 349 } |
347 | 350 |
348 | 351 |
349 OpenGLLinesProgram::Data::~Data() | 352 OpenGLLinesProgram::Data::~Data() |
350 { | 353 { |
351 if (!IsEmpty()) | 354 if (!context_.IsContextLost() && !IsEmpty()) |
352 { | 355 { |
353 context_.MakeCurrent(); | 356 context_.MakeCurrent(); |
357 ORTHANC_OPENGL_TRACE_CURRENT_CONTEXT("About to call glDeleteBuffers"); | |
354 glDeleteBuffers(3, buffers_); | 358 glDeleteBuffers(3, buffers_); |
355 } | 359 } |
356 } | 360 } |
357 | |
358 | 361 |
359 GLuint OpenGLLinesProgram::Data::GetVerticesBuffer() const | 362 GLuint OpenGLLinesProgram::Data::GetVerticesBuffer() const |
360 { | 363 { |
361 if (IsEmpty()) | 364 if (IsEmpty()) |
362 { | 365 { |
396 | 399 |
397 | 400 |
398 OpenGLLinesProgram::OpenGLLinesProgram(OpenGL::IOpenGLContext& context) : | 401 OpenGLLinesProgram::OpenGLLinesProgram(OpenGL::IOpenGLContext& context) : |
399 context_(context) | 402 context_(context) |
400 { | 403 { |
401 context_.MakeCurrent(); | 404 if (!context_.IsContextLost()) |
402 | 405 { |
403 program_.reset(new OpenGL::OpenGLProgram); | 406 context_.MakeCurrent(); |
404 program_->CompileShaders(VERTEX_SHADER, FRAGMENT_SHADER); | 407 program_.reset(new OpenGL::OpenGLProgram(context_)); |
405 } | 408 program_->CompileShaders(VERTEX_SHADER, FRAGMENT_SHADER); |
406 | 409 } |
410 } | |
407 | 411 |
408 void OpenGLLinesProgram::Apply(const Data& data, | 412 void OpenGLLinesProgram::Apply(const Data& data, |
409 const AffineTransform2D& transform, | 413 const AffineTransform2D& transform, |
410 bool antialiasing, | 414 bool antialiasing, |
411 bool scaleIndependantThickness) | 415 bool scaleIndependantThickness) |
412 { | 416 { |
413 if (!data.IsEmpty()) | 417 if (!context_.IsContextLost() && !data.IsEmpty()) |
414 { | 418 { |
415 context_.MakeCurrent(); | 419 context_.MakeCurrent(); |
416 program_->Use(); | 420 program_->Use(); |
417 | 421 |
418 GLint locationPosition = program_->GetAttributeLocation("a_position"); | 422 GLint locationPosition = program_->GetAttributeLocation("a_position"); |