Page 74 - Computer Graphics Handout
P. 74

divide_tetra(v[0], v[1], v[2], v[3], n);
          There are two more problems that we must address before we have a useful three-dimensional program. The first is how to deal
          with color. If we use just a single color as in our first example, we won’t be able to see any of the three-dimensional structure.
          Alternately, we could use the approach of our last example of letting the color of  each fragment be determined by where the point
          is located in three dimensions. But we would prefer to use a small number of colors and color the face of each triangle with one of
          these colors. We can set this scheme by choosing some base colors in the application, such as
          typedef vec3 color3;
          color3 base_colors[4] = {color3(1.0, 0.0, 0.0), color3(0.0, 1.0, 0.0),
          color3(0.0, 0.0, 1.0), color3(0.0, 0.0, 0.0)};
          and then assigning colors to each point as it is generated. We set a color index as we generate the triangles
          int colorindex;
          void tetra(point3 a, point3 b, point3 c, point3 d)
          {
          colorindex = 0;
          triangle(a,b,c);
          colorindex = 1;
          triangle(a,c,d);
          colorindex = 2;
          triangle(a,d,b);
          colorindex = 3;
          triangle(b,d,c);
          }
          and then form a color array with a color for each point:
          color3 colors[NumVertices];
          int i = 0; // number of vertices
          void triangle(point3 a, point3 b, point3 c)
          /* specify one triangle */
          {
          colors[i] = base_colors[colorindex];
          points[i] = a;
          i++;
          colors[i] = base_colors[colorindex];
          points[i] = b;
          i++;
          colors[i] = base_colors[colorindex];
          points[i] = c;
          i++;
          }
          We send these colors to the GPU along with their associated vertices in a buffer object. Inside of the buffer object, we’ll place the
          vertex data at the start of the buffer’s memory and then follow it with the color data. To do this, however, we’ll need to first allocate
          a buffer large enough to contain all of the data, and then load data into the buffer in two operations using the OpenGL function
          glBufferSubData. The function glBufferSubData allows us to update parts of an existing buffer object with new data. The first
          parameter specifies which array in the buffer we want to update. The second parameter specifies which byte in the buffer to start
          writing data at, and the third parameter specifies how many bytes to read from the memory pointer, which is passed in using the
          fourth parameter. Consider the code:
          GLuint buffer;
          glGenBuffers(1, &buffer);
          glBindBuffer(GL_ARRAY_BUFFER, buffer);
          // Allocate a buffer of uninitialized data of the correct size
          glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors),
          NULL, GL_STATIC_DRAW);
          // Load the separate arrays of data
          glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points );
          glBufferSubData(GL_ARRAY_BUFFER, sizeof(points),
          sizeof(colors), colors );
          In the above example, the first call updates the bytes in the range [0, sizeof(points)-1]. Since we need to write the data for the colors
          immediately after in the buffer, we start at the byte immediately following the vertex data, which is just the length (in bytes) of the

                                                              74
   69   70   71   72   73   74   75   76   77   78   79