Mercurial > games > semicongine
comparison README.md @ 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 | 0f3f2017b054 |
children |
comparison
equal
deleted
inserted
replaced
1442:8d26eb12f6e8 | 1443:768bf1a8407b |
---|---|
33 collision detection, noise generation and texture packing, and a simple | 33 collision detection, noise generation and texture packing, and a simple |
34 settings API with hot-reloading | 34 settings API with hot-reloading |
35 | 35 |
36 ## Wishlist | 36 ## Wishlist |
37 | 37 |
38 [ ] Macro-based internal DSL to convert Nim code into GLSL/slang at compile time | 38 - Macro-based internal DSL to convert Nim code into GLSL/slang at compile time |
39 [ ] Better memory management | 39 - Better memory management |
40 - Simple buffer resizing | 40 - Simple buffer resizing |
41 - Mechanism to mark unused buffers | 41 - Mechanism to mark unused buffers |
42 - Use mapped GPU buffers without copying (implement seq with pointers to GPU memory) | 42 - Use mapped GPU buffers without copying (implement seq with pointers to GPU memory) |
43 - Do not keep copy of content for un-mapped buffers around (only pass data on creating or update) | 43 - Do not keep copy of content for un-mapped buffers around (only pass data on creating or update) |
44 | 44 |
45 ## Hello world example | 45 ## Hello world example |
46 | 46 |
47 Attention, this project is not optimized for "hello world"-scenarios, so you | 47 Attention, this project is not optimized for "hello world"-scenarios, so you |
48 have to write quite a few lines to get something to display: | 48 have to write quite a few lines to get something to display: |
49 | 49 |
50 ```nim | 50 ```nim |
51 | 51 |
52 import semicongine | 52 import ../semicongine |
53 import ../semicongine/rendering | |
54 import ../semicongine/input | |
53 | 55 |
54 # required | 56 # required |
55 InitVulkan() | 57 initEngine("Hello triangle") |
56 | 58 |
57 # set up a simple render pass to render the displayed frame | 59 # set up a simple render pass to render the displayed frame |
58 var renderpass = CreateDirectPresentationRenderPass(depthBuffer = false, samples = VK_SAMPLE_COUNT_1_BIT) | 60 var renderpass = createDirectPresentationRenderPass( |
61 depthBuffer = false, samples = VK_SAMPLE_COUNT_1_BIT | |
62 ) | |
59 | 63 |
60 # the swapchain, needs to be attached to the main renderpass | 64 # the swapchain, needs to be attached to the main renderpass |
61 SetupSwapchain(renderpass = renderpass) | 65 setupSwapchain(renderpass = renderpass) |
62 | 66 |
63 # render data is used for memory management on the GPU | 67 # render data is used for memory management on the GPU |
64 var renderdata = InitRenderData() | 68 var renderdata = initRenderData() |
65 | 69 |
66 type | 70 type |
67 # define a push constant, to have something moving | 71 # define a push constant, to have something moving |
68 PushConstant = object | 72 PushConstant = object |
69 scale: float32 | 73 scale: float32 |
74 | |
70 # This is how we define shaders: the interface needs to be "typed" | 75 # This is how we define shaders: the interface needs to be "typed" |
71 # but the shader code itself can freely be written in glsl | 76 # but the shader code itself can freely be written in glsl |
72 Shader = object | 77 Shader = object |
73 position {.VertexAttribute.}: Vec3f | 78 position {.VertexAttribute.}: Vec3f |
74 color {.VertexAttribute.}: Vec3f | 79 color {.VertexAttribute.}: Vec3f |
75 pushConstant {.PushConstantAttribute.}: PushConstant | 80 pushConstant {.PushConstant.}: PushConstant |
76 fragmentColor {.Pass.}: Vec3f | 81 fragmentColor {.Pass.}: Vec3f |
77 outColor {.ShaderOutput.}: Vec4f | 82 outColor {.ShaderOutput.}: Vec4f |
78 # code | 83 # code |
79 vertexCode: string = """void main() { | 84 vertexCode: string = |
85 """void main() { | |
80 fragmentColor = color; | 86 fragmentColor = color; |
81 gl_Position = vec4(position * pushConstant.scale, 1);}""" | 87 gl_Position = vec4(position * pushConstant.scale, 1);}""" |
82 fragmentCode: string = """void main() { | 88 fragmentCode: string = |
89 """void main() { | |
83 outColor = vec4(fragmentColor, 1);}""" | 90 outColor = vec4(fragmentColor, 1);}""" |
91 | |
84 # And we also need to define our Mesh, which does describe the vertex layout | 92 # And we also need to define our Mesh, which does describe the vertex layout |
85 TriangleMesh = object | 93 TriangleMesh = object |
86 position: GPUArray[Vec3f, VertexBuffer] | 94 position: GPUArray[Vec3f, VertexBuffer] |
87 color: GPUArray[Vec3f, VertexBuffer] | 95 color: GPUArray[Vec3f, VertexBuffer] |
88 | 96 |
89 # instantiate the mesh and fill with data | 97 # instantiate the mesh and fill with data |
90 var mesh = TriangleMesh( | 98 var mesh = TriangleMesh( |
91 position: asGPUArray([NewVec3f(-0.5, -0.5), NewVec3f(0, 0.5), NewVec3f(0.5, -0.5)], VertexBuffer), | 99 position: asGPUArray([vec3(-0.5, -0.5), vec3(0, 0.5), vec3(0.5, -0.5)], VertexBuffer), |
92 color: asGPUArray([NewVec3f(0, 0, 1), NewVec3f(0, 1, 0), NewVec3f(1, 0, 0)], VertexBuffer), | 100 color: asGPUArray([vec3(0, 0, 1), vec3(0, 1, 0), vec3(1, 0, 0)], VertexBuffer), |
93 ) | 101 ) |
94 | 102 |
95 # this allocates GPU data, uploads the data to the GPU and flushes any thing that is host-cached | 103 # this allocates GPU data, uploads the data to the GPU and flushes any thing that is host-cached |
96 # this is a shortcut version, more fine-grained control is possible | 104 # this is a shortcut version, more fine-grained control is possible |
97 AssignBuffers(renderdata, mesh) | 105 assignBuffers(renderdata, mesh) |
98 renderdata.FlushAllMemory() | 106 renderdata.flushAllMemory() |
99 | 107 |
100 # Now we need to instantiate the shader as a pipeline object that is attached to a renderpass | 108 # Now we need to instantiate the shader as a pipeline object that is attached to a renderpass |
101 var pipeline = CreatePipeline[Shader](renderPass = vulkan.swapchain.renderPass) | 109 var pipeline = createPipeline(Shader(), renderPass = renderPass) |
102 | 110 |
103 # the main render-loop will exit if we get a kill-signal from the OS | 111 # the main render-loop will exit if we get a kill-signal from the OS |
104 while UpdateInputs(): | 112 while updateInputs(): |
105 | |
106 # starts the drawing for the next frame and provides us necesseary framebuffer and commandbuffer objects in this scope | 113 # starts the drawing for the next frame and provides us necesseary framebuffer and commandbuffer objects in this scope |
107 WithNextFrame(framebuffer, commandbuffer): | 114 withNextFrame(framebuffer, commandbuffer): |
108 | |
109 # start the main (and only) renderpass we have, needs to know the target framebuffer and a commandbuffer | 115 # start the main (and only) renderpass we have, needs to know the target framebuffer and a commandbuffer |
110 WithRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, NewVec4f(0, 0, 0, 0)): | 116 withRenderPass( |
111 | 117 renderPass, |
118 framebuffer, | |
119 commandbuffer, | |
120 frameWidth(), | |
121 frameHeight(), | |
122 vec4(0, 0, 0, 0), | |
123 ): | |
112 # now activate our shader-pipeline | 124 # now activate our shader-pipeline |
113 WithPipeline(commandbuffer, pipeline): | 125 withPipeline(commandbuffer, pipeline): |
114 | |
115 # and finally, draw the mesh and set a single parameter | 126 # and finally, draw the mesh and set a single parameter |
116 # more complicated setups with descriptors/uniforms are of course possible | 127 # more complicated setups with descriptors/uniforms are of course possible |
117 RenderWithPushConstant(commandbuffer = commandbuffer, pipeline = pipeline, mesh = mesh, pushConstant = PushConstant(scale: 0.3)) | 128 renderWithPushConstant( |
129 commandbuffer = commandbuffer, | |
130 pipeline = pipeline, | |
131 mesh = mesh, | |
132 pushConstant = PushConstant(scale: 0.3), | |
133 ) | |
118 | 134 |
119 # cleanup | 135 # cleanup |
120 checkVkResult vkDeviceWaitIdle(vulkan.device) | 136 checkVkResult vkDeviceWaitIdle(engine().vulkan.device) |
121 DestroyPipeline(pipeline) | 137 destroyPipeline(pipeline) |
122 DestroyRenderData(renderdata) | 138 destroyRenderData(renderdata) |
123 vkDestroyRenderPass(vulkan.device, renderpass.vk, nil) | 139 destroyRenderPass(renderpass) |
124 DestroyVulkan() | 140 destroyVulkan() |
125 | 141 |
126 ``` | 142 ``` |
127 | 143 |
128 ## Future development | 144 ## Future development |
129 | 145 |