Mercurial > games > semicongine
diff 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 |
line wrap: on
line diff
--- a/README.md Sun Feb 16 23:12:32 2025 +0700 +++ b/README.md Mon Feb 24 10:09:41 2025 +0700 @@ -35,12 +35,12 @@ ## Wishlist -[ ] Macro-based internal DSL to convert Nim code into GLSL/slang at compile time -[ ] Better memory management - - Simple buffer resizing - - Mechanism to mark unused buffers - - Use mapped GPU buffers without copying (implement seq with pointers to GPU memory) - - Do not keep copy of content for un-mapped buffers around (only pass data on creating or update) +- Macro-based internal DSL to convert Nim code into GLSL/slang at compile time +- Better memory management + - Simple buffer resizing + - Mechanism to mark unused buffers + - Use mapped GPU buffers without copying (implement seq with pointers to GPU memory) + - Do not keep copy of content for un-mapped buffers around (only pass data on creating or update) ## Hello world example @@ -49,38 +49,46 @@ ```nim -import semicongine +import ../semicongine +import ../semicongine/rendering +import ../semicongine/input # required -InitVulkan() +initEngine("Hello triangle") # set up a simple render pass to render the displayed frame -var renderpass = CreateDirectPresentationRenderPass(depthBuffer = false, samples = VK_SAMPLE_COUNT_1_BIT) +var renderpass = createDirectPresentationRenderPass( + depthBuffer = false, samples = VK_SAMPLE_COUNT_1_BIT +) # the swapchain, needs to be attached to the main renderpass -SetupSwapchain(renderpass = renderpass) +setupSwapchain(renderpass = renderpass) # render data is used for memory management on the GPU -var renderdata = InitRenderData() +var renderdata = initRenderData() type # define a push constant, to have something moving PushConstant = object scale: float32 + # This is how we define shaders: the interface needs to be "typed" # but the shader code itself can freely be written in glsl Shader = object position {.VertexAttribute.}: Vec3f color {.VertexAttribute.}: Vec3f - pushConstant {.PushConstantAttribute.}: PushConstant + pushConstant {.PushConstant.}: PushConstant fragmentColor {.Pass.}: Vec3f outColor {.ShaderOutput.}: Vec4f # code - vertexCode: string = """void main() { + vertexCode: string = + """void main() { fragmentColor = color; gl_Position = vec4(position * pushConstant.scale, 1);}""" - fragmentCode: string = """void main() { + fragmentCode: string = + """void main() { outColor = vec4(fragmentColor, 1);}""" + # And we also need to define our Mesh, which does describe the vertex layout TriangleMesh = object position: GPUArray[Vec3f, VertexBuffer] @@ -88,40 +96,48 @@ # instantiate the mesh and fill with data var mesh = TriangleMesh( - position: asGPUArray([NewVec3f(-0.5, -0.5), NewVec3f(0, 0.5), NewVec3f(0.5, -0.5)], VertexBuffer), - color: asGPUArray([NewVec3f(0, 0, 1), NewVec3f(0, 1, 0), NewVec3f(1, 0, 0)], VertexBuffer), + position: asGPUArray([vec3(-0.5, -0.5), vec3(0, 0.5), vec3(0.5, -0.5)], VertexBuffer), + color: asGPUArray([vec3(0, 0, 1), vec3(0, 1, 0), vec3(1, 0, 0)], VertexBuffer), ) # this allocates GPU data, uploads the data to the GPU and flushes any thing that is host-cached # this is a shortcut version, more fine-grained control is possible -AssignBuffers(renderdata, mesh) -renderdata.FlushAllMemory() +assignBuffers(renderdata, mesh) +renderdata.flushAllMemory() # Now we need to instantiate the shader as a pipeline object that is attached to a renderpass -var pipeline = CreatePipeline[Shader](renderPass = vulkan.swapchain.renderPass) +var pipeline = createPipeline(Shader(), renderPass = renderPass) # the main render-loop will exit if we get a kill-signal from the OS -while UpdateInputs(): - +while updateInputs(): # starts the drawing for the next frame and provides us necesseary framebuffer and commandbuffer objects in this scope - WithNextFrame(framebuffer, commandbuffer): - + withNextFrame(framebuffer, commandbuffer): # start the main (and only) renderpass we have, needs to know the target framebuffer and a commandbuffer - WithRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, NewVec4f(0, 0, 0, 0)): - + withRenderPass( + renderPass, + framebuffer, + commandbuffer, + frameWidth(), + frameHeight(), + vec4(0, 0, 0, 0), + ): # now activate our shader-pipeline - WithPipeline(commandbuffer, pipeline): - + withPipeline(commandbuffer, pipeline): # and finally, draw the mesh and set a single parameter # more complicated setups with descriptors/uniforms are of course possible - RenderWithPushConstant(commandbuffer = commandbuffer, pipeline = pipeline, mesh = mesh, pushConstant = PushConstant(scale: 0.3)) + renderWithPushConstant( + commandbuffer = commandbuffer, + pipeline = pipeline, + mesh = mesh, + pushConstant = PushConstant(scale: 0.3), + ) # cleanup -checkVkResult vkDeviceWaitIdle(vulkan.device) -DestroyPipeline(pipeline) -DestroyRenderData(renderdata) -vkDestroyRenderPass(vulkan.device, renderpass.vk, nil) -DestroyVulkan() +checkVkResult vkDeviceWaitIdle(engine().vulkan.device) +destroyPipeline(pipeline) +destroyRenderData(renderdata) +destroyRenderPass(renderpass) +destroyVulkan() ```