Wireframe rendering.
This commit is contained in:
@@ -38,7 +38,7 @@ size_t Cell::triangle_count(uint32_t subdiv_count) {
|
||||
}
|
||||
|
||||
void Cell::build_mesh(
|
||||
Vector3AV positions, TriangleAV triangles,
|
||||
Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
|
||||
uint32_t subdiv_count, Index index_offset
|
||||
) const {
|
||||
auto const side_edge_count = (1u << subdiv_count);
|
||||
@@ -54,8 +54,8 @@ void Cell::build_mesh(
|
||||
auto const index = [side_vert_count](uint32_t x, uint32_t y) -> uint32_t {
|
||||
return x + y * side_vert_count;
|
||||
};
|
||||
auto const vertex = [&positions, &index](uint32_t x, uint32_t y) -> Vector3& {
|
||||
return positions[index(x, y)];
|
||||
auto const vertex = [&normals, &index](uint32_t x, uint32_t y) -> Vector3& {
|
||||
return normals[index(x, y)];
|
||||
};
|
||||
|
||||
vertex( 0, 0) = m_corners[0];
|
||||
@@ -106,16 +106,46 @@ void Cell::build_mesh(
|
||||
}
|
||||
}
|
||||
|
||||
for (Index index = 0; index < normals.size(); index += 1) {
|
||||
positions[index] = normals[index];
|
||||
}
|
||||
|
||||
int x_offset = (
|
||||
m_corners[0][0] < m_corners[1][0] ||
|
||||
m_corners[0][1] < m_corners[1][1] ||
|
||||
m_corners[0][2] < m_corners[1][2]
|
||||
)? -1: 1;
|
||||
int y_offset = (
|
||||
m_corners[0][0] < m_corners[2][0] ||
|
||||
m_corners[0][1] < m_corners[2][1] ||
|
||||
m_corners[0][2] < m_corners[2][2]
|
||||
)? -1: 1;
|
||||
for(Index y = 0; y < side_vert_count; y += 1) {
|
||||
for(Index x = 0; x < side_vert_count; x += 1) {
|
||||
Index x2 = x + (x & 0x01) * x_offset;
|
||||
Index y2 = y + (y & 0x01) * y_offset;
|
||||
|
||||
positions2[index(x, y)] = positions[index(x2, y2)];
|
||||
}
|
||||
}
|
||||
|
||||
auto triangleIndex = 0;
|
||||
for(uint32_t y = 0; y < side_edge_count; y += 1) {
|
||||
for(uint32_t x = 0; x < side_edge_count; x += 1) {
|
||||
bool flip = false; // (x_offset > 0) ^ (y_offset > 0);
|
||||
for(Index y = 0; y < side_edge_count; y += 1) {
|
||||
for(Index x = 0; x < side_edge_count; x += 1) {
|
||||
const auto i00 = index_offset + index(x, y);
|
||||
const auto i01 = i00 + 1;
|
||||
const auto i10 = i00 + side_vert_count;
|
||||
const auto i11 = i10 + 1;
|
||||
|
||||
triangles[triangleIndex++] = Triangle { i00, i01, i10 };
|
||||
triangles[triangleIndex++] = Triangle { i10, i01, i11 };
|
||||
if (flip) {
|
||||
triangles[triangleIndex++] = Triangle { i00, i01, i11 };
|
||||
triangles[triangleIndex++] = Triangle { i00, i11, i10 };
|
||||
}
|
||||
else {
|
||||
triangles[triangleIndex++] = Triangle { i00, i01, i10 };
|
||||
triangles[triangleIndex++] = Triangle { i10, i01, i11 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,7 +199,7 @@ Planet::Planet()
|
||||
{}
|
||||
|
||||
void Planet::build_mesh(
|
||||
Vector3AV positions, TriangleAV triangles,
|
||||
Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
|
||||
uint32_t subdiv_count, Index index_offset
|
||||
) const {
|
||||
auto const vertex_count = Cell::vertex_count(subdiv_count);
|
||||
@@ -179,11 +209,19 @@ void Planet::build_mesh(
|
||||
auto sub_positions = positions.slice(
|
||||
cell_index * vertex_count, vertex_count
|
||||
);
|
||||
auto sub_positions2 = positions2.slice(
|
||||
cell_index * vertex_count, vertex_count
|
||||
);
|
||||
auto sub_normals = normals.slice(
|
||||
cell_index * vertex_count, vertex_count
|
||||
);
|
||||
auto sub_triangles = triangles.slice(
|
||||
cell_index * index_count, index_count
|
||||
);
|
||||
cell(cell_index).build_mesh(
|
||||
sub_positions,
|
||||
sub_positions2,
|
||||
sub_normals,
|
||||
sub_triangles,
|
||||
subdiv_count,
|
||||
index_offset + cell_index * vertex_count
|
||||
|
||||
10
src/Planet.h
10
src/Planet.h
@@ -12,6 +12,8 @@ using CellUP = std::unique_ptr<Cell>;
|
||||
|
||||
struct Vertex {
|
||||
Vector3 position;
|
||||
Vector3 position2;
|
||||
Vector3 normal;
|
||||
Vector3 color;
|
||||
};
|
||||
|
||||
@@ -41,7 +43,7 @@ public:
|
||||
static size_t triangle_count(uint32_t subdiv_count);
|
||||
|
||||
void build_mesh(
|
||||
Vector3AV positions, TriangleAV triangles,
|
||||
Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
|
||||
uint32_t subdiv_count=4, Index index_offset=0
|
||||
) const;
|
||||
|
||||
@@ -78,8 +80,10 @@ public:
|
||||
return m_cells[cell_index];
|
||||
}
|
||||
|
||||
void build_mesh(Vector3AV positions, TriangleAV triangles,
|
||||
uint32_t subdiv_count=4, Index index_offset=0) const;
|
||||
void build_mesh(
|
||||
Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
|
||||
uint32_t subdiv_count=4, Index index_offset=0
|
||||
) const;
|
||||
|
||||
private:
|
||||
Cell m_cells[CellCount];
|
||||
|
||||
@@ -737,6 +737,13 @@ std::optional<VkPhysicalDeviceProperties> Context::select_physical_device(
|
||||
VkPhysicalDeviceProperties device_properties;
|
||||
vkGetPhysicalDeviceProperties(physical_device, &device_properties);
|
||||
|
||||
VkPhysicalDeviceFeatures available_features;
|
||||
vkGetPhysicalDeviceFeatures(physical_device, &available_features);
|
||||
|
||||
if (!available_features.geometryShader)
|
||||
return std::nullopt;
|
||||
|
||||
|
||||
m_transfer_queue_index = settings.queues().size();
|
||||
m_queue_families.assign(settings.queues().size() + 1, INVALID_QUEUE_FAMILY);
|
||||
m_presentation_queue_family = INVALID_QUEUE_FAMILY;
|
||||
@@ -841,6 +848,7 @@ void Context::create_device(const ContextSettings& settings) {
|
||||
}
|
||||
|
||||
VkPhysicalDeviceFeatures const device_features {
|
||||
.geometryShader = true,
|
||||
};
|
||||
|
||||
std::vector<const char*> extensions;
|
||||
|
||||
@@ -24,7 +24,7 @@ VkVertexInputBindingDescription vertex_binding_description() {
|
||||
};
|
||||
}
|
||||
|
||||
std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description() {
|
||||
std::array<VkVertexInputAttributeDescription, 4> vertex_attributes_description() {
|
||||
return {
|
||||
VkVertexInputAttributeDescription {
|
||||
.location = 0,
|
||||
@@ -32,10 +32,22 @@ std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description()
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(Vertex, position),
|
||||
},
|
||||
{
|
||||
VkVertexInputAttributeDescription {
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(Vertex, position2),
|
||||
},
|
||||
VkVertexInputAttributeDescription {
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(Vertex, normal),
|
||||
},
|
||||
{
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.offset = offsetof(Vertex, color),
|
||||
},
|
||||
};
|
||||
@@ -43,40 +55,42 @@ std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description()
|
||||
|
||||
|
||||
std::vector<Vertex> vertices = {
|
||||
{{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
{{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{-0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
{{0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}},
|
||||
// {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
// {{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
// {{-0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
// {{0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}},
|
||||
|
||||
{{-0.5f, -0.5f, 0.5f}, {0.0f, 1.0f, 1.0f}},
|
||||
{{0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 0.0f}},
|
||||
{{0.5f, 0.5f, 0.5f}, {0.2f, 0.2f, 0.2f}},
|
||||
// {{-0.5f, -0.5f, 0.5f}, {0.0f, 1.0f, 1.0f}},
|
||||
// {{0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 1.0f}},
|
||||
// {{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 0.0f}},
|
||||
// {{0.5f, 0.5f, 0.5f}, {0.2f, 0.2f, 0.2f}},
|
||||
};
|
||||
|
||||
std::vector<uint32_t> indices = {
|
||||
0, 1, 2,
|
||||
2, 1, 3,
|
||||
// 0, 1, 2,
|
||||
// 2, 1, 3,
|
||||
|
||||
1, 5, 3,
|
||||
3, 5, 7,
|
||||
// 1, 5, 3,
|
||||
// 3, 5, 7,
|
||||
|
||||
5, 4, 7,
|
||||
7, 4, 6,
|
||||
// 5, 4, 7,
|
||||
// 7, 4, 6,
|
||||
|
||||
4, 0, 6,
|
||||
6, 0, 2,
|
||||
// 4, 0, 6,
|
||||
// 6, 0, 2,
|
||||
|
||||
0, 4, 1,
|
||||
1, 4, 5,
|
||||
// 0, 4, 1,
|
||||
// 1, 4, 5,
|
||||
|
||||
2, 3, 6,
|
||||
6, 3, 7,
|
||||
// 2, 3, 6,
|
||||
// 6, 3, 7,
|
||||
};
|
||||
|
||||
struct Uniforms {
|
||||
alignas(16) Eigen::Matrix4f scene_from_model;
|
||||
alignas(16) Eigen::Matrix4f projection_from_scene;
|
||||
alignas(8) Eigen::Vector2f half_screen_size;
|
||||
alignas(4) float lod;
|
||||
};
|
||||
|
||||
|
||||
@@ -91,24 +105,21 @@ VulkanTutorial::VulkanTutorial() {
|
||||
vertices.resize(6 * Cell::vertex_count(subdiv_count));
|
||||
indices.resize(6 * 3 * Cell::triangle_count(subdiv_count));
|
||||
|
||||
// MeshView mesh(
|
||||
// vertices.size(),
|
||||
// reinterpret_cast<Byte*>(vertices.data()) + offsetof(Vertex, position),
|
||||
// sizeof(Vertex),
|
||||
// nullptr,
|
||||
// sizeof(Vertex),
|
||||
// reinterpret_cast<Byte*>(vertices.data()) + offsetof(Vertex, color),
|
||||
// sizeof(Vertex),
|
||||
// indices.size(),
|
||||
// reinterpret_cast<Byte*>(indices.data()),
|
||||
// sizeof(Index)
|
||||
// );
|
||||
|
||||
Vector3AV positions(
|
||||
vertices.size(), vertices.data(),
|
||||
sizeof(Vertex), offsetof(Vertex, position)
|
||||
);
|
||||
|
||||
Vector3AV positions2(
|
||||
vertices.size(), vertices.data(),
|
||||
sizeof(Vertex), offsetof(Vertex, position2)
|
||||
);
|
||||
|
||||
Vector3AV normals(
|
||||
vertices.size(), vertices.data(),
|
||||
sizeof(Vertex), offsetof(Vertex, normal)
|
||||
);
|
||||
|
||||
Vector3AV colors(
|
||||
vertices.size(), vertices.data(),
|
||||
sizeof(Vertex), offsetof(Vertex, color)
|
||||
@@ -120,7 +131,7 @@ VulkanTutorial::VulkanTutorial() {
|
||||
);
|
||||
|
||||
Planet planet;
|
||||
planet.build_mesh(positions, triangles, subdiv_count);
|
||||
planet.build_mesh(positions, positions2, normals, triangles, subdiv_count);
|
||||
|
||||
for (size_t vertex_index = 0; vertex_index < vertices.size(); vertex_index += 1) {
|
||||
colors[vertex_index] =
|
||||
@@ -195,7 +206,7 @@ void VulkanTutorial::draw_frame() {
|
||||
}
|
||||
m_last_frame_time = now;
|
||||
|
||||
const float alpha = SecondsD(m_time).count() * (2.0 * M_PI) / 3.0;
|
||||
const float alpha = SecondsD(m_time).count() * (2.0 * M_PI) / 10.0;
|
||||
const float dist = 2.0f;
|
||||
const Eigen::Matrix4f view = look_at_matrix(
|
||||
// Eigen::Vector3f(0.0f, 0.0f, -dist),
|
||||
@@ -226,6 +237,11 @@ void VulkanTutorial::draw_frame() {
|
||||
const Uniforms uniforms = {
|
||||
.scene_from_model = model.matrix(),
|
||||
.projection_from_scene = proj * view,
|
||||
.half_screen_size = {
|
||||
0.5 * m_swapchain.extent().width,
|
||||
0.5 * m_swapchain.extent().height,
|
||||
},
|
||||
.lod = std::cos(alpha) * 0.5f + 0.5f,
|
||||
};
|
||||
|
||||
void* uniform_buffer;
|
||||
@@ -381,7 +397,7 @@ void VulkanTutorial::create_descriptor_set_layout() {
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||
};
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo layout_info {
|
||||
@@ -405,6 +421,12 @@ void VulkanTutorial::create_graphic_pipeline() {
|
||||
vkDestroyShaderModule(m_context.device(), vertex_shader_module, nullptr);
|
||||
});
|
||||
|
||||
auto const geometry_shader_module =
|
||||
m_context.create_shader_module_from_file("shaders/shader.geom.spv");
|
||||
auto const geometry_shader_guard = make_guard([&]{
|
||||
vkDestroyShaderModule(m_context.device(), geometry_shader_module, nullptr);
|
||||
});
|
||||
|
||||
auto const fragment_shader_module =
|
||||
m_context.create_shader_module_from_file("shaders/shader.frag.spv");
|
||||
auto const fragment_shader_guard = make_guard([&]{
|
||||
@@ -418,6 +440,12 @@ void VulkanTutorial::create_graphic_pipeline() {
|
||||
.module = vertex_shader_module,
|
||||
.pName = "main",
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||
.module = geometry_shader_module,
|
||||
.pName = "main",
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
@@ -534,7 +562,7 @@ void VulkanTutorial::create_graphic_pipeline() {
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipeline_info {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.stageCount = 2,
|
||||
.stageCount = 3,
|
||||
.pStages = shader_stage_infos,
|
||||
.pVertexInputState = &vertex_info,
|
||||
.pInputAssemblyState = &assembly_info,
|
||||
@@ -819,6 +847,13 @@ void VulkanTutorial::create_command_buffers() {
|
||||
offsets
|
||||
);
|
||||
|
||||
vkCmdBindIndexBuffer(
|
||||
command_buffer,
|
||||
m_index_buffer,
|
||||
0,
|
||||
VK_INDEX_TYPE_UINT32
|
||||
);
|
||||
|
||||
vkCmdBindDescriptorSets(
|
||||
command_buffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
@@ -827,13 +862,6 @@ void VulkanTutorial::create_command_buffers() {
|
||||
0, nullptr
|
||||
);
|
||||
|
||||
vkCmdBindIndexBuffer(
|
||||
command_buffer,
|
||||
m_index_buffer,
|
||||
0,
|
||||
VK_INDEX_TYPE_UINT32
|
||||
);
|
||||
|
||||
vkCmdDrawIndexed(
|
||||
command_buffer,
|
||||
uint32_t(indices.size()),
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
|
||||
VkVertexInputBindingDescription vertex_binding_description();
|
||||
std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description();
|
||||
std::array<VkVertexInputAttributeDescription, 4> vertex_attributes_description();
|
||||
|
||||
|
||||
class VulkanTutorial {
|
||||
|
||||
Reference in New Issue
Block a user