This commit is contained in:
bailehuni 2024-05-16 01:31:19 +01:00
parent 3692dcf64f
commit 160de92a8c
8 changed files with 125 additions and 125 deletions

View File

@ -29,6 +29,7 @@
#include "scene.h" #include "scene.h"
#include "scene_manager.h" #include "scene_manager.h"
#include "window.h" #include "window.h"
#include "util/gltf_loader.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#include <windows.h> #include <windows.h>
@ -326,19 +327,15 @@ void Application::GameLoop()
ImGui::Checkbox("Show entity hitboxes", &debug_menu_state.show_entity_boxes); ImGui::Checkbox("Show entity hitboxes", &debug_menu_state.show_entity_boxes);
ImGui::Checkbox("Show bounding volumes", &debug_menu_state.show_bounding_volumes); ImGui::Checkbox("Show bounding volumes", &debug_menu_state.show_bounding_volumes);
ImGui::Separator(); ImGui::Separator();
#ifndef _WIN32 if (!scene) ImGui::BeginDisabled();
ImGui::BeginDisabled();
#endif
// load gltf file dialog // load gltf file dialog
if (ImGui::Button("Load glTF")) { if (ImGui::Button("Load glTF")) {
#ifdef _WIN32 #ifdef _WIN32
std::string path = std::filesystem::path(openGLTFDialog()).string(); std::string path = std::filesystem::path(openGLTFDialog()).string();
LOG_ERROR("Not yet implemented!"); util::LoadGLTF(*scene, std::filesystem::path(path).string(), false);
#endif #endif
} }
#ifndef _WIN32 if (!scene) ImGui::EndDisabled();
ImGui::EndDisabled();
#endif
} }
ImGui::End(); ImGui::End();
} }

View File

@ -583,16 +583,17 @@ void GFXDevice::ChangePresentMode(gfx::PresentMode mode)
pimpl->swapchainIsOutOfDate = true; pimpl->swapchainIsOutOfDate = true;
} }
gfx::PresentMode GFXDevice::GetPresentMode() { gfx::PresentMode GFXDevice::GetPresentMode()
{
switch (pimpl->swapchain.presentMode) { switch (pimpl->swapchain.presentMode) {
case VK_PRESENT_MODE_FIFO_KHR: case VK_PRESENT_MODE_FIFO_KHR:
return gfx::PresentMode::kDoubleBufferedVsync; return gfx::PresentMode::kDoubleBufferedVsync;
case VK_PRESENT_MODE_IMMEDIATE_KHR: case VK_PRESENT_MODE_IMMEDIATE_KHR:
return gfx::PresentMode::kDoubleBufferedNoVsync; return gfx::PresentMode::kDoubleBufferedNoVsync;
case VK_PRESENT_MODE_MAILBOX_KHR: case VK_PRESENT_MODE_MAILBOX_KHR:
return gfx::PresentMode::kTripleBuffered; return gfx::PresentMode::kTripleBuffered;
default: default:
throw std::runtime_error("Unknown present mode"); throw std::runtime_error("Unknown present mode");
} }
} }
@ -736,7 +737,7 @@ gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized)
createSwapchain(&pimpl->swapchain, pimpl->swapchainInfo); createSwapchain(&pimpl->swapchain, pimpl->swapchainInfo);
} }
// THIS FUNCTION BLOCKS UNTIL AN IMAGE IS AVAILABLE (it waits for vsync) // THIS FUNCTION BLOCKS UNTIL AN IMAGE IS AVAILABLE (it waits for vsync)
res = vkAcquireNextImageKHR(pimpl->device.device, pimpl->swapchain.swapchain, 1000000000LL, frameData.presentSemaphore, VK_NULL_HANDLE, res = vkAcquireNextImageKHR(pimpl->device.device, pimpl->swapchain.swapchain, 1'000'000'000LL, frameData.presentSemaphore, VK_NULL_HANDLE,
&swapchainImageIndex); &swapchainImageIndex);
if (res != VK_SUBOPTIMAL_KHR && res != VK_ERROR_OUT_OF_DATE_KHR) VKCHECK(res); if (res != VK_SUBOPTIMAL_KHR && res != VK_ERROR_OUT_OF_DATE_KHR) VKCHECK(res);
if (res == VK_ERROR_OUT_OF_DATE_KHR) pimpl->swapchainIsOutOfDate = true; if (res == VK_ERROR_OUT_OF_DATE_KHR) pimpl->swapchainIsOutOfDate = true;
@ -1594,7 +1595,7 @@ void GFXDevice::UpdateDescriptorCombinedImageSampler(const gfx::DescriptorSet* s
assert(image != nullptr); assert(image != nullptr);
assert(sampler != nullptr); assert(sampler != nullptr);
if (pimpl->FRAMECOUNT != 0) abort(); // TODO. This is annoying // if (pimpl->FRAMECOUNT != 0) abort(); // TODO. This is annoying
VkDescriptorImageInfo imageInfo{}; VkDescriptorImageInfo imageInfo{};
imageInfo.sampler = sampler->sampler; imageInfo.sampler = sampler->sampler;
@ -1620,6 +1621,8 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
{ {
assert(initialData != nullptr); assert(initialData != nullptr);
if (pimpl->FRAMECOUNT != 0) abort();
gfx::UniformBuffer* out = new gfx::UniformBuffer{}; gfx::UniformBuffer* out = new gfx::UniformBuffer{};
/* first make staging buffer */ /* first make staging buffer */
@ -1778,7 +1781,7 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu
{ {
assert(imageData != nullptr); assert(imageData != nullptr);
if (pimpl->FRAMECOUNT != 0) abort(); // TODO. This is annoying // if (pimpl->FRAMECOUNT != 0) abort(); // TODO. This is annoying
gfx::Image* out = new gfx::Image{}; gfx::Image* out = new gfx::Image{};

View File

@ -10,125 +10,123 @@
namespace engine { namespace engine {
Font::Font(const std::string& path) { Font::Font(const std::string& path)
font_buffer_ = util::ReadBinaryFile(path); {
font_info_ = std::make_unique<stbtt_fontinfo>(); font_buffer_ = util::ReadBinaryFile(path);
font_info_ = std::make_unique<stbtt_fontinfo>();
if (stbtt_InitFont(font_info_.get(), font_buffer_->data(), 0) == 0) { if (stbtt_InitFont(font_info_.get(), font_buffer_->data(), 0) == 0) {
throw std::runtime_error("Failed to initialise font!"); throw std::runtime_error("Failed to initialise font!");
} }
LOG_DEBUG("Created font: {}", path); LOG_DEBUG("Created font: {}", path);
} }
Font::~Font() { LOG_DEBUG("Destroyed font"); } Font::~Font() { LOG_DEBUG("Destroyed font"); }
std::unique_ptr<std::vector<uint8_t>> Font::GetTextBitmap( std::unique_ptr<std::vector<uint8_t>> Font::GetTextBitmap(const std::string& text, float height_px, int& width_out, int& height_out)
const std::string& text, float height_px, int& width_out, int& height_out) { {
const float sf = stbtt_ScaleForPixelHeight(font_info_.get(), height_px); const float sf = stbtt_ScaleForPixelHeight(font_info_.get(), height_px);
int ascent, descent, line_gap; int ascent, descent, line_gap;
stbtt_GetFontVMetrics(font_info_.get(), &ascent, &descent, &line_gap); stbtt_GetFontVMetrics(font_info_.get(), &ascent, &descent, &line_gap);
struct CharacterRenderInfo { struct CharacterRenderInfo {
int advance; // bitmap advance int advance; // bitmap advance
bool isEmpty; bool isEmpty;
int xoff, yoff, width, height; int xoff, yoff, width, height;
unsigned char* bitmap; unsigned char* bitmap;
}; };
std::vector<CharacterRenderInfo> characterRenderInfos{}; std::vector<CharacterRenderInfo> characterRenderInfos{};
int width = 0; int width = 0;
for (size_t i = 0; i < text.size(); i++) { for (size_t i = 0; i < text.size(); i++) {
const int glyph_index = GetGlyphIndex(static_cast<int>(text.at(i))); const int glyph_index = GetGlyphIndex(static_cast<int>(text.at(i)));
int advanceWidth, leftSideBearing; int advanceWidth, leftSideBearing;
stbtt_GetGlyphHMetrics(font_info_.get(), glyph_index, &advanceWidth, stbtt_GetGlyphHMetrics(font_info_.get(), glyph_index, &advanceWidth, &leftSideBearing);
&leftSideBearing);
if (i == 0 && leftSideBearing < 0) { if (i == 0 && leftSideBearing < 0) {
// if the character extends before the current point // if the character extends before the current point
width -= leftSideBearing; width -= leftSideBearing;
}
width += advanceWidth;
CharacterRenderInfo renderInfo{};
renderInfo.advance = static_cast<int>(static_cast<float>(advanceWidth) * sf);
if (stbtt_IsGlyphEmpty(font_info_.get(), glyph_index) == 0) {
renderInfo.isEmpty = false;
} else {
renderInfo.isEmpty = true;
}
if (!renderInfo.isEmpty) {
renderInfo.bitmap = stbtt_GetGlyphBitmap(
font_info_.get(), sf, sf, glyph_index, &renderInfo.width,
&renderInfo.height, &renderInfo.xoff, &renderInfo.yoff);
}
characterRenderInfos.push_back(renderInfo);
}
const size_t bitmap_width = std::ceil(static_cast<float>(width) * sf);
const size_t bitmap_height =
std::ceil(static_cast<float>(ascent - descent) * sf);
auto bitmap =
std::make_unique<std::vector<uint8_t>>(bitmap_width * bitmap_height * 4);
for (size_t i = 0; i < bitmap->size() / 4; i++) {
bitmap->at(i * 4 + 0) = 0x00;
bitmap->at(i * 4 + 1) = 0x00;
bitmap->at(i * 4 + 2) = 0x00;
bitmap->at(i * 4 + 3) = 0x00;
}
int top_left_x = 0;
for (const auto& renderInfo : characterRenderInfos) {
if (renderInfo.isEmpty == false) {
top_left_x += renderInfo.xoff;
const int top_left_y = static_cast<int>(ascent * sf) + renderInfo.yoff;
const int char_bitmap_width = renderInfo.width;
const int char_bitmap_height = renderInfo.height;
// copy the 8bpp char bitmap to the 4bpp output
for (int y = 0; y < char_bitmap_height; y++) {
for (int x = 0; x < char_bitmap_width; x++) {
const int out_index =
((bitmap_width * (top_left_y + y)) + (top_left_x + x)) * 4;
const uint8_t pixel = renderInfo.bitmap[y * char_bitmap_width + x];
(*bitmap)[out_index + 0] = pixel;
(*bitmap)[out_index + 1] = pixel;
(*bitmap)[out_index + 2] = pixel;
(*bitmap)[out_index + 3] = (pixel == 0x00) ? 0x00 : 0xFF;
} }
} width += advanceWidth;
stbtt_FreeBitmap(renderInfo.bitmap, nullptr); CharacterRenderInfo renderInfo{};
renderInfo.advance = static_cast<int>(static_cast<float>(advanceWidth) * sf);
if (stbtt_IsGlyphEmpty(font_info_.get(), glyph_index) == 0) {
renderInfo.isEmpty = false;
}
else {
renderInfo.isEmpty = true;
}
if (!renderInfo.isEmpty) {
renderInfo.bitmap =
stbtt_GetGlyphBitmap(font_info_.get(), sf, sf, glyph_index, &renderInfo.width, &renderInfo.height, &renderInfo.xoff, &renderInfo.yoff);
}
characterRenderInfos.push_back(renderInfo);
} }
top_left_x += renderInfo.advance - renderInfo.xoff; const size_t bitmap_width = static_cast<size_t>(std::ceil(static_cast<float>(width) * sf));
} const size_t bitmap_height = static_cast<size_t>(std::ceil(static_cast<float>(ascent - descent) * sf));
auto bitmap = std::make_unique<std::vector<uint8_t>>(bitmap_width * bitmap_height * 4);
width_out = bitmap_width; for (size_t i = 0; i < bitmap->size() / 4; i++) {
height_out = bitmap_height; bitmap->at(i * 4 + 0) = 0x00;
return bitmap; bitmap->at(i * 4 + 1) = 0x00;
} bitmap->at(i * 4 + 2) = 0x00;
bitmap->at(i * 4 + 3) = 0x00;
int Font::GetGlyphIndex(int unicode_codepoint) {
if (unicode_to_glyph_.contains(unicode_codepoint)) {
return unicode_to_glyph_.at(unicode_codepoint);
} else {
const int glyph_index =
stbtt_FindGlyphIndex(font_info_.get(), unicode_codepoint);
if (glyph_index == 0) {
throw std::runtime_error("Glyph not found in font!");
} }
unicode_to_glyph_.emplace(std::make_pair(unicode_codepoint, glyph_index));
return glyph_index; int top_left_x = 0;
} for (const auto& renderInfo : characterRenderInfos) {
if (renderInfo.isEmpty == false) {
top_left_x += renderInfo.xoff;
const int top_left_y = static_cast<int>(ascent * sf) + renderInfo.yoff;
const int char_bitmap_width = renderInfo.width;
const int char_bitmap_height = renderInfo.height;
// copy the 8bpp char bitmap to the 4bpp output
for (int y = 0; y < char_bitmap_height; y++) {
for (int x = 0; x < char_bitmap_width; x++) {
const size_t out_index = ((bitmap_width * (static_cast<size_t>(top_left_y) + y)) + (static_cast<size_t>(top_left_x) + x)) * 4;
const uint8_t pixel = renderInfo.bitmap[y * char_bitmap_width + x];
(*bitmap)[out_index + 0] = pixel;
(*bitmap)[out_index + 1] = pixel;
(*bitmap)[out_index + 2] = pixel;
(*bitmap)[out_index + 3] = (pixel == 0x00) ? 0x00 : 0xFF;
}
}
stbtt_FreeBitmap(renderInfo.bitmap, nullptr);
}
top_left_x += renderInfo.advance - renderInfo.xoff;
}
width_out = static_cast<int>(bitmap_width);
height_out = static_cast<int>(bitmap_height);
return bitmap;
} }
} // namespace engine int Font::GetGlyphIndex(int unicode_codepoint)
{
if (unicode_to_glyph_.contains(unicode_codepoint)) {
return unicode_to_glyph_.at(unicode_codepoint);
}
else {
const int glyph_index = stbtt_FindGlyphIndex(font_info_.get(), unicode_codepoint);
if (glyph_index == 0) {
throw std::runtime_error("Glyph not found in font!");
}
unicode_to_glyph_.emplace(std::make_pair(unicode_codepoint, glyph_index));
return glyph_index;
}
}
} // namespace engine

View File

@ -15,7 +15,7 @@ struct Color {
uint8_t r, g, b, a; uint8_t r, g, b, a;
Color(const std::vector<double>& doubles) Color(const std::vector<double>& doubles)
{ {
if (doubles.size() != 4) throw std::runtime_error("Invalid color doubles array"); assert(doubles.size() == 4 && "Invalid color doubles array");
r = static_cast<uint8_t>(lround(doubles[0] * 255.0)); r = static_cast<uint8_t>(lround(doubles[0] * 255.0));
g = static_cast<uint8_t>(lround(doubles[1] * 255.0)); g = static_cast<uint8_t>(lround(doubles[1] * 255.0));
b = static_cast<uint8_t>(lround(doubles[2] * 255.0)); b = static_cast<uint8_t>(lround(doubles[2] * 255.0));

View File

@ -244,6 +244,8 @@ Device createDevice(VkInstance instance, const DeviceRequirements& requirements,
} }
} }
// TODO: Remove optional extensions. They'll never be handled anyway. Just stick to well-supported extensions.
bool formatsSupported = true; bool formatsSupported = true;
for (const FormatRequirements& formatRequirements : requirements.formats) { for (const FormatRequirements& formatRequirements : requirements.formats) {
VkFormatFeatureFlags requiredLinearFlags = formatRequirements.properties.linearTilingFeatures; VkFormatFeatureFlags requiredLinearFlags = formatRequirements.properties.linearTilingFeatures;

Binary file not shown.

BIN
test/res/models/floor2.glb Normal file

Binary file not shown.

View File

@ -97,7 +97,7 @@ void PlayGame(GameSettings settings)
main_scene->AddComponent<CameraControllerComponent>(camera); main_scene->AddComponent<CameraControllerComponent>(camera);
/* floor */ /* floor */
engine::Entity floor = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/floor.glb"), true); engine::Entity floor = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/floor2.glb"), true);
//main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false; //main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false;
engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb"), true); engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb"), true);
@ -159,13 +159,13 @@ void PlayGame(GameSettings settings)
engine::Entity box = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/box.glb"), true); engine::Entity box = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/box.glb"), true);
main_scene->GetPosition(box) = glm::vec3{ -5.0f, -17.0f, 0.1f }; main_scene->GetPosition(box) = glm::vec3{ -5.0f, -17.0f, 0.1f };
main_scene->GetScale(box) *= 10.0f; main_scene->GetScale(box) *= 10.0f;
main_scene->GetRotation(box) = glm::angleAxis(glm::pi<float>(), glm::vec3{ 0.0f, 0.0f, 1.0f }); main_scene->GetRotation(box) = glm::angleAxis(glm::pi<float>() * 0.0f, glm::vec3{ 0.0f, 0.0f, 1.0f });
main_scene->GetRotation(box) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f }); main_scene->GetRotation(box) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f });
} }
start_scene->GetSystem<CameraControllerSystem>()->next_scene_ = main_scene; start_scene->GetSystem<CameraControllerSystem>()->next_scene_ = main_scene;
main_scene->GetSystem<CameraControllerSystem>()->next_scene_ = start_scene; main_scene->GetSystem<CameraControllerSystem>()->next_scene_ = start_scene;
app.scene_manager()->SetActiveScene(main_scene); app.scene_manager()->SetActiveScene(start_scene);
app.GameLoop(); app.GameLoop();
} }