132 lines
6.1 KiB
Plaintext
132 lines
6.1 KiB
Plaintext
////
|
|
- Copyright (c) 2023, Mobica Limited
|
|
-
|
|
- 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.
|
|
-
|
|
////
|
|
= Fragment shader barycentric
|
|
|
|
ifdef::site-gen-antora[]
|
|
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/extensions/fragment_shader_barycentric[Khronos Vulkan samples github repository].
|
|
endif::[]
|
|
|
|
|
|
image::./images/fragment_shader_barycentric_screenshot.png[fragment_shader_barycentric]
|
|
|
|
Fragment shader barycentric feature provides support for accessing the barycentric coordinates (linear and perspective) in the fragment shader and vertex attribute with the `pervertexEXT` decoration.
|
|
|
|
== Overview
|
|
|
|
The https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_fragment_shader_barycentric.html[VK_KHR_fragment_shader_barycentric] extension is based on https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_NV_fragment_shader_barycentric.html[VK_NV_fragment_shader_barycentric].
|
|
|
|
The extension provides access to additional built-in variables and decorations:
|
|
|
|
|===
|
|
| Type | GLSL | SPIR-V
|
|
|
|
| built-in variable
|
|
| in vec3 gl_BaryCoordEXT;
|
|
| BaryCoordKHR
|
|
|
|
| built-in variable
|
|
| in vec3 gl_BaryCoordNoPerspEXT;
|
|
| BaryCoordNoPerspKHR
|
|
|
|
| decoration
|
|
| pervertexEXT
|
|
| perVertexKHR
|
|
|===
|
|
|
|
The built-in fragment shader input variables `gl_BaryCoordEXT` and `gl_BaryCoordNoPerspEXT` are three-component floating-point vectors that provide the barycentric coordinates for the fragment.
|
|
The values for these built-ins are derived as described in https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#interfaces-builtin-variables[the Vulkan API Specifications].
|
|
The built-in variables hold barycentric weights for the fragment produced using:
|
|
|
|
* perspective interpolation: `gl_BaryCoordEXT`
|
|
* linear interpolation: `gl_BaryCoordNoPerspEXT`
|
|
|
|
The fragment shader inputs declared with the `pervertexEXT` decoration get the per-vertex values of the outputs from the previous shader stage declared with the same name.
|
|
Such inputs must be declared as an array, because they have values for each vertex in the input primitive, e.g.
|
|
|
|
----
|
|
layout(location = 0) pervertexEXT in vec4 perVertexAttr[];
|
|
----
|
|
|
|
Each array element corresponds to one of the vertices of the primitive that produced the fragment.
|
|
The order of the vertices is defined in https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#primsrast-barycentric[the Vulkan API Specifications].
|
|
Interpolated values are not available for inputs declared with the https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#shaders-interpolation-decorations-pervertexkhr[`pervertexEXT`].
|
|
|
|
The fragment shader barycentric sample demonstrates feature usage by applying different effects on a cube.
|
|
The effects are implemented using the `pervertexEXT` decoration and built-in variables `gl_BaryCoordEXT` and `gl_BaryCoordNoPerspEXT`.
|
|
|
|
The following effects are available from the GUI:
|
|
|
|
* Color interpolation - Demonstrates color interpolation using barycentric coordinates and information about color in vertices of the triangle (passed as `pervertexEXT` variable from the vertex shader).
|
|
* Perspective vs non-perspective - Demonstrates the difference between barycentric perspective and non-perspective coordinates.
|
|
* Wireframe - Demonstrates rendering a wireframe using barycentric coordinates.
|
|
* Interpolate to mass center - Demonstrates color interpolation to the triangle's center of mass using barycentric coordinates.
|
|
* Barycoord texture - Demonstrates the modification of a texture using barycentric coordinates.
|
|
|
|
== Enabling the Extension
|
|
|
|
Enabling the fragment shader barycentric feature is done using the https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR.html[`VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR`] structure, where `fragmentShaderBarycentric` indicates barycentric support in fragment shaders.
|
|
The structure should be passed to `vkGetPhysicalDeviceFeatures2` in the pNext member of the https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceFeatures2.html[`VkPhysicalDeviceFeatures2`] structure.
|
|
|
|
[,C++]
|
|
----
|
|
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR requested_fragment_shader_barycentric_features
|
|
requested_fragment_shader_barycentric_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR;
|
|
requested_fragment_shader_barycentric_features.fragmentShaderBarycentric = VK_TRUE;
|
|
----
|
|
|
|
In the sample it is done in the `FragmentShaderBarycentric::request_gpu_features` method using the template function `vkb::PhysicalDevice::request_extension_features` provided by the Vulkan-Samples framework.
|
|
|
|
== Shaders
|
|
|
|
=== Vertex shader
|
|
|
|
In the vertex shader a variable `outColor` is declared.
|
|
It is used in the fragment shader with the `pervertexEXT` decoration:
|
|
|
|
[,GLSL]
|
|
----
|
|
layout (location = 0) out vec3 outColor;
|
|
----
|
|
|
|
=== Fragment shader
|
|
|
|
In the fragment shader the required feature is defined:
|
|
|
|
[,GLSL]
|
|
----
|
|
#extension GL_EXT_fragment_shader_barycentric : require
|
|
----
|
|
|
|
The color input variable is declared with the `pervertexEXT` decoration and as a matrix (it contains color for three vertices of the triangle for each processed fragment):
|
|
|
|
[,GLSL]
|
|
----
|
|
layout (location = 0) in pervertexEXT vec3 inColor[];
|
|
----
|
|
|
|
Depending on the effect chosen in the GUI `outColor` is calculated differently in the switch-case statement, e.g.
|
|
for color interpolation using barycentric perspective coordinates:
|
|
|
|
[,GLSL]
|
|
----
|
|
outColor.rgb = inColor[0].rgb * gl_BaryCoordEXT.x +
|
|
inColor[1].rgb * gl_BaryCoordEXT.y +
|
|
inColor[2].rgb * gl_BaryCoordEXT.z;
|
|
----
|