最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

GLSL 學(xué)習(xí)筆記

2023-08-31 20:44 作者:友紀(jì)V-入OP  | 我要投稿


其實(shí)我也在迷路

為啥學(xué)這玩意?

翻伊月クロ老師的本子時(shí),發(fā)現(xiàn)他上調(diào)子完全只使用墨汁(純黑)和網(wǎng)點(diǎn),沒有任何灰度,發(fā)現(xiàn)這種方式能很快出效果且很有味道,又意識到網(wǎng)點(diǎn)對打印機(jī)友好,將來要是打印自己的作品的話會很方便,不需要很好的打印機(jī)。

然后找到一個(gè)網(wǎng)點(diǎn)的筆刷,繪制時(shí)發(fā)現(xiàn)難以保證純黑白的基礎(chǔ)上做漸變(就像刮刀),下面是最終得到的效果和實(shí)現(xiàn)方式的說明,基本原理是對網(wǎng)點(diǎn)的濾鏡應(yīng)用一個(gè)有明顯漸變的純黑白的不透明度蒙版(在 ps 里是剪切蒙版?),即做一個(gè)減法。

before
after
  1. 繪制網(wǎng)點(diǎn)

  2. 在網(wǎng)點(diǎn)下方建立一個(gè)圖層,填充一個(gè)顏色

  3. 應(yīng)用噪聲濾鏡,級別調(diào)到最高,生成就像電視沒臺時(shí)的噪聲圖

  4. 在噪聲圖層上創(chuàng)建一個(gè)圖層,混合模式調(diào)整為線性光 Linear Light,它是線性減淡(相加)和線性加深(相乘、正片疊底)的混合,在亮度大于 0.5 時(shí)使用相加,小于 0.5 時(shí)使用線性加深

  5. 修改前景色為純黑,背景色為純白,在該圖層拉一個(gè)前景色到背景色的漸變

  6. 合并這兩個(gè)圖層,做一個(gè)閾值濾鏡,調(diào)整至邊緣位置合適;漸變的拉的方式和閾值的設(shè)置會影響邊緣的位置和柔軟程度

  7. 將該圖層轉(zhuǎn)換為不透明度蒙版,置于網(wǎng)點(diǎn)圖層下,bingo

將圖層中的每一個(gè)像素看作一個(gè) 0-1 之間的數(shù)字,將閾值看作布爾化(變?yōu)?0,1),將相加和相乘模式看作數(shù)字的相加相減,上述的過程是非常容易理解的。

現(xiàn)在還是放棄了研究網(wǎng)點(diǎn)的想法了,原因是這玩意更適用于打印,在屏幕上縮放級別的不同會影響灰度,而顯然后者現(xiàn)在是更主要的受眾。但不能說白費(fèi)功夫了,研究實(shí)現(xiàn)該效果的過程中熟悉了圖層,蒙版,混合模式等概念并建立了相應(yīng)心智模型,同時(shí)意識到我以前光把著畫筆工具不放的想法和行為是多么睿智。

然后發(fā)現(xiàn) krita 允許通過 SeExpr 這門腳本語言進(jìn)行繪圖,其中有兩個(gè)效果超級炫酷的示例(第一張簡直壯觀),引起了我很強(qiáng)烈的興趣:

要是能在背景,材質(zhì)等地方使用這樣酷炫的材質(zhì)豈不美哉?于是就來到這里了。然而 SeExpr 的學(xué)習(xí)材料實(shí)在太少(全互聯(lián)網(wǎng)有 10 篇嗎?),這里只得去拿和它思想一致的 glsl 來動手動腳。這里跟隨 https://thebookofshaders.com/?lan=ch 進(jìn)行學(xué)習(xí)。SeExpr 的用法應(yīng)當(dāng)參考 https://docs.krita.org/zh_CN/reference_manual/seexpr.html(Krita 的官方文檔是好東西,值得反反復(fù)復(fù)看 10 遍)。本打算每個(gè)例子都用 SeExpr 實(shí)現(xiàn)一下,但是懶了。先把畫畫畫好再說!

glsl 是什么

glsl 與其說是編程語言,不如說是 DSL;glsl 語法和數(shù)據(jù)類型類似 C,glsl 腳本被交付給 GPU,在每一個(gè)像素上執(zhí)行,用于修改該像素的顏色??梢哉J(rèn)為 glsl 是一個(gè)接受像素坐標(biāo)(和一些其他參數(shù),稱為 uniform;根據(jù) GPU 的架構(gòu)的性質(zhì),對每一個(gè)像素,uniform 的值均一致且不可變)的函數(shù),返回像素顏色的函數(shù),在這里,像素坐標(biāo)是二元組,分別為 x,y 軸坐標(biāo)(其實(shí)是四元組,但我們只看二維),其中原點(diǎn)在左下角;像素顏色為四元組,分別為 rgba 通道上的值。在 glsl 中,rgba 均使用 0-1 的浮點(diǎn)數(shù)表示,這種表示似乎稱為 normalize 表示,它們乘以 255 會得到我們熟知的表示法。

下面是一個(gè)最簡單的 glsl 腳本,它給整個(gè)畫面從左到右做了一個(gè)黑白漸變:

此外,glsl 支持 if-else,while,for(循環(huán)次數(shù)必須在“編譯期”確定),三目表達(dá)式,但復(fù)雜語句可能會影響著色器性能,應(yīng)盡量使用 glsl 提供的函數(shù)來完成功能,這些函數(shù)很多都是可以直接在硬件上執(zhí)行的。

注意 glsl 很少會進(jìn)行自動的類型轉(zhuǎn)換,寫浮點(diǎn)數(shù)時(shí)加上.是好習(xí)慣。

下面是另一個(gè)腳本,其使用了 distance 函數(shù),繪制從中心開始的圓形漸變:

教程關(guān)卡結(jié)束了!該來點(diǎn)燒腦子的東西了。下面的所有代碼都有一個(gè)很大的問題——只考慮了畫布為正方形的情況;但懶得研究了。

繪制函數(shù)汗背景

在 glsl 中,函數(shù)可視化有兩種方式——使用灰度來表達(dá) y 軸,或者使用 y 軸來表達(dá) y 軸,前者就是繪制像上面第一個(gè)例子的黑白漸變,其就是通過灰度繪制了 y=x 的圖像,后者就是在圖像中實(shí)際繪制出函數(shù)曲線。

現(xiàn)在有個(gè)數(shù)學(xué)函數(shù)y=x^2,如何將它作為一條線繪制在畫面上?具體來說就是,如何繪制這樣的圖像,它的大多數(shù)地方亮度為 0,該函數(shù)周圍區(qū)域亮度為 1?

第一印象是,對每一個(gè)點(diǎn),可以計(jì)算它到函數(shù)的距離,小于一定距離,則認(rèn)為它在線上,繪制亮度為 1,否則繪制為 0,這里為了實(shí)現(xiàn)簡單,只比較 y 軸方向的距離;代碼如下:

這種方法有兩個(gè)缺點(diǎn),第一是函數(shù)導(dǎo)數(shù)大時(shí)函數(shù)會畫得更細(xì),反之會畫得更粗;第二是繪制出來的線條的邊緣會非常硬——從 1 直接躍遷到 0 了,中間沒有任何漸變。

第一個(gè)問題先不考慮,看第二個(gè)問題,如何把它畫的更平滑一些?我們需要一個(gè)類似階梯函數(shù)但中間要有一個(gè)平滑但微小的過渡的東西,讓它在距離大于特定值時(shí)返回 0,距離小于該特定值時(shí)返回 0-1 之間的數(shù),更小時(shí)返回 1(處理這個(gè)“更小”和“特定值”就是處理函數(shù)邊緣的硬度)。smoothstep 函數(shù) 滿足我們的需求——它需要用戶給定階梯的開始和結(jié)束位置,通過某種插值法在中間生成平滑的過渡,下面是使用 smoothstep 函數(shù)來做的實(shí)現(xiàn):

還是尖銳一點(diǎn)好

然后下一步,這函數(shù)的背景有點(diǎn)寡淡了,想給它加個(gè)背景,該怎么辦?

考慮plot(st)的返回值,在大多數(shù)時(shí)候它返回 0,只有在函數(shù)附近時(shí)它才返回 1,我們的需求是,在 plot(st) 返回 0 的時(shí)候,顯示背景色,在 plot(st) 返回 1 的時(shí)候顯示前景色……在 plot(st) 在 0-1 之間的時(shí)候,返回前景色和背景色的混合……混合,混合……混合?

混合!答案實(shí)際上呼之欲出了——

背景色當(dāng)然也可以是計(jì)算出來的,這里同時(shí)使用背景色和曲線來可視化y=x^2,下面使用功能相同的 mix 函數(shù)來進(jìn)行混合:

組合圖形

就像繪畫時(shí)復(fù)雜的形體可以認(rèn)為是簡單的幾何體的組合,使用 glsl 也可以組合不同的形狀來繪制復(fù)雜圖形;最簡單的組合顯然是加法(加法需要做一個(gè)clamp(0, 1)來保證最終的值仍然是歸一化的)和乘法,分別對應(yīng)求兩個(gè)圖形的并集和交集,比如下面就用四個(gè)圖形的交集繪制一個(gè)矩形:

該流程可以抽象成返回 float 的函數(shù),返回 1 時(shí)表示需要繪制該圖形,返回 0 時(shí)表示需要繪制背景,結(jié)合這樣的函數(shù)和 mix 函數(shù),就可以繪制多層的圖像了,下面使用該方法臨摹一幅抽象畫:

二維變換

首先定義一個(gè)在原點(diǎn)處繪制坐標(biāo)系和繪制一個(gè)描邊矩形的函數(shù),方便后面做示例:

每次對坐標(biāo)進(jìn)行修改時(shí),我們就是在進(jìn)行二維變換,最簡單的二維變換包括平移,旋轉(zhuǎn),縮放,工業(yè)上這玩意應(yīng)該是用齊次矩陣做的,但這里圖簡單。

如何理解二維變換?可以認(rèn)為,每次對原坐標(biāo)做映射,得到一個(gè)新坐標(biāo)時(shí),就是創(chuàng)建了一個(gè)對畫布(后面把它稱為世界坐標(biāo)系)的新的視圖坐標(biāo)系(就像對數(shù)組或表的視圖)。前面的學(xué)習(xí)中,其實(shí)也是在視圖坐標(biāo)系中繪制,只是它們正巧和世界坐標(biāo)系一致罷了。當(dāng)然,也可以以視圖去建立視圖,前者會成為后者的世界坐標(biāo)系,相對和絕對嘛。

對每個(gè)像素,我們首先拿到的是它的世界坐標(biāo)系的位置,我們需要找到這個(gè)像素在視圖中的位置,并從視圖的角度檢查需要繪制何種內(nèi)容。比如,將整個(gè)坐標(biāo)系向右上角移動 (1, 1)。我們嘗試在 (0, 0) 處繪制方塊時(shí),實(shí)際上就是在問,世界坐標(biāo)系的哪里是我們的 (0, 0)?

為此,需要找到世界坐標(biāo)系到視圖的映射,下面的幾種二維變換,實(shí)際上都是根據(jù)相應(yīng)參數(shù)找到這樣一個(gè)映射。

這個(gè)心智模型頗有些奇怪,第一印象是找到視圖到世界坐標(biāo)系的映射,但在這里似乎不適用,因?yàn)?glsl 做的是對世界坐標(biāo)系的每一個(gè)坐標(biāo),檢查它要畫什么,而不是我要在(視圖的)某個(gè)坐標(biāo)畫什么。前者的話,坐標(biāo)的變換流程就會是 世界坐標(biāo)系 -> 視圖 1 -> 視圖 2 -> 當(dāng)前視圖,后者的話就是當(dāng)前視圖 -> 視圖 2 -> 視圖 1 -> 世界坐標(biāo)系。

實(shí)現(xiàn)了二維變換后,編寫新的圖形繪制函數(shù)的時(shí)候,只需要實(shí)現(xiàn)它在原點(diǎn)處的“單位”形狀即可,后面的通過二維變換操作就行。

平移

要將坐標(biāo)系平移到 (1, 2),就需要以 (1, 2) 為原點(diǎn)建立一個(gè)坐標(biāo)系,并始終在該坐標(biāo)系下進(jìn)行繪制,這樣,代碼在視圖的 (0, 0) 處繪制時(shí),實(shí)際上就是在世界坐標(biāo)系的 (1, 2) 處繪制。

容易發(fā)現(xiàn)這樣的對應(yīng)關(guān)系:

實(shí)現(xiàn)很顯然了:

下面的代碼中利用平移在 (1, 1) 處繪制了一個(gè)矩形,并繪制了此時(shí)的視圖坐標(biāo)系。

旋轉(zhuǎn)

旋轉(zhuǎn)直接抄作業(yè),總之是視圖坐標(biāo)系的旋轉(zhuǎn)(惱),用初高中的知識應(yīng)該就能推導(dǎo)出來,但我已經(jīng)失掉這個(gè)能力了。實(shí)現(xiàn)和示例如下,移動到 (1, 1),然后再隨時(shí)間旋轉(zhuǎn)。

旋轉(zhuǎn)示例

平移和旋轉(zhuǎn)

同時(shí)使用平移和旋轉(zhuǎn)時(shí),平移和旋轉(zhuǎn)的先后順序會影響最終效果,但使用這套心智模型的話很容易理解它們的差異。

假設(shè)隨時(shí)間旋轉(zhuǎn)。先平移再旋轉(zhuǎn)時(shí),就是先向前走 10 步,然后原地轉(zhuǎn)圈圈;先旋轉(zhuǎn)再平移,就是在當(dāng)前位置旋轉(zhuǎn),然后對每個(gè)角度,都向前走 10 步,它們的差別通過下面的例子可以看到;前者就是普通的原地轉(zhuǎn)圈圈,后者類似月球圍繞地球運(yùn)動且潮汐鎖定。

先平移再旋轉(zhuǎn)
先旋轉(zhuǎn)再平移

縮放

縮放很好玩;如何把圖形到原來的 2 倍呢?我們繪制圖形還是同樣的畫,但需要這樣一個(gè)效果,即我們在 (1, 0) 處繪制時(shí),實(shí)際上要在 (2, 0) 處繪制,在 (2, 3) 處繪制時(shí),實(shí)際上要在 (4, 6) 處繪制:

很顯然了,實(shí)現(xiàn)和示例如下:

take a jump

距離場

距離場是畫面上任意一點(diǎn)同特定點(diǎn)的距離相關(guān)聯(lián)的場,距離可以使用亮度來表示,距離越遠(yuǎn),亮度越大。距離場并不是特定的幾何圖形,它是無窮大的,通過距離場來繪制各種東西是把它當(dāng)作工具,而不是繪制它本身。利用距離場,能做出非常多有趣的效果,用途包括但不限于:

  1. 繪制硬邊和軟邊圓形

  2. 繪制對稱圓形,矩形,四角星

  3. 為上述的形狀描邊

注意下面的例子中使用 abs,max,min 等函數(shù)創(chuàng)建的視圖。這個(gè)懶得截圖了。

下面利用距離場和二維變換繪制了開頭的 MyGo!!!!!! 的羅盤 logo,寫得倉促,將就看。

模式

很多時(shí)候需要創(chuàng)建重復(fù)的圖案,但是又不想挨個(gè)繪制,而是期待它們能自己就重復(fù),使用 fract 函數(shù)創(chuàng)建的視圖允許做到這一點(diǎn)。fract 函數(shù)獲取浮點(diǎn)數(shù)的小數(shù)部分,只要將浮點(diǎn)數(shù)乘以 10,做個(gè) fract,就能得到重復(fù) 10 次的圖像:

這樣,只要我們在視圖的 0.1 處繪圖時(shí),在 0.01,0.11,0.21 這三個(gè)坐標(biāo)都能看到同樣的結(jié)果,因?yàn)樗鼈兌紝?yīng)著視圖的 0.1。這樣的每個(gè)重復(fù)的結(jié)果稱為子空間。

一些例子如下。需要注意,在構(gòu)造子空間前進(jìn)行變換時(shí),會對整個(gè)子空間進(jìn)行變換,例子 2,3,4 都應(yīng)用了這點(diǎn);構(gòu)造子空間后進(jìn)行變換,則是分別對每個(gè)子空間進(jìn)行變換。例子 4 結(jié)合了距離場做了一個(gè)漸變圓,這效果感覺畫畫時(shí)可以用到。

下圖為例子3和例子4。

圓形漸變半調(diào)子

“臨摹”上面的第一張 SeExpr 作為結(jié)束。首先需要研究它們的效果。

第一張是圓形組成的半調(diào)子,能發(fā)現(xiàn),每個(gè)圓形沒有灰度變化,純粹是根據(jù)每個(gè)小塊黑白的比例來表示亮度的。

假設(shè)亮度從白到黑,圓形的大小從小到大的方向是 x 軸,垂直于此的方向?yàn)?y 軸,能發(fā)現(xiàn) y 軸方向每一個(gè)圓形的間距都是一樣的,顯然,這里使用了 pattern 和距離場,x 軸方向越大就越暗。

但也能注意到,同一行中,隨著 x 軸坐標(biāo)變大,亮度并非是單調(diào)遞增的,有時(shí)候會開一下倒車,這證明其中有一些隨機(jī)性,但總體還是遞增的。顯然,對每一列,需要一個(gè)不同的亮度函數(shù)——想象柯里化,我們對每一列都構(gòu)造一個(gè)這樣的亮度函數(shù)。

但先忘記隨機(jī)性,只考慮單調(diào)遞增的情況。繪制這樣的“單位”漸變的方法如下:

示例如下,有點(diǎn)丑,或許得調(diào)整這個(gè)亮度函數(shù),但就這樣了:

和我畫的畫一樣糙

當(dāng)前學(xué)的東西其實(shí)非常有限,都是最基礎(chǔ)的東西,但我意識到我不應(yīng)該當(dāng)前就去追求這種很“風(fēng)格化”的東西,先把基礎(chǔ)學(xué)好吧!之后或許會學(xué)一些 blender 和程序化建模來方便學(xué)習(xí)和實(shí)驗(yàn),GLSL 和 SeExpr 就先這樣了,已經(jīng)收獲足夠多,必可活用于下一次。

GLSL 學(xué)習(xí)筆記的評論 (共 條)

分享到微博請遵守國家法律
巍山| 云霄县| 临沂市| 舞钢市| 文安县| 霍山县| 巍山| 屏南县| 沅陵县| 玉溪市| 金堂县| 霍林郭勒市| 正宁县| 东海县| 汉中市| 鄂托克旗| 衡阳县| 德清县| 青浦区| 克山县| 旺苍县| 崇阳县| 来凤县| 平阴县| 秦安县| 蛟河市| 无极县| 尼木县| 安康市| 平阴县| 秦安县| 南召县| 平遥县| 兴业县| 遂昌县| 文水县| 武山县| 天峻县| 丹寨县| 金溪县| 芜湖县|