#[ #{.experimental: "codeReordering".} {.deadCodeElim: on.} import textUtils , glm , text_types , bitops , ../scenes/[ scene_object ] , ../vk/[ vulkan_utils , vkTypes , buffer , vulkan_record , graphics_pipeline ] , ../vk/vulkan , ../ktx/ktxutils , ../camera , ../drawable/texture , ../utils/lets import ../vk/vkm/vkmat as vkm # TODO: caching #[ proc genVertBuffers*( rec: var Vulkan_Record , text: var SDFText , str: string ) = var indexOffset: uint32 indices: array[6, uint32] = [0.uint32,1,2, 2,3,0 ] w: float32 = text.texture.width.float32 posX = 0.0 posY = 0.0 data: pointer for c in str: var ci: Bmchar = text.font.chars[int(c)] if ci.width == 0: ci.width = 36 var charw: float32 = ci.width.float32 / 36.0f dimx: float32 = 1.0f * charw charh: float32 = ci.height.float32 / 36.0f dimy: float32 = 1.0f * charh us: float32 = ci.x.float32 / w ue: float32 = (ci.x + ci.width).float32 / w ts: float32 = ci.y.float32 / w te: float32 = (ci.y + ci.height).float32 / w xo: float32 = ci.xoffset.float32 / 36.0f yo: float32 = ci.yoffset.float32 / 36.0f posy = yo text.vertices.add TextVert( pos: vec3f(posx + dimx + xo, posy + dimy, 0.0f) , uv: vec2(ue, te) ) text.vertices.add TextVert( pos: vec3f(posx + xo, posy + dimy, 0.0f) , uv: vec2(us, te) ) text.vertices.add TextVert( pos: vec3f(posx + xo, posy, 0.0f) , uv: vec2(us, ts) ) text.vertices.add TextVert( pos: vec3f(posx + dimx + xo, posy, 0.0f) , uv: vec2(ue, ts) ) for i in indices: text.indices.add indexOffset + i indexOffset += 4 var adv: float32 = ci.xadvance.float32 / 36.0 posx += adv text.indexCount = text.indices.len.uint32 # centering? for v in text.vertices.mitems: v.pos.x -= (posx / 2.0).float32 v.pos.y -= 0.5.float32 var indSize = VkDeviceSize text.indices.len * uint32.sizeof vertSize = VkDeviceSize text.vertices.len.uint32 * TextVert.sizeof.uint32 copyCmd: VkCommandBuffer = rec.vk_device.getCommandBuffers(rec.command_pool, true) copyRegion: VkBufferCopy text.stVertexBuffer = a_vulkan_buffer( rec.vk_device , rec.gpu.memory_properties , VkBufferUsageFlags VK_BUFFER_USAGE_TRANSFER_SRC_BIT , VkMemoryPropertyFlags bitor( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT.ord , VK_MEMORY_PROPERTY_HOST_COHERENT_BIT.ord ) , vertSize ) text.vertexBuffer = a_vulkan_buffer( rec.vk_device , rec.gpu.memory_properties , VkBufferUsageFlags bitor( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT.ord , VK_BUFFER_USAGE_TRANSFER_DST_BIT.ord ) , VkMemoryPropertyFlags VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT , vertSize ) rec.vk_device.map_memory( text.stVertexBuffer.memory , data ) copyMem(data, addr text.vertices[0], Natural vertSize) vkUnmapMemory( rec.vk_device, text.stVertexBuffer.memory) discard vkBindBufferMemory( rec.vk_device, text.stVertexBuffer.vkbuffer, text.stVertexBuffer.memory, VkDeviceSize 0) discard vkBindBufferMemory( rec.vk_device, text.vertexBuffer.vkbuffer, text.vertexBuffer.memory, VkDeviceSize 0) text.stIndexBuffer = a_vulkan_buffer( rec.vk_device , rec.gpu.memory_properties , VkBufferUsageFlags VK_BUFFER_USAGE_TRANSFER_SRC_BIT , VkMemoryPropertyFlags bitor( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT.ord , VK_MEMORY_PROPERTY_HOST_COHERENT_BIT.ord ) , indSize ) text.indexBuffer = a_vulkan_buffer( rec.vk_device , rec.gpu.memory_properties , VkBufferUsageFlags bitor(VK_BUFFER_USAGE_INDEX_BUFFER_BIT.ord, VK_BUFFER_USAGE_TRANSFER_DST_BIT.ord) , VkMemoryPropertyFlags VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT , indSize ) rec.vk_device.map_memory( text.stIndexBuffer.memory , data ) copyMem(data, addr text.indices[0], Natural indSize) vkUnmapMemory( rec.vk_device, text.stIndexBuffer.memory) discard vkBindBufferMemory( rec.vk_device, text.stIndexBuffer.vkbuffer, text.stIndexBuffer.memory, VkDeviceSize 0) discard vkBindBufferMemory( rec.vk_device, text.indexBuffer.vkbuffer, text.indexBuffer.memory, VkDeviceSize 0) copyRegion.size = vertSize vkCmdCopyBuffer(copyCmd , text.stVertexBuffer.vkbuffer , text.vertexBuffer.vkbuffer , 1.uint32 , addr copyRegion ) copyRegion.size = indSize vkCmdCopyBuffer( copyCmd , text.stIndexBuffer.vkbuffer , text.indexBuffer.vkbuffer , 1.uint32 , addr copyRegion ) # # Flushing the command buffer will also submit it to the queue and # # uses a fence to ensure that all commands have been executed before returning rec.vk_device.flushCommandBuffer rec.queue, rec.command_pool, copyCmd # Destroy staging buffers # Note: Staging buffer must not be deleted before the copies have been submitted and executed vkDestroyBuffer( rec.vk_device, text.stVertexBuffer.vkbuffer, nil) vkFreeMemory( rec.vk_device, text.stVertexBuffer.memory, nil) vkDestroyBuffer( rec.vk_device, text.stIndexBuffer.vkbuffer, nil) vkFreeMemory( rec.vk_device, text.stIndexBuffer.memory, nil) ]# proc updateUniformBuffers*(text: SDFText, rec: Vulkan_Record ) = copyMem(text.uniBufferV.data, addr text.ubos.vs, text.ubos.vs.sizeof) proc prepare_uniform_buffers*( rec: Vulkan_Record , text: var SDFText ) = text.uniBufferV = a_vulkan_buffer( rec.vk_device , rec.gpu.memory_properties , VkBufferUsageFlags VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT , VkMemoryPropertyFlags ( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT.ord or VK_MEMORY_PROPERTY_HOST_COHERENT_BIT.ord ) , VkDeviceSize text.ubos.vs.sizeof ) text.uniBufferF = a_vulkan_buffer( rec.vk_device , rec.gpu.memory_properties , VkBufferUsageFlags VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT , VkMemoryPropertyFlags ( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT.ord or VK_MEMORY_PROPERTY_HOST_COHERENT_BIT.ord ) , VkDeviceSize text.ubos.fs.sizeof ) rec.vk_device.bindIt text.uniBufferV rec.vk_device.bindIt text.uniBufferF text.uniBufferV.fillDescr text.uniBufferF.fillDescr proc setupDescrSetLayout*( rec: Vulkan_Record , text: var SDFText ) = var #Binding 0: Vertex shader uniform buffer #Binding 1: Fragment shader image sampler #Binding 2: Fragment shader uniform buffer descriptorSetLayoutBindings = [ aVkDescriptorSetLayoutBinding( descType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , stageFlags = VkShaderStageFlags VK_SHADER_STAGE_VERTEX_BIT , binding = 0 ) , aVkDescriptorSetLayoutBinding( descType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , stageFlags = VkShaderStageFlags VK_SHADER_STAGE_FRAGMENT_BIT , binding = 1 ) , aVkDescriptorSetLayoutBinding( descType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , stageFlags = VkShaderStageFlags VK_SHADER_STAGE_FRAGMENT_BIT , binding = 2 ) ] descriptorLayout: VkDescriptorSetLayoutCreateInfo pPipelineLayoutCreateInfo: VkPipelineLayoutCreateInfo descriptorLayout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO descriptorLayout.bindingCount = descriptorSetLayoutBindings.len.uint32 descriptorLayout.pBindings = addr descriptorSetLayoutBindings[0] discard vkCreateDescriptorSetLayout(rec.vk_device , addr descriptorLayout , nil , addr text.descrSetLayout ) # Create the pipeline layout that is used to # generate the rendering pipelines that are based on this descriptor set layout # In a more complex scenario you would have different pipeline layouts # for different descriptor set layouts that could be reused pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO #pPipelineLayoutCreateInfo.pNext = nil pPipelineLayoutCreateInfo.setLayoutCount = 1 pPipelineLayoutCreateInfo.pSetLayouts = addr text.descrSetLayout discard vkCreatePipelineLayout(rec.vk_device, addr pPipelineLayoutCreateInfo, nil, addr text.graphicsPipeline.pipelineLayout) proc prepPipeline*( rec: Vulkan_Record , rp: VkRenderPass , gp: Graphics_Pipeline ) = var # Input attribute bindings describe shader attribute locations and memory layouts # Location 0 : Position # Location 1 : Texture coordinates vertexInputAttributs: array[2,VkVertexInputAttributeDescription] var pipelineInfo = VkGraphicsPipelineCreateInfo( sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO , layout: gp.pipelineLayout , render_pass: rp #subpass: 0, #basePipelineHandle: VkPipeline(VK_NULL_HANDLE), # optional #basePipelineIndex: -1, # optional ) #Input assembly state describes how primitives are assembled #This pipeline will assemble vertex data as a triangle lists (though we only use one triangle) inputAssembly = VkPipelineInputAssemblyStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO , topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , primitiveRestartEnable: vkfalse , flags: VkPipelineInputAssemblyStateCreateFlags 0 ) rasterizer = VkPipelineRasterizationStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO , depthClampEnable: vkfalse , rasterizerDiscardEnable: vkfalse , polygonMode: VK_POLYGON_MODE_FILL , lineWidth: 1f , cullMode: VkCullModeFlags VK_CULL_MODE_NONE , frontFace: VK_FRONT_FACE_COUNTER_CLOCKWISE , depthBiasEnable: vkfalse , flags: VkPipelineRasterizationStateCreateFlags 0 # , depthBiasConstantFactor: 0f # optional # , depthBiasClamp: 0f # optional # , depthBiasSlopeFactor: 0f # optional ) colorBlendAttachment = VkPipelineColorBlendAttachmentState( #colorWriteMask: VkColorComponentFlags 0xf blendEnable: vktrue , srcColorBlendFactor: VK_BLEND_FACTOR_ONE , dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA , colorBlendOp: VK_BLEND_OP_ADD , srcAlphaBlendFactor: VK_BLEND_FACTOR_ONE , dstAlphaBlendFactor: VK_BLEND_FACTOR_ZERO , alphaBlendOp: VK_BLEND_OP_ADD , colorWriteMask: VkColorComponentFlags bitor( VK_COLOR_COMPONENT_R_BIT.ord , VK_COLOR_COMPONENT_G_BIT.ord , VK_COLOR_COMPONENT_B_BIT.ord , VK_COLOR_COMPONENT_A_BIT.ord ) ) colorBlending = VkPipelineColorBlendStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO # , logicOpEnable: vkfalse # , logicOp: VK_LOGIC_OP_COPY # optional , attachmentCount: 1 , pAttachments: colorBlendAttachment.addr # , blendConstants: [0f, 0f, 0f, 0f] # optional ) # Enable dynamic states # Most states are baked into the pipeline, but there are still a few dynamic states that can be changed within a command buffer # To be able to change these we need do specify which dynamic states VkPipelineViewportStateCreateInfoVkPipelineViewportStateCreateInfo be changed using this pipeline. Their actual states are set later on in the command buffer. # For this example we will set the viewport and scissor using dynamic states dynamicStateEnables: array[2,VkDynamicState] = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, #[VK_DYNAMIC_STATE_LINE_WIDTH]#] dynamicState = VkPipelineDynamicStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO , pDynamicStates: addr dynamicStateEnables[0] , dynamicStateCount: dynamicStateEnables.len.uint32 ) # Depth and stencil state containing depth and stencil compare and test operations # We only use depth tests and want depth tests and writes to be enabled and compare with less or equal depthStencilState = VkPipelineDepthStencilStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO , depthTestEnable: vkfalse , depthWriteEnable: vktrue , depthCompareOp: VK_COMPARE_OP_LESS_OR_EQUAL # , depthBoundsTestEnable: VkBool32 VK_FALSE , back: VkStencilOpState( #failOp: VK_STENCIL_OP_KEEP #, passOp: VK_STENCIL_OP_KEEP compareOp: VK_COMPARE_OP_ALWAYS ) # , front: VkStencilOpState( failOp: VK_STENCIL_OP_KEEP # , passOp: VK_STENCIL_OP_KEEP # , compareOp: VK_COMPARE_OP_ALWAYS # ) # , stencilTestEnable: VkBool32 VK_FALSE ) # Multi sampling state # This example does not make use of multi sampling (for anti-aliasing), the state must still be set and passed to the pipeline multisampleState = VkPipelineMultisampleStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO , rasterizationSamples: VK_SAMPLE_COUNT_1_BIT , pSampleMask: nil ) # Vertex input state used for pipeline creation var viewport = VkViewport( x: 0f, y: 0f , width: rec.swapchain.current_extent.width.float32 , height: rec.swapchain.current_extent.height.float32 , minDepth: 0f , maxDepth: 1f ) scissor = VkRect2D( offset: VkOffset2D(x: 0, y: 0) , extent: rec.swapchain.current_extent, ) viewportState = VkPipelineViewportStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO , viewportCount: 1 , pViewports: viewport.addr , scissorCount: 1 , pScissors: scissor.addr , flags: VkPipelineViewportStateCreateFlags 0 ) # Shaders vertexInputAttributs[0].binding = 0 vertexInputAttributs[0].location = 0 vertexInputAttributs[0].format = VK_FORMAT_R32G32B32_SFLOAT vertexInputAttributs[0].offset = 0 vertexInputAttributs[1].binding = 0 vertexInputAttributs[1].location = 1 vertexInputAttributs[1].format = VK_FORMAT_R32G32_SFLOAT vertexInputAttributs[1].offset = float32.sizeof * 3 var bindingDescs = [ VkVertexInputBindingDescription( binding: 0 , stride: TextVert.sizeof.uint32 , inputRate: VK_VERTEX_INPUT_RATE_VERTEX ) ] vertexInputState = VkPipelineVertexInputStateCreateInfo( sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO , vertexBindingDescriptionCount: bindingDescs.len.uint32 , pVertexBindingDescriptions: addr bindingDescs[0] , vertexAttributeDescriptionCount: vertexInputAttributs.len.uint32 , pVertexAttributeDescriptions: addr vertexInputAttributs[0] ) shaderStages: array[2,VkPipelineShaderStageCreateInfo] const vertShaderCode = staticRead("../../data/shaders/sdfV.spv") fragShaderCode = staticRead("../../data/shaders/sdfF.spv") # Vertex shader shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO # Set pipeline stage for this shader shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT # Load binary SPIR-V shader shaderStages[0].module = rec.vk_device.createShaderModule vertShaderCode # Main entry point for the shader shaderStages[0].pName = "main" # Fragment shader shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO # Set pipeline stage for this shader shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT # Load binary SPIR-V shader shaderStages[1].module = rec.vk_device.createShaderModule fragShaderCode # Main entry point for the shader shaderStages[1].pName = "main" # Set pipeline shader stage info pipelineInfo.stageCount = shaderStages.len.uint32 pipelineInfo.pStages = addr shaderStages[0] # Assign the pipeline states to the pipeline creation info structure pipelineInfo.pVertexInputState = addr vertexInputState pipelineInfo.pInputAssemblyState = addr inputAssembly pipelineInfo.pRasterizationState = addr rasterizer pipelineInfo.pColorBlendState = addr colorBlending pipelineInfo.pMultisampleState = addr multisampleState pipelineInfo.pViewportState = addr viewportState pipelineInfo.pDepthStencilState = addr depthStencilState pipelineInfo.render_pass = rp pipelineInfo.pDynamicState = addr dynamicState # Create rendering pipeline using the specified states discard vkCreateGraphicsPipelines(rec.vk_device , rec.pipelineCache , 1 , addr pipelineInfo , nil , addr gp.pipeline ) # Shader modules are no longer needed once the graphics pipeline has been created vkDestroyShaderModule(rec.vk_device, shaderStages[0].module, nil) vkDestroyShaderModule(rec.vk_device, shaderStages[1].module, nil) proc setupDescrSets*(rec: Vulkan_Record, text: SDFText) = var dSet: VkDescriptorSet allocInfo = VkDescriptorSetAllocateInfo( sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO , descriptorPool: text.descrPool , descriptorSetCount: 1 , pSetLayouts: addr text.descrSetLayout ) discard vkAllocateDescriptorSets( rec.vk_device , addr allocInfo , addr dSet ) var cms = aVkDescriptorImageInfo( sampler = text.texture.sampler , imageView = text.texture.view , imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) sets = [ #Binding 0: Vertex shader uniform buffer #Binding 1: Fragment shader image sampler #Binding 2: Fragment shader uniform buffer VkWriteDescriptorSet( sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET , dstSet: dSet , descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , dstBinding: 0 , pBufferInfo: cast[ ptr ptr VkDescriptorBufferInfo](addr text.uniBufferV.descriptor) , descriptorCount: 1 ) , VkWriteDescriptorSet( sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET , dstSet: dSet , descriptorType: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , dstBinding: 1 , pImageInfo: addr cms , descriptorCount: 1 ) , VkWriteDescriptorSet( sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET , dstSet: dSet , descriptorType: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , dstBinding: 2 , pBufferInfo: cast[ ptr ptr VkDescriptorBufferInfo](addr text.uniBufferF.descriptor) , descriptorCount: 1 ) ] vkUpdateDescriptorSets(rec.vk_device, sets.len.uint32, addr sets[0], 0, nil) text.descrSet = dSet proc buildCommandBuffers*( rec: Vulkan_Record , text: SDFText , rp: VkRenderpass , i: int ) = var offsets = VkDeviceSize 0 vkCmdBindPipeline( rec.draw_command_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, text.graphicsPipeline.pipeline) vkCmdBindDescriptorSets( rec.draw_command_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, text.graphicsPipeline.pipelineLayout, 0, 1, addr text.descrSet, 0, nil) vkCmdBindVertexBuffers( rec.draw_command_buffers[i], 0, 1, addr text.vertexBuffer.vkbuffer, addr offsets) vkCmdBindIndexBuffer( rec.draw_command_buffers[i], text.indexBuffer.vkbuffer, VkDeviceSize 0, VK_INDEX_TYPE_UINT32) vkCmdDrawIndexed( rec.draw_command_buffers[i], text.indexCount , 1, 0, 0, 0) # , 1 ? text.camera.set_aspect_ratio_with( 60 , (float rec.swapchain.current_extent.width) / (float rec.swapchain.current_extent.height) ) rec.readyFrame = true proc setupDescrPool(rec: var Vulkan_Record , text: var SDFText ) = var sizes = [ VkDescriptorPoolSize( typee: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , descriptorCount: 4 ) , VkDescriptorPoolSize( typee: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , descriptorCount: 2 ) ] descpoolinfo = VkDescriptorPoolCreateInfo( sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO , poolSizeCount: sizes.len.uint32 , pPoolSizes: addr sizes[0] , maxSets: 2 ) discard vkCreateDescriptorPool(rec.vk_device, addr descpoolinfo, nil, addr text.descrPool) proc anSDFUBO*( outLineColor: Vec4[float32] = vec4f(1.float32, 0, 0, 0.0) , outLineWidth: float32 = 98.543 , isOutlined: bool = true ): UBOS = result = UBOS( vs: text_types.UBOVS() , fs: text_types.UBOFS() ) result.fs.outlineColor = outlineColor result.fs.outlineWidth = outlineWidth result.fs.outlined = 0.1 #[ proc updateCamera*( text: var SDFText ) = # if text.camera_type == Ortho: #text.ubos.vs.view = text.camera.matrices.view #text.camera.updateViewMatrix() # if text.camera_type == Perspective: # text.ubos.vs.proj = text.camera.matrices.persp # text.ubos.vs.view = text.camera.matrices.view # text.ubos.vs.model = mat4(1.0.float32).scale 0.16 # text.camera.updateViewMatrix() text.device[].map_memory( text.uniBufferV.memory , text.uniBufferV.data ) text.device[].map_memory( text.uniBufferF.memory , text.uniBufferF.data ) copymem(text.uniBufferV.data, addr text.ubos.vs, text.ubos.vs.sizeof) copymem(text.uniBufferF.data, addr text.ubos.fs, text.ubos.fs.sizeof) vkUnmapMemory(text.device[], text.uniBufferV.memory) vkUnmapMemory(text.device[], text.uniBufferF.memory) text.changed = false ]# proc rotate*( t: var SDFText , a, x,y,z: float32 ) = case t.camera_type of Ortho: t.ubos.vs.model = t.ubos.vs.model.rotate(radians a,x,y,z) #t.updateCamera of Perspective: discard proc move*( t: var SDFText , x,y: float32 ) = case t.camera_type of Ortho: t.ubos.vs.model = t.ubos.vs.model.translate(x,y,0) #t.updateCamera of Perspective: discard # TODO: outlined needs to be a bool in the fragment shader # but for some reason is currently a float32, that checks for >0.0 to outline proc updateFS*( t: var SDFText , outLineColor: Vec4[float32] = vec4f(1.float32, 0, 0, 0.1) , outLineWidth: float32 = 90 , outlined: float32 = 0.0 ) = t.ubos.fs.outLineColor = outlineColor t.ubos.fs.outLineWidth = outLineWidth t.ubos.fs.outlined = outlined #t.updateCamera proc strIs*( t: var SDFText , s: string #, rec: var Vulkan_Record ) = t.str = s t.strChanged = true t.theVkRec[].genVertBuffers( t , s ) t.strChanged = false # Vulkan is y neg # TODO: get rid of the hack. # currently the SDF text gets chopped off at the tops which messed up capital letters # after modifying the model(?) proc move_to*( t: var SDFText , x,y: float32 ) = case t.camera_type of Ortho: t.ubos.vs.model = mat4f(1) .translate(0,0,0) .translate(x,-y,0) # SDF text currently upside down # TODO: Actually fix please, thank you. .scale(t.size * 4.0) .rotate(radians -540.float32, 1,0,0) #var ts = t.str #t.updateCamera of Perspective: discard proc anSDFText*( rec: var Vulkan_Record , scene: var Scene , name: string , str: string , size: float32 , camTy: Camera_Kind = Ortho ): SDFText = result = SDFText( font: aPBMFont() , ubos: anSDFUBO() , texture: Texture2D() , indexBuffer: Buffer() , vertexBuffer: Buffer() , graphicsPipeline: GraphicsPipeline() , camera: aCamera( float32 ( rec.current_viewport.width / rec.current_viewport.height ) , camTy ) , name: name , device: addr rec.vk_device , id: scene.current_entity_id , size: size , theVkRec: addr rec , str: str ) rec.loadFromFile(result.texture) rec.genVertBuffers( result , str ) rec.prepare_uniform_buffers result rec.setupDescrSetLayout result rec.prepPipeline scene.render_pass, result.graphicsPipeline rec.setupDescrPool result rec.setupDescrSets result result.ubos.vs.proj = vkm.ortho( 0.float32 , rec.swapchain.current_extent.width.float32 , 0.float32 , rec.swapchain.current_extent.height.float32 , 0.0.float32 , -1000.0.float32 ) result.ubos.vs.model = mat4f(1) .scale(size * 4) # SDF text currently upside down # TODO: Actually fix please, thank you. .rotate(radians -540.float32, 1,0,0) result.ubos.vs.view = mat4f(1) #result.updateCamera ]#