mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Add textures
This commit is contained in:
parent
7cc09484c1
commit
d71254985b
@ -23,7 +23,7 @@ namespace engine {
|
|||||||
|
|
||||||
// adds a draw call to the queue
|
// adds a draw call to the queue
|
||||||
// vertexBuffer is required, indexBuffer can be NULL, uniformData is required
|
// vertexBuffer is required, indexBuffer can be NULL, uniformData is required
|
||||||
void draw(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count, const void* pushConstantData, size_t pushConstantSize);
|
void 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);
|
||||||
|
|
||||||
// Call once per frame. Executes all queued draw calls and renders to the screen.
|
// Call once per frame. Executes all queued draw calls and renders to the screen.
|
||||||
void renderFrame();
|
void renderFrame();
|
||||||
|
@ -14,6 +14,8 @@ public:
|
|||||||
Texture(const std::filesystem::path& resPath);
|
Texture(const std::filesystem::path& resPath);
|
||||||
~Texture() override;
|
~Texture() override;
|
||||||
|
|
||||||
|
gfx::Texture* getHandle();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gfx::Texture* m_gpuTexture;
|
gfx::Texture* m_gpuTexture;
|
||||||
};
|
};
|
||||||
|
@ -77,7 +77,6 @@ void Camera::usePerspective(float fovDeg)
|
|||||||
|
|
||||||
float fovRad = glm::radians(fovDeg);
|
float fovRad = glm::radians(fovDeg);
|
||||||
m_projMatrix = glm::perspectiveFovRH_ZO(fovRad, viewportDim.x, viewportDim.y, NEAR, FAR);
|
m_projMatrix = glm::perspectiveFovRH_ZO(fovRad, viewportDim.x, viewportDim.y, NEAR, FAR);
|
||||||
m_projMatrix[1][1] *= -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::useOrtho()
|
void Camera::useOrtho()
|
||||||
@ -88,7 +87,6 @@ void Camera::useOrtho()
|
|||||||
float aspect = viewportDim.x / viewportDim.y;
|
float aspect = viewportDim.x / viewportDim.y;
|
||||||
|
|
||||||
m_projMatrix = glm::orthoRH_ZO(-10.0f * aspect, 10.0f * aspect, -10.0f, 10.0f, -100.0f, 100.0f);
|
m_projMatrix = glm::orthoRH_ZO(-10.0f * aspect, 10.0f * aspect, -10.0f, 10.0f, -100.0f, 100.0f);
|
||||||
m_projMatrix[1][1] *= -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace engine::components {
|
|||||||
Renderer::Renderer(Object* parent) : Component(parent, TypeEnum::RENDERER)
|
Renderer::Renderer(Object* parent) : Component(parent, TypeEnum::RENDERER)
|
||||||
{
|
{
|
||||||
m_shader = this->parent.res.get<resources::Shader>("shader.glsl");
|
m_shader = this->parent.res.get<resources::Shader>("shader.glsl");
|
||||||
// m_texture = this->parent.res.get<resources::Texture>("textures/missing.png");
|
m_texture = this->parent.res.get<resources::Texture>("textures/missing.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::~Renderer()
|
Renderer::~Renderer()
|
||||||
@ -32,7 +32,7 @@ void Renderer::render(glm::mat4 transform, glm::mat4 view)
|
|||||||
gfxdev->updateUniformBuffer(m_shader->getPipeline(), &uniformData.color, sizeof(uniformData.color), offsetof(resources::Shader::UniformBuffer, color));
|
gfxdev->updateUniformBuffer(m_shader->getPipeline(), &uniformData.color, sizeof(uniformData.color), offsetof(resources::Shader::UniformBuffer, color));
|
||||||
|
|
||||||
glm::mat4 pushConsts[] = { transform, view };
|
glm::mat4 pushConsts[] = { transform, view };
|
||||||
gfxdev->draw(m_shader->getPipeline(), m_mesh->vb, m_mesh->ib, m_mesh->m_vertices.size(), pushConsts, sizeof(glm::mat4) * 2);
|
gfxdev->draw(m_shader->getPipeline(), m_mesh->vb, m_mesh->ib, m_mesh->m_indices.size(), pushConsts, sizeof(glm::mat4) * 2, m_texture->getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::setMesh(const std::string& name)
|
void Renderer::setMesh(const std::string& name)
|
||||||
|
@ -58,7 +58,6 @@ namespace engine {
|
|||||||
VkQueue handle;
|
VkQueue handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DepthBuffer {
|
struct DepthBuffer {
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
@ -91,6 +90,7 @@ namespace engine {
|
|||||||
const gfx::Buffer* indexBuffer = nullptr; // if this is nullptr, don't use indexed
|
const gfx::Buffer* indexBuffer = nullptr; // if this is nullptr, don't use indexed
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
uint8_t pushConstantData[PUSH_CONSTANT_MAX_SIZE];
|
uint8_t pushConstantData[PUSH_CONSTANT_MAX_SIZE];
|
||||||
|
const gfx::Texture* texture = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class QueueFlags : uint32_t {
|
enum class QueueFlags : uint32_t {
|
||||||
@ -119,6 +119,11 @@ namespace engine {
|
|||||||
struct gfx::Texture {
|
struct gfx::Texture {
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VmaAllocation alloc;
|
VmaAllocation alloc;
|
||||||
|
VkImageView imageView;
|
||||||
|
VkSampler sampler;
|
||||||
|
VkDescriptorPool pool;
|
||||||
|
std::array<VkDescriptorSet, FRAMES_IN_FLIGHT> descriptorSets{};
|
||||||
|
uint32_t mipLevels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -164,7 +169,6 @@ namespace engine {
|
|||||||
options.SetOptimizationLevel(shaderc_optimization_level_size);
|
options.SetOptimizationLevel(shaderc_optimization_level_size);
|
||||||
options.SetTargetSpirv(shaderc_spirv_version_1_6);
|
options.SetTargetSpirv(shaderc_spirv_version_1_6);
|
||||||
options.SetAutoBindUniforms(false);
|
options.SetAutoBindUniforms(false);
|
||||||
options.SetInvertY(false);
|
|
||||||
|
|
||||||
// preprocess
|
// preprocess
|
||||||
shaderc::PreprocessedSourceCompilationResult preprocessed = compiler.PreprocessGlsl(source, kind, filename, options);
|
shaderc::PreprocessedSourceCompilationResult preprocessed = compiler.PreprocessGlsl(source, kind, filename, options);
|
||||||
@ -774,7 +778,7 @@ namespace engine {
|
|||||||
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImageLayout oldLayout, VkImageLayout newLayout, VkImage image)
|
static void cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels, VkImage image)
|
||||||
{
|
{
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||||
@ -785,7 +789,7 @@ namespace engine {
|
|||||||
barrier.image = image;
|
barrier.image = image;
|
||||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
barrier.subresourceRange.baseMipLevel = 0;
|
||||||
barrier.subresourceRange.levelCount = 1;
|
barrier.subresourceRange.levelCount = mipLevels;
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
barrier.subresourceRange.layerCount = 1;
|
barrier.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
@ -814,6 +818,77 @@ namespace engine {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cmdGenerateMipmaps(VkCommandBuffer commandBuffer, VkImage image, int32_t width, int32_t height, uint32_t mipLevels)
|
||||||
|
{
|
||||||
|
|
||||||
|
VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||||
|
barrier.image = image;
|
||||||
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
|
barrier.subresourceRange.layerCount = 1;
|
||||||
|
barrier.subresourceRange.levelCount = 1;
|
||||||
|
|
||||||
|
int32_t mipWidth = width;
|
||||||
|
int32_t mipHeight = height;
|
||||||
|
for (uint32_t i = 1; i < mipLevels; i++) {
|
||||||
|
barrier.subresourceRange.baseMipLevel = i - 1;
|
||||||
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||||
|
0, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier);
|
||||||
|
|
||||||
|
VkImageBlit blit{};
|
||||||
|
blit.srcOffsets[0] = { 0, 0, 0 };
|
||||||
|
blit.srcOffsets[1] = { mipWidth, mipHeight, 1 };
|
||||||
|
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
blit.srcSubresource.mipLevel = i - 1;
|
||||||
|
blit.srcSubresource.baseArrayLayer = 0;
|
||||||
|
blit.srcSubresource.layerCount = 1;
|
||||||
|
blit.dstOffsets[0] = { 0, 0, 0 };
|
||||||
|
blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };
|
||||||
|
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
blit.dstSubresource.mipLevel = i;
|
||||||
|
blit.dstSubresource.baseArrayLayer = 0;
|
||||||
|
blit.dstSubresource.layerCount = 1;
|
||||||
|
|
||||||
|
vkCmdBlitImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
|
||||||
|
|
||||||
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
||||||
|
0,
|
||||||
|
0, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier);
|
||||||
|
|
||||||
|
if (mipWidth > 1) mipWidth /= 2;
|
||||||
|
if (mipHeight > 1) mipHeight /= 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
barrier.subresourceRange.baseMipLevel = mipLevels - 1;
|
||||||
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(commandBuffer,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
||||||
|
0, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier);
|
||||||
|
}
|
||||||
|
|
||||||
// class definitions
|
// class definitions
|
||||||
|
|
||||||
struct GFXDevice::Impl {
|
struct GFXDevice::Impl {
|
||||||
@ -845,7 +920,10 @@ namespace engine {
|
|||||||
std::map<const gfx::Pipeline*, std::queue<DrawCall>> drawQueues{};
|
std::map<const gfx::Pipeline*, std::queue<DrawCall>> drawQueues{};
|
||||||
|
|
||||||
VkDescriptorSetLayoutBinding uboLayoutBinding{};
|
VkDescriptorSetLayoutBinding uboLayoutBinding{};
|
||||||
VkDescriptorSetLayout uboLayout{};
|
VkDescriptorSetLayout descriptorSetLayout{};
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutBinding samplerLayoutBinding{};
|
||||||
|
VkDescriptorSetLayout samplerSetLayout{};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1032,6 +1110,19 @@ namespace engine {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for some features:
|
||||||
|
VkPhysicalDeviceFeatures devFeatures;
|
||||||
|
vkGetPhysicalDeviceFeatures(dev, &devFeatures);
|
||||||
|
// anisotropic filtering is needed
|
||||||
|
if (devFeatures.samplerAnisotropy == VK_FALSE) continue;
|
||||||
|
|
||||||
|
// check for linear filtering for mipmaps
|
||||||
|
VkFormatProperties formatProperties{};
|
||||||
|
vkGetPhysicalDeviceFormatProperties(dev, VK_FORMAT_R8G8B8A8_SRGB, &formatProperties);
|
||||||
|
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
pimpl->physicalDevice = dev;
|
pimpl->physicalDevice = dev;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1127,6 +1218,9 @@ namespace engine {
|
|||||||
throw std::runtime_error("The selected queue family does not support this surface");
|
throw std::runtime_error("The selected queue family does not support this surface");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||||
|
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||||
|
|
||||||
VkDeviceCreateInfo deviceCreateInfo{
|
VkDeviceCreateInfo deviceCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@ -1137,7 +1231,7 @@ namespace engine {
|
|||||||
// IGNORED: .ppEnabledLayerNames
|
// IGNORED: .ppEnabledLayerNames
|
||||||
.enabledExtensionCount = (uint32_t)requiredDeviceExtensions.size(),
|
.enabledExtensionCount = (uint32_t)requiredDeviceExtensions.size(),
|
||||||
.ppEnabledExtensionNames = requiredDeviceExtensions.data(),
|
.ppEnabledExtensionNames = requiredDeviceExtensions.data(),
|
||||||
.pEnabledFeatures = nullptr,
|
.pEnabledFeatures = &deviceFeatures,
|
||||||
};
|
};
|
||||||
|
|
||||||
res = vkCreateDevice(pimpl->physicalDevice, &deviceCreateInfo, nullptr, &pimpl->device);
|
res = vkCreateDevice(pimpl->physicalDevice, &deviceCreateInfo, nullptr, &pimpl->device);
|
||||||
@ -1244,24 +1338,41 @@ namespace engine {
|
|||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create uniform buffer stuff
|
// create uniform buffer descriptor set layout
|
||||||
pimpl->uboLayoutBinding.binding = 0;
|
pimpl->uboLayoutBinding.binding = 0;
|
||||||
pimpl->uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
pimpl->uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
pimpl->uboLayoutBinding.descriptorCount = 1;
|
pimpl->uboLayoutBinding.descriptorCount = 1;
|
||||||
pimpl->uboLayoutBinding.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
|
pimpl->uboLayoutBinding.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
|
||||||
pimpl->uboLayoutBinding.pImmutableSamplers = nullptr;
|
pimpl->uboLayoutBinding.pImmutableSamplers = nullptr;
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||||
descriptorSetLayoutInfo.bindingCount = 1;
|
descriptorSetLayoutInfo.bindingCount = 1;
|
||||||
descriptorSetLayoutInfo.pBindings = &pimpl->uboLayoutBinding;
|
descriptorSetLayoutInfo.pBindings = &pimpl->uboLayoutBinding;
|
||||||
res = vkCreateDescriptorSetLayout(pimpl->device, &descriptorSetLayoutInfo, nullptr, &pimpl->uboLayout);
|
res = vkCreateDescriptorSetLayout(pimpl->device, &descriptorSetLayoutInfo, nullptr, &pimpl->descriptorSetLayout);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
// create texture sampler descriptor set layout
|
||||||
|
pimpl->samplerLayoutBinding.binding = 0;
|
||||||
|
pimpl->samplerLayoutBinding.descriptorCount = 1;
|
||||||
|
pimpl->samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
pimpl->samplerLayoutBinding.pImmutableSamplers = nullptr;
|
||||||
|
pimpl->samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo samplerSetLayoutInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
|
||||||
|
samplerSetLayoutInfo.bindingCount = 1;
|
||||||
|
samplerSetLayoutInfo.pBindings = &pimpl->samplerLayoutBinding;
|
||||||
|
res = vkCreateDescriptorSetLayout(pimpl->device, &samplerSetLayoutInfo, nullptr, &pimpl->samplerSetLayout);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXDevice::~GFXDevice()
|
GFXDevice::~GFXDevice()
|
||||||
{
|
{
|
||||||
TRACE("Destroying GFXDevice...");
|
TRACE("Destroying GFXDevice...");
|
||||||
|
|
||||||
vkDestroyDescriptorSetLayout(pimpl->device, pimpl->uboLayout, nullptr);
|
vkDestroyDescriptorSetLayout(pimpl->device, pimpl->samplerSetLayout, nullptr);
|
||||||
|
vkDestroyDescriptorSetLayout(pimpl->device, pimpl->descriptorSetLayout, nullptr);
|
||||||
|
|
||||||
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
|
|
||||||
@ -1298,7 +1409,7 @@ namespace engine {
|
|||||||
*h = (uint32_t)height;
|
*h = (uint32_t)height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::draw(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count, const void* pushConstantData, size_t pushConstantSize)
|
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(vertexBuffer->type == gfx::BufferType::VERTEX);
|
||||||
assert(vertexBuffer != nullptr);
|
assert(vertexBuffer != nullptr);
|
||||||
@ -1313,6 +1424,8 @@ namespace engine {
|
|||||||
|
|
||||||
memcpy(call.pushConstantData, pushConstantData, pushConstantSize);
|
memcpy(call.pushConstantData, pushConstantData, pushConstantSize);
|
||||||
|
|
||||||
|
call.texture = texture; // will be ignored if nullptr
|
||||||
|
|
||||||
pimpl->drawQueues[pipeline].push(call);
|
pimpl->drawQueues[pipeline].push(call);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1367,9 +1480,9 @@ namespace engine {
|
|||||||
|
|
||||||
VkViewport viewport{};
|
VkViewport viewport{};
|
||||||
viewport.x = 0.0f;
|
viewport.x = 0.0f;
|
||||||
viewport.y = 0.0f;
|
viewport.y = (float)pimpl->swapchain.extent.height;
|
||||||
viewport.width = (float)pimpl->swapchain.extent.width;
|
viewport.width = (float)pimpl->swapchain.extent.width;
|
||||||
viewport.height = (float)pimpl->swapchain.extent.height;
|
viewport.height = -(float)pimpl->swapchain.extent.height;
|
||||||
viewport.minDepth = 0.0f;
|
viewport.minDepth = 0.0f;
|
||||||
viewport.maxDepth = 1.0f;
|
viewport.maxDepth = 1.0f;
|
||||||
vkCmdSetViewport(pimpl->commandBuffers[frameIndex], 0, 1, &viewport);
|
vkCmdSetViewport(pimpl->commandBuffers[frameIndex], 0, 1, &viewport);
|
||||||
@ -1390,6 +1503,8 @@ namespace engine {
|
|||||||
|
|
||||||
DrawCall call = queue.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);
|
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);
|
vkCmdBindVertexBuffers(pimpl->commandBuffers[frameIndex], 0, 1, &call.vertexBuffer->buffer, offsets);
|
||||||
@ -1490,10 +1605,11 @@ namespace engine {
|
|||||||
pipeline->uniformBuffers[i] = buf;
|
pipeline->uniformBuffers[i] = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create descriptor pool for uniform buffers
|
// create descriptor pools
|
||||||
VkDescriptorPoolSize poolSize{};
|
VkDescriptorPoolSize poolSize{};
|
||||||
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
poolSize.descriptorCount = FRAMES_IN_FLIGHT;
|
poolSize.descriptorCount = FRAMES_IN_FLIGHT;
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo poolInfo{};
|
VkDescriptorPoolCreateInfo poolInfo{};
|
||||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
poolInfo.poolSizeCount = 1;
|
poolInfo.poolSizeCount = 1;
|
||||||
@ -1503,19 +1619,21 @@ namespace engine {
|
|||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
std::array<VkDescriptorSetLayout, FRAMES_IN_FLIGHT> layouts;
|
std::array<VkDescriptorSetLayout, FRAMES_IN_FLIGHT> layouts;
|
||||||
layouts.fill(pimpl->uboLayout);
|
layouts.fill(pimpl->descriptorSetLayout);
|
||||||
VkDescriptorSetAllocateInfo dSetAllocInfo{};
|
VkDescriptorSetAllocateInfo dSetAllocInfo{};
|
||||||
dSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
dSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
dSetAllocInfo.descriptorPool = pipeline->descriptorPool;
|
dSetAllocInfo.descriptorPool = pipeline->descriptorPool;
|
||||||
dSetAllocInfo.descriptorSetCount = FRAMES_IN_FLIGHT;
|
dSetAllocInfo.descriptorSetCount = FRAMES_IN_FLIGHT;
|
||||||
dSetAllocInfo.pSetLayouts = layouts.data();
|
dSetAllocInfo.pSetLayouts = layouts.data();
|
||||||
res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, pipeline->descriptorSets.data());
|
res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, pipeline->descriptorSets.data());
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
VkDescriptorBufferInfo bufferInfo{};
|
VkDescriptorBufferInfo bufferInfo{};
|
||||||
bufferInfo.buffer = pipeline->uniformBuffers[i]->buffer;
|
bufferInfo.buffer = pipeline->uniformBuffers[i]->buffer;
|
||||||
bufferInfo.offset = 0;
|
bufferInfo.offset = 0;
|
||||||
bufferInfo.range = uniformBufferSize;
|
bufferInfo.range = uniformBufferSize;
|
||||||
|
|
||||||
VkWriteDescriptorSet descriptorWrite{};
|
VkWriteDescriptorSet descriptorWrite{};
|
||||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
descriptorWrite.dstSet = pipeline->descriptorSets[i];
|
descriptorWrite.dstSet = pipeline->descriptorSets[i];
|
||||||
@ -1576,9 +1694,9 @@ namespace engine {
|
|||||||
|
|
||||||
VkViewport viewport{};
|
VkViewport viewport{};
|
||||||
viewport.x = 0.0f;
|
viewport.x = 0.0f;
|
||||||
viewport.y = 0.0f;
|
viewport.y = (float)pimpl->swapchain.extent.height;
|
||||||
viewport.width = (float)pimpl->swapchain.extent.width;
|
viewport.width = (float)pimpl->swapchain.extent.width;
|
||||||
viewport.height = (float)pimpl->swapchain.extent.height;
|
viewport.height = -(float)pimpl->swapchain.extent.height;
|
||||||
viewport.minDepth = 0.0f;
|
viewport.minDepth = 0.0f;
|
||||||
viewport.maxDepth = 1.0f;
|
viewport.maxDepth = 1.0f;
|
||||||
|
|
||||||
@ -1667,10 +1785,12 @@ namespace engine {
|
|||||||
pushConstantRange.size = PUSH_CONSTANT_MAX_SIZE;
|
pushConstantRange.size = PUSH_CONSTANT_MAX_SIZE;
|
||||||
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
|
||||||
|
std::array<VkDescriptorSetLayout, 2> setLayouts{ pimpl->descriptorSetLayout, pimpl->samplerSetLayout};
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo layoutInfo{};
|
VkPipelineLayoutCreateInfo layoutInfo{};
|
||||||
layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
layoutInfo.setLayoutCount = 1;
|
layoutInfo.setLayoutCount = setLayouts.size();
|
||||||
layoutInfo.pSetLayouts = &pimpl->uboLayout;
|
layoutInfo.pSetLayouts = setLayouts.data();
|
||||||
layoutInfo.pushConstantRangeCount = 1;
|
layoutInfo.pushConstantRangeCount = 1;
|
||||||
layoutInfo.pPushConstantRanges = &pushConstantRange;
|
layoutInfo.pPushConstantRanges = &pushConstantRange;
|
||||||
|
|
||||||
@ -1810,6 +1930,8 @@ namespace engine {
|
|||||||
|
|
||||||
size_t imageSize = w * h * 4;
|
size_t imageSize = w * h * 4;
|
||||||
|
|
||||||
|
out->mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(w, h)))) + 1;
|
||||||
|
|
||||||
// first load image into staging buffer
|
// first load image into staging buffer
|
||||||
VkBuffer stagingBuffer;
|
VkBuffer stagingBuffer;
|
||||||
VmaAllocation stagingAllocation;
|
VmaAllocation stagingAllocation;
|
||||||
@ -1841,12 +1963,12 @@ namespace engine {
|
|||||||
imageInfo.extent.width = w;
|
imageInfo.extent.width = w;
|
||||||
imageInfo.extent.height = h;
|
imageInfo.extent.height = h;
|
||||||
imageInfo.extent.depth = 1;
|
imageInfo.extent.depth = 1;
|
||||||
imageInfo.mipLevels = 1;
|
imageInfo.mipLevels = out->mipLevels;
|
||||||
imageInfo.arrayLayers = 1;
|
imageInfo.arrayLayers = 1;
|
||||||
imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
imageInfo.flags = 0;
|
imageInfo.flags = 0;
|
||||||
@ -1863,7 +1985,7 @@ namespace engine {
|
|||||||
|
|
||||||
// begin cmd buffer
|
// begin cmd buffer
|
||||||
|
|
||||||
cmdTransitionImageLayout(commandBuffer, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, out->image);
|
cmdTransitionImageLayout(commandBuffer, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, out->mipLevels, out->image);
|
||||||
|
|
||||||
VkBufferImageCopy region{};
|
VkBufferImageCopy region{};
|
||||||
region.bufferOffset = 0;
|
region.bufferOffset = 0;
|
||||||
@ -1880,7 +2002,8 @@ namespace engine {
|
|||||||
|
|
||||||
vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, out->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, out->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||||
|
|
||||||
cmdTransitionImageLayout(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, out->image);
|
// Mipmap generation handles the transition to SHADER_READ_ONLY_OPTIMAL
|
||||||
|
cmdGenerateMipmaps(commandBuffer, out->image, w, h, out->mipLevels);
|
||||||
|
|
||||||
// end cmd buffer
|
// end cmd buffer
|
||||||
endOneTimeCommands(pimpl->device, pimpl->commandPool, commandBuffer, pimpl->gfxQueue.handle);
|
endOneTimeCommands(pimpl->device, pimpl->commandPool, commandBuffer, pimpl->gfxQueue.handle);
|
||||||
@ -1890,11 +2013,101 @@ namespace engine {
|
|||||||
// destroy staging buffer
|
// destroy staging buffer
|
||||||
vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation);
|
vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation);
|
||||||
|
|
||||||
|
// create image view
|
||||||
|
VkImageViewCreateInfo imageViewInfo{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||||
|
imageViewInfo.image = out->image;
|
||||||
|
imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
imageViewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
imageViewInfo.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = out->mipLevels,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
res = vkCreateImageView(pimpl->device, &imageViewInfo, nullptr, &out->imageView);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
// create texture sampler
|
||||||
|
{
|
||||||
|
VkSamplerCreateInfo samplerInfo{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||||
|
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||||
|
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||||
|
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
samplerInfo.anisotropyEnable = VK_TRUE;
|
||||||
|
// Find max anisotropic filtering level
|
||||||
|
{
|
||||||
|
VkPhysicalDeviceProperties properties{};
|
||||||
|
vkGetPhysicalDeviceProperties(pimpl->physicalDevice, &properties);
|
||||||
|
|
||||||
|
INFO("Anisotropic filtering level: {}", properties.limits.maxSamplerAnisotropy);
|
||||||
|
samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
|
||||||
|
}
|
||||||
|
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||||
|
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
||||||
|
samplerInfo.compareEnable = VK_FALSE;
|
||||||
|
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
|
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
|
samplerInfo.minLod = 0.0f;
|
||||||
|
samplerInfo.maxLod = static_cast<float>(out->mipLevels);
|
||||||
|
samplerInfo.mipLodBias = 0.0f;
|
||||||
|
|
||||||
|
res = vkCreateSampler(pimpl->device, &samplerInfo, nullptr, &out->sampler);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create descriptor pools
|
||||||
|
VkDescriptorPoolSize poolSize{};
|
||||||
|
poolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
poolSize.descriptorCount = FRAMES_IN_FLIGHT;
|
||||||
|
|
||||||
|
VkDescriptorPoolCreateInfo poolInfo{};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
|
poolInfo.poolSizeCount = 1;
|
||||||
|
poolInfo.pPoolSizes = &poolSize;
|
||||||
|
poolInfo.maxSets = FRAMES_IN_FLIGHT;
|
||||||
|
res = vkCreateDescriptorPool(pimpl->device, &poolInfo, nullptr, &out->pool);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
std::array<VkDescriptorSetLayout, FRAMES_IN_FLIGHT> layouts{};
|
||||||
|
layouts.fill(pimpl->samplerSetLayout);
|
||||||
|
VkDescriptorSetAllocateInfo dSetAllocInfo{};
|
||||||
|
dSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
|
dSetAllocInfo.descriptorPool = out->pool;
|
||||||
|
dSetAllocInfo.descriptorSetCount = FRAMES_IN_FLIGHT;
|
||||||
|
dSetAllocInfo.pSetLayouts = layouts.data();
|
||||||
|
res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, out->descriptorSets.data());
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
|
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
|
VkDescriptorImageInfo imageInfo{};
|
||||||
|
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
imageInfo.imageView = out->imageView;
|
||||||
|
imageInfo.sampler = out->sampler;
|
||||||
|
|
||||||
|
VkWriteDescriptorSet descriptorWrite{};
|
||||||
|
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
descriptorWrite.dstSet = out->descriptorSets[i];
|
||||||
|
descriptorWrite.dstBinding = 0;
|
||||||
|
descriptorWrite.dstArrayElement = 0;
|
||||||
|
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
descriptorWrite.descriptorCount = 1;
|
||||||
|
descriptorWrite.pImageInfo = &imageInfo;
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(pimpl->device, 1, &descriptorWrite, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::destroyTexture(const gfx::Texture* texture)
|
void GFXDevice::destroyTexture(const gfx::Texture* texture)
|
||||||
{
|
{
|
||||||
|
vkDestroyDescriptorPool(pimpl->device, texture->pool, nullptr);
|
||||||
|
vkDestroySampler(pimpl->device, texture->sampler, nullptr);
|
||||||
|
vkDestroyImageView(pimpl->device, texture->imageView, nullptr);
|
||||||
vmaDestroyImage(pimpl->allocator, texture->image, texture->alloc);
|
vmaDestroyImage(pimpl->allocator, texture->image, texture->alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ static void loadMeshFromFile(const std::filesystem::path& path, std::vector<Vert
|
|||||||
vertices->resize(header.vertex_count);
|
vertices->resize(header.vertex_count);
|
||||||
|
|
||||||
fread(indices->data(), sizeof(uint32_t) * header.index_count, 1, fp);
|
fread(indices->data(), sizeof(uint32_t) * header.index_count, 1, fp);
|
||||||
fread(vertices->data(), sizeof(float) * 8 * header.vertex_count, 1, fp);
|
fread(vertices->data(), sizeof(Vertex) * header.vertex_count, 1, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
namespace engine::resources {
|
namespace engine::resources {
|
||||||
|
|
||||||
// returns false if unable to open file
|
// returns false if unable to open file
|
||||||
static bool readPNG(const std::string& path, std::vector<uint8_t>& texbuf, int *width, int *height, bool *isRGBA)
|
static bool readPNG(const std::string& path, std::vector<uint8_t>* texbuf, int *width, int *height, bool *isRGBA)
|
||||||
{
|
{
|
||||||
int x, y, n;
|
int x, y, n;
|
||||||
unsigned char *data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha);
|
unsigned char *data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha);
|
||||||
@ -22,8 +22,8 @@ static bool readPNG(const std::string& path, std::vector<uint8_t>& texbuf, int *
|
|||||||
|
|
||||||
const size_t size = (size_t)x * (size_t)y * 4;
|
const size_t size = (size_t)x * (size_t)y * 4;
|
||||||
|
|
||||||
texbuf.resize(size);
|
texbuf->resize(size);
|
||||||
memcpy(texbuf.data(), data, size);
|
memcpy(texbuf->data(), data, size);
|
||||||
|
|
||||||
*width = x;
|
*width = x;
|
||||||
*height = y;
|
*height = y;
|
||||||
@ -35,7 +35,7 @@ static bool readPNG(const std::string& path, std::vector<uint8_t>& texbuf, int *
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool readGLRaw(const std::string& path, std::vector<uint8_t>& texbuf, int *width, int *height, bool *isRGBA)
|
static bool readGLRaw(const std::string& path, std::vector<uint8_t>* texbuf, int *width, int *height, bool *isRGBA)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(path.c_str(), "rb");
|
FILE *fp = fopen(path.c_str(), "rb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
@ -49,9 +49,9 @@ static bool readGLRaw(const std::string& path, std::vector<uint8_t>& texbuf, int
|
|||||||
fseek(fp, 0L, SEEK_END);
|
fseek(fp, 0L, SEEK_END);
|
||||||
uint64_t end = ftell(fp);
|
uint64_t end = ftell(fp);
|
||||||
|
|
||||||
texbuf.resize(end);
|
texbuf->resize(end);
|
||||||
fseek(fp, (long)tex_data_offset, SEEK_SET);
|
fseek(fp, (long)tex_data_offset, SEEK_SET);
|
||||||
fread(texbuf.data(), 1, end, fp);
|
fread(texbuf->data(), 1, end, fp);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
@ -66,15 +66,15 @@ static bool readGLRaw(const std::string& path, std::vector<uint8_t>& texbuf, int
|
|||||||
Texture::Texture(const std::filesystem::path& resPath) : Resource(resPath, "texture")
|
Texture::Texture(const std::filesystem::path& resPath) : Resource(resPath, "texture")
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<uint8_t> texbuf;
|
auto texbuf = std::make_unique<std::vector<uint8_t>>();
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
bool isRGBA, success;
|
bool isRGBA, success;
|
||||||
|
|
||||||
if (resPath.extension() == ".png") {
|
if (resPath.extension() == ".png" || resPath.extension() == ".jpg") {
|
||||||
success = readPNG(resPath.string(), texbuf, &width, &height, &isRGBA);
|
success = readPNG(resPath.string(), texbuf.get(), &width, &height, &isRGBA);
|
||||||
} else {
|
} else {
|
||||||
success = readGLRaw(resPath.string(), texbuf, &width, &height, &isRGBA);
|
success = readGLRaw(resPath.string(), texbuf.get(), &width, &height, &isRGBA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@ -82,12 +82,12 @@ Texture::Texture(const std::filesystem::path& resPath) : Resource(resPath, "text
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isRGBA == false) {
|
if (isRGBA == false) {
|
||||||
throw std::runtime_error("Currently, only RGBA textures are supported. Size: " + std::to_string(texbuf.size()));
|
throw std::runtime_error("Currently, only RGBA textures are supported. Size: " + std::to_string(texbuf->size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_gpuTexture = gfxdev->createTexture(texbuf.data(), (uint32_t)width, (uint32_t)height);
|
m_gpuTexture = gfxdev->createTexture(texbuf->data(), (uint32_t)width, (uint32_t)height);
|
||||||
|
|
||||||
DEBUG("loaded texture {} width: {} height: {} size: {}", resPath.filename().string(), width, height, texbuf.size());
|
DEBUG("loaded texture {} width: {} height: {} size: {}", resPath.filename().string(), width, height, texbuf->size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,4 +96,9 @@ Texture::~Texture()
|
|||||||
gfxdev->destroyTexture(m_gpuTexture);
|
gfxdev->destroyTexture(m_gpuTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx::Texture* Texture::getHandle()
|
||||||
|
{
|
||||||
|
return m_gpuTexture;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -276,12 +276,19 @@ namespace engine {
|
|||||||
|
|
||||||
void Window::setFullscreen(bool fullscreen, bool exclusive)
|
void Window::setFullscreen(bool fullscreen, bool exclusive)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_resizable) {
|
if (m_resizable) {
|
||||||
|
|
||||||
|
SDL_DisplayMode mode;
|
||||||
|
SDL_GetDesktopDisplayMode(SDL_GetWindowDisplayIndex(m_handle), &mode);
|
||||||
|
SDL_SetWindowDisplayMode(m_handle, &mode);
|
||||||
|
|
||||||
if (SDL_SetWindowFullscreen(m_handle, fullscreen ? (exclusive ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP) : 0) != 0) {
|
if (SDL_SetWindowFullscreen(m_handle, fullscreen ? (exclusive ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP) : 0) != 0) {
|
||||||
throw std::runtime_error("Unable to set window to fullscreen/windowed");
|
throw std::runtime_error("Unable to set window to fullscreen/windowed");
|
||||||
}
|
}
|
||||||
m_fullscreen = fullscreen;
|
m_fullscreen = fullscreen;
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_GetWindowSize(m_handle, &width, &height);
|
SDL_GetWindowSize(m_handle, &width, &height);
|
||||||
onResize(width, height);
|
onResize(width, height);
|
||||||
@ -291,7 +298,7 @@ namespace engine {
|
|||||||
|
|
||||||
void Window::toggleFullscreen()
|
void Window::toggleFullscreen()
|
||||||
{
|
{
|
||||||
setFullscreen(!m_fullscreen, false);
|
setFullscreen(!m_fullscreen, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::isFullscreen() const
|
bool Window::isFullscreen() const
|
||||||
|
BIN
test/game.aps
Normal file
BIN
test/game.aps
Normal file
Binary file not shown.
BIN
test/res/meshes/castle_0.mesh
Normal file
BIN
test/res/meshes/castle_0.mesh
Normal file
Binary file not shown.
BIN
test/res/meshes/castle_1.mesh
Normal file
BIN
test/res/meshes/castle_1.mesh
Normal file
Binary file not shown.
BIN
test/res/meshes/castle_2.mesh
Normal file
BIN
test/res/meshes/castle_2.mesh
Normal file
Binary file not shown.
BIN
test/res/meshes/castle_3.mesh
Normal file
BIN
test/res/meshes/castle_3.mesh
Normal file
Binary file not shown.
BIN
test/res/meshes/castle_4.mesh
Normal file
BIN
test/res/meshes/castle_4.mesh
Normal file
Binary file not shown.
BIN
test/res/meshes/castle_5.mesh
Normal file
BIN
test/res/meshes/castle_5.mesh
Normal file
Binary file not shown.
@ -8,7 +8,7 @@ layout(location = 4) in vec3 fragColor;
|
|||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
float snoise(vec2 v);
|
layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ void main() {
|
|||||||
vec3 lightColor = vec3(1.0, 1.0, 1.0);
|
vec3 lightColor = vec3(1.0, 1.0, 1.0);
|
||||||
vec3 ambientColor = vec3(1.0, 1.0, 1.0);
|
vec3 ambientColor = vec3(1.0, 1.0, 1.0);
|
||||||
float ambientStrength = 0.1;
|
float ambientStrength = 0.1;
|
||||||
vec3 baseColor = vec3(fragColor.x * snoise(fragUV * 10.0), mod(fragUV.x, 1.0), mod(fragUV.y, 1.0));
|
vec3 baseColor = vec3(texture(texSampler, fragUV));
|
||||||
vec3 emission = vec3(0.0, 0.0, 0.0);
|
vec3 emission = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
// code
|
// code
|
||||||
@ -36,36 +36,3 @@ void main() {
|
|||||||
vec3 lighting = min(diffuse + ambient + specular, 1.0);
|
vec3 lighting = min(diffuse + ambient + specular, 1.0);
|
||||||
outColor = min( ( vec4(baseColor, 1.0) ) * vec4(lighting + emission, 1.0), vec4(1.0));
|
outColor = min( ( vec4(baseColor, 1.0) ) * vec4(lighting + emission, 1.0), vec4(1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Simplex 2D noise
|
|
||||||
//
|
|
||||||
vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }
|
|
||||||
|
|
||||||
float snoise(vec2 v){
|
|
||||||
const vec4 C = vec4(0.211324865405187, 0.366025403784439,
|
|
||||||
-0.577350269189626, 0.024390243902439);
|
|
||||||
vec2 i = floor(v + dot(v, C.yy) );
|
|
||||||
vec2 x0 = v - i + dot(i, C.xx);
|
|
||||||
vec2 i1;
|
|
||||||
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
|
||||||
vec4 x12 = x0.xyxy + C.xxzz;
|
|
||||||
x12.xy -= i1;
|
|
||||||
i = mod(i, 289.0);
|
|
||||||
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
|
|
||||||
+ i.x + vec3(0.0, i1.x, 1.0 ));
|
|
||||||
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy),
|
|
||||||
dot(x12.zw,x12.zw)), 0.0);
|
|
||||||
m = m*m ;
|
|
||||||
m = m*m ;
|
|
||||||
vec3 x = 2.0 * fract(p * C.www) - 1.0;
|
|
||||||
vec3 h = abs(x) - 0.5;
|
|
||||||
vec3 ox = floor(x + 0.5);
|
|
||||||
vec3 a0 = x - ox;
|
|
||||||
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
|
|
||||||
vec3 g;
|
|
||||||
g.x = a0.x * x0.x + h.x * x0.y;
|
|
||||||
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
|
||||||
return 130.0 * dot(m, g);
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
BIN
test/res/textures/door.jpg
Normal file
BIN
test/res/textures/door.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 462 KiB |
BIN
test/res/textures/grass.jpg
Normal file
BIN
test/res/textures/grass.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 205 KiB |
BIN
test/res/textures/metal.jpg
Normal file
BIN
test/res/textures/metal.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
BIN
test/res/textures/rock.jpg
Normal file
BIN
test/res/textures/rock.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 476 KiB |
@ -56,8 +56,8 @@ void playGame()
|
|||||||
auto camCamera = cam->createComponent<engine::components::Camera>();
|
auto camCamera = cam->createComponent<engine::components::Camera>();
|
||||||
camCamera->usePerspective(70.0f);
|
camCamera->usePerspective(70.0f);
|
||||||
cam->createComponent<CameraController>();
|
cam->createComponent<CameraController>();
|
||||||
cam->createComponent<engine::components::Renderer>()->m_mesh = genSphereMesh(0.2f, 20);
|
//cam->createComponent<engine::components::Renderer>()->m_mesh = genSphereMesh(0.2f, 20);
|
||||||
cam->getComponent<engine::components::Renderer>()->setTexture("textures/cobble_stone.png");
|
//cam->getComponent<engine::components::Renderer>()->setTexture("textures/cobble_stone.png");
|
||||||
|
|
||||||
auto gun = cam->createChild("gun");
|
auto gun = cam->createChild("gun");
|
||||||
gun->transform.position = glm::vec3{ 0.2f, -0.1f, -0.15f };
|
gun->transform.position = glm::vec3{ 0.2f, -0.1f, -0.15f };
|
||||||
@ -76,7 +76,7 @@ void playGame()
|
|||||||
auto floor = app.scene()->createChild("floor");
|
auto floor = app.scene()->createChild("floor");
|
||||||
auto floorRenderer = floor->createComponent<engine::components::Renderer>();
|
auto floorRenderer = floor->createComponent<engine::components::Renderer>();
|
||||||
floor->transform.position = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
floor->transform.position = glm::vec3{ 0.0f, 0.0f, 0.0f };
|
||||||
floorRenderer->setTexture("textures/stone_bricks.png");
|
floorRenderer->setTexture("textures/grass.jpg");
|
||||||
floorRenderer->m_mesh = std::make_unique<engine::resources::Mesh>(std::vector<Vertex>{
|
floorRenderer->m_mesh = std::make_unique<engine::resources::Mesh>(std::vector<Vertex>{
|
||||||
{ { -16.0f, 0.0f, 16.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, GRASS_DENSITY } },
|
{ { -16.0f, 0.0f, 16.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, GRASS_DENSITY } },
|
||||||
{ { 16.0f, 0.0f, -16.0f }, { 0.0f, 1.0f, 0.0f }, { GRASS_DENSITY, 0.0f } },
|
{ { 16.0f, 0.0f, -16.0f }, { 0.0f, 1.0f, 0.0f }, { GRASS_DENSITY, 0.0f } },
|
||||||
@ -128,5 +128,30 @@ void playGame()
|
|||||||
sphereRenderer->m_mesh = genSphereMesh(5.0f, 100, false);
|
sphereRenderer->m_mesh = genSphereMesh(5.0f, 100, false);
|
||||||
sphereRenderer->setTexture("textures/cobble_stone.png");
|
sphereRenderer->setTexture("textures/cobble_stone.png");
|
||||||
|
|
||||||
|
/* castle */
|
||||||
|
auto castle = app.scene()->createChild("castle");
|
||||||
|
castle->transform.scale = { 0.01f, 0.01f, 0.01f };
|
||||||
|
std::vector<engine::Object*> castleParts(6);
|
||||||
|
for (int i = 0; i < castleParts.size(); i++) {
|
||||||
|
if (i == 2) continue;
|
||||||
|
castleParts[i] = castle->createChild(std::to_string(i));
|
||||||
|
auto ren = castleParts[i]->createComponent<engine::components::Renderer>();
|
||||||
|
ren->setMesh("meshes/castle_" + std::to_string(i) + ".mesh");
|
||||||
|
ren->setTexture("textures/rock.jpg");
|
||||||
|
|
||||||
|
if (i == 5) {
|
||||||
|
ren->setTexture("textures/metal.jpg");
|
||||||
|
}
|
||||||
|
if (i == 4) {
|
||||||
|
ren->setTexture("textures/door.jpg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// boundary
|
||||||
|
auto bounds = app.scene()->createChild("bounds");
|
||||||
|
auto boundsRen = bounds->createComponent<engine::components::Renderer>();
|
||||||
|
boundsRen->m_mesh = genSphereMesh(100.0f, 100, true);
|
||||||
|
boundsRen->setTexture("textures/metal.jpg");
|
||||||
|
|
||||||
app.gameLoop();
|
app.gameLoop();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user