Master the fundamental concepts of software rasterizer through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksTexture mapping applies a 2D image to a 3D surface. Edwin Catmull introduced the idea in 1974; today every real-time renderer depends on it. Each vertex carries texture coordinates (u, v) in the range 0 to 1. During rasterization, UVs interpolate across the triangle (with perspective correction) and each fragment looks up a texel color.
Texture mapping decouples surface detail from geometry. A flat triangle can look like brick, wood, or skin without extra vertices.
Nearest-neighbor rounds (u, v) to the closest texel. Fast but blocky when magnified.
Bilinear filtering blends four neighboring texels:
cLoading…
For example, sampling (u=0.375, v=0.625) on a 4x4 texture blends texels at (1,2), (2,2), (1,3), and (2,3). Mipmaps (Lance Williams, 1983) add precomputed smaller versions to fix minification aliasing when distant textures shrink to a few pixels.
You will sample a 4x4 gradient texture using nearest-neighbor and bilinear filtering at test UV coordinates. This task requires you to print both results so the quality difference is visible. Understanding these two modes is essential for software renderers, image resizers, and any GLSL texture() call where you choose sampler settings.
Implement a GPU texture sampler for a small grayscale texture:
Texture coordinates arrive in normalized units (0..1 across the texture). Converting them to texel space correctly, with texel centres at half-integers, is where most sampler bugs live. Everything is fixed-point integer arithmetic, so results are exact.
# starts a comment line.
cLoading…
((i mod n) + n) mod n;p = i mod 2n (made non-negative), then p < n ? p : 2n-1-p.i = floor(U·W / 1000) and j = floor(V·H / 1000), then wrapped.xs = 2·U·W - 1000, i0 = floor(xs / 2000), fx = xs - 2000·i0 (0..1999), and the same for y;((2000-fx)(2000-fy)·t00 + fx(2000-fy)·t10 + (2000-fx)fy·t01 + fx·fy·t11 + 2000000) / 4000000, using integer division, so rounding is half up.cLoading…
-> (x, y) if wrapping changed either index.texture: W H (1-16)texture row R: expected W hex bytes (the texture is discarded)sample: U V nearest|bilinear repeat|clamp|mirror (U V in 1/1000)sample: wrap mode must be repeat, clamp or mirrorsample: load a texture firstunknown command XInput:
cLoading…
Output:
cLoading…
/ truncates toward zero and would pick the wrong texel.Hidden tests cover samples at exact texel centres and edges, negative and out-of-range coordinates with every wrap mode, a non-square texture, bilinear filtering across the repeat seam, and malformed input.