All Projects → Naitsirc98 → Vulkan-Tutorial-Java

Naitsirc98 / Vulkan-Tutorial-Java

Licence: other
Vulkan tutorial by Alexander Overvoorde ported to Java

Programming Languages

java
68154 projects - #9 most used programming language
GLSL
2045 projects

Projects that are alternatives of or similar to Vulkan-Tutorial-Java

rendering-fw
Rendering framework with rasterizers & path tracers implemented using Vulkan, OptiX & OpenGL
Stars: ✭ 81 (-8.99%)
Mutual labels:  vulkan, assimp
SFE-Engine
A real time renderer based on Vulkan(LWJGL).
Stars: ✭ 20 (-77.53%)
Mutual labels:  vulkan, lwjgl3
Vortex2D
Real-time fluid simulation engine running on GPU with Vulkan
Stars: ✭ 91 (+2.25%)
Mutual labels:  vulkan
Vulkan.jl
Simplify usage of Vulkan in Julia
Stars: ✭ 77 (-13.48%)
Mutual labels:  vulkan
osre
An open source render engine
Stars: ✭ 95 (+6.74%)
Mutual labels:  vulkan
VulkanResources
A list of resources for learning Vulkan
Stars: ✭ 50 (-43.82%)
Mutual labels:  vulkan
CrossWindow-Graphics
A header only library to simplify creating 🌋 Vulkan / ⚪ OpenGL / 🌐 WebGL / ❎DirectX / 🤖 Metal data structures with CrossWindow.
Stars: ✭ 48 (-46.07%)
Mutual labels:  vulkan
ncnn-android-squeezenet
The squeezenet image classification android example
Stars: ✭ 100 (+12.36%)
Mutual labels:  vulkan
vuk
vuk - A rendergraph-based abstraction for Vulkan
Stars: ✭ 167 (+87.64%)
Mutual labels:  vulkan
solo
Small C++ game engine with Lua scripting
Stars: ✭ 26 (-70.79%)
Mutual labels:  vulkan
hms-computer-graphics-demo
This is the demo project of CGKit(Short for computer graphics kit). CGKit is a vulkan-based rendering framework, which is designed to improve performance of vulkan devices, especially for Android platform. This project will show you how to load textures, models, add pbr effects and render with vulkan.
Stars: ✭ 19 (-78.65%)
Mutual labels:  vulkan
assimpjs
The emscripten interface for the assimp library that allows you to import 40+ 3D file formats in the browser.
Stars: ✭ 19 (-78.65%)
Mutual labels:  assimp
gl vk bk3dthreaded
Vulkan sample rendering 3D with 'worker-threads'
Stars: ✭ 80 (-10.11%)
Mutual labels:  vulkan
Xacor
Experimental Game Engine
Stars: ✭ 24 (-73.03%)
Mutual labels:  vulkan
vktut
Shabi's Vulkan Tutorials
Stars: ✭ 88 (-1.12%)
Mutual labels:  vulkan
nanovg vulkan
Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations. (added Vulkan support)
Stars: ✭ 26 (-70.79%)
Mutual labels:  vulkan
tokonoma
Graphics related projects/prototypes/playground (Vulkan, C++17)
Stars: ✭ 23 (-74.16%)
Mutual labels:  vulkan
pygfx
Like ThreeJS but for Python and based on wgpu
Stars: ✭ 72 (-19.1%)
Mutual labels:  vulkan
gearoenix
Cross-platform C++ 3D game engine.
Stars: ✭ 33 (-62.92%)
Mutual labels:  vulkan
kool
A Vulkan/OpenGL engine for Desktop Java and Javascript written in Kotlin
Stars: ✭ 76 (-14.61%)
Mutual labels:  vulkan

Vulkan-Tutorial-Java

Java port of the great tutorial by Alexander Overvoorde. The original code can be found here.

Tutorial Image 3


Introduction

These tutorials are written to be easily followed with the C++ tutorial. However, I've made some changes to fit the Java and LWJGL styles. The repository follows the same structure as in the original one.

Every chapter have its own Java file to make them independent to each other. However, there are some common classes that many of them need:

  • AlignmentUtils: Utility class for dealing with uniform buffer object alignments.
  • Frame: A wrapper around all the necessary Vulkan handles for an in-flight frame (image-available semaphore, render-finished semaphore and a fence).
  • ModelLoader: An utility class for loading 3D models. They are loaded with Assimp.
  • ShaderSPIRVUtils: An utility class for compiling GLSL shaders into SPIRV binaries at runtime.

For maths calculations I will be using JOML, a Java math library for graphics mathematics. Its very similar to GLM.

Finally, each chapter have its own .diff file, so you can quickly see the changes made between chapters.

Please note that the Java code is more verbose than C or C++, so the source files are larger.

LWJGL

I'm going to be using LWJGL (Lightweight Java Game Library), a fantastic low level API for Java with bindings for GLFW, Vulkan, OpenGL, and other C libraries.

If you don't know LWJGL, it may be difficult to you to understand certain concepts and patterns you will see throughout this tutorials. I will briefly explain some of the most important concepts you need to know to properly follow the code.

Native handles

Vulkan has its own handles named properly, such as VkImage, VkBuffer or VkCommandPool. These are unsigned integer numbers behind the scenes, and because Java does not have typedefs, we need to use long as the type of all of those objects. For that reason, you will see lots of long variables.

Pointers and references

Some structs and functions will take as parameters references and pointers to other variables, for example to output multiple values. Consider this function in C:

int width;
int height;

glfwGetWindowSize(window, &width, &height);

// Now width and height contains the window dimension values

We pass in 2 int pointers, and the function writes the memory pointed by them. Easy and fast.

But how about in Java? There is no concept of pointer at all. While we can pass a copy of a reference and modify the object's contents inside a function, we cannot do so with primitives. We have two options. We can use either an int array, which is effectively an object, or to use Java NIO Buffers. Buffers in LWJGL are basically a windowed array, with an internal position and limit. We are going to use these buffers, since we can allocate them off heap, as we will see later.

Then, the above function will look like this with NIO Buffers:

IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer height = BufferUtils.createIntBuffer(1);

glfwGetWindowSize(window, width, height);

// Print the values 
System.out.println("width = " + width.get(0));
System.out.println("height = " + height.get(0));

Nice, now we can pass pointers to primitive values, but we are dynamically allocating 2 new objects for just 2 integers. And what if we only need these 2 variables for a short period of time? We need to wait for the Garbage Collector to get rid of those disposable variables.

Luckily for us, LWJGL solves this problem with its own memory management system. You can learn about that here.

Stack allocation

In C and C++, we can easily allocate objects on the stack:

VkApplicationInfo appInfo = {};
// ...

However, this is not possible in Java. Fortunately for us, LWJGL allows us to kind of stack allocate variables on the stack. For that, we need a MemoryStack instance. Since a stack frame is pushed at the beginning of a function and is popped at the end, no matter what happens in the middle, we should use try-with-resources syntax to imitate this behaviour:

try(MemoryStack stack = stackPush()) {

  // ...
  
  
} // By this line, stack is popped and all the variables in this stack frame are released

Great, now we are able to use stack allocation in Java. Let's see how it looks like:

try(MemoryStack stack = stackPush()) {

  IntBuffer width = stack.mallocInt(1); // 1 int unitialized
  IntBuffer height = stack.ints(0); // 1 int initialized with 0

  glfwGetWindowSize(window, width, height);

  // Print the values 
  System.out.println("width = " + width.get(0));
  System.out.println("height = " + height.get(0));
}

Now let's see a real Vulkan example with MemoryStack:

private void createInstance() {

    try(MemoryStack stack = stackPush()) {

        // Use calloc to initialize the structs with 0s. Otherwise, the program can crash due to random values

        VkApplicationInfo appInfo = VkApplicationInfo.callocStack(stack);

        appInfo.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO);
        appInfo.pApplicationName(stack.UTF8Safe("Hello Triangle"));
        appInfo.applicationVersion(VK_MAKE_VERSION(1, 0, 0));
        appInfo.pEngineName(stack.UTF8Safe("No Engine"));
        appInfo.engineVersion(VK_MAKE_VERSION(1, 0, 0));
        appInfo.apiVersion(VK_API_VERSION_1_0);

        VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.callocStack(stack);

        createInfo.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
        createInfo.pApplicationInfo(appInfo);
        // enabledExtensionCount is implicitly set when you call ppEnabledExtensionNames
        createInfo.ppEnabledExtensionNames(glfwGetRequiredInstanceExtensions());
        // same with enabledLayerCount
        createInfo.ppEnabledLayerNames(null);

        // We need to retrieve the pointer of the created instance
        PointerBuffer instancePtr = stack.mallocPointer(1);

        if(vkCreateInstance(createInfo, null, instancePtr) != VK_SUCCESS) {
            throw new RuntimeException("Failed to create instance");
        }

        instance = new VkInstance(instancePtr.get(0), createInfo);
    }
}

Drawing a triangle

Setup

Base code

Read the tutorial

c++Original code

javaJava code

Instance

Read the tutorial

c++Original code

javaJava code

diffDiff

Validation layers

Read the tutorial

c++Original code

javaJava code

diffDiff

Physical devices and queue families

Read the tutorial

c++Original code

javaJava code

diffDiff

Logical device and queues

Read the tutorial

c++Original code

javaJava code

diffDiff

Presentation

Window surface

Read the tutorial

c++Original code

javaJava code

diffDiff

Swap chain

Read the tutorial

c++Original code

javaJava code

diffDiff

Image views

Read the tutorial

c++Original code

javaJava code

diffDiff

Graphics pipeline basics

Introduction

Read the tutorial

c++Original code

javaJava code

diffDiff

Shader Modules

The shaders are compiled into SPIRV at runtime using shaderc library. GLSL files are located at the resources/shaders folder.

Read the tutorial

c++Original code

javaJava code

diffDiff

Fixed functions

Read the tutorial

c++Original code

javaJava code

diffDiff

Render passes

Read the tutorial

c++Original code

javaJava code

diffDiff

Conclusion

Read the tutorial

c++Original code

javaJava code

diffDiff

Drawing

Framebuffers

Read the tutorial

c++Original code

javaJava code

diffDiff

Command buffers

Read the tutorial

c++Original code

javaJava code

diffDiff

Rendering and presentation

Read the tutorial

c++Original code

javaJava code

diffDiff

Swapchain recreation

Read the tutorial

c++Original code

javaJava code

diffDiff

Vertex buffers

Vertex input description

(Will cause Validation Layer errors, but that will be fixed in the next chapter)

Read the tutorial

c++Original code

javaJava code

diffDiff

Vertex buffer creation

Read the tutorial

c++Original code

javaJava code

diffDiff

Staging buffer

Read the tutorial

c++Original code

javaJava code

diffDiff

Version with dedicated Transfer Queue

javaJava code

diffDiff

Index buffer

Read the tutorial

c++Original code

javaJava code

diffDiff

Uniform buffers

Uniform Buffer Object

Descriptor layout and buffer

Read the tutorial

c++Original code

javaJava code

diffDiff

Descriptor pool and sets

Read the tutorial

c++Original code

javaJava code

diffDiff

Texture mapping

Images

Read the tutorial

c++Original code

javaJava code

diffDiff

Image view and sampler

Read the tutorial

c++Original code

javaJava code

diffDiff

Combined image sampler

Read the tutorial

c++Original code

javaJava code

diffDiff

Depth buffering

Read the tutorial

c++Original code

javaJava code

diffDiff

Loading models

The models will be loaded using Assimp, a library for loading 3D models in different formats which LWJGL has bindings for. I have wrapped all the model loading stuff into the ModelLoader class.

Read the tutorial

c++Original code

javaJava code

diffDiff

Generating Mipmaps

Read the tutorial

c++Original code

javaJava code

diffDiff

Multisampling

Read the tutorial

c++Original code

javaJava code

diffDiff


Icons made by Icon Mafia

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].