Mercurial > games > semicongine
comparison tests/hello_triangle.nim @ 1443:768bf1a8407b
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 | 1f58458b7ef7 |
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() |
