**NVIDIA Vulkan Ray Tracing Tutorial** **Animation** Authors: [Martin-Karl Lefrançois](https://devblogs.nvidia.com/author/mlefrancois/), Neil Bickford # Animation ![](Images/animation2.gif) This is an extension of the [Vulkan ray tracing tutorial](vkrt_tutorial.md.html). We will discuss two animation methods: animating only the transformation matrices, and animating the geometry itself. (insert setup.md.html here) # Animating the Matrices This first example shows how we can update the matrices used for instances in the TLAS. ## Creating a Scene In main.cpp we can create a new scene with a ground plane and 21 instances of the Wuson model, by replacing the `helloVk.loadModel` calls in `main()`. The code below creates all of the instances at the same position, but we will displace them later in the animation function. If you run the example, you will find that the rendering is considerably slow, because the geometries are exactly at the same position and the acceleration structure does not deal with this well. ~~~~ C++ helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths), nvmath::scale_mat4(nvmath::vec3f(2.f, 1.f, 2.f))); helloVk.loadModel(nvh::findFile("media/scenes/wuson.obj", defaultSearchPaths)); HelloVulkan::ObjInstance inst = helloVk.m_objInstance.back(); for(int i = 0; i < 20; i++) helloVk.m_objInstance.push_back(inst); ~~~~ ## Animation Function We want to have all of the Wuson models running in a circle, and we will first modify the rasterizer to handle this. Animating the transformation matrices will be done entirely on the CPU, and we will copy the computed transformation to the GPU. In the next example, the animation will be done on the GPU using a compute shader. Add the declaration of the animation to the `HelloVulkan` class. ~~~~ C++ void animationInstances(float time); ~~~~ The first part computes the transformations for all of the Wuson models, placing each one behind another. ~~~~ C++ void HelloVulkan::animationInstances(float time) { const int32_t nbWuson = static_cast(m_objInstance.size() - 1); const float deltaAngle = 6.28318530718f / static_cast(nbWuson); const float wusonLength = 3.f; const float radius = wusonLength / (2.f * sin(deltaAngle / 2.0f)); const float offset = time * 0.5f; for(int i = 0; i < nbWuson; i++) { int wusonIdx = i + 1; ObjInstance& inst = m_objInstance[wusonIdx]; inst.transform = nvmath::rotation_mat4_y(i * deltaAngle + offset) * nvmath::translation_mat4(radius, 0.f, 0.f); inst.transformIT = nvmath::transpose(nvmath::invert(inst.transform)); } ~~~~ Next, we update the buffer that describes the scene, which is used by the rasterizer to set each object's position, and also by the ray tracer to compute shading normals. ~~~~ C++ // Update the buffer vk::DeviceSize bufferSize = m_objInstance.size() * sizeof(ObjInstance); nvvkBuffer stagingBuffer = m_alloc.createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible); // Copy data to staging buffer auto* gInst = m_alloc.map(stagingBuffer); memcpy(gInst, m_objInstance.data(), bufferSize); m_alloc.unmap(stagingBuffer); // Copy staging buffer to the Scene Description buffer nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize)); m_debug.endLabel(cmdBuf); genCmdBuf.submitAndWait(cmdBuf); m_alloc.destroy(stagingBuffer); m_rtBuilder.updateTlasMatrices(m_tlas); m_rtBuilder.updateBlas(2); } ~~~~ # Final Code You can find the final code in the folder [ray_tracing_animation](https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing_animation)