comparison tests/test_gltf.nim @ 1255:2b5ca798f6d6

did: make example town loadable and renderable, yay!
author sam <sam@basx.dev>
date Sun, 28 Jul 2024 00:17:34 +0700
parents b0f4c8ccd49a
children bfb75c934f4e
comparison
equal deleted inserted replaced
1254:b0f4c8ccd49a 1255:2b5ca798f6d6
11 var renderdata = InitRenderData() 11 var renderdata = InitRenderData()
12 12
13 type 13 type
14 ObjectData = object 14 ObjectData = object
15 transform: Mat4 15 transform: Mat4
16 materialId: int32
16 Camera = object 17 Camera = object
17 viewPerspective: Mat4 18 viewPerspective: Mat4
18 Material = object 19 Material = object
19 color: Vec4f = NewVec4f(1, 1, 1, 1) 20 color: Vec4f = NewVec4f(1, 1, 1, 1)
20 colorTexture: int32 = -1 21 # colorTexture: int32 = -1
21 metallic: float32 = 0 22 metallic: float32 = 0
22 roughness: float32 = 0 23 roughness: float32 = 0
23 metallicRoughnessTexture: int32 = -1 24 # metallicRoughnessTexture: int32 = -1
24 25 # normalTexture: int32 = -1
25 normalTexture: int32 = -1 26 # occlusionTexture: int32 = -1
26 occlusionTexture: int32 = -1
27 emissive: Vec4f = NewVec4f(0, 0, 0, 0) 27 emissive: Vec4f = NewVec4f(0, 0, 0, 0)
28 emissiveTexture: int32 = -1 28 # emissiveTexture: int32 = -1
29 MainDescriptors = object 29 MainDescriptors = object
30 material: GPUValue[Material, UniformBuffer] 30 materials: array[32, GPUValue[Material, UniformBuffer]]
31 camera: GPUValue[Camera, UniformBufferMapped] 31 camera: GPUValue[Camera, UniformBufferMapped]
32 Shader = object 32 Shader = object
33 objectData {.PushConstantAttribute.}: ObjectData 33 objectData {.PushConstantAttribute.}: ObjectData
34 position {.VertexAttribute.}: Vec3f 34 position {.VertexAttribute.}: Vec3f
35 color {.VertexAttribute.}: Vec4f 35 color {.VertexAttribute.}: Vec4f
36 # uv {.VertexAttribute.}: Vec2f 36 normal {.VertexAttribute.}: Vec3f
37 fragmentColor {.Pass.}: Vec4f 37 fragmentColor {.Pass.}: Vec4f
38 fragmentUv {.Pass.}: Vec2f 38 fragmentNormal {.Pass.}: Vec3f
39 outColor {.ShaderOutput.}: Vec4f 39 outColor {.ShaderOutput.}: Vec4f
40 descriptors {.DescriptorSets.}: (MainDescriptors, ) 40 descriptors {.DescriptorSets.}: (MainDescriptors, )
41 # code 41 # code
42 vertexCode: string = """ 42 vertexCode: string = """
43 void main() { 43 void main() {
44 fragmentColor = color; 44 fragmentColor = color * materials[objectData.materialId].color;
45 // fragmentUv = uv; 45 fragmentNormal = normal;
46 gl_Position = vec4(position, 1) * camera.viewPerspective; 46 gl_Position = vec4(position, 1) * (objectData.transform * camera.viewPerspective);
47 }""" 47 }"""
48 fragmentCode: string = """void main() { outColor = fragmentColor;}""" 48 fragmentCode: string = """
49 const vec3 lightDir = normalize(vec3(1, -1, 1));
50 void main() {
51 outColor = vec4(fragmentColor.rgb * (1 - abs(dot(fragmentNormal, lightDir))), fragmentColor.a);
52 }"""
49 Mesh = object 53 Mesh = object
50 position: GPUArray[Vec3f, VertexBuffer] 54 position: GPUArray[Vec3f, VertexBuffer]
51 color: GPUArray[Vec4f, VertexBuffer] 55 color: GPUArray[Vec4f, VertexBuffer]
52 uv: GPUArray[Vec2f, VertexBuffer] 56 normal: GPUArray[Vec3f, VertexBuffer]
53 DebugMesh = object 57 indices: GPUArray[uint32, IndexBuffer]
54 position: GPUArray[Vec3f, VertexBuffer] 58 material: int32
55 color: GPUArray[Vec4f, VertexBuffer]
56 59
57 var gltfData = LoadMeshes[Mesh, Material]( 60 var gltfData = LoadMeshes[Mesh, Material](
58 "town.glb", 61 "town.glb",
59 MeshAttributeNames( 62 MeshAttributeNames(
60 POSITION: "position", 63 POSITION: "position",
61 COLOR: @["color"], 64 COLOR: @["color"],
62 TEXCOORD: @["uv"], 65 NORMAL: "normal",
66 indices: "indices",
67 material: "material",
63 ), 68 ),
64 MaterialAttributeNames( 69 MaterialAttributeNames(
65 baseColorFactor: "color", 70 baseColorFactor: "color",
66 baseColorTexture: "colorTexture", 71 baseColorTexture: "colorTexture",
67 metallicFactor: "metallic", 72 metallicFactor: "metallic",
78 camera: asGPUValue(Camera( 83 camera: asGPUValue(Camera(
79 viewPerspective: Unit4, 84 viewPerspective: Unit4,
80 ), UniformBufferMapped) 85 ), UniformBufferMapped)
81 ) 86 )
82 ) 87 )
88 for i in 0 ..< gltfData.materials.len:
89 descriptors.data.materials[i] = asGPUValue(gltfData.materials[i], UniformBuffer)
83 for mesh in mitems(gltfData.meshes): 90 for mesh in mitems(gltfData.meshes):
84 for primitive in mitems(mesh): 91 for primitive in mitems(mesh):
85 primitive[0].color = asGPUArray(newSeqWith(primitive[0].position.data.len, NewVec4f(1, 1, 1, 1)), VertexBuffer) 92 primitive[0].color = asGPUArray(newSeqWith(primitive[0].position.data.len, NewVec4f(1, 1, 1, 1)), VertexBuffer)
86 renderdata.AssignBuffers(primitive[0]) 93 renderdata.AssignBuffers(primitive[0])
87 renderdata.AssignBuffers(descriptors) 94 renderdata.AssignBuffers(descriptors)
88 95
89 let O = default(Vec3f) 96 var pipeline = CreatePipeline[Shader](renderPass = vulkan.swapchain.renderPass)
90 let Gray = NewVec4f(0.5, 0.5, 0.5, 1)
91 var gridPos = @[O, X, O, Y, O, Z]
92 var gridColor = @[R, R, G, G, B, B]
93 for i in 0 ..< 10:
94 gridPos.add [NewVec3f(-5, -0.001, i.float32 - 5), NewVec3f(5, -0.001, i.float32 - 5)]
95 gridPos.add [NewVec3f(i.float32 - 5, -0.001, -5), NewVec3f(i.float32 - 5, -0.001, 5)]
96 gridColor.add [Gray, Gray, Gray, Gray]
97 var grid = DebugMesh(
98 position: asGPUArray(gridPos, VertexBuffer),
99 color: asGPUArray(gridColor, VertexBuffer),
100 )
101 renderdata.AssignBuffers(grid)
102
103 var pipeline = CreatePipeline[Shader](renderPass = vulkan.swapchain.renderPass, cullMode = [])
104 var debugpipeline = CreatePipeline[Shader](renderPass = vulkan.swapchain.renderPass, topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST, lineWidth=10)
105 InitDescriptorSet(renderdata, pipeline.descriptorSetLayouts[0], descriptors) 97 InitDescriptorSet(renderdata, pipeline.descriptorSetLayouts[0], descriptors)
106 98
107 renderdata.FlushAllMemory() 99 renderdata.FlushAllMemory()
108 100
109 proc drawNode(commandbuffer: VkCommandBuffer, pipeline: Pipeline, nodeId: int, 101 proc drawNode(commandbuffer: VkCommandBuffer, pipeline: Pipeline, nodeId: int, transform: Mat4) =
110 transform: Mat4 = Unit4) =
111 let nodeTransform = gltfData.nodes[nodeId].transform * transform 102 let nodeTransform = gltfData.nodes[nodeId].transform * transform
112 if gltfData.nodes[nodeId].mesh >= 0: 103 if gltfData.nodes[nodeId].mesh >= 0:
113 for primitive in gltfData.meshes[gltfData.nodes[nodeId].mesh]: 104 for primitive in gltfData.meshes[gltfData.nodes[nodeId].mesh]:
114 RenderWithPushConstant( 105 RenderWithPushConstant(
115 commandbuffer = commandbuffer, 106 commandbuffer = commandbuffer,
116 pipeline = pipeline, 107 pipeline = pipeline,
117 mesh = primitive[0], 108 mesh = primitive[0],
118 pushConstant = ObjectData(transform: nodeTransform) 109 pushConstant = ObjectData(transform: nodeTransform, materialId: primitive[0].material)
119 ) 110 )
120 for childNode in gltfData.nodes[nodeId].children: 111 for childNode in gltfData.nodes[nodeId].children:
121 drawNode(commandbuffer = commandbuffer, pipeline = pipeline, nodeId = childNode, transform = nodeTransform) 112 drawNode(commandbuffer = commandbuffer, pipeline = pipeline, nodeId = childNode, transform = nodeTransform)
122 113
123 var camPos: Vec3f 114 var camPos: Vec3f
140 if KeyIsDown(W): forward += 2 131 if KeyIsDown(W): forward += 2
141 if KeyIsDown(S): forward -= 2 132 if KeyIsDown(S): forward -= 2
142 if KeyIsDown(A): sideward -= 2 133 if KeyIsDown(A): sideward -= 2
143 if KeyIsDown(D): sideward += 2 134 if KeyIsDown(D): sideward += 2
144 135
145 let camDir = (Rotate(camPitch, X) * Rotate(camYaw, Y)) * Z 136 let camDir = (Rotate(camYaw, Y) * Rotate(camPitch, X)) * Z
146 echo camDir 137 let camDirSide = camDir.Cross(-Y).Normalized
147 let camDirSide = (Rotate(camPitch, X) * Rotate(camYaw, Y)) * X
148 # echo camDir
149 # echo camDirSide
150 camPos += camDir * forward * dt 138 camPos += camDir * forward * dt
151 camPos += camDirSide * sideward * dt 139 camPos += camDirSide * sideward * dt
152 140
153 descriptors.data.camera.data.viewPerspective = ( 141 descriptors.data.camera.data.viewPerspective = (
154 Perspective(PI/3, aspect = GetAspectRatio(), zNear = 0.001, zFar = 100) * 142 Perspective(PI/3, aspect = GetAspectRatio(), zNear = 0.1, zFar = 1) *
155 Rotate(-camPitch, X) * Rotate(-camYaw, Y) * Translate(-camPos) 143 Rotate(-camPitch, X) * Rotate(-camYaw, Y) * Translate(-camPos)
156 ) 144 )
157 145
158 UpdateGPUBuffer(descriptors.data.camera) 146 UpdateGPUBuffer(descriptors.data.camera)
159 147
162 WithRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, NewVec4f(0, 0, 0, 0)): 150 WithRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, NewVec4f(0, 0, 0, 0)):
163 151
164 WithPipeline(commandbuffer, pipeline): 152 WithPipeline(commandbuffer, pipeline):
165 WithBind(commandbuffer, (descriptors, ), pipeline): 153 WithBind(commandbuffer, (descriptors, ), pipeline):
166 for nodeId in gltfData.scenes[0]: 154 for nodeId in gltfData.scenes[0]:
167 drawNode(commandbuffer = commandbuffer, pipeline = pipeline, nodeId = nodeId) 155 drawNode(
168 WithBind(commandbuffer, (descriptors, ), pipeline): 156 commandbuffer = commandbuffer,
169 WithPipeline(commandbuffer, debugpipeline): 157 pipeline = pipeline,
170 Render(commandbuffer = commandbuffer, pipeline = debugpipeline, mesh = grid) 158 nodeId = nodeId,
159 transform = Rotate(PI / 2, Z)
160 )
171 161
172 # cleanup 162 # cleanup
173 checkVkResult vkDeviceWaitIdle(vulkan.device) 163 checkVkResult vkDeviceWaitIdle(vulkan.device)
174 DestroyPipeline(pipeline) 164 DestroyPipeline(pipeline)
175 DestroyPipeline(debugpipeline)
176 DestroyRenderData(renderdata) 165 DestroyRenderData(renderdata)
166
177 when isMainModule: 167 when isMainModule:
178 var time = 1000'f32 168 var time = 1000'f32
179 InitVulkan() 169 InitVulkan()
180 170
181 var renderpass = CreateDirectPresentationRenderPass(depthBuffer = true, samples = VK_SAMPLE_COUNT_4_BIT) 171 var renderpass = CreateDirectPresentationRenderPass(depthBuffer = true, samples = VK_SAMPLE_COUNT_4_BIT)