Per-viewport eye separation
This commit is contained in:
parent
1fc0d17b63
commit
182ff9e72d
1 changed files with 69 additions and 17 deletions
|
|
@ -48,16 +48,20 @@ public:
|
||||||
VkDescriptorSet descriptorSet;
|
VkDescriptorSet descriptorSet;
|
||||||
VkDescriptorSetLayout descriptorSetLayout;
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
||||||
|
// Camera and view properties
|
||||||
|
float eyeSeparation = 0.08f;
|
||||||
|
const float focalLength = 0.5f;
|
||||||
|
const float fov = 90.0f;
|
||||||
|
const float zNear = 0.1f;
|
||||||
|
const float zFar = 256.0f;
|
||||||
|
|
||||||
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
||||||
{
|
{
|
||||||
zoom = -8.0f;
|
|
||||||
rotation = glm::vec3(0.0f, -25.0f, 0.0f);
|
|
||||||
enableTextOverlay = true;
|
|
||||||
title = "Vulkan Example - Viewport arrays";
|
title = "Vulkan Example - Viewport arrays";
|
||||||
|
enableTextOverlay = true;
|
||||||
camera.type = Camera::CameraType::firstperson;
|
camera.type = Camera::CameraType::firstperson;
|
||||||
camera.setPerspective(90.0f, (float)(width * 0.5) / (float)height, 0.1f, 256.0f);
|
|
||||||
camera.setRotation(glm::vec3(0.0f, 90.0f, 0.0f));
|
camera.setRotation(glm::vec3(0.0f, 90.0f, 0.0f));
|
||||||
camera.setTranslation(glm::vec3(9.5f, 3.2f, 0.75f));
|
camera.setTranslation(glm::vec3(7.0f, 3.2f, 0.0f));
|
||||||
camera.movementSpeed = 5.0f;
|
camera.movementSpeed = 5.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,26 +308,58 @@ public:
|
||||||
|
|
||||||
void updateUniformBuffers()
|
void updateUniformBuffers()
|
||||||
{
|
{
|
||||||
// Geometry shader
|
// Geometry shader matrices for the two viewports
|
||||||
uboGS.projection[0] = camera.matrices.perspective;
|
// See http://paulbourke.net/stereographics/stereorender/
|
||||||
uboGS.projection[1] = camera.matrices.perspective;
|
|
||||||
// todo: offsets left/right
|
// Calculate some variables
|
||||||
uboGS.modelview[0] = camera.matrices.view;
|
float aspectRatio = (float)(width * 0.5f) / (float)height;
|
||||||
uboGS.modelview[1] = camera.matrices.view;
|
float wd2 = zNear * tan(glm::radians(fov / 2.0f));
|
||||||
|
float ndfl = zNear / focalLength;
|
||||||
|
float left, right;
|
||||||
|
float top = wd2;
|
||||||
|
float bottom = -wd2;
|
||||||
|
|
||||||
|
glm::vec3 camFront;
|
||||||
|
camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
|
||||||
|
camFront.y = sin(glm::radians(rotation.x));
|
||||||
|
camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
|
||||||
|
camFront = glm::normalize(camFront);
|
||||||
|
glm::vec3 camRight = glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||||
|
|
||||||
|
glm::mat4 rotM = glm::mat4();
|
||||||
|
glm::mat4 transM;
|
||||||
|
|
||||||
|
rotM = glm::rotate(rotM, glm::radians(camera.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
rotM = glm::rotate(rotM, glm::radians(camera.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
rotM = glm::rotate(rotM, glm::radians(camera.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
// Left eye
|
||||||
|
left = -aspectRatio * wd2 + 0.5f * eyeSeparation * ndfl;
|
||||||
|
right = aspectRatio * wd2 + 0.5f * eyeSeparation * ndfl;
|
||||||
|
|
||||||
|
transM = glm::translate(glm::mat4(), camera.position - camRight * (eyeSeparation / 2.0f));
|
||||||
|
|
||||||
|
uboGS.projection[0] = glm::frustum(left, right, bottom, top, zNear, zFar);
|
||||||
|
uboGS.modelview[0] = rotM * transM;
|
||||||
|
|
||||||
|
// Right eye
|
||||||
|
left = -aspectRatio * wd2 - 0.5f * eyeSeparation * ndfl;
|
||||||
|
right = aspectRatio * wd2 - 0.5f * eyeSeparation * ndfl;
|
||||||
|
|
||||||
|
transM = glm::translate(glm::mat4(), camera.position + camRight * (eyeSeparation / 2.0f));
|
||||||
|
|
||||||
|
uboGS.projection[1] = glm::frustum(left, right, bottom, top, zNear, zFar);
|
||||||
|
uboGS.modelview[1] = rotM * transM;
|
||||||
|
|
||||||
memcpy(uniformBufferGS.mapped, &uboGS, sizeof(uboGS));
|
memcpy(uniformBufferGS.mapped, &uboGS, sizeof(uboGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw()
|
void draw()
|
||||||
{
|
{
|
||||||
VulkanExampleBase::prepareFrame();
|
VulkanExampleBase::prepareFrame();
|
||||||
|
|
||||||
// Command buffer to be sumitted to the queue
|
|
||||||
submitInfo.commandBufferCount = 1;
|
submitInfo.commandBufferCount = 1;
|
||||||
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
||||||
|
|
||||||
// Submit to queue
|
|
||||||
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
|
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
|
||||||
|
|
||||||
VulkanExampleBase::submitFrame();
|
VulkanExampleBase::submitFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,9 +388,25 @@ public:
|
||||||
updateUniformBuffers();
|
updateUniformBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void changeEyeSeparation(float delta)
|
||||||
|
{
|
||||||
|
eyeSeparation += delta;
|
||||||
|
updateUniformBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
virtual void keyPressed(uint32_t keyCode)
|
virtual void keyPressed(uint32_t keyCode)
|
||||||
{
|
{
|
||||||
//
|
switch (keyCode)
|
||||||
|
{
|
||||||
|
case KEY_KPADD:
|
||||||
|
case GAMEPAD_BUTTON_R1:
|
||||||
|
changeEyeSeparation(0.005);
|
||||||
|
break;
|
||||||
|
case KEY_KPSUB:
|
||||||
|
case GAMEPAD_BUTTON_L1:
|
||||||
|
changeEyeSeparation(-0.005);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue