BlueHour ☕

The hour between memory and weather. 🌘

  • The lamps are lit, though no one remembers lighting them.
  • Every road returns somewhere familiar, but never twice to the same place.
  • If a window shows you standing outside, please wait for the rain to correct itself.

Rest here. For a while, nothing is chasing you. ☕

Notes on Developing Vulkan on Mac

Setup environment on MacOS First, install the Vulkan SDK. I recommend downloading the latest version from the LunarG website. The default install path is usually /Users/$USER/VulkanSDK/version-number. The SDK includes a script named setup-env.sh for setting environment variables, so you need to run it every time your shell starts. Open your shell config file, such as /.zshrc for zsh or /.bash_profile for bash, and add the following line. This gives every new shell session the corresponding Vulkan environment variables, and CMake can also find Vulkan through find_package. # Note: replace this path with your actual VulkanSDK installation path source /Users/USER/VulkanSDK/1.3.xxx.x/setup-env.sh MoltenVK Apple’s native graphics API is Metal, and there is no native Vulkan implementation on macOS. So you need MoltenVK to translate Vulkan calls into Metal calls. If you installed the Vulkan SDK, MoltenVK is already included. One extra thing to watch out for: when creating Vulkan-related contexts, there are three places you need to configure. ...

2025-09-27 · 4 min · 672 words · BlueHour

C#, Java, and Cpp Communication in Unity

This post covers four things: How C# calls Java functions in Unity. How Java calls C++ through JNI. How C++ under JNI calls Java. How Java calls Unity’s C#. CSharp Call Java Use Unity’s AndroidJavaObject, and pass the Java class object into the constructor. The format is the package name followed by the class name. For example, in Java: package com.example.jni; public class ExampleJavaClass { // Function with no return value void TestFuncVoid(int a) { /* ... */ } // Function with a return value int TestFuncInt(int a) { /* ... */ } } In CSharp, write it like this: ...

2024-09-12 · 6 min · 1165 words · BlueHour

Cross-Compiling C++ for Android Without Android Studio

AndroidCppCrossCompile Android Studio has quite a few bugs, and the C++ development experience is not exactly great. A lot of the time, when we need to do JNI development or pure C++ development, we do not really want to do it inside Android Studio. So we need an environment for cross-compiling C++ programs for Android without relying on Android Studio. Next, I will use CMake to build the whole workflow. First, the preparation: you must download the NDK, because we need to use the NDK toolchain. The version I use here is r23c. ...

2023-12-17 · 5 min · 889 words · BlueHour

Using Arm64 Assembly on Android

AndroidAsm First, create an Android Studio JNI project. By default, the project will generate a C++ file that calls a native function from the Java side to display a string. The function generated on the Cpp side uses static binding, so the function name is extremely long and not very pleasant to look at. Let’s change it to dynamic binding first. Start by renaming that verbose function. JNIEXPORT jstring JNICALL StringFromJNI(JNIEnv *env, jclass clazz) { std::string hello { "Hello World From JNI" }; return env->NewStringUTF(hello.c_str()); } Next, implement dynamic binding. Add a function called JniOnLoad to the Cpp file, and load the native function from the Java side inside this function. ...

2023-10-16 · 3 min · 516 words · BlueHour

Lock-Free Programming

Lock-Free Programming The goal of lock-free programming is not to make synchronization “free”. It is to avoid as much of the extra overhead of traditional locks as possible in highly concurrent scenarios. In a multithreaded environment, the most common and simplest synchronization tool is still a lock. For example, many implementations of std::mutex try to stay in user space when there is no contention. But once contention becomes heavy, threads may block, wake up, and context switch, and performance can drop sharply. Even when the kernel is not involved, locks can still introduce cache synchronization, pipeline stalls, and scheduling overhead. ...

2023-04-21 · 52 min · 11028 words · BlueHour

Getting Started with OpenGL Using SFML

If you have ever taught yourself OpenGL, you probably remember the pain of pulling in a whole pile of libraries. GLEW and GLUT in particular are awkward to use. SFML makes opening a window very simple, and for anyone learning OpenGL, I think it can completely replace GLUT. So in this post I will use SFML to create the window, then write a casual OpenGL example: a simple forward renderer using the Phong model. ...

2021-10-22 · 10 min · 1979 words · BlueHour

Differential Geometry

Theory of Curves A Few Results I Often Forget Double cross product formula $$ (\vec{a} \times \vec{b}) \times \vec{c} = \vec{b} (\vec{a} \cdot \vec{c}) - \vec{a} (\vec{b} \cdot \vec{c}) $$ Lagrange identity $$ (\vec{a} \times \vec{b}) (\vec{c} \times \vec{d})= (\vec{a}\cdot\vec{c})(\vec{b}\cdot\vec{d})-(\vec{a}\cdot\vec{d})(\vec{b}\cdot\vec{c}) $$ Suppose the vector-valued function ${a}(t)$ is nowhere zero and continuously differentiable. Then the length of ${a}(t)$ is constant if and only if: $$ \vec{a}^{\prime}(t) \cdot \vec{a}(t) \equiv 0 $$ Regular Parametric Curves A parametric curve ${\textbf{r} }(t)$ is a regular parametric curve if it satisfies the following conditions: ...

2021-10-07 · 15 min · 3166 words · BlueHour

Topology 05 - Homogeneous Coordinates and Projective Geometry

Homogeneous Coordinates and Projective Geometry If you work in computer graphics, you deal with the following operations every day: A point in 3D space is written as a 4D vector $(x,y,z,w)$. $(x,y,z,w)$ and $(kx,ky,kz,kw)\;(k \neq 0)$ represent the same point. At render time, you perform a “perspective divide”: $(x/w,\;y/w,\;z/w)$. $w=0$ is treated as a “direction”—a point at infinity. This design is not a graphics programmer’s invention. Its roots lie in 19th-century projective geometry. Homogeneous coordinates are not an engineering hack; they are the most natural coordinate system for projective space. ...

2021-09-05 · 17 min · 3539 words · BlueHour

Topology 04 - Quaternions

Quaternions Algebraic Definition Let $\mathbb{H}=\lbrace a+bi+cj+dk \mid a,b,c,d \in \mathbb{R}\rbrace$. There is a vector-space structure on $\mathbb{H}$: $$ \cdot: \mathbb{R} \times \mathbb{H} \rightarrow \mathbb{H}: (\lambda, a+bi+cj+dk) \rightarrow (\lambda, \lambda a+\lambda bi+\lambda cj+\lambda dk) $$ $$ \begin{aligned} +:\mathbb{H} \times \mathbb{H} \rightarrow \mathbb{H}: (a_1+b_1i+c_1j+d_1k, a_2+b_2i+c_2j+d_2k) \\ \rightarrow (a_1+a_2, (b_1+b_2)i,(c_1+c_2)j,(d_1+d_2)k) \end{aligned} $$ Clearly $(\mathbb{H},+)$ is an abelian group, so $(\mathbb{H},+,\cdot)$ is an $\mathbb{R}$-linear space. In addition, we define a multiplication operation on $\mathbb{H}$. First set: $$ i^2=j^2=k^2=ijk=-1 $$ $$ ij=k,jk=i,ki=j,ji=-k,kj=-i,ik=-j $$ Then multiplication is defined componentwise. To keep the notation lighter, the imaginary part can be written as a vector: $\vec{v}=(b,c,d)$. A quaternion can then be written as $x=[a,\vec{v}]=a+\vec{v}$; this is only notation, and does not mean we are adding a scalar and a vector. ...

2021-08-30 · 8 min · 1678 words · BlueHour

Topology 03 - Quotient Sets

Quotients Quotient Sets Let $X$ be a set. An equivalence relation on $X$ is a relation that is reflexive, symmetric, and transitive. Let $X$ be a set, and let $\sim$ be an equivalence relation on $X$. For any $a \in X$, the set $\bar{a} =\lbrace b \in X | b \sim a \rbrace$ is the equivalence class containing $a$. An equivalence class is a special kind of subset: if two equivalence classes intersect, then they must actually be the same class (by transitivity). ...

2021-08-21 · 9 min · 1908 words · BlueHour