diff src/engine.nim @ 17:b40466fa446a

add: vertex basics, some refactoring
author Sam <sam@basx.dev>
date Sun, 01 Jan 2023 01:00:50 +0700
parents 3415afff1d1a
children 90e117952f74
line wrap: on
line diff
--- a/src/engine.nim	Fri Dec 30 15:56:17 2022 +0700
+++ b/src/engine.nim	Sun Jan 01 01:00:50 2023 +0700
@@ -8,6 +8,9 @@
 import ./vulkan_helpers
 import ./window
 import ./events
+import ./math/vector
+import ./shader
+import ./vertex
 
 import ./glslang/glslang
 
@@ -18,24 +21,56 @@
 addHandler(logger)
 
 
-var vertexShaderCode: string = """#version 450
+type
+  MyVertex = object
+    position: VertexAttribute[Vec2[float32]]
+    color: VertexAttribute[Vec3[float32]]
+
+const vertices = [
+    (Vec2([ 0.0'f32, -0.5'f32]), Vec3([1.0'f32, 0.0'f32, 0.0'f32])),
+    (Vec2([ 0.5'f32,  0.5'f32]), Vec3([0.0'f32, 1.0'f32, 0.0'f32])),
+    (Vec2([-0.5'f32,  0.5'f32]), Vec3([0.0'f32, 0.0'f32, 1.0'f32]))
+]
+
+
+proc getBindingDescription(binding: int): auto =
+  VkVertexInputBindingDescription(
+    binding: uint32(binding),
+    stride: uint32(sizeof(vertices[0])),
+    inputRate: VK_VERTEX_INPUT_RATE_VERTEX, # VK_VERTEX_INPUT_RATE_INSTANCE for instances
+  )
+
+proc getAttributeDescriptions(binding: int): auto =
+  [
+    VkVertexInputAttributeDescription(
+      binding: 0'u32,
+      location: 0,
+      format: VK_FORMAT_R32G32_SFLOAT,
+      offset: 0,
+    ),
+    VkVertexInputAttributeDescription(
+      binding: 0'u32,
+      location: 1,
+      format: VK_FORMAT_R32G32B32_SFLOAT,
+      offset: uint32(sizeof(Vec2)), # use offsetOf?
+    ),
+  ]
+
+var vertexShaderCode = """
+#version 450
+
+layout(location = 0) in vec2 inPosition;
+layout(location = 1) in vec3 inColor;
+
 layout(location = 0) out vec3 fragColor;
-vec3 colors[3] = vec3[](
-    vec3(1.0, 0.0, 0.0),
-    vec3(0.0, 1.0, 0.0),
-    vec3(0.0, 0.0, 1.0)
-);
-vec2 positions[3] = vec2[](
-  vec2(0.0, -0.5),
-  vec2(0.5, 0.5),
-  vec2(-0.5, 0.5)
-);
+
 void main() {
-  gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
-  fragColor = colors[gl_VertexIndex];
-}"""
+    gl_Position = vec4(inPosition, 0.0, 1.0);
+    fragColor = inColor;
+}
+"""
 
-var fragmentShaderCode: string = """#version 450
+var fragmentShaderCode = """#version 450
 layout(location = 0) out vec4 outColor;
 layout(location = 0) in vec3 fragColor;
 void main() {
@@ -57,7 +92,7 @@
     images: seq[VkImage]
     imageviews: seq[VkImageView]
   RenderPipeline = object
-    shaderStages*: seq[VkPipelineShaderStageCreateInfo]
+    shaders*: seq[ShaderProgram]
     layout*: VkPipelineLayout
     pipeline*: VkPipeline
   QueueFamily = object
@@ -265,11 +300,9 @@
   checkVkResult device.vkCreateRenderPass(addr(renderPassCreateInfo), nil, addr(result))
 
 proc setupRenderPipeline(device: VkDevice, frameDimension: VkExtent2D, renderPass: VkRenderPass): RenderPipeline =
-  # (seq[VkPipelineShaderStageCreateInfo], VkViewport, VkRect2D, VkPipelineLayout, VkPipeline) =
-
   # load shaders
-  result.shaderStages.add(device.createShaderStage(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderCode))
-  result.shaderStages.add(device.createShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderCode))
+  result.shaders.add(device.initShaderProgram(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderCode))
+  result.shaders.add(device.initShaderProgram(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderCode))
 
   var
     # define which parts can be dynamic (pipeline is fixed after setup)
@@ -279,13 +312,16 @@
       dynamicStateCount: uint32(dynamicStates.len),
       pDynamicStates: addr(dynamicStates[0]),
     )
+    vertexbindings = generateInputVertexBinding[MyVertex]()
+    attributebindings = generateInputAttributeBinding[MyVertex]()
+
     # define input data format
     vertexInputInfo = VkPipelineVertexInputStateCreateInfo(
       sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
-      vertexBindingDescriptionCount: 0,
-      pVertexBindingDescriptions: nil,
-      vertexAttributeDescriptionCount: 0,
-      pVertexAttributeDescriptions: nil,
+      vertexBindingDescriptionCount: uint32(vertexbindings.len),
+      pVertexBindingDescriptions: addr(vertexbindings[0]),
+      vertexAttributeDescriptionCount: uint32(attributebindings.len),
+      pVertexAttributeDescriptions: addr(attributebindings[0]),
     )
     inputAssembly = VkPipelineInputAssemblyStateCreateInfo(
       sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
@@ -358,10 +394,13 @@
     )
   checkVkResult device.vkCreatePipelineLayout(addr(pipelineLayoutInfo), nil, addr(result.layout))
 
+  var stages: seq[VkPipelineShaderStageCreateInfo]
+  for shader in result.shaders:
+    stages.add(shader.shader)
   var pipelineInfo = VkGraphicsPipelineCreateInfo(
     sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-    stageCount: 2,
-    pStages: addr(result.shaderStages[0]),
+    stageCount: uint32(stages.len),
+    pStages: addr(stages[0]),
     pVertexInputState: addr(vertexInputInfo),
     pInputAssemblyState: addr(inputAssembly),
     pViewportState: addr(viewportState),
@@ -633,8 +672,8 @@
   engine.vulkan.device.device.vkDestroyPipelineLayout(engine.vulkan.pipeline.layout, nil)
   engine.vulkan.device.device.vkDestroyRenderPass(engine.vulkan.renderPass, nil)
 
-  for shaderStage in engine.vulkan.pipeline.shaderStages:
-    engine.vulkan.device.device.vkDestroyShaderModule(shaderStage.module, nil)
+  for shader in engine.vulkan.pipeline.shaders:
+    engine.vulkan.device.device.vkDestroyShaderModule(shader.shader.module, nil)
 
   engine.vulkan.instance.vkDestroySurfaceKHR(engine.vulkan.surface, nil)
   engine.vulkan.device.device.vkDestroyDevice(nil)