Task 6: “Level sampling” with mipmaps for texture mapping (25 pts)

Relevant lecture: 5

Finally, update RasterizerImp::rasterize_textured_triangle(...) to support sampling different mipmap levels (MipLevels). The GUI toggles RasterizerImp’s LevelSampleMethod variable lsm using the L key. Please implement the following level sampling methods in the helper function Texture::sample.

  • When lsm == L_ZERO, you should sample from the zero-th MipLevel, as in Part 5.
  • When lsm == L_NEAREST, you should compute the nearest appropriate mipmap level and pass that level as a parameter to the nearest or bilinear sample function.
  • When lsm == L_LINEAR, you should compute the mipmap level as a continuous number. Then compute a weighted sum of using one sample from each of the adjacent mipmap levels as described in lecture.

In addition, implement Texture::get_level as a helper function. You will need $(\frac{du}{dx}, \frac{dv}{dx})$ and $(\frac{du}{dy}, \frac{dv}{dy})$ to calculate the correct mipmap level. In order to get these values corresponding to a point $(x,y)$ inside a triangle, you must perform the following.

  1. Calculate the uv barycentric coordinates of $(x,y)$, $(x+1,y)$, and $(x,y+1)$ in rasterize_textured_triangle(...) as sp.p_uv, sp.p_dx_uv, and sp.p_dy_uv, assign them to a SampleParams struct sp, along with other values required by the struct, and pass sp to Texture::get_level
  2. Calculate the difference vectors sp.p_dx_uv - sp.p_uv and sp.p_dy_uv - sp.p_uv inside Texture::get_level, and finally
  3. Scale up the difference vectors accordingly by the width and height of the full-resolution texture image.

With these, you can proceed with the calculation from the lecture slides.

Notes:

  • The lsm and psm variables can be set independently and interacted independently. In other words, all combinations of psm==[P_NEAREST, P_LINEAR] x lsm==[L_ZERO, L_NEAREST, L_LINEAR] are valid.
  • When lsm == L_LINEAR and psm == P_LINEAR, this is known as trilinear sampling, or trilinear texture filtering, as described in lecture.
  • You may find it helpful to visualize what parts of the image use different levels of the mipmap. One way to do this is by normalizing the value returned by Texture::get_level by the maximum level (i.e. size of the mipmap) and have that value returned by Texture::sample as a color. Zoom in and out of the image to see how the levels change. This is a great way to both debug your implementation as well as gain intuition about level sampling! See below for two examples, where we zoom out/in to illustrate how the computed levels change.
  • Please be careful do not make copies of an entire Miplevel. Make sure you always use a pointer or a reference to access the miplevel. Copying entire miplevels as arguments is extremely slow!

For convenience, here is a list of functions you will need to modify:

  1. RasterizerImp::rasterize_textured_triangle
  2. Texture::sample
  3. Texture::get_level

Extra Credit: Implement anisotropic filtering or summed area tables. Show comparisons of your method to nearest, bilinear, and trilinear sampling. Use clock() to measure the relative performance of the methods.

For Your Write-Up: Task 6

  • Explain level sampling in your own words and describe how you implemented it for texture mapping.
  • You can now adjust your sampling technique by selecting pixel sampling, level sampling, or the number of samples per pixel. Describe the tradeoffs between speed, memory usage, and antialiasing power between the three various techniques.
  • Using a png file you find yourself, show us four versions of the image, using the combinations of L_ZERO and P_NEAREST, L_ZERO and P_LINEAR, L_NEAREST and P_NEAREST, as well as L_NEAREST and P_LINEAR.
    • To use your own png, make a copy of one of the existing svg files in svg/texmap/ (or create your own modelled after one of the provided svg files). Then, near the top of the file, change the texture filename to point to your own png. From there, you can run ./draw and pass in that svg file to render it and then save a screenshot of your results.
    • Note: Choose a png that showcases the different sampling effects well. You may also want to zoom in/out, use the pixel inspector, etc. to demonstrate the differences.
  • Extra credit: If you implemented any extra filtering methods, describe them and show comparisons between your results with the other above methods.