~untaugh/meteormaker

b771c0995ef3961d8c87b63e96d34a2a436030ff — Oskar Rundgren 9 days ago 5e1a4a3
Outline testing.
9 files changed, 325 insertions(+), 7 deletions(-)

M CMakeLists.txt
M meteormaker.cc
A outline.frag
A outline.h
A outline.vert
M render_vulkan.cc
M render_vulkan.h
M shape.cc
M shape.frag
M CMakeLists.txt => CMakeLists.txt +1 -1
@@ 24,7 24,7 @@ target_include_directories(metmak PRIVATE Vulkan::Vulkan)
target_include_directories(metmak PRIVATE Freetype)

# Shaders
set(shaders sprite.vert sprite.frag shape.vert shape.frag
set(shaders sprite.vert sprite.frag shape.vert shape.frag outline.frag outline.vert
  text.vert text.frag text_correct.vert text_correct.frag)

foreach(shader ${shaders})

M meteormaker.cc => meteormaker.cc +0 -1
@@ 156,7 156,6 @@ void MeteorMaker::loop()
    }

    physics.run(registry, time.getSeconds());

    starSystem.run(registry);

    render.update(registry);

A outline.frag => outline.frag +17 -0
@@ 0,0 1,17 @@
#version 450
#extension  GL_ARB_separate_shader_objects : enable

layout(location = 0) out vec4 outColor;
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec3 inNormal;

void main()
{
  vec3 lightDir = normalize(vec3(1,1,0));
  vec3 norm = normalize(inNormal);
  float diff = max(dot(norm, lightDir), 0.0);
  vec3 diffuse = 0.5 * diff * vec3(1,1,1);
  vec3 result = (diffuse + 0.5) * fragColor;
  //outColor = vec4(result, 1.0);
  outColor = vec4(0.0, 0.0, 0.0, 1.0);
}

A outline.h => outline.h +187 -0
@@ 0,0 1,187 @@
#ifndef OUTLINE_H
#define OUTLINE_H

#include <vulkan/vulkan.h>

#include "shader.h"

namespace meteormaker
{

struct OutlinePipelineInfo
{
  VkDevice device;
  VkPipelineLayout layout;
  VkRenderPass pass;
  VkExtent2D extent;
};

class OutlinePipeline
{
public:
  OutlinePipeline(OutlinePipelineInfo &info)
    : device(info.device)
  {
    Shader vertShader(info.device, "outline.vert.spv");
    Shader fragShader(info.device, "outline.frag.spv");

    VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
    vertShaderStageInfo.sType =
      VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
    vertShaderStageInfo.module = vertShader.module;
    vertShaderStageInfo.pName = "main";

    VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
    fragShaderStageInfo.sType =
      VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
    fragShaderStageInfo.module = fragShader.module;
    fragShaderStageInfo.pName = "main";

    VkPipelineShaderStageCreateInfo shaderStages[] =
      {vertShaderStageInfo, fragShaderStageInfo};

    VkVertexInputBindingDescription bindingDescription = {};
    bindingDescription.binding = 0;
    bindingDescription.stride = sizeof(VertexNormal);
    bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

    VkVertexInputAttributeDescription attributeVertex = {};
    attributeVertex.binding = 0;
    attributeVertex.location = 0;
    attributeVertex.format = VK_FORMAT_R32G32B32_SFLOAT;
    attributeVertex.offset = offsetof(VertexNormal, vertex);

    VkVertexInputAttributeDescription attributeNormal = {};
    attributeNormal.binding = 0;
    attributeNormal.location = 1;
    attributeNormal.format = VK_FORMAT_R32G32B32_SFLOAT;
    attributeNormal.offset = offsetof(VertexNormal, normal);

    std::array<VkVertexInputAttributeDescription,2> attributes =
      {attributeVertex, attributeNormal};

    VkPipelineVertexInputStateCreateInfo vertexInputState = {};
    vertexInputState.sType =
      VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
    vertexInputState.vertexBindingDescriptionCount = 1;
    vertexInputState.pVertexBindingDescriptions = &bindingDescription;
    vertexInputState.vertexAttributeDescriptionCount = attributes.size();
    vertexInputState.pVertexAttributeDescriptions = attributes.data();

    VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {};
    inputAssemblyState.sType =
      VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
    inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
    inputAssemblyState.primitiveRestartEnable = VK_FALSE;

    VkViewport viewport = {};
    viewport.x = 0.0f;
    viewport.y = 0.0f;
    viewport.width = info.extent.width;
    viewport.height = info.extent.height;
    viewport.minDepth = 0.0f;
    viewport.maxDepth = 1.0f;

    VkRect2D scissor = {};
    scissor.offset = {0,0};
    scissor.extent = info.extent;

    VkPipelineViewportStateCreateInfo viewportState = {};
    viewportState.sType =
      VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
    viewportState.viewportCount = 1;
    viewportState.pViewports = &viewport;
    viewportState.scissorCount = 1;
    viewportState.pScissors = &scissor;

    VkPipelineRasterizationStateCreateInfo rasterizer = {};
    rasterizer.sType =
      VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
    rasterizer.depthClampEnable = VK_FALSE;
    rasterizer.rasterizerDiscardEnable = VK_FALSE;
    rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
    rasterizer.lineWidth = 1.0f;
    rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
    rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
    rasterizer.depthBiasEnable = VK_FALSE;
    rasterizer.depthBiasConstantFactor = 0.0f;
    rasterizer.depthBiasClamp = 0.0f;
    rasterizer.depthBiasSlopeFactor = 0.0f;

    VkPipelineMultisampleStateCreateInfo multisampling = {};
    multisampling.sType =
      VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
    multisampling.sampleShadingEnable = VK_FALSE;
    multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
    multisampling.minSampleShading = 0.0f;
    multisampling.pSampleMask = nullptr;
    multisampling.alphaToCoverageEnable = VK_FALSE;
    multisampling.alphaToOneEnable = VK_FALSE;

    VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
    colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
      VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
      VK_COLOR_COMPONENT_A_BIT;
    colorBlendAttachment.blendEnable = VK_FALSE;

    VkPipelineDepthStencilStateCreateInfo depthStencilInfo = {};
    depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
    depthStencilInfo.pNext = nullptr;
    depthStencilInfo.flags = 0;
    depthStencilInfo.depthTestEnable = VK_TRUE;
    depthStencilInfo.depthWriteEnable = VK_TRUE;
    depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS;
    depthStencilInfo.depthBoundsTestEnable = VK_FALSE;
    depthStencilInfo.stencilTestEnable = VK_FALSE;
    depthStencilInfo.front = {};
    depthStencilInfo.back = {};
    depthStencilInfo.minDepthBounds = 0.0f;
    depthStencilInfo.maxDepthBounds = 1.0f;

    VkPipelineColorBlendStateCreateInfo colorBlending = {};
    colorBlending.sType =
      VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
    colorBlending.logicOpEnable = VK_FALSE;
    colorBlending.logicOp = VK_LOGIC_OP_COPY;
    colorBlending.attachmentCount = 1;
    colorBlending.pAttachments = &colorBlendAttachment;
    colorBlending.blendConstants[0] = 0.0f;
    colorBlending.blendConstants[1] = 0.0f;
    colorBlending.blendConstants[2] = 0.0f;
    colorBlending.blendConstants[3] = 0.0f;

    VkGraphicsPipelineCreateInfo createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
    createInfo.stageCount = 2;
    createInfo.pStages = shaderStages;
    createInfo.pVertexInputState = &vertexInputState;
    createInfo.pInputAssemblyState = &inputAssemblyState;
    createInfo.pViewportState = &viewportState;
    createInfo.pRasterizationState = &rasterizer;
    createInfo.pMultisampleState = &multisampling;
    createInfo.pColorBlendState = &colorBlending;
    createInfo.layout = info.layout;
    createInfo.renderPass = info.pass;
    createInfo.subpass = 0;
    createInfo.basePipelineHandle = VK_NULL_HANDLE;
    createInfo.basePipelineIndex = -1;
    createInfo.pDepthStencilState = &depthStencilInfo;

    if(vkCreateGraphicsPipelines(info.device, VK_NULL_HANDLE, 1, &createInfo,
                                 nullptr, &pipeline) != VK_SUCCESS)
    {
      std::runtime_error("Failed to create graphics outline pipeline!");
    }
  }

  const VkPipeline &get() const { return pipeline; };

private:
  VkDevice device; /* needed in destruction */
  VkPipeline pipeline;
};

}
#endif

A outline.vert => outline.vert +27 -0
@@ 0,0 1,27 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject0 {
               mat4 view;
               mat4 proj;
} ubo0;

layout(binding = 1) uniform UniformBufferObject1 {
               mat4 model;
} ubo1;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec3 outNormal;

void main()
{
  vec4 pos = ubo0.proj * ubo0.view * ubo1.model * vec4(inPosition, 1.0);
  vec4 normal = ubo0.proj * ubo0.view * transpose(inverse(ubo1.model)) * vec4(inNormal, 1.0);
  vec2 offset = normalize(normal.xy) * 0.02 * pos.w;
  pos.xy += offset;
  gl_Position = pos;
  fragColor = vec3(1,0.5,0.5);
  outNormal = vec3(transpose(inverse(ubo1.model)) * vec4(inNormal, 1.0));
}

M render_vulkan.cc => render_vulkan.cc +37 -3
@@ 1414,9 1414,6 @@ RenderVulkan::createCommandBuffers(entt::registry &registry) const
    vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo,
                         VK_SUBPASS_CONTENTS_INLINE);

    vkCmdBindPipeline(commandBuffers[i],
                      VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

    VkBuffer vertexBuffers[] = {vertexBuffer->getBuffer()};

    VkDeviceSize offsets[] = {0};


@@ 1424,6 1421,10 @@ RenderVulkan::createCommandBuffers(entt::registry &registry) const
    vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers,
                           offsets);

    vkCmdBindPipeline(commandBuffers[i],
                      VK_PIPELINE_BIND_POINT_GRAPHICS, outlinePipeline->get());

    // repeat
    auto view = registry.view<Render,Mesh>();
    for (auto entity : view)
    {


@@ 1443,6 1444,30 @@ RenderVulkan::createCommandBuffers(entt::registry &registry) const
                vertices.count,
                1, vertices.offset/24, 0);
    }
    // end repeat

    vkCmdBindPipeline(commandBuffers[i],
                      VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

    //auto view = registry.view<Render,Mesh>();
    for (auto entity : view)
    {
      auto &render = view.get<Render>(entity);
      const auto &mesh = view.get<Mesh>(entity);
      const auto &vertices = verticesOffsets.at(mesh.id);

      uint32_t dynamicOffsets[] = {render.uboOffset *
                                   static_cast<uint32_t>(sizeof(glm::mat4))};
      vkCmdBindDescriptorSets(commandBuffers[i],
                              VK_PIPELINE_BIND_POINT_GRAPHICS,
                              pipelineLayout,
                              0, 1, &descriptorSet,
                              1,
                              dynamicOffsets);
      vkCmdDraw(commandBuffers[i],
                vertices.count,
                1, vertices.offset/24, 0);
    }

    vkCmdBindPipeline(commandBuffers[i],
                      VK_PIPELINE_BIND_POINT_GRAPHICS, spritePipeline->getPipeline());


@@ 1964,6 1989,15 @@ void RenderVulkan::initSwapchain()
  pushConstantRange.size = 4;
  pushConstantRanges.push_back(pushConstantRange);
  pipeline = createPipeline();

  OutlinePipelineInfo outlineInfo = {};
  outlineInfo.device = engine.device;
  outlineInfo.layout = pipelineLayout;
  outlineInfo.pass = renderPass;
  outlineInfo.extent = engine.extent;

  outlinePipeline = std::unique_ptr<OutlinePipeline>(new OutlinePipeline(outlineInfo));

  spritePipeline = std::unique_ptr<SpritePipeline>(new SpritePipeline(engine.device,
                                                                      engine.extent,
                                                                      renderPass));

M render_vulkan.h => render_vulkan.h +2 -0
@@ 13,6 13,7 @@
#include "shape.h"
#include "text_pipeline.h"
#include "sprite_pipeline.h"
#include "outline.h"
#include "buffer.h"
#include "text_glyphs.h"
#include "text_render.h"


@@ 102,6 103,7 @@ private:
  VkDescriptorSetLayout descriptorSetLayout;
  VkPipelineLayout pipelineLayout;
  VkPipeline pipeline;
  std::unique_ptr<OutlinePipeline> outlinePipeline;
  std::unique_ptr<Buffer> vertexBuffer;
  std::map<uint32_t, Vertices> verticesOffsets;
  std::unique_ptr<Buffer> modelBuffer;

M shape.cc => shape.cc +52 -1
@@ 49,6 49,55 @@ void Shape::generate()
{
  outVertices.clear();
  outFaces.clear();

  std::vector<Vertex> normals(vertices.size());

  for (auto &n : normals)
  {
    n.x = 0.0;
    n.y = 0.0;
    n.z = 0.0;
  }

  for (const auto &face : faces)
  {
    auto v0 = vertices[face[0]];
    auto v1 = vertices[face[1]];
    auto v2 = vertices[face[2]];

    Vertex normal = (v1 - v0).cross(v2 - v0).normalize();

    for (size_t i=0; i<3; i++)
    {
      uint32_t v = face[i];

      //std::cout << vertices[v] << "("<< normal << ") : " << normals[v] << " -> ";

      normals[v] = normals[v] + normal;
      // if (normals[v].x == 0.0 &&
      //     normals[v].y == 0.0 &&
      //     normals[v].z == 0.0)
      // {
      //   normals[v] = normal;
      // }
      // else
      // {
      //   normals[v] = normals[v].mid(normal);
      // }

      //std::cout << normals[v] << std::endl;;
    }
  }
  for (auto &n : normals)
  {
    n.normalize();
  }

  for (size_t i=0; i<vertices.size(); i++)
  {
    //std::cout << vertices[i] << " : " << normals[i] << std::endl;
  }

  for (const auto &face : faces)
  {
    auto v0 = vertices[face[0]];


@@ 61,7 110,9 @@ void Shape::generate()
    {
      VertexNormal vn;
      vn.vertex = vertices[face[i]];
      vn.normal = normal;
      //vn.normal = normal;
      (void)normal;
      vn.normal = normals[face[i]];
      outVertices.push_back(vn);
    }
    Face outFace = {outVertices.size() - 3,

M shape.frag => shape.frag +2 -1
@@ 12,5 12,6 @@ void main()
  float diff = max(dot(norm, lightDir), 0.0);
  vec3 diffuse = 0.5 * diff * vec3(1,1,1);
  vec3 result = (diffuse + 0.5) * fragColor;
  outColor = vec4(result, 1.0);
  //outColor = vec4(result, 1.0);
  outColor = vec4(0.1, 0.5, 0.7, 1.0);
}