Added frustum culling, use low-poly mesh to move limitation towards cpu
This commit is contained in:
parent
7768992bda
commit
a41ff27bb9
7 changed files with 1599 additions and 18 deletions
|
|
@ -8,7 +8,7 @@ if %ERRORLEVEL% EQU 0 (
|
||||||
xcopy "..\..\data\shaders\multithreading\*.spv" "assets\shaders\multithreading" /Y
|
xcopy "..\..\data\shaders\multithreading\*.spv" "assets\shaders\multithreading" /Y
|
||||||
|
|
||||||
mkdir "assets\models"
|
mkdir "assets\models"
|
||||||
xcopy "..\..\data\models\retroufo_red.dae" "assets\models" /Y
|
xcopy "..\..\data\models\retroufo_red_lowpoly.dae" "assets\models" /Y
|
||||||
xcopy "..\..\data\models\sphere.obj" "assets\models" /Y
|
xcopy "..\..\data\models\sphere.obj" "assets\models" /Y
|
||||||
|
|
||||||
mkdir "res\drawable"
|
mkdir "res\drawable"
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ namespace vkMeshLoader
|
||||||
MeshBufferInfo vertices;
|
MeshBufferInfo vertices;
|
||||||
MeshBufferInfo indices;
|
MeshBufferInfo indices;
|
||||||
uint32_t indexCount;
|
uint32_t indexCount;
|
||||||
|
glm::vec3 dim;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get vertex size from vertex layout
|
// Get vertex size from vertex layout
|
||||||
|
|
@ -449,6 +450,10 @@ public:
|
||||||
}
|
}
|
||||||
meshBuffer->vertices.size = vertexBuffer.size() * sizeof(float);
|
meshBuffer->vertices.size = vertexBuffer.size() * sizeof(float);
|
||||||
|
|
||||||
|
dim.min *= scale;
|
||||||
|
dim.max *= scale;
|
||||||
|
dim.size *= scale;
|
||||||
|
|
||||||
std::vector<uint32_t> indexBuffer;
|
std::vector<uint32_t> indexBuffer;
|
||||||
for (uint32_t m = 0; m < m_Entries.size(); m++)
|
for (uint32_t m = 0; m < m_Entries.size(); m++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -309,6 +309,8 @@ void VulkanExampleBase::loadMesh(
|
||||||
vertexLayout,
|
vertexLayout,
|
||||||
scale);
|
scale);
|
||||||
|
|
||||||
|
meshBuffer->dim = mesh->dim.size;
|
||||||
|
|
||||||
delete(mesh);
|
delete(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1549
data/models/retroufo_red_lowpoly.dae
Normal file
1549
data/models/retroufo_red_lowpoly.dae
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -22,6 +22,7 @@
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
|
|
||||||
#include "threadpool.hpp"
|
#include "threadpool.hpp"
|
||||||
|
#include "frustum.hpp"
|
||||||
|
|
||||||
#define VERTEX_BUFFER_BIND_ID 0
|
#define VERTEX_BUFFER_BIND_ID 0
|
||||||
#define ENABLE_VALIDATION false
|
#define ENABLE_VALIDATION false
|
||||||
|
|
@ -88,6 +89,8 @@ public:
|
||||||
float rotationSpeed;
|
float rotationSpeed;
|
||||||
float scale;
|
float scale;
|
||||||
float deltaT;
|
float deltaT;
|
||||||
|
float stateT = 0;
|
||||||
|
bool visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ThreadData {
|
struct ThreadData {
|
||||||
|
|
@ -104,17 +107,21 @@ public:
|
||||||
|
|
||||||
vkTools::ThreadPool threadPool;
|
vkTools::ThreadPool threadPool;
|
||||||
|
|
||||||
|
// Max. dimension of the ufo mesh for use as the sphere
|
||||||
|
// radius for frustum culling
|
||||||
|
float objectSphereDim;
|
||||||
|
|
||||||
|
// View frustum for culling invisible objects
|
||||||
|
vkTools::Frustum frustum;
|
||||||
|
|
||||||
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
||||||
{
|
{
|
||||||
width = 1280;
|
zoom = -32.5f;
|
||||||
height = 720;
|
|
||||||
zoom = -16.0f;
|
|
||||||
zoomSpeed = 2.5f;
|
zoomSpeed = 2.5f;
|
||||||
rotationSpeed = 0.5f;
|
rotationSpeed = 0.5f;
|
||||||
rotation = { -30.0f, -35.0f, 0.0f };
|
rotation = { 0.0f, 37.5f, 0.0f };
|
||||||
title = "Vulkan Example - Multi threaded rendering";
|
title = "Vulkan Example - Multi threaded rendering";
|
||||||
// Get number of max. concurrrent threads
|
// Get number of max. concurrrent threads
|
||||||
// todo : May not work on all compilers (e.g. old GCC versions?)
|
|
||||||
numThreads = std::thread::hardware_concurrency();
|
numThreads = std::thread::hardware_concurrency();
|
||||||
assert(numThreads > 0);
|
assert(numThreads > 0);
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
|
|
@ -126,7 +133,7 @@ public:
|
||||||
|
|
||||||
threadPool.setThreadCount(numThreads);
|
threadPool.setThreadCount(numThreads);
|
||||||
|
|
||||||
numObjectsPerThread = 128 / numThreads;
|
numObjectsPerThread = 256 / numThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
~VulkanExample()
|
~VulkanExample()
|
||||||
|
|
@ -262,7 +269,7 @@ public:
|
||||||
thread->objectData[j].rotation = glm::vec3(0.0f, rnd(360.0f), 0.0f);
|
thread->objectData[j].rotation = glm::vec3(0.0f, rnd(360.0f), 0.0f);
|
||||||
thread->objectData[j].deltaT = rnd(1.0f);
|
thread->objectData[j].deltaT = rnd(1.0f);
|
||||||
thread->objectData[j].rotationDir = (rnd(100.0f) < 50.0f) ? 1.0f : -1.0f;
|
thread->objectData[j].rotationDir = (rnd(100.0f) < 50.0f) ? 1.0f : -1.0f;
|
||||||
thread->objectData[j].rotationSpeed = (2.0f + rnd(4.0f)) * thread->objectData[i].rotationDir;
|
thread->objectData[j].rotationSpeed = (2.0f + rnd(4.0f)) * thread->objectData[j].rotationDir;
|
||||||
thread->objectData[j].scale = 0.75f + rnd(0.5f);
|
thread->objectData[j].scale = 0.75f + rnd(0.5f);
|
||||||
|
|
||||||
thread->pushConstBlock[j].color = glm::vec3(rnd(1.0f), rnd(1.0f), rnd(1.0f));
|
thread->pushConstBlock[j].color = glm::vec3(rnd(1.0f), rnd(1.0f), rnd(1.0f));
|
||||||
|
|
@ -277,11 +284,21 @@ public:
|
||||||
// Builds the secondary command buffer for each thread
|
// Builds the secondary command buffer for each thread
|
||||||
void threadRenderCode(uint32_t threadIndex, uint32_t cmdBufferIndex, VkCommandBufferInheritanceInfo inheritanceInfo)
|
void threadRenderCode(uint32_t threadIndex, uint32_t cmdBufferIndex, VkCommandBufferInheritanceInfo inheritanceInfo)
|
||||||
{
|
{
|
||||||
|
ThreadData *thread = &threadData[threadIndex];
|
||||||
|
ObjectData *objectData = &thread->objectData[cmdBufferIndex];
|
||||||
|
|
||||||
|
// Check visibility against view frustum
|
||||||
|
objectData->visible = frustum.checkSphere(objectData->pos, objectSphereDim * 0.5f);
|
||||||
|
|
||||||
|
if (!objectData->visible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VkCommandBufferBeginInfo commandBufferBeginInfo = vkTools::initializers::commandBufferBeginInfo();
|
VkCommandBufferBeginInfo commandBufferBeginInfo = vkTools::initializers::commandBufferBeginInfo();
|
||||||
commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
|
commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
|
||||||
commandBufferBeginInfo.pInheritanceInfo = &inheritanceInfo;
|
commandBufferBeginInfo.pInheritanceInfo = &inheritanceInfo;
|
||||||
|
|
||||||
ThreadData *thread = &threadData[threadIndex];
|
|
||||||
VkCommandBuffer cmdBuffer = thread->commandBuffer[cmdBufferIndex];
|
VkCommandBuffer cmdBuffer = thread->commandBuffer[cmdBufferIndex];
|
||||||
|
|
||||||
vkTools::checkResult(vkBeginCommandBuffer(cmdBuffer, &commandBufferBeginInfo));
|
vkTools::checkResult(vkBeginCommandBuffer(cmdBuffer, &commandBufferBeginInfo));
|
||||||
|
|
@ -295,17 +312,15 @@ public:
|
||||||
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phong);
|
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phong);
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
// todo : timebased
|
objectData->rotation.y += 2.5f * objectData->rotationSpeed * frameTimer;
|
||||||
ObjectData *objectData = &thread->objectData[cmdBufferIndex];
|
|
||||||
objectData->rotation.y += 0.15f * objectData->rotationSpeed;
|
|
||||||
if (objectData->rotation.y > 360.0f)
|
if (objectData->rotation.y > 360.0f)
|
||||||
{
|
{
|
||||||
objectData->rotation.y -= 360.0f;
|
objectData->rotation.y -= 360.0f;
|
||||||
}
|
}
|
||||||
objectData->deltaT += 0.0015f;
|
objectData->deltaT += 0.15f * frameTimer;
|
||||||
if (objectData->deltaT > 1.0f)
|
if (objectData->deltaT > 1.0f)
|
||||||
objectData->deltaT -= 1.0f;
|
objectData->deltaT -= 1.0f;
|
||||||
objectData->pos.y = sin(glm::radians(objectData->deltaT * 360.0f)) * 1.5f;
|
objectData->pos.y = sin(glm::radians(objectData->deltaT * 360.0f)) * 2.5f;
|
||||||
|
|
||||||
objectData->model = glm::translate(glm::mat4(), objectData->pos);
|
objectData->model = glm::translate(glm::mat4(), objectData->pos);
|
||||||
objectData->model = glm::rotate(objectData->model, -sinf(glm::radians(objectData->deltaT * 360.0f)) * 0.25f, glm::vec3(objectData->rotationDir, 0.0f, 0.0f));
|
objectData->model = glm::rotate(objectData->model, -sinf(glm::radians(objectData->deltaT * 360.0f)) * 0.25f, glm::vec3(objectData->rotationDir, 0.0f, 0.0f));
|
||||||
|
|
@ -423,9 +438,13 @@ public:
|
||||||
for (uint32_t i = 0; i < numObjectsPerThread; i++)
|
for (uint32_t i = 0; i < numObjectsPerThread; i++)
|
||||||
{
|
{
|
||||||
threadPool.threads[t]->addJob([=] { threadRenderCode(t, i, inheritanceInfo); });
|
threadPool.threads[t]->addJob([=] { threadRenderCode(t, i, inheritanceInfo); });
|
||||||
|
// Only submit if object is within the current view frustum
|
||||||
|
if (threadData[t].objectData[i].visible)
|
||||||
|
{
|
||||||
commandBuffers.push_back(threadData[t].commandBuffer[i]);
|
commandBuffers.push_back(threadData[t].commandBuffer[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
threadPool.wait();
|
threadPool.wait();
|
||||||
|
|
||||||
|
|
@ -461,7 +480,6 @@ public:
|
||||||
VkResult fenceRes;
|
VkResult fenceRes;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// todo : timeout as define
|
|
||||||
fenceRes = vkWaitForFences(device, 1, &renderFence, VK_TRUE, 100000000);
|
fenceRes = vkWaitForFences(device, 1, &renderFence, VK_TRUE, 100000000);
|
||||||
} while (fenceRes == VK_TIMEOUT);
|
} while (fenceRes == VK_TIMEOUT);
|
||||||
vkTools::checkResult(fenceRes);
|
vkTools::checkResult(fenceRes);
|
||||||
|
|
@ -477,8 +495,9 @@ public:
|
||||||
|
|
||||||
void loadMeshes()
|
void loadMeshes()
|
||||||
{
|
{
|
||||||
loadMesh(getAssetPath() + "models/retroufo_red.dae", &meshes.ufo, vertexLayout, 0.12f);
|
loadMesh(getAssetPath() + "models/retroufo_red_lowpoly.dae", &meshes.ufo, vertexLayout, 0.12f);
|
||||||
loadMesh(getAssetPath() + "models/sphere.obj", &meshes.skysphere, vertexLayout, 1.0f);
|
loadMesh(getAssetPath() + "models/sphere.obj", &meshes.skysphere, vertexLayout, 1.0f);
|
||||||
|
objectSphereDim = std::max(std::max(meshes.ufo.dim.x, meshes.ufo.dim.y), meshes.ufo.dim.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupVertexDescriptions()
|
void setupVertexDescriptions()
|
||||||
|
|
@ -632,6 +651,8 @@ public:
|
||||||
matrices.view = glm::rotate(matrices.view, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
|
matrices.view = glm::rotate(matrices.view, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
matrices.view = glm::rotate(matrices.view, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
|
matrices.view = glm::rotate(matrices.view, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
matrices.view = glm::rotate(matrices.view, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
|
matrices.view = glm::rotate(matrices.view, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
frustum.update(matrices.projection * matrices.view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<ClCompile Include="multithreading.cpp" />
|
<ClCompile Include="multithreading.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\base\frustum.hpp" />
|
||||||
<ClInclude Include="..\base\threadpool.hpp" />
|
<ClInclude Include="..\base\threadpool.hpp" />
|
||||||
<ClInclude Include="..\base\vulkandebug.h" />
|
<ClInclude Include="..\base\vulkandebug.h" />
|
||||||
<ClInclude Include="..\base\vulkanexamplebase.h" />
|
<ClInclude Include="..\base\vulkanexamplebase.h" />
|
||||||
|
|
|
||||||
|
|
@ -41,5 +41,8 @@
|
||||||
<ClInclude Include="..\base\threadpool.hpp">
|
<ClInclude Include="..\base\threadpool.hpp">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\base\frustum.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue