| 360 | } |
| 361 | |
| 362 | void Instancing::prepare_instance_data() |
| 363 | { |
| 364 | std::vector<InstanceData> instance_data; |
| 365 | instance_data.resize(INSTANCE_COUNT); |
| 366 | |
| 367 | std::default_random_engine rnd_generator(lock_simulation_speed ? 0 : static_cast<unsigned>(time(nullptr))); |
| 368 | std::uniform_real_distribution<float> uniform_dist(0.0, 1.0); |
| 369 | std::uniform_int_distribution<uint32_t> rnd_texture_index(0, textures.rocks.image->get_vk_image().get_array_layer_count()); |
| 370 | |
| 371 | // Distribute rocks randomly on two different rings |
| 372 | for (auto i = 0; i < INSTANCE_COUNT / 2; i++) |
| 373 | { |
| 374 | glm::vec2 ring0{7.0f, 11.0f}; |
| 375 | glm::vec2 ring1{14.0f, 18.0f}; |
| 376 | |
| 377 | float rho, theta; |
| 378 | |
| 379 | // Inner ring |
| 380 | rho = sqrt((pow(ring0[1], 2.0f) - pow(ring0[0], 2.0f)) * uniform_dist(rnd_generator) + pow(ring0[0], 2.0f)); |
| 381 | theta = 2.0f * glm::pi<float>() * uniform_dist(rnd_generator); |
| 382 | instance_data[i].pos = glm::vec3(rho * cos(theta), uniform_dist(rnd_generator) * 0.5f - 0.25f, rho * sin(theta)); |
| 383 | instance_data[i].rot = glm::vec3(glm::pi<float>() * uniform_dist(rnd_generator), glm::pi<float>() * uniform_dist(rnd_generator), glm::pi<float>() * uniform_dist(rnd_generator)); |
| 384 | instance_data[i].scale = 1.5f + uniform_dist(rnd_generator) - uniform_dist(rnd_generator); |
| 385 | instance_data[i].texIndex = rnd_texture_index(rnd_generator); |
| 386 | instance_data[i].scale *= 0.75f; |
| 387 | |
| 388 | // Outer ring |
| 389 | rho = sqrt((pow(ring1[1], 2.0f) - pow(ring1[0], 2.0f)) * uniform_dist(rnd_generator) + pow(ring1[0], 2.0f)); |
| 390 | theta = 2.0f * glm::pi<float>() * uniform_dist(rnd_generator); |
| 391 | instance_data[static_cast<size_t>(i + INSTANCE_COUNT / 2)].pos = glm::vec3(rho * cos(theta), uniform_dist(rnd_generator) * 0.5f - 0.25f, rho * sin(theta)); |
| 392 | instance_data[static_cast<size_t>(i + INSTANCE_COUNT / 2)].rot = glm::vec3(glm::pi<float>() * uniform_dist(rnd_generator), glm::pi<float>() * uniform_dist(rnd_generator), glm::pi<float>() * uniform_dist(rnd_generator)); |
| 393 | instance_data[static_cast<size_t>(i + INSTANCE_COUNT / 2)].scale = 1.5f + uniform_dist(rnd_generator) - uniform_dist(rnd_generator); |
| 394 | instance_data[static_cast<size_t>(i + INSTANCE_COUNT / 2)].texIndex = rnd_texture_index(rnd_generator); |
| 395 | instance_data[static_cast<size_t>(i + INSTANCE_COUNT / 2)].scale *= 0.75f; |
| 396 | } |
| 397 | |
| 398 | instance_buffer.size = instance_data.size() * sizeof(InstanceData); |
| 399 | |
| 400 | // Staging |
| 401 | // Instanced data is static, copy to device local memory |
| 402 | // On devices with separate memory types for host visible and device local memory this will result in better performance |
| 403 | // On devices with unified memory types (DEVICE_LOCAL_BIT and HOST_VISIBLE_BIT supported at once) this isn't necessary and you could skip the staging |
| 404 | |
| 405 | vkb::core::BufferC staging_buffer = vkb::core::BufferC::create_staging_buffer(get_device(), instance_data); |
| 406 | |
| 407 | instance_buffer.buffer = std::make_unique<vkb::core::BufferC>(get_device(), instance_buffer.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); |
| 408 | |
| 409 | // Copy to staging buffer |
| 410 | VkCommandBuffer copy_command = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); |
| 411 | |
| 412 | VkBufferCopy copy_region = {}; |
| 413 | copy_region.size = instance_buffer.size; |
| 414 | vkCmdCopyBuffer( |
| 415 | copy_command, |
| 416 | staging_buffer.get_handle(), |
| 417 | instance_buffer.buffer->get_handle(), |
| 418 | 1, |
| 419 | ©_region); |
nothing calls this directly
no test coverage detected