From 5d7014b221363043844a5ebd2c9057c394e93685 Mon Sep 17 00:00:00 2001 From: Voultapher Date: Thu, 21 Apr 2016 11:21:48 +0200 Subject: [PATCH] Visual Update for computeparticles Instead of using a small amount of large textured particles, use a large amount of small monochrome particles. Which uses a new vulkanexamplebase functionality of creating and updating a only device visible buffer via a temporary staging buffer. --- base/vulkanexamplebase.cpp | 91 +++++++ base/vulkanexamplebase.h | 14 + computeparticles/computeparticles.cpp | 251 +++++------------- data/shaders/computeparticles/particle.comp | 45 ++-- .../computeparticles/particle.comp.spv | Bin 3664 -> 4684 bytes data/shaders/computeparticles/particle.frag | 4 +- .../computeparticles/particle.frag.spv | Bin 748 -> 452 bytes data/shaders/computeparticles/particle.vert | 7 +- .../computeparticles/particle.vert.spv | Bin 1144 -> 1096 bytes 9 files changed, 203 insertions(+), 209 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index b76db783..195f6b14 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -283,6 +283,97 @@ VkPipelineShaderStageCreateInfo VulkanExampleBase::loadShader(std::string fileNa return shaderStage; } +VkBool32 VulkanExampleBase::createDeviceBuffer( + const VkBufferUsageFlags usage, + const VkDeviceSize size, + VkBuffer& buffer, + VkDeviceMemory& memory, + VkDescriptorBufferInfo& descriptor) +{ + VkMemoryRequirements memReqs; + VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); + VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT, size); + + VkResult err = vkCreateBuffer(device, &bufferCreateInfo, nullptr, &buffer); + assert(!err); + + vkGetBufferMemoryRequirements(device, buffer, &memReqs); + memAlloc.allocationSize = memReqs.size; + + getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAlloc.memoryTypeIndex); + + err = vkAllocateMemory(device, &memAlloc, nullptr, &memory); + assert(!err); + + err = vkBindBufferMemory(device, buffer, memory, 0); + assert(!err); + + descriptor.offset = 0; + descriptor.buffer = buffer; + descriptor.range = size; + + return VK_TRUE; +} + +VkBool32 VulkanExampleBase::updateDeviceBuffer( + const VkDeviceSize size, + VkBuffer& deviceBuffer, + void* data) +{ + //todo check that size is not larger than memory size + + // create staging buffer and copy data to it + VkMemoryRequirements memReqs; + VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); + VkBufferCreateInfo bufferCreateInfo = vkTools::initializers::bufferCreateInfo(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, size); + VkBuffer stagingBuffer; + VkDeviceMemory stagingMemory; + + VkResult err = vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer); + assert(!err); + + vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); + memAlloc.allocationSize = memReqs.size; + + getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); + + err = vkAllocateMemory(device, &memAlloc, nullptr, &stagingMemory); + assert(!err); + + if (data != nullptr) + { + void* mapped; + err = vkMapMemory(device, stagingMemory, 0, size, 0, &mapped); + assert(!err); + memcpy(mapped, data, size); + vkUnmapMemory(device, stagingMemory); + } + + err = vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0); + assert(!err); + + // create cmdbuffer to copy staging buffer to device local buffer + createSetupCommandBuffer(); + + VkBufferCopy copyRegion = {}; + copyRegion.size = size; + + vkCmdCopyBuffer( + setupCmdBuffer, + stagingBuffer, + deviceBuffer, + 1, + ©Region); + + flushSetupCommandBuffer(); + + // free staging memory + vkDestroyBuffer(device, stagingBuffer, nullptr); + vkFreeMemory(device, stagingMemory, nullptr); + + return VK_TRUE; +} + VkBool32 VulkanExampleBase::createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, void * data, VkBuffer * buffer, VkDeviceMemory * memory) { VkMemoryRequirements memReqs; diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index c2f13210..b8cd194f 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -271,6 +271,20 @@ public: // Load a SPIR-V shader VkPipelineShaderStageCreateInfo loadShader(std::string fileName, VkShaderStageFlagBits stage); + // create device local buffer and use staging to access + VkBool32 createDeviceBuffer( + const VkBufferUsageFlags usage, + const VkDeviceSize size, + VkBuffer& buffer, + VkDeviceMemory& memory, + VkDescriptorBufferInfo& descriptor); + + // update loacal buffer memory by creating a host visible staging buffer + VkBool32 updateDeviceBuffer( + const VkDeviceSize size, + VkBuffer& deviceBuffer, + void* data); + // Create a buffer, fill it with data (if != NULL) and bind buffer memory VkBool32 createBuffer( VkBufferUsageFlags usageFlags, diff --git a/computeparticles/computeparticles.cpp b/computeparticles/computeparticles.cpp index 060b39e0..1330f48d 100644 --- a/computeparticles/computeparticles.cpp +++ b/computeparticles/computeparticles.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #define GLM_FORCE_RADIANS #define GLM_FORCE_DEPTH_ZERO_TO_ONE @@ -22,15 +23,15 @@ #define VERTEX_BUFFER_BIND_ID 0 #define ENABLE_VALIDATION false -#define PARTICLE_COUNT 8 * 1024 +#define PARTICLE_COUNT 3000 * 1024 class VulkanExample : public VulkanExampleBase { private: vkTools::VulkanTexture textureColorMap; public: - float timer = 0.0f; - float animStart = 50.0f; + float timer = 0.f; + float animStart = 20.0f; bool animate = true; struct { @@ -68,13 +69,11 @@ public: } uniformData; struct Particle { - glm::vec4 pos; - glm::vec4 col; - glm::vec4 vel; + glm::vec2 pos; + glm::vec2 vel; }; VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSetPostCompute; VkDescriptorSetLayout descriptorSetLayout; VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) @@ -103,17 +102,6 @@ public: vkDestroyPipelineLayout(device, computePipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, computeDescriptorSetLayout, nullptr); vkDestroyPipeline(device, pipelines.compute, nullptr); - - textureLoader->destroyTexture(textureColorMap); - } - - void loadTextures() - { - textureLoader->loadTexture( - getAssetPath() + "textures/particle01_rgba.ktx", - VK_FORMAT_R8G8B8A8_UNORM, - &textureColorMap, - false); } void buildCommandBuffers() @@ -151,7 +139,7 @@ public: assert(!err); // 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 // in the vertex shader VkBufferMemoryBarrier bufferBarrier = vkTools::initializers::bufferMemoryBarrier(); // Source access : Compute shader buffer write @@ -191,7 +179,6 @@ public: ); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); - vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSetPostCompute, 0, NULL); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.postCompute); VkDeviceSize offsets[1] = { 0 }; @@ -243,9 +230,6 @@ public: err = swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete); assert(!err); - err = vkQueueWaitIdle(queue); - assert(!err); - // Compute VkSubmitInfo computeSubmitInfo = vkTools::initializers::submitInfo(); computeSubmitInfo.commandBufferCount = 1; @@ -254,6 +238,9 @@ public: err = vkQueueSubmit(computeQueue, 1, &computeSubmitInfo, VK_NULL_HANDLE); assert(!err); + err = vkQueueWaitIdle(queue); + assert(!err); + err = vkQueueWaitIdle(computeQueue); assert(!err); } @@ -262,93 +249,25 @@ public: // vertex positions and velocities void prepareStorageBuffers() { - float destPosX = 0.0f; - float destPosY = 0.0f; + + std::mt19937 rGenerator; + std::uniform_real_distribution rDistribution(-1.f, 1.f); // Initial particle positions - std::vector particleBuffer; - for (int i = 0; i < PARTICLE_COUNT; ++i) + std::vector particleBuffer(PARTICLE_COUNT); + for (auto& element : particleBuffer) { - // Position - float aspectRatio = (float)height / (float)width; - float rndVal = (float)rand() / (float)(RAND_MAX / (360.0f * 3.14f * 2.0f)); - float rndRad = (float)rand() / (float)(RAND_MAX) * 0.5f; - Particle p; - p.pos = glm::vec4( - destPosX + cos(rndVal) * rndRad * aspectRatio, - destPosY + sin(rndVal) * rndRad, - 0.0f, - 1.0f); - p.col = glm::vec4( - (float)(rand() % 255) / 255.0f, - (float)(rand() % 255) / 255.0f, - (float)(rand() % 255) / 255.0f, - 1.0f); - p.vel = glm::vec4(0.0f); - particleBuffer.push_back(p); + element.pos = glm::vec2(rDistribution(rGenerator), rDistribution(rGenerator)); + element.vel = glm::vec2(0.f); } // Buffer size is the same for all storage buffers uint32_t storageBufferSize = particleBuffer.size() * sizeof(Particle); - VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo(); - VkMemoryRequirements memReqs; + createDeviceBuffer(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, storageBufferSize, computeStorageBuffer.buffer, + computeStorageBuffer.memory, computeStorageBuffer.descriptor); - VkResult err; - void *data; - - struct StagingBuffer { - VkDeviceMemory memory; - VkBuffer buffer; - } stagingBuffer; - - // Allocate and fill host-visible staging storage buffer object - - // Allocate and fill storage buffer object - VkBufferCreateInfo vBufferInfo = - vkTools::initializers::bufferCreateInfo( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - storageBufferSize); - vkTools::checkResult(vkCreateBuffer(device, &vBufferInfo, nullptr, &stagingBuffer.buffer)); - vkGetBufferMemoryRequirements(device, stagingBuffer.buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); - vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffer.memory)); - vkTools::checkResult(vkMapMemory(device, stagingBuffer.memory, 0, storageBufferSize, 0, &data)); - memcpy(data, particleBuffer.data(), storageBufferSize); - vkUnmapMemory(device, stagingBuffer.memory); - vkTools::checkResult(vkBindBufferMemory(device, stagingBuffer.buffer, stagingBuffer.memory, 0)); - - // Allocate device local storage buffer ojbect - vBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - vkTools::checkResult(vkCreateBuffer(device, &vBufferInfo, nullptr, &computeStorageBuffer.buffer)); - vkGetBufferMemoryRequirements(device, computeStorageBuffer.buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAlloc.memoryTypeIndex); - vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &computeStorageBuffer.memory)); - vkTools::checkResult(vkBindBufferMemory(device, computeStorageBuffer.buffer, computeStorageBuffer.memory, 0)); - - // Copy from host to device - createSetupCommandBuffer(); - - VkBufferCopy copyRegion = {}; - copyRegion.size = storageBufferSize; - vkCmdCopyBuffer( - setupCmdBuffer, - stagingBuffer.buffer, - computeStorageBuffer.buffer, - 1, - ©Region); - - flushSetupCommandBuffer(); - - // Destroy staging buffer - vkDestroyBuffer(device, stagingBuffer.buffer, nullptr); - vkFreeMemory(device, stagingBuffer.memory, nullptr); - - computeStorageBuffer.descriptor.buffer = computeStorageBuffer.buffer; - computeStorageBuffer.descriptor.offset = 0; - computeStorageBuffer.descriptor.range = storageBufferSize; + updateDeviceBuffer(storageBufferSize, computeStorageBuffer.buffer, particleBuffer.data()); // Binding description vertices.bindingDescriptions.resize(1); @@ -360,7 +279,7 @@ public: // Attribute descriptions // Describes memory layout and shader positions - vertices.attributeDescriptions.resize(2); + vertices.attributeDescriptions.resize(1); // Location 0 : Position vertices.attributeDescriptions[0] = vkTools::initializers::vertexInputAttributeDescription( @@ -368,13 +287,6 @@ public: 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0); - // Location 1 : Color - vertices.attributeDescriptions[1] = - vkTools::initializers::vertexInputAttributeDescription( - VERTEX_BUFFER_BIND_ID, - 1, - VK_FORMAT_R32G32B32A32_SFLOAT, - sizeof(float) * 4); // Assign to vertex buffer vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo(); @@ -389,15 +301,14 @@ public: std::vector poolSizes = { vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), - vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1), - vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1) + vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1) }; VkDescriptorPoolCreateInfo descriptorPoolInfo = vkTools::initializers::descriptorPoolCreateInfo( poolSizes.size(), poolSizes.data(), - 3); + 2); VkResult vkRes = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool); assert(!vkRes); @@ -405,63 +316,26 @@ public: void setupDescriptorSetLayout() { - std::vector setLayoutBindings = - { - // Binding 0 : Fragment shader image sampler - vkTools::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - VK_SHADER_STAGE_FRAGMENT_BIT, - 0) - }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vkTools::initializers::descriptorSetLayoutCreateInfo( - setLayoutBindings.data(), - setLayoutBindings.size()); + VkDescriptorSetLayoutCreateInfo descriptorLayoutInfo; + descriptorLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptorLayoutInfo.pNext = NULL; + descriptorLayoutInfo.flags = 0; + descriptorLayoutInfo.bindingCount = 0; + descriptorLayoutInfo.pBindings = nullptr; - VkResult err = vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout); + VkResult err = vkCreateDescriptorSetLayout(device, &descriptorLayoutInfo, nullptr, &descriptorSetLayout); assert(!err); VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vkTools::initializers::pipelineLayoutCreateInfo( &descriptorSetLayout, - 1); + 0); err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout); assert(!err); } - void setupDescriptorSet() - { - VkDescriptorSetAllocateInfo allocInfo = - vkTools::initializers::descriptorSetAllocateInfo( - descriptorPool, - &descriptorSetLayout, - 1); - - VkResult vkRes = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSetPostCompute); - assert(!vkRes); - - // Image descriptor for the color map texture - VkDescriptorImageInfo texDescriptor = - vkTools::initializers::descriptorImageInfo( - textureColorMap.sampler, - textureColorMap.view, - VK_IMAGE_LAYOUT_GENERAL); - - std::vector writeDescriptorSets = - { - // Binding 1 : Fragment shader image sampler - vkTools::initializers::writeDescriptorSet( - descriptorSetPostCompute, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 0, - &texDescriptor) - }; - - vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); - } - // Create a separate command buffer for compute commands void createComputeCommandBuffer() { @@ -504,16 +378,16 @@ public: VkPipelineDepthStencilStateCreateInfo depthStencilState = vkTools::initializers::pipelineDepthStencilStateCreateInfo( - VK_TRUE, - VK_TRUE, - VK_COMPARE_OP_LESS_OR_EQUAL); + VK_FALSE, + VK_FALSE, + VK_COMPARE_OP_ALWAYS); VkPipelineViewportStateCreateInfo viewportState = vkTools::initializers::pipelineViewportStateCreateInfo(1, 1, 0); VkPipelineMultisampleStateCreateInfo multisampleState = vkTools::initializers::pipelineMultisampleStateCreateInfo( - VK_SAMPLE_COUNT_1_BIT, + VK_SAMPLE_COUNT_4_BIT, 0); std::vector dynamicStateEnables = { @@ -650,27 +524,34 @@ public: void prepareUniformBuffers() { // Compute shader uniform buffer block - createBuffer( + createDeviceBuffer( VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, sizeof(computeUbo), - &computeUbo, - &uniformData.computeShader.ubo.buffer, - &uniformData.computeShader.ubo.memory, - &uniformData.computeShader.ubo.descriptor); + uniformData.computeShader.ubo.buffer, + uniformData.computeShader.ubo.memory, + uniformData.computeShader.ubo.descriptor); + updateDeviceBuffer(sizeof(computeUbo), uniformData.computeShader.ubo.buffer, &computeUbo); updateUniformBuffers(); } void updateUniformBuffers() { - computeUbo.deltaT = frameTimer * 5.0f; - computeUbo.destX = sin(glm::radians(timer*360.0)) * 0.75f; - computeUbo.destY = 0; - uint8_t *pData; - VkResult err = vkMapMemory(device, uniformData.computeShader.ubo.memory, 0, sizeof(computeUbo), 0, (void **)&pData); - assert(!err); - memcpy(pData, &computeUbo, sizeof(computeUbo)); - vkUnmapMemory(device, uniformData.computeShader.ubo.memory); + computeUbo.deltaT = frameTimer * 4.0f; + if (animate) // tmp + { + computeUbo.destX = sin(glm::radians(timer*360.0)) * 0.75f; + computeUbo.destY = 0.f; + } + else + { + float normalizedMx = (mousePos.x - static_cast(width / 2)) / static_cast(width / 2); + float normalizedMy = (mousePos.y - static_cast(height / 2)) / static_cast(height / 2); + computeUbo.destX = normalizedMx; + computeUbo.destY = normalizedMy; + } + + updateDeviceBuffer(sizeof(computeUbo), uniformData.computeShader.ubo.buffer, &computeUbo); } // Find and create a compute capable device queue @@ -693,6 +574,8 @@ public: assert(queueIndex < queueCount); VkDeviceQueueCreateInfo queueCreateInfo = {}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.pNext = NULL; queueCreateInfo.queueFamilyIndex = queueIndex; queueCreateInfo.queueCount = 1; vkGetDeviceQueue(device, queueIndex, 0, &computeQueue); @@ -701,7 +584,6 @@ public: void prepare() { VulkanExampleBase::prepare(); - loadTextures(); getComputeQueue(); createComputeCommandBuffer(); prepareStorageBuffers(); @@ -709,7 +591,6 @@ public: setupDescriptorSetLayout(); preparePipelines(); setupDescriptorPool(); - setupDescriptorSet(); prepareCompute(); buildCommandBuffers(); buildComputeCommandBuffer(); @@ -723,16 +604,18 @@ public: vkDeviceWaitIdle(device); draw(); vkDeviceWaitIdle(device); - if (animStart > 0.0f) + + if (animate) { - animStart -= frameTimer * 5.0f; - } - if ((animate) & (animStart <= 0.0f)) - { - timer += frameTimer * 0.1f; - if (timer > 1.0) + if (animStart > 0.0f) { - timer -= 1.0f; + animStart -= frameTimer * 5.0f; + } + else if (animStart <= 0.0f) + { + timer += frameTimer * 0.04f; + if (timer > 1.f) + timer = 0.f; } } updateUniformBuffers(); diff --git a/data/shaders/computeparticles/particle.comp b/data/shaders/computeparticles/particle.comp index 8af1037d..7209c481 100644 --- a/data/shaders/computeparticles/particle.comp +++ b/data/shaders/computeparticles/particle.comp @@ -5,9 +5,8 @@ struct Particle { - vec4 pos; - vec4 col; - vec4 vel; + vec2 pos; + vec2 vel; }; // Binding 0 : Position storage buffer @@ -26,14 +25,21 @@ layout (binding = 1) uniform UBO int particleCount; } ubo; -vec3 attraction(vec3 pos, vec3 attractPos) +vec2 attraction(vec2 pos, vec2 attractPos) { - vec3 delta = attractPos - pos; + vec2 delta = attractPos - pos; const float damp = 0.5; float dDampedDot = dot(delta, delta) + damp; float invDist = 1.0f / sqrt(dDampedDot); float invDistCubed = invDist*invDist*invDist; - return delta * invDistCubed * 0.00035; + return delta * invDistCubed * 0.0035; +} + +vec2 repulsion(vec2 pos, vec2 attractPos) +{ + vec2 delta = attractPos - pos; + float targetDistance = sqrt(dot(delta, delta)); + return delta * (1.0 / (targetDistance * targetDistance * targetDistance)) * -0.000035; } void main() @@ -45,22 +51,25 @@ void main() return; // Read position and velocity - vec3 vPos = particles[index].pos.xyz; - vec3 vVel = particles[index].vel.xyz; - - vec3 destPos = vec3(ubo.destX, ubo.destY, 0.0); + vec2 vVel = particles[index].vel.xy; + vec2 vPos = particles[index].pos.xy; + + vec2 destPos = vec2(ubo.destX, ubo.destY); + + vec2 delta = destPos - vPos; + float targetDistance = sqrt(dot(delta, delta)); + vVel += repulsion(vPos, destPos.xy) * 0.05; - // Calculate new velocity depending on attraction point - vVel += attraction(vPos, destPos.xyz); - // Move by velocity vPos += vVel * ubo.deltaT; - - if ((vPos.x < -1.0) || (vPos.x > 1.0)) - vVel.x -= vVel.x; + + // collide with boundary + if ((vPos.x < -1.0) || (vPos.x > 1.0) || (vPos.y < -1.0) || (vPos.y > 1.0)) + vVel = (-vVel * 0.1) + attraction(vPos, destPos) * 12; + else + particles[index].pos.xy = vPos; // Write back - particles[index].pos.xyz = vPos; - particles[index].vel.xyz = vVel; + particles[index].vel.xy = vVel; } diff --git a/data/shaders/computeparticles/particle.comp.spv b/data/shaders/computeparticles/particle.comp.spv index cbeab76aab711165266b86e58660751b4343e6aa..ca56a5e57cbfbbb5b2e4559fc326ff2f1e5195d0 100644 GIT binary patch literal 4684 zcmZvd_j6QL6vrQINI;RMfQ=Bujw6Uz5hWOjXjJTNG}$DN7!12H*~G3v#NK=Fy#`d_)SfIPU_F>WHLNS_D!0z zv9s&auH#2*{l~93X_+1~l2YcV&rE!#Fg9VE%7Yar)?u^I)n;c{ZkB|VC88(EuaKr> zTGH9o-G0fM?$LC(JW{Tu-J>^@`_qx`YVXFhuQs~34^xAcf$pJlWnip4kan+FzHGSM zcO&_m_R2pcX-TG&qg<2If)ymQ18M)56%3RGVY1hoSX=+l}85BnoG--zO?SQ7JabNpWc$Ko0^^fz)*MRP_?%_w5~E< z?JIi->pHUeQnH@$@--J_Hz)SV@?4he*1W6!bhLIAqc^Od_ojArrnO|6oxs)A2K$E6 zv#VnjwupBrxrA}7x0>zaI`H@v=@0{aN^(8p`h1O=oucOBy#%+0ah4gc2kZqk^Ar0- zUal?k>CM#onGAx*vm34RO>k>h@(#u_9{1Fo+zS7{v%L%5)^xq=CK~vs4SZXHcjE86 zV2>S&olAr`@5OMR(A=wT-U?s6YI>|1219vd+x=&a`XB){}ZEUa1gdXT{M|-5vyG|nU-U9O`mzWW}GE($3rllvx2u~bYeGO0$aidGpAIZ;)pIhrs%&d=j~K!FLhz|n?1HFKc@?F{Y-Xb z{qmT*5Ul2Ud*pJ=KC*Z8v0tvh)bGgSU72g2vBo~~f515EzmwxyMxVd%ckUWY&9fB$ z&8>;mqKu2v|*D^E#(y9^cVNF}3qBW0>bLOno~(z5`F>n%}4o z@KJj**L^3R2K)FUsriT`yyC2CstE;|yK{t9b_26>%J+uGhilwpRVk z5p}%*cHX+)V)U`DHyGc<)T~P!b-fL4tm_>#^*FD0!D?|{5yvs=dJk-FYt`Qz*6{(O zk9FwtKK2b}9pdPz55e~4-T1XIeuSw-AAXW+A2Y_9&%oAh&wa`$kGapm@s4c+%i|sU z0z4gajdPLXE3k84Vw>}K>T9sMor`x$&HHh0?!*0c5nMJ#((u3uxsV>80RxY`1Hk5tZ}nWTKI+zPKDF>a5Udvb zpq$6I`e3*|>fT>7>!F`H-FasVvF%xVb%w~)}SPCxo!HGGKI+wv+7yJaUG2@<>gY{8&pT<)Q{}o`h z;3wrg?)hZ6KI(CAr-0+$oHwp@sYjes!4cQyi1=mkK ddgV;8z2aQl!&zYSI~Q6zSba6--N?P0e*ujbzYYKZ literal 3664 zcmZvd+jCS!5XOh><_0kk0z?pE0xDDmBbRWAkxN2ki3SrvK)h|v?jFLzW;bR}R#enP zMDhCMAK{a)TE1B2|73Zo((?PwPRB!vNp($sU-xwPbkCk-TK2U&w?Tg$?pxPfJ+4LA zxlOLk@44yA)5GYMxHMTynm#+lm8*@(ay^kpo9q7{pIa`(B|#tSSxk{}NRi>(q zS}~%)sY!3oxD(p1Ow9PMqO*K0uemjjK9=Ho^161qj~_jSyY9Jm&oL#nH7OS>@wwV^ zRi(>2<3_bF7izvf@;3a0!DSFtxC-f1{ng@K$^ELdZ9$)0{`&A&qmoereAR6Tpak_?=g<1Gt)Q*kV zR^#Qs8RnZoKk&aEY}ALH{T&I*aLuEYU%~YDD+zDd@Ym9bcTlI932zP`1lw`lnVPsi zi+=qnrd2z4V%~fsnK_tu#WyL9`97rawRL!I9WDest}M*|sDwAdyEql@F%tOGs)+nx zvmKKT$9d-Zf`r*KZ+w{XDGB`D5bt#0e$*Lee^x>q_&=0mLObhk`JdH3E`g&L=>MpT z=x|oYwDe{j?S8he2s3|Xj*T5(<~<|9KBErOtJ%Q8vzSqfg!|H8?3U+}^mHEmt69r~ zjW=X@u1Lpjd9F%_Ls;oN%ndtzAb~Z z|6QFV_j?j*;_c&44(fPcJBvE-xg&w24s@&I1L^cSediB_;mzmnBYZv*2Y*ks(x;Cl zaGbSspGddZ^c##Hcd=U7>GhEI6$!s3o8PK*dNi)PUex}n#D2po((OI)8@?yOKBND% z;Lid_jI5+pLY)~2wcv}7<-RXHo%?fPYPZ~9NVnYhUY2l{Tn{AJE%%p!BgUh0Rk>CSQ-^d4N{@bL(8Qvc7_u*aa5XJ|7HE@qhhwqaRlbYd(!Hk}ez;y|McT4y- zJ}JTWAjH`to!*852nVZjQlTBk#kFi1|AJu YT}F+sLbIzoI`|t^VLx!c>f%!N2Xosy<^TWy diff --git a/data/shaders/computeparticles/particle.vert b/data/shaders/computeparticles/particle.vert index 5b0c0191..96cea5cf 100644 --- a/data/shaders/computeparticles/particle.vert +++ b/data/shaders/computeparticles/particle.vert @@ -4,13 +4,12 @@ #extension GL_ARB_shading_language_420pack : enable layout (location = 0) in vec4 inPos; -layout (location = 1) in vec4 inColor; layout (location = 0) out vec4 outColor; void main () { - gl_PointSize = 32.0; - outColor = inColor; - gl_Position = vec4(inPos.xyz, 1.0); + gl_PointSize = 1.0; + outColor = vec4(0.035); + gl_Position = vec4(inPos.xy, 1.0, 1.0); } \ No newline at end of file diff --git a/data/shaders/computeparticles/particle.vert.spv b/data/shaders/computeparticles/particle.vert.spv index f2706b60acfa4f24a5ae5064468f0d7dda564242..4f0dc82c3d8d5fc61f7c5052ad8008989629a9e5 100644 GIT binary patch delta 336 zcmXw!OAY}+5Qb}dh8c-x24g%&tR^fhC0=m?>{(b!5C^bu1?iKxg|)4XW7tUiKdn38 zRQ>hns(E=gFSb?36|rzVY0K{vL_v$tM#i=;VH|khyo2w4vprB`K=HcvEq%65I<4;N zJk?Lt-*v^2B$6c%uX5v_xVR!^6Jz`jYqQV+;EA9su-t(?L!(0z3!tm;`Mv`BXpdSG zv84#X0b>-fu?E;Q7gs;*FtwD#x2d5m$6qv&sRNE#nDtul8-TgIVTLXregycxT$9tN KS^vfh1MmT