Added text overlay to cubemap sample, multiple objects, optimizations

This commit is contained in:
saschawillems 2016-06-04 11:03:17 +02:00
parent 6344a0e016
commit c68025a332
10 changed files with 212 additions and 60 deletions

View file

@ -7,7 +7,6 @@ if %ERRORLEVEL% EQU 0 (
mkdir "assets\shaders\base" mkdir "assets\shaders\base"
xcopy "..\..\data\shaders\base\*.spv" "assets\shaders\base" /Y xcopy "..\..\data\shaders\base\*.spv" "assets\shaders\base" /Y
mkdir "assets\shaders\cubemap" mkdir "assets\shaders\cubemap"
xcopy "..\..\data\shaders\cubemap\*.spv" "assets\shaders\cubemap" /Y xcopy "..\..\data\shaders\cubemap\*.spv" "assets\shaders\cubemap" /Y
@ -16,6 +15,8 @@ if %ERRORLEVEL% EQU 0 (
mkdir "assets\models" mkdir "assets\models"
xcopy "..\..\data\models\sphere.obj" "assets\models" /Y xcopy "..\..\data\models\sphere.obj" "assets\models" /Y
xcopy "..\..\data\models\teapot.dae" "assets\models" /Y
xcopy "..\..\data\models\torusknot.obj" "assets\models" /Y
xcopy "..\..\data\models\cube.obj" "assets\models" /Y xcopy "..\..\data\models\cube.obj" "assets\models" /Y
mkdir "res\drawable" mkdir "res\drawable"

61
data/models/teapot.dae Normal file

File diff suppressed because one or more lines are too long

View file

@ -5,18 +5,30 @@
layout (binding = 1) uniform samplerCube samplerColor; layout (binding = 1) uniform samplerCube samplerColor;
layout (location = 0) in vec3 inEyePos; layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inEyeNormal; layout (location = 1) in vec3 inNormal;
layout (location = 2) in mat4 inView; layout (location = 2) in vec3 inViewVec;
layout (location = 3) in vec3 inLightVec;
layout (location = 4) in mat4 inInvModelView;
layout (location = 0) out vec4 outFragColor; layout (location = 0) out vec4 outFragColor;
void main() void main()
{ {
vec3 I = normalize (inEyePos); vec3 cI = normalize (inPos);
vec3 R = reflect (I, normalize(inEyeNormal)); vec3 cR = reflect (cI, normalize(inNormal));
cR = vec3(inInvModelView * vec4(cR, 0.0));
vec4 color = texture(samplerColor, cR);
vec3 N = normalize(inNormal);
vec3 L = normalize(inLightVec);
vec3 V = normalize(inViewVec);
vec3 R = reflect(-L, N);
vec3 ambient = vec3(0.5) * color.rgb;
vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.5);
outFragColor = vec4(ambient + diffuse * color.rgb + specular, 1.0);
R = vec3(inverse (inView) * vec4(R, 0.0));
outFragColor = texture(samplerColor, R);
} }

View file

@ -12,16 +12,27 @@ layout (binding = 0) uniform UBO
mat4 model; mat4 model;
} ubo; } ubo;
layout (location = 0) out vec3 outEyePos; layout (location = 0) out vec3 outPos;
layout (location = 1) out vec3 outEyeNormal; layout (location = 1) out vec3 outNormal;
layout (location = 2) out mat4 outView; layout (location = 2) out vec3 outViewVec;
layout (location = 3) out vec3 outLightVec;
layout (location = 4) out mat4 outInvModelView;
out gl_PerVertex
{
vec4 gl_Position;
};
void main() void main()
{ {
gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
outEyePos = vec3(ubo.model * vec4(inPos, 1.0)); outPos = vec3(ubo.model * vec4(inPos, 1.0));
outEyeNormal = vec3(ubo.model * vec4(inNormal, 0.0)); outNormal = mat3(ubo.model) * inNormal;
outView = ubo.model; outInvModelView = inverse(ubo.model);
vec3 lightPos = vec3(0.0f, -5.0f, 5.0f);
outLightVec = lightPos.xyz - outPos.xyz;
outViewVec = -outPos.xyz;
} }

Binary file not shown.

View file

@ -13,6 +13,11 @@ layout (binding = 0) uniform UBO
layout (location = 0) out vec3 outUVW; layout (location = 0) out vec3 outUVW;
out gl_PerVertex
{
vec4 gl_Position;
};
void main() void main()
{ {
outUVW = inPos; outUVW = inPos;

Binary file not shown.

View file

@ -36,6 +36,8 @@ std::vector<vkMeshLoader::VertexLayout> vertexLayout =
class VulkanExample : public VulkanExampleBase class VulkanExample : public VulkanExampleBase
{ {
public: public:
bool displaySkybox = true;
vkTools::VulkanTexture cubeMap; vkTools::VulkanTexture cubeMap;
struct { struct {
@ -45,7 +47,9 @@ public:
} vertices; } vertices;
struct { struct {
vkMeshLoader::MeshBuffer skybox, object; vkMeshLoader::MeshBuffer skybox;
std::vector<vkMeshLoader::MeshBuffer> objects;
uint32_t objectIndex = 0;
} meshes; } meshes;
struct { struct {
@ -76,6 +80,7 @@ public:
zoom = -4.0f; zoom = -4.0f;
rotationSpeed = 0.25f; rotationSpeed = 0.25f;
rotation = { -2.25f, -35.0f, 0.0f }; rotation = { -2.25f, -35.0f, 0.0f };
enableTextOverlay = true;
title = "Vulkan Example - Cube map"; title = "Vulkan Example - Cube map";
} }
@ -96,7 +101,10 @@ public:
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
vkMeshLoader::freeMeshBufferResources(device, &meshes.object); for (size_t i = 0; i < meshes.objects.size(); i++)
{
vkMeshLoader::freeMeshBufferResources(device, &meshes.objects[i]);
}
vkMeshLoader::freeMeshBufferResources(device, &meshes.skybox); vkMeshLoader::freeMeshBufferResources(device, &meshes.skybox);
vkTools::destroyUniformData(device, &uniformData.objectVS); vkTools::destroyUniformData(device, &uniformData.objectVS);
@ -124,8 +132,9 @@ public:
assert(!texCube.empty()); assert(!texCube.empty());
cubeMap.width = texCube[0].dimensions().x; cubeMap.width = texCube.dimensions().x;
cubeMap.height = texCube[0].dimensions().y; cubeMap.height = texCube.dimensions().y;
cubeMap.mipLevels = texCube.levels();
VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo(); VkMemoryAllocateInfo memAllocInfo = vkTools::initializers::memoryAllocateInfo();
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
@ -144,11 +153,9 @@ public:
// Get memory requirements for the staging buffer (alignment, memory type bits) // Get memory requirements for the staging buffer (alignment, memory type bits)
vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs); vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);
memAllocInfo.allocationSize = memReqs.size; memAllocInfo.allocationSize = memReqs.size;
// Get memory type index for a host visible buffer // Get memory type index for a host visible buffer
memAllocInfo.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); memAllocInfo.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory));
VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0)); VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));
@ -269,6 +276,16 @@ public:
vkDestroyBuffer(device, stagingBuffer, nullptr); vkDestroyBuffer(device, stagingBuffer, nullptr);
} }
void reBuildCommandBuffers()
{
if (!checkCommandBuffers())
{
destroyCommandBuffers();
createCommandBuffers();
}
buildCommandBuffers();
}
void buildCommandBuffers() void buildCommandBuffers()
{ {
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
@ -304,18 +321,21 @@ public:
VkDeviceSize offsets[1] = { 0 }; VkDeviceSize offsets[1] = { 0 };
// Skybox // Skybox
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.skybox, 0, NULL); if (displaySkybox)
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.skybox.vertices.buf, offsets); {
vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.skybox.indices.buf, 0, VK_INDEX_TYPE_UINT32); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.skybox, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.skybox.vertices.buf, offsets);
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.skybox.indexCount, 1, 0, 0, 0); vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.skybox.indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.skybox);
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.skybox.indexCount, 1, 0, 0, 0);
}
// 3D object // 3D object
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.object, 0, NULL); vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.object, 0, NULL);
vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.object.vertices.buf, offsets); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &meshes.objects[meshes.objectIndex].vertices.buf, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.object.indices.buf, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(drawCmdBuffers[i], meshes.objects[meshes.objectIndex].indices.buf, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.reflect); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.reflect);
vkCmdDrawIndexed(drawCmdBuffers[i], meshes.object.indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(drawCmdBuffers[i], meshes.objects[meshes.objectIndex].indexCount, 1, 0, 0, 0);
vkCmdEndRenderPass(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]);
@ -323,31 +343,15 @@ public:
} }
} }
void draw()
{
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer));
submitPostPresentBarrier(swapChain.buffers[currentBuffer].image);
// 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));
submitPrePresentBarrier(swapChain.buffers[currentBuffer].image);
VK_CHECK_RESULT(swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete));
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
}
void loadMeshes() void loadMeshes()
{ {
loadMesh(getAssetPath() + "models/sphere.obj", &meshes.object, vertexLayout, 0.05f); // Skybox
loadMesh(getAssetPath() + "models/cube.obj", &meshes.skybox, vertexLayout, 0.05f); loadMesh(getAssetPath() + "models/cube.obj", &meshes.skybox, vertexLayout, 0.05f);
// Objects
meshes.objects.resize(3);
loadMesh(getAssetPath() + "models/sphere.obj", &meshes.objects[0], vertexLayout, 0.05f);
loadMesh(getAssetPath() + "models/teapot.dae", &meshes.objects[1], vertexLayout, 0.05f);
loadMesh(getAssetPath() + "models/torusknot.obj", &meshes.objects[2], vertexLayout, 0.05f);
} }
void setupVertexDescriptions() void setupVertexDescriptions()
@ -507,7 +511,7 @@ public:
VkPipelineRasterizationStateCreateInfo rasterizationState = VkPipelineRasterizationStateCreateInfo rasterizationState =
vkTools::initializers::pipelineRasterizationStateCreateInfo( vkTools::initializers::pipelineRasterizationStateCreateInfo(
VK_POLYGON_MODE_FILL, VK_POLYGON_MODE_FILL,
VK_CULL_MODE_NONE, VK_CULL_MODE_BACK_BIT,
VK_FRONT_FACE_COUNTER_CLOCKWISE, VK_FRONT_FACE_COUNTER_CLOCKWISE,
0); 0);
@ -523,7 +527,7 @@ public:
VkPipelineDepthStencilStateCreateInfo depthStencilState = VkPipelineDepthStencilStateCreateInfo depthStencilState =
vkTools::initializers::pipelineDepthStencilStateCreateInfo( vkTools::initializers::pipelineDepthStencilStateCreateInfo(
VK_TRUE, VK_FALSE,
VK_FALSE, VK_FALSE,
VK_COMPARE_OP_LESS_OR_EQUAL); VK_COMPARE_OP_LESS_OR_EQUAL);
@ -573,7 +577,11 @@ public:
// Cube map reflect pipeline // Cube map reflect pipeline
shaderStages[0] = loadShader(getAssetPath() + "shaders/cubemap/reflect.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[0] = loadShader(getAssetPath() + "shaders/cubemap/reflect.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader(getAssetPath() + "shaders/cubemap/reflect.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); shaderStages[1] = loadShader(getAssetPath() + "shaders/cubemap/reflect.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// Enable depth test and write
depthStencilState.depthWriteEnable = VK_TRUE; depthStencilState.depthWriteEnable = VK_TRUE;
depthStencilState.depthTestEnable = VK_TRUE;
// Flip cull mode
rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.reflect)); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.reflect));
} }
@ -583,8 +591,9 @@ public:
// 3D objact // 3D objact
createBuffer( createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
sizeof(uboVS), sizeof(uboVS),
&uboVS, nullptr,
&uniformData.objectVS.buffer, &uniformData.objectVS.buffer,
&uniformData.objectVS.memory, &uniformData.objectVS.memory,
&uniformData.objectVS.descriptor); &uniformData.objectVS.descriptor);
@ -592,11 +601,14 @@ public:
// Skybox // Skybox
createBuffer( createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
sizeof(uboVS), sizeof(uboVS),
&uboVS, nullptr,
&uniformData.skyboxVS.buffer, &uniformData.skyboxVS.buffer,
&uniformData.skyboxVS.memory, &uniformData.skyboxVS.memory,
&uniformData.skyboxVS.descriptor); &uniformData.skyboxVS.descriptor);
updateUniformBuffers();
} }
void updateUniformBuffers() void updateUniformBuffers()
@ -607,7 +619,7 @@ public:
viewMatrix = glm::translate(viewMatrix, glm::vec3(0.0f, 0.0f, zoom)); viewMatrix = glm::translate(viewMatrix, glm::vec3(0.0f, 0.0f, zoom));
uboVS.model = glm::mat4(); uboVS.model = glm::mat4();
uboVS.model = viewMatrix * glm::translate(uboVS.model, glm::vec3(0, 0, 0)); uboVS.model = viewMatrix * glm::translate(uboVS.model, cameraPos);
uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); uboVS.model = glm::rotate(uboVS.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
@ -617,7 +629,7 @@ public:
memcpy(pData, &uboVS, sizeof(uboVS)); memcpy(pData, &uboVS, sizeof(uboVS));
vkUnmapMemory(device, uniformData.objectVS.memory); vkUnmapMemory(device, uniformData.objectVS.memory);
// Skysphere // Skybox
viewMatrix = glm::mat4(); viewMatrix = glm::mat4();
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.001f, 256.0f);
@ -632,6 +644,17 @@ public:
vkUnmapMemory(device, uniformData.skyboxVS.memory); vkUnmapMemory(device, uniformData.skyboxVS.memory);
} }
void draw()
{
VulkanExampleBase::prepareFrame();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
}
void prepare() void prepare()
{ {
VulkanExampleBase::prepare(); VulkanExampleBase::prepare();
@ -654,16 +677,55 @@ public:
{ {
if (!prepared) if (!prepared)
return; return;
vkDeviceWaitIdle(device);
draw(); draw();
vkDeviceWaitIdle(device);
updateUniformBuffers();
} }
virtual void viewChanged() virtual void viewChanged()
{ {
updateUniformBuffers(); updateUniformBuffers();
} }
void toggleSkyBox()
{
displaySkybox = !displaySkybox;
reBuildCommandBuffers();
}
void toggleObject()
{
meshes.objectIndex++;
if (meshes.objectIndex >= static_cast<uint32_t>(meshes.objects.size()))
{
meshes.objectIndex = 0;
}
reBuildCommandBuffers();
}
virtual void keyPressed(uint32_t keyCode)
{
switch (keyCode)
{
case 0x53:
case GAMEPAD_BUTTON_A:
toggleSkyBox();
break;
case 0x20:
case GAMEPAD_BUTTON_X:
toggleObject();
break;
}
}
virtual void getOverlayText(VulkanTextOverlay *textOverlay)
{
#if defined(__ANDROID__)
textOverlay->addText("Press \"Button A\" to toggle skybox", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
textOverlay->addText("Press \"Button X\" to toggle object", 5.0f, 100.0f, VulkanTextOverlay::alignLeft);
#else
textOverlay->addText("Press \"s\" to toggle skybox", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
textOverlay->addText("Press \"space\" to toggle object", 5.0f, 100.0f, VulkanTextOverlay::alignLeft);
#endif
}
}; };
VulkanExample *vulkanExample; VulkanExample *vulkanExample;