Browse Source

Wireframe rendering.

master
Draklaw 4 years ago
parent
commit
906290edfa
  1. 1
      CMakeLists.txt
  2. 25
      shaders/shader.frag
  3. 49
      shaders/shader.geom
  4. 26
      shaders/shader.vert
  5. 54
      src/Planet.cpp
  6. 10
      src/Planet.h
  7. 8
      src/Vulkan/Context.cpp
  8. 122
      src/VulkanTutorial.cpp
  9. 2
      src/VulkanTutorial.h

1
CMakeLists.txt

@ -42,6 +42,7 @@ add_executable(vk_expe
add_shaders(vk_expe add_shaders(vk_expe
shaders/shader.vert shaders/shader.vert
shaders/shader.geom
shaders/shader.frag shaders/shader.frag
) )

25
shaders/shader.frag

@ -1,9 +1,28 @@
#version 450 #version 450
layout(location = 0) in vec3 fragColor; layout(location = 1) in vec3 in_normal;
layout(location = 2) in vec3 in_color;
layout(location = 3) in vec3 in_edge_dist;
layout(location = 0) out vec4 outColor; layout(location = 0) out vec4 out_color;
void main() { void main() {
outColor = vec4(fragColor, 1.0); vec3 edge_dist = vec3(0.75) - in_edge_dist;
float edge = clamp(
max(edge_dist[0], max(edge_dist[1], edge_dist[2])),
0.0, 1.0
);
vec3 edge_color = vec3(1.0);
vec3 light_dir = normalize(vec3(-0.2, -0.1, -1.0));
vec3 color = in_color;
// vec3 normal = normalize(in_normal);
// color *= clamp(
// dot(normal, light_dir),
// 0.0, 1.0
// );
out_color = vec4(mix(color, edge_color, edge), 1.0);
} }

49
shaders/shader.geom

@ -0,0 +1,49 @@
#version 450
layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;
layout(binding = 0) uniform Uniforms {
mat4 scene_from_model;
mat4 projection_from_scene;
vec2 half_screen_size;
float lod;
} uniforms;
layout(location = 0) in vec4 in_position[3];
layout(location = 1) in vec3 in_normal[3];
layout(location = 2) in vec3 in_color[3];
layout(location = 0) out vec4 out_position;
layout(location = 1) out vec3 out_normal;
layout(location = 2) out vec3 out_color;
layout(location = 3) noperspective out vec3 out_edge_dist;
void main() {
vec2 positions[3] = {
uniforms.half_screen_size * gl_in[0].gl_Position.xy / gl_in[0].gl_Position.w,
uniforms.half_screen_size * gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w,
uniforms.half_screen_size * gl_in[2].gl_Position.xy / gl_in[2].gl_Position.w,
};
for(int i = 0; i < 3; i += 1) {
gl_Position = gl_in[i].gl_Position;
out_position = in_position[i];
out_normal = in_normal[i];
out_color = in_color[i];
out_edge_dist = vec3(0.0);
vec2 p0 = positions[(i + 0) % 3];
vec2 p1 = positions[(i + 1) % 3];
vec2 p2 = positions[(i + 2) % 3];
// vec2 v21 = p2 - p1;
// out_edge_dist[i] = (p1.x * v21.x + p1.y * v21.y) / dot(v21, v21);
vec2 v0 = p0 - p2;
vec2 v1 = p1 - p2;
out_edge_dist[i] = determinant(mat2(v0, v1)) / length(v1);
EmitVertex();
}
}

26
shaders/shader.vert

@ -3,17 +3,31 @@
layout(binding = 0) uniform Uniforms { layout(binding = 0) uniform Uniforms {
mat4 scene_from_model; mat4 scene_from_model;
mat4 projection_from_scene; mat4 projection_from_scene;
vec2 screen_size;
float lod;
} uniforms; } uniforms;
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 in_position;
layout(location = 1) in vec3 inColor; layout(location = 1) in vec3 in_position2;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in vec3 in_color;
layout(location = 0) out vec3 fragColor; layout(location = 0) out vec4 out_position;
layout(location = 1) out vec3 out_normal;
layout(location = 2) out vec3 out_color;
void main() { void main() {
gl_Position = float lod = clamp(
2.0 * dot(transpose(uniforms.scene_from_model)[0].xyz, in_position) + 0.5,
0.0, 1.0
);
vec3 position = mix(in_position2, in_position, lod);
out_position =
uniforms.projection_from_scene * uniforms.projection_from_scene *
uniforms.scene_from_model * uniforms.scene_from_model *
vec4(inPosition, 1.0); vec4(position, 1.0);
fragColor = inColor; out_normal = in_normal;
out_color = in_color;
gl_Position = out_position;
} }

54
src/Planet.cpp

@ -38,7 +38,7 @@ size_t Cell::triangle_count(uint32_t subdiv_count) {
} }
void Cell::build_mesh( void Cell::build_mesh(
Vector3AV positions, TriangleAV triangles, Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
uint32_t subdiv_count, Index index_offset uint32_t subdiv_count, Index index_offset
) const { ) const {
auto const side_edge_count = (1u << subdiv_count); 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 { auto const index = [side_vert_count](uint32_t x, uint32_t y) -> uint32_t {
return x + y * side_vert_count; return x + y * side_vert_count;
}; };
auto const vertex = [&positions, &index](uint32_t x, uint32_t y) -> Vector3& { auto const vertex = [&normals, &index](uint32_t x, uint32_t y) -> Vector3& {
return positions[index(x, y)]; return normals[index(x, y)];
}; };
vertex( 0, 0) = m_corners[0]; 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; auto triangleIndex = 0;
for(uint32_t y = 0; y < side_edge_count; y += 1) { bool flip = false; // (x_offset > 0) ^ (y_offset > 0);
for(uint32_t x = 0; x < side_edge_count; x += 1) { 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 i00 = index_offset + index(x, y);
const auto i01 = i00 + 1; const auto i01 = i00 + 1;
const auto i10 = i00 + side_vert_count; const auto i10 = i00 + side_vert_count;
const auto i11 = i10 + 1; const auto i11 = i10 + 1;
triangles[triangleIndex++] = Triangle { i00, i01, i10 }; if (flip) {
triangles[triangleIndex++] = Triangle { i10, i01, i11 }; 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( void Planet::build_mesh(
Vector3AV positions, TriangleAV triangles, Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
uint32_t subdiv_count, Index index_offset uint32_t subdiv_count, Index index_offset
) const { ) const {
auto const vertex_count = Cell::vertex_count(subdiv_count); auto const vertex_count = Cell::vertex_count(subdiv_count);
@ -179,11 +209,19 @@ void Planet::build_mesh(
auto sub_positions = positions.slice( auto sub_positions = positions.slice(
cell_index * vertex_count, vertex_count 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( auto sub_triangles = triangles.slice(
cell_index * index_count, index_count cell_index * index_count, index_count
); );
cell(cell_index).build_mesh( cell(cell_index).build_mesh(
sub_positions, sub_positions,
sub_positions2,
sub_normals,
sub_triangles, sub_triangles,
subdiv_count, subdiv_count,
index_offset + cell_index * vertex_count index_offset + cell_index * vertex_count

10
src/Planet.h

@ -12,6 +12,8 @@ using CellUP = std::unique_ptr<Cell>;
struct Vertex { struct Vertex {
Vector3 position; Vector3 position;
Vector3 position2;
Vector3 normal;
Vector3 color; Vector3 color;
}; };
@ -41,7 +43,7 @@ public:
static size_t triangle_count(uint32_t subdiv_count); static size_t triangle_count(uint32_t subdiv_count);
void build_mesh( void build_mesh(
Vector3AV positions, TriangleAV triangles, Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
uint32_t subdiv_count=4, Index index_offset=0 uint32_t subdiv_count=4, Index index_offset=0
) const; ) const;
@ -78,8 +80,10 @@ public:
return m_cells[cell_index]; return m_cells[cell_index];
} }
void build_mesh(Vector3AV positions, TriangleAV triangles, void build_mesh(
uint32_t subdiv_count=4, Index index_offset=0) const; Vector3AV positions, Vector3AV positions2, Vector3AV normals, TriangleAV triangles,
uint32_t subdiv_count=4, Index index_offset=0
) const;
private: private:
Cell m_cells[CellCount]; Cell m_cells[CellCount];

8
src/Vulkan/Context.cpp

@ -737,6 +737,13 @@ std::optional<VkPhysicalDeviceProperties> Context::select_physical_device(
VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceProperties device_properties;
vkGetPhysicalDeviceProperties(physical_device, &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_transfer_queue_index = settings.queues().size();
m_queue_families.assign(settings.queues().size() + 1, INVALID_QUEUE_FAMILY); m_queue_families.assign(settings.queues().size() + 1, INVALID_QUEUE_FAMILY);
m_presentation_queue_family = 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 { VkPhysicalDeviceFeatures const device_features {
.geometryShader = true,
}; };
std::vector<const char*> extensions; std::vector<const char*> extensions;

122
src/VulkanTutorial.cpp

@ -24,7 +24,7 @@ VkVertexInputBindingDescription vertex_binding_description() {
}; };
} }
std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description() { std::array<VkVertexInputAttributeDescription, 4> vertex_attributes_description() {
return { return {
VkVertexInputAttributeDescription { VkVertexInputAttributeDescription {
.location = 0, .location = 0,
@ -32,10 +32,22 @@ std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description()
.format = VK_FORMAT_R32G32B32_SFLOAT, .format = VK_FORMAT_R32G32B32_SFLOAT,
.offset = offsetof(Vertex, position), .offset = offsetof(Vertex, position),
}, },
{ VkVertexInputAttributeDescription {
.location = 1, .location = 1,
.binding = 0, .binding = 0,
.format = VK_FORMAT_R32G32B32_SFLOAT, .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), .offset = offsetof(Vertex, color),
}, },
}; };
@ -43,40 +55,42 @@ std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description()
std::vector<Vertex> vertices = { std::vector<Vertex> vertices = {
{{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.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, 1.0f, 0.0f}},
{{-0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.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, 1.0f, 1.0f}},
{{-0.5f, -0.5f, 0.5f}, {0.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, 0.0f, 1.0f}},
{{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 0.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.2f, 0.2f, 0.2f}},
}; };
std::vector<uint32_t> indices = { std::vector<uint32_t> indices = {
0, 1, 2, // 0, 1, 2,
2, 1, 3, // 2, 1, 3,
1, 5, 3, // 1, 5, 3,
3, 5, 7, // 3, 5, 7,
5, 4, 7, // 5, 4, 7,
7, 4, 6, // 7, 4, 6,
4, 0, 6, // 4, 0, 6,
6, 0, 2, // 6, 0, 2,
0, 4, 1, // 0, 4, 1,
1, 4, 5, // 1, 4, 5,
2, 3, 6, // 2, 3, 6,
6, 3, 7, // 6, 3, 7,
}; };
struct Uniforms { struct Uniforms {
alignas(16) Eigen::Matrix4f scene_from_model; alignas(16) Eigen::Matrix4f scene_from_model;
alignas(16) Eigen::Matrix4f projection_from_scene; 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)); vertices.resize(6 * Cell::vertex_count(subdiv_count));
indices.resize(6 * 3 * Cell::triangle_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( Vector3AV positions(
vertices.size(), vertices.data(), vertices.size(), vertices.data(),
sizeof(Vertex), offsetof(Vertex, position) 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( Vector3AV colors(
vertices.size(), vertices.data(), vertices.size(), vertices.data(),
sizeof(Vertex), offsetof(Vertex, color) sizeof(Vertex), offsetof(Vertex, color)
@ -120,7 +131,7 @@ VulkanTutorial::VulkanTutorial() {
); );
Planet planet; 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) { for (size_t vertex_index = 0; vertex_index < vertices.size(); vertex_index += 1) {
colors[vertex_index] = colors[vertex_index] =
@ -195,7 +206,7 @@ void VulkanTutorial::draw_frame() {
} }
m_last_frame_time = now; 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 float dist = 2.0f;
const Eigen::Matrix4f view = look_at_matrix( const Eigen::Matrix4f view = look_at_matrix(
// Eigen::Vector3f(0.0f, 0.0f, -dist), // Eigen::Vector3f(0.0f, 0.0f, -dist),
@ -226,6 +237,11 @@ void VulkanTutorial::draw_frame() {
const Uniforms uniforms = { const Uniforms uniforms = {
.scene_from_model = model.matrix(), .scene_from_model = model.matrix(),
.projection_from_scene = proj * view, .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; void* uniform_buffer;
@ -381,7 +397,7 @@ void VulkanTutorial::create_descriptor_set_layout() {
.binding = 0, .binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1, .descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT, .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
}; };
VkDescriptorSetLayoutCreateInfo layout_info { VkDescriptorSetLayoutCreateInfo layout_info {
@ -405,6 +421,12 @@ void VulkanTutorial::create_graphic_pipeline() {
vkDestroyShaderModule(m_context.device(), vertex_shader_module, nullptr); 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 = auto const fragment_shader_module =
m_context.create_shader_module_from_file("shaders/shader.frag.spv"); m_context.create_shader_module_from_file("shaders/shader.frag.spv");
auto const fragment_shader_guard = make_guard([&]{ auto const fragment_shader_guard = make_guard([&]{
@ -418,6 +440,12 @@ void VulkanTutorial::create_graphic_pipeline() {
.module = vertex_shader_module, .module = vertex_shader_module,
.pName = "main", .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, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT, .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
@ -534,7 +562,7 @@ void VulkanTutorial::create_graphic_pipeline() {
VkGraphicsPipelineCreateInfo pipeline_info { VkGraphicsPipelineCreateInfo pipeline_info {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.stageCount = 2, .stageCount = 3,
.pStages = shader_stage_infos, .pStages = shader_stage_infos,
.pVertexInputState = &vertex_info, .pVertexInputState = &vertex_info,
.pInputAssemblyState = &assembly_info, .pInputAssemblyState = &assembly_info,
@ -819,6 +847,13 @@ void VulkanTutorial::create_command_buffers() {
offsets offsets
); );
vkCmdBindIndexBuffer(
command_buffer,
m_index_buffer,
0,
VK_INDEX_TYPE_UINT32
);
vkCmdBindDescriptorSets( vkCmdBindDescriptorSets(
command_buffer, command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_GRAPHICS,
@ -827,13 +862,6 @@ void VulkanTutorial::create_command_buffers() {
0, nullptr 0, nullptr
); );
vkCmdBindIndexBuffer(
command_buffer,
m_index_buffer,
0,
VK_INDEX_TYPE_UINT32
);
vkCmdDrawIndexed( vkCmdDrawIndexed(
command_buffer, command_buffer,
uint32_t(indices.size()), uint32_t(indices.size()),

2
src/VulkanTutorial.h

@ -11,7 +11,7 @@
VkVertexInputBindingDescription vertex_binding_description(); VkVertexInputBindingDescription vertex_binding_description();
std::array<VkVertexInputAttributeDescription, 2> vertex_attributes_description(); std::array<VkVertexInputAttributeDescription, 4> vertex_attributes_description();
class VulkanTutorial { class VulkanTutorial {

Loading…
Cancel
Save