{"id":13537180,"url":"https://github.com/Dominaezzz/kgl","last_synced_at":"2025-04-02T04:30:25.380Z","repository":{"id":47462710,"uuid":"164507082","full_name":"Dominaezzz/kgl","owner":"Dominaezzz","description":"Thin multiplatform wrappers for graphics.","archived":true,"fork":false,"pushed_at":"2023-02-25T12:46:35.000Z","size":2521,"stargazers_count":105,"open_issues_count":13,"forks_count":13,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-03T02:32:32.881Z","etag":null,"topics":["glfw3","graphics","kgl","kotlin","kotlin-multiplatform","kotlin-native","opengl","vulkan","vulkan-api"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dominaezzz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-07T22:29:28.000Z","updated_at":"2024-09-15T15:08:51.000Z","dependencies_parsed_at":"2024-11-03T02:31:06.776Z","dependency_job_id":"3e17c530-de5a-429b-a84a-b12f8d73a0fa","html_url":"https://github.com/Dominaezzz/kgl","commit_stats":null,"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dominaezzz%2Fkgl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dominaezzz%2Fkgl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dominaezzz%2Fkgl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dominaezzz%2Fkgl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dominaezzz","download_url":"https://codeload.github.com/Dominaezzz/kgl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246756736,"owners_count":20828755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["glfw3","graphics","kgl","kotlin","kotlin-multiplatform","kotlin-native","opengl","vulkan","vulkan-api"],"created_at":"2024-08-01T09:00:55.955Z","updated_at":"2025-04-02T04:30:23.398Z","avatar_url":"https://github.com/Dominaezzz.png","language":"Kotlin","funding_links":[],"categories":["Libraries"],"sub_categories":["GUI"],"readme":"[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)\n[![](https://github.com/Dominaezzz/kgl/workflows/Build/badge.svg)](https://github.com/Dominaezzz/kgl/actions)\n\n# Kotlin Graphics Libraries\n\nKotlin Multiplatform libraries for graphics.\n- [GLFW](https://www.glfw.org)\n- [Vulkan](https://www.khronos.org/vulkan)\n- [OpenGL](https://www.opengl.org)\n- [STB](https://github.com/nothings/stb)\n\nKGL uses LWJGL for the JVM target and the respective native libraries on the native targets.\nIt provides a thin OOP wrapper with DSLs to make programming with vulkan easier.\n\nYou can find some kgl-vulkan samples [here](https://github.com/Dominaezzz/kgl-vulkan-samples) and kgl-opengl samples [here](https://github.com/Dominaezzz/kgl-opengl-samples).\n\n## Usage\n```kotlin\nrepositories {\n    maven(\"https://maven.pkg.github.com/Dominaezzz/kgl\") {\n        credentials {\n            username = System.getenv(\"GITHUB_USER\") // Your GitHub username.\n            password = System.getenv(\"GITHUB_TOKEN\") // A GitHub token with `read:packages`.\n        }\n    }\n}\n\ndependencies {\n    api(\"com.kgl:kgl-core:$kglVersion\")\n    api(\"com.kgl:kgl-glfw:$kglVersion\")\n    api(\"com.kgl:kgl-glfw-static:$kglVersion\") // For GLFW static binaries\n    api(\"com.kgl:kgl-opengl:$kglVersion\")\n    api(\"com.kgl:kgl-vulkan:$kglVersion\")\n    api(\"com.kgl:kgl-glfw-vulkan:$kglVersion\")\n    api(\"com.kgl:kgl-stb:$kglVersion\")\n}\n```\n\n## Design\nThe main goal of this library is to hide the verbosity of working with vulkan.\n\nFor example in C++, to create a vulkan instance one would have to write code like,\n```C++\nstd::vector\u003cstd::string\u003e layers = TODO();\nstd::vector\u003cstd::string\u003e extensions = TODO();\n\nVkApplicationInfo applicationInfo = {};\napplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;\napplicationInfo.pNext = nullptr;\napplicationInfo.pApplicationName = \"Kgl App\";\napplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);\napplicationInfo.pEngineName = \"No Engine yet\";\napplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);\napplicationInfo.apiVersion = VK_VERSION_1_1;\n\nVkInstanceCreateInfo createInfo = {};\ncreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;\ncreateInfo.pNext = nullptr;\ncreateInfo.flags = 0;\ncreateInfo.pApplicationInfo = \u0026applicationInfo;\ncreateInfo.enabledLayerCount = layers.size();\ncreateInfo.ppEnabledLayerNames = layers.data();\ncreateInfo.enabledExtensionCount = extensions.size();\ncreateInfo.ppEnabledExtensionNames = extensions.data();\n\nVkInstance instance;\nif (vkCreateInstance(\u0026createInfo, nullptr, \u0026instance) != VK_SUCCESS) {\n    throw std::runtime_error(\"Failed to create instance!\");\n}\n```\nbut in Kotlin (with the help of KGL),\n```kotlin\nval layers: List\u003cString\u003e = TODO()\nval extensions: List\u003cString\u003e = TODO()\n\nval instance = Instance.create(layers, extensions) {\n    applicationInfo {\n        applicationName = \"Kgl App\"\n        applicationVersion = VkVersion(1u, 1u, 0u)\n        engineName = \"No engine yet\"\n        engineVersion = VkVersion(1u, 0u, 0u)\n        apiVersion = VkVersion(1u, 1u, 0u)\n    }\n}\n```\n\nTo create a device in C++,\n```C++\nuint32_t deviceCount = 1;\nVkPhysicalDevice physicalDevice;\nvkEnumeratePhysicalDevices(instance, \u0026deviceCount, \u0026physicalDevice);\nif (deviceCount \u003c 1) throw std::runtime_error(\"Failed to find GPU with vulkan support.\");\n\nstd::vector\u003cVkDeviceQueueCreateInfo\u003e queueCreateInfos(2);\n\nfloat queuePriority = 1.0f;\n\nVkDeviceQueueCreateInfo\u0026 queueCreateInfo1 = queueCreateInfos[0];\nqueueCreateInfo1.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;\nqueueCreateInfo1.pNext = nullptr;\nqueueCreateInfo1.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED;\nqueueCreateInfo1.queueFamilyIndex = 1;\nqueueCreateInfo1.queueCount = 1;\nqueueCreateInfo1.pQueuePriorities = \u0026queuePriority;\n\nVkDeviceQueueCreateInfo\u0026 queueCreateInfo2 = queueCreateInfos[1];\nqueueCreateInfo2.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;\nqueueCreateInfo2.pNext = nullptr;\nqueueCreateInfo2.flags = 0;\nqueueCreateInfo2.queueFamilyIndex = 2;\nqueueCreateInfo2.queueCount = 1;\nqueueCreateInfo2.pQueuePriorities = \u0026queuePriority;\n\nVkPhysicalDeviceFeatures deviceFeatures = {};\ndeviceFeatures.samplerAnisotropy = VK_TRUE;\ndeviceFeatures.geometryShader = VK_TRUE;\ndeviceFeatures.depthClamp = VK_TRUE;\n\nstd::vector\u003cstd::string\u003e layers = TODO();\nstd::vector\u003cstd::string\u003e extensions = TODO();\n\nVkDeviceCreateInfo createInfo = {};\ncreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;\ncreateInfo.pNext = nullptr;\ncreateInfo.pQueueCreateInfos = queueCreateInfos.data();\ncreateInfo.queueCreateInfoCount = queueCreateInfos.size();\ncreateInfo.pEnabledFeatures = \u0026deviceFeatures;\ncreateInfo.enabledExtensionCount = extensions.size();\ncreateInfo.ppEnabledExtensionNames = extensions.data();\ncreateInfo.enabledLayerCount = layers.size();\ncreateInfo.ppEnabledLayerNames = layers.data();\n\nVkDevice device;\nif (vkCreateDevice(physicalDevice, \u0026createInfo, nullptr, \u0026device) != VK_SUCCESS) {\n    throw std::runtime_error(\"failed to create logical device!\");\n}\n```\nbut in Kotlin,\n```kotlin\nval physicalDevice = instance.physicalDevices.first()\n\nval device = physicalDevice.createDevice(layers, extensions) {\n    queues {\n        queue(1u, 1.0f) {\n            flags = DeviceQueueCreate.PROTECTED\n        }\n\n        queue(2u, 1.0f)\n    }\n\n    enabledFeatures {\n        samplerAnisotropy = true\n        geometryShader = true\n        depthClamp = true\n    }\n}\n```\n\n### Handles\nEvery vulkan handle has a class of it's own. The name of the class being the name of the handle without the `Vk` prefix.\nLike `Instance` for `VkInstance`, `CommandBuffer` for `VkCommandBuffer`, etc.\nAll handles keep a reference to their parent, to be able to destroy or free themselves later.\nSome handles hold a few values from their creation. Like `Image` has `size`, `layers` and `format` properies.\n\n### Structs\nInput structs on the other hand have a DSL builder class.\nOutput structs have a corresponding data class.\n```C++\ntypedef struct VkLayerProperties {\n    char        layerName[VK_MAX_EXTENSION_NAME_SIZE];\n    uint32_t    specVersion;\n    uint32_t    implementationVersion;\n    char        description[VK_MAX_DESCRIPTION_SIZE];\n} VkLayerProperties;\n```\n```kotlin\ndata class LayerProperties(\n    val layerName: String,\n    val specVersion: VkVersion,\n    val implementationVersion: UInt,\n    val description: String\n)\n```\n\n### Enums\nEnums are represented with a kotlin enum.\nIf the enum is a part a bitmask then it extends `VkFlag\u003cT\u003e` to allow for type-safe bit fiddling.\n```C++\ntypedef VkFlags VkCullModeFlags;\ntypedef enum VkCullModeFlagBits {\n    VK_CULL_MODE_NONE = 0,\n    VK_CULL_MODE_FRONT_BIT = 0x00000001,\n    VK_CULL_MODE_BACK_BIT = 0x00000002,\n    VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,\n} VkCullModeFlagBits;\n\nVkCullModeFlags flags = VK_CULL_MODE_FRONT_BIT | VK_CULL_MODE_BACK_BIT;\n```\n```kotlin\nenum class CullMode : VkFlag\u003cCullMode\u003e {\n    NONE,\n    FRONT,\n    BACK\n}\n\nval flags: VkFlag\u003cCullMode\u003e = CullMode.FRONT or CullMode.BACK\n```\nAlthough this does mean that bitwise operations create new objects.\nOnce inline enums are implemented in Kotlin, we'll get the type-safety without the allocations.\n\n### Commands\nEvery command's function pointer has been explicitly loaded using `vkGetDeviceProcAddr` and `vkGetInstanceProcAddr` for optimal command calling performance.\nThis also means you don't need to have the [Vulkan SDK](https://vulkan.lunarg.com/sdk/home) installed to get started with kgl-vulkan.\n\nAt the moment every core and extension (non-platform specific) command has been implemented as a member function/property of a handle class.\nIn most cases it is a member of the last of the first consecutive handles in the parameter list.\nIn other cases, it is moved to a handle class that makes the most sense.\n```C\nVkResult vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);\n```\n```kotlin\nfun DeviceMemory.map(offset: ULong, size: ULong, flags: VkFlag\u003cMemoryMap\u003e? = null): IoBuffer\n```\nor\n```C++\nVkResult vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);\n```\n```kotlin\nval Instance.physicalDevices: List\u003cPhysicalDevice\u003e\n```\n\n### GLFW Example\n```kotlin\nval window = Window(1080, 720, \"Sample!\") {\n    clientApi = ClientApi.None\n    resizable = false\n    visible = true\n}\n\nval (width, height) = window.size\nval mode = Glfw.primaryMonitor!!.videoMode\nwindow.position = ((mode.width - width) / 2) to ((mode.height - height) / 2)\n```\n\n## Limitations\n- OpenGL is only supported on native targets.\n- Only core OpenGL is supported and is loaded on the first gl function call.\n- Platform specific extensions have not been implemented yet. Mostly because of [this](https://youtrack.jetbrains.com/issue/KT-27801).\n- Support for pNext has not been implemented yet.\n- Some parts of the api that use an `IoBuffer` have not yet been implemented as it requires bespoke design.\n- Documentation is partially generated.\n- Until the bulk of library is under codegen, only version `1.1.92` will be supported.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDominaezzz%2Fkgl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDominaezzz%2Fkgl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDominaezzz%2Fkgl/lists"}