5.8 - Example 4: Textures

This chapter has explained how shader programs, GPU object buffers, and JavaScript rendering code works together to create WebGL renderings. We have keep the shader programs very simple to help make the concepts understandable. However, we have barely scratched the surface on what is possible. The WebGL program below is presented to spark your interest in what is coming in future lessons. We won’t walk through the details of procedural texture mapping in this lesson, but please review the program code to get an idea of what a more complex shader program might do.

The example WebGL program below does the following:

A Texture Map Example

Show: Code   Canvas   Run Info
../_static/05_simple_pyramid_texture/simple_pyramid_texture.html

A simple, 3D model where pixel colors are calculated using a procedural texture map.

Please use a browser that supports "canvas"
Animate
Draw the edges of the triangles using a gl.LINE_LOOP
Render the model as a "wireframe"
Render the global axes (x:red, y:green, z:blue)
Average time to render the model is 0.00000 milliseconds.
Show: Process information    Warnings    Errors
Open this webgl program in a new tab or window

Summary

To render a model, it requires a GPU shader program, one or more GPU object-buffers, and JavaScript rendering code. Let’s summarize the big picture behind rendering:

  • A vertex shader program retrieves vertex and other associated data from buffer objects. All buffer objects are 1-dimensional arrays of floats. The data in the buffer objects are organized by vertex. The vertex shader calculates the position a vertex in the scene and prepares any data needed by the fragment shader for calculating colors.
  • A fragment shader program receives data from the vertex shader for each vertex and then interpolates the values over the fragments of the primitive (either a point, line or triangle).
  • A pre-processing step must create appropriate GPU buffer objects and copy the model data into them.
  • Each time a model is rendered, a shader’s uniform variables must be assigned a value, a shader’s attribute variables must be linked to their appropriate buffer objects and a call to gl.drawArrays() executes the graphics pipeline.

Self-Assessments

    Q-345: Code in the example fragment shader in the above WebGL program uses a floor function to to convert a floating point number to an integer, and a mod function to get the remainder after division by 2. What are the only possible values this expression can return?

    mod((floor(s/grid_size) + floor(t/grid_size)),2.0)
    
  • 0 and 1.
  • Correct. The sum of the two floor() values will always be an integer, and the remainder of dividing any integer by 2 has to be 0 or 1, which is equivalent to saying all integers are either even or odd.
  • 0, 1, or 2.
  • Incorrect. It is not possible to get 2.
  • Any positive integer value greater than or equal to 0.
  • Incorrect. Mod(n,2) divides by 2 and returns the remainder as an integer.
  • Only 0 and 2.
  • Incorrect.

    Q-346: The SimpleModel4 function in the above WebGL program uses a array of arrays to define the data for each vertex like this:

    vertices = [  [ [ 0.0, -0.25, -0.50], [1, 0, 0, 1], [2.0, 0.0] ],
                  [ [ 0.0,  0.25,  0.00], [0, 1, 0, 1], [0.5, 1.0] ],
                  [ [ 0.5, -0.25,  0.25], [0, 0, 1, 1], [1.0, 0.0] ],
                  [ [-0.5, -0.25,  0.25], [1, 0, 1, 1], [0.0, 0.0] ]
               ];
    

    Could you have defined the vertex data using a single array for each vertex like this:

    vertices = [  [ 0.0, -0.25, -0.50,   1, 0, 0, 1,  2.0, 0.0 ],
                  [ 0.0,  0.25,  0.00,   0, 1, 0, 1,  0.5, 1.0 ],
                  [ 0.5, -0.25,  0.25,   0, 0, 1, 1,  1.0, 0.0 ],
                  [ -0.5, -0.25,  0.25,  1, 0, 1, 1,  0.0, 0.0 ]
               ];
    
  • Yes, the exact structure of the model data is arbitrary.
  • Correct.
  • No, there is only one way to define model data.
  • Incorrect. There are many, many ways.
  • Yes, but it would be very confusing.
  • Incorrect. There is no confusion if you did it that way for a reason!
  • No, model data must be defined in arrays of arrays.
  • Incorrect. Using arrays of arrays might make the data more structured, but it is not required.
Next Section - 5.9 - Interleaved Buffers