mirror of
https://github.com/KhronosGroup/Vulkan-Hpp.git
synced 2024-10-14 16:32:17 +00:00
Add sample RayTracing. (#361)
This commit is contained in:
parent
d5d4f3457b
commit
ecfaf9a0df
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
|||||||
[submodule "Vulkan-Headers"]
|
[submodule "Vulkan-Headers"]
|
||||||
path = Vulkan-Headers
|
path = Vulkan-Headers
|
||||||
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||||
|
[submodule "glfw"]
|
||||||
|
path = glfw
|
||||||
|
url = https://github.com/glfw/glfw
|
||||||
|
@ -79,6 +79,7 @@ target_include_directories(VulkanHppGenerator PRIVATE "${CMAKE_SOURCE_DIR}/tinyx
|
|||||||
|
|
||||||
option (SAMPLES_BUILD OFF)
|
option (SAMPLES_BUILD OFF)
|
||||||
if (SAMPLES_BUILD)
|
if (SAMPLES_BUILD)
|
||||||
|
add_subdirectory(glfw)
|
||||||
add_subdirectory(glslang)
|
add_subdirectory(glslang)
|
||||||
add_subdirectory(samples)
|
add_subdirectory(samples)
|
||||||
endif (SAMPLES_BUILD)
|
endif (SAMPLES_BUILD)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 097a1045098213919fd56442f52c716fc78eeb27
|
Subproject commit 552e49ee964e138352fbc0ecac3a16ca052ea7cb
|
1
glfw
Submodule
1
glfw
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 3a5e99e59a74aae9cb74dbd1170374aec9ecc6a2
|
55
samples/RayTracing/CMakeLists.txt
Normal file
55
samples/RayTracing/CMakeLists.txt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
|
project(RayTracing)
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
CameraManipulator.hpp
|
||||||
|
../utils/shaders.hpp
|
||||||
|
../utils/utils.hpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
CameraManipulator.cpp
|
||||||
|
RayTracing.cpp
|
||||||
|
../utils/shaders.cpp
|
||||||
|
../utils/utils.cpp
|
||||||
|
../../glslang/StandAlone/ResourceLimits.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
source_group(headers FILES ${HEADERS})
|
||||||
|
source_group(sources FILES ${SOURCES})
|
||||||
|
|
||||||
|
add_executable(RayTracing
|
||||||
|
${HEADERS}
|
||||||
|
${SOURCES}
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(RayTracing PROPERTIES FOLDER "Samples")
|
||||||
|
target_include_directories(RayTracing PUBLIC
|
||||||
|
${CMAKE_SOURCE_DIR}/glslang
|
||||||
|
${CMAKE_SOURCE_DIR}/glfw/include
|
||||||
|
${CMAKE_SOURCE_DIR}/samples/RayTracing/common
|
||||||
|
${CMAKE_SOURCE_DIR}/samples/RayTracing/vulkannv
|
||||||
|
${CMAKE_SOURCE_DIR}/stb
|
||||||
|
${CMAKE_SOURCE_DIR}/tinyobjloader
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(RayTracing PUBLIC glslang SPIRV
|
||||||
|
legacy_stdio_definitions.lib
|
||||||
|
${CMAKE_SOURCE_DIR}/builds/VS2017_64/glfw/src/Debug/glfw3.lib
|
||||||
|
"${Vulkan_LIBRARIES}"
|
||||||
|
)
|
428
samples/RayTracing/CameraManipulator.cpp
Normal file
428
samples/RayTracing/CameraManipulator.cpp
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "CameraManipulator.hpp"
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/rotate_vector.hpp>
|
||||||
|
|
||||||
|
namespace vk
|
||||||
|
{
|
||||||
|
namespace su
|
||||||
|
{
|
||||||
|
const float trackballSize = 0.8f;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// MATH functions
|
||||||
|
//
|
||||||
|
template <typename T>
|
||||||
|
bool isZero(const T& _a)
|
||||||
|
{
|
||||||
|
return fabs(_a) < std::numeric_limits<T>::epsilon();
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
bool isOne(const T& _a)
|
||||||
|
{
|
||||||
|
return areEqual(_a, (T)1);
|
||||||
|
}
|
||||||
|
inline float sign(float s)
|
||||||
|
{
|
||||||
|
return (s < 0.f) ? -1.f : 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraManipulator::CameraManipulator()
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 const& CameraManipulator::getCameraPosition() const
|
||||||
|
{
|
||||||
|
return m_cameraPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 const& CameraManipulator::getCenterPosition() const
|
||||||
|
{
|
||||||
|
return m_centerPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 const& CameraManipulator::getMatrix() const
|
||||||
|
{
|
||||||
|
return m_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraManipulator::Mode CameraManipulator::getMode() const
|
||||||
|
{
|
||||||
|
return m_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::ivec2 const& CameraManipulator::getMousePosition() const
|
||||||
|
{
|
||||||
|
return m_mousePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CameraManipulator::getRoll() const
|
||||||
|
{
|
||||||
|
return m_roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CameraManipulator::getSpeed() const
|
||||||
|
{
|
||||||
|
return m_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 const& CameraManipulator::getUpVector() const
|
||||||
|
{
|
||||||
|
return m_upVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::u32vec2 const& CameraManipulator::getWindowSize() const
|
||||||
|
{
|
||||||
|
return m_windowSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraManipulator::Action CameraManipulator::mouseMove(glm::ivec2 const& position, MouseButton mouseButton, ModifierFlags & modifiers)
|
||||||
|
{
|
||||||
|
Action curAction = Action::None;
|
||||||
|
switch (mouseButton)
|
||||||
|
{
|
||||||
|
case MouseButton::Left:
|
||||||
|
if (((modifiers & ModifierFlagBits::Ctrl) && (modifiers & ModifierFlagBits::Shift)) || (modifiers & ModifierFlagBits::Alt))
|
||||||
|
{
|
||||||
|
curAction = m_mode == Mode::Examine ? Action::LookAround : Action::Orbit;
|
||||||
|
}
|
||||||
|
else if (modifiers & ModifierFlagBits::Shift)
|
||||||
|
{
|
||||||
|
curAction = Action::Dolly;
|
||||||
|
}
|
||||||
|
else if (modifiers & ModifierFlagBits::Ctrl)
|
||||||
|
{
|
||||||
|
curAction = Action::Pan;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curAction = m_mode == Mode::Examine ? Action::Orbit : Action::LookAround;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MouseButton::Middle:
|
||||||
|
curAction = Action::Pan;
|
||||||
|
break;
|
||||||
|
case MouseButton::Right:
|
||||||
|
curAction = Action::Dolly;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
assert(curAction != Action::None);
|
||||||
|
motion(position, curAction);
|
||||||
|
|
||||||
|
return curAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::setLookat(const glm::vec3& cameraPosition, const glm::vec3& centerPosition, const glm::vec3& upVector)
|
||||||
|
{
|
||||||
|
m_cameraPosition = cameraPosition;
|
||||||
|
m_centerPosition = centerPosition;
|
||||||
|
m_upVector = upVector;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::setMode(Mode mode)
|
||||||
|
{
|
||||||
|
m_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::setMousePosition(glm::ivec2 const& position)
|
||||||
|
{
|
||||||
|
m_mousePosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::setRoll(float roll)
|
||||||
|
{
|
||||||
|
m_roll = roll;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::setSpeed(float speed)
|
||||||
|
{
|
||||||
|
m_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::setWindowSize(glm::ivec2 const& size)
|
||||||
|
{
|
||||||
|
m_windowSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::wheel(int value)
|
||||||
|
{
|
||||||
|
float fValue = static_cast<float>(value);
|
||||||
|
float dx = (fValue * abs(fValue)) / static_cast<float>(m_windowSize[0]);
|
||||||
|
|
||||||
|
glm::vec3 z = m_cameraPosition - m_centerPosition;
|
||||||
|
float length = z.length() * 0.1f;
|
||||||
|
length = length < 0.001f ? 0.001f : length;
|
||||||
|
|
||||||
|
dx *= m_speed;
|
||||||
|
dolly(glm::vec2(dx, dx));
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::dolly(glm::vec2 const& delta)
|
||||||
|
{
|
||||||
|
glm::vec3 z = m_centerPosition - m_cameraPosition;
|
||||||
|
float length = glm::length(z);
|
||||||
|
|
||||||
|
// We are at the point of interest, and don't know any direction, so do nothing!
|
||||||
|
if(isZero(length))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the larger movement.
|
||||||
|
float dd;
|
||||||
|
if(m_mode != Mode::Examine)
|
||||||
|
{
|
||||||
|
dd = -delta[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dd = fabs(delta[0]) > fabs(delta[1]) ? delta[0] : -delta[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
float factor = m_speed * dd / length;
|
||||||
|
|
||||||
|
// Adjust speed based on distance.
|
||||||
|
length /= 10;
|
||||||
|
length = length < 0.001f ? 0.001f : length;
|
||||||
|
factor *= length;
|
||||||
|
|
||||||
|
// Don't move to or through the point of interest.
|
||||||
|
if (1.0f <= factor)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
z *= factor;
|
||||||
|
|
||||||
|
// Not going up
|
||||||
|
if(m_mode == Mode::Walk)
|
||||||
|
{
|
||||||
|
if(m_upVector.y > m_upVector.z)
|
||||||
|
{
|
||||||
|
z.y = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
z.z = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cameraPosition += z;
|
||||||
|
|
||||||
|
// In fly mode, the interest moves with us.
|
||||||
|
if(m_mode != Mode::Examine)
|
||||||
|
{
|
||||||
|
m_centerPosition += z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::motion(glm::ivec2 const& position, Action action)
|
||||||
|
{
|
||||||
|
glm::vec2 delta(float(position[0] - m_mousePosition[0]) / float(m_windowSize[0]), float(position[1] - m_mousePosition[1]) / float(m_windowSize[1]));
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
{
|
||||||
|
case Action::Orbit:
|
||||||
|
if(m_mode == Mode::Trackball)
|
||||||
|
{
|
||||||
|
orbit(delta, true); // trackball(position);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
orbit(delta, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Action::Dolly:
|
||||||
|
dolly(delta);
|
||||||
|
break;
|
||||||
|
case Action::Pan:
|
||||||
|
pan(delta);
|
||||||
|
break;
|
||||||
|
case Action::LookAround:
|
||||||
|
if(m_mode == Mode::Trackball)
|
||||||
|
{
|
||||||
|
trackball(position);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
orbit(glm::vec2(delta[0], -delta[1]), true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
m_mousePosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::orbit(glm::vec2 const& delta, bool invert)
|
||||||
|
{
|
||||||
|
if(isZero(delta[0]) && isZero(delta[1]))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Full width will do a full turn
|
||||||
|
float dx = delta[0] * float(glm::two_pi<float>());
|
||||||
|
float dy = delta[1] * float(glm::two_pi<float>());
|
||||||
|
|
||||||
|
// Get the camera
|
||||||
|
glm::vec3 origin(invert ? m_cameraPosition : m_centerPosition);
|
||||||
|
glm::vec3 position(invert ? m_centerPosition : m_cameraPosition);
|
||||||
|
|
||||||
|
// Get the length of sight
|
||||||
|
glm::vec3 centerToEye(position - origin);
|
||||||
|
float radius = glm::length(centerToEye);
|
||||||
|
centerToEye = glm::normalize(centerToEye);
|
||||||
|
|
||||||
|
// Find the rotation around the UP axis (Y)
|
||||||
|
glm::vec3 zAxis(centerToEye);
|
||||||
|
glm::mat4 yRotation = glm::rotate(-dx, m_upVector);
|
||||||
|
|
||||||
|
// Apply the (Y) rotation to the eye-center vector
|
||||||
|
glm::vec4 tmpVector = yRotation * glm::vec4(centerToEye.x, centerToEye.y, centerToEye.z, 0.0f);
|
||||||
|
centerToEye = glm::vec3(tmpVector.x, tmpVector.y, tmpVector.z);
|
||||||
|
|
||||||
|
// Find the rotation around the X vector: cross between eye-center and up (X)
|
||||||
|
glm::vec3 xAxis = glm::cross(m_upVector, zAxis);
|
||||||
|
xAxis = glm::normalize(xAxis);
|
||||||
|
glm::mat4 xRotation = glm::rotate(-dy, xAxis);
|
||||||
|
|
||||||
|
// Apply the (X) rotation to the eye-center vector
|
||||||
|
tmpVector = xRotation * glm::vec4(centerToEye.x, centerToEye.y, centerToEye.z, 0);
|
||||||
|
glm::vec3 rotatedVector(tmpVector.x, tmpVector.y, tmpVector.z);
|
||||||
|
if(sign(rotatedVector.x) == sign(centerToEye.x))
|
||||||
|
{
|
||||||
|
centerToEye = rotatedVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the vector as long as it was originally
|
||||||
|
centerToEye *= radius;
|
||||||
|
|
||||||
|
// Finding the new position
|
||||||
|
glm::vec3 newPosition = centerToEye + origin;
|
||||||
|
|
||||||
|
if(!invert)
|
||||||
|
{
|
||||||
|
m_cameraPosition = newPosition; // Normal: change the position of the camera
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_centerPosition = newPosition; // Inverted: change the interest point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::pan(glm::vec2 const& delta)
|
||||||
|
{
|
||||||
|
glm::vec3 z(m_cameraPosition - m_centerPosition);
|
||||||
|
float length = static_cast<float>(glm::length(z)) / 0.785f; // 45 degrees
|
||||||
|
z = glm::normalize(z);
|
||||||
|
glm::vec3 x = glm::normalize(glm::cross(m_upVector, z));
|
||||||
|
glm::vec3 y = glm::normalize(glm::cross(z, x));
|
||||||
|
x *= -delta[0] * length;
|
||||||
|
y *= delta[1] * length;
|
||||||
|
|
||||||
|
if(m_mode == Mode::Fly)
|
||||||
|
{
|
||||||
|
x = -x;
|
||||||
|
y = -y;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cameraPosition += x + y;
|
||||||
|
m_centerPosition += x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
double CameraManipulator::projectOntoTBSphere(const glm::vec2& p)
|
||||||
|
{
|
||||||
|
double z;
|
||||||
|
double d = length(p);
|
||||||
|
if(d < trackballSize * 0.70710678118654752440)
|
||||||
|
{
|
||||||
|
// inside sphere
|
||||||
|
z = sqrt(trackballSize * trackballSize - d * d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// on hyperbola
|
||||||
|
double t = trackballSize / 1.41421356237309504880;
|
||||||
|
z = t * t / d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::trackball(glm::ivec2 const& position)
|
||||||
|
{
|
||||||
|
glm::vec2 p0(2 * (m_mousePosition[0] - m_windowSize[0] / 2) / double(m_windowSize[0]),
|
||||||
|
2 * (m_windowSize[1] / 2 - m_mousePosition[1]) / double(m_windowSize[1]));
|
||||||
|
glm::vec2 p1(2 * (position[0] - m_windowSize[0] / 2) / double(m_windowSize[0]), 2 * (m_windowSize[1] / 2 - position[1]) / double(m_windowSize[1]));
|
||||||
|
|
||||||
|
// determine the z coordinate on the sphere
|
||||||
|
glm::vec3 pTB0(p0[0], p0[1], projectOntoTBSphere(p0));
|
||||||
|
glm::vec3 pTB1(p1[0], p1[1], projectOntoTBSphere(p1));
|
||||||
|
|
||||||
|
// calculate the rotation axis via cross product between p0 and p1
|
||||||
|
glm::vec3 axis = glm::cross(pTB0, pTB1);
|
||||||
|
axis = glm::normalize(axis);
|
||||||
|
|
||||||
|
// calculate the angle
|
||||||
|
float t = glm::length(pTB0 - pTB1) / (2.f * trackballSize);
|
||||||
|
|
||||||
|
// clamp between -1 and 1
|
||||||
|
if(t > 1.0f)
|
||||||
|
{
|
||||||
|
t = 1.0f;
|
||||||
|
}
|
||||||
|
else if(t < -1.0f)
|
||||||
|
{
|
||||||
|
t = -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rad = 2.0f * asin(t);
|
||||||
|
|
||||||
|
{
|
||||||
|
glm::vec4 rot_axis = m_matrix * glm::vec4(axis, 0);
|
||||||
|
glm::mat4 rot_mat = glm::rotate(rad, glm::vec3(rot_axis.x, rot_axis.y, rot_axis.z));
|
||||||
|
|
||||||
|
glm::vec3 pnt = m_cameraPosition - m_centerPosition;
|
||||||
|
glm::vec4 pnt2 = rot_mat * glm::vec4(pnt.x, pnt.y, pnt.z, 1);
|
||||||
|
m_cameraPosition = m_centerPosition + glm::vec3(pnt2.x, pnt2.y, pnt2.z);
|
||||||
|
glm::vec4 up2 = rot_mat * glm::vec4(m_upVector.x, m_upVector.y, m_upVector.z, 0);
|
||||||
|
m_upVector = glm::vec3(up2.x, up2.y, up2.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraManipulator::update()
|
||||||
|
{
|
||||||
|
m_matrix = glm::lookAt(m_cameraPosition, m_centerPosition, m_upVector);
|
||||||
|
|
||||||
|
if(!isZero(m_roll))
|
||||||
|
{
|
||||||
|
glm::mat4 rot = glm::rotate(m_roll, glm::vec3(0, 0, 1));
|
||||||
|
m_matrix = m_matrix * rot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace su
|
||||||
|
} // namespace vk
|
79
samples/RayTracing/CameraManipulator.hpp
Normal file
79
samples/RayTracing/CameraManipulator.hpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
namespace vk
|
||||||
|
{
|
||||||
|
namespace su
|
||||||
|
{
|
||||||
|
class CameraManipulator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Action { None, Orbit, Dolly, Pan, LookAround };
|
||||||
|
enum class Mode { Examine, Fly, Walk, Trackball };
|
||||||
|
enum class MouseButton { None, Left, Middle, Right };
|
||||||
|
enum class ModifierFlagBits { Shift = 1, Ctrl = 2, Alt = 4 };
|
||||||
|
using ModifierFlags = vk::Flags<ModifierFlagBits, uint32_t>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CameraManipulator();
|
||||||
|
|
||||||
|
glm::vec3 const& getCameraPosition() const;
|
||||||
|
glm::vec3 const& getCenterPosition() const;
|
||||||
|
glm::mat4 const& getMatrix() const;
|
||||||
|
Mode getMode() const;
|
||||||
|
glm::ivec2 const& getMousePosition() const;
|
||||||
|
float getRoll() const;
|
||||||
|
float getSpeed() const;
|
||||||
|
glm::vec3 const& getUpVector() const;
|
||||||
|
glm::u32vec2 const& getWindowSize() const;
|
||||||
|
Action mouseMove(glm::ivec2 const& position, MouseButton mouseButton, ModifierFlags & modifiers);
|
||||||
|
void setLookat(const glm::vec3& cameraPosition, const glm::vec3& centerPosition, const glm::vec3& upVector);
|
||||||
|
void setMode(Mode mode);
|
||||||
|
void setMousePosition(glm::ivec2 const& position);
|
||||||
|
void setRoll(float roll); // roll in radians
|
||||||
|
void setSpeed(float speed);
|
||||||
|
void setWindowSize(glm::ivec2 const& size);
|
||||||
|
void wheel(int value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void dolly(glm::vec2 const& delta);
|
||||||
|
void motion(glm::ivec2 const& position, Action action = Action::None);
|
||||||
|
void orbit(glm::vec2 const& delta, bool invert = false);
|
||||||
|
void pan(glm::vec2 const& delta);
|
||||||
|
double projectOntoTBSphere(const glm::vec2& p);
|
||||||
|
void trackball(glm::ivec2 const& position);
|
||||||
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::vec3 m_cameraPosition = glm::vec3(10, 10, 10);
|
||||||
|
glm::vec3 m_centerPosition = glm::vec3(0, 0, 0);
|
||||||
|
glm::vec3 m_upVector = glm::vec3(0, 1, 0);
|
||||||
|
float m_roll = 0; // Rotation around the Z axis in RAD
|
||||||
|
glm::mat4 m_matrix = glm::mat4(1);
|
||||||
|
|
||||||
|
glm::u32vec2 m_windowSize = glm::u32vec2(1, 1);
|
||||||
|
|
||||||
|
float m_speed = 30.0f;
|
||||||
|
glm::ivec2 m_mousePosition = glm::ivec2(0, 0);
|
||||||
|
|
||||||
|
Mode m_mode = Mode::Examine;
|
||||||
|
};
|
||||||
|
} // namespace su
|
||||||
|
} // namespace vk
|
1082
samples/RayTracing/RayTracing.cpp
Normal file
1082
samples/RayTracing/RayTracing.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,14 @@ namespace vk
|
|||||||
case vk::ShaderStageFlagBits::eGeometry: return EShLangGeometry;
|
case vk::ShaderStageFlagBits::eGeometry: return EShLangGeometry;
|
||||||
case vk::ShaderStageFlagBits::eFragment: return EShLangFragment;
|
case vk::ShaderStageFlagBits::eFragment: return EShLangFragment;
|
||||||
case vk::ShaderStageFlagBits::eCompute: return EShLangCompute;
|
case vk::ShaderStageFlagBits::eCompute: return EShLangCompute;
|
||||||
|
case vk::ShaderStageFlagBits::eRaygenNV: return EShLangRayGenNV;
|
||||||
|
case vk::ShaderStageFlagBits::eAnyHitNV: return EShLangAnyHitNV;
|
||||||
|
case vk::ShaderStageFlagBits::eClosestHitNV: return EShLangClosestHitNV;
|
||||||
|
case vk::ShaderStageFlagBits::eMissNV: return EShLangMissNV;
|
||||||
|
case vk::ShaderStageFlagBits::eIntersectionNV: return EShLangIntersectNV;
|
||||||
|
case vk::ShaderStageFlagBits::eCallableNV: return EShLangCallableNV;
|
||||||
|
case vk::ShaderStageFlagBits::eTaskNV: return EShLangTaskNV;
|
||||||
|
case vk::ShaderStageFlagBits::eMeshNV: return EShLangMeshNV;
|
||||||
default:
|
default:
|
||||||
assert(false && "Unknown shader stage");
|
assert(false && "Unknown shader stage");
|
||||||
return EShLangVertex;
|
return EShLangVertex;
|
||||||
|
@ -537,14 +537,15 @@ namespace vk
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
||||||
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData, vk::su::TextureData const& textureData)
|
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData, vk::su::TextureData const& textureData,
|
||||||
|
uint32_t bindingOffset)
|
||||||
{
|
{
|
||||||
std::vector<vk::DescriptorBufferInfo> bufferInfos;
|
std::vector<vk::DescriptorBufferInfo> bufferInfos;
|
||||||
bufferInfos.reserve(bufferData.size());
|
bufferInfos.reserve(bufferData.size());
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
||||||
writeDescriptorSets.reserve(bufferData.size() + 1);
|
writeDescriptorSets.reserve(bufferData.size() + 1);
|
||||||
uint32_t dstBinding = 0;
|
uint32_t dstBinding = bindingOffset;
|
||||||
for (auto const& bd : bufferData)
|
for (auto const& bd : bufferData)
|
||||||
{
|
{
|
||||||
bufferInfos.push_back(vk::DescriptorBufferInfo(*std::get<1>(bd), 0, VK_WHOLE_SIZE));
|
bufferInfos.push_back(vk::DescriptorBufferInfo(*std::get<1>(bd), 0, VK_WHOLE_SIZE));
|
||||||
@ -559,14 +560,14 @@ namespace vk
|
|||||||
|
|
||||||
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
||||||
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData,
|
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData,
|
||||||
std::vector<vk::su::TextureData> const& textureData)
|
std::vector<vk::su::TextureData> const& textureData, uint32_t bindingOffset)
|
||||||
{
|
{
|
||||||
std::vector<vk::DescriptorBufferInfo> bufferInfos;
|
std::vector<vk::DescriptorBufferInfo> bufferInfos;
|
||||||
bufferInfos.reserve(bufferData.size());
|
bufferInfos.reserve(bufferData.size());
|
||||||
|
|
||||||
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
|
||||||
writeDescriptorSets.reserve(bufferData.size() + textureData.empty() ? 0 : 1);
|
writeDescriptorSets.reserve(bufferData.size() + textureData.empty() ? 0 : 1);
|
||||||
uint32_t dstBinding = 0;
|
uint32_t dstBinding = bindingOffset;
|
||||||
for (auto const& bd : bufferData)
|
for (auto const& bd : bufferData)
|
||||||
{
|
{
|
||||||
bufferInfos.push_back(vk::DescriptorBufferInfo(*std::get<1>(bd), 0, VK_WHOLE_SIZE));
|
bufferInfos.push_back(vk::DescriptorBufferInfo(*std::get<1>(bd), 0, VK_WHOLE_SIZE));
|
||||||
@ -684,18 +685,23 @@ namespace vk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckerboardImageGenerator::CheckerboardImageGenerator(std::array<uint8_t, 3> const& rgb0, std::array<uint8_t, 3> const& rgb1)
|
||||||
|
: m_rgb0(rgb0)
|
||||||
|
, m_rgb1(rgb1)
|
||||||
|
{}
|
||||||
|
|
||||||
void CheckerboardImageGenerator::operator()(void* data, vk::Extent2D &extent) const
|
void CheckerboardImageGenerator::operator()(void* data, vk::Extent2D &extent) const
|
||||||
{
|
{
|
||||||
// Checkerboard of 16x16 pixel squares
|
// Checkerboard of 16x16 pixel squares
|
||||||
unsigned char *pImageMemory = static_cast<unsigned char*>(data);
|
uint8_t *pImageMemory = static_cast<uint8_t *>(data);
|
||||||
for (uint32_t row = 0; row < extent.height; row++)
|
for (uint32_t row = 0; row < extent.height; row++)
|
||||||
{
|
{
|
||||||
for (uint32_t col = 0; col < extent.width; col++)
|
for (uint32_t col = 0; col < extent.width; col++)
|
||||||
{
|
{
|
||||||
unsigned char rgb = (((row & 0x10) == 0) ^ ((col & 0x10) == 0)) * 255;
|
std::array<uint8_t, 3> const& rgb = (((row & 0x10) == 0) ^ ((col & 0x10) == 0)) ? m_rgb1 : m_rgb0;
|
||||||
pImageMemory[0] = rgb;
|
pImageMemory[0] = rgb[0];
|
||||||
pImageMemory[1] = rgb;
|
pImageMemory[1] = rgb[1];
|
||||||
pImageMemory[2] = rgb;
|
pImageMemory[2] = rgb[2];
|
||||||
pImageMemory[3] = 255;
|
pImageMemory[3] = 255;
|
||||||
pImageMemory += 4;
|
pImageMemory += 4;
|
||||||
}
|
}
|
||||||
|
@ -42,34 +42,34 @@ namespace vk
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename DataType>
|
template <typename DataType>
|
||||||
void upload(vk::UniqueDevice const& device, std::vector<DataType> const& data) const
|
void upload(vk::UniqueDevice const& device, std::vector<DataType> const& data, size_t stride = 0) const
|
||||||
{
|
{
|
||||||
assert((m_propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent) && (m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible));
|
assert(m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
|
|
||||||
size_t dataSize = data.size() * sizeof(DataType);
|
size_t elementSize = stride ? stride : sizeof(DataType);
|
||||||
assert(dataSize <= m_size);
|
assert(sizeof(DataType) <= elementSize);
|
||||||
|
|
||||||
void* dataPtr = device->mapMemory(*this->deviceMemory, 0, dataSize);
|
copyToDevice(device, deviceMemory, data.data(), data.size(), elementSize);
|
||||||
memcpy(dataPtr, data.data(), dataSize);
|
|
||||||
device->unmapMemory(*this->deviceMemory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename DataType>
|
template <typename DataType>
|
||||||
void upload(vk::PhysicalDevice const& physicalDevice, vk::UniqueDevice const& device, vk::UniqueCommandPool const& commandPool, vk::Queue queue, std::vector<DataType> const& data) const
|
void upload(vk::PhysicalDevice const& physicalDevice, vk::UniqueDevice const& device, vk::UniqueCommandPool const& commandPool, vk::Queue queue, std::vector<DataType> const& data,
|
||||||
|
size_t stride) const
|
||||||
{
|
{
|
||||||
assert(m_usage & vk::BufferUsageFlagBits::eTransferDst);
|
assert(m_usage & vk::BufferUsageFlagBits::eTransferDst);
|
||||||
assert(m_propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal);
|
assert(m_propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal);
|
||||||
|
|
||||||
size_t dataSize = data.size() * sizeof(DataType);
|
size_t elementSize = stride ? stride : sizeof(DataType);
|
||||||
|
assert(sizeof(DataType) <= elementSize);
|
||||||
|
|
||||||
|
size_t dataSize = data.size() * elementSize;
|
||||||
assert(dataSize <= m_size);
|
assert(dataSize <= m_size);
|
||||||
|
|
||||||
vk::su::BufferData stagingBuffer(physicalDevice, device, dataSize, vk::BufferUsageFlagBits::eTransferSrc);
|
vk::su::BufferData stagingBuffer(physicalDevice, device, dataSize, vk::BufferUsageFlagBits::eTransferSrc);
|
||||||
void* dataPtr = device->mapMemory(*stagingBuffer.deviceMemory, 0, dataSize);
|
copyToDevice(device, stagingBuffer.deviceMemory, data.data(), data.size(), elementSize);
|
||||||
memcpy(dataPtr, data.data(), dataSize);
|
|
||||||
device->unmapMemory(*stagingBuffer.deviceMemory);
|
|
||||||
|
|
||||||
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(*commandPool, vk::CommandBufferLevel::ePrimary, 1)).front());
|
vk::su::oneTimeSubmit(device, commandPool, queue,
|
||||||
vk::su::oneTimeSubmit(commandBuffer, queue, [&]() { commandBuffer->copyBuffer(*stagingBuffer.buffer, *this->buffer, vk::BufferCopy(0, 0, dataSize)); });
|
[&](vk::UniqueCommandBuffer const& commandBuffer) { commandBuffer->copyBuffer(*stagingBuffer.buffer, *this->buffer, vk::BufferCopy(0, 0, dataSize)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::UniqueBuffer buffer;
|
vk::UniqueBuffer buffer;
|
||||||
@ -120,8 +120,14 @@ namespace vk
|
|||||||
|
|
||||||
class CheckerboardImageGenerator
|
class CheckerboardImageGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
CheckerboardImageGenerator(std::array<uint8_t, 3> const& rgb0 = {0, 0, 0}, std::array<uint8_t, 3> const& rgb1 = {255, 255, 255});
|
||||||
|
|
||||||
void operator()(void* data, vk::Extent2D &extent) const;
|
void operator()(void* data, vk::Extent2D &extent) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<uint8_t, 3> const& m_rgb0;
|
||||||
|
std::array<uint8_t, 3> const& m_rgb1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MonochromeImageGenerator
|
class MonochromeImageGenerator
|
||||||
@ -207,7 +213,7 @@ namespace vk
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const* pData, size_t count, size_t stride = sizeof(T))
|
void copyToDevice(vk::UniqueDevice const& device, vk::UniqueDeviceMemory const& memory, T const* pData, size_t count, size_t stride = sizeof(T))
|
||||||
{
|
{
|
||||||
assert(sizeof(T) <= stride);
|
assert(sizeof(T) <= stride);
|
||||||
uint8_t* deviceData = static_cast<uint8_t*>(device->mapMemory(memory.get(), 0, count * stride));
|
uint8_t* deviceData = static_cast<uint8_t*>(device->mapMemory(memory.get(), 0, count * stride));
|
||||||
@ -227,7 +233,7 @@ namespace vk
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const& data)
|
void copyToDevice(vk::UniqueDevice const& device, vk::UniqueDeviceMemory const& memory, T const& data)
|
||||||
{
|
{
|
||||||
copyToDevice<T>(device, memory, &data, 1);
|
copyToDevice<T>(device, memory, &data, 1);
|
||||||
}
|
}
|
||||||
@ -238,16 +244,23 @@ namespace vk
|
|||||||
return v < lo ? lo : hi < v ? hi : v;
|
return v < lo ? lo : hi < v ? hi : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Func, typename... Args>
|
template <typename Func>
|
||||||
void oneTimeSubmit(vk::UniqueCommandBuffer const& commandBuffer, vk::Queue const& queue, Func const& func, Args... args)
|
void oneTimeSubmit(vk::UniqueCommandBuffer const& commandBuffer, vk::Queue const& queue, Func const& func)
|
||||||
{
|
{
|
||||||
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit));
|
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit));
|
||||||
func(args...);
|
func(commandBuffer);
|
||||||
commandBuffer->end();
|
commandBuffer->end();
|
||||||
queue.submit(vk::SubmitInfo(0, nullptr, nullptr, 1, &(*commandBuffer)), nullptr);
|
queue.submit(vk::SubmitInfo(0, nullptr, nullptr, 1, &(*commandBuffer)), nullptr);
|
||||||
queue.waitIdle();
|
queue.waitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
void oneTimeSubmit(vk::UniqueDevice const& device, vk::UniqueCommandPool const& commandPool, vk::Queue const& queue, Func const& func)
|
||||||
|
{
|
||||||
|
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(*commandPool, vk::CommandBufferLevel::ePrimary, 1)).front());
|
||||||
|
oneTimeSubmit(commandBuffer, queue, func);
|
||||||
|
}
|
||||||
|
|
||||||
vk::UniqueDeviceMemory allocateMemory(vk::UniqueDevice const& device, vk::PhysicalDeviceMemoryProperties const& memoryProperties, vk::MemoryRequirements const& memoryRequirements,
|
vk::UniqueDeviceMemory allocateMemory(vk::UniqueDevice const& device, vk::PhysicalDeviceMemoryProperties const& memoryProperties, vk::MemoryRequirements const& memoryRequirements,
|
||||||
vk::MemoryPropertyFlags memoryPropertyFlags);
|
vk::MemoryPropertyFlags memoryPropertyFlags);
|
||||||
vk::UniqueCommandPool createCommandPool(vk::UniqueDevice &device, uint32_t queueFamilyIndex);
|
vk::UniqueCommandPool createCommandPool(vk::UniqueDevice &device, uint32_t queueFamilyIndex);
|
||||||
@ -277,10 +290,11 @@ namespace vk
|
|||||||
void setImageLayout(vk::UniqueCommandBuffer const& commandBuffer, vk::Image image, vk::Format format, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout);
|
void setImageLayout(vk::UniqueCommandBuffer const& commandBuffer, vk::Image image, vk::Format format, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout);
|
||||||
void submitAndWait(vk::UniqueDevice &device, vk::Queue queue, vk::UniqueCommandBuffer &commandBuffer);
|
void submitAndWait(vk::UniqueDevice &device, vk::Queue queue, vk::UniqueCommandBuffer &commandBuffer);
|
||||||
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
||||||
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData, vk::su::TextureData const& textureData);
|
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData, vk::su::TextureData const& textureData,
|
||||||
|
uint32_t bindingOffset = 0);
|
||||||
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet,
|
||||||
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData,
|
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData,
|
||||||
std::vector<vk::su::TextureData> const& textureData);
|
std::vector<vk::su::TextureData> const& textureData, uint32_t bindingOffset = 0);
|
||||||
|
|
||||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||||
HWND initializeWindow(std::string const& className, std::string const& windowName, LONG width, LONG height);
|
HWND initializeWindow(std::string const& className, std::string const& windowName, LONG width, LONG height);
|
||||||
|
Loading…
Reference in New Issue
Block a user