2016-06-11 17:05:29 +02:00
/*
2016-07-23 22:47:58 +02:00
* Vulkan Example - Scene rendering
2016-06-11 17:05:29 +02:00
*
* Copyright ( C ) 2016 by Sascha Willems - www . saschawillems . de
*
* This code is licensed under the MIT license ( MIT ) ( http : //opensource.org/licenses/MIT)
2016-07-23 22:47:58 +02:00
*
* Summary :
2017-02-11 09:44:22 +01:00
* Renders a scene made of multiple parts with different materials and textures .
2016-07-23 22:47:58 +02:00
*
2017-02-11 09:44:22 +01:00
* The example loads a scene made up of multiple parts into one vertex and index buffer to only
2016-07-23 22:47:58 +02:00
* have one ( big ) memory allocation . In Vulkan it ' s advised to keep number of memory allocations
* down and try to allocate large blocks of memory at once instead of having many small allocations .
*
2017-02-11 09:44:22 +01:00
* Every part has a separate material and multiple descriptor sets ( set = x layout qualifier in GLSL )
* are used to bind a uniform buffer with global matrices and the part ' s material ' s sampler at once .
2016-07-23 22:47:58 +02:00
*
* To demonstrate another way of passing data the example also uses push constants for passing
* material properties .
*
2017-02-11 09:44:22 +01:00
* Note that this example is just one way of rendering a scene made up of multiple parts in Vulkan .
2016-06-11 17:05:29 +02:00
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# include <vector>
# define GLM_FORCE_RADIANS
# define GLM_FORCE_DEPTH_ZERO_TO_ONE
# include <glm/glm.hpp>
# include <glm/gtc/matrix_transform.hpp>
# include <glm/gtc/type_ptr.hpp>
2017-02-11 09:44:22 +01:00
# include <assimp/Importer.hpp>
# include <assimp/scene.h>
# include <assimp/postprocess.h>
# include <assimp/cimport.h>
2016-06-11 17:05:29 +02:00
# include <vulkan/vulkan.h>
# include "vulkanexamplebase.h"
2017-02-09 21:55:35 +01:00
# include "VulkanTexture.hpp"
2017-02-12 10:16:07 +01:00
# include "VulkanDevice.hpp"
2017-02-12 10:44:51 +01:00
# include "VulkanBuffer.hpp"
2016-06-11 17:05:29 +02:00
# define VERTEX_BUFFER_BIND_ID 0
# define ENABLE_VALIDATION false
// Vertex layout used in this example
struct Vertex {
glm : : vec3 pos ;
glm : : vec3 normal ;
glm : : vec2 uv ;
glm : : vec3 color ;
} ;
// Scene related structs
2016-06-12 16:55:53 +02:00
// Shader properites for a material
// Will be passed to the shaders using push constant
struct SceneMaterialProperites
{
glm : : vec4 ambient ;
glm : : vec4 diffuse ;
glm : : vec4 specular ;
float opacity ;
} ;
2016-06-11 17:05:29 +02:00
// Stores info on the materials used in the scene
struct SceneMaterial
{
std : : string name ;
2016-06-12 16:55:53 +02:00
// Material properties
SceneMaterialProperites properties ;
2016-06-11 17:05:29 +02:00
// The example only uses a diffuse channel
2017-02-09 21:55:35 +01:00
vks : : Texture2D diffuse ;
2016-06-11 17:05:29 +02:00
// The material's descriptor contains the material descriptors
VkDescriptorSet descriptorSet ;
// Pointer to the pipeline used by this material
VkPipeline * pipeline ;
} ;
// Stores per-mesh Vulkan resources
2017-02-11 09:44:22 +01:00
struct ScenePart
2016-06-11 17:05:29 +02:00
{
2016-07-23 22:47:58 +02:00
// Index of first index in the scene buffer
uint32_t indexBase ;
2016-06-11 17:05:29 +02:00
uint32_t indexCount ;
// Pointer to the material used by this mesh
SceneMaterial * material ;
} ;
// Class for loading the scene and generating all Vulkan resources
class Scene
{
private :
2017-02-12 10:16:07 +01:00
vks : : VulkanDevice * vulkanDevice ;
2016-06-11 17:05:29 +02:00
VkQueue queue ;
VkDescriptorPool descriptorPool ;
2016-06-12 13:29:21 +02:00
// We will be using separate descriptor sets (and bindings)
// for material and scene related uniforms
struct
{
VkDescriptorSetLayout material ;
VkDescriptorSetLayout scene ;
} descriptorSetLayouts ;
2016-07-23 22:47:58 +02:00
// We will be using one single index and vertex buffer
// containing vertices and indices for all meshes in the scene
// This allows us to keep memory allocations down
2017-02-12 10:44:51 +01:00
vks : : Buffer vertexBuffer ;
vks : : Buffer indexBuffer ;
2016-07-23 22:47:58 +02:00
2016-06-12 13:29:21 +02:00
VkDescriptorSet descriptorSetScene ;
2016-06-11 17:05:29 +02:00
const aiScene * aScene ;
// Get materials from the assimp scene and map to our scene structures
void loadMaterials ( )
{
materials . resize ( aScene - > mNumMaterials ) ;
for ( size_t i = 0 ; i < materials . size ( ) ; i + + )
{
materials [ i ] = { } ;
aiString name ;
aScene - > mMaterials [ i ] - > Get ( AI_MATKEY_NAME , name ) ;
// Properties
2016-06-12 16:55:53 +02:00
aiColor4D color ;
aScene - > mMaterials [ i ] - > Get ( AI_MATKEY_COLOR_AMBIENT , color ) ;
2016-06-12 17:38:06 +02:00
materials [ i ] . properties . ambient = glm : : make_vec4 ( & color . r ) + glm : : vec4 ( 0.1f ) ;
2016-06-11 17:05:29 +02:00
aScene - > mMaterials [ i ] - > Get ( AI_MATKEY_COLOR_DIFFUSE , color ) ;
2016-06-12 16:55:53 +02:00
materials [ i ] . properties . diffuse = glm : : make_vec4 ( & color . r ) ;
2016-06-11 17:05:29 +02:00
aScene - > mMaterials [ i ] - > Get ( AI_MATKEY_COLOR_SPECULAR , color ) ;
2016-06-12 16:55:53 +02:00
materials [ i ] . properties . specular = glm : : make_vec4 ( & color . r ) ;
aScene - > mMaterials [ i ] - > Get ( AI_MATKEY_OPACITY , materials [ i ] . properties . opacity ) ;
2016-06-11 17:05:29 +02:00
2016-06-12 16:55:53 +02:00
if ( ( materials [ i ] . properties . opacity ) > 0.0f )
materials [ i ] . properties . specular = glm : : vec4 ( 0.0f ) ;
2016-06-11 17:05:29 +02:00
materials [ i ] . name = name . C_Str ( ) ;
std : : cout < < " Material \" " < < materials [ i ] . name < < " \" " < < std : : endl ;
// Textures
aiString texturefile ;
// Diffuse
aScene - > mMaterials [ i ] - > GetTexture ( aiTextureType_DIFFUSE , 0 , & texturefile ) ;
if ( aScene - > mMaterials [ i ] - > GetTextureCount ( aiTextureType_DIFFUSE ) > 0 )
{
std : : cout < < " Diffuse: \" " < < texturefile . C_Str ( ) < < " \" " < < std : : endl ;
std : : string fileName = std : : string ( texturefile . C_Str ( ) ) ;
std : : replace ( fileName . begin ( ) , fileName . end ( ) , ' \\ ' , ' / ' ) ;
2017-02-09 21:55:35 +01:00
materials [ i ] . diffuse . loadFromFile ( assetPath + fileName , VK_FORMAT_BC3_UNORM_BLOCK , vulkanDevice , queue ) ;
2016-06-11 17:05:29 +02:00
}
else
{
std : : cout < < " Material has no diffuse, using dummy texture! " < < std : : endl ;
// todo : separate pipeline and layout
2017-02-09 21:55:35 +01:00
materials [ i ] . diffuse . loadFromFile ( assetPath + " dummy.ktx " , VK_FORMAT_BC2_UNORM_BLOCK , vulkanDevice , queue ) ;
2016-06-11 17:05:29 +02:00
}
// For scenes with multiple textures per material we would need to check for additional texture types, e.g.:
// aiTextureType_HEIGHT, aiTextureType_OPACITY, aiTextureType_SPECULAR, etc.
2016-06-12 16:55:53 +02:00
// Assign pipeline
materials [ i ] . pipeline = ( materials [ i ] . properties . opacity = = 0.0f ) ? & pipelines . solid : & pipelines . blending ;
2016-06-11 17:05:29 +02:00
}
// Generate descriptor sets for the materials
// Descriptor pool
std : : vector < VkDescriptorPoolSize > poolSizes ;
2017-02-12 11:12:42 +01:00
poolSizes . push_back ( vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , static_cast < uint32_t > ( materials . size ( ) ) ) ) ;
poolSizes . push_back ( vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , static_cast < uint32_t > ( materials . size ( ) ) ) ) ;
2016-06-11 17:05:29 +02:00
VkDescriptorPoolCreateInfo descriptorPoolInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorPoolCreateInfo (
2016-06-11 17:05:29 +02:00
static_cast < uint32_t > ( poolSizes . size ( ) ) ,
poolSizes . data ( ) ,
2016-06-12 13:29:21 +02:00
static_cast < uint32_t > ( materials . size ( ) ) + 1 ) ;
2016-06-11 17:05:29 +02:00
2016-07-23 21:21:32 +02:00
VK_CHECK_RESULT ( vkCreateDescriptorPool ( vulkanDevice - > logicalDevice , & descriptorPoolInfo , nullptr , & descriptorPool ) ) ;
2016-06-11 17:05:29 +02:00
2016-06-12 13:29:21 +02:00
// Descriptor set and pipeline layouts
2016-06-11 17:05:29 +02:00
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings ;
2016-06-12 13:29:21 +02:00
VkDescriptorSetLayoutCreateInfo descriptorLayout ;
// Set 0: Scene matrices
2017-02-12 11:12:42 +01:00
setLayoutBindings . push_back ( vks : : initializers : : descriptorSetLayoutBinding (
2016-06-11 17:05:29 +02:00
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ,
VK_SHADER_STAGE_VERTEX_BIT ,
0 ) ) ;
2017-02-12 11:12:42 +01:00
descriptorLayout = vks : : initializers : : descriptorSetLayoutCreateInfo (
2016-06-11 17:05:29 +02:00
setLayoutBindings . data ( ) ,
static_cast < uint32_t > ( setLayoutBindings . size ( ) ) ) ;
2016-07-23 21:21:32 +02:00
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( vulkanDevice - > logicalDevice , & descriptorLayout , nullptr , & descriptorSetLayouts . scene ) ) ;
2016-06-11 17:05:29 +02:00
2016-06-12 13:29:21 +02:00
// Set 1: Material data
setLayoutBindings . clear ( ) ;
2017-02-12 11:12:42 +01:00
setLayoutBindings . push_back ( vks : : initializers : : descriptorSetLayoutBinding (
2016-06-12 13:29:21 +02:00
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ,
VK_SHADER_STAGE_FRAGMENT_BIT ,
0 ) ) ;
2016-07-23 21:21:32 +02:00
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( vulkanDevice - > logicalDevice , & descriptorLayout , nullptr , & descriptorSetLayouts . material ) ) ;
2016-06-11 17:05:29 +02:00
2016-06-12 13:29:21 +02:00
// Setup pipeline layout
std : : array < VkDescriptorSetLayout , 2 > setLayouts = { descriptorSetLayouts . scene , descriptorSetLayouts . material } ;
2017-02-12 11:12:42 +01:00
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks : : initializers : : pipelineLayoutCreateInfo ( setLayouts . data ( ) , static_cast < uint32_t > ( setLayouts . size ( ) ) ) ;
2016-06-11 17:05:29 +02:00
// We will be using a push constant block to pass material properties to the fragment shaders
2017-02-12 11:12:42 +01:00
VkPushConstantRange pushConstantRange = vks : : initializers : : pushConstantRange (
2016-06-12 16:55:53 +02:00
VK_SHADER_STAGE_FRAGMENT_BIT ,
sizeof ( SceneMaterialProperites ) ,
0 ) ;
2016-06-11 17:05:29 +02:00
pipelineLayoutCreateInfo . pushConstantRangeCount = 1 ;
pipelineLayoutCreateInfo . pPushConstantRanges = & pushConstantRange ;
2016-07-23 21:21:32 +02:00
VK_CHECK_RESULT ( vkCreatePipelineLayout ( vulkanDevice - > logicalDevice , & pipelineLayoutCreateInfo , nullptr , & pipelineLayout ) ) ;
2016-06-11 17:05:29 +02:00
2016-06-12 13:29:21 +02:00
// Material descriptor sets
2016-06-11 17:05:29 +02:00
for ( size_t i = 0 ; i < materials . size ( ) ; i + + )
{
// Descriptor set
VkDescriptorSetAllocateInfo allocInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorSetAllocateInfo (
2016-06-11 17:05:29 +02:00
descriptorPool ,
2016-06-12 13:29:21 +02:00
& descriptorSetLayouts . material ,
2016-06-11 17:05:29 +02:00
1 ) ;
2016-07-23 21:21:32 +02:00
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( vulkanDevice - > logicalDevice , & allocInfo , & materials [ i ] . descriptorSet ) ) ;
2016-06-11 17:05:29 +02:00
std : : vector < VkWriteDescriptorSet > writeDescriptorSets ;
// todo : only use image sampler descriptor set and use one scene ubo for matrices
2016-06-12 13:29:21 +02:00
// Binding 0: Diffuse texture
2017-02-12 11:12:42 +01:00
writeDescriptorSets . push_back ( vks : : initializers : : writeDescriptorSet (
2016-06-11 17:05:29 +02:00
materials [ i ] . descriptorSet ,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ,
2016-06-12 13:29:21 +02:00
0 ,
2016-07-23 22:47:58 +02:00
& materials [ i ] . diffuse . descriptor ) ) ;
2016-06-11 17:05:29 +02:00
2016-07-23 22:47:58 +02:00
vkUpdateDescriptorSets ( vulkanDevice - > logicalDevice , static_cast < uint32_t > ( writeDescriptorSets . size ( ) ) , writeDescriptorSets . data ( ) , 0 , NULL ) ;
2016-06-11 17:05:29 +02:00
}
2016-06-12 13:29:21 +02:00
// Scene descriptor set
VkDescriptorSetAllocateInfo allocInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : descriptorSetAllocateInfo (
2016-06-12 13:29:21 +02:00
descriptorPool ,
& descriptorSetLayouts . scene ,
1 ) ;
2016-07-23 21:21:32 +02:00
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( vulkanDevice - > logicalDevice , & allocInfo , & descriptorSetScene ) ) ;
2016-06-12 13:29:21 +02:00
std : : vector < VkWriteDescriptorSet > writeDescriptorSets ;
// Binding 0 : Vertex shader uniform buffer
2017-02-12 11:12:42 +01:00
writeDescriptorSets . push_back ( vks : : initializers : : writeDescriptorSet (
2016-06-12 13:29:21 +02:00
descriptorSetScene ,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ,
0 ,
2016-06-12 16:55:53 +02:00
& uniformBuffer . descriptor ) ) ;
2016-06-12 13:29:21 +02:00
2016-07-23 22:47:58 +02:00
vkUpdateDescriptorSets ( vulkanDevice - > logicalDevice , static_cast < uint32_t > ( writeDescriptorSets . size ( ) ) , writeDescriptorSets . data ( ) , 0 , NULL ) ;
2016-06-11 17:05:29 +02:00
}
2016-07-23 22:47:58 +02:00
// Load all meshes from the scene and generate the buffers for rendering them
2016-06-11 17:05:29 +02:00
void loadMeshes ( VkCommandBuffer copyCmd )
{
2016-07-23 22:47:58 +02:00
std : : vector < Vertex > vertices ;
std : : vector < uint32_t > indices ;
uint32_t indexBase = 0 ;
2016-06-11 17:05:29 +02:00
meshes . resize ( aScene - > mNumMeshes ) ;
for ( uint32_t i = 0 ; i < meshes . size ( ) ; i + + )
{
aiMesh * aMesh = aScene - > mMeshes [ i ] ;
std : : cout < < " Mesh \" " < < aMesh - > mName . C_Str ( ) < < " \" " < < std : : endl ;
std : : cout < < " Material: \" " < < materials [ aMesh - > mMaterialIndex ] . name < < " \" " < < std : : endl ;
std : : cout < < " Faces: " < < aMesh - > mNumFaces < < std : : endl ;
meshes [ i ] . material = & materials [ aMesh - > mMaterialIndex ] ;
2016-07-23 22:47:58 +02:00
meshes [ i ] . indexBase = indexBase ;
meshes [ i ] . indexCount = aMesh - > mNumFaces * 3 ;
2016-06-11 17:05:29 +02:00
// Vertices
bool hasUV = aMesh - > HasTextureCoords ( 0 ) ;
bool hasColor = aMesh - > HasVertexColors ( 0 ) ;
bool hasNormals = aMesh - > HasNormals ( ) ;
2016-06-12 13:29:21 +02:00
for ( uint32_t v = 0 ; v < aMesh - > mNumVertices ; v + + )
2016-06-11 17:05:29 +02:00
{
2016-07-23 22:47:58 +02:00
Vertex vertex ;
vertex . pos = glm : : make_vec3 ( & aMesh - > mVertices [ v ] . x ) ;
vertex . pos . y = - vertex . pos . y ;
vertex . uv = hasUV ? glm : : make_vec2 ( & aMesh - > mTextureCoords [ 0 ] [ v ] . x ) : glm : : vec2 ( 0.0f ) ;
vertex . normal = hasNormals ? glm : : make_vec3 ( & aMesh - > mNormals [ v ] . x ) : glm : : vec3 ( 0.0f ) ;
vertex . normal . y = - vertex . normal . y ;
vertex . color = hasColor ? glm : : make_vec3 ( & aMesh - > mColors [ 0 ] [ v ] . r ) : glm : : vec3 ( 1.0f ) ;
vertices . push_back ( vertex ) ;
2016-06-11 17:05:29 +02:00
}
// Indices
2016-06-12 13:29:21 +02:00
for ( uint32_t f = 0 ; f < aMesh - > mNumFaces ; f + + )
2016-06-11 17:05:29 +02:00
{
2016-07-23 22:47:58 +02:00
for ( uint32_t j = 0 ; j < 3 ; j + + )
{
indices . push_back ( aMesh - > mFaces [ f ] . mIndices [ j ] ) ;
}
2016-06-11 17:05:29 +02:00
}
2016-07-23 22:47:58 +02:00
indexBase + = aMesh - > mNumFaces * 3 ;
2016-06-11 17:05:29 +02:00
}
2016-07-23 22:47:58 +02:00
// Create buffers
// For better performance we only create one index and vertex buffer to keep number of memory allocations down
size_t vertexDataSize = vertices . size ( ) * sizeof ( Vertex ) ;
size_t indexDataSize = indices . size ( ) * sizeof ( uint32_t ) ;
2017-02-12 10:44:51 +01:00
vks : : Buffer vertexStaging , indexStaging ;
2016-07-23 22:47:58 +02:00
// Vertex buffer
// Staging buffer
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_TRANSFER_SRC_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
& vertexStaging ,
static_cast < uint32_t > ( vertexDataSize ) ,
vertices . data ( ) ) ) ;
// Target
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT ,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ,
& vertexBuffer ,
static_cast < uint32_t > ( vertexDataSize ) ) ) ;
// Index buffer
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_TRANSFER_SRC_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
& indexStaging ,
static_cast < uint32_t > ( indexDataSize ) ,
indices . data ( ) ) ) ;
// Target
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT ,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ,
& indexBuffer ,
static_cast < uint32_t > ( indexDataSize ) ) ) ;
// Copy
2017-02-12 11:12:42 +01:00
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
2016-07-23 22:47:58 +02:00
VK_CHECK_RESULT ( vkBeginCommandBuffer ( copyCmd , & cmdBufInfo ) ) ;
VkBufferCopy copyRegion = { } ;
copyRegion . size = vertexDataSize ;
vkCmdCopyBuffer (
copyCmd ,
vertexStaging . buffer ,
vertexBuffer . buffer ,
1 ,
& copyRegion ) ;
copyRegion . size = indexDataSize ;
vkCmdCopyBuffer (
copyCmd ,
indexStaging . buffer ,
indexBuffer . buffer ,
1 ,
& copyRegion ) ;
VK_CHECK_RESULT ( vkEndCommandBuffer ( copyCmd ) ) ;
VkSubmitInfo submitInfo = { } ;
submitInfo . sType = VK_STRUCTURE_TYPE_SUBMIT_INFO ;
submitInfo . commandBufferCount = 1 ;
submitInfo . pCommandBuffers = & copyCmd ;
VK_CHECK_RESULT ( vkQueueSubmit ( queue , 1 , & submitInfo , VK_NULL_HANDLE ) ) ;
VK_CHECK_RESULT ( vkQueueWaitIdle ( queue ) ) ;
//todo: fence
vertexStaging . destroy ( ) ;
indexStaging . destroy ( ) ;
2016-06-11 17:05:29 +02:00
}
public :
# if defined(__ANDROID__)
AAssetManager * assetManager = nullptr ;
# endif
std : : string assetPath = " " ;
std : : vector < SceneMaterial > materials ;
2017-02-11 09:44:22 +01:00
std : : vector < ScenePart > meshes ;
2016-06-11 17:05:29 +02:00
2016-06-12 16:55:53 +02:00
// Shared ubo containing matrices used by all
// materials and meshes
2017-02-12 10:44:51 +01:00
vks : : Buffer uniformBuffer ;
2016-12-24 12:48:01 +01:00
struct UniformData {
2016-06-12 16:55:53 +02:00
glm : : mat4 projection ;
glm : : mat4 view ;
glm : : mat4 model ;
2016-06-12 17:38:06 +02:00
glm : : vec4 lightPos = glm : : vec4 ( 1.25f , 8.35f , 0.0f , 0.0f ) ;
2016-06-12 16:55:53 +02:00
} uniformData ;
// Scene uses multiple pipelines
struct {
VkPipeline solid ;
VkPipeline blending ;
VkPipeline wireframe ;
} pipelines ;
// Shared pipeline layout
2016-06-11 17:05:29 +02:00
VkPipelineLayout pipelineLayout ;
// For displaying only a single part of the scene
bool renderSingleScenePart = false ;
uint32_t scenePartIndex = 0 ;
2016-07-23 21:21:32 +02:00
// Default constructor
2017-02-12 10:16:07 +01:00
Scene ( vks : : VulkanDevice * vulkanDevice , VkQueue queue )
2016-06-11 17:05:29 +02:00
{
2016-07-23 21:21:32 +02:00
this - > vulkanDevice = vulkanDevice ;
2016-06-11 17:05:29 +02:00
this - > queue = queue ;
2016-06-12 16:55:53 +02:00
// Prepare uniform buffer for global matrices
VkMemoryRequirements memReqs ;
2017-02-12 11:12:42 +01:00
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
VkBufferCreateInfo bufferCreateInfo = vks : : initializers : : bufferCreateInfo ( VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT , sizeof ( uniformData ) ) ;
2016-07-23 21:21:32 +02:00
VK_CHECK_RESULT ( vkCreateBuffer ( vulkanDevice - > logicalDevice , & bufferCreateInfo , nullptr , & uniformBuffer . buffer ) ) ;
vkGetBufferMemoryRequirements ( vulkanDevice - > logicalDevice , uniformBuffer . buffer , & memReqs ) ;
2016-06-12 16:55:53 +02:00
memAlloc . allocationSize = memReqs . size ;
2016-07-23 21:21:32 +02:00
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( vulkanDevice - > logicalDevice , & memAlloc , nullptr , & uniformBuffer . memory ) ) ;
VK_CHECK_RESULT ( vkBindBufferMemory ( vulkanDevice - > logicalDevice , uniformBuffer . buffer , uniformBuffer . memory , 0 ) ) ;
VK_CHECK_RESULT ( vkMapMemory ( vulkanDevice - > logicalDevice , uniformBuffer . memory , 0 , sizeof ( uniformData ) , 0 , ( void * * ) & uniformBuffer . mapped ) ) ;
2016-06-12 16:55:53 +02:00
uniformBuffer . descriptor . offset = 0 ;
uniformBuffer . descriptor . buffer = uniformBuffer . buffer ;
uniformBuffer . descriptor . range = sizeof ( uniformData ) ;
2016-12-24 12:48:01 +01:00
uniformBuffer . device = vulkanDevice - > logicalDevice ;
2016-06-11 17:05:29 +02:00
}
2016-07-23 21:21:32 +02:00
// Default destructor
2016-06-11 17:05:29 +02:00
~ Scene ( )
{
2016-07-23 22:47:58 +02:00
vertexBuffer . destroy ( ) ;
indexBuffer . destroy ( ) ;
2016-06-11 17:05:29 +02:00
for ( auto material : materials )
{
2017-02-09 21:55:35 +01:00
material . diffuse . destroy ( ) ;
2016-06-11 17:05:29 +02:00
}
2016-07-23 21:21:32 +02:00
vkDestroyPipelineLayout ( vulkanDevice - > logicalDevice , pipelineLayout , nullptr ) ;
vkDestroyDescriptorSetLayout ( vulkanDevice - > logicalDevice , descriptorSetLayouts . material , nullptr ) ;
vkDestroyDescriptorSetLayout ( vulkanDevice - > logicalDevice , descriptorSetLayouts . scene , nullptr ) ;
vkDestroyDescriptorPool ( vulkanDevice - > logicalDevice , descriptorPool , nullptr ) ;
vkDestroyPipeline ( vulkanDevice - > logicalDevice , pipelines . solid , nullptr ) ;
vkDestroyPipeline ( vulkanDevice - > logicalDevice , pipelines . blending , nullptr ) ;
vkDestroyPipeline ( vulkanDevice - > logicalDevice , pipelines . wireframe , nullptr ) ;
2016-12-24 12:48:01 +01:00
uniformBuffer . destroy ( ) ;
2016-06-11 17:05:29 +02:00
}
void load ( std : : string filename , VkCommandBuffer copyCmd )
{
Assimp : : Importer Importer ;
2016-06-12 16:55:53 +02:00
int flags = aiProcess_PreTransformVertices | aiProcess_Triangulate | aiProcess_GenNormals ;
2016-06-11 17:05:29 +02:00
# if defined(__ANDROID__)
AAsset * asset = AAssetManager_open ( assetManager , filename . c_str ( ) , AASSET_MODE_STREAMING ) ;
assert ( asset ) ;
size_t size = AAsset_getLength ( asset ) ;
assert ( size > 0 ) ;
void * meshData = malloc ( size ) ;
AAsset_read ( asset , meshData , size ) ;
AAsset_close ( asset ) ;
aScene = Importer . ReadFileFromMemory ( meshData , size , flags ) ;
free ( meshData ) ;
# else
aScene = Importer . ReadFile ( filename . c_str ( ) , flags ) ;
# endif
if ( aScene )
{
loadMaterials ( ) ;
loadMeshes ( copyCmd ) ;
}
else
{
printf ( " Error parsing '%s': '%s' \n " , filename . c_str ( ) , Importer . GetErrorString ( ) ) ;
# if defined(__ANDROID__)
LOGE ( " Error parsing '%s': '%s' " , filename . c_str ( ) , Importer . GetErrorString ( ) ) ;
# endif
}
}
// Renders the scene into an active command buffer
// In a real world application we would do some visibility culling in here
2016-06-12 16:55:53 +02:00
void render ( VkCommandBuffer cmdBuffer , bool wireframe )
2016-06-11 17:05:29 +02:00
{
VkDeviceSize offsets [ 1 ] = { 0 } ;
2016-07-23 22:47:58 +02:00
// Bind scene vertex and index buffers
vkCmdBindVertexBuffers ( cmdBuffer , 0 , 1 , & vertexBuffer . buffer , offsets ) ;
vkCmdBindIndexBuffer ( cmdBuffer , indexBuffer . buffer , 0 , VK_INDEX_TYPE_UINT32 ) ;
2016-06-11 17:05:29 +02:00
for ( size_t i = 0 ; i < meshes . size ( ) ; i + + )
{
if ( ( renderSingleScenePart ) & & ( i ! = scenePartIndex ) )
continue ;
2016-06-12 16:55:53 +02:00
2016-06-11 17:05:29 +02:00
// todo : per material pipelines
2016-07-23 22:47:58 +02:00
// vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *mesh.material->pipeline);
2016-06-11 17:05:29 +02:00
2016-06-12 13:29:21 +02:00
// We will be using multiple descriptor sets for rendering
// In GLSL the selection is done via the set and binding keywords
// VS: layout (set = 0, binding = 0) uniform UBO;
// FS: layout (set = 1, binding = 0) uniform sampler2D samplerColorMap;
2016-06-11 17:05:29 +02:00
2016-06-12 13:29:21 +02:00
std : : array < VkDescriptorSet , 2 > descriptorSets ;
// Set 0: Scene descriptor set containing global matrices
descriptorSets [ 0 ] = descriptorSetScene ;
// Set 1: Per-Material descriptor set containing bound images
descriptorSets [ 1 ] = meshes [ i ] . material - > descriptorSet ;
2016-06-11 17:05:29 +02:00
2016-06-12 16:55:53 +02:00
vkCmdBindPipeline ( cmdBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , wireframe ? pipelines . wireframe : * meshes [ i ] . material - > pipeline ) ;
2016-06-12 13:29:21 +02:00
vkCmdBindDescriptorSets ( cmdBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayout , 0 , static_cast < uint32_t > ( descriptorSets . size ( ) ) , descriptorSets . data ( ) , 0 , NULL ) ;
2016-06-11 17:05:29 +02:00
2016-06-12 13:29:21 +02:00
// Pass material properies via push constants
2016-06-11 17:05:29 +02:00
vkCmdPushConstants (
cmdBuffer ,
pipelineLayout ,
VK_SHADER_STAGE_FRAGMENT_BIT ,
0 ,
2016-06-12 16:55:53 +02:00
sizeof ( SceneMaterialProperites ) ,
& meshes [ i ] . material - > properties ) ;
2016-06-11 17:05:29 +02:00
2016-07-23 22:47:58 +02:00
// Render from the global scene vertex buffer using the mesh index offset
vkCmdDrawIndexed ( cmdBuffer , meshes [ i ] . indexCount , 1 , 0 , meshes [ i ] . indexBase , 0 ) ;
2016-06-11 17:05:29 +02:00
}
}
} ;
class VulkanExample : public VulkanExampleBase
{
public :
bool wireframe = false ;
bool attachLight = false ;
Scene * scene = nullptr ;
struct {
VkPipelineVertexInputStateCreateInfo inputState ;
std : : vector < VkVertexInputBindingDescription > bindingDescriptions ;
std : : vector < VkVertexInputAttributeDescription > attributeDescriptions ;
} vertices ;
VulkanExample ( ) : VulkanExampleBase ( ENABLE_VALIDATION )
{
rotationSpeed = 0.5f ;
enableTextOverlay = true ;
2016-06-20 20:17:46 +02:00
camera . type = Camera : : CameraType : : firstperson ;
2016-06-11 17:05:29 +02:00
camera . movementSpeed = 7.5f ;
camera . position = { 15.0f , - 13.5f , 0.0f } ;
camera . setRotation ( glm : : vec3 ( 5.0f , 90.0f , 0.0f ) ) ;
camera . setPerspective ( 60.0f , ( float ) width / ( float ) height , 0.1f , 256.0f ) ;
title = " Vulkan Example - Scene rendering " ;
2016-12-24 12:48:01 +01:00
enabledFeatures . fillModeNonSolid = VK_TRUE ;
2016-06-11 17:05:29 +02:00
}
~ VulkanExample ( )
{
delete ( scene ) ;
}
void reBuildCommandBuffers ( )
{
if ( ! checkCommandBuffers ( ) )
{
destroyCommandBuffers ( ) ;
createCommandBuffers ( ) ;
}
buildCommandBuffers ( ) ;
}
void buildCommandBuffers ( )
{
2017-02-12 11:12:42 +01:00
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
2016-06-11 17:05:29 +02:00
VkClearValue clearValues [ 2 ] ;
clearValues [ 0 ] . color = defaultClearColor ;
clearValues [ 0 ] . color = { { 0.25f , 0.25f , 0.25f , 1.0f } } ;
clearValues [ 1 ] . depthStencil = { 1.0f , 0 } ;
2017-02-12 11:12:42 +01:00
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
2016-06-11 17:05:29 +02:00
renderPassBeginInfo . renderPass = renderPass ;
renderPassBeginInfo . renderArea . offset . x = 0 ;
renderPassBeginInfo . renderArea . offset . y = 0 ;
renderPassBeginInfo . renderArea . extent . width = width ;
renderPassBeginInfo . renderArea . extent . height = height ;
renderPassBeginInfo . clearValueCount = 2 ;
renderPassBeginInfo . pClearValues = clearValues ;
for ( int32_t i = 0 ; i < drawCmdBuffers . size ( ) ; + + i )
{
renderPassBeginInfo . framebuffer = frameBuffers [ i ] ;
VK_CHECK_RESULT ( vkBeginCommandBuffer ( drawCmdBuffers [ i ] , & cmdBufInfo ) ) ;
vkCmdBeginRenderPass ( drawCmdBuffers [ i ] , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
2017-02-12 11:12:42 +01:00
VkViewport viewport = vks : : initializers : : viewport ( ( float ) width , ( float ) height , 0.0f , 1.0f ) ;
2016-06-11 17:05:29 +02:00
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
2017-02-12 11:12:42 +01:00
VkRect2D scissor = vks : : initializers : : rect2D ( width , height , 0 , 0 ) ;
2016-06-11 17:05:29 +02:00
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
2016-06-12 16:55:53 +02:00
scene - > render ( drawCmdBuffers [ i ] , wireframe ) ;
2016-06-11 17:05:29 +02:00
vkCmdEndRenderPass ( drawCmdBuffers [ i ] ) ;
VK_CHECK_RESULT ( vkEndCommandBuffer ( drawCmdBuffers [ i ] ) ) ;
}
}
void setupVertexDescriptions ( )
{
// Binding description
vertices . bindingDescriptions . resize ( 1 ) ;
vertices . bindingDescriptions [ 0 ] =
2017-02-12 11:12:42 +01:00
vks : : initializers : : vertexInputBindingDescription (
2016-06-11 17:05:29 +02:00
VERTEX_BUFFER_BIND_ID ,
sizeof ( Vertex ) ,
VK_VERTEX_INPUT_RATE_VERTEX ) ;
// Attribute descriptions
// Describes memory layout and shader positions
vertices . attributeDescriptions . resize ( 4 ) ;
// Location 0 : Position
vertices . attributeDescriptions [ 0 ] =
2017-02-12 11:12:42 +01:00
vks : : initializers : : vertexInputAttributeDescription (
2016-06-11 17:05:29 +02:00
VERTEX_BUFFER_BIND_ID ,
0 ,
VK_FORMAT_R32G32B32_SFLOAT ,
0 ) ;
// Location 1 : Normal
vertices . attributeDescriptions [ 1 ] =
2017-02-12 11:12:42 +01:00
vks : : initializers : : vertexInputAttributeDescription (
2016-06-11 17:05:29 +02:00
VERTEX_BUFFER_BIND_ID ,
1 ,
VK_FORMAT_R32G32B32_SFLOAT ,
sizeof ( float ) * 3 ) ;
// Location 2 : Texture coordinates
vertices . attributeDescriptions [ 2 ] =
2017-02-12 11:12:42 +01:00
vks : : initializers : : vertexInputAttributeDescription (
2016-06-11 17:05:29 +02:00
VERTEX_BUFFER_BIND_ID ,
2 ,
VK_FORMAT_R32G32_SFLOAT ,
sizeof ( float ) * 6 ) ;
// Location 3 : Color
vertices . attributeDescriptions [ 3 ] =
2017-02-12 11:12:42 +01:00
vks : : initializers : : vertexInputAttributeDescription (
2016-06-11 17:05:29 +02:00
VERTEX_BUFFER_BIND_ID ,
3 ,
VK_FORMAT_R32G32B32_SFLOAT ,
sizeof ( float ) * 8 ) ;
2017-02-12 11:12:42 +01:00
vertices . inputState = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
2016-07-23 22:47:58 +02:00
vertices . inputState . vertexBindingDescriptionCount = static_cast < uint32_t > ( vertices . bindingDescriptions . size ( ) ) ;
2016-06-11 17:05:29 +02:00
vertices . inputState . pVertexBindingDescriptions = vertices . bindingDescriptions . data ( ) ;
2016-07-23 22:47:58 +02:00
vertices . inputState . vertexAttributeDescriptionCount = static_cast < uint32_t > ( vertices . attributeDescriptions . size ( ) ) ;
2016-06-11 17:05:29 +02:00
vertices . inputState . pVertexAttributeDescriptions = vertices . attributeDescriptions . data ( ) ;
}
void preparePipelines ( )
{
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineInputAssemblyStateCreateInfo (
2016-06-11 17:05:29 +02:00
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ,
0 ,
VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineRasterizationStateCreateInfo (
2016-06-11 17:05:29 +02:00
VK_POLYGON_MODE_FILL ,
2016-06-12 17:38:06 +02:00
VK_CULL_MODE_BACK_BIT ,
2016-06-11 17:05:29 +02:00
VK_FRONT_FACE_COUNTER_CLOCKWISE ,
0 ) ;
VkPipelineColorBlendAttachmentState blendAttachmentState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineColorBlendAttachmentState (
2016-06-11 17:05:29 +02:00
0xf ,
VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineColorBlendStateCreateInfo (
2016-06-11 17:05:29 +02:00
1 ,
& blendAttachmentState ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineDepthStencilStateCreateInfo (
2016-06-11 17:05:29 +02:00
VK_TRUE ,
VK_TRUE ,
VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 , 0 ) ;
2016-06-11 17:05:29 +02:00
VkPipelineMultisampleStateCreateInfo multisampleState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineMultisampleStateCreateInfo (
2016-06-11 17:05:29 +02:00
VK_SAMPLE_COUNT_1_BIT ,
0 ) ;
std : : vector < VkDynamicState > dynamicStateEnables = {
VK_DYNAMIC_STATE_VIEWPORT ,
VK_DYNAMIC_STATE_SCISSOR
} ;
VkPipelineDynamicStateCreateInfo dynamicState =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineDynamicStateCreateInfo (
2016-06-11 17:05:29 +02:00
dynamicStateEnables . data ( ) ,
2016-07-23 22:47:58 +02:00
static_cast < uint32_t > ( dynamicStateEnables . size ( ) ) ,
2016-06-11 17:05:29 +02:00
0 ) ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
2016-06-12 16:55:53 +02:00
// Solid rendering pipeline
2016-06-11 17:05:29 +02:00
shaderStages [ 0 ] = loadShader ( getAssetPath ( ) + " shaders/scenerendering/scene.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getAssetPath ( ) + " shaders/scenerendering/scene.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
VkGraphicsPipelineCreateInfo pipelineCreateInfo =
2017-02-12 11:12:42 +01:00
vks : : initializers : : pipelineCreateInfo (
2016-06-11 17:05:29 +02:00
scene - > pipelineLayout ,
renderPass ,
0 ) ;
pipelineCreateInfo . pVertexInputState = & vertices . inputState ;
pipelineCreateInfo . pInputAssemblyState = & inputAssemblyState ;
pipelineCreateInfo . pRasterizationState = & rasterizationState ;
pipelineCreateInfo . pColorBlendState = & colorBlendState ;
pipelineCreateInfo . pMultisampleState = & multisampleState ;
pipelineCreateInfo . pViewportState = & viewportState ;
pipelineCreateInfo . pDepthStencilState = & depthStencilState ;
pipelineCreateInfo . pDynamicState = & dynamicState ;
2016-07-23 22:47:58 +02:00
pipelineCreateInfo . stageCount = static_cast < uint32_t > ( shaderStages . size ( ) ) ;
2016-06-11 17:05:29 +02:00
pipelineCreateInfo . pStages = shaderStages . data ( ) ;
2016-06-12 16:55:53 +02:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & scene - > pipelines . solid ) ) ;
// Alpha blended pipeline
rasterizationState . cullMode = VK_CULL_MODE_NONE ;
blendAttachmentState . blendEnable = VK_TRUE ;
blendAttachmentState . colorBlendOp = VK_BLEND_OP_ADD ;
blendAttachmentState . srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR ;
blendAttachmentState . dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & scene - > pipelines . blending ) ) ;
2016-06-11 17:05:29 +02:00
// Wire frame rendering pipeline
2016-06-12 16:55:53 +02:00
rasterizationState . cullMode = VK_CULL_MODE_BACK_BIT ;
blendAttachmentState . blendEnable = VK_FALSE ;
2016-06-11 17:05:29 +02:00
rasterizationState . polygonMode = VK_POLYGON_MODE_LINE ;
rasterizationState . lineWidth = 1.0f ;
2016-06-12 16:55:53 +02:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & scene - > pipelines . wireframe ) ) ;
2016-06-11 17:05:29 +02:00
}
void updateUniformBuffers ( )
{
if ( attachLight )
{
2016-06-12 16:55:53 +02:00
scene - > uniformData . lightPos = glm : : vec4 ( - camera . position , 1.0f ) ;
2016-06-11 17:05:29 +02:00
}
2016-06-12 16:55:53 +02:00
scene - > uniformData . projection = camera . matrices . perspective ;
scene - > uniformData . view = camera . matrices . view ;
scene - > uniformData . model = glm : : mat4 ( ) ;
2016-06-11 17:05:29 +02:00
2016-06-12 16:55:53 +02:00
memcpy ( scene - > uniformBuffer . mapped , & scene - > uniformData , sizeof ( scene - > uniformData ) ) ;
2016-06-11 17:05:29 +02:00
}
void draw ( )
{
VulkanExampleBase : : prepareFrame ( ) ;
// Command buffer to be sumitted to the queue
submitInfo . commandBufferCount = 1 ;
submitInfo . pCommandBuffers = & drawCmdBuffers [ currentBuffer ] ;
// Submit to queue
VK_CHECK_RESULT ( vkQueueSubmit ( queue , 1 , & submitInfo , VK_NULL_HANDLE ) ) ;
VulkanExampleBase : : submitFrame ( ) ;
}
void loadScene ( )
{
VkCommandBuffer copyCmd = VulkanExampleBase : : createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , false ) ;
2017-02-09 21:55:35 +01:00
scene = new Scene ( vulkanDevice , queue ) ;
2016-06-11 17:05:29 +02:00
# if defined(__ANDROID__)
scene - > assetManager = androidApp - > activity - > assetManager ;
# endif
scene - > assetPath = getAssetPath ( ) + " models/sibenik/ " ;
2016-06-12 13:29:21 +02:00
scene - > load ( getAssetPath ( ) + " models/sibenik/sibenik.dae " , copyCmd ) ;
2016-06-11 17:05:29 +02:00
vkFreeCommandBuffers ( device , cmdPool , 1 , & copyCmd ) ;
2016-06-12 16:55:53 +02:00
updateUniformBuffers ( ) ;
2016-06-11 17:05:29 +02:00
}
void prepare ( )
{
VulkanExampleBase : : prepare ( ) ;
setupVertexDescriptions ( ) ;
loadScene ( ) ;
preparePipelines ( ) ;
buildCommandBuffers ( ) ;
prepared = true ;
}
virtual void render ( )
{
if ( ! prepared )
return ;
draw ( ) ;
}
virtual void viewChanged ( )
{
updateUniformBuffers ( ) ;
}
virtual void keyPressed ( uint32_t keyCode )
{
switch ( keyCode )
{
2016-08-11 13:15:49 +02:00
case KEY_SPACE :
2016-06-11 17:05:29 +02:00
case GAMEPAD_BUTTON_A :
wireframe = ! wireframe ;
reBuildCommandBuffers ( ) ;
break ;
2016-08-11 13:15:49 +02:00
case KEY_P :
2016-06-12 16:55:53 +02:00
scene - > renderSingleScenePart = ! scene - > renderSingleScenePart ;
reBuildCommandBuffers ( ) ;
updateTextOverlay ( ) ;
break ;
2016-08-11 13:15:49 +02:00
case KEY_KPADD :
2016-06-12 16:55:53 +02:00
scene - > scenePartIndex = ( scene - > scenePartIndex < static_cast < uint32_t > ( scene - > meshes . size ( ) ) ) ? scene - > scenePartIndex + 1 : 0 ;
reBuildCommandBuffers ( ) ;
updateTextOverlay ( ) ;
break ;
2016-08-11 13:15:49 +02:00
case KEY_KPSUB :
2016-06-12 16:55:53 +02:00
scene - > scenePartIndex = ( scene - > scenePartIndex > 0 ) ? scene - > scenePartIndex - 1 : static_cast < uint32_t > ( scene - > meshes . size ( ) ) - 1 ;
updateTextOverlay ( ) ;
2016-06-11 17:05:29 +02:00
reBuildCommandBuffers ( ) ;
break ;
2016-08-11 13:15:49 +02:00
case KEY_L :
2016-06-11 17:05:29 +02:00
attachLight = ! attachLight ;
updateUniformBuffers ( ) ;
break ;
}
}
virtual void getOverlayText ( VulkanTextOverlay * textOverlay )
{
# if defined(__ANDROID__)
textOverlay - > addText ( " Press \" Button A \" to toggle wireframe " , 5.0f , 85.0f , VulkanTextOverlay : : alignLeft ) ;
# else
2016-07-23 21:21:32 +02:00
textOverlay - > addText ( " Press \" space \" to toggle wireframe " , 5.0f , 85.0f , VulkanTextOverlay : : alignLeft ) ;
2016-06-11 17:05:29 +02:00
if ( ( scene ) & & ( scene - > renderSingleScenePart ) )
{
2016-06-20 22:06:36 +02:00
textOverlay - > addText ( " Rendering mesh " + std : : to_string ( scene - > scenePartIndex + 1 ) + " of " + std : : to_string ( static_cast < uint32_t > ( scene - > meshes . size ( ) ) ) + " ( \" p \" to toggle) " , 5.0f , 100.0f , VulkanTextOverlay : : alignLeft ) ;
2016-06-11 17:05:29 +02:00
}
else
{
2016-06-20 22:06:36 +02:00
textOverlay - > addText ( " Rendering whole scene ( \" p \" to toggle) " , 5.0f , 100.0f , VulkanTextOverlay : : alignLeft ) ;
2016-06-11 17:05:29 +02:00
}
2016-06-20 22:06:36 +02:00
# endif
2016-06-11 17:05:29 +02:00
}
} ;
2016-12-13 19:25:56 +01:00
VULKAN_EXAMPLE_MAIN ( )