Mercurial > hg > orthanc-stone
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 } |