You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 10_Multisampling.md
+27-15Lines changed: 27 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,21 +1,31 @@
1
1
## Introduction
2
-
Our program can now load and render 3D models. In this chapter, we will add one more feature, mipmap generation. Mipmaps are widely used in games and rendering software, and Vulkan gives us complete control over how they are created.
3
2
4
-
Mipmaps are precalculated, downscaled versions of an image. Each new image is half the width and height of the previous one. Mipmaps are used as a form of *Level of Detail* or *LOD.* Objects that are far away from the camera will sample their textures from the smaller mip images. Using smaller images increases the rendering speed and avoids artifacts such as [Moiré patterns](https://en.wikipedia.org/wiki/Moir%C3%A9_pattern). An example of what mipmaps look like:
3
+
Our program can now load multiple levels of detail for textures which fixes artifacts when rendering objects far away from the viewer. The image is now a lot smoother, however on closer inspection you will notice jagged saw-like patterns along the edges of drawn geometric shapes. This is especially visible in one of our early programs when we rendered a quad:
5
4
6
-

5
+

7
6
8
-
## Checking for multisampling support
7
+
This undesired effect is called "aliasing" and it's a result of a limited numbers of pixels that are available for rendering. Since there are no displays out there with unlimited resolution, it will be always visible to some extent. There's a number of ways to fix this and in this chapter we'll focus on one of the more popular ones: [Multisample anti-aliasing](https://en.wikipedia.org/wiki/Multisample_anti-aliasing) (MSAA).
9
8
10
-
First, add a class member that will store the number of samples used by the renderer. This number will be used in various places in our code:
9
+
In ordinary rendering, the pixel color is determined based on a single sample point which in most cases is the center of target pixel on screen. If part of the drawn line passes through a certain pixel but doesn't cover the sample point, that pixel will be left blank, leading to the jagged "staircase" effect.
10
+
11
+

12
+
13
+
What MSAA does is it uses multiple sample points per pixel (hence the name) to determine its final color. As one might expect, more samples lead to better results, however it is also more computationally expensive.
14
+
15
+
In our implementation, we will focus on using the maximum available sample count. Depending on your application this may not always be the best approach and it might be better to use less samples for the sake of higher performance if the final result meets your quality demands.
16
+
17
+
18
+
## Getting available sample count
19
+
20
+
Let's start off by determining how many samples our hardware can use. Most modern GPUs support at least 8 samples but this number is not guaranteed to be the same everywhere. We'll keep track of it by adding a new class member:
We now need to determine what is the maximum number of samples supported by the hardware. This information can be extracted from `VkPhysicalDeviceProperties` associated with our selected physical device. We're using a depth buffer, so we have to take into account the sample count for both color and depth - the lower number will be the maximum we can support. If the hardware supports only one sample (unlikely on modern graphics cards) the final image will look unchanged.
28
+
The exact maximum sample count can be extracted from `VkPhysicalDeviceProperties` associated with our selected physical device. We're using a depth buffer, so we have to take into account the sample count for both color and depth - the lower number will be the maximum we can support. If the hardware supports only one sample the final image will look unchanged. Add a function that will fetch this information for us:
19
29
20
30
```c++
21
31
VkSampleCountFlagBits getMaxUsableSampleCount() {
@@ -48,7 +58,7 @@ void pickPhysicalDevice() {
48
58
}
49
59
```
50
60
51
-
Next, update `createImage`functions to allow us to specify the number of samples by adding a `numSmaples` parameter - this will become important later:
61
+
Next, update `createImage`function to allow us to specify the number of used samples by adding a `numSmaples` parameter - this will become important later:
For now, update all calls to these functions using `VK_SAMPLE_COUNT_1_BIT` - we will be replacing this with proper values as we progress with implementation:
70
+
For now, update all calls to this function using `VK_SAMPLE_COUNT_1_BIT` - we will be replacing this with proper values as we progress with implementation:
Multisampling requires additional render targets. Add following class members:
80
+
In MSAA, each pixel is sampled in an offscreen buffer which is then rendered to the screen. These new buffers are slightly different from regular images we've been rendering to - they have to be able to store more than one sample per pixel. Once a multisampled buffer is created, it has to be attached to the default framebuffer (which stores only a single sample per pixel). This is why we have to create additional render targets and modify our current drawing process. Add following class members:
71
81
72
82
```c++
73
83
...
@@ -81,7 +91,7 @@ VkImageView depthMsaaImageView;
81
91
...
82
92
```
83
93
84
-
We will now create a multisampled color buffer. Add a `createColorResources` function and note that we're using `msaaSamples` here as a function parameter to `createImage`. We're also using only one mip level, since this buffer will be rendered fullscreen at all times and Vulkan specifications states that an image buffer with sample count greater than 1 can only have a single mip level:
94
+
We will now create a multisampled color buffer. Add a `createColorResources` function and note that we're using `msaaSamples` here as a function parameter to `createImage`. We're also using only one mip level, since this is enforced by the Vulkan specification in case of images with more than one sample per pixel:
85
95
86
96
```c++
87
97
voidcreateColorResources() {
@@ -105,7 +115,7 @@ void initVulkan() {
105
115
}
106
116
```
107
117
108
-
You may notice that the newly created color image transitions from undefined state to `VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL` which is a new case for us to handle. Let's update `transitionImageLayout` function to take this into account:
118
+
You may notice that the newly created color image uses a transition path from `VK_IMAGE_LAYOUT_UNDEFINED` to `VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL` which is a new case for us to handle. Let's update `transitionImageLayout` function to take this into account:
With only a few simple steps we created additional buffers and image views necessary for multsampling - it's now time to put it all together and see the results!
162
+
163
+
## Adding new attachments
152
164
153
-
With only a few simple steps we created additional buffers and image views necessary for multsampling and also determined how many samples we can use on our hardware - it's now time to put it all together and see the results! Let's take care of the render pass first. Modify `createRenderPass` and update color and depth attachment creation info structs:
165
+
Let's take care of the render pass first. Modify `createRenderPass` and update color and depth attachment creation info structs:
154
166
155
167
```c++
156
168
void createRenderPass() {
@@ -188,7 +200,7 @@ Apart from the obvious change that tells the attachments to use more samples, yo
188
200
...
189
201
```
190
202
191
-
Add atachment reference for color:
203
+
We now have to add new color resolve attachment to the subpass. Create a new attachment reference and update the `pResolveAttachments` pointer:
192
204
193
205
```c++
194
206
...
@@ -208,7 +220,7 @@ Update render pass info struct with new attachments:
208
220
...
209
221
```
210
222
211
-
With render pass in place, modify `createFrameBuffers` and add additional attachments:
223
+
With render pass in place, modify `createFrameBuffers` and add new image views to the list:
0 commit comments