From 5ce9ef0eae895234f10c08ba03e6a107b5920cd9 Mon Sep 17 00:00:00 2001 From: Shi Yan Date: Tue, 30 Jul 2024 22:45:43 -0500 Subject: [PATCH] update --- 2D_Techniques/billboarding.html | 32 ++++++++++------- 2D_Techniques/implementing_fake_3d.html | 32 ++++++++++------- 2D_Techniques/implementing_gaussian_blur.html | 32 ++++++++++------- 2D_Techniques/orthogonal_cameras.html | 32 ++++++++++------- 2D_Techniques/rendering_to_textures.html | 32 ++++++++++------- 2D_Techniques/text_rendering.html | 32 ++++++++++------- 2D_Techniques/video_rendering.html | 32 ++++++++++------- Advanced/equirectangular_rendering.html | 32 ++++++++++------- Advanced/gaussian_splatting.html | 32 ++++++++++------- Advanced/mega_texture.html | 32 ++++++++++------- Advanced/normal_mapping_and_bump_mapping.html | 32 ++++++++++------- Advanced/shadow_mapping.html | 32 ++++++++++------- Advanced/skeleton_animation.html | 32 ++++++++++------- Advanced/stencil_buffer.html | 32 ++++++++++------- Advanced/toon_shading.html | 32 ++++++++++------- Advanced/transparency_with_depth_peeling.html | 32 ++++++++++------- Basics/applying_hardcoded_vertex_colors.html | 32 ++++++++++------- Basics/creating_an_empty_canvas.html | 32 ++++++++++------- Basics/depth_testing.html | 32 ++++++++++------- ...colored_triangle_with_a_single_buffer.html | 32 ++++++++++------- Basics/drawing_a_triangle.html | 32 ++++++++++------- ...wing_a_triangle_with_defined_vertices.html | 32 ++++++++++------- Basics/front_and_back_face_culling.html | 32 ++++++++++------- Basics/implementing_cameras.html | 32 ++++++++++------- Basics/index_buffers.html | 32 ++++++++++------- Basics/lighting.html | 32 ++++++++++------- Basics/loading_3d_models.html | 32 ++++++++++------- .../mipmapping_and_anisotropic_filtering.html | 34 +++++++++++------- Basics/multi_sample_anti_aliasing.html | 32 ++++++++++------- Basics/sampling.png | Bin 0 -> 1369070 bytes Basics/triangle_strips.html | 32 ++++++++++------- Basics/understanding_normals.html | 32 ++++++++++------- Basics/understanding_uniforms.html | 32 ++++++++++------- Basics/using_different_vertex_colors.html | 32 ++++++++++------- Basics/utilizing_transformation_matrices.html | 32 ++++++++++------- Basics/working_with_textures.html | 32 ++++++++++------- Compute/prefix_sum.html | 32 ++++++++++------- Compute/radix_sort.html | 32 ++++++++++------- Compute/reaction_diffusion.html | 32 ++++++++++------- Control/arcball_camera_control.html | 32 ++++++++++------- Control/canvas_resizing.html | 32 ++++++++++------- Control/error_handling_and_limits.html | 32 ++++++++++------- Control/object_picking.html | 32 ++++++++++------- Control/saving_images_and_videos.html | 32 ++++++++++------- Control/using_web_workers.html | 32 ++++++++++------- Introduction/the_gpu_driver.html | 32 ++++++++++------- Introduction/the_gpu_pipeline.html | 32 ++++++++++------- index.html | 32 ++++++++++------- 48 files changed, 941 insertions(+), 565 deletions(-) create mode 100644 Basics/sampling.png diff --git a/2D_Techniques/billboarding.html b/2D_Techniques/billboarding.html index b45cb78..1273113 100644 --- a/2D_Techniques/billboarding.html +++ b/2D_Techniques/billboarding.html @@ -43,18 +43,6 @@ - - @@ -216,6 +204,26 @@

2.5 Billboarding

We will look at a technique called billboarding thi

@@ -232,6 +220,26 @@

2.6 Implementing Fake 3D

in this example, we will look at a fake 3d

@@ -355,6 +343,26 @@

2.2 Implementing Gaussian Blur

2D image processing is a great use ca

@@ -210,6 +198,26 @@

2.1 Orthogonal Cameras

In this section, we'll discuss orthogonal cam

@@ -325,6 +313,26 @@

2.0 Rendering to Textures

In this section, we'll explore the "render

@@ -256,6 +244,26 @@

2.4 Text Rendering

You might be surprised to discover that text rend

@@ -300,6 +288,26 @@

2.3 Video Rendering

We have seen how to load and render images as te

@@ -268,6 +256,26 @@

5.3 Equirectangular Rendering

Equirectangular rendering is a useful

@@ -365,6 +353,26 @@

5.8 Gaussian Splatting

@@ -616,6 +604,26 @@

5.4 Mega Texture

mega texture is also called the virtualized texture

@@ -197,6 +185,26 @@

5.7 Normal Mapping and Bump Mapping

@@ -342,6 +330,26 @@

5.1 Shadow Mapping

previously we have learned about lighting, but li

@@ -811,6 +799,26 @@

5.6 Skeleton Animation

so far we have learned how to create animatio

@@ -331,6 +319,26 @@

5.0 Stencil Buffer

stencil buffer is highly related to depth buffer.

@@ -321,6 +309,26 @@

5.2 Toon Shading

achieving realistisity is not the only goal of rend

@@ -491,6 +479,26 @@

5.5 Transparency with Depth Peeling

transparency is another example

@@ -227,6 +215,26 @@

1.3 Applying Hardcoded Vertex Colors

Welcome to our fourth tutorial!

@@ -281,6 +269,26 @@

1.0 Creating an Empty Canvas

Creating an empty canvas might initiall

@@ -255,6 +243,26 @@

1.12 Depth Testing

In this section, we'll explore depth testing, a c

@@ -259,6 +247,26 @@

1.5 Drawing a Colored Triangle with a Single Buffer

In our previous

@@ -269,6 +257,26 @@

1.1 Drawing a Triangle

Our first tutorial is a bit boring as we were

@@ -269,6 +257,26 @@

1.2 Drawing a Triangle with Defined Vertices

In our previous tutoria

@@ -223,6 +211,26 @@

1.11 Front and Back Face Culling

This section explores the crucial r

@@ -334,6 +322,26 @@

1.9 Implementing Cameras

In our exploration of computer graphics, we

@@ -248,6 +236,26 @@

1.13 Index Buffers

Before implementing model loading in the next tut

@@ -350,6 +338,26 @@

1.16 Lighting

In this section, we'll explore the most fundamental li

@@ -249,6 +237,26 @@

1.14 Loading 3D Models

In this tutorial, we'll explore how to load 3

@@ -156,7 +144,7 @@
-

1.18 Mipmapping and Anisotropic Filtering

In this tutorial, we're going to talk about Mipmaps. It's a wrong belief that a texture map is simply just an image, because a texture map can have multiple levels.

At each level, we usually have the same image of different resolution with the level 0 being the original resolution. At level 1, we have a smaller version of the original image, and so on. We call this the level of details.

The reason that we need multiple resolutions of the same image is to resolve a sampling issue. Let me explain.

We access the texture image through a sampling function. What I mean by sampling is that we're not going to read the entire image as a whole. Instead, we read the image color by color by providing texture coordinates. Because we don't have the holistic view of the image, our sampling density will determine what we see, even the texture image is unchanged.

If our sampling density is very low, we will not be able to reconstruct the original appearance of the original image. Instead, we're going to get some weird result.

Let me explain this more clearly using an analogy. Assume you wake up at an interval to look at the sky. In the end, you want to conclude the color of the sky. If the interval is very short, let's say 5 minutes, you will be able to see all different colors of the sky. In the nighttime, the sky is very dark. During the daytime, it's bright, sometimes it's blue, sometimes it's gray. During the sunset, the color can be orange. You will be able to see all color variants of the sky. However, if your interval is very long, you wake up once every 24 hours. And you happen to wake up during the nighttime, then all you can see is the dark sky. And you will incorrectly conclude that the sky's color is always dark, which is wrong.

So a similar thing could happen for texture map. If we're sampling the texture map at a very low density, then we will get a very weird looking image. when will the sampling density be low? Well, for example, if you apply a texture map on a 3D plane, and the 3D plane is very away from our camera, and because of the perspective projection, an object that is further away will be projected on the screen into a small size. Because texture map sampling is carried out on each fragment, it could happen that only a few fragments overlap with the 3D plane, which means we're not going to sample the texture map enough. We will end up with a very strange looking image.

So let me actually show you a situation like this with actual code. below is the same shader we've seen before when introducing texture mapping. But instead of using the baboon texture map, this time we're going to use a checkerboard to make the issue more obvious.

An Example of Checker Board
An Example of Checker Board

So with this naive implementation, as you can see, on the near side of the checkerboard, we see clearly the checkerboard pattern. However, on the far side of the checkerboard, we start to see that the pattern becomes stripes. They don't resemble a checkerboard anymore. This is because we're not sampling the texture map enough.

if when we sample fragments, we happen to fall on a black area. We end up getting a lot of black from the texture map.The end result will be a black stripe instead of the alternating black and white color.Similarly, if we happen to sample always on the white area, we're going to get a white stripe without any black.That's why the far side looks like a zebra stripe instead of a checkerboard.

Now to fix this issue, we need to rely on the Mipmap. Given an original image, we're going to gradually shrink its size to make a smaller version of the same image.

An Image to Explain Mipmap Interpolation
An Image to Explain Mipmap Interpolation

When we sample the texture map, we will Based on the distance, choose the most appropriate texture map level. We sample a pixel of color from that level of texture map. The reason being, by choosing a smaller version of the texture map, we essentially mix nearby pixels to get an average color.

In the checkerboard case, when we shrink the size of the checkerboard, we make it a gray color because we essentially mix white and black areas. But it will produce a better result because when the checkerboard is further away, we will naturally see a gray color instead of a zebra stripe.

An Example of Checker Board
An Example of Checker Board

With this way of sampling texture map, we can avoid weird artifacts due to not enough sampling rate.

One difficulty of doing Mipmap with WebGPU is that we have to manually create our Mipmap using a shader.If you come from other graphics API like OpenGL, you probably know that generating Mipmap for texture map is mostly automatic. But for WebGPU, we have to write code. But it's not that difficult. Now let's look at the code side of changes.

        const textureDescriptor = {
+            

1.18 Mipmapping and Anisotropic Filtering

Sampling issue can happen everywhere. in the previous tutorial we talked about the sampling issue of low screen resolution. sampling problem can also happen on texture map sampling. recall in the texture tutorial, we use the function textureSample to sample colors form a texture map. when the texture map is away from the camera, the projected size of the texture map on the screen plane can be very small. when the projected size is very small, compared to the fragment size, we will have texture sampling issue. this can be illustrated by the following:

Insufficient Texture Sampling Rate Results in Artifacts
Insufficient Texture Sampling Rate Results in Artifacts

Assuming we have a checkerboard texture. The bigger squares are the fragments. Again we are using the fragment center as the texture coordinates to sample from the checkerboard texture. only the right most two fragments are black, the rest are white.

Similar to the rasterization issue we saw in the MSAA tutorial. these fragments all have overlapping with both white and black checkers. they should be in a gray color, instead of either black or white.

While using multi-samples per fragment can improve the rendering result, it is very costly. unlike rendering results, which is dynamic, texture map is static. for a static image, there is no need to do run-time super sampling. instead we can do it offline, and save the sampled color in a cache, and read the value in fragment.

in the msaa tutorial, we used extra samples and calculate the averaged color as the final color. an alternative method is down-sizing the texture map to smaller sizes. because down-sizing also involves averaging pixels. and the down-sized texture map caches the sampled color. this method is also called filtering.

It's a wrong belief that a texture map is simply just an image, in fact, a texture map can have multiple levels. In this tutorial, we're going to talk about mipMapping, a solution to use a pyramid of a texture of different sizes to solve the sampling issue.

At each level, we usually have the same image of different resolution with the level 0 being the original resolution. At level 1, we quarter the original image, and so on till the whole image is down sized to a single pixel. We call this the level of details.

The reason that we need multiple resolutions of the same image is to resolve a sampling issue. Let me explain.

We access the texture image through a sampling function. What I mean by sampling is that we're not going to read the entire image as a whole. Instead, we read the image color by color by providing texture coordinates. Because we don't have the holistic view of the image, our sampling density will determine what we see, even the texture image is unchanged.

If our sampling density is very low, we will not be able to reconstruct the original appearance of the original image. Instead, we're going to get some weird result.

Let me explain this more clearly using an analogy. Assume you wake up at an interval to look at the sky. In the end, you want to conclude the color of the sky. If the interval is very short, let's say 5 minutes, you will be able to see all different colors of the sky. In the nighttime, the sky is very dark. During the daytime, it's bright, sometimes it's blue, sometimes it's gray. During the sunset, the color can be orange. You will be able to see all color variants of the sky. However, if your interval is very long, you wake up once every 24 hours. And you happen to wake up during the nighttime, then all you can see is the dark sky. And you will incorrectly conclude that the sky's color is always dark, which is wrong.

So a similar thing could happen for texture map. If we're sampling the texture map at a very low density, then we will get a very weird looking image. when will the sampling density be low? Well, for example, if you apply a texture map on a 3D plane, and the 3D plane is very away from our camera, and because of the perspective projection, an object that is further away will be projected on the screen into a small size. Because texture map sampling is carried out on each fragment, it could happen that only a few fragments overlap with the 3D plane, which means we're not going to sample the texture map enough. We will end up with a very strange looking image.

So let me actually show you a situation like this with actual code. below is the same shader we've seen before when introducing texture mapping. But instead of using the baboon texture map, this time we're going to use a checkerboard to make the issue more obvious.

An Example of Checker Board
An Example of Checker Board

So with this naive implementation, as you can see, on the near side of the checkerboard, we see clearly the checkerboard pattern. However, on the far side of the checkerboard, we start to see that the pattern becomes stripes. They don't resemble a checkerboard anymore. This is because we're not sampling the texture map enough.

if when we sample fragments, we happen to fall on a black area. We end up getting a lot of black from the texture map.The end result will be a black stripe instead of the alternating black and white color.Similarly, if we happen to sample always on the white area, we're going to get a white stripe without any black.That's why the far side looks like a zebra stripe instead of a checkerboard.

Now to fix this issue, we need to rely on the Mipmap. Given an original image, we're going to gradually shrink its size to make a smaller version of the same image.

An Image to Explain Mipmap Interpolation
An Image to Explain Mipmap Interpolation

When we sample the texture map, we will Based on the distance, choose the most appropriate texture map level. We sample a pixel of color from that level of texture map. The reason being, by choosing a smaller version of the texture map, we essentially mix nearby pixels to get an average color.

In the checkerboard case, when we shrink the size of the checkerboard, we make it a gray color because we essentially mix white and black areas. But it will produce a better result because when the checkerboard is further away, we will naturally see a gray color instead of a zebra stripe.

An Example of Checker Board
An Example of Checker Board

With this way of sampling texture map, we can avoid weird artifacts due to not enough sampling rate.

One difficulty of doing Mipmap with WebGPU is that we have to manually create our Mipmap using a shader.If you come from other graphics API like OpenGL, you probably know that generating Mipmap for texture map is mostly automatic. But for WebGPU, we have to write code. But it's not that difficult. Now let's look at the code side of changes.

        const textureDescriptor = {
             size: { width: imgBitmap.width, height: imgBitmap.height },
             format: 'rgba8unorm',
             mipLevelCount: Math.ceil(Math.log2(Math.max(imgBitmap.width, imgBitmap.height))),
@@ -317,6 +305,26 @@ 

1.18 Mipmapping and Anisotropic Filtering

In this tutorial, we're go

@@ -229,6 +217,26 @@

1.17 Multi-Sample Anti-Aliasing (MSAA)

We perceive the world through

@@ -247,6 +235,26 @@

1.10 Triangle Strips

Up until now, we've exclusively used triangle l

@@ -311,6 +299,26 @@

1.15 Understanding Normals

In this tutorial, we explore into the con

@@ -248,6 +236,26 @@

1.6 Understanding Uniforms

In this tutorial, we'll explore the conce

@@ -316,6 +304,26 @@

1.4 Using Different Vertex Colors

In this tutorial, we're making ano

@@ -322,6 +310,26 @@

1.8 Utilizing Transformation Matrices

In this tutorial, we'll revisi

@@ -360,6 +348,26 @@

1.7 Working with Textures

Having established a foundation in uniform

@@ -326,6 +314,26 @@

4.0 Prefix Sum

The first tutorial will cover calculating the prefix

@@ -561,6 +549,26 @@

4.1 Radix Sort

Prefix sum is a crucial foundation for numerous paral

@@ -512,6 +500,26 @@

4.2 Reaction Diffusion

As a third example, let's explore a scenario

@@ -354,6 +342,26 @@

3.1 Arcball Camera Control

another common interaction we want to hav

@@ -260,6 +248,26 @@

3.0 Canvas Resizing

At this point, all of our samples are rendered i

@@ -197,6 +185,26 @@
@@ -436,6 +424,26 @@

3.2 Object Picking

Another important way of interaction is picking o

@@ -332,6 +320,26 @@

3.3 Saving Images and Videos

In this tutorial, we are going to look

@@ -236,6 +224,26 @@

3.4 Using Web Workers

WebGPU can be executed in a worker to further

@@ -197,6 +185,26 @@

0.0 The GPU Driver

After graduating from school, I landed my first j

@@ -197,6 +185,26 @@

0.1 The GPU Pipeline

Previously, we learned how applications connect

@@ -184,6 +172,26 @@

WebGPU Unleashed: A Practical Tutorial