Skip to content

Commit

Permalink
load embedded texture
Browse files Browse the repository at this point in the history
  • Loading branch information
WinteryFox committed Dec 14, 2023
1 parent a158160 commit 8a4a1ea
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 41 deletions.
90 changes: 57 additions & 33 deletions src/engine/vk/VkImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ namespace Vixen::Vk {
const uint8_t mipLevels
) : device(device),
allocation(VK_NULL_HANDLE),
image(VK_NULL_HANDLE),
width(width),
height(height),
format(format),
usageFlags(usageFlags),
layout(VK_IMAGE_LAYOUT_UNDEFINED),
usageFlags(usageFlags),
image(VK_NULL_HANDLE),
format(format),
mipLevels(mipLevels) {
const VkImageCreateInfo imageCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
Expand All @@ -34,7 +34,7 @@ namespace Vixen::Vk {
.arrayLayers = 1,
.samples = samples,
.tiling = tiling,
.usage = usageFlags,
.usage = usageFlags | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
Expand Down Expand Up @@ -101,50 +101,38 @@ namespace Vixen::Vk {
if (!bitmap)
error("Failed to load image from file \"{}\"", path);

const auto& converted = FreeImage_ConvertTo32Bits(bitmap);
if (!converted)
error("Failed to convert image to 32 bits");

const auto& width = FreeImage_GetWidth(converted);
const auto& height = FreeImage_GetHeight(converted);
const auto& bitsPerPixel = FreeImage_GetBPP(converted);
const auto& pixels = FreeImage_GetBits(converted);

const VkDeviceSize size = width * height * (bitsPerPixel / 8);

auto staging = VkBuffer(device, Buffer::Usage::UNIFORM | Buffer::Usage::TRANSFER_SRC, size);
staging.write(reinterpret_cast<char*>(pixels), size, 0);
return from(device, bitmap);
}

FreeImage_Unload(converted);
FreeImage_Unload(bitmap);
VkImage VkImage::from(const std::shared_ptr<Device>& device, const std::string& format, const std::byte* data,
const uint32_t size) {
// TODO: Add some way to detect the format
const auto& memory = FreeImage_OpenMemory((BYTE*)data, size);
if (!memory)
error("Failed to open image from memory");

FreeImage_DeInitialise();
const auto& bitmap = FreeImage_LoadFromMemory(FreeImage_GetFIFFromFormat(format.c_str()), memory, 0);
if (!bitmap)
throw std::runtime_error("Failed to load image from memory");

VkFormat f;
switch (bitsPerPixel) {
case 24:
f = VK_FORMAT_R8G8B8_SRGB;
break;
case 32:
f = VK_FORMAT_R8G8B8A8_SRGB;
break;
default:
throw std::runtime_error("Failed to determine format");
}
return from(device, bitmap);
}

VkImage VkImage::from(const std::shared_ptr<Device>& device, const VkBuffer& buffer, const uint32_t width,
const uint32_t height, const VkFormat format) {
auto image = VkImage(
device,
width,
height,
VK_SAMPLE_COUNT_1_BIT,
f,
format,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1
);

image.transition(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
image.copyFrom(staging);
image.copyFrom(buffer);
image.transition(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);

return image;
Expand Down Expand Up @@ -258,6 +246,42 @@ namespace Vixen::Vk {
return mipLevels;
}

VkImage VkImage::from(const std::shared_ptr<Device>& device, FIBITMAP* bitmap) {
const auto& converted = FreeImage_ConvertTo32Bits(bitmap);
if (!converted)
error("Failed to convert image to 32 bits");

const auto& width = FreeImage_GetWidth(converted);
const auto& height = FreeImage_GetHeight(converted);
const auto& bitsPerPixel = FreeImage_GetBPP(converted);
const auto& pixels = FreeImage_GetBits(converted);

const VkDeviceSize size = width * height * (bitsPerPixel / 8);

auto staging = VkBuffer(device, Buffer::Usage::UNIFORM | Buffer::Usage::TRANSFER_SRC, size);
staging.write(reinterpret_cast<char*>(pixels), size, 0);

FreeImage_Unload(converted);
FreeImage_Unload(bitmap);

FreeImage_DeInitialise();

VkFormat f;
// TODO: This will need a better implementation to detect the exact format later
switch (bitsPerPixel) {
case 24:
f = VK_FORMAT_B8G8R8_SRGB;
break;
case 32:
f = VK_FORMAT_B8G8R8A8_SRGB;
break;
default:
throw std::runtime_error("Failed to determine format");
}

return from(device, staging, width, height, f);
}

VkFormat VkImage::getFormat() const {
return format;
}
Expand Down
8 changes: 8 additions & 0 deletions src/engine/vk/VkImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ namespace Vixen::Vk {

static VkImage from(const std::shared_ptr<Device>& device, const std::string& path);

static VkImage from(const std::shared_ptr<Device>& device, const std::string& format, const std::byte* data, uint32_t size);

static VkImage from(const std::shared_ptr<Device>& device, const VkBuffer& buffer, uint32_t width,
uint32_t height, VkFormat format);

void transition(VkImageLayout newLayout);

void copyFrom(const VkBuffer& buffer);
Expand All @@ -63,5 +68,8 @@ namespace Vixen::Vk {
[[nodiscard]] const std::shared_ptr<Device>& getDevice() const;

[[nodiscard]] uint8_t getMipLevels() const;

private:
static VkImage from(const std::shared_ptr<Device>& device, FIBITMAP* bitmap);
};
}
41 changes: 33 additions & 8 deletions src/engine/vk/test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,19 @@ int main() {
Assimp::Importer importer;
const auto& scene = importer.ReadFile("../../src/engine/vk/test/vikingroom.glb",
aiProcessPreset_TargetRealtime_Fast);
if (nullptr == scene)
if (!scene)
throw std::runtime_error("Failed to load model from file");

const auto& mesh = scene->mMeshes[0];
const auto& hasColors = mesh->HasVertexColors(0);
const auto& hasUvs = mesh->HasTextureCoords(0);

std::vector<Vertex> vertices(mesh->mNumVertices);
for (uint32_t i = 0; i < mesh->mNumVertices; i++) {
const auto& vertex = mesh->mVertices[i];
const auto& color = mesh->HasVertexColors(i) ? *mesh->mColors[i] : aiColor4D{1.0f, 1.0f, 1.0f, 1.0f};
const auto& uv = mesh->HasTextureCoords(i) ? *mesh->mTextureCoords[i] : aiVector3D{0.0f, 0.0f, 0.0f};
// TODO: Instead of storing default values for each vertex where a color or UV is missing, we should compact this down to save memory
const auto& color = hasColors ? mesh->mColors[0][i] : aiColor4D{1.0f, 1.0f, 1.0f, 1.0f};
const auto& uv = hasUvs ? mesh->mTextureCoords[0][i] : aiVector3D{1.0f, 1.0f, 1.0f};

vertices[i] = Vertex{
.position = {vertex.x, vertex.y, vertex.z},
Expand All @@ -101,7 +105,7 @@ int main() {

std::vector<uint32_t> indices(mesh->mNumFaces * 3);
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
const auto &face = mesh->mFaces[i];
const auto& face = mesh->mFaces[i];
if (face.mNumIndices != 3) {
spdlog::warn("Skipping face with {} indices", face.mNumIndices);
continue;
Expand All @@ -112,6 +116,27 @@ int main() {
indices[i * 3 + 2] = face.mIndices[2];
}

aiString path;
scene->mMaterials[mesh->mMaterialIndex]->GetTexture(aiTextureType_DIFFUSE, 0, &path);

const auto& texture = scene->GetEmbeddedTexture(path.C_Str());
assert(texture != nullptr && "Texture is nullptr");

std::shared_ptr<Vixen::Vk::VkImage> image;
if (texture->mHeight != 0) {
image = nullptr; // TODO
}
else {
image = std::make_shared<Vixen::Vk::VkImage>(
Vixen::Vk::VkImage::from(
vixen.device,
texture->achFormatHint,
reinterpret_cast<const std::byte*>(texture->pcData),
texture->mWidth
)
);
}

const auto buffer = Vixen::Vk::VkBuffer::stage(
vixen.device,
Vixen::Buffer::Usage::VERTEX |
Expand Down Expand Up @@ -162,8 +187,8 @@ int main() {
auto mvp = Vixen::Vk::VkDescriptorSet(vixen.device, descriptorPool, *program.getDescriptorSetLayout());
mvp.updateUniformBuffer(0, uniformBuffer, 0, uniformBuffer.getSize());

auto image = std::make_shared<Vixen::Vk::VkImage>(
Vixen::Vk::VkImage::from(vixen.device, "../../src/engine/vk/test/texture.jpg"));
auto testImage = std::make_shared<Vixen::Vk::VkImage>(
Vixen::Vk::VkImage::from(vixen.device, std::string("../../src/engine/vk/test/texture.jpg")));
auto view = Vixen::Vk::VkImageView(image, VK_IMAGE_ASPECT_COLOR_BIT);
auto sampler = Vixen::Vk::VkSampler(vixen.device);

Expand All @@ -185,8 +210,8 @@ int main() {
const double& now = glfwGetTime();
double deltaTime = now - lastFrame;
lastFrame = now;
ubo.model = rotate(ubo.model, static_cast<float>(deltaTime) * glm::radians(90.0f),
glm::vec3(0.0f, 0.0f, 1.0f));
ubo.model = rotate(glm::mat4(1.0f), /*static_cast<float>(deltaTime) **/ glm::radians(90.0f),
glm::vec3(1.0f, 0.0f, 0.0f));
ubo.view = camera.view();
ubo.projection = camera.perspective(
static_cast<float>(vixen.swapchain.getExtent().width) /
Expand Down
Binary file modified src/engine/vk/test/vikingroom.glb
Binary file not shown.

0 comments on commit 8a4a1ea

Please sign in to comment.