There’s a lot of ffmpeg build script out there you can find on the Internet. But I can find none of them using r21e with FFMpeg 4.3. So, let’s build it.

It seems r21e has different C compiler path. clang is separated from gcc toolchains.

CC=$CLANG_TOOLCHAIN/bin/aarch64-linux-android30-clang
CXX=$CLANG_TOOLCHAIN/bin/aarch64-linux-android30-clang++

The configure is not that hard, although the build process takes really long. Since we are using libav only, I disable all standalone program like ffmpeg, ffplay.

Those lovely libxxxx.a file will reside in ./android/arm64.

If you are using Qt Creator. API Level Should changed to at least 28. Contact me if you need pre-compiled binary.


The story starts here: kotlin has been out for a while. But Qt’s kotlin support is zero. It will scare away many beginners

Add Kotlin Support in Existing Qt Project

There’s no template project for Kotlin development in Qt. For those who are not familiar with Gradle or Qt for Android. Here I provide the instructions to create Kotlin+Qt android project with minimum modification to original template.

  • Step 1 — Create Template

Navigate to Projects/Build/Build Steps. Click the “Create Templates” button.


For string searching, it is easy to come up with a naive solution for string searching

However the naive solution takes O(MN), where N and M denote the length of str and pattern respectively. And often, we meet the worst case.

str=aaaaaaaaaaaaaaaa; pattern=aaaaaaaab

for each position i in str, we need to compare the pattern ‘til the end.

The intuition is that we have known that the prefix a* is already compared and matched. We only need to make sure if the next one is b. Take a look at more example

str=abcd[e]; pattern=abcd[f]
// strstr(str, pattern) == [];


I’ve been use cmake+vscode workflow happily for years. Both cpptool and cmake-tool work well and they interlope perfectly. Recently, I started heavy development of embedded device. It seems cmake-tool is buggy here, but I cannot abandon cmake. So I started reading the document of cmake server to extract the configuration of the project especially includePath.

You can start server by following command

cmake -E server --debug --experimental

When you start the server, it will print its protocol version to standard output. notice an empty line before the response text.


[== "CMake Server" ==[
{"supportedProtocolVersions":[{"isExperimental":true,"major":1,"minor":2}],"type":"hello"}
]== "CMake Server" ==]

Now do…


Since I need fast autograd for my research, and PyTorch naturally becomes my best choice. Calculating stuff in batch make my code more elegant. Some are harder to achieve, especially when the if-else clause involved in.

PyCUDA is one of CUDA binding for python. Since it creates its own CUDA context, we should do some dirty trick to share context with pytorch. I found this solution somewhere(stackoverflow?)

https://gist.github.com/tim37021/2aaaed0b563d83d69fa17226e5b663ee

There is another choice to execute CUDA kernel in Python: CuPy. …


有發現自己比較適合閱讀字少少的哲學書,可以讓我在腦中細細品味。《薄伽梵歌》只有七百行就特別適合我!不過當初會拿來閱讀只是聽說愛因斯坦明明是無神論者,他卻也讀過這本書,而這本書是宗教的經典。同為無神論者的我也很想要一探究竟!

本書的故事背景是阿朱那面對持國諸子而怯戰,在一旁的克里希那給予一個靈性的教誨。學習如何不執著,無私的付出,享受行動當下即刻的果實。

小時候師長總是教導要不生氣,這壓抑了我們自然的情緒,華人總是重視表面上的和諧,但內心早已掀起巨大波瀾,等到衝突發生之時往往已經無可挽回。不生氣其實是不執著的一部分,但我們往往只理解表面上的意思,這容易落入”執著於不執著”的陷阱之中。

物質社會充斥的現代生活,精神生活的論述總是被非常表面的解讀成一種幹話。真理很有趣,它是一種覺知的知識,也可以說一種感覺或思考脈絡,他不能很容易的言傳。我還記得海濤法師前陣子爭議性的"劈腿都是假的!",這大概是在說「空性」吧!其實這是一個看似消極的積極論述。劈腿或是無縫發生的時候,其實感情大概已經生變很久了,最後人往往只在意那個具體事件,留下滿滿的憎恨,長期下來那樣的憎恨繼續荼毒自己的身心。

事件本身是中性的,沒有對錯好壞!

你無法接受嗎?這樣想好了,事發當下也許是別人的錯,但在事發之後我們的情緒管控就是自己的問題了。人對事件的認知來自於個人的主觀,本書也有說我們必須超越成敗的看待事情(化解二元對立)

得就是失,失就是得

道德觀不停的告訴我們什麼是對的什麼是好的什麼是成功的,其實這反而會加深我們對事件的執著。所有的事情都具有正反兩面,而我們往往只看到事情的其中一面。可能我們在創業成功之時會得大頭症,忘了自己失去陪伴家人的時間,在失敗的時候會一蹶不振,卻忘了自己獲得了個寶貴的經驗。很多時候我們只想要得,所以才會痛苦萬分。但是這本身是違反自然法則的

提倡不執著,也是提倡一種寧靜自在的生活觀。怎麼做呢?怎麼樣做事不綁手綁腳,而能做出全然自由的行動呢?其實這是之前的我一直想獲得的答案。這本書就說,把行動想成一種獻祭,所有行動都是奉獻給上帝,就能達成無私。其實就是Just Do It,會綁手綁腳是因為我們對一直成功有所執著,但是又有誰只會成功呢?「享受行動即刻的果實」也就是覺察與活在當下,而非期待未來的快樂

讀到這邊我恍然大悟,常常我們會看到有人拿貴重金子去拜拜,想說這樣就可以獲得更強的成效,我才發現,經書根本就不是這樣說,也許帶著執念去信宗教,那就會獲得滿滿的執念的宗教觀吧。原來上帝不是讓自己心想事成的上帝,造物者只創造萬物的和諧。人與上帝,如同i之於旋轉與傅立葉轉換,i是什麼?我們看不到,但它開啟了我們新的視野。

若以「心靈和諧,歲月靜好」為本,那還真的有一條路給你走。我還記得有一天,我的同學跑來跟我說:「欸,我剛讀六祖禪經,很多跟你說的很像欸!」其實進而確認之後,發現幾乎是等價的!

也許真理是超越宗教的吧!唯有還沒悟得的人,才會覺得世界上有很多宗教。從歷史下去看,宗教造成非常多的麻煩。但宗教仍然有其存在的必要,畢竟每個人生長環境不同,可以接受的悟道途徑也不同,也就是每個人需要有不同的導師。以一個例子來說,我們傾向於相信與自己有類似處境的人講出的話,小時候我被霸凌,媽媽就叫我檢討自己?當下只覺得我何錯之有?「你不是我,你不懂啦。」在了悟這些之後,我才發現原來我媽媽早就跟我說過了!現在甚至認為,相同處境的人有時候也不見得能給予適當的建議。書本章節的導讀也有說

在一個還沒了悟的人面前,也許上帝站在他旁邊他也不會發現吧。

其實再寫下去根本寫不完,《薄伽梵歌》某種程度上完全解除了我長期內心的衝突,向外求永遠求不得又陷自己於不利,那只能試著往內看,再從自我覺察了解整個宇宙。《翠玉錄》也有說:

as the universe, so the soul.


最近這些日子需要用到自動微分選擇了pytorch,batch運算有時候很爽快,只不過依然有某些操作實在很難寫,尤其是batch運算裡面有if-else的。比如以下:

這段是針對一個ray,如果是batch of rays實在很難改…

於是就想到用CUDA,不過缺點就是這時候gradient要自己手算了,之後我會再介紹怎麼樣寫autograd。

PyCUDA按字面意思就是python的cuda binding。只是他當初設計時並沒有考慮跟其他lib交互…所以他會自己創一個CUDA Context,我們得用髒髒的方式讓他跟Pytorch共用Context,就省下GPU->CPU->GPU的垃圾途徑。

使用上:

其實還蠻簡單的,torch tensor丟給Holder。剩下就是PyCUDA跟CUDA的使用,各位可以自己去看document。

解說一下

1. SourceModule的no_extern_c的意思,就是要他用C++模式去編譯,因為SDK附的helper_math.h是滿滿的C++

2. 我們自己的code去extern “C”,是因為c++ mangling會讓pycuda找不到ray_sphere這個symbol,因此我們放棄函數多載(function overloading)等C++特徵去export這個symbol,就可以用原始名稱找到這個函數。


我們都知道python中,array的slice可以用下面來描述;

arr[start:end:stride]

1. stride在音訊處理上可以拿來做downsampling,圖片的話拿來做品質很差的mipmap。

signal = signal[::2]

2. 全選剩餘的所有dimension -> arr[...]

3. 比較運算子

arr = np.asarray([-1, 0, 1, -1, 2, 3])# [False, True, True, False, True, True]
arr!=-1

4. np.where

np.where拿來整理出,比較後,結果是True的index是多少。筆者之前不知道有這個function的時候,為了加速幹了不少髒事情。不過後來發現有個numba可以做python jit,這改天再介紹

# [1, 2, 4]
np.where(arr!=-1)

5. Array subscribe with array

這功能拿來多選(可以複選)

6. 指定運算子

要用指定運算子等號左右邊數量要一樣,或是右邊有一個list或tuple,dimension要跟左邊最後一個維度一樣。4跟5的技巧一起使用,常常拿來做thresholding

7. Structured array

關於Structured Array網路上很少有著墨,大概因為ML用不太到。這裡用我論文實作舉例,補充幾個用法。

假設我們要用描述一批射線,需要原點跟方向,他們各自都是R^3空間下。hits用來描述射線打到物體時的資訊,其中tri是三角形編號,沒打中的話t=-1.0, tri=-1

由於使用C Library去做加速,得確保little-endian,因此明確寫<i4

rays = np.zeros(shape=(600, 800), dtype=[('o', '<f4', 3), ('d', '<f4', 3)])
hits = np.zeros(shape=(600, 800), dtype=[('t', '<f4'), ('tri', '<i4')])

存取這些射線很簡單:

# 我覺得第一個方法比較合語意
rays[...]['o']
rays['o']

存取打中物體的射線

active_rays = rays[hits[...]['tri']!=-1]

以光跡追蹤,我們要用這些active_rays繼續延伸射線

之後逆向跌代會用到這些active_indices,只是這超出本章要講述的範圍。有機會再說我怎麼用python寫path tracer


最近NVidia RTX顯卡很紅,我想原本的OptiX光跡追蹤引擎應該也因此被加速了不少。其中OptiX Prime是他的Low-level API,拿來讓你做triangle hit test

最近要實作論文就把OptiX Prime弄了個Python binding出來。為什麼是python?其實有在搞Graphics的人都知道:每次要寫ABCDEFG part你才看得到畫面,然而你只想寫C part,這實在浪費很多時間。所以我選擇用python來整合Library。

因為自動產生binding的code目前手動還是有點多。之後有空我會弄好程式碼給大家安裝使用。

其實prime是一個很簡單的library,有幾個大觀念各位需要知道:

  1. Context:就是你知道的Context,可以選擇要CUDA/CPU運算
  2. BufferDesc:用來描述Buffer (長度/Stride/是GPU記憶體?)
  3. Model:模型。通常由vertices跟indices組成(他可以讓你選)
  4. Query:模型對一個批次的Ray做Hit Test,結果會存在Hit Buffer

我寫的pyoptixprime用起來基本上跟C++ API沒啥兩樣,完全沒高階封裝,不用擔心要學兩套。

大概只要import這些就行了,不過pytorch或cupy都可以用(如果你想要最純粹的GPU加速)

import pyoptixprime as prime
import numpy as np
#import torch
#import cupy as cp
ctx = prime.Context(prime.RTP_CONTEXT_TYPE_CUDA)

這裡講比較複雜的BufferDesc,以建立Ray跟Hit為例子,然後再送去Query查詢,Query結束之後,答案會存在hits裡面,可以繼續用numpy操作

可以看到BufferDesc用來描述自己指向的那個緩衝區的格式。對於Ray的origin/Dir大家應該沒什麼意見,但Hits只支援t跟三角形ID就說不過去了。當然這不可能!以下是支援的Format,基本上T_TRIID_U_V就很夠用了。


現在大家對軟體的顏值要求不斷上升。因此,最近幾年一直使用Electron開發一些對UI/UX高要求的程式,比如SLiMTAB和ChessGameDesigner。

說老實話,Web-based UI真的讓排版變很簡單,尤其你家UI/UX人員還有機會學會這些東西,幫你弄出Layout。甚至還有很多動態UI套件可以直接使用。

我們來看第一個例子SLiMTAB:

SLiMTAB — 樂譜編輯軟體。

中間樂譜就用SVG畫出來的!有夠方便,放大縮小功能天生支援,還能把樂譜匯出成PDF,這也是我用javascript寫出的第一支程式。

許友綸

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store