mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Fix fonts. Optimise vulkan renderer
This commit is contained in:
parent
d8911df619
commit
9c9b74f8fc
@ -22,7 +22,8 @@ public:
|
||||
struct CharData {
|
||||
glm::vec2 atlas_top_left{};
|
||||
glm::vec2 atlas_bottom_right{};
|
||||
glm::vec2 offset{};
|
||||
glm::vec2 char_top_left{};
|
||||
glm::vec2 char_bottom_right{};
|
||||
float xAdvance{};
|
||||
};
|
||||
|
||||
|
@ -13,12 +13,13 @@ UI::UI(Object* parent) : Component(parent, TypeEnum::UI)
|
||||
m_shader = parent->res.get<resources::Shader>("shaders/font.glsl");
|
||||
|
||||
m_atlasMesh = std::make_unique<resources::Mesh>(std::vector<Vertex>{
|
||||
{ { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 0.0f } },
|
||||
{ { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f } },
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f } },
|
||||
{ { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 0.0f } },
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f } },
|
||||
{ { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f } }
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f } },
|
||||
{ { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f } },
|
||||
{ { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f } },
|
||||
|
||||
{ { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 0.0f } },
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f } },
|
||||
{ { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f } },
|
||||
});
|
||||
}
|
||||
|
||||
@ -38,14 +39,15 @@ void UI::render(glm::mat4 transform, glm::mat4 view)
|
||||
glm::vec2 size;
|
||||
} pushConsts{};
|
||||
|
||||
int advance = 0;
|
||||
|
||||
float advance = 0.0f;
|
||||
for (char c : m_text) {
|
||||
auto charData = m_font->getCharData(c);
|
||||
pushConsts.m = glm::mat4{1.0f};
|
||||
charData.char_top_left.y *= -1;
|
||||
pushConsts.m = transform;
|
||||
pushConsts.atlas_top_left = charData.atlas_top_left;
|
||||
pushConsts.atlas_bottom_right = charData.atlas_bottom_right;
|
||||
pushConsts.offset = charData.offset;
|
||||
pushConsts.size = (charData.char_bottom_right - charData.char_top_left);
|
||||
pushConsts.offset = glm::vec2{ charData.char_top_left.x + advance, charData.char_top_left.y };
|
||||
gfxdev->draw(
|
||||
m_shader->getPipeline(), m_atlasMesh->vb, m_atlasMesh->ib, m_atlasMesh->m_indices.size(),
|
||||
&pushConsts, sizeof(pushConsts), m_font->getAtlasTexture());
|
||||
|
@ -95,6 +95,7 @@ namespace engine {
|
||||
};
|
||||
|
||||
struct DrawCall {
|
||||
const gfx::Pipeline* pipeline = nullptr; // for performance, keep this the same for consecutive draw calls
|
||||
const gfx::Buffer* vertexBuffer = nullptr;
|
||||
const gfx::Buffer* indexBuffer = nullptr; // if this is nullptr, don't use indexed
|
||||
uint32_t count = 0;
|
||||
@ -1011,8 +1012,8 @@ namespace engine {
|
||||
std::array<VkCommandBuffer, FRAMES_IN_FLIGHT> commandBuffers{};
|
||||
std::array<VkFence, FRAMES_IN_FLIGHT> inFlightFences{};
|
||||
|
||||
std::map<const gfx::Pipeline*, std::queue<DrawCall>> drawQueues{};
|
||||
|
||||
std::queue<DrawCall> drawQueue{};
|
||||
|
||||
VkDescriptorSetLayoutBinding uboLayoutBinding{};
|
||||
VkDescriptorSetLayout descriptorSetLayout{};
|
||||
|
||||
@ -1510,12 +1511,14 @@ namespace engine {
|
||||
|
||||
void GFXDevice::draw(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count, const void* pushConstantData, size_t pushConstantSize, const gfx::Texture* texture)
|
||||
{
|
||||
assert(vertexBuffer->type == gfx::BufferType::VERTEX);
|
||||
assert(pipeline != nullptr);
|
||||
assert(vertexBuffer != nullptr);
|
||||
assert(vertexBuffer->type == gfx::BufferType::VERTEX);
|
||||
assert(indexBuffer == nullptr || indexBuffer->type == gfx::BufferType::INDEX);
|
||||
assert(pushConstantSize <= PUSH_CONSTANT_MAX_SIZE);
|
||||
|
||||
DrawCall call{
|
||||
.pipeline = pipeline,
|
||||
.vertexBuffer = vertexBuffer,
|
||||
.indexBuffer = indexBuffer, // will be ignored if nullptr
|
||||
.count = count,
|
||||
@ -1525,7 +1528,7 @@ namespace engine {
|
||||
|
||||
call.texture = texture; // will be ignored if nullptr
|
||||
|
||||
pimpl->drawQueues[pipeline].push(call);
|
||||
pimpl->drawQueue.push(call);
|
||||
|
||||
}
|
||||
|
||||
@ -1570,7 +1573,7 @@ namespace engine {
|
||||
renderPassInfo.renderArea.extent = pimpl->swapchain.extent;
|
||||
|
||||
std::array<VkClearValue, 2> clearValues{};
|
||||
clearValues[0].color = { {0.1f, 0.1f, 0.8f, 1.0f} };
|
||||
clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
|
||||
clearValues[1].depthStencil = { 1.0f, 0 };
|
||||
renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
|
||||
renderPassInfo.pClearValues = clearValues.data();
|
||||
@ -1595,33 +1598,50 @@ namespace engine {
|
||||
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
|
||||
for (auto& [pipeline, queue] : pimpl->drawQueues) {
|
||||
vkCmdBindPipeline(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
||||
vkCmdBindDescriptorSets(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, 0, 1, &pipeline->descriptorSets[frameIndex], 0, nullptr);
|
||||
while (queue.empty() == false) {
|
||||
const gfx::Pipeline* lastPipeline = nullptr;
|
||||
const gfx::Texture* lastTexture = nullptr;
|
||||
const gfx::Buffer* lastVertexBuffer = nullptr;
|
||||
const gfx::Buffer* lastIndexBuffer = nullptr;
|
||||
while (pimpl->drawQueue.empty() == false) {
|
||||
|
||||
DrawCall call = pimpl->drawQueue.front();
|
||||
|
||||
DrawCall call = queue.front();
|
||||
|
||||
vkCmdBindDescriptorSets(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, 1, 1, &call.texture->descriptorSets[frameIndex], 0, nullptr);
|
||||
|
||||
vkCmdPushConstants(pimpl->commandBuffers[frameIndex], pipeline->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, PUSH_CONSTANT_MAX_SIZE, call.pushConstantData);
|
||||
|
||||
vkCmdBindVertexBuffers(pimpl->commandBuffers[frameIndex], 0, 1, &call.vertexBuffer->buffer, offsets);
|
||||
|
||||
if (call.indexBuffer == nullptr) {
|
||||
// no index buffer
|
||||
vkCmdDraw(pimpl->commandBuffers[frameIndex], call.count, 1, 0, 0);
|
||||
} else {
|
||||
// use index buffer
|
||||
vkCmdBindIndexBuffer(pimpl->commandBuffers[frameIndex], call.indexBuffer->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
vkCmdDrawIndexed(pimpl->commandBuffers[frameIndex], call.count, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
queue.pop();
|
||||
if (call.pipeline != lastPipeline) {
|
||||
vkCmdBindPipeline(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, call.pipeline->handle);
|
||||
// bind pipeline uniform-buffer
|
||||
vkCmdBindDescriptorSets(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, call.pipeline->layout, 0, 1, &call.pipeline->descriptorSets[frameIndex], 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (call.texture != lastTexture) {
|
||||
// set the texture
|
||||
vkCmdBindDescriptorSets(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, call.pipeline->layout, 1, 1, &call.texture->descriptorSets[frameIndex], 0, nullptr);
|
||||
}
|
||||
|
||||
// like uniforms but faster
|
||||
vkCmdPushConstants(pimpl->commandBuffers[frameIndex], call.pipeline->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, PUSH_CONSTANT_MAX_SIZE, call.pushConstantData);
|
||||
|
||||
pimpl->drawQueues.clear();
|
||||
if (call.vertexBuffer != lastVertexBuffer) {
|
||||
vkCmdBindVertexBuffers(pimpl->commandBuffers[frameIndex], 0, 1, &call.vertexBuffer->buffer, offsets);
|
||||
}
|
||||
if (call.indexBuffer == nullptr) {
|
||||
// no index buffer
|
||||
vkCmdDraw(pimpl->commandBuffers[frameIndex], call.count, 1, 0, 0);
|
||||
} else {
|
||||
// use index buffer
|
||||
if (call.indexBuffer != lastIndexBuffer) {
|
||||
vkCmdBindIndexBuffer(pimpl->commandBuffers[frameIndex], call.indexBuffer->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
}
|
||||
vkCmdDrawIndexed(pimpl->commandBuffers[frameIndex], call.count, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
lastPipeline = call.pipeline;
|
||||
lastTexture = call.texture;
|
||||
lastVertexBuffer = call.vertexBuffer;
|
||||
lastIndexBuffer = call.indexBuffer;
|
||||
|
||||
pimpl->drawQueue.pop();
|
||||
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(pimpl->commandBuffers[frameIndex]);
|
||||
|
||||
@ -1783,7 +1803,7 @@ namespace engine {
|
||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = attribDescs.size();
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)attribDescs.size();
|
||||
vertexInputInfo.pVertexAttributeDescriptions = attribDescs.data();
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||
@ -1810,7 +1830,7 @@ namespace engine {
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamicState{};
|
||||
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamicState.dynamicStateCount = dynamicStates.size();
|
||||
dynamicState.dynamicStateCount = (uint32_t)dynamicStates.size();
|
||||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportState{};
|
||||
@ -1898,7 +1918,7 @@ namespace engine {
|
||||
|
||||
VkPipelineLayoutCreateInfo layoutInfo{};
|
||||
layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layoutInfo.setLayoutCount = setLayouts.size();
|
||||
layoutInfo.setLayoutCount = (uint32_t)setLayouts.size();
|
||||
layoutInfo.pSetLayouts = setLayouts.data();
|
||||
layoutInfo.pushConstantRangeCount = 1;
|
||||
layoutInfo.pPushConstantRanges = &pushConstantRange;
|
||||
|
@ -19,32 +19,35 @@ Font::Font(const std::filesystem::path& resPath) : Resource(resPath, "font")
|
||||
constexpr int FIRST_CHAR = 32;
|
||||
constexpr int NUM_CHARS = 96;
|
||||
|
||||
constexpr float SCALE = 128.0f;
|
||||
|
||||
constexpr int BITMAP_WIDTH = 1024;
|
||||
constexpr int BITMAP_HEIGHT = 1024;
|
||||
auto pixels = std::make_unique<unsigned char[]>(BITMAP_WIDTH * BITMAP_HEIGHT);
|
||||
auto bakedChars = std::make_unique<stbtt_bakedchar[]>(NUM_CHARS);
|
||||
|
||||
stbtt_BakeFontBitmap(fontBuffer->data(), 0, 128.0f, pixels.get(), BITMAP_WIDTH, BITMAP_HEIGHT, FIRST_CHAR, NUM_CHARS, bakedChars.get());
|
||||
stbtt_BakeFontBitmap(fontBuffer->data(), 0, SCALE, pixels.get(), BITMAP_WIDTH, BITMAP_HEIGHT, FIRST_CHAR, NUM_CHARS, bakedChars.get());
|
||||
|
||||
auto textureData = std::make_unique<uint8_t[]>(BITMAP_WIDTH * BITMAP_HEIGHT * 4);
|
||||
|
||||
for (int i = 0; i < BITMAP_WIDTH * BITMAP_HEIGHT; i++) {
|
||||
textureData[i * 4 + 0] = pixels[i];
|
||||
textureData[i * 4 + 1] = pixels[i];
|
||||
textureData[i * 4 + 2] = pixels[i];
|
||||
textureData[i * 4 + 0] = 255;
|
||||
textureData[i * 4 + 1] = 255;
|
||||
textureData[i * 4 + 2] = 255;
|
||||
textureData[i * 4 + 3] = pixels[i];
|
||||
}
|
||||
|
||||
m_atlas = gfxdev->createTexture(textureData.get(), BITMAP_WIDTH, BITMAP_HEIGHT, gfx::TextureFilter::LINEAR, gfx::TextureFilter::LINEAR);
|
||||
|
||||
for (int i = FIRST_CHAR; i < NUM_CHARS; i++) {
|
||||
for (int i = FIRST_CHAR; i < FIRST_CHAR + NUM_CHARS; i++) {
|
||||
CharData charData{};
|
||||
charData.atlas_top_left = { bakedChars[i].x0, bakedChars[i].y0 };
|
||||
charData.atlas_bottom_right = { bakedChars[i].x1, bakedChars[i].y1 };
|
||||
charData.offset = { bakedChars[i].xoff, bakedChars[i].yoff };
|
||||
charData.xAdvance = bakedChars[i].xadvance;
|
||||
stbtt_bakedchar baked = bakedChars[i - FIRST_CHAR];
|
||||
charData.atlas_top_left = { (float)baked.x0 / (float)BITMAP_WIDTH, (float)baked.y0 / (float)BITMAP_HEIGHT };
|
||||
charData.atlas_bottom_right = { (float)baked.x1 / (float)BITMAP_WIDTH, (float)baked.y1 / (float)BITMAP_HEIGHT};
|
||||
charData.char_top_left = { baked.xoff, baked.yoff };
|
||||
charData.char_bottom_right = charData.char_top_left + glm::vec2{ baked.x1 - baked.x0, baked.y1 - baked.y0 };
|
||||
charData.xAdvance = baked.xadvance;
|
||||
m_charData[i] = charData;
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
layout( push_constant ) uniform Constants {
|
||||
mat4 model;
|
||||
vec2 atlas_top_left;
|
||||
vec2 atlas_bottom_right;
|
||||
vec2 offset;
|
||||
vec2 size;
|
||||
} constants;
|
||||
@ -13,6 +15,8 @@ layout(location = 2) in vec2 inUV;
|
||||
layout(location = 0) out vec2 fragUV;
|
||||
|
||||
void main() {
|
||||
gl_Position = constants.model * vec4(inPosition, 1.0);
|
||||
fragUV = inUV;
|
||||
vec2 position = inPosition.xy * constants.size + constants.offset;
|
||||
position *= 0.001;
|
||||
gl_Position = constants.model * vec4(position, 0.0, 1.0);
|
||||
fragUV = constants.atlas_top_left + (inUV * (constants.atlas_bottom_right - constants.atlas_top_left));
|
||||
}
|
@ -58,8 +58,6 @@ void playGame()
|
||||
auto camCamera = cam->createComponent<engine::components::Camera>();
|
||||
camCamera->usePerspective(130.0f);
|
||||
cam->createComponent<CameraController>();
|
||||
cam->createComponent<engine::components::Renderer>()->m_mesh = genSphereMesh(0.2f, 20);
|
||||
cam->getComponent<engine::components::Renderer>()->setTexture("textures/cobble_stone.png");
|
||||
|
||||
/*
|
||||
auto gun = cam->createChild("gun");
|
||||
@ -73,8 +71,6 @@ void playGame()
|
||||
*/
|
||||
|
||||
// FLOOR
|
||||
|
||||
/*
|
||||
constexpr float GRASS_DENSITY = 128.0f * 20.0f;
|
||||
auto floor = app.scene()->createChild("floor");
|
||||
auto floorRenderer = floor->createComponent<engine::components::Renderer>();
|
||||
@ -89,15 +85,12 @@ void playGame()
|
||||
{ { -16.0f, 0.0f, 16.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, GRASS_DENSITY } }
|
||||
});
|
||||
floor->transform.scale = { 100.0f, 1.0f, 100.0f };
|
||||
*/
|
||||
|
||||
/*
|
||||
auto cube = app.scene()->createChild("cube");
|
||||
auto cubeRen = cube->createComponent<engine::components::Renderer>();
|
||||
cubeRen->setMesh("meshes/cube.mesh");
|
||||
cube->transform.position = glm::vec3{ -5.0f, 1.0f, 0.0f };
|
||||
class Spin : public engine::components::CustomComponent {
|
||||
|
||||
public:
|
||||
Spin(engine::Object* parent) : CustomComponent(parent)
|
||||
{
|
||||
@ -123,32 +116,34 @@ void playGame()
|
||||
pitchQuat.w = glm::cos(halfPitch);
|
||||
parent.transform.rotation *= pitchQuat;
|
||||
}
|
||||
|
||||
private:
|
||||
float m_yaw = 0.0f;
|
||||
|
||||
};
|
||||
app.scene()->getChild("cube")->createComponent<Spin>();
|
||||
*/
|
||||
|
||||
/*auto sphere = app.scene()->createChild("sphere");
|
||||
sphere->transform.position = { 10.0f, 5.0f, 10.0f };
|
||||
*/
|
||||
|
||||
/*auto sphereRenderer = sphere->createComponent<engine::components::Renderer>();
|
||||
sphereRenderer->m_mesh = genSphereMesh(5.0f, 100, false);
|
||||
sphereRenderer->setTexture("textures/cobble_stone.png");
|
||||
cube->createComponent<Spin>();
|
||||
|
||||
// boundary
|
||||
auto bounds = app.scene()->createChild("bounds");
|
||||
auto boundsRen = bounds->createComponent<engine::components::Renderer>();
|
||||
boundsRen->m_mesh = genSphereMesh(100.0f, 36, true);
|
||||
boundsRen->setTexture("textures/metal.jpg");
|
||||
*/
|
||||
|
||||
auto message = app.scene()->createChild("message");
|
||||
message->transform.position = { 0.0f, 2.0f, 0.0f };
|
||||
message->transform.position = { -1.0f, 0.95f, 0.0f };
|
||||
message->transform.scale *= 0.5f;
|
||||
auto messageUI = message->createComponent<engine::components::UI>();
|
||||
class FPSTextUpdater : public engine::components::CustomComponent {
|
||||
engine::components::UI* textUI = nullptr;
|
||||
public:
|
||||
FPSTextUpdater(engine::Object* parent) : CustomComponent(parent)
|
||||
{
|
||||
textUI = parent->getComponent<engine::components::UI>();
|
||||
}
|
||||
void onUpdate(glm::mat4 t) override
|
||||
{
|
||||
textUI->m_text = std::to_string(parent.win.dt() * 1000.0f) + " ms";
|
||||
}
|
||||
};
|
||||
message->createComponent<FPSTextUpdater>();
|
||||
|
||||
/*
|
||||
auto myModel = engine::util::loadAssimpMeshFromFile(app.scene(), app.resources()->getFilePath("models/pyramid/pyramid.dae").string());
|
||||
@ -156,17 +151,11 @@ void playGame()
|
||||
|
||||
auto myRoom = engine::util::loadAssimpMeshFromFile(app.scene(), app.resources()->getFilePath("models/room/room.dae").string());
|
||||
myRoom->transform.position = { 9.0f, 0.1f, 3.0f };
|
||||
|
||||
*/
|
||||
auto astronaut = engine::util::loadAssimpMeshFromFile(app.scene(), app.resources()->getFilePath("models/astronaut/astronaut.dae").string());
|
||||
astronaut->transform.position.z += 5.0f;
|
||||
astronaut->createComponent<Spin>();
|
||||
|
||||
auto plane = engine::util::loadAssimpMeshFromFile(app.scene(), app.resources()->getFilePath("models/plane/plane.dae").string());
|
||||
plane->transform.position = { -30.0f, 2.0f, 10.0f };
|
||||
*/
|
||||
|
||||
auto van = engine::util::loadAssimpMeshFromFile(app.scene(), app.resources()->getFilePath("models/van/van.dae").string());
|
||||
|
||||
/*
|
||||
auto lego = engine::util::loadAssimpMeshFromFile(app.scene(), app.resources()->getFilePath("models/lego/lego.dae").string());
|
||||
lego->transform.position = { -30.0f, -33.0f, -30.0f };
|
||||
|
Loading…
Reference in New Issue
Block a user