shader가 image를 읽을 때는
2가지 방법이 있다.
The first is to perform a raw load, which directly reads formatted or unformatted data from a specific location in the image,
and the second is to sample the image using a sampler.
여기서 두번째 방법에 대해 공부해보자.
image를 샘플링(sampling)한다는 게 뭘까?
바로 다음 설명을 보면 어느정도 예상이 가능하다.
Sampling can include operations such as
performing basic transformations on the image coordinates
or filtering texels to smooth the image data returned to the shader.
image 좌표계에서 기본적인 변환을 수행한다거나,
shader가 image를 사용하기전에 적절한 filtering (eg. smoothing by Gaussian filter)을
수행하는 걸로 이해가 된다.
자, sampler에 대한 직관적인 이해가 되었다면
이제 어떻게 사용되고 있는지 확인해보자.
우선 shader는 자원에 접근하기 위한 handler로써
descriptor를 사용하고,
각각의 descriptor는 descriptor set에 묶여있다.
// Sets
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
// Image descriptors for the offscreen color attachments
VkDescriptorImageInfo texDescriptorPosition =
vks::initializers::descriptorImageInfo(
colorSampler,
offScreenFrameBuf.position.view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VkDescriptorImageInfo texDescriptorNormal =
vks::initializers::descriptorImageInfo(
colorSampler,
offScreenFrameBuf.normal.view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VkDescriptorImageInfo texDescriptorAlbedo =
vks::initializers::descriptorImageInfo(
colorSampler,
offScreenFrameBuf.albedo.view,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Deferred composition
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets.composition));
writeDescriptorSets = {
// Binding 1 : Position texture target
vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &texDescriptorPosition),
// Binding 2 : Normals texture target
vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &texDescriptorNormal),
// Binding 3 : Albedo texture target
vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3, &texDescriptorAlbedo),
// Binding 4 : Fragment shader uniform buffer
vks::initializers::writeDescriptorSet(descriptorSets.composition, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4, &uniformBuffers.composition.descriptor),
};
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
descriptor set에 각 descriptor가 어떤 건지 명시해주는 역할을 하는 구조체인
VkWriteDescriptorSet은 다음과 같이 생겼다.
typedef struct VkWriteDescriptorSet {
VkStructureType sType;
const void* pNext;
VkDescriptorSet dstSet;
uint32_t dstBinding;
uint32_t dstArrayElement;
uint32_t descriptorCount;
VkDescriptorType descriptorType;
const VkDescriptorImageInfo* pImageInfo;
const VkDescriptorBufferInfo* pBufferInfo;
const VkBufferView* pTexelBufferView;
} VkWriteDescriptorSet;
여기서 VkDescriptorImageInfo, VkDescriptorBufferInfo 은 어떻게 생겼는지 다시 따라가보자.
typedef struct VkDescriptorImageInfo {
VkSampler sampler;
VkImageView imageView;
VkImageLayout imageLayout;
} VkDescriptorImageInfo;
typedef struct VkDescriptorBufferInfo {
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize range;
} VkDescriptorBufferInfo;
VkDescriptorImageInfo의 멤버로 드디어
VkSampler 타입의 sampler가 나왔다 !!
위 코드 블럭에서는 3개의 descriptor가 모두 같은 sampler인 "colorSampler"를 사용한다.
이 친구는 어떻게 만들어졌는지 또다시 코드를 추적해오자.
// Create sampler to sample from the color attachments
VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo();
sampler.magFilter = VK_FILTER_NEAREST;
sampler.minFilter = VK_FILTER_NEAREST;
sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler.addressModeV = sampler.addressModeU;
sampler.addressModeW = sampler.addressModeU;
sampler.mipLodBias = 0.0f;
sampler.maxAnisotropy = 1.0f;
sampler.minLod = 0.0f;
sampler.maxLod = 1.0f;
sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &colorSampler));
앞서 sampler가 어떤 일을 하는지 살펴보았던 대로,
filtering과 관련된 정보들을 확인할 수 있다.
Reference
Vulkan Programming Guide 2016
Vulkan 1.4.304 - A specification (with all ratified extensions)
https://github.com/SaschaWillems/Vulkan - project 'deferred'
'Graphics' 카테고리의 다른 글
[Vulkan] Descriptor, descriptor set, descriptor layout의 관계 (0) | 2024.07.29 |
---|---|
[Unity] 공놀이 게임 만들기 (0) | 2023.07.12 |
[이론] Single Buffering / Double Buffering / VSync / Triple Buffering (0) | 2023.03.13 |
* 일반적인 Rendering Pipeline 정리 (0) | 2023.03.13 |
[GLUT/openGL] glViewport 함수 (0) | 2023.03.08 |