#[ #{.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 ]#