90 lines
3.6 KiB
Plaintext
90 lines
3.6 KiB
Plaintext
////
|
|
- Copyright (c) 2023, Google
|
|
-
|
|
- SPDX-License-Identifier: Apache-2.0
|
|
-
|
|
- Licensed under the Apache License, Version 2.0 the "License";
|
|
- you may not use this file except in compliance with the License.
|
|
- You may obtain a copy of the License at
|
|
-
|
|
- http://www.apache.org/licenses/LICENSE-2.0
|
|
-
|
|
- Unless required by applicable law or agreed to in writing, software
|
|
- distributed under the License is distributed on an "AS IS" BASIS,
|
|
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
- See the License for the specific language governing permissions and
|
|
- limitations under the License.
|
|
-
|
|
////
|
|
|
|
= Order-independent transparency with per-pixel ordered linked lists
|
|
|
|
ifdef::site-gen-antora[]
|
|
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/api/oit_linked_lists[Khronos Vulkan samples github repository].
|
|
endif::[]
|
|
|
|
:pp: {plus}{plus}
|
|
|
|
image::./images/sample.png[Sample]
|
|
|
|
== Overview
|
|
|
|
This sample implements an order-independent transparency (OIT) algorithm using per-pixel ordered linked lists.
|
|
It renders 64 spheres with random color and opacity (from 0.2 to 1.0).
|
|
It produces pixel-perfect results.
|
|
|
|
== Algorithm
|
|
|
|
The OIT algorithm consists of two passes: the _gather_ pass and the _combine_ pass.
|
|
|
|
During the gather pass, the transparent geometry is rendered into per-pixel order linked lists.
|
|
Each fragment color and depth is pushed into the linked list associated with its destination pixel.
|
|
The linked lists head are stored into a storage image that is the size of the screen.
|
|
The fragment data (color and depth) is stored into a storage buffer shared by all linked lists.
|
|
|
|
The _combine_ pass is a screen-space operation.
|
|
For each pixel, it sorts the fragments stored in the linked list of that pixel.
|
|
It then alpha blends (in the shader code) them to produce the final transparent color and coverage.
|
|
Finally, it alpha blends (via the fixed blend function) the transparent color into the backbuffer.
|
|
|
|
The algorithm can produce pixel-perfect results, even with intersecting geometry.
|
|
However, there is a catch.
|
|
To keep performance high, the maximum number of sorted fragments per-pixel is limited to 16.
|
|
For more than 16 fragments, the algorithm does its best effort to blend the extra fragments, but the results might be inaccurate.
|
|
This is well enough for the sample, due to the way the objects are placed in the scene.
|
|
In general, there is a trade-off between performance and correctness.
|
|
To keep occupancy high, the maximum number of sorted fragments (`SORTED_FRAGMENT_MAX_COUNT` in `combine.frag`) should be kept low.
|
|
To get correct results in every situation, that same number should be as high as possible.
|
|
The artifacts resulting from a low number of sorted fragments per pixel can be observed by using the `Sorted fragments per pixel` option.
|
|
|
|
== Options
|
|
|
|
[cols="2,4,4"]
|
|
|===
|
|
| Option | Description | Comments
|
|
|
|
| Sort fragments
|
|
| Enable fragment sorting in the combine pass
|
|
| This option, when disabled, is meant to demonstrate the visual issues that occur with non-sorted transparent geometry.
|
|
|
|
| Camera auto-rotation
|
|
| Enable the automatic rotation of the camera
|
|
|
|
|
|
|
| Sorted fragments per pixel
|
|
| Specify the maximum number of fragments sorted per pixel
|
|
| This option, when set to a low number (e.g. 4), highlights the main weakness of the algorithm.
|
|
|
|
| Background grayscale
|
|
| Specify the grayscale value by which the background color is multiplied (0.0 to 1.0)
|
|
|
|
|
|===
|
|
|
|
== Tests
|
|
|
|
This sample was tested on Windows.
|
|
The validation layers were enabled and all reported issues were fixed.
|
|
The sample was also tested on Linux during development.
|
|
Both systems featured an AMD GPU.
|
|
|