Page 181 - Computer Graphics Handout
P. 181

glEnableVertexAttribArray(loc);
          glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0,
          BUFFER_OFFSET(0));
          glGenBuffers(1, buffers);
          glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
          glBufferData(GL_ARRAY_BUFFER, sizeof(triangles), triangles,
          GL_STATIC_DRAW);
          and display it as
          glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
          glDrawArrays(GL_TRIANGLES, 0, 6*N*M);
          If we integrate this code with our previous example using line strips, the output will look almost identical. Although we have designed
          a  surface,  by  choosing  to  display  only  the  edges  by  using  a  polygon  mode  of  GL_LINE,  we  do  not  generate  any  fragments
          corresponding to the inside of the polygon, and thus we see the edges of polygons that would be hidden if the mode were GL_FILL.
          We can fix this problem by rendering the data twice, first as a filled white surface and second as black lines. Because the data are
          already on the GPU, we do not have to send any vertex data to the GPU for the second rendering.We can specify two colors in the
          initialization that we will send to the fragment shader
          color4 white = vec4(1.0, 1.0, 1.0, 1.0);
          color4 black = vec4(0.0, 0.0, 0.0, 1.0);
          color_loc = glGetUniformLocation(program, “fcolor”);

          and then modify to the display callback to have the code
          glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
          glUniform4fv(color_loc, 1, white);
          glDrawArrays(GL_TRIANGLES, 0, 6*N*M);
          glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
          glUniform4fv(color_loc, 1, black);
          glDrawArrays(GL_TRIANGLES, 0, 6*N*M);
          The modified fragment shader is
          uniform vec4 fcolor;
          void main()
          {
          gl_FragColor = fcolor;
          }
          4.9.2 Polygon Offset
          There are interesting aspects to this OpenGL program, and we can make various modifications. First, if we use all the data, the
          resulting plot may contain many small polygons. The resulting density of lines in the display may be annoying and can contain moir´e
          patterns. Hence, we might prefer to subsample the data either by using every kth point for some k or by averaging groups of data
          points to obtain a new set of samples with smaller N and M.
          There is one additional trick that we used in the display of Figure 4.44. If we draw both a polygon and a line loop with the code in
          the previous section, then each triangle is rendered twice in the same plane, once filled and once by its edges. Even though the
          second rendering of just the edges is done with filled rendering, numerical inaccuracies in the renderer often cause parts of second
          rendering to lie behind the corresponding fragments in the first rendering. We can avoid this problem by enabling the polygon offset
          mode and setting the offset parameters using glPolygonOffset.
          Polygon fill offset moves fragments slightly away from the viewer, so all the desired lines should be visible. In initialization, we can
          set up polygon offset by
          glEnable(GL_POLYGON_OFFSET_FILL);
          glPolygonOffset(1.0, 1.0);
          The two parameters in PolygonOffset are combined with the slope of the polygon and an implementation-dependent constant.
          Consequently, you may have to do a little experimentation to find the best values. Perhaps the greatest weakness of our code is
          that we are sending too much data to the GPU and not using the most efficient rendering method. Consider a mesh consisting of a
          single row of N quadrilaterals. If we render it as 2N triangles using
          point4 vertices[6*N];
          glDrawArrays(GL_TRIANGLES, 0, 6*N);
          we send 6N vertices to the GPU. If we instead set our vertices as a triangle strip, then these two lines of code become
          point4 vertices[2*N-2];
          glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*N-2);
                                                             181
   176   177   178   179   180   181   182   183   184   185   186