mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
add support for different texture samplers
This commit is contained in:
parent
424d22cf69
commit
15d62ecf6b
@ -47,7 +47,7 @@ namespace engine {
|
||||
|
||||
/* this descriptor set is bound per-material */
|
||||
const gfx::DescriptorSetLayout* materialSetLayout;
|
||||
const gfx::Sampler* materialSetSampler;
|
||||
std::unordered_map<gfx::SamplerInfo, const gfx::Sampler*> samplers{};
|
||||
};
|
||||
|
||||
class Application {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
|
||||
// Enums and structs for the graphics abstraction
|
||||
|
||||
@ -70,17 +71,11 @@ namespace engine::gfx {
|
||||
FLOAT4
|
||||
};
|
||||
|
||||
enum class TextureFilter {
|
||||
enum class Filter : int {
|
||||
LINEAR,
|
||||
NEAREST,
|
||||
};
|
||||
|
||||
enum class MipmapSetting {
|
||||
OFF,
|
||||
NEAREST,
|
||||
LINEAR,
|
||||
};
|
||||
|
||||
enum class DescriptorType {
|
||||
UNIFORM_BUFFER,
|
||||
COMBINED_IMAGE_SAMPLER,
|
||||
@ -123,4 +118,35 @@ namespace engine::gfx {
|
||||
ShaderStageFlags::Flags stageFlags = 0;
|
||||
};
|
||||
|
||||
struct SamplerInfo {
|
||||
Filter minify;
|
||||
Filter magnify;
|
||||
Filter mipmap;
|
||||
bool anisotropicFiltering;
|
||||
|
||||
bool operator==(const SamplerInfo&) const = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct std::hash<engine::gfx::SamplerInfo>
|
||||
{
|
||||
std::size_t operator()(const engine::gfx::SamplerInfo& k) const
|
||||
{
|
||||
using std::hash;
|
||||
|
||||
size_t h1 = hash<int>()(static_cast<int>(k.minify));
|
||||
size_t h2 = hash<int>()(static_cast<int>(k.magnify));
|
||||
size_t h3 = hash<int>()(static_cast<int>(k.mipmap));
|
||||
size_t h4 = hash<bool>()(k.anisotropicFiltering);
|
||||
|
||||
return ((h1 & 0xFF) << 24) |
|
||||
((h2 & 0xFF) << 16) |
|
||||
((h3 & 0xFF) << 8) |
|
||||
((h4 & 0xFF) << 0);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -52,7 +52,7 @@ namespace engine {
|
||||
gfx::Image* createImage(uint32_t w, uint32_t h, const void* imageData);
|
||||
void destroyImage(const gfx::Image* image);
|
||||
|
||||
gfx::Sampler* createSampler();
|
||||
const gfx::Sampler* createSampler(const gfx::SamplerInfo& info);
|
||||
void destroySampler(const gfx::Sampler* sampler);
|
||||
|
||||
uint64_t getFrameCount();
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace engine {
|
||||
struct RenderData;
|
||||
}
|
||||
|
||||
namespace engine::resources {
|
||||
|
||||
class Texture {
|
||||
@ -16,7 +20,7 @@ public:
|
||||
ANISOTROPIC,
|
||||
};
|
||||
|
||||
Texture(GFXDevice* gfxDevice, const gfx::DescriptorSetLayout* materialSetLayout, const gfx::Sampler* sampler, const std::string& path, Filtering filtering, bool useMipmaps, bool useLinearMagFilter);
|
||||
Texture(RenderData& renderData, const std::string& path, Filtering filtering);
|
||||
~Texture();
|
||||
Texture(const Texture&) = delete;
|
||||
Texture& operator=(const Texture&) = delete;
|
||||
|
@ -111,7 +111,6 @@ namespace engine {
|
||||
binding0.stageFlags = gfx::ShaderStageFlags::FRAGMENT;
|
||||
}
|
||||
renderData.materialSetLayout = gfx()->createDescriptorSetLayout(materialSetBindings);
|
||||
renderData.materialSetSampler = gfx()->createSampler();
|
||||
|
||||
// default resources
|
||||
{
|
||||
@ -144,13 +143,9 @@ namespace engine {
|
||||
}
|
||||
{
|
||||
auto whiteTexture = std::make_unique<resources::Texture>(
|
||||
gfx(),
|
||||
renderData.materialSetLayout,
|
||||
renderData.materialSetSampler,
|
||||
renderData,
|
||||
getResourcePath("engine/textures/white.png"),
|
||||
resources::Texture::Filtering::OFF,
|
||||
false,
|
||||
false
|
||||
resources::Texture::Filtering::OFF
|
||||
);
|
||||
getResourceManager<resources::Texture>()->addPersistent("builtin.white", std::move(whiteTexture));
|
||||
}
|
||||
@ -158,7 +153,9 @@ namespace engine {
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
gfx()->destroySampler(renderData.materialSetSampler);
|
||||
for (const auto& [info, sampler] : renderData.samplers) {
|
||||
gfx()->destroySampler(sampler);
|
||||
}
|
||||
gfx()->destroyDescriptorSetLayout(renderData.materialSetLayout);
|
||||
|
||||
gfx()->destroyUniformBuffer(renderData.frameSetUniformBuffer);
|
||||
|
@ -154,15 +154,26 @@ namespace engine {
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] static VkFilter getTextureFilter(gfx::TextureFilter filter)
|
||||
[[maybe_unused]] static VkFilter getFilter(gfx::Filter filter)
|
||||
{
|
||||
switch (filter) {
|
||||
case gfx::TextureFilter::LINEAR:
|
||||
case gfx::Filter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
case gfx::TextureFilter::NEAREST:
|
||||
case gfx::Filter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
}
|
||||
throw std::runtime_error("Unknown texture filter");
|
||||
throw std::runtime_error("Unknown filter");
|
||||
}
|
||||
|
||||
[[maybe_unused]] static VkSamplerMipmapMode getSamplerMipmapMode(gfx::Filter filter)
|
||||
{
|
||||
switch (filter) {
|
||||
case gfx::Filter::LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
case gfx::Filter::NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
}
|
||||
throw std::runtime_error("Unknown filter");
|
||||
}
|
||||
|
||||
[[maybe_unused]] static VkSampleCountFlags getSampleCountFlags(gfx::MSAALevel level)
|
||||
@ -1537,20 +1548,20 @@ namespace engine {
|
||||
delete image;
|
||||
}
|
||||
|
||||
gfx::Sampler *GFXDevice::createSampler()
|
||||
const gfx::Sampler *GFXDevice::createSampler(const gfx::SamplerInfo& info)
|
||||
{
|
||||
gfx::Sampler* out = new gfx::Sampler{};
|
||||
|
||||
VkSamplerCreateInfo samplerInfo{};
|
||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
samplerInfo.magFilter = converters::getFilter(info.magnify);
|
||||
samplerInfo.minFilter = converters::getFilter(info.minify);
|
||||
samplerInfo.mipmapMode = converters::getSamplerMipmapMode(info.mipmap);
|
||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerInfo.mipLodBias = 0.0f;
|
||||
samplerInfo.anisotropyEnable = VK_TRUE;
|
||||
samplerInfo.anisotropyEnable = info.anisotropicFiltering ? VK_TRUE : VK_FALSE;
|
||||
samplerInfo.maxAnisotropy = pimpl->device.properties.limits.maxSamplerAnisotropy;
|
||||
samplerInfo.minLod = 0.0f;
|
||||
samplerInfo.maxLod = VK_LOD_CLAMP_NONE;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "resources/texture.hpp"
|
||||
|
||||
#include "application.hpp"
|
||||
#include "util/files.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
@ -7,58 +8,46 @@
|
||||
|
||||
namespace engine::resources {
|
||||
|
||||
Texture::Texture(GFXDevice* gfxDevice, const gfx::DescriptorSetLayout* materialSetLayout, const gfx::Sampler* sampler, const std::string& path, Filtering filtering, bool useMipmaps, bool useLinearMagFilter)
|
||||
: m_gfxDevice(gfxDevice)
|
||||
Texture::Texture(RenderData& renderData, const std::string& path, Filtering filtering)
|
||||
: m_gfxDevice(renderData.gfxdev.get())
|
||||
{
|
||||
|
||||
int width, height;
|
||||
std::unique_ptr<std::vector<uint8_t>> texbuf = util::readImageFile(path, &width, &height);
|
||||
|
||||
gfx::TextureFilter minFilter = gfx::TextureFilter::NEAREST;
|
||||
gfx::TextureFilter magFilter = gfx::TextureFilter::NEAREST;
|
||||
gfx::MipmapSetting mipmapSetting = gfx::MipmapSetting::OFF;
|
||||
bool anisotropyEnable = false;
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
|
||||
if (useLinearMagFilter) {
|
||||
magFilter = gfx::TextureFilter::LINEAR;
|
||||
} else {
|
||||
magFilter = gfx::TextureFilter::NEAREST;
|
||||
}
|
||||
samplerInfo.magnify = gfx::Filter::LINEAR;
|
||||
|
||||
switch (filtering) {
|
||||
case Filtering::OFF:
|
||||
minFilter = gfx::TextureFilter::NEAREST;
|
||||
mipmapSetting = gfx::MipmapSetting::NEAREST;
|
||||
anisotropyEnable = false;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropicFiltering = false;
|
||||
break;
|
||||
case Filtering::BILINEAR:
|
||||
minFilter = gfx::TextureFilter::LINEAR;
|
||||
mipmapSetting = gfx::MipmapSetting::NEAREST;
|
||||
anisotropyEnable = false;
|
||||
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropicFiltering = false;
|
||||
break;
|
||||
case Filtering::TRILINEAR:
|
||||
minFilter = gfx::TextureFilter::LINEAR;
|
||||
mipmapSetting = gfx::MipmapSetting::LINEAR;
|
||||
anisotropyEnable = false;
|
||||
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||
samplerInfo.anisotropicFiltering = false;
|
||||
break;
|
||||
case Filtering::ANISOTROPIC:
|
||||
minFilter = gfx::TextureFilter::LINEAR;
|
||||
mipmapSetting = gfx::MipmapSetting::LINEAR;
|
||||
anisotropyEnable = true;
|
||||
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||
samplerInfo.anisotropicFiltering = true;
|
||||
}
|
||||
|
||||
if (useMipmaps == false) {
|
||||
mipmapSetting = gfx::MipmapSetting::OFF;
|
||||
if (renderData.samplers.contains(samplerInfo) == false) {
|
||||
renderData.samplers.insert(std::make_pair(samplerInfo, m_gfxDevice->createSampler(samplerInfo)));
|
||||
}
|
||||
|
||||
(void)minFilter;
|
||||
(void)magFilter;
|
||||
(void)mipmapSetting;
|
||||
(void)anisotropyEnable;
|
||||
|
||||
m_image = m_gfxDevice->createImage(width, height, texbuf->data());
|
||||
m_descriptorSet = m_gfxDevice->allocateDescriptorSet(materialSetLayout);
|
||||
m_gfxDevice->updateDescriptorCombinedImageSampler(m_descriptorSet, 0, m_image, sampler);
|
||||
m_descriptorSet = m_gfxDevice->allocateDescriptorSet(renderData.materialSetLayout);
|
||||
m_gfxDevice->updateDescriptorCombinedImageSampler(m_descriptorSet, 0, m_image, renderData.samplers.at(samplerInfo));
|
||||
|
||||
LOG_INFO("Loaded texture: {}, width: {} height: {}", path, width, height);
|
||||
|
||||
|
@ -182,8 +182,8 @@ namespace engine::util {
|
||||
absPath /= texPath.C_Str();
|
||||
try {
|
||||
textures[i] = std::make_shared<resources::Texture>(
|
||||
parent->app()->gfx(), parent->app()->renderData.materialSetLayout, parent->app()->renderData.materialSetSampler, absPath.string(),
|
||||
resources::Texture::Filtering::TRILINEAR, true, true);
|
||||
parent->app()->renderData, absPath.string(),
|
||||
resources::Texture::Filtering::TRILINEAR);
|
||||
} catch (const std::runtime_error&) {
|
||||
textures[i] = parent->app()->getResource<resources::Texture>("builtin.white");
|
||||
}
|
||||
|
@ -84,22 +84,14 @@ void playGame(GameSettings settings)
|
||||
|
||||
/* shared resources */
|
||||
auto grassTexture = std::make_shared<engine::resources::Texture>(
|
||||
app.gfx(),
|
||||
app.renderData.materialSetLayout,
|
||||
app.renderData.materialSetSampler,
|
||||
app.renderData,
|
||||
app.getResourcePath("textures/grass.jpg"),
|
||||
engine::resources::Texture::Filtering::ANISOTROPIC,
|
||||
true,
|
||||
true
|
||||
engine::resources::Texture::Filtering::ANISOTROPIC
|
||||
);
|
||||
auto spaceTexture = std::make_shared<engine::resources::Texture>(
|
||||
app.gfx(),
|
||||
app.renderData.materialSetLayout,
|
||||
app.renderData.materialSetSampler,
|
||||
app.renderData,
|
||||
app.getResourcePath("textures/space2.png"),
|
||||
engine::resources::Texture::Filtering::ANISOTROPIC,
|
||||
true,
|
||||
true
|
||||
engine::resources::Texture::Filtering::ANISOTROPIC
|
||||
);
|
||||
|
||||
/* cube */
|
||||
|
Loading…
Reference in New Issue
Block a user