Updated compute shader particle system with point sprites and gradient coloring
This commit is contained in:
parent
72af27a49a
commit
3ae4f26901
9 changed files with 131 additions and 77 deletions
|
|
@ -9,6 +9,7 @@ if %ERRORLEVEL% EQU 0 (
|
||||||
|
|
||||||
mkdir "assets\textures"
|
mkdir "assets\textures"
|
||||||
xcopy "..\..\data\textures\particle01_rgba.ktx" "assets\textures" /Y
|
xcopy "..\..\data\textures\particle01_rgba.ktx" "assets\textures" /Y
|
||||||
|
xcopy "..\..\data\textures\particle_gradient_rgba.ktx" "assets\textures" /Y
|
||||||
|
|
||||||
mkdir "res\drawable"
|
mkdir "res\drawable"
|
||||||
xcopy "..\..\android\images\icon.png" "res\drawable" /Y
|
xcopy "..\..\android\images\icon.png" "res\drawable" /Y
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Vulkan Example - Attraction based compute shader particle system
|
* Vulkan Example - Attraction based compute shader particle system
|
||||||
*
|
*
|
||||||
|
* Updated compute shader by Lukas Bergdoll (https://github.com/Voultapher)
|
||||||
|
*
|
||||||
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
||||||
*
|
*
|
||||||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||||
|
|
@ -25,20 +27,23 @@
|
||||||
#define ENABLE_VALIDATION false
|
#define ENABLE_VALIDATION false
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
// Lower particle count on Android for performance reasons
|
// Lower particle count on Android for performance reasons
|
||||||
#define PARTICLE_COUNT 512 * 1024
|
#define PARTICLE_COUNT 64 * 1024
|
||||||
#else
|
#else
|
||||||
#define PARTICLE_COUNT 2048 * 1024
|
#define PARTICLE_COUNT 256 * 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class VulkanExample : public VulkanExampleBase
|
class VulkanExample : public VulkanExampleBase
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
vkTools::VulkanTexture textureColorMap;
|
|
||||||
public:
|
public:
|
||||||
float timer = 0.f;
|
float timer = 0.f;
|
||||||
float animStart = 20.0f;
|
float animStart = 20.0f;
|
||||||
bool animate = true;
|
bool animate = true;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
vkTools::VulkanTexture particle;
|
||||||
|
vkTools::VulkanTexture gradient;
|
||||||
|
} textures;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
VkPipelineVertexInputStateCreateInfo inputState;
|
VkPipelineVertexInputStateCreateInfo inputState;
|
||||||
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
|
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
|
||||||
|
|
@ -76,9 +81,11 @@ public:
|
||||||
struct Particle {
|
struct Particle {
|
||||||
glm::vec2 pos;
|
glm::vec2 pos;
|
||||||
glm::vec2 vel;
|
glm::vec2 vel;
|
||||||
|
glm::vec4 gradientPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
|
VkDescriptorSet descriptorSetPostCompute;
|
||||||
VkDescriptorSetLayout descriptorSetLayout;
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
||||||
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
||||||
|
|
@ -105,6 +112,15 @@ public:
|
||||||
vkDestroyPipelineLayout(device, computePipelineLayout, nullptr);
|
vkDestroyPipelineLayout(device, computePipelineLayout, nullptr);
|
||||||
vkDestroyDescriptorSetLayout(device, computeDescriptorSetLayout, nullptr);
|
vkDestroyDescriptorSetLayout(device, computeDescriptorSetLayout, nullptr);
|
||||||
vkDestroyPipeline(device, pipelines.compute, nullptr);
|
vkDestroyPipeline(device, pipelines.compute, nullptr);
|
||||||
|
|
||||||
|
textureLoader->destroyTexture(textures.particle);
|
||||||
|
textureLoader->destroyTexture(textures.gradient);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadTextures()
|
||||||
|
{
|
||||||
|
textureLoader->loadTexture(getAssetPath() + "textures/particle01_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, &textures.particle, false);
|
||||||
|
textureLoader->loadTexture(getAssetPath() + "textures/particle_gradient_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, &textures.gradient, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildCommandBuffers()
|
void buildCommandBuffers()
|
||||||
|
|
@ -131,15 +147,12 @@ public:
|
||||||
renderPassBeginInfo.clearValueCount = 2;
|
renderPassBeginInfo.clearValueCount = 2;
|
||||||
renderPassBeginInfo.pClearValues = clearValues;
|
renderPassBeginInfo.pClearValues = clearValues;
|
||||||
|
|
||||||
VkResult err;
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
|
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
|
||||||
{
|
{
|
||||||
// Set target frame buffer
|
// Set target frame buffer
|
||||||
renderPassBeginInfo.framebuffer = frameBuffers[i];
|
renderPassBeginInfo.framebuffer = frameBuffers[i];
|
||||||
|
|
||||||
err = vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo);
|
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
// Buffer memory barrier to make sure that compute shader
|
// Buffer memory barrier to make sure that compute shader
|
||||||
// writes are finished before using the storage buffer
|
// writes are finished before using the storage buffer
|
||||||
|
|
@ -166,23 +179,15 @@ public:
|
||||||
|
|
||||||
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
VkViewport viewport = vkTools::initializers::viewport(
|
VkViewport viewport = vkTools::initializers::viewport((float)width, (float)height, 0.0f, 1.0f
|
||||||
(float)width,
|
|
||||||
(float)height,
|
|
||||||
0.0f,
|
|
||||||
1.0f
|
|
||||||
);
|
);
|
||||||
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
|
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
|
||||||
|
|
||||||
VkRect2D scissor = vkTools::initializers::rect2D(
|
VkRect2D scissor = vkTools::initializers::rect2D(width, height, 0, 0);
|
||||||
width,
|
|
||||||
height,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
|
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.postCompute);
|
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.postCompute);
|
||||||
|
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSetPostCompute, 0, NULL);
|
||||||
|
|
||||||
VkDeviceSize offsets[1] = { 0 };
|
VkDeviceSize offsets[1] = { 0 };
|
||||||
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &computeStorageBuffer.buffer, offsets);
|
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &computeStorageBuffer.buffer, offsets);
|
||||||
|
|
@ -190,8 +195,7 @@ public:
|
||||||
|
|
||||||
vkCmdEndRenderPass(drawCmdBuffers[i]);
|
vkCmdEndRenderPass(drawCmdBuffers[i]);
|
||||||
|
|
||||||
err = vkEndCommandBuffer(drawCmdBuffers[i]);
|
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
|
||||||
assert(!err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -212,11 +216,8 @@ public:
|
||||||
|
|
||||||
void draw()
|
void draw()
|
||||||
{
|
{
|
||||||
VkResult err;
|
|
||||||
|
|
||||||
// Get next image in the swap chain (back/front buffer)
|
// Get next image in the swap chain (back/front buffer)
|
||||||
err = swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer);
|
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
submitPostPresentBarrier(swapChain.buffers[currentBuffer].image);
|
submitPostPresentBarrier(swapChain.buffers[currentBuffer].image);
|
||||||
|
|
||||||
|
|
@ -225,27 +226,22 @@ public:
|
||||||
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
||||||
|
|
||||||
// Submit to queue
|
// Submit to queue
|
||||||
err = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
submitPrePresentBarrier(swapChain.buffers[currentBuffer].image);
|
submitPrePresentBarrier(swapChain.buffers[currentBuffer].image);
|
||||||
|
|
||||||
err = swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete);
|
VK_CHECK_RESULT(swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
// Compute
|
// Compute
|
||||||
VkSubmitInfo computeSubmitInfo = vkTools::initializers::submitInfo();
|
VkSubmitInfo computeSubmitInfo = vkTools::initializers::submitInfo();
|
||||||
computeSubmitInfo.commandBufferCount = 1;
|
computeSubmitInfo.commandBufferCount = 1;
|
||||||
computeSubmitInfo.pCommandBuffers = &computeCmdBuffer;
|
computeSubmitInfo.pCommandBuffers = &computeCmdBuffer;
|
||||||
|
|
||||||
err = vkQueueSubmit(computeQueue, 1, &computeSubmitInfo, VK_NULL_HANDLE);
|
VK_CHECK_RESULT(vkQueueSubmit(computeQueue, 1, &computeSubmitInfo, VK_NULL_HANDLE));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
err = vkQueueWaitIdle(queue);
|
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
err = vkQueueWaitIdle(computeQueue);
|
VK_CHECK_RESULT(vkQueueWaitIdle(computeQueue));
|
||||||
assert(!err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup and fill the compute shader storage buffers for
|
// Setup and fill the compute shader storage buffers for
|
||||||
|
|
@ -262,6 +258,7 @@ public:
|
||||||
{
|
{
|
||||||
particle.pos = glm::vec2(rDistribution(rGenerator), rDistribution(rGenerator));
|
particle.pos = glm::vec2(rDistribution(rGenerator), rDistribution(rGenerator));
|
||||||
particle.vel = glm::vec2(0.0f);
|
particle.vel = glm::vec2(0.0f);
|
||||||
|
particle.gradientPos.x = particle.pos.x / 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t storageBufferSize = particleBuffer.size() * sizeof(Particle);
|
uint32_t storageBufferSize = particleBuffer.size() * sizeof(Particle);
|
||||||
|
|
@ -319,7 +316,7 @@ public:
|
||||||
|
|
||||||
// Attribute descriptions
|
// Attribute descriptions
|
||||||
// Describes memory layout and shader positions
|
// Describes memory layout and shader positions
|
||||||
vertices.attributeDescriptions.resize(1);
|
vertices.attributeDescriptions.resize(2);
|
||||||
// Location 0 : Position
|
// Location 0 : Position
|
||||||
vertices.attributeDescriptions[0] =
|
vertices.attributeDescriptions[0] =
|
||||||
vkTools::initializers::vertexInputAttributeDescription(
|
vkTools::initializers::vertexInputAttributeDescription(
|
||||||
|
|
@ -327,6 +324,13 @@ public:
|
||||||
0,
|
0,
|
||||||
VK_FORMAT_R32G32_SFLOAT,
|
VK_FORMAT_R32G32_SFLOAT,
|
||||||
0);
|
0);
|
||||||
|
// Location 1 : Gradient position
|
||||||
|
vertices.attributeDescriptions[1] =
|
||||||
|
vkTools::initializers::vertexInputAttributeDescription(
|
||||||
|
VERTEX_BUFFER_BIND_ID,
|
||||||
|
1,
|
||||||
|
VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
4 * sizeof(float));
|
||||||
|
|
||||||
// Assign to vertex buffer
|
// Assign to vertex buffer
|
||||||
vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
|
vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
|
||||||
|
|
@ -341,7 +345,8 @@ public:
|
||||||
std::vector<VkDescriptorPoolSize> poolSizes =
|
std::vector<VkDescriptorPoolSize> poolSizes =
|
||||||
{
|
{
|
||||||
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
|
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
|
||||||
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1)
|
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1),
|
||||||
|
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo descriptorPoolInfo =
|
VkDescriptorPoolCreateInfo descriptorPoolInfo =
|
||||||
|
|
@ -350,30 +355,74 @@ public:
|
||||||
poolSizes.data(),
|
poolSizes.data(),
|
||||||
2);
|
2);
|
||||||
|
|
||||||
VkResult vkRes = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool);
|
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
|
||||||
assert(!vkRes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupDescriptorSetLayout()
|
void setupDescriptorSetLayout()
|
||||||
{
|
{
|
||||||
|
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
|
||||||
|
// Binding 0 : Particle color map
|
||||||
|
setLayoutBindings.push_back(vkTools::initializers::descriptorSetLayoutBinding(
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
0));
|
||||||
|
// Binding 1 : Particle gradient ramp
|
||||||
|
setLayoutBindings.push_back(vkTools::initializers::descriptorSetLayoutBinding(
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
1));
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo;
|
VkDescriptorSetLayoutCreateInfo descriptorLayout =
|
||||||
descriptorLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
vkTools::initializers::descriptorSetLayoutCreateInfo(
|
||||||
descriptorLayoutInfo.pNext = NULL;
|
setLayoutBindings.data(),
|
||||||
descriptorLayoutInfo.flags = 0;
|
setLayoutBindings.size());
|
||||||
descriptorLayoutInfo.bindingCount = 0;
|
|
||||||
descriptorLayoutInfo.pBindings = nullptr;
|
|
||||||
|
|
||||||
VkResult err = vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayout);
|
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
|
||||||
vkTools::initializers::pipelineLayoutCreateInfo(
|
vkTools::initializers::pipelineLayoutCreateInfo(
|
||||||
&descriptorSetLayout,
|
&descriptorSetLayout,
|
||||||
0);
|
1);
|
||||||
|
|
||||||
err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout);
|
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
assert(!err);
|
}
|
||||||
|
|
||||||
|
void setupDescriptorSet()
|
||||||
|
{
|
||||||
|
VkDescriptorSetAllocateInfo allocInfo =
|
||||||
|
vkTools::initializers::descriptorSetAllocateInfo(
|
||||||
|
descriptorPool,
|
||||||
|
&descriptorSetLayout,
|
||||||
|
1);
|
||||||
|
|
||||||
|
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSetPostCompute));
|
||||||
|
|
||||||
|
// Image descriptor for the color map texture
|
||||||
|
std::vector<VkDescriptorImageInfo> texDescriptors;
|
||||||
|
texDescriptors.push_back(vkTools::initializers::descriptorImageInfo(
|
||||||
|
textures.particle.sampler,
|
||||||
|
textures.particle.view,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL));
|
||||||
|
texDescriptors.push_back(vkTools::initializers::descriptorImageInfo(
|
||||||
|
textures.gradient.sampler,
|
||||||
|
textures.gradient.view,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL));
|
||||||
|
|
||||||
|
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
||||||
|
// Binding 0 : Particle color map
|
||||||
|
writeDescriptorSets.push_back(vkTools::initializers::writeDescriptorSet(
|
||||||
|
descriptorSetPostCompute,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
0,
|
||||||
|
&texDescriptors[0]));
|
||||||
|
// Binding 1 : Particle gradient ramp
|
||||||
|
writeDescriptorSets.push_back(vkTools::initializers::writeDescriptorSet(
|
||||||
|
descriptorSetPostCompute,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
1,
|
||||||
|
&texDescriptors[1]));
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a separate command buffer for compute commands
|
// Create a separate command buffer for compute commands
|
||||||
|
|
@ -385,14 +434,11 @@ public:
|
||||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
VkResult vkRes = vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &computeCmdBuffer);
|
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &computeCmdBuffer));
|
||||||
assert(!vkRes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void preparePipelines()
|
void preparePipelines()
|
||||||
{
|
{
|
||||||
VkResult err;
|
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
|
||||||
vkTools::initializers::pipelineInputAssemblyStateCreateInfo(
|
vkTools::initializers::pipelineInputAssemblyStateCreateInfo(
|
||||||
VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
|
VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
|
||||||
|
|
@ -475,8 +521,7 @@ public:
|
||||||
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
|
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
|
||||||
|
|
||||||
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.postCompute);
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.postCompute));
|
||||||
assert(!err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareCompute()
|
void prepareCompute()
|
||||||
|
|
@ -503,12 +548,7 @@ public:
|
||||||
setLayoutBindings.data(),
|
setLayoutBindings.data(),
|
||||||
setLayoutBindings.size());
|
setLayoutBindings.size());
|
||||||
|
|
||||||
VkResult err = vkCreateDescriptorSetLayout(
|
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &computeDescriptorSetLayout));
|
||||||
device,
|
|
||||||
&descriptorLayout,
|
|
||||||
nullptr,
|
|
||||||
&computeDescriptorSetLayout);
|
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
||||||
|
|
@ -516,12 +556,7 @@ public:
|
||||||
&computeDescriptorSetLayout,
|
&computeDescriptorSetLayout,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
err = vkCreatePipelineLayout(
|
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &computePipelineLayout));
|
||||||
device,
|
|
||||||
&pPipelineLayoutCreateInfo,
|
|
||||||
nullptr,
|
|
||||||
&computePipelineLayout);
|
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
VkDescriptorSetAllocateInfo allocInfo =
|
VkDescriptorSetAllocateInfo allocInfo =
|
||||||
vkTools::initializers::descriptorSetAllocateInfo(
|
vkTools::initializers::descriptorSetAllocateInfo(
|
||||||
|
|
@ -529,8 +564,7 @@ public:
|
||||||
&computeDescriptorSetLayout,
|
&computeDescriptorSetLayout,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
err = vkAllocateDescriptorSets(device, &allocInfo, &computeDescriptorSet);
|
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &computeDescriptorSet));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
std::vector<VkWriteDescriptorSet> computeWriteDescriptorSets =
|
std::vector<VkWriteDescriptorSet> computeWriteDescriptorSets =
|
||||||
{
|
{
|
||||||
|
|
@ -556,8 +590,7 @@ public:
|
||||||
computePipelineLayout,
|
computePipelineLayout,
|
||||||
0);
|
0);
|
||||||
computePipelineCreateInfo.stage = loadShader(getAssetPath() + "shaders/computeparticles/particle.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT);
|
computePipelineCreateInfo.stage = loadShader(getAssetPath() + "shaders/computeparticles/particle.comp.spv", VK_SHADER_STAGE_COMPUTE_BIT);
|
||||||
err = vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipelines.compute);
|
VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipelines.compute));
|
||||||
assert(!err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare and initialize uniform buffer containing shader uniforms
|
// Prepare and initialize uniform buffer containing shader uniforms
|
||||||
|
|
@ -580,7 +613,7 @@ public:
|
||||||
|
|
||||||
void updateUniformBuffers()
|
void updateUniformBuffers()
|
||||||
{
|
{
|
||||||
computeUbo.deltaT = frameTimer * 4.0f;
|
computeUbo.deltaT = frameTimer * 2.5f;
|
||||||
if (animate)
|
if (animate)
|
||||||
{
|
{
|
||||||
computeUbo.destX = sin(glm::radians(timer*360.0)) * 0.75f;
|
computeUbo.destX = sin(glm::radians(timer*360.0)) * 0.75f;
|
||||||
|
|
@ -627,6 +660,7 @@ public:
|
||||||
void prepare()
|
void prepare()
|
||||||
{
|
{
|
||||||
VulkanExampleBase::prepare();
|
VulkanExampleBase::prepare();
|
||||||
|
loadTextures();
|
||||||
getComputeQueue();
|
getComputeQueue();
|
||||||
createComputeCommandBuffer();
|
createComputeCommandBuffer();
|
||||||
prepareStorageBuffers();
|
prepareStorageBuffers();
|
||||||
|
|
@ -634,6 +668,7 @@ public:
|
||||||
setupDescriptorSetLayout();
|
setupDescriptorSetLayout();
|
||||||
preparePipelines();
|
preparePipelines();
|
||||||
setupDescriptorPool();
|
setupDescriptorPool();
|
||||||
|
setupDescriptorSet();
|
||||||
prepareCompute();
|
prepareCompute();
|
||||||
buildCommandBuffers();
|
buildCommandBuffers();
|
||||||
buildComputeCommandBuffer();
|
buildComputeCommandBuffer();
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ struct Particle
|
||||||
{
|
{
|
||||||
vec2 pos;
|
vec2 pos;
|
||||||
vec2 vel;
|
vec2 vel;
|
||||||
|
vec4 gradientPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Binding 0 : Position storage buffer
|
// Binding 0 : Position storage buffer
|
||||||
|
|
@ -71,5 +72,8 @@ void main()
|
||||||
|
|
||||||
// Write back
|
// Write back
|
||||||
particles[index].vel.xy = vVel;
|
particles[index].vel.xy = vVel;
|
||||||
|
particles[index].gradientPos.x += 0.02 * ubo.deltaT;
|
||||||
|
if (particles[index].gradientPos.x > 1.0)
|
||||||
|
particles[index].gradientPos.x -= 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -3,11 +3,16 @@
|
||||||
#extension GL_ARB_separate_shader_objects : enable
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
#extension GL_ARB_shading_language_420pack : enable
|
#extension GL_ARB_shading_language_420pack : enable
|
||||||
|
|
||||||
|
layout (binding = 0) uniform sampler2D samplerColorMap;
|
||||||
|
layout (binding = 1) uniform sampler2D samplerGradientRamp;
|
||||||
|
|
||||||
layout (location = 0) in vec4 inColor;
|
layout (location = 0) in vec4 inColor;
|
||||||
|
layout (location = 1) in float inGradientPos;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
void main ()
|
void main ()
|
||||||
{
|
{
|
||||||
outFragColor = inColor;
|
vec3 color = texture(samplerGradientRamp, vec2(inGradientPos, 0.0)).rgb;
|
||||||
|
outFragColor.rgb = texture(samplerColorMap, gl_PointCoord).rgb * color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -4,12 +4,21 @@
|
||||||
#extension GL_ARB_shading_language_420pack : enable
|
#extension GL_ARB_shading_language_420pack : enable
|
||||||
|
|
||||||
layout (location = 0) in vec2 inPos;
|
layout (location = 0) in vec2 inPos;
|
||||||
|
layout (location = 1) in vec4 inGradientPos;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outColor;
|
layout (location = 0) out vec4 outColor;
|
||||||
|
layout (location = 1) out float outGradientPos;
|
||||||
|
|
||||||
|
out gl_PerVertex
|
||||||
|
{
|
||||||
|
vec4 gl_Position;
|
||||||
|
float gl_PointSize;
|
||||||
|
};
|
||||||
|
|
||||||
void main ()
|
void main ()
|
||||||
{
|
{
|
||||||
gl_PointSize = 1.0;
|
gl_PointSize = 8.0;
|
||||||
outColor = vec4(0.035);
|
outColor = vec4(0.035);
|
||||||
|
outGradientPos = inGradientPos.x;
|
||||||
gl_Position = vec4(inPos.xy, 1.0, 1.0);
|
gl_Position = vec4(inPos.xy, 1.0, 1.0);
|
||||||
}
|
}
|
||||||
Binary file not shown.
BIN
data/textures/particle_gradient_rgba.ktx
Normal file
BIN
data/textures/particle_gradient_rgba.ktx
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue