Revised instancing example
This commit is contained in:
parent
93bdd86917
commit
094ed4bccf
13 changed files with 289 additions and 236 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
Binary file not shown.
|
|
@ -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;
|
||||
mat3 rotMat = mz * my * mx;
|
||||
|
||||
outNormal = inNormal * mat3(rotMat);
|
||||
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);
|
||||
|
||||
vec4 pos = vec4((inPos.xyz * instanceScale) + instancePos, 1.0) * rotMat;
|
||||
vec4 locPos = vec4(inPos.xyz * rotMat, 1.0);
|
||||
vec4 pos = vec4((locPos.xyz * instanceScale) + instancePos, 1.0);
|
||||
|
||||
outEyePos = vec3(ubo.view * pos);
|
||||
gl_Position = ubo.projection * ubo.modelview * gRotMat * pos;
|
||||
outNormal = mat3(ubo.modelview * gRotMat) * inverse(rotMat) * inNormal;
|
||||
|
||||
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);
|
||||
pos = ubo.modelview * vec4(inPos.xyz + instancePos, 1.0);
|
||||
vec3 lPos = mat3(ubo.modelview) * ubo.lightPos.xyz;
|
||||
outLightVec = lPos - pos.xyz;
|
||||
outViewVec = -pos.xyz;
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
26
data/shaders/instancing/planet.frag
Normal file
26
data/shaders/instancing/planet.frag
Normal 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);
|
||||
}
|
||||
BIN
data/shaders/instancing/planet.frag.spv
Normal file
BIN
data/shaders/instancing/planet.frag.spv
Normal file
Binary file not shown.
35
data/shaders/instancing/planet.vert
Normal file
35
data/shaders/instancing/planet.vert
Normal 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;
|
||||
}
|
||||
BIN
data/shaders/instancing/planet.vert.spv
Normal file
BIN
data/shaders/instancing/planet.vert.spv
Normal file
Binary file not shown.
BIN
data/textures/lavaplanet_bc3.ktx
Normal file
BIN
data/textures/lavaplanet_bc3.ktx
Normal file
Binary file not shown.
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
Loading…
Add table
Add a link
Reference in a new issue