comparison src/zamikongine/vertex.nim @ 19:b55d6ecde79d

did: introduce scene graph, meshs and generic vertex buffers
author Sam <sam@basx.dev>
date Mon, 09 Jan 2023 11:04:19 +0700
parents src/vertex.nim@b40466fa446a
children 9edca5dc4e93
comparison
equal deleted inserted replaced
18:90e117952f74 19:b55d6ecde79d
1 import std/macros
2 import std/strutils
3 import std/strformat
4 import std/typetraits
5
6 import ./math/vector
7 import ./vulkan
8
9 type
10 VertexAttributeType = SomeNumber|Vec
11 VertexAttribute*[T:VertexAttributeType] = object
12 data*: seq[T]
13
14 template rawAttributeType(v: VertexAttribute): auto = get(genericParams(typeof(v)), 0)
15
16 func datasize*(attribute: VertexAttribute): uint64 =
17 uint64(sizeof(rawAttributeType(attribute))) * uint64(attribute.data.len)
18
19 # from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html
20 func nLocationSlots[T: VertexAttributeType](): int =
21 when (T is Vec3[float64] or T is Vec3[uint64] or T is Vec4[float64] or T is Vec4[float64]):
22 2
23 else:
24 1
25
26 # numbers
27 func getVkFormat[T: VertexAttributeType](): VkFormat =
28 when T is uint8: VK_FORMAT_R8_UINT
29 elif T is int8: VK_FORMAT_R8_SINT
30 elif T is uint16: VK_FORMAT_R16_UINT
31 elif T is int16: VK_FORMAT_R16_SINT
32 elif T is uint32: VK_FORMAT_R32_UINT
33 elif T is int32: VK_FORMAT_R32_SINT
34 elif T is uint64: VK_FORMAT_R64_UINT
35 elif T is int64: VK_FORMAT_R64_SINT
36 elif T is float32: VK_FORMAT_R32_SFLOAT
37 elif T is float64: VK_FORMAT_R64_SFLOAT
38 elif T is Vec2[uint8]: VK_FORMAT_R8G8_UINT
39 elif T is Vec2[int8]: VK_FORMAT_R8G8_SINT
40 elif T is Vec2[uint16]: VK_FORMAT_R16G16_UINT
41 elif T is Vec2[int16]: VK_FORMAT_R16G16_SINT
42 elif T is Vec2[uint32]: VK_FORMAT_R32G32_UINT
43 elif T is Vec2[int32]: VK_FORMAT_R32G32_SINT
44 elif T is Vec2[uint64]: VK_FORMAT_R64G64_UINT
45 elif T is Vec2[int64]: VK_FORMAT_R64G64_SINT
46 elif T is Vec2[float32]: VK_FORMAT_R32G32_SFLOAT
47 elif T is Vec2[float64]: VK_FORMAT_R64G64_SFLOAT
48 elif T is Vec3[uint8]: VK_FORMAT_R8G8B8_UINT
49 elif T is Vec3[int8]: VK_FORMAT_R8G8B8_SINT
50 elif T is Vec3[uint16]: VK_FORMAT_R16G16B16_UINT
51 elif T is Vec3[int16]: VK_FORMAT_R16G16B16_SINT
52 elif T is Vec3[uint32]: VK_FORMAT_R32G32B32_UINT
53 elif T is Vec3[int32]: VK_FORMAT_R32G32B32_SINT
54 elif T is Vec3[uint64]: VK_FORMAT_R64G64B64_UINT
55 elif T is Vec3[int64]: VK_FORMAT_R64G64B64_SINT
56 elif T is Vec3[float32]: VK_FORMAT_R32G32B32_SFLOAT
57 elif T is Vec3[float64]: VK_FORMAT_R64G64B64_SFLOAT
58 elif T is Vec4[uint8]: VK_FORMAT_R8G8B8A8_UINT
59 elif T is Vec4[int8]: VK_FORMAT_R8G8B8A8_SINT
60 elif T is Vec4[uint16]: VK_FORMAT_R16G16B16A16_UINT
61 elif T is Vec4[int16]: VK_FORMAT_R16G16B16A16_SINT
62 elif T is Vec4[uint32]: VK_FORMAT_R32G32B32A32_UINT
63 elif T is Vec4[int32]: VK_FORMAT_R32G32B32A32_SINT
64 elif T is Vec4[uint64]: VK_FORMAT_R64G64B64A64_UINT
65 elif T is Vec4[int64]: VK_FORMAT_R64G64B64A64_SINT
66 elif T is Vec4[float32]: VK_FORMAT_R32G32B32A32_SFLOAT
67 elif T is Vec4[float64]: VK_FORMAT_R64G64B64A64_SFLOAT
68
69 func getGLSLType[T: VertexAttributeType](): string =
70 # todo: likely not correct as we would need to enable some
71 # extensions somewhere (Vulkan/GLSL compiler?) to have
72 # everything work as intended. Or maybe the GPU driver does
73 # some automagic conversion stuf..
74 when T is uint8: "uint"
75 elif T is int8: "int"
76 elif T is uint16: "uint"
77 elif T is int16: "int"
78 elif T is uint32: "uint"
79 elif T is int32: "int"
80 elif T is uint64: "uint"
81 elif T is int64: "int"
82 elif T is float32: "float"
83 elif T is float64: "double"
84
85 elif T is Vec2[uint8]: "uvec2"
86 elif T is Vec2[int8]: "ivec2"
87 elif T is Vec2[uint16]: "uvec2"
88 elif T is Vec2[int16]: "ivec2"
89 elif T is Vec2[uint32]: "uvec2"
90 elif T is Vec2[int32]: "ivec2"
91 elif T is Vec2[uint64]: "uvec2"
92 elif T is Vec2[int64]: "ivec2"
93 elif T is Vec2[float32]: "vec2"
94 elif T is Vec2[float64]: "dvec2"
95
96 elif T is Vec3[uint8]: "uvec3"
97 elif T is Vec3[int8]: "ivec3"
98 elif T is Vec3[uint16]: "uvec3"
99 elif T is Vec3[int16]: "ivec3"
100 elif T is Vec3[uint32]: "uvec3"
101 elif T is Vec3[int32]: "ivec3"
102 elif T is Vec3[uint64]: "uvec3"
103 elif T is Vec3[int64]: "ivec3"
104 elif T is Vec3[float32]: "vec3"
105 elif T is Vec3[float64]: "dvec3"
106
107 elif T is Vec4[uint8]: "uvec4"
108 elif T is Vec4[int8]: "ivec4"
109 elif T is Vec4[uint16]: "uvec4"
110 elif T is Vec4[int16]: "ivec4"
111 elif T is Vec4[uint32]: "uvec4"
112 elif T is Vec4[int32]: "ivec4"
113 elif T is Vec4[uint64]: "uvec4"
114 elif T is Vec4[int64]: "ivec4"
115 elif T is Vec4[float32]: "vec4"
116 elif T is Vec4[float64]: "dvec4"
117
118
119 func VertexCount*[T](t: T): uint32 =
120 for name, value in t.fieldPairs:
121 when typeof(value) is VertexAttribute:
122 if result == 0:
123 result = uint32(value.data.len)
124 else:
125 assert result == uint32(value.data.len)
126
127 func generateGLSLDeclarations*[T](): string =
128 var stmtList: seq[string]
129 var i = 0
130 for name, value in T().fieldPairs:
131 when typeof(value) is VertexAttribute:
132 let glsltype = getGLSLType[rawAttributeType(value)]()
133 let n = name
134 stmtList.add(&"layout(location = {i}) in {glsltype} {n};")
135 i += nLocationSlots[rawAttributeType(value)]()
136
137 return stmtList.join("\n")
138
139 func generateInputVertexBinding*[T](bindingoffset: int = 0, locationoffset: int = 0): seq[VkVertexInputBindingDescription] =
140 # packed attribute data, not interleaved (aks "struct of arrays")
141 var binding = bindingoffset
142 for name, value in T().fieldPairs:
143 when typeof(value) is VertexAttribute:
144 result.add(
145 VkVertexInputBindingDescription(
146 binding: uint32(binding),
147 stride: uint32(sizeof(rawAttributeType(value))),
148 inputRate: VK_VERTEX_INPUT_RATE_VERTEX, # VK_VERTEX_INPUT_RATE_INSTANCE for instances
149 )
150 )
151 binding += 1
152
153 func generateInputAttributeBinding*[T](bindingoffset: int = 0, locationoffset: int = 0): seq[VkVertexInputAttributeDescription] =
154 # packed attribute data, not interleaved (aks "struct of arrays")
155 var location = 0
156 var binding = bindingoffset
157 for name, value in T().fieldPairs:
158 when typeof(value) is VertexAttribute:
159 result.add(
160 VkVertexInputAttributeDescription(
161 binding: uint32(binding),
162 location: uint32(location),
163 format: getVkFormat[rawAttributeType(value)](),
164 offset: 0,
165 )
166 )
167 location += nLocationSlots[rawAttributeType(value)]()
168 binding += 1