Revised instancing example

This commit is contained in:
saschawillems 2017-01-08 11:13:21 +01:00
parent 93bdd86917
commit 094ed4bccf
13 changed files with 289 additions and 236 deletions

View file

@ -1,21 +1,21 @@
cd jni
call ndk-build
if %ERRORLEVEL% EQU 0 (
echo ndk-build has failed, build cancelled
cd..
mkdir "assets\shaders\base"
xcopy "..\..\data\shaders\base\*.spv" "assets\shaders\base" /Y
mkdir "assets\shaders\instancing"
xcopy "..\..\data\shaders\instancing\*.spv" "assets\shaders\instancing" /Y
mkdir "assets\textures"
xcopy "..\..\data\textures\texturearray_rocks_bc3.ktx" "assets\textures" /Y
xcopy "..\..\data\textures\lavaplanet_bc3.ktx" "assets\textures" /Y
mkdir "assets\models"
xcopy "..\..\data\models\rock01.dae" "assets\models" /Y
xcopy "..\..\data\models\sphere.obj" "assets\models" /Y
mkdir "res\drawable"
xcopy "..\..\android\images\icon.png" "res\drawable" /Y

View file

@ -7,28 +7,20 @@ layout (binding = 1) uniform sampler2DArray samplerArray;
layout (location = 0) in vec3 inNormal;
layout (location = 1) in vec3 inColor;
layout (location = 2) in vec3 inEyePos;
layout (location = 3) in vec3 inLightVec;
layout (location = 4) in vec3 inUV;
layout (location = 2) in vec3 inUV;
layout (location = 3) in vec3 inViewVec;
layout (location = 4) in vec3 inLightVec;
layout (location = 0) out vec4 outFragColor;
void main()
{
vec4 color = texture(samplerArray, inUV) * vec4(inColor, 1.0);
vec3 N = normalize(inNormal);
vec3 L = normalize(vec3(1.0));
vec3 Eye = normalize(-inEyePos);
vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
vec4 IAmbient = vec4(vec3(0.1), 1.0);
vec4 IDiffuse = vec4(1.0) * max(dot(inNormal, inLightVec), 0.0);
float specular = 0.75;
vec4 ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 32.0) * specular;
outFragColor = vec4((IAmbient + IDiffuse) * color + ISpecular);
vec3 L = normalize(inLightVec);
vec3 V = normalize(inViewVec);
vec3 R = reflect(-L, N);
vec3 diffuse = max(dot(N, L), 0.0) * inColor;
vec3 specular = (dot(N,L) > 0.0) ? pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75) * color.r : vec3(0.0);
outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
}

View file

@ -4,7 +4,7 @@
#extension GL_ARB_shading_language_420pack : enable
// Vertex attributes
layout (location = 0) in vec4 inPos;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inUV;
layout (location = 3) in vec3 inColor;
@ -18,60 +18,67 @@ layout (location = 7) in int instanceTexIndex;
layout (binding = 0) uniform UBO
{
mat4 projection;
mat4 view;
float time;
mat4 modelview;
vec4 lightPos;
float locSpeed;
float globSpeed;
} ubo;
layout (location = 0) out vec3 outNormal;
layout (location = 1) out vec3 outColor;
layout (location = 2) out vec3 outEyePos;
layout (location = 3) out vec3 outLightVec;
layout (location = 4) out vec3 outUV;
layout (location = 2) out vec3 outUV;
layout (location = 3) out vec3 outViewVec;
layout (location = 4) out vec3 outLightVec;
void main()
{
outColor = inColor;
outUV = vec3(inUV, instanceTexIndex);
mat4 mx, my, mz;
mat3 mx, my, mz;
// rotate around x
float s = sin(instanceRot.x);
float c = cos(instanceRot.x);
float s = sin(instanceRot.x + ubo.locSpeed);
float c = cos(instanceRot.x + ubo.locSpeed);
mx[0] = vec4(c, s, 0.0, 0.0);
mx[1] = vec4(-s, c, 0.0, 0.0);
mx[2] = vec4(0.0, 0.0, 1.0, 0.0);
mx[3] = vec4(0.0, 0.0, 0.0, 1.0);
mx[0] = vec3(c, s, 0.0);
mx[1] = vec3(-s, c, 0.0);
mx[2] = vec3(0.0, 0.0, 1.0);
// rotate around y
s = sin(instanceRot.y + ubo.time);
c = cos(instanceRot.y + ubo.time);
s = sin(instanceRot.y + ubo.locSpeed);
c = cos(instanceRot.y + ubo.locSpeed);
my[0] = vec4(c, 0.0, s, 0.0);
my[1] = vec4(0.0, 1.0, 0.0, 0.0);
my[2] = vec4(-s, 0.0, c, 0.0);
my[3] = vec4(0.0, 0.0, 0.0, 1.0);
my[0] = vec3(c, 0.0, s);
my[1] = vec3(0.0, 1.0, 0.0);
my[2] = vec3(-s, 0.0, c);
// rot around z
s = sin(instanceRot.z);
c = cos(instanceRot.z);
s = sin(instanceRot.z + ubo.locSpeed);
c = cos(instanceRot.z + ubo.locSpeed);
mz[0] = vec4(1.0, 0.0, 0.0, 0.0);
mz[1] = vec4(0.0, c, s, 0.0);
mz[2] = vec4(0.0, -s, c, 0.0);
mz[3] = vec4(0.0, 0.0, 0.0, 1.0);
mz[0] = vec3(1.0, 0.0, 0.0);
mz[1] = vec3(0.0, c, s);
mz[2] = vec3(0.0, -s, c);
mat4 rotMat = mz * my * mx;
outNormal = inNormal * mat3(rotMat);
vec4 pos = vec4((inPos.xyz * instanceScale) + instancePos, 1.0) * rotMat;
mat3 rotMat = mz * my * mx;
outEyePos = vec3(ubo.view * pos);
mat4 gRotMat;
s = sin(instanceRot.y + ubo.globSpeed);
c = cos(instanceRot.y + ubo.globSpeed);
gRotMat[0] = vec4(c, 0.0, s, 0.0);
gRotMat[1] = vec4(0.0, 1.0, 0.0, 0.0);
gRotMat[2] = vec4(-s, 0.0, c, 0.0);
gRotMat[3] = vec4(0.0, 0.0, 0.0, 1.0);
gl_Position = ubo.projection * ubo.view * pos;
vec4 lightPos = vec4(0.0, 0.0, 0.0, 1.0) * ubo.view;
outLightVec = normalize(lightPos.xyz - outEyePos);
vec4 locPos = vec4(inPos.xyz * rotMat, 1.0);
vec4 pos = vec4((locPos.xyz * instanceScale) + instancePos, 1.0);
gl_Position = ubo.projection * ubo.modelview * gRotMat * pos;
outNormal = mat3(ubo.modelview * gRotMat) * inverse(rotMat) * inNormal;
pos = ubo.modelview * vec4(inPos.xyz + instancePos, 1.0);
vec3 lPos = mat3(ubo.modelview) * ubo.lightPos.xyz;
outLightVec = lPos - pos.xyz;
outViewVec = -pos.xyz;
}

View file

@ -0,0 +1,26 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (binding = 1) uniform sampler2D samplerColorMap;
layout (location = 0) in vec3 inNormal;
layout (location = 1) in vec3 inColor;
layout (location = 2) in vec2 inUV;
layout (location = 3) in vec3 inViewVec;
layout (location = 4) in vec3 inLightVec;
layout (location = 0) out vec4 outFragColor;
void main()
{
vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0) * 1.5;
vec3 N = normalize(inNormal);
vec3 L = normalize(inLightVec);
vec3 V = normalize(inViewVec);
vec3 R = reflect(-L, N);
vec3 diffuse = max(dot(N, L), 0.0) * inColor;
vec3 specular = pow(max(dot(R, V), 0.0), 4.0) * vec3(0.5) * color.r;
outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
}

Binary file not shown.

View file

@ -0,0 +1,35 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inUV;
layout (location = 3) in vec3 inColor;
layout (binding = 0) uniform UBO
{
mat4 projection;
mat4 modelview;
vec4 lightPos;
} ubo;
layout (location = 0) out vec3 outNormal;
layout (location = 1) out vec3 outColor;
layout (location = 2) out vec2 outUV;
layout (location = 3) out vec3 outViewVec;
layout (location = 4) out vec3 outLightVec;
void main()
{
outColor = inColor;
outUV = inUV * vec2(10.0, 6.0);
gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
vec4 pos = ubo.modelview * vec4(inPos, 1.0);
outNormal = mat3(ubo.modelview) * inNormal;
vec3 lPos = mat3(ubo.modelview) * ubo.lightPos.xyz;
outLightVec = lPos - pos.xyz;
outViewVec = -pos.xyz;
}

Binary file not shown.

Binary file not shown.

View file

@ -26,7 +26,7 @@
#define VERTEX_BUFFER_BIND_ID 0
#define INSTANCE_BUFFER_BIND_ID 1
#define ENABLE_VALIDATION false
#define INSTANCE_COUNT 2048
#define INSTANCE_COUNT 8192
// Vertex layout for this example
std::vector<vkMeshLoader::VertexLayout> vertexLayout =
@ -41,17 +41,13 @@ class VulkanExample : public VulkanExampleBase
{
public:
struct {
VkPipelineVertexInputStateCreateInfo inputState;
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
} vertices;
struct {
vkMeshLoader::MeshBuffer example;
vkMeshLoader::MeshBuffer rock;
vkMeshLoader::MeshBuffer planet;
} meshes;
struct {
vkTools::VulkanTexture colorMap;
vkTools::VulkanTexture rocks;
vkTools::VulkanTexture planet;
} textures;
// Per-instance data block
@ -61,48 +57,62 @@ public:
float scale;
uint32_t texIndex;
};
// Contains the instanced data
struct {
struct InstanceBuffer {
VkBuffer buffer = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
size_t size = 0;
VkDescriptorBufferInfo descriptor;
} instanceBuffer;
struct {
struct UBOVS {
glm::mat4 projection;
glm::mat4 view;
float time = 0.0f;
glm::vec4 lightPos = glm::vec4(0.0f, -5.0f, 0.0f, 1.0f);
float locSpeed = 0.0f;
float globSpeed = 0.0f;
} uboVS;
struct {
vk::Buffer scene;
} uniformBuffers;
VkPipeline pipeline;
VkPipelineLayout pipelineLayout;
VkDescriptorSet descriptorSet;
struct {
VkPipeline instancedRocks;
VkPipeline planet;
} pipelines;
VkDescriptorSetLayout descriptorSetLayout;
struct {
VkDescriptorSet instancedRocks;
VkDescriptorSet planet;
} descriptorSets;
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
{
zoom = -12.0f;
rotationSpeed = 0.25f;
enableTextOverlay = true;
title = "Vulkan Example - Instanced mesh rendering";
enableTextOverlay = true;
srand(time(NULL));
zoom = -18.5f;
rotation = { -17.2f, -4.7f, 0.0f };
cameraPos = { 5.5f, -1.85f, 0.0f };
rotationSpeed = 0.25f;
}
~VulkanExample()
{
vkDestroyPipeline(device, pipeline, nullptr);
vkDestroyPipeline(device, pipelines.instancedRocks, nullptr);
vkDestroyPipeline(device, pipelines.planet, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
vkDestroyBuffer(device, instanceBuffer.buffer, nullptr);
vkFreeMemory(device, instanceBuffer.memory, nullptr);
vkMeshLoader::freeMeshBufferResources(device, &meshes.example);
textureLoader->destroyTexture(textures.colorMap);
vkMeshLoader::freeMeshBufferResources(device, &meshes.rock);
vkMeshLoader::freeMeshBufferResources(device, &meshes.planet);
textures.rocks.destroy();
textures.planet.destroy();
uniformBuffers.scene.destroy();
}
@ -136,19 +146,27 @@ public:
VkRect2D scissor = vkTools::initializers::rect2D(width, height, 0, 0);
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
VkDeviceSize offsets[1] = { 0 };
// Planet
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.planet, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.planet);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.planet.vertices.buf, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.planet.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.planet.indexCount, 1, 0, 0, 0);
// Instanced rocks
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.instancedRocks, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.instancedRocks);
// Binding point 0 : Mesh vertex buffer
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.example.vertices.buf, offsets);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.rock.vertices.buf, offsets);
// Binding point 1 : Instance data buffer
vkCmdBindVertexBuffers(drawCmdBuffers[i], INSTANCE_BUFFER_BIND_ID, 1, &instanceBuffer.buffer, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.example.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.rock.indices.buf, 0, VK_INDEX_TYPE_UINT32);
// Render instances
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.example.indexCount, INSTANCE_COUNT, 0, 0, 0);
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.rock.indexCount, INSTANCE_COUNT, 0, 0, 0);
vkCmdEndRenderPass(drawCmdBuffers[i]);
@ -156,119 +174,12 @@ public:
}
}
void loadMeshes()
void loadAssets()
{
loadMesh(getAssetPath() + "models/rock01.dae", &meshes.example, vertexLayout, 0.1f);
}
void loadTextures()
{
textureLoader->loadTextureArray(
getAssetPath() + "textures/texturearray_rocks_bc3.ktx",
VK_FORMAT_BC3_UNORM_BLOCK,
&textures.colorMap);
}
void setupVertexDescriptions()
{
// Binding description
vertices.bindingDescriptions.resize(2);
// Mesh vertex buffer (description) at binding point 0
vertices.bindingDescriptions[0] =
vkTools::initializers::vertexInputBindingDescription(
VERTEX_BUFFER_BIND_ID,
vkMeshLoader::vertexSize(vertexLayout),
// Input rate for the data passed to shader
// Step for each vertex rendered
VK_VERTEX_INPUT_RATE_VERTEX);
vertices.bindingDescriptions[1] =
vkTools::initializers::vertexInputBindingDescription(
INSTANCE_BUFFER_BIND_ID,
sizeof(InstanceData),
// Input rate for the data passed to shader
// Step for each instance rendered
VK_VERTEX_INPUT_RATE_INSTANCE);
// Attribute descriptions
// Describes memory layout and shader positions
vertices.attributeDescriptions.clear();
// Per-Vertex attributes
// Location 0 : Position
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
VERTEX_BUFFER_BIND_ID,
0,
VK_FORMAT_R32G32B32_SFLOAT,
0)
);
// Location 1 : Normal
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
VERTEX_BUFFER_BIND_ID,
1,
VK_FORMAT_R32G32B32_SFLOAT,
sizeof(float) * 3)
);
// Location 2 : Texture coordinates
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
VERTEX_BUFFER_BIND_ID,
2,
VK_FORMAT_R32G32_SFLOAT,
sizeof(float) * 6)
);
// Location 3 : Color
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
VERTEX_BUFFER_BIND_ID,
3,
VK_FORMAT_R32G32B32_SFLOAT,
sizeof(float) * 8)
);
// Instanced attributes
// Location 4 : Position
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
INSTANCE_BUFFER_BIND_ID,
5,
VK_FORMAT_R32G32B32_SFLOAT,
sizeof(float) * 3)
);
// Location 5 : Rotation
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
INSTANCE_BUFFER_BIND_ID,
4,
VK_FORMAT_R32G32B32_SFLOAT,
0)
);
// Location 6 : Scale
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
INSTANCE_BUFFER_BIND_ID,
6,
VK_FORMAT_R32_SFLOAT,
sizeof(float) * 6)
);
// Location 7 : Texture array layer index
vertices.attributeDescriptions.push_back(
vkTools::initializers::vertexInputAttributeDescription(
INSTANCE_BUFFER_BIND_ID,
7,
VK_FORMAT_R32_SINT,
sizeof(float) * 7)
);
vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size();
vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data();
vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size();
vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data();
loadMesh(getAssetPath() + "models/rock01.dae", &meshes.rock, vertexLayout, 0.1f);
loadMesh(getAssetPath() + "models/sphere.obj", &meshes.planet, vertexLayout, 0.2f);
textureLoader->loadTextureArray(getAssetPath() + "textures/texturearray_rocks_bc3.ktx", VK_FORMAT_BC3_UNORM_BLOCK, &textures.rocks);
textureLoader->loadTexture(getAssetPath() + "textures/lavaplanet_bc3.ktx", VK_FORMAT_BC3_UNORM_BLOCK, &textures.planet);
}
void setupDescriptorPool()
@ -276,8 +187,8 @@ public:
// Example uses one ubo
std::vector<VkDescriptorPoolSize> poolSizes =
{
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1),
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2),
vkTools::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2),
};
VkDescriptorPoolCreateInfo descriptorPoolInfo =
@ -322,31 +233,27 @@ public:
void setupDescriptorSet()
{
VkDescriptorSetAllocateInfo allocInfo =
vkTools::initializers::descriptorSetAllocateInfo(
descriptorPool,
&descriptorSetLayout,
1);
VkDescriptorSetAllocateInfo descripotrSetAllocInfo;
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
descripotrSetAllocInfo = vkTools::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);;
std::vector<VkWriteDescriptorSet> writeDescriptorSets =
{
// Binding 0 : Vertex shader uniform buffer
vkTools::initializers::writeDescriptorSet(
descriptorSet,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0,
&uniformBuffers.scene.descriptor),
// Binding 1 : Color map
vkTools::initializers::writeDescriptorSet(
descriptorSet,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1,
&textures.colorMap.descriptor)
// Instanced rocks
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descripotrSetAllocInfo, &descriptorSets.instancedRocks));
writeDescriptorSets = {
vkTools::initializers::writeDescriptorSet(descriptorSets.instancedRocks, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), // Binding 0 : Vertex shader uniform buffer
vkTools::initializers::writeDescriptorSet(descriptorSets.instancedRocks, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.rocks.descriptor) // Binding 1 : Color map
};
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
// Planet
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descripotrSetAllocInfo, &descriptorSets.planet));
writeDescriptorSets = {
vkTools::initializers::writeDescriptorSet(descriptorSets.planet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), // Binding 0 : Vertex shader uniform buffer
vkTools::initializers::writeDescriptorSet(descriptorSets.planet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textures.planet.descriptor) // Binding 1 : Color map
};
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);
}
void preparePipelines()
@ -398,20 +305,15 @@ public:
dynamicStateEnables.size(),
0);
// Instacing pipeline
// Load shaders
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages;
shaderStages[0] = loadShader(getAssetPath() + "shaders/instancing/instancing.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/instancing/instancing.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
VkGraphicsPipelineCreateInfo pipelineCreateInfo =
vkTools::initializers::pipelineCreateInfo(
pipelineLayout,
renderPass,
0);
pipelineCreateInfo.pVertexInputState = &vertices.inputState;
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
pipelineCreateInfo.pRasterizationState = &rasterizationState;
pipelineCreateInfo.pColorBlendState = &colorBlendState;
@ -422,7 +324,60 @@ public:
pipelineCreateInfo.stageCount = shaderStages.size();
pipelineCreateInfo.pStages = shaderStages.data();
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
// This example uses two different input states, one for the instanced part and one for non-instanced rendering
VkPipelineVertexInputStateCreateInfo inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
std::vector<VkVertexInputBindingDescription> bindingDescriptions;
std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
// Vertex input bindings
// The instancing pipeline uses a vertex input state with two bindings
bindingDescriptions = {
// Binding point 0: Mesh vertex layout description at per-vertex rate
vkTools::initializers::vertexInputBindingDescription(VERTEX_BUFFER_BIND_ID, vkMeshLoader::vertexSize(vertexLayout), VK_VERTEX_INPUT_RATE_VERTEX),
// Binding point 1: Instanced data at per-instance rate
vkTools::initializers::vertexInputBindingDescription(INSTANCE_BUFFER_BIND_ID, sizeof(InstanceData), VK_VERTEX_INPUT_RATE_INSTANCE)
};
// Vertex attribute bindings
// Note that the shader declaration for per-vertex and per-instance attributes is the same, the different input rates are only stored in the bindings:
// instanced.vert:
// layout (location = 0) in vec3 inPos; Per-Vertex
// ...
// layout (location = 4) in vec3 instancePos; Per-Instance
attributeDescriptions = {
// Per-vertex attributees
// These are advanced for each vertex fetched by the vertex shader
vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 0: Position
vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 1: Normal
vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 2, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 6), // Location 2: Texture coordinates
vkTools::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 3, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 8), // Location 3: Color
// Per-Instance attributes
// These are fetched for each instance rendered
vkTools::initializers::vertexInputAttributeDescription(INSTANCE_BUFFER_BIND_ID, 5, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 4: Position
vkTools::initializers::vertexInputAttributeDescription(INSTANCE_BUFFER_BIND_ID, 4, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 5: Rotation
vkTools::initializers::vertexInputAttributeDescription(INSTANCE_BUFFER_BIND_ID, 6, VK_FORMAT_R32_SFLOAT,sizeof(float) * 6), // Location 6: Scale
vkTools::initializers::vertexInputAttributeDescription(INSTANCE_BUFFER_BIND_ID, 7, VK_FORMAT_R32_SINT, sizeof(float) * 7), // Location 7: Texture array layer index
};
inputState.pVertexBindingDescriptions = bindingDescriptions.data();
inputState.pVertexAttributeDescriptions = attributeDescriptions.data();
pipelineCreateInfo.pVertexInputState = &inputState;
// Instancing pipeline
shaderStages[0] = loadShader(getAssetPath() + "shaders/instancing/instancing.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/instancing/instancing.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// Use all input bindings and attribute descriptions
inputState.vertexBindingDescriptionCount = static_cast<uint32_t>(bindingDescriptions.size());
inputState.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.instancedRocks));
// Planet rendering pipeline
shaderStages[0] = loadShader(getAssetPath() + "shaders/instancing/planet.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/instancing/planet.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// Only use the non-instanced input bindings and attribute descriptions
inputState.vertexBindingDescriptionCount = 1;
inputState.vertexAttributeDescriptionCount = 4;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.planet));
}
float rnd(float range)
@ -436,17 +391,33 @@ public:
instanceData.resize(INSTANCE_COUNT);
std::mt19937 rndGenerator(time(NULL));
std::uniform_real_distribution<double> uniformDist(0.0, 1.0);
std::uniform_real_distribution<float> uniformDist(0.0, 1.0);
for (auto i = 0; i < INSTANCE_COUNT; i++)
{
// Distribute rocks randomly on two different rings
for (auto i = 0; i < INSTANCE_COUNT / 2; i++)
{
glm::vec2 ring0 { 7.0f, 11.0f };
glm::vec2 ring1 { 14.0f, 18.0f };
float rho, theta;
// Inner ring
rho = sqrt((pow(ring0[1], 2.0f) - pow(ring0[0], 2.0f)) * uniformDist(rndGenerator) + pow(ring0[0], 2.0f));
theta = 2.0 * M_PI * uniformDist(rndGenerator);
instanceData[i].pos = glm::vec3(rho*cos(theta), uniformDist(rndGenerator) * 0.5f - 0.25f, rho*sin(theta));
instanceData[i].rot = glm::vec3(M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator));
float theta = 2 * M_PI * uniformDist(rndGenerator);
float phi = acos(1 - 2 * uniformDist(rndGenerator));
glm::vec3 pos;
instanceData[i].pos = glm::vec3(sin(phi) * cos(theta), sin(theta) * uniformDist(rndGenerator) / 1500.0f, cos(phi)) * 7.5f;
instanceData[i].scale = 1.0f + uniformDist(rndGenerator) * 2.0f;
instanceData[i].texIndex = rnd(textures.colorMap.layerCount);
instanceData[i].scale = 1.5f + uniformDist(rndGenerator) - uniformDist(rndGenerator);
instanceData[i].texIndex = rnd(textures.rocks.layerCount);
instanceData[i].scale *= 0.75f;
// Outer ring
rho = sqrt((pow(ring1[1], 2.0f) - pow(ring1[0], 2.0f)) * uniformDist(rndGenerator) + pow(ring1[0], 2.0f));
theta = 2.0 * M_PI * uniformDist(rndGenerator);
instanceData[i + INSTANCE_COUNT / 2].pos = glm::vec3(rho*cos(theta), uniformDist(rndGenerator) * 0.5f - 0.25f, rho*sin(theta));
instanceData[i + INSTANCE_COUNT / 2].rot = glm::vec3(M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator), M_PI * uniformDist(rndGenerator));
instanceData[i + INSTANCE_COUNT / 2].scale = 1.5f + uniformDist(rndGenerator) - uniformDist(rndGenerator);
instanceData[i + INSTANCE_COUNT / 2].texIndex = rnd(textures.rocks.layerCount);
instanceData[i + INSTANCE_COUNT / 2].scale *= 0.75f;
}
instanceBuffer.size = instanceData.size() * sizeof(InstanceData);
@ -516,7 +487,7 @@ public:
{
if (viewChanged)
{
uboVS.projection = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.001f, 256.0f);
uboVS.projection = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.1f, 256.0f);
uboVS.view = glm::translate(glm::mat4(), cameraPos + glm::vec3(0.0f, 0.0f, zoom));
uboVS.view = glm::rotate(uboVS.view, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
uboVS.view = glm::rotate(uboVS.view, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
@ -525,7 +496,8 @@ public:
if (!paused)
{
uboVS.time += frameTimer * 0.05f;
uboVS.locSpeed += frameTimer * 0.35f;
uboVS.globSpeed += frameTimer * 0.01f;
}
memcpy(uniformBuffers.scene.mapped, &uboVS, sizeof(uboVS));
@ -548,10 +520,8 @@ public:
void prepare()
{
VulkanExampleBase::prepare();
loadTextures();
loadMeshes();
loadAssets();
prepareInstanceData();
setupVertexDescriptions();
prepareUniformBuffers();
setupDescriptorSetLayout();
preparePipelines();

View file

@ -21,6 +21,12 @@
<ClInclude Include="..\base\vulkanexamplebase.h" />
<ClInclude Include="..\base\vulkantools.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\data\shaders\instancing\instancing.frag" />
<None Include="..\data\shaders\instancing\instancing.vert" />
<None Include="..\data\shaders\instancing\planet.frag" />
<None Include="..\data\shaders\instancing\planet.vert" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{CF2E27EC-5A81-412A-A3E2-E6EB5C8B66E3}</ProjectGuid>
<RootNamespace>instancing</RootNamespace>

View file

@ -13,6 +13,9 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{f3943aa8-abcf-4afa-b9d0-51c790106e29}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\base\vulkandebug.cpp">
@ -39,4 +42,18 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\data\shaders\instancing\instancing.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\instancing\instancing.vert">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\instancing\planet.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\data\shaders\instancing\planet.vert">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
</Project>