This commit is contained in:
Joshua Ashton 2022-08-12 20:18:11 +00:00
parent 0b97e6eeec
commit 81e8b94a0f
10 changed files with 353 additions and 34 deletions

View File

@ -0,0 +1,77 @@
#pragma once
#include <Orange/Math/Unit.h>
#include <Orange/Math/Constants.h>
namespace orange
{
namespace detail
{
template <typename T>
class Radian;
template <typename T>
class Degree : public Unit<Degree, T>
{
public:
Degree() {}
explicit Degree(T value)
: Unit<orange::detail::Degree, T>(value)
{
}
Degree(Unit<orange::detail::Degree, T> value)
: Unit<orange::detail::Degree, T>(value)
{
}
template <class U>
explicit Degree(Unit<orange::detail::Degree, U> value)
: Unit<orange::detail::Degree, T>(value)
{
}
Degree(Unit<Radian, T> value);
};
template <typename T>
class Radian : public Unit<Radian, T>
{
public:
Radian() {}
explicit Radian(T value)
: Unit<orange::detail::Radian, T>(value)
{
}
Radian(Unit<orange::detail::Radian, T> value)
: Unit<orange::detail::Radian, T>(value)
{
}
template <class U>
explicit Radian(Unit<orange::detail::Radian, U> value)
: Unit<orange::detail::Radian, T>(value)
{
}
Radian(Unit<Degree, T> value);
};
template <typename T>
Degree<T>::Degree(Unit<Radian, T> value)
: Unit<orange::detail::Degree, T>(T(360) * T(value) / Math::Tau)
{
}
template <typename T>
Radian<T>::Radian(Unit<Degree, T> value)
: Unit<orange::detail::Radian, T>(T(value) * Math::Tau / T(360))
{
}
}
using Radian = detail::Radian<float>;
using Degree = detail::Degree<float>;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <Orange/Math/Angle.h>
#include <math.h>
namespace orange::Math
{
inline float sin(const Radian& theta) { return sinf(static_cast<float>(theta)); }
inline float cos(const Radian& theta) { return cosf(static_cast<float>(theta)); }
inline float tan(const Radian& theta) { return tanf(static_cast<float>(theta)); }
template <typename T>
constexpr T kroneckerDelta(const T& i, const T& j)
{
return i == j ? T{1} : T{0};
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <limits>
namespace orange::Math
{
static constexpr float Epsilon = std::numeric_limits<float>::epsilon();
static constexpr float Zero = 0.0f;
static constexpr float One = 1.0f;
static constexpr float Third = 0.33333333f;
static constexpr float TwoThirds = 0.66666667f;
static constexpr float E = 2.718281828f;
static constexpr float Pi = 3.141592654f;
static constexpr float Tau = 6.283185307f;
static constexpr float Sqrt2 = 1.414213562f;
static constexpr float Sqrt3 = 1.732050808f;
static constexpr float GoldenRatio = 1.618033989f;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <Orange/Math/Vector.h>
#include <Orange/Math/Angle.h>
namespace orange
{
@ -19,6 +20,16 @@ namespace orange
}
}
constexpr Matrix(const RowVector& scale)
{
for (size_t i = 0; i < Rows; i++)
{
RowVector vector{};
vector[i] = scale[i];
data[i] = vector;
}
}
template <typename... Args>
constexpr Matrix(const Args&... args)
: data {{ args... }}
@ -245,4 +256,6 @@ namespace orange
return x.TransformResult(y, math::Multiply);
}
using mat4 = Matrix<float, 4, 4>;
}

View File

@ -0,0 +1,34 @@
#pragma once
#include <Orange/Math/Common.h>
namespace orange
{
mat4 translate(const vec3& v)
{
mat4 result;
result[3] = vec4{ v[0], v[1], v[2], 1.0f };
return result;
}
mat4 scale(const vec3& v)
{
return mat4{vec4{v[0], v[1], v[2], 1.0f}};
}
mat4 perspective(const Radian& fovy, float aspect, float zNear, float zFar)
{
Assert(fabsf(aspect - Math::Epsilon) > 0.0f && "Math::perspective `fovy` is 0/inf.");
const float tanHalfFovy = Math::tan(0.5f * fovy);
mat4 result{0.0f};
result[0][0] = 1.0f / (aspect * tanHalfFovy);
result[1][1] = 1.0f / (tanHalfFovy);
result[2][2] = -(zFar + zNear) / (zFar - zNear);
result[2][3] = -1.0f;
result[3][2] = -2.0f * zFar * zNear / (zFar - zNear);
return result;
}
}

113
include/Orange/Math/Unit.h Normal file
View File

@ -0,0 +1,113 @@
#pragma once
namespace orange
{
template <template <typename> class Derived, typename T>
class Unit
{
template <template <typename> class, typename>
friend class Unit;
public:
using Type = T;
Unit()
: m_value{T{0}}
{
}
explicit Unit(T value)
: m_value{value}
{
}
template <typename U>
explicit Unit(Unit<Derived, U> value)
: m_value{T{value.m_value}}
{
}
explicit operator T() const { return m_value; }
bool operator==(Unit<Derived, T> other) const
{
return m_value == other.m_value;
}
bool operator!=(Unit<Derived, T> other) const { return !operator==(other); }
bool operator<(Unit<Derived, T> other) const
{
return m_value < other.m_value;
}
bool operator>(Unit<Derived, T> other) const
{
return m_value > other.m_value;
}
bool operator<=(Unit<Derived, T> other) const { return !operator>(other); }
bool operator>=(Unit<Derived, T> other) const { return !operator<(other); }
Unit<Derived, T> operator-() const { return Unit<Derived, T>{-m_value}; }
Unit<Derived, T>& operator+=(Unit<Derived, T> other)
{
m_value += other.m_value;
return *this;
}
Unit<Derived, T> operator+(Unit<Derived, T> other) const
{
return Unit<Derived, T>{m_value + other.m_value};
}
Unit<Derived, T>& operator-=(Unit<Derived, T> other)
{
m_value -= other.m_value;
return *this;
}
Unit<Derived, T> operator-(Unit<Derived, T> other) const
{
return Unit<Derived, T>{m_value - other.m_value};
}
Unit<Derived, T>& operator*=(T number)
{
m_value *= number;
return *this;
}
Unit<Derived, T> operator*(T number) const
{
return Unit<Derived, T>{m_value * number};
}
Unit<Derived, T>& operator/=(T number)
{
m_value /= number;
return *this;
}
Unit<Derived, T> operator/(T number) const
{
return Unit<Derived, T>{m_value / number};
}
T operator/(Unit<Derived, T> other) const { return m_value / other.value; }
private:
T m_value;
};
template <template <typename> class Derived, typename T>
Unit<Derived, T> operator*(typename std::common_type<T>::type number,
const Unit<Derived, T>& value)
{
return value * number;
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <Orange/Core/Traits.h>
#include <Orange/Core/Result.h>
#include <vulkan/vulkan_core.h>
namespace orange
@ -40,4 +41,22 @@ namespace orange
return format;
}
}
template <typename... Formats>
Result<VkFormat> FindSupportedFormat(VkPhysicalDevice physicalDevice, VkImageTiling tiling, VkFormatFeatureFlags features, Formats... formats)
{
for (auto& format : {formats...})
{
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props);
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features)
return Result<VkFormat>::Success(format);
if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features)
return Result<VkFormat>::Success(format);
}
return Result<VkFormat>::Error(BasicErrorCode::NotFound);
}
}

View File

@ -5,6 +5,7 @@
#include <Orange/Core/FileSystem.h>
#include <Orange/Math/Vector.h>
#include <Orange/Math/Matrix.h>
#include <Orange/Math/Transformation.h>
#include <Orange/Core/Parse.h>
#include <Orange/Core/Variant.h>
@ -202,7 +203,7 @@ Result<MeshData> ParseOBJ(StringView buffer)
if (j == 0 || stream::Consume(obj, end, "/"))
{
if (auto r_int = stream::Parse<uint32_t>(obj, end))
indices[i][j] = *r_int;
indices[i][j] = *r_int - 1; // OBJ indexing starts at one.
}
}
}
@ -321,19 +322,13 @@ int main(int argc, char** argv)
},
{
.binding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
.descriptorCount = MaxBindlessResources,
.stageFlags = VK_SHADER_STAGE_ALL,
},
{
.binding = 2,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = &sampler,
},
{
.binding = 3,
.binding = 2,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = MaxBindlessResources,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
@ -342,7 +337,6 @@ int main(int argc, char** argv)
constexpr VkDescriptorBindingFlags bindingFlags[] =
{
0,
0,
0,
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT,
@ -453,7 +447,7 @@ int main(int argc, char** argv)
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.cullMode = VK_CULL_MODE_NONE, //VK_CULL_MODE_BACK_BIT,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
.lineWidth = 1.0f,
};
@ -463,6 +457,16 @@ int main(int argc, char** argv)
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
};
VkPipelineDepthStencilStateCreateInfo depthStencilInfo =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = VK_TRUE,
.depthWriteEnable = VK_TRUE,
.depthCompareOp = VK_COMPARE_OP_LESS,
.minDepthBounds = 0.0f,
.maxDepthBounds = 1.0f,
};
VkPipelineColorBlendAttachmentState attachmentBlendState =
{
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
@ -505,7 +509,7 @@ int main(int argc, char** argv)
.pViewportState = &viewportStateInfo,
.pRasterizationState = &rasterizationInfo,
.pMultisampleState = &multisampleInfo,
.pDepthStencilState = nullptr,
.pDepthStencilState = &depthStencilInfo,
.pColorBlendState = &colorBlendStateInfo,
.pDynamicState = &dynamicStateInfo,
.layout = pipelineLayout,
@ -533,11 +537,29 @@ int main(int argc, char** argv)
VkBufferView bufferView = VK_NULL_HANDLE;
vkCreateBufferView(r_renderContext->Device(), &bufferViewInfo, nullptr, &bufferView);
struct UniformData
{
mat4 projection;
mat4 view;
};
UniformData uniformData
{
.projection = perspective(Degree(90.0f), 16.0f / 9.0f, 0.01f, 1024.0f),
.view = translate(vec3{0.0f, 0.0f, -4.0f}),
};
auto pooler = BufferPooler{ *r_buffer };
auto meshData = r_mesh->vertexData.View();
auto vertexSlice = *pooler.AllocSlice(meshData.size);
auto indexSlice = *pooler.AllocSlice(r_mesh->indices.Size() * sizeof(uint16_t));
auto uniformSlice = *pooler.AllocSlice(sizeof(UniformData));
VkDescriptorBufferInfo bufferInfo =
{
.buffer = r_buffer->buffer,
.offset = 0,
.range = r_buffer->size,
.offset = uniformSlice.offset,
.range = uniformSlice.size,
};
VkWriteDescriptorSet writeDescriptorSet[] =
@ -550,25 +572,14 @@ int main(int argc, char** argv)
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = &bufferInfo,
},
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSet,
.dstBinding = 1,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
.pTexelBufferView = &bufferView,
},
};
vkUpdateDescriptorSets(r_renderContext->Device(), Size(writeDescriptorSet), writeDescriptorSet, 0, nullptr);
auto pooler = BufferPooler{ *r_buffer };
auto meshData = r_mesh->vertexData.View();
auto vertexSlice = *pooler.AllocSlice(meshData.size);
auto indexSlice = *pooler.AllocSlice(r_mesh->indices.Size() * sizeof(uint16_t));
meshData.Copy ((uint8_t*)(r_buffer->ptr) + vertexSlice.offset);
r_mesh->indices.Copy((uint8_t*)(r_buffer->ptr) + indexSlice.offset);
memcpy((uint8_t*)(r_buffer->ptr) + uniformSlice.offset, &uniformData, sizeof(uniformData));
while (r_window->Update())
{
VkCommandBuffer cmdBuf = r_swapchain->CommandBuffer();
@ -637,7 +648,7 @@ int main(int argc, char** argv)
.pColorAttachments = &attachmentInfo,
};
vkCmdBeginRendering(cmdBuf, &renderInfo);
vkCmdDrawIndexed(cmdBuf, r_mesh->vertexData.VertexCount(), 1, 0, 0, 0);
vkCmdDrawIndexed(cmdBuf, r_mesh->indices.Size(), 1, 0, 0, 0);
vkCmdEndRendering(cmdBuf);
const VkImageMemoryBarrier colorToPresentBarrier =

View File

@ -1,12 +1,17 @@
#version 450
layout(location = 0) in vec3 inPos;
layout(location = 1) in vec2 inUV;
layout(location = 2) in vec3 inNormal;
layout(binding = 0) uniform UniformData {
mat4 projection;
mat4 view;
} u_data;
layout(location = 0) out vec4 outColor;
layout(location = 0) in vec3 i_pos;
layout(location = 1) in vec2 i_uv;
layout(location = 2) in vec3 i_normal;
vec3 colors[3] = vec3[]
layout(location = 0) out vec4 o_color;
vec3 k_colors[3] = vec3[]
(
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
@ -15,6 +20,6 @@ vec3 colors[3] = vec3[]
void main()
{
gl_Position = vec4(inPos, 1.0);
outColor = vec4(colors[gl_VertexIndex], 1.0);
gl_Position = u_data.projection * u_data.view * vec4(i_pos, 1.0);
o_color = vec4(k_colors[gl_VertexIndex % 3], 1.0);
}

View File

@ -66,6 +66,12 @@ namespace orange
return imageCount;
}
static Result<VkFormat> FindDepthFormat(VkPhysicalDevice physicalDevice)
{
return FindSupportedFormat(physicalDevice, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT);
}
Result<Swapchain> Swapchain::Create(RenderContext& context, VkSurfaceKHR surface)
{
VkSurfaceCapabilitiesKHR capabilities;
@ -166,6 +172,8 @@ namespace orange
renderFinishedSemaphores[i] = *r_renderSem;
}
// TODO: Handle failure
uint32_t imageIndex;
vkAcquireNextImageKHR(context.Device(), swapchain, ~0u, imageAvailableSemaphores[0], VK_NULL_HANDLE, &imageIndex);