title: How to access all vertexes within the same patch in Tessellation Control Shader
body: <p>I want to do LOD in Tessenllation Control Shader. And my method is to calculate the area each patch occupyed on screen coordinate, and set different tessellation level for them.</p>
  
  <p>So I need to access all vertices within a patch and I do so like:</p>
  
  <pre><code>for(int i = 0; i &lt; 4; i++)
  {
      position_screen[i] = ProjectionMatrix * ModelViewMatrix * gl_in[i].gl_Position;
  }
  </code></pre>
  
  <p>where i defined my patch in TCS like:</p>
  
  <pre><code>#version 400  
  layout( vertices=4 ) out; 
  </code></pre>
  
  <p>and here is related codes in OpenGL:</p>
  
  <pre><code>glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rect_index_buffer);
  glPatchParameteri(GL_PATCH_VERTICES, 4);
  glDrawElements(GL_PATCHES, RECT_INDEX_SIZE, GL_UNSIGNED_INT, 0);    
  </code></pre>
  
  <p><br/></p>
  
  <p>However the result is strange.The tessellation level is related to the area on the scrren, but all patches have the same tessellation level.</p>
  
  <p>So what's the problem?</p>
  
  <p>I guess it's the way I try getting access to vertices within a patch went wrong. Then how can I do that?</p>
  
  <p>The following is codes in my Tessellation Control Shader, I hope it helps:</p>
  
  <pre><code>#version 400  
  layout( vertices=4 ) out; 
  
  uniform mat4 ProjectionMatrix;
  uniform mat4 ModelViewMatrix;
  
  uniform float window_height;
  uniform float window_width;
  
  float PI = 3.14159;
  
  float calcTriangleArea(float l[3])  //Heron's formula
  {
      float p = (l[0] + l[1] + l[2]) / 2.0;
  
      return sqrt(p * (p - l[0]) * (p - l[1]) * (p - l[2]));
  }
  
  float calcSqureArea(vec4 position[4])
  {
      vec2 position_screen[4];
      for(int i=0;i&lt;4;i++)
      {
          position_screen[i] = position[i].xy;
      }
  
      float l[4];
  
      for(int i = 0;i &lt; 4;i++)
      {
          l[i] = length(position_screen[(i + 1) % 4] - position_screen[i % 4]);
      }
  
      float diagonal = length(position_screen[2] - position_screen[0]);
  
      float l1[3];
      float l2[3];
  
      l1[0] = l[0];
      l1[1] = l[1];
      l1[2] = diagonal;
  
      l2[0] = l[2];
      l2[1] = l[3];
      l2[2] = diagonal;
  
      float area = calcTriangleArea(l1) + calcTriangleArea(l2);
  
      return area;
  }
  
  float checkInsideView(vec4 position[4]) //check if the patch is visible
  {
      int flag = 4;
      for(int i=0;i&lt;4;i++)
      {
          if((position[i].x &gt;= -window_width / 2.0) &amp;&amp; (position[i].x &lt;= window_width / 2.0) &amp;&amp; 
      (position[i].y &gt;= -window_height / 2.0) &amp;&amp; (position[i].y &lt;= window_height / 2.0))
          {
              flag --;
          }
      }
  
      if(flag == 0)   //all 4 vertices are visible
      {
          return 0.0;
      }
      else if(flag == 4)  //not all visible
      {
          return 2.0;
      }
      else    //all vertices are not visible
      {
          return 1.0;
      }
  }
  
  float calcLODLevel()
  {
      vec4 position_screen[4];
      for(int i = 0; i &lt; 4; i++)
      {
          position_screen[i] = ProjectionMatrix * ModelViewMatrix * gl_in[i].gl_Position;
      }
  
      float in_view_level = checkInsideView(position_screen);
  
      //tess number is decided by the area that this patch covers on 
      //the screen
      float area = calcSqureArea(position_screen);
      float level = sqrt(area);   
  
      if(in_view_level == 1.0)    
      {
          level /= sqrt(2);
      }
      //dont do tessellation
      //if this patch is not visible
      else if(in_view_level == 2.0)
      {
          level = 1.0;
      }
  
      return level;
  }
  
  void main()
  {
      gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
  
      float lod_level = calcLODLevel();
  
      gl_TessLevelOuter[0] = lod_level;
      gl_TessLevelOuter[1] = lod_level;
      gl_TessLevelOuter[2] = lod_level;  
      gl_TessLevelOuter[3] = lod_level;  
      gl_TessLevelInner[0] = lod_level;
      gl_TessLevelInner[1] = lod_level;   
  }
  </code></pre>