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