{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreicx3qm6gy4g236yp3pxtbuqstsclxrvy25iv7xpfdu5fci3ndwycy",
    "uri": "at://did:plc:dxjzgxe7cvirxkwfjr2tjspt/app.bsky.feed.post/3mjipvcz4n2m2"
  },
  "path": "/t/jme-vulkan/49551#post_1",
  "publishedAt": "2026-04-13T08:33:17.000Z",
  "site": "https://hub.jmonkeyengine.org",
  "tags": [
    "icyboxs/jmonkeyengine-vulkan",
    "github.com/icyboxs/jmonkeyengine-vulkan",
    "jme3-lwjgl3/src/main/java/com/jme3/renderer/vulkan/VKRenderer.java",
    "aac0d5cf3",
    "@author",
    "@Override"
  ],
  "textContent": "icyboxs/jmonkeyengine-vulkan\n\ngithub.com/icyboxs/jmonkeyengine-vulkan\n\n#### jme3-lwjgl3/src/main/java/com/jme3/renderer/vulkan/VKRenderer.java\n\naac0d5cf3\n\n\n\n\n\n\n        25. import java.nio.ByteBuffer;\n\n\n        26. import java.util.EnumMap;\n\n\n        27. import java.util.EnumSet;\n\n\n        28. import java.util.logging.Level;\n\n\n        29. import java.util.logging.Logger;\n\n\n        30.\n\n        31. /**\n\n\n        32.  *\n\n\n        33.  * @author icyboxs\n\n\n        34.  */\n\n\n        35. public final class VKRenderer implements Renderer, VkCommandRecorder {\n\n\n        36.\n\n        37.     private static final Logger LOGGER = Logger.getLogger(VKRenderer.class.getName());\n\n\n        38.\n\n        39.     private final VulkanRuntime runtime;\n\n\n        40.\n\n        41.     private final Statistics stats = new Statistics();\n\n\n        42.     private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);\n\n\n        43.     private final EnumMap<Limits, Integer> limits = new EnumMap<>(Limits.class);\n\n\n        44.\n\n        45.     private boolean initialized = false;\n\n\n\n\n\nCurrently, the shaders for the project are not yet completed, and there is only a demonstration shader available.\nI have been too busy recently and haven’t had time to work on it yet.\nThere is also a large amount of Chinese text in the project that has not been translated into English (I’ll handle the translation when I have time, so that others can read it).\n\nI’m not yet sure how the jMonkeyEngine (JME) project handles incubation, as there seems to be a lack of guidance on this in the community.\n\nI hope someone can help test this project so I can identify what functionalities are still missing.\n\nI’ve implemented the Vulkan part based on the frontend logic in the JME core, but some features currently rely solely on OpenGL-specific functionality that does not exist in Vulkan.\n\nMy hope is that this project can be incubated by the community until it reaches the same level of stability and usability as the current OpenGL components.\n\nI’m not a proficient Vulkan user, so the design is bound to have flaws.\nIf you have any questions or doubts, please feel free to leave a message here.\n\n\n    package com.example.JmeTest;\n\n    import com.jme3.app.FlyCamAppState;\n    import com.jme3.app.SimpleApplication;\n    import com.jme3.audio.AudioListenerState;\n    import com.jme3.material.Material;\n    import com.jme3.math.ColorRGBA;\n    import com.jme3.renderer.vulkan.context.LwjglVulkanContext;\n    import com.jme3.scene.Geometry;\n    import com.jme3.scene.shape.Box;\n    import com.jme3.system.AppSettings;\n    import com.jme3.texture.Image;\n    import com.jme3.texture.Texture;\n    import com.jme3.texture.Texture2D;\n    import com.jme3.texture.image.ColorSpace;\n    import com.jme3.util.BufferUtils;\n    import java.awt.image.BufferedImage;\n    import java.io.File;\n    import java.nio.ByteBuffer;\n    import javax.imageio.ImageIO;\n\n    public class HelloVulkan extends SimpleApplication {\n\n        // 声明变量,但不在这里初始化 (避免 AssetManager 报空指针)\n        private Material mat;\n        private Texture tex;\n        private Texture tex1;\n\n        // 用于记录累计时间\n        private float timer = 0f;\n        // 标记当前使用的是哪张贴图 (true 代表 tex, false 代表 tex1)\n        private boolean useTex1 = true;\n\n        // 【新增】:用于控制 FPS 更新频率的计时器\n        private float fpsTimer = 0f;\n\n        public static void main(String[] args) {\n            HelloVulkan app = new HelloVulkan();\n\n            AppSettings settings = new AppSettings(true);\n            settings.setTitle(\"JME Vulkan\");\n            settings.setWidth(1280);\n            settings.setHeight(720);\n            settings.setRenderer(AppSettings.LWJGL_VULKAN);\n            // 如果开启 VSync,FPS 将被限制在显示器的刷新率(如 60 或 144)\n            settings.setVSync(true);\n            settings.setCustomRenderer(LwjglVulkanContext.class);\n            app.setShowSettings(false);\n            app.setSettings(settings);\n            app.start();\n        }\n\n        public HelloVulkan() {\n            super(new AudioListenerState(), new FlyCamAppState());\n        }\n\n        @Override\n        public void simpleInitApp() {\n            Box box = new Box(2f, 2f, 2f);\n            Geometry geom = new Geometry(\"MultiSetBox\", box);\n\n            // 初始化材质\n            mat = new Material(assetManager, \"Common/MatDefs/Misc/VKUnshaded.j3md\");\n            geom.setMaterial(mat);\n\n            // 必须在 simpleInitApp 中调用 assetManager\n            tex = assetManager.loadTexture(\"sky.png\");\n            tex1 = assetManager.loadTexture(\"test.png\"); // 确保你真的有 Test.png 文件\n\n            // 初始设置第一张贴图\n            mat.setTexture(\"ColorMap\", tex);\n\n            rootNode.attachChild(geom);\n            viewPort.setBackgroundColor(ColorRGBA.Green);\n\n            // ==========================================\n            // 相机与鼠标控制设置\n            // ==========================================\n            flyCam.setEnabled(true);\n            flyCam.setMoveSpeed(10f);\n            flyCam.setRotationSpeed(2f);\n            flyCam.setDragToRotate(true);\n        }\n\n        @Override\n        public void simpleUpdate(float tpf) {\n            // 每一帧都把经过的时间 (tpf) 累加到计时器上\n            timer += tpf;\n\n            // 【新增】:累计 FPS 计时器\n            fpsTimer += tpf;\n            // 每 0.5 秒更新一次标题栏,避免更新过快导致看不清\n            if (fpsTimer >= 0.5f) {\n                // getTimer() 返回的是 JME 引擎底层的 Timer 对象\n                int fps = (int) getTimer().getFrameRate();\n                context.setTitle(\"JME Vulkan - FPS: \" + fps);\n                fpsTimer -= 0.5f;\n            }\n\n            // 判断是否已经积累了 3 秒\n            if (timer >= 3.0f) {\n\n                // 交替切换贴图逻辑\n                if (useTex1) {\n                    // 如果当前是 tex,就换成 tex1\n                    mat.setTexture(\"ColorMap\", tex1);\n                    System.out.println(\"Switched to Test.png\");\n                } else {\n                    // 如果当前是 tex1,就换回 tex\n                    mat.setTexture(\"ColorMap\", tex);\n                    System.out.println(\"Switched to sky.png\");\n                }\n\n                // 反转状态标记\n                useTex1 = !useTex1;\n\n                // 扣除 3 秒,保证周期精准\n                timer -= 3.0f;\n            }\n        }\n    }\n\n\nThis is the startup method.\n\nSome thoughts:\n\nTheoretically, Vulkan should indeed be faster than OpenGL, but that requires optimization for different targets to truly shine.\nI hope to gradually transition jME3 to modern APIs step by step.\nI haven’t looked closely at Android and Mac compatibility yet — Android likely needs some JNI work for support, and Mac has its own APIs.\nMaking all of these compatible still has a long way to go.\n\nOh, by the way, I haven’t conducted any tests on Linux. Currently, I don’t have any devices at hand. I have only performed the running tests on Windows 10.\n\nI cannot guarantee that this is the perfect way to run Vulkan. The details of other engines vary greatly and each has its own unique approach.",
  "title": "jme-Vulkan"
}