comparison tests/hello_triangle.nim @ 1443:768bf1a8407b default tip main

add: hello-triangle example, did: update according readme parts
author sam <sam@basx.dev>
date Mon, 24 Feb 2025 10:09:41 +0700
parents
children
comparison
equal deleted inserted replaced
1442:8d26eb12f6e8 1443:768bf1a8407b
1 import ../semicongine
2 import ../semicongine/rendering
3 import ../semicongine/input
4
5 # required
6 initEngine("Hello triangle")
7
8 # set up a simple render pass to render the displayed frame
9 var renderpass = createDirectPresentationRenderPass(
10 depthBuffer = false, samples = VK_SAMPLE_COUNT_1_BIT
11 )
12
13 # the swapchain, needs to be attached to the main renderpass
14 setupSwapchain(renderpass = renderpass)
15
16 # render data is used for memory management on the GPU
17 var renderdata = initRenderData()
18
19 type
20 # define a push constant, to have something moving
21 PushConstant = object
22 scale: float32
23
24 # This is how we define shaders: the interface needs to be "typed"
25 # but the shader code itself can freely be written in glsl
26 Shader = object
27 position {.VertexAttribute.}: Vec3f
28 color {.VertexAttribute.}: Vec3f
29 pushConstant {.PushConstant.}: PushConstant
30 fragmentColor {.Pass.}: Vec3f
31 outColor {.ShaderOutput.}: Vec4f
32 # code
33 vertexCode: string =
34 """void main() {
35 fragmentColor = color;
36 gl_Position = vec4(position * pushConstant.scale, 1);}"""
37 fragmentCode: string =
38 """void main() {
39 outColor = vec4(fragmentColor, 1);}"""
40
41 # And we also need to define our Mesh, which does describe the vertex layout
42 TriangleMesh = object
43 position: GPUArray[Vec3f, VertexBuffer]
44 color: GPUArray[Vec3f, VertexBuffer]
45
46 # instantiate the mesh and fill with data
47 var mesh = TriangleMesh(
48 position: asGPUArray([vec3(-0.5, -0.5), vec3(0, 0.5), vec3(0.5, -0.5)], VertexBuffer),
49 color: asGPUArray([vec3(0, 0, 1), vec3(0, 1, 0), vec3(1, 0, 0)], VertexBuffer),
50 )
51
52 # this allocates GPU data, uploads the data to the GPU and flushes any thing that is host-cached
53 # this is a shortcut version, more fine-grained control is possible
54 assignBuffers(renderdata, mesh)
55 renderdata.flushAllMemory()
56
57 # Now we need to instantiate the shader as a pipeline object that is attached to a renderpass
58 var pipeline = createPipeline(Shader(), renderPass = renderPass)
59
60 # the main render-loop will exit if we get a kill-signal from the OS
61 while updateInputs():
62 # starts the drawing for the next frame and provides us necesseary framebuffer and commandbuffer objects in this scope
63 withNextFrame(framebuffer, commandbuffer):
64 # start the main (and only) renderpass we have, needs to know the target framebuffer and a commandbuffer
65 withRenderPass(
66 renderPass,
67 framebuffer,
68 commandbuffer,
69 frameWidth(),
70 frameHeight(),
71 vec4(0, 0, 0, 0),
72 ):
73 # now activate our shader-pipeline
74 withPipeline(commandbuffer, pipeline):
75 # and finally, draw the mesh and set a single parameter
76 # more complicated setups with descriptors/uniforms are of course possible
77 renderWithPushConstant(
78 commandbuffer = commandbuffer,
79 pipeline = pipeline,
80 mesh = mesh,
81 pushConstant = PushConstant(scale: 0.3),
82 )
83
84 # cleanup
85 checkVkResult vkDeviceWaitIdle(engine().vulkan.device)
86 destroyPipeline(pipeline)
87 destroyRenderData(renderdata)
88 destroyRenderPass(renderpass)
89 destroyVulkan()