comparison Framework/Scene2D/Internals/OpenGLLinesProgram.cpp @ 804:61ba4b504e9a

PolylineSceneLayer now has one color per chain
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 28 May 2019 15:58:21 +0200
parents c0a5eb9a4290
children 1091b2adeb5a
comparison
equal deleted inserted replaced
802:f38c1fc08655 804:61ba4b504e9a
24 24
25 #include <Core/OrthancException.h> 25 #include <Core/OrthancException.h>
26 26
27 27
28 static const unsigned int COMPONENTS_POSITION = 3; 28 static const unsigned int COMPONENTS_POSITION = 3;
29 static const unsigned int COMPONENTS_COLOR = 3;
29 static const unsigned int COMPONENTS_MITER = 2; 30 static const unsigned int COMPONENTS_MITER = 2;
30 31
31 32
32 static const char* VERTEX_SHADER = 33 static const char* VERTEX_SHADER =
33 ORTHANC_STONE_OPENGL_SHADER_VERSION_DIRECTIVE 34 ORTHANC_STONE_OPENGL_SHADER_VERSION_DIRECTIVE
34 "attribute vec2 a_miter_direction; \n" 35 "attribute vec2 a_miter_direction; \n"
35 "attribute vec4 a_position; \n" 36 "attribute vec4 a_position; \n"
37 "attribute vec3 a_color; \n"
36 "uniform float u_thickness; \n" 38 "uniform float u_thickness; \n"
37 "uniform mat4 u_matrix; \n" 39 "uniform mat4 u_matrix; \n"
38 "varying float v_distance; \n" 40 "varying float v_distance; \n"
41 "varying vec3 v_color; \n"
39 "void main() \n" 42 "void main() \n"
40 "{ \n" 43 "{ \n"
41 " v_distance = a_position.z; \n" 44 " v_distance = a_position.z; \n"
45 " v_color = a_color; \n"
42 " gl_Position = u_matrix * vec4(a_position.xy + a_position.z * a_miter_direction * u_thickness, 0, 1); \n" 46 " gl_Position = u_matrix * vec4(a_position.xy + a_position.z * a_miter_direction * u_thickness, 0, 1); \n"
43 "}"; 47 "}";
44 48
45 49
46 static const char* FRAGMENT_SHADER = 50 static const char* FRAGMENT_SHADER =
47 ORTHANC_STONE_OPENGL_SHADER_VERSION_DIRECTIVE 51 ORTHANC_STONE_OPENGL_SHADER_VERSION_DIRECTIVE
48 "uniform bool u_antialiasing; \n" 52 "uniform bool u_antialiasing; \n"
49 "uniform float u_antialiasing_start; \n" 53 "uniform float u_antialiasing_start; \n"
50 "uniform vec3 u_color; \n"
51 "varying float v_distance; \n" // Distance of the point to the segment 54 "varying float v_distance; \n" // Distance of the point to the segment
55 "varying vec3 v_color; \n"
52 "void main() \n" 56 "void main() \n"
53 "{ \n" 57 "{ \n"
54 " float d = abs(v_distance); \n" 58 " float d = abs(v_distance); \n"
55 " if (!u_antialiasing || \n" 59 " if (!u_antialiasing || \n"
56 " d <= u_antialiasing_start) \n" 60 " d <= u_antialiasing_start) \n"
57 " gl_FragColor = vec4(u_color, 1); \n" 61 " gl_FragColor = vec4(v_color, 1); \n"
58 " else if (d >= 1.0) \n" 62 " else if (d >= 1.0) \n"
59 " gl_FragColor = vec4(0, 0, 0, 0); \n" 63 " gl_FragColor = vec4(0, 0, 0, 0); \n"
60 " else \n" 64 " else \n"
61 " { \n" 65 " { \n"
62 " float alpha = 1.0 - smoothstep(u_antialiasing_start, 1.0, d); \n" 66 " float alpha = 1.0 - smoothstep(u_antialiasing_start, 1.0, d); \n"
63 " gl_FragColor = vec4(u_color * alpha, alpha); \n" 67 " gl_FragColor = vec4(v_color * alpha, alpha); \n"
64 " } \n" 68 " } \n"
65 "}"; 69 "}";
66 70
67 71
68 namespace OrthancStone 72 namespace OrthancStone
195 } 199 }
196 } 200 }
197 } 201 }
198 202
199 void AddTriangles(std::vector<float>& coords, 203 void AddTriangles(std::vector<float>& coords,
200 std::vector<float>& miterDirections) 204 std::vector<float>& miterDirections,
205 std::vector<float>& colors,
206 const Color& color)
201 { 207 {
202 if (isEmpty_) 208 if (isEmpty_)
203 { 209 {
204 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 210 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
205 } 211 }
237 miterDirections.push_back(static_cast<float>(miterY1_)); 243 miterDirections.push_back(static_cast<float>(miterY1_));
238 miterDirections.push_back(static_cast<float>(miterX1_)); 244 miterDirections.push_back(static_cast<float>(miterX1_));
239 miterDirections.push_back(static_cast<float>(miterY1_)); 245 miterDirections.push_back(static_cast<float>(miterY1_));
240 miterDirections.push_back(static_cast<float>(miterX2_)); 246 miterDirections.push_back(static_cast<float>(miterX2_));
241 miterDirections.push_back(static_cast<float>(miterY2_)); 247 miterDirections.push_back(static_cast<float>(miterY2_));
248
249 // Add the colors of the 2 triangles (leading to 2 * 3 values)
250 for (unsigned int i = 0; i < 6; i++)
251 {
252 colors.push_back(color.GetRedAsFloat());
253 colors.push_back(color.GetGreenAsFloat());
254 colors.push_back(color.GetBlueAsFloat());
255 }
242 } 256 }
243 }; 257 };
244 258
245 259
246 OpenGLLinesProgram::Data::Data(OpenGL::IOpenGLContext& context, 260 OpenGLLinesProgram::Data::Data(OpenGL::IOpenGLContext& context,
247 const PolylineSceneLayer& layer) : 261 const PolylineSceneLayer& layer) :
248 context_(context), 262 context_(context),
249 verticesCount_(0), 263 verticesCount_(0),
250 thickness_(static_cast<float>(layer.GetThickness())), 264 thickness_(static_cast<float>(layer.GetThickness()))
251 red_(layer.GetRedAsFloat()),
252 green_(layer.GetGreenAsFloat()),
253 blue_(layer.GetBlueAsFloat())
254 { 265 {
255 // High-level reference: 266 // High-level reference:
256 // https://mattdesl.svbtle.com/drawing-lines-is-hard 267 // https://mattdesl.svbtle.com/drawing-lines-is-hard
257 // https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader 268 // https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
258 269
269 // Each segment is made of 2 triangles. One triangle is 280 // Each segment is made of 2 triangles. One triangle is
270 // defined by 3 points in 2D => 6 vertices per segment. 281 // defined by 3 points in 2D => 6 vertices per segment.
271 countVertices += countSegments * 2 * 3; 282 countVertices += countSegments * 2 * 3;
272 } 283 }
273 284
274 std::vector<float> coords, miterDirections; 285 std::vector<float> coords, colors, miterDirections;
275 coords.reserve(countVertices * COMPONENTS_POSITION); 286 coords.reserve(countVertices * COMPONENTS_POSITION);
287 colors.reserve(countVertices * COMPONENTS_COLOR);
276 miterDirections.reserve(countVertices * COMPONENTS_MITER); 288 miterDirections.reserve(countVertices * COMPONENTS_MITER);
277 289
278 for (size_t i = 0; i < layer.GetChainsCount(); i++) 290 for (size_t i = 0; i < layer.GetChainsCount(); i++)
279 { 291 {
280 const PolylineSceneLayer::Chain& chain = layer.GetChain(i); 292 const PolylineSceneLayer::Chain& chain = layer.GetChain(i);
305 317
306 for (size_t j = 0; j < segments.size(); j++) 318 for (size_t j = 0; j < segments.size(); j++)
307 { 319 {
308 if (!segments[j].IsEmpty()) 320 if (!segments[j].IsEmpty())
309 { 321 {
310 segments[j].AddTriangles(coords, miterDirections); 322 segments[j].AddTriangles(coords, miterDirections, colors, layer.GetColor(i));
311 } 323 }
312 } 324 }
313 } 325 }
314 } 326 }
315 327
328 assert(coords.size() == colors.size());
329
316 if (!coords.empty()) 330 if (!coords.empty())
317 { 331 {
318 verticesCount_ = coords.size() / COMPONENTS_POSITION; 332 verticesCount_ = coords.size() / COMPONENTS_POSITION;
319 333
320 context_.MakeCurrent(); 334 context_.MakeCurrent();
321 glGenBuffers(2, buffers_); 335 glGenBuffers(3, buffers_);
322 336
323 glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]); 337 glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]);
324 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * coords.size(), &coords[0], GL_STATIC_DRAW); 338 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * coords.size(), &coords[0], GL_STATIC_DRAW);
325 339
326 glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]); 340 glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]);
327 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * miterDirections.size(), &miterDirections[0], GL_STATIC_DRAW); 341 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * miterDirections.size(), &miterDirections[0], GL_STATIC_DRAW);
342
343 glBindBuffer(GL_ARRAY_BUFFER, buffers_[2]);
344 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size(), &colors[0], GL_STATIC_DRAW);
328 } 345 }
329 } 346 }
330 347
331 348
332 OpenGLLinesProgram::Data::~Data() 349 OpenGLLinesProgram::Data::~Data()
333 { 350 {
334 if (!IsEmpty()) 351 if (!IsEmpty())
335 { 352 {
336 context_.MakeCurrent(); 353 context_.MakeCurrent();
337 glDeleteBuffers(2, buffers_); 354 glDeleteBuffers(3, buffers_);
338 } 355 }
339 } 356 }
340 357
341 358
342 GLuint OpenGLLinesProgram::Data::GetVerticesBuffer() const 359 GLuint OpenGLLinesProgram::Data::GetVerticesBuffer() const
363 return buffers_[1]; 380 return buffers_[1];
364 } 381 }
365 } 382 }
366 383
367 384
385 GLuint OpenGLLinesProgram::Data::GetColorsBuffer() const
386 {
387 if (IsEmpty())
388 {
389 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
390 }
391 else
392 {
393 return buffers_[2];
394 }
395 }
396
397
368 OpenGLLinesProgram::OpenGLLinesProgram(OpenGL::IOpenGLContext& context) : 398 OpenGLLinesProgram::OpenGLLinesProgram(OpenGL::IOpenGLContext& context) :
369 context_(context) 399 context_(context)
370 { 400 {
371
372 context_.MakeCurrent(); 401 context_.MakeCurrent();
373 402
374 program_.reset(new OpenGL::OpenGLProgram); 403 program_.reset(new OpenGL::OpenGLProgram);
375 program_->CompileShaders(VERTEX_SHADER, FRAGMENT_SHADER); 404 program_->CompileShaders(VERTEX_SHADER, FRAGMENT_SHADER);
376 } 405 }
386 context_.MakeCurrent(); 415 context_.MakeCurrent();
387 program_->Use(); 416 program_->Use();
388 417
389 GLint locationPosition = program_->GetAttributeLocation("a_position"); 418 GLint locationPosition = program_->GetAttributeLocation("a_position");
390 GLint locationMiterDirection = program_->GetAttributeLocation("a_miter_direction"); 419 GLint locationMiterDirection = program_->GetAttributeLocation("a_miter_direction");
420 GLint locationColor = program_->GetAttributeLocation("a_color");
391 421
392 float m[16]; 422 float m[16];
393 transform.ConvertToOpenGLMatrix(m, context_.GetCanvasWidth(), context_.GetCanvasHeight()); 423 transform.ConvertToOpenGLMatrix(m, context_.GetCanvasWidth(), context_.GetCanvasHeight());
394 424
395 glUniformMatrix4fv(program_->GetUniformLocation("u_matrix"), 1, GL_FALSE, m); 425 glUniformMatrix4fv(program_->GetUniformLocation("u_matrix"), 1, GL_FALSE, m);
396 glUniform3f(program_->GetUniformLocation("u_color"),
397 data.GetRed(), data.GetGreen(), data.GetBlue());
398 426
399 glBindBuffer(GL_ARRAY_BUFFER, data.GetVerticesBuffer()); 427 glBindBuffer(GL_ARRAY_BUFFER, data.GetVerticesBuffer());
400 glEnableVertexAttribArray(locationPosition); 428 glEnableVertexAttribArray(locationPosition);
401 glVertexAttribPointer(locationPosition, COMPONENTS_POSITION, GL_FLOAT, GL_FALSE, 0, 0); 429 glVertexAttribPointer(locationPosition, COMPONENTS_POSITION, GL_FLOAT, GL_FALSE, 0, 0);
402 430
403 glBindBuffer(GL_ARRAY_BUFFER, data.GetMiterDirectionsBuffer()); 431 glBindBuffer(GL_ARRAY_BUFFER, data.GetMiterDirectionsBuffer());
404 glEnableVertexAttribArray(locationMiterDirection); 432 glEnableVertexAttribArray(locationMiterDirection);
405 glVertexAttribPointer(locationMiterDirection, COMPONENTS_MITER, GL_FLOAT, GL_FALSE, 0, 0); 433 glVertexAttribPointer(locationMiterDirection, COMPONENTS_MITER, GL_FLOAT, GL_FALSE, 0, 0);
434
435 glBindBuffer(GL_ARRAY_BUFFER, data.GetColorsBuffer());
436 glEnableVertexAttribArray(locationColor);
437 glVertexAttribPointer(locationColor, COMPONENTS_COLOR, GL_FLOAT, GL_FALSE, 0, 0);
406 438
407 glUniform1i(program_->GetUniformLocation("u_antialiasing"), (antialiasing ? 1 : 0)); 439 glUniform1i(program_->GetUniformLocation("u_antialiasing"), (antialiasing ? 1 : 0));
408 440
409 const double zoom = transform.ComputeZoom(); 441 const double zoom = transform.ComputeZoom();
410 const double thickness = data.GetThickness() / 2.0; 442 const double thickness = data.GetThickness() / 2.0;
462 static_cast<GLsizei>(data.GetVerticesCount())); 494 static_cast<GLsizei>(data.GetVerticesCount()));
463 } 495 }
464 496
465 glDisableVertexAttribArray(locationPosition); 497 glDisableVertexAttribArray(locationPosition);
466 glDisableVertexAttribArray(locationMiterDirection); 498 glDisableVertexAttribArray(locationMiterDirection);
499 glDisableVertexAttribArray(locationColor);
467 } 500 }
468 } 501 }
469 } 502 }
470 } 503 }