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. 50
      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
shaders/shader.vert
shaders/shader.geom
shaders/shader.frag
)

25
shaders/shader.frag

@ -1,9 +1,28 @@
#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() {
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 {
mat4 scene_from_model;
mat4 projection_from_scene;
vec2 screen_size;
float lod;
} uniforms;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 0) in vec3 in_position;
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() {
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.scene_from_model *
vec4(inPosition, 1.0);
fragColor = inColor;
vec4(position, 1.0);
out_normal = in_normal;
out_color = in_color;
gl_Position = out_position;
}

50
src/Planet.cpp

@ -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,18 +106,48 @@ 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;
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 };
}
}
}
}
Real Cell::height_factor(Vector3 corners[CornerCount]) {
@ -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

@ -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];

8
src/Vulkan/Context.cpp

@ -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;

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 {
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}, {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}, {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}},
};
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()),

2
src/VulkanTutorial.h

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

Loading…
Cancel
Save