Skip to content
Snippets Groups Projects
Unverified Commit 3d0aa6b9 authored by TheJackiMonster's avatar TheJackiMonster
Browse files

Created initial firework project

parent 1ce12078
No related branches found
No related tags found
1 merge request!106Created initial firework project
......@@ -130,7 +130,7 @@ namespace vkcv::camera {
}
Camera& CameraManager::getCamera(uint32_t cameraIndex) {
if (cameraIndex < 0 || cameraIndex > m_cameras.size() - 1) {
if (cameraIndex < 0 || cameraIndex >= m_cameras.size()) {
vkcv_log(LogLevel::ERROR, "Invalid camera index: The index must range from 0 to %lu", m_cameras.size());
return getActiveCamera();
}
......@@ -143,7 +143,7 @@ namespace vkcv::camera {
}
void CameraManager::setActiveCamera(uint32_t cameraIndex) {
if (cameraIndex < 0 || cameraIndex > m_cameras.size() - 1) {
if (cameraIndex < 0 || cameraIndex >= m_cameras.size()) {
vkcv_log(LogLevel::ERROR, "Invalid camera index: The index must range from 0 to %lu", m_cameras.size());
return;
}
......@@ -156,7 +156,7 @@ namespace vkcv::camera {
}
void CameraManager::setControllerType(uint32_t cameraIndex, ControllerType controllerType) {
if (cameraIndex < 0 || cameraIndex > m_cameras.size() - 1) {
if (cameraIndex < 0 || cameraIndex >= m_cameras.size()) {
vkcv_log(LogLevel::ERROR, "Invalid camera index: The index must range from 0 to %lu", m_cameras.size());
return;
}
......@@ -165,7 +165,7 @@ namespace vkcv::camera {
}
ControllerType CameraManager::getControllerType(uint32_t cameraIndex) {
if (cameraIndex < 0 || cameraIndex > m_cameras.size() - 1) {
if (cameraIndex < 0 || cameraIndex >= m_cameras.size()) {
vkcv_log(LogLevel::ERROR, "Invalid camera index: The index must range from 0 to %lu", m_cameras.size());
return ControllerType::NONE;
}
......
......@@ -2,18 +2,19 @@
include(${vkcv_config_ext}/Project.cmake)
# Add new projects/examples here:
add_subdirectory(bindless_textures)
add_subdirectory(fire_works)
add_subdirectory(first_triangle)
add_subdirectory(first_mesh)
add_subdirectory(first_scene)
add_subdirectory(head_demo)
add_subdirectory(indirect_dispatch)
add_subdirectory(indirect_draw)
add_subdirectory(mesh_shader)
add_subdirectory(particle_simulation)
add_subdirectory(path_tracer)
add_subdirectory(rtx_ambient_occlusion)
add_subdirectory(saf_r)
add_subdirectory(sph)
add_subdirectory(voxelization)
add_subdirectory(mesh_shader)
add_subdirectory(indirect_draw)
add_subdirectory(bindless_textures)
add_subdirectory(saf_r)
add_subdirectory(indirect_dispatch)
add_subdirectory(path_tracer)
add_subdirectory(wobble_bobble)
\ No newline at end of file
fire_works
cmake_minimum_required(VERSION 3.16)
project(fire_works)
# setting c++ standard for the project
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# adding source files to the project
add_project(fire_works
src/main.cpp)
# including headers of dependencies and the VkCV framework
target_include_directories(fire_works SYSTEM BEFORE PRIVATE
${vkcv_include}
${vkcv_includes}
${vkcv_camera_include}
${vkcv_gui_include}
${vkcv_shader_compiler_include}
${vkcv_effects_include})
# linking with libraries from all dependencies and the VkCV framework
target_link_libraries(fire_works
vkcv
vkcv_camera
vkcv_gui
vkcv_shader_compiler
vkcv_effects)
#version 450 core
#extension GL_GOOGLE_include_directive : enable
#extension GL_ARB_separate_shader_objects : enable
layout(local_size_x = 256) in;
#include "particle.inc"
layout(set=0, binding=0, std430) coherent buffer particleBuffer {
particle_t particles [];
};
layout( push_constant ) uniform constants{
float dt;
};
const float g = 9.81;
void main() {
uint id = gl_GlobalInvocationID.x;
if (id >= particles.length()) {
return;
}
vec3 position = particles[id].position;
float lifetime = particles[id].lifetime;
vec3 velocity = particles[id].velocity;
if (lifetime > dt) {
lifetime -= dt;
} else {
lifetime = 0.0f;
}
position = position + velocity * dt;
velocity = velocity + vec3(0.0f, -g, 0.0f) * dt;
particles[id].position = position;
particles[id].velocity = velocity;
}
#version 450
layout(location = 0) in vec2 passPos;
layout(location = 1) in vec3 passColor;
layout(location = 0) out vec3 outColor;
void main() {
const float value = length(passPos);
if (value < 0.5f) {
outColor = passColor;
} else {
discard;
}
}
\ No newline at end of file
#ifndef PARTICLE_INC
#define PARTICLE_INC
struct particle_t {
vec3 position;
float lifetime;
vec3 velocity;
float size;
vec3 color;
float mass;
};
#endif // PARTICLE_INC
\ No newline at end of file
#version 450
#extension GL_GOOGLE_include_directive : enable
#include "particle.inc"
layout(set=0, binding=0, std430) readonly buffer particleBuffer {
particle_t particles [];
};
layout(location = 0) in vec2 vertexPos;
layout(location = 0) out vec2 passPos;
layout(location = 1) out vec3 passColor;
layout( push_constant ) uniform constants{
mat4 mvp;
};
void main() {
vec3 position = particles[gl_InstanceIndex].position;
float size = particles[gl_InstanceIndex].size;
vec3 color = particles[gl_InstanceIndex].color;
passPos = vertexPos;
passColor = color;
// align particle to face camera
gl_Position = mvp * vec4(position, 1); // transform position into projected view space
gl_Position.xy += vertexPos * size * 2.0f; // move position directly in view space
}
\ No newline at end of file
#version 440
layout(set=0, binding=0, rgba16f) readonly uniform image2D inImage;
layout(set=0, binding=1, rgba8) writeonly uniform image2D outImage;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
void main() {
if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(inImage)))){
return;
}
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
vec3 linearColor = imageLoad(inImage, uv).rgb;
vec3 tonemapped = linearColor / (dot(linearColor, vec3(0.21, 0.71, 0.08)) + 1); // reinhard tonemapping
vec3 gammaCorrected = pow(tonemapped, vec3(1.f / 2.2f));
imageStore(outImage, uv, vec4(gammaCorrected, 0.f));
}
\ No newline at end of file
#include <vkcv/Core.hpp>
#include <vkcv/DrawcallRecording.hpp>
#include <vkcv/camera/CameraManager.hpp>
#include <vkcv/shader/GLSLCompiler.hpp>
#include <vkcv/gui/GUI.hpp>
#include <vkcv/effects/BloomAndFlaresEffect.hpp>
struct particle_t {
glm::vec3 position;
float lifetime;
glm::vec3 velocity;
float size;
glm::vec3 color;
float pad2;
};
int main(int argc, const char **argv) {
vkcv::Core core = vkcv::Core::create(
"Firework",
VK_MAKE_VERSION(0, 0, 1),
{vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute},
{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }
);
vkcv::WindowHandle windowHandle = core.createWindow("Firework", 800, 600, true);
vkcv::Window& window = core.getWindow (windowHandle);
vkcv::camera::CameraManager cameraManager (window);
uint32_t trackballIdx = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL);
cameraManager.getCamera(trackballIdx).setCenter(glm::vec3(0.0f, 0.0f, 0.0f)); // set camera to look at the center of the particle volume
cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
cameraManager.getCamera(trackballIdx).setNearFar(0.1f, 50.0f);
cameraManager.getCamera(trackballIdx).setPosition(glm::vec3(0, 0, -25));
vkcv::gui::GUI gui (core, windowHandle);
auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
const vk::Format depthFormat = vk::Format::eD32Sfloat;
vkcv::ImageHandle depthBuffer = core.createImage(
depthFormat,
swapchainExtent.width,
swapchainExtent.height
).getHandle();
const vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat;
vkcv::ImageHandle colorBuffer = core.createImage(
colorFormat,
swapchainExtent.width,
swapchainExtent.height,
1, false, true, true
).getHandle();
vkcv::shader::GLSLCompiler compiler;
vkcv::ShaderProgram particleShaderProgram;
compiler.compile(vkcv::ShaderStage::VERTEX, "shaders/particle.vert", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
particleShaderProgram.addShader(shaderStage, path);
});
compiler.compile(vkcv::ShaderStage::FRAGMENT, "shaders/particle.frag", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
particleShaderProgram.addShader(shaderStage, path);
});
vkcv::DescriptorBindings descriptorBindings;
vkcv::DescriptorBinding binding {
0,
vkcv::DescriptorType::STORAGE_BUFFER,
1,
vkcv::ShaderStage::VERTEX | vkcv::ShaderStage::COMPUTE,
false,
false
};
descriptorBindings.insert(std::make_pair(0, binding));
vkcv::DescriptorSetLayoutHandle descriptorSetLayout = core.createDescriptorSetLayout(descriptorBindings);
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
std::vector<particle_t> particles;
for (size_t i = 0; i < 1024; i++) {
particle_t particle;
particle.position = glm::vec3(
2.0f * (std::rand() % RAND_MAX) / RAND_MAX - 1.0f,
2.0f * (std::rand() % RAND_MAX) / RAND_MAX - 1.0f,
2.0f * (std::rand() % RAND_MAX) / RAND_MAX - 1.0f
);
particle.lifetime = 0.0f;
particle.velocity = glm::vec3(0.0f);
particle.size = 0.01f;
particle.color = glm::vec3(1.0f, 0.0f, 0.0f);
particles.push_back(particle);
}
vkcv::Buffer<particle_t> particleBuffer = core.createBuffer<particle_t>(
vkcv::BufferType::STORAGE,
particles.size()
);
particleBuffer.fill(particles);
vkcv::DescriptorWrites writes;
writes.writeStorageBuffer(0, particleBuffer.getHandle());
core.writeDescriptorSet(descriptorSet, writes);
vkcv::Buffer<glm::vec2> trianglePositions = core.createBuffer<glm::vec2>(vkcv::BufferType::VERTEX, 3);
trianglePositions.fill({
glm::vec2(-1.0f, -1.0f),
glm::vec2(+0.0f, +1.5f),
glm::vec2(+1.0f, -1.0f)
});
vkcv::Buffer<uint16_t> triangleIndices = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3);
triangleIndices.fill({
0, 1, 2
});
vkcv::Mesh triangleMesh (
{ vkcv::VertexBufferBinding(0, trianglePositions.getVulkanHandle()) },
triangleIndices.getVulkanHandle(),
triangleIndices.getCount()
);
const std::vector<vkcv::VertexAttachment> vertexAttachments = particleShaderProgram.getVertexAttachments();
const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
vkcv::VertexBufferBinding(0, trianglePositions.getVulkanHandle())
};
std::vector<vkcv::VertexBinding> bindings;
for (size_t i = 0; i < vertexAttachments.size(); i++) {
bindings.push_back(vkcv::createVertexBinding(i, {vertexAttachments[i]}));
}
const vkcv::VertexLayout particleLayout { bindings };
const vkcv::AttachmentDescription present_color_attachment(
vkcv::AttachmentOperation::STORE,
vkcv::AttachmentOperation::CLEAR,
colorFormat
);
const vkcv::AttachmentDescription depth_attachment(
vkcv::AttachmentOperation::STORE,
vkcv::AttachmentOperation::CLEAR,
depthFormat
);
vkcv::PassConfig particlePassDefinition({present_color_attachment, depth_attachment}, vkcv::Multisampling::None);
vkcv::PassHandle particlePass = core.createPass(particlePassDefinition);
vkcv::GraphicsPipelineConfig particlePipelineDefinition{
particleShaderProgram,
UINT32_MAX,
UINT32_MAX,
particlePass,
{particleLayout},
{descriptorSetLayout},
true
};
// particlePipelineDefinition.m_blendMode = vkcv::BlendMode::Additive;
vkcv::GraphicsPipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition);
std::vector<vkcv::DrawcallInfo> drawcallsParticles;
drawcallsParticles.push_back(vkcv::DrawcallInfo(
triangleMesh,
{ vkcv::DescriptorSetUsage(0, descriptorSet) },
particleBuffer.getCount()
));
vkcv::ShaderProgram motionShader;
compiler.compile(vkcv::ShaderStage::COMPUTE, "shaders/motion.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
motionShader.addShader(shaderStage, path);
});
vkcv::ComputePipelineHandle motionPipeline = core.createComputePipeline({
motionShader,
{ descriptorSetLayout }
});
vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core);
bloomAndFlares.setUpsamplingLimit(3);
vkcv::ShaderProgram tonemappingShader;
compiler.compile(vkcv::ShaderStage::COMPUTE, "shaders/tonemapping.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
tonemappingShader.addShader(shaderStage, path);
});
vkcv::DescriptorSetLayoutHandle tonemappingDescriptorLayout = core.createDescriptorSetLayout(tonemappingShader.getReflectedDescriptors().at(0));
vkcv::DescriptorSetHandle tonemappingDescriptor = core.createDescriptorSet(tonemappingDescriptorLayout);
vkcv::ComputePipelineHandle tonemappingPipe = core.createComputePipeline({
tonemappingShader,
{ tonemappingDescriptorLayout }
});
vkcv::ImageHandle swapchainImage = vkcv::ImageHandle::createSwapchainImageHandle();
auto start = std::chrono::system_clock::now();
auto current = start;
while (vkcv::Window::hasOpenWindow()) {
vkcv::Window::pollEvents();
uint32_t swapchainWidth, swapchainHeight;
if (!core.beginFrame(swapchainWidth, swapchainHeight, windowHandle)) {
continue;
}
if ((core.getImageWidth(colorBuffer) != swapchainWidth) ||
(core.getImageHeight(colorBuffer) != swapchainHeight)) {
colorBuffer = core.createImage(
colorFormat,
swapchainWidth,
swapchainHeight,
1, false, true, true
).getHandle();
}
if ((core.getImageWidth(depthBuffer) != swapchainWidth) ||
(core.getImageHeight(depthBuffer) != swapchainHeight)) {
depthBuffer = core.createImage(
depthFormat,
swapchainWidth,
swapchainHeight
).getHandle();
}
auto next = std::chrono::system_clock::now();
auto time = std::chrono::duration_cast<std::chrono::microseconds>(next - start);
auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(next - current);
current = next;
// auto t = static_cast<float>(0.000001 * static_cast<double>(time.count()));
auto dt = static_cast<float>(0.000001 * static_cast<double>(deltatime.count()));
auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
uint32_t motionDispatchCount[3];
motionDispatchCount[0] = std::ceil(particleBuffer.getCount() / 256.f);
motionDispatchCount[1] = 1;
motionDispatchCount[2] = 1;
vkcv::PushConstants pushConstantsTime (sizeof(float));
pushConstantsTime.appendDrawcall(dt);
core.recordComputeDispatchToCmdStream(
cmdStream,
motionPipeline,
motionDispatchCount,
{vkcv::DescriptorSetUsage(0, descriptorSet) },
pushConstantsTime
);
cameraManager.update(dt);
const auto& camera = cameraManager.getActiveCamera();
vkcv::PushConstants pushConstantsDraw (sizeof(glm::mat4));
pushConstantsDraw.appendDrawcall(camera.getMVP());
core.recordDrawcallsToCmdStream(
cmdStream,
particlePass,
particlePipeline,
pushConstantsDraw,
{drawcallsParticles},
{ colorBuffer, depthBuffer },
windowHandle
);
bloomAndFlares.recordEffect(cmdStream, colorBuffer, colorBuffer);
core.prepareImageForStorage(cmdStream, colorBuffer);
core.prepareImageForStorage(cmdStream, swapchainImage);
vkcv::DescriptorWrites tonemappingDescriptorWrites;
tonemappingDescriptorWrites.writeStorageImage(
0, colorBuffer
).writeStorageImage(
1, swapchainImage
);
core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites);
uint32_t tonemappingDispatchCount[3];
tonemappingDispatchCount[0] = std::ceil(swapchainWidth / 8.f);
tonemappingDispatchCount[1] = std::ceil(swapchainHeight / 8.f);
tonemappingDispatchCount[2] = 1;
core.recordComputeDispatchToCmdStream(
cmdStream,
tonemappingPipe,
tonemappingDispatchCount,
{vkcv::DescriptorSetUsage(0, tonemappingDescriptor) },
vkcv::PushConstants(0)
);
core.prepareSwapchainImageForPresent(cmdStream);
core.submitCommandStream(cmdStream);
core.endFrame(windowHandle);
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment