diff 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
line wrap: on
line diff
--- a/Framework/Scene2D/Internals/OpenGLLinesProgram.cpp	Tue May 28 14:18:46 2019 +0200
+++ b/Framework/Scene2D/Internals/OpenGLLinesProgram.cpp	Tue May 28 15:58:21 2019 +0200
@@ -26,6 +26,7 @@
 
 
 static const unsigned int COMPONENTS_POSITION = 3;
+static const unsigned int COMPONENTS_COLOR = 3;
 static const unsigned int COMPONENTS_MITER = 2;
 
 
@@ -33,12 +34,15 @@
   ORTHANC_STONE_OPENGL_SHADER_VERSION_DIRECTIVE
   "attribute vec2 a_miter_direction; \n"
   "attribute vec4 a_position;        \n"
+  "attribute vec3 a_color;           \n"
   "uniform float u_thickness;        \n"
   "uniform mat4 u_matrix;            \n"
   "varying float v_distance;         \n"
+  "varying vec3 v_color;             \n"
   "void main()                       \n"
   "{                                 \n"
   "  v_distance = a_position.z;      \n"
+  "  v_color = a_color;              \n"
   "  gl_Position = u_matrix * vec4(a_position.xy + a_position.z * a_miter_direction * u_thickness, 0, 1); \n"
   "}";
 
@@ -47,20 +51,20 @@
   ORTHANC_STONE_OPENGL_SHADER_VERSION_DIRECTIVE
   "uniform bool u_antialiasing;           \n"
   "uniform float u_antialiasing_start;    \n"
-  "uniform vec3 u_color;                  \n"
   "varying float v_distance;              \n"   // Distance of the point to the segment
+  "varying vec3 v_color;                  \n"
   "void main()                            \n"
   "{                                      \n"
   "  float d = abs(v_distance);           \n"
   "  if (!u_antialiasing ||               \n"
   "      d <= u_antialiasing_start)       \n"
-  "    gl_FragColor = vec4(u_color, 1);   \n"
+  "    gl_FragColor = vec4(v_color, 1);   \n"
   "  else if (d >= 1.0)                   \n"
   "    gl_FragColor = vec4(0, 0, 0, 0);   \n"
   "  else                                 \n"
   "  {                                    \n"
   "    float alpha = 1.0 - smoothstep(u_antialiasing_start, 1.0, d); \n"
-  "    gl_FragColor = vec4(u_color * alpha, alpha); \n"
+  "    gl_FragColor = vec4(v_color * alpha, alpha); \n"
   "  }                                    \n"
   "}";
 
@@ -197,7 +201,9 @@
       }
 
       void AddTriangles(std::vector<float>& coords,
-                        std::vector<float>& miterDirections)
+                        std::vector<float>& miterDirections,
+                        std::vector<float>& colors,
+                        const Color& color)
       {
         if (isEmpty_)
         {
@@ -239,6 +245,14 @@
         miterDirections.push_back(static_cast<float>(miterY1_));
         miterDirections.push_back(static_cast<float>(miterX2_));
         miterDirections.push_back(static_cast<float>(miterY2_));
+
+        // Add the colors of the 2 triangles (leading to 2 * 3 values)
+        for (unsigned int i = 0; i < 6; i++)
+        {
+          colors.push_back(color.GetRedAsFloat());
+          colors.push_back(color.GetGreenAsFloat());
+          colors.push_back(color.GetBlueAsFloat());
+        }
       }        
     };
 
@@ -247,10 +261,7 @@
                                    const PolylineSceneLayer& layer) :
       context_(context),
       verticesCount_(0),
-      thickness_(static_cast<float>(layer.GetThickness())),
-      red_(layer.GetRedAsFloat()),
-      green_(layer.GetGreenAsFloat()),
-      blue_(layer.GetBlueAsFloat())
+      thickness_(static_cast<float>(layer.GetThickness()))
     {
       // High-level reference:
       // https://mattdesl.svbtle.com/drawing-lines-is-hard
@@ -271,8 +282,9 @@
         countVertices += countSegments * 2 * 3;
       }
 
-      std::vector<float>  coords, miterDirections;
+      std::vector<float>  coords, colors, miterDirections;
       coords.reserve(countVertices * COMPONENTS_POSITION);
+      colors.reserve(countVertices * COMPONENTS_COLOR);
       miterDirections.reserve(countVertices * COMPONENTS_MITER);
 
       for (size_t i = 0; i < layer.GetChainsCount(); i++)
@@ -307,24 +319,29 @@
           {
             if (!segments[j].IsEmpty())
             {
-              segments[j].AddTriangles(coords, miterDirections);
+              segments[j].AddTriangles(coords, miterDirections, colors, layer.GetColor(i));
             }
           }
         }
       }
 
+      assert(coords.size() == colors.size());
+
       if (!coords.empty())
       {
         verticesCount_ = coords.size() / COMPONENTS_POSITION;
 
         context_.MakeCurrent();
-        glGenBuffers(2, buffers_);
+        glGenBuffers(3, buffers_);
 
         glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]);
         glBufferData(GL_ARRAY_BUFFER, sizeof(float) * coords.size(), &coords[0], GL_STATIC_DRAW);
 
         glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]);
         glBufferData(GL_ARRAY_BUFFER, sizeof(float) * miterDirections.size(), &miterDirections[0], GL_STATIC_DRAW);
+
+        glBindBuffer(GL_ARRAY_BUFFER, buffers_[2]);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size(), &colors[0], GL_STATIC_DRAW);
       }
     }
 
@@ -334,7 +351,7 @@
       if (!IsEmpty())
       {
         context_.MakeCurrent();
-        glDeleteBuffers(2, buffers_);
+        glDeleteBuffers(3, buffers_);
       }
     }
 
@@ -365,10 +382,22 @@
     }
 
 
+    GLuint OpenGLLinesProgram::Data::GetColorsBuffer() const
+    {
+      if (IsEmpty())
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+      }
+      else
+      {
+        return buffers_[2];
+      }
+    }
+
+
     OpenGLLinesProgram::OpenGLLinesProgram(OpenGL::IOpenGLContext&  context) :
       context_(context)
     {
-
       context_.MakeCurrent();
 
       program_.reset(new OpenGL::OpenGLProgram);
@@ -388,13 +417,12 @@
 
         GLint locationPosition = program_->GetAttributeLocation("a_position");
         GLint locationMiterDirection = program_->GetAttributeLocation("a_miter_direction");
+        GLint locationColor = program_->GetAttributeLocation("a_color");
 
         float m[16];
         transform.ConvertToOpenGLMatrix(m, context_.GetCanvasWidth(), context_.GetCanvasHeight());
 
         glUniformMatrix4fv(program_->GetUniformLocation("u_matrix"), 1, GL_FALSE, m);
-        glUniform3f(program_->GetUniformLocation("u_color"), 
-                    data.GetRed(), data.GetGreen(), data.GetBlue());
 
         glBindBuffer(GL_ARRAY_BUFFER, data.GetVerticesBuffer());
         glEnableVertexAttribArray(locationPosition);
@@ -404,6 +432,10 @@
         glEnableVertexAttribArray(locationMiterDirection);
         glVertexAttribPointer(locationMiterDirection, COMPONENTS_MITER, GL_FLOAT, GL_FALSE, 0, 0);
 
+        glBindBuffer(GL_ARRAY_BUFFER, data.GetColorsBuffer());
+        glEnableVertexAttribArray(locationColor);
+        glVertexAttribPointer(locationColor, COMPONENTS_COLOR, GL_FLOAT, GL_FALSE, 0, 0);
+
         glUniform1i(program_->GetUniformLocation("u_antialiasing"), (antialiasing ? 1 : 0));
 
         const double zoom = transform.ComputeZoom();
@@ -464,6 +496,7 @@
 
         glDisableVertexAttribArray(locationPosition);
         glDisableVertexAttribArray(locationMiterDirection);
+        glDisableVertexAttribArray(locationColor);
       }
     }
   }