Merge
This commit is contained in:
Vendored
-20
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "(lldb) Launch",
|
|
||||||
"type": "cppdbg",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "${workspaceFolder}/bin/RayTracer",
|
|
||||||
"args": [],
|
|
||||||
"stopAtEntry": false,
|
|
||||||
"cwd": "${workspaceFolder}/bin/",
|
|
||||||
"environment": [],
|
|
||||||
"externalConsole": false,
|
|
||||||
"MIMode": "lldb"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"cmake.buildDirectory": "${workspaceFolder}/bin/",
|
|
||||||
"cmake.generator": ""
|
|
||||||
}
|
|
||||||
+3
-4
@@ -11,6 +11,7 @@ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/external/vcpkg/scripts/buil
|
|||||||
|
|
||||||
project(RayTracer)
|
project(RayTracer)
|
||||||
|
|
||||||
|
find_package(Vulkan REQUIRED)
|
||||||
find_package(glew CONFIG REQUIRED)
|
find_package(glew CONFIG REQUIRED)
|
||||||
find_package(assimp CONFIG REQUIRED)
|
find_package(assimp CONFIG REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
@@ -20,14 +21,12 @@ find_package(imgui CONFIG REQUIRED)
|
|||||||
|
|
||||||
add_executable(RayTracer "")
|
add_executable(RayTracer "")
|
||||||
target_include_directories(RayTracer PUBLIC src/)
|
target_include_directories(RayTracer PUBLIC src/)
|
||||||
|
target_link_libraries(RayTracer PUBLIC Vulkan::Vulkan)
|
||||||
|
target_link_libraries(RayTracer PUBLIC Vulkan::Headers)
|
||||||
target_link_libraries(RayTracer PUBLIC assimp::assimp)
|
target_link_libraries(RayTracer PUBLIC assimp::assimp)
|
||||||
target_link_libraries(RayTracer PUBLIC glfw)
|
target_link_libraries(RayTracer PUBLIC glfw)
|
||||||
target_link_libraries(RayTracer PUBLIC imgui::imgui)
|
target_link_libraries(RayTracer PUBLIC imgui::imgui)
|
||||||
if(APPLE)
|
|
||||||
target_link_libraries(RayTracer PUBLIC GLEW::GLEW)
|
target_link_libraries(RayTracer PUBLIC GLEW::GLEW)
|
||||||
else()
|
|
||||||
target_link_libraries(RayTracer PUBLIC GLEW::glew)
|
|
||||||
endif()
|
|
||||||
target_link_libraries(RayTracer PUBLIC glm::glm)
|
target_link_libraries(RayTracer PUBLIC glm::glm)
|
||||||
target_link_libraries(RayTracer PUBLIC KTX::ktx)
|
target_link_libraries(RayTracer PUBLIC KTX::ktx)
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
Submodule external/vcpkg updated: 01be99fec0...791ae5e74b
+3
-1
@@ -3,8 +3,10 @@ target_sources(RayTracer
|
|||||||
main.cpp
|
main.cpp
|
||||||
Minimal.h
|
Minimal.h
|
||||||
ThreadPool.h
|
ThreadPool.h
|
||||||
ThreadPool.cpp)
|
ThreadPool.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(gpu/)
|
||||||
add_subdirectory(scene/)
|
add_subdirectory(scene/)
|
||||||
add_subdirectory(window/)
|
add_subdirectory(window/)
|
||||||
add_subdirectory(util/)
|
add_subdirectory(util/)
|
||||||
|
|||||||
+17
-4
@@ -1,9 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <coroutine>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#define DEFINE_REF(x) \
|
#define DEFINE_REF(x) typedef ::std::unique_ptr<x> P##x;
|
||||||
typedef ::std::unique_ptr<x> P##x; \
|
|
||||||
|
|
||||||
#define DECLARE_REF(x) \
|
#define DECLARE_REF(x) \
|
||||||
class x; \
|
class x; \
|
||||||
typedef ::std::unique_ptr<x> P##x; \
|
typedef ::std::unique_ptr<x> P##x;
|
||||||
|
|
||||||
|
struct Task
|
||||||
|
{
|
||||||
|
struct promise_type
|
||||||
|
{
|
||||||
|
Task get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
|
||||||
|
std::suspend_always initial_suspend() noexcept { return {}; }
|
||||||
|
std::suspend_never final_suspend() noexcept { return {}; }
|
||||||
|
void return_void() {}
|
||||||
|
void unhandled_exception() {}
|
||||||
|
};
|
||||||
|
std::coroutine_handle<promise_type> handle;
|
||||||
|
};
|
||||||
|
|||||||
+48
-46
@@ -3,64 +3,66 @@
|
|||||||
|
|
||||||
ThreadPool::ThreadPool(uint32_t numThreads)
|
ThreadPool::ThreadPool(uint32_t numThreads)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < numThreads; ++i)
|
for (uint32_t i = 0; i < numThreads; ++i)
|
||||||
{
|
{
|
||||||
workers.push_back(std::thread(&ThreadPool::work, this));
|
workers.push_back(std::thread(&ThreadPool::work, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPool::~ThreadPool()
|
ThreadPool::~ThreadPool()
|
||||||
{
|
{
|
||||||
running.store(false);
|
running.store(false);
|
||||||
{
|
{
|
||||||
std::unique_lock l(queueLock);
|
std::unique_lock l(queueLock);
|
||||||
queueCV.notify_all();
|
queueCV.notify_all();
|
||||||
}
|
}
|
||||||
for (auto& worker : workers)
|
for (auto& worker : workers)
|
||||||
{
|
{
|
||||||
worker.join();
|
worker.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadPool::runBatch(Batch&& batch)
|
void ThreadPool::runBatch(Batch&& batch)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::unique_lock l(queueLock);
|
std::unique_lock l(queueLock);
|
||||||
taskQueue.push_back(batch);
|
numRemaining = batch.jobs.size();
|
||||||
queueCV.notify_one();
|
taskQueue.push_back(batch);
|
||||||
}
|
queueCV.notify_all();
|
||||||
while (true)
|
}
|
||||||
{
|
while (true)
|
||||||
std::unique_lock l(queueLock);
|
{
|
||||||
if (taskQueue.empty())
|
std::unique_lock l(queueLock);
|
||||||
return;
|
if (taskQueue.empty())
|
||||||
completedCV.wait(l);
|
return;
|
||||||
}
|
completedCV.wait(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadPool::work()
|
void ThreadPool::work()
|
||||||
{
|
{
|
||||||
while (running)
|
while (running)
|
||||||
|
{
|
||||||
|
Task job;
|
||||||
{
|
{
|
||||||
std::function<void()> job;
|
std::unique_lock l(queueLock);
|
||||||
{
|
if (taskQueue.empty() || taskQueue.front().jobs.empty())
|
||||||
std::unique_lock l(queueLock);
|
{
|
||||||
if (taskQueue.empty() || taskQueue.front().jobs.empty())
|
queueCV.wait(l);
|
||||||
{
|
continue;
|
||||||
queueCV.wait(l);
|
}
|
||||||
continue;
|
job = taskQueue.front().jobs.front();
|
||||||
}
|
taskQueue.front().jobs.pop_front();
|
||||||
job = taskQueue.front().jobs.front();
|
|
||||||
taskQueue.front().jobs.pop_front();
|
|
||||||
}
|
|
||||||
job();
|
|
||||||
{
|
|
||||||
std::unique_lock l(queueLock);
|
|
||||||
if (taskQueue.front().jobs.empty())
|
|
||||||
{
|
|
||||||
taskQueue.pop_front();
|
|
||||||
completedCV.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
job.handle();
|
||||||
|
{
|
||||||
|
std::unique_lock l(queueLock);
|
||||||
|
numRemaining--;
|
||||||
|
if (numRemaining == 0)
|
||||||
|
{
|
||||||
|
taskQueue.pop_front();
|
||||||
|
completedCV.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -3,10 +3,11 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include "Minimal.h"
|
||||||
|
|
||||||
struct Batch
|
struct Batch
|
||||||
{
|
{
|
||||||
std::list<std::function<void()>> jobs;
|
std::list<Task> jobs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadPool
|
class ThreadPool
|
||||||
@@ -21,6 +22,7 @@ private:
|
|||||||
std::mutex queueLock;
|
std::mutex queueLock;
|
||||||
std::condition_variable queueCV;
|
std::condition_variable queueCV;
|
||||||
std::condition_variable completedCV;
|
std::condition_variable completedCV;
|
||||||
|
uint32_t numRemaining;
|
||||||
std::list<Batch> taskQueue;
|
std::list<Batch> taskQueue;
|
||||||
std::vector<std::thread> workers;
|
std::vector<std::thread> workers;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
target_sources(RayTracer
|
||||||
|
PRIVATE
|
||||||
|
Renderer.h
|
||||||
|
Renderer.cpp)
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#include "Renderer.h"
|
||||||
|
|
||||||
|
Renderer::Renderer()
|
||||||
|
: instance(nullptr), physicalDevice(nullptr), device(nullptr), queue(nullptr), cmdPool(nullptr), cmdBuffers(nullptr),
|
||||||
|
descriptorLayout(nullptr), descriptorSet(nullptr), descriptorPool(nullptr), pipelineLayout(nullptr), rayGen(nullptr),
|
||||||
|
closestHit(nullptr), miss(nullptr), pipeline(nullptr)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
vk::RayTracingPipelineCreateInfoKHR pipelineCreateInfo(0, );
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::~Renderer() {}
|
||||||
|
|
||||||
|
void Renderer::createDevice() {
|
||||||
|
vk::ApplicationInfo appInfo("RayTracer", 1, "RayTracer", 1, VK_API_VERSION_1_3);
|
||||||
|
vk::InstanceCreateInfo instanceCreateInfo({}, &appInfo);
|
||||||
|
instance = Instance(context, instanceCreateInfo);
|
||||||
|
auto physicalDevices = PhysicalDevices(instance);
|
||||||
|
for (auto& dev : physicalDevices)
|
||||||
|
{
|
||||||
|
for (auto ext : dev.enumerateDeviceExtensionProperties())
|
||||||
|
{
|
||||||
|
if (std::strcmp(ext.extensionName, vk::KHRRayTracingPipelineExtensionName))
|
||||||
|
{
|
||||||
|
physicalDevice = dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t computeQueueFamily = 0;
|
||||||
|
auto queueProps = physicalDevice.getQueueFamilyProperties();
|
||||||
|
for (uint32_t i = 0; i < queueProps.size(); ++i)
|
||||||
|
{
|
||||||
|
if (queueProps[i].queueFlags & vk::QueueFlagBits::eCompute)
|
||||||
|
{
|
||||||
|
computeQueueFamily = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float queuePriority = 0.0f;
|
||||||
|
vk::DeviceQueueCreateInfo deviceQueueCreateInfo({}, computeQueueFamily, 1, &queuePriority);
|
||||||
|
vk::DeviceCreateInfo deviceCreateInfo({}, deviceQueueCreateInfo);
|
||||||
|
device = Device(physicalDevice, deviceCreateInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::createCommands()
|
||||||
|
{
|
||||||
|
vk::CommandPoolCreateInfo commandPoolCreateInfo({}, computeQueueFamily);
|
||||||
|
cmdPool = CommandPool(device, commandPoolCreateInfo);
|
||||||
|
|
||||||
|
// allocate a CommandBuffer from the CommandPool
|
||||||
|
vk::CommandBufferAllocateInfo commandBufferAllocateInfo(cmdPool, vk::CommandBufferLevel::ePrimary, 10);
|
||||||
|
cmdBuffers = vk::raii::CommandBuffers(device, commandBufferAllocateInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::createDescriptors() {
|
||||||
|
vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex);
|
||||||
|
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo({}, descriptorSetLayoutBinding);
|
||||||
|
descriptorLayout = DescriptorSetLayout(device, descriptorSetLayoutCreateInfo);
|
||||||
|
|
||||||
|
// create a PipelineLayout using that DescriptorSetLayout
|
||||||
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, *descriptorLayout);
|
||||||
|
pipelineLayout = PipelineLayout(device, pipelineLayoutCreateInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::createShaders() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::render(Camera cam, RenderParameter param) {}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "scene/Scene.h"
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
#include <vulkan/vulkan_raii.hpp>
|
||||||
|
|
||||||
|
using namespace vk::raii;
|
||||||
|
|
||||||
|
struct Renderer : public Scene
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Renderer();
|
||||||
|
virtual ~Renderer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createDevice();
|
||||||
|
void createCommands();
|
||||||
|
void createDescriptors();
|
||||||
|
void createShaders();
|
||||||
|
|
||||||
|
Context context;
|
||||||
|
Instance instance;
|
||||||
|
PhysicalDevice physicalDevice;
|
||||||
|
Device device;
|
||||||
|
Queue queue;
|
||||||
|
|
||||||
|
uint32_t computeQueueFamily;
|
||||||
|
CommandPool cmdPool;
|
||||||
|
CommandBuffers cmdBuffers;
|
||||||
|
|
||||||
|
DescriptorSetLayout descriptorLayout;
|
||||||
|
DescriptorSet descriptorSet;
|
||||||
|
DescriptorPool descriptorPool;
|
||||||
|
PipelineLayout pipelineLayout;
|
||||||
|
|
||||||
|
ShaderModule rayGen;
|
||||||
|
ShaderModule closestHit;
|
||||||
|
ShaderModule miss;
|
||||||
|
|
||||||
|
Pipeline pipeline;
|
||||||
|
|
||||||
|
virtual void render(Camera cam, RenderParameter param);
|
||||||
|
};
|
||||||
+4
-4
@@ -8,15 +8,15 @@
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Scene scene;
|
Scene scene;
|
||||||
Window window(800, 600);
|
Window window(1920, 1080);
|
||||||
scene.render(
|
scene.startRender(
|
||||||
Camera{
|
Camera{
|
||||||
.position = glm::vec3(10, 0, 0),
|
.position = glm::vec3(10, 0, 0),
|
||||||
.direction = glm::vec3(-1, 0, 0),
|
.direction = glm::vec3(-1, 0, 0),
|
||||||
},
|
},
|
||||||
RenderParameter{
|
RenderParameter{
|
||||||
.width = 800,
|
.width = 1920,
|
||||||
.height = 600,
|
.height = 1080,
|
||||||
.numSamples = 10000,
|
.numSamples = 10000,
|
||||||
});
|
});
|
||||||
while (true)
|
while (true)
|
||||||
|
|||||||
+45
-50
@@ -1,69 +1,64 @@
|
|||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
#include "util/ModelLoader.h"
|
#include "util/ModelLoader.h"
|
||||||
#include <iostream>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
Scene::Scene()
|
Scene::Scene()
|
||||||
{
|
{
|
||||||
bvh.addModels(ModelLoader::loadModel("../cube.fbx"),
|
bvh.addModels(ModelLoader::loadModel("../res/models/cube.fbx"),
|
||||||
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f),
|
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
||||||
glm::vec4(0.0f, 1.0f, 0.0f, 0.0f),
|
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
|
||||||
glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
|
||||||
glm::vec4(0.0f, 0.0f, 4.0f, 0.0f)));
|
|
||||||
bvh.generate();
|
bvh.generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::~Scene() {}
|
Scene::~Scene() {}
|
||||||
|
|
||||||
static bool firstTime = true;
|
static bool firstTime = true;
|
||||||
|
void Scene::startRender(Camera cam, RenderParameter params)
|
||||||
|
{
|
||||||
|
if (!firstTime)
|
||||||
|
{
|
||||||
|
pendingCancel = true;
|
||||||
|
worker.join();
|
||||||
|
firstTime = false;
|
||||||
|
}
|
||||||
|
pendingCancel = false;
|
||||||
|
image.clear();
|
||||||
|
accumulator.clear();
|
||||||
|
image.resize(params.width * params.height);
|
||||||
|
accumulator.resize(params.width * params.height);
|
||||||
|
worker = std::thread(&Scene::render, this, cam, params);
|
||||||
|
}
|
||||||
|
|
||||||
void Scene::render(Camera cam, RenderParameter params)
|
void Scene::render(Camera cam, RenderParameter params)
|
||||||
{
|
{
|
||||||
if (!firstTime)
|
for (int samp = 0; samp < params.numSamples; ++samp)
|
||||||
|
{
|
||||||
|
if (pendingCancel)
|
||||||
|
return;
|
||||||
|
Batch batch;
|
||||||
|
for (int w = 0; w < params.width; ++w)
|
||||||
{
|
{
|
||||||
pendingCancel = true;
|
batch.jobs.push_back(
|
||||||
worker.join();
|
[&](int w) -> Task
|
||||||
firstTime = false;
|
{
|
||||||
}
|
for (int h = 0; h < params.height; ++h)
|
||||||
pendingCancel = false;
|
|
||||||
image.clear();
|
|
||||||
accumulator.clear();
|
|
||||||
image.resize(params.width * params.height);
|
|
||||||
accumulator.resize(params.width * params.height);
|
|
||||||
worker = std::thread(
|
|
||||||
[&, cam, params]()
|
|
||||||
{
|
|
||||||
for (int samp = 0; samp < params.numSamples; ++samp)
|
|
||||||
{
|
{
|
||||||
if (pendingCancel)
|
Ray r = Ray{.origin = glm::vec3(0.0f),
|
||||||
return;
|
.direction = glm::normalize(
|
||||||
Batch batch;
|
glm::vec3((float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX))};
|
||||||
for (int w = 0; w < params.width; ++w)
|
bvh.traceRay(r);
|
||||||
{
|
|
||||||
batch.jobs.push_back(
|
|
||||||
[&, w]()
|
|
||||||
{
|
|
||||||
for (int h = 0; h < params.height; ++h)
|
|
||||||
{
|
|
||||||
Ray r = Ray{
|
|
||||||
.origin = glm::vec3(0.0f),
|
|
||||||
.direction = glm::normalize(glm::vec3((float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX, (float)std::rand() / RAND_MAX))
|
|
||||||
};
|
|
||||||
|
|
||||||
auto intersectionInfo = bvh.traceRay(r);
|
accumulator[w + h * params.width] +=
|
||||||
|
glm::vec3(w / float(params.width * params.numSamples), h / float(params.height * params.numSamples), 0);
|
||||||
if(intersectionInfo.has_value())
|
|
||||||
{
|
|
||||||
accumulator[w + h * params.width] += intersectionInfo->albedo;
|
|
||||||
//glm::vec3(w / float(params.width * params.numSamples), h / float(params.height * params.numSamples), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
|
||||||
threadPool.runBatch(std::move(batch));
|
|
||||||
auto end = std::chrono::high_resolution_clock::now();
|
|
||||||
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << std::endl;
|
|
||||||
std::memcpy(image.data(), accumulator.data(), accumulator.size() * sizeof(glm::vec3));
|
|
||||||
}
|
}
|
||||||
});
|
co_return;
|
||||||
|
}(w));
|
||||||
|
}
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
threadPool.runBatch(std::move(batch));
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << std::endl;
|
||||||
|
std::memcpy(image.data(), accumulator.data(), accumulator.size() * sizeof(glm::vec3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -15,10 +15,11 @@ class Scene
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Scene();
|
Scene();
|
||||||
~Scene();
|
virtual ~Scene();
|
||||||
void render(Camera cam, RenderParameter params);
|
void startRender(Camera cam, RenderParameter params);
|
||||||
constexpr const std::vector<glm::vec3>& getImage() const { return image; }
|
constexpr const std::vector<glm::vec3>& getImage() const { return image; }
|
||||||
private:
|
private:
|
||||||
|
virtual void render(Camera cam, RenderParameter params);
|
||||||
std::atomic_bool pendingCancel = false;
|
std::atomic_bool pendingCancel = false;
|
||||||
ThreadPool threadPool;
|
ThreadPool threadPool;
|
||||||
std::thread worker;
|
std::thread worker;
|
||||||
|
|||||||
+1
-1
@@ -4,12 +4,12 @@
|
|||||||
"name": "imgui",
|
"name": "imgui",
|
||||||
"features": [ "glfw-binding", "opengl3-binding" ]
|
"features": [ "glfw-binding", "opengl3-binding" ]
|
||||||
},
|
},
|
||||||
|
"vulkan",
|
||||||
"assimp",
|
"assimp",
|
||||||
"ktx",
|
"ktx",
|
||||||
"glfw3",
|
"glfw3",
|
||||||
"glew",
|
"glew",
|
||||||
"glm",
|
"glm",
|
||||||
"stb",
|
|
||||||
"fmt"
|
"fmt"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user