OpenGL雜談之復(fù)用GLSL代碼

歡迎訪問我的個(gè)人主頁了解更多關(guān)于OpenGL的知識(shí)

前言

GLSL是OpenGL的著色語言绽诚,在編寫GLSL的過程中疚漆,復(fù)用代碼是一件比較麻煩的事情碉克,GLSL基本是不支持#include預(yù)編譯指令的尖滚。
目前我已知的OpenGL對于GLSL include的支持僅限于擴(kuò)展ARB_shading_language_include,如果你的系統(tǒng)支持該OpenGL擴(kuò)展键袱,那么你就可以在GLSL中使用include再菊。不過似乎只有nvidia的OpenGL驅(qū)動(dòng)對它有支持。

復(fù)用GLSL代碼的級別

既然官方的include使用如此艱難宏邮,我們就來自己造輪子吧泽示。首先我們要確定在什么級別復(fù)用代碼。有兩種選擇:

  1. 程序代碼運(yùn)行時(shí)將可復(fù)用的GLSL代碼塊合并成可運(yùn)行的GLSL代碼蜜氨。
  2. 程序編譯時(shí)跑一個(gè)腳本械筛,將可復(fù)用的GLSL代碼合并成可運(yùn)行的GLSL文件,然后在運(yùn)行時(shí)使用生成好的GLSL文件记劝。

我之前嘗試過第一種方法变姨,運(yùn)行時(shí)合并GLSL代碼族扰,不過調(diào)試不是很方便厌丑,報(bào)錯(cuò)時(shí)不好定位到哪行,而且運(yùn)行時(shí)生成終究會(huì)消耗一些性能渔呵。所以這一次我打算探索第二條路怒竿。

預(yù)編譯工具m4

在研究第二種方式時(shí),碰巧找到了一個(gè)非常符合解決本次問題的工具m4扩氢。m4說白的就是一個(gè)預(yù)編譯工具耕驰,將寫有宏的文本進(jìn)行預(yù)編譯展開。如果你使用Mac录豺。在終端輸入

m4 --version

如果得到如下朦肘,恭喜你饭弓,你已經(jīng)擁有了此工具。

GNU M4 1.4.6
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Written by Rene' Seindal.

當(dāng)然你也可能是其他版本媒抠。如果沒有出現(xiàn)弟断,你可以使用homebrew安裝。

brew install m4

如果你喜歡使用源碼安裝趴生,可以訪問m4的官網(wǎng)阀趴。

m4的使用示例

我們先來寫一個(gè)例子來感受一下m4的功能。在同一個(gè)目錄下創(chuàng)建2個(gè)文件苍匆,Test.m4和inc.m4刘急。


在inc.m4中輸入下面內(nèi)容。
這里是被包含的內(nèi)容

在Test.m4中我們做兩件事情浸踩,包含inc.m4叔汁,定義一個(gè)變量。

include(`inc.m4')

define(`content', `例子')

這是一個(gè)content

注意检碗,inc.m4左邊不是單引號(hào)攻柠,是`,右邊是單引號(hào)后裸。content例子也是一樣瑰钮。include(`inc.m4')將inc.m4包含到Test.m4中,define(`content', `例子')例子這個(gè)值賦給content微驶。我們使用m4預(yù)處理一下看看結(jié)果浪谴。在終端運(yùn)行。

m4 Test.m4

結(jié)果如下因苹。

這里是被包含的內(nèi)容




這是一個(gè)例子

將m4運(yùn)用于GLSL

下面是我的一個(gè)GLSL程序結(jié)構(gòu)目錄苟耻,我使用m4將這些復(fù)用代碼合并到一起。


這里我寫了兩個(gè)光照模型扶檐,lambert_phong和lambert_blinn凶杖,它們大部分代碼都是一樣的,只有高光部分代碼不一樣款筑。targets文件夾下是最終被m4處理的文件智蝠。處理完后直接被OpenGL使用。我們看一下其中的一個(gè)文件frag_lambert_phong.glsl奈梳。

// defines
include(`fragment shader components/frag_base_header.glsl')
include(`fragment shader components/frag_structs.glsl')
include(`fragment shader components/frag_in_vars.glsl')
include(`fragment shader components/frag_uniform_vars.glsl')

// functions
include(`fragment shader components/frag_normal.glsl')
include(`fragment shader components/frag_light_base.glsl')
include(`fragment shader components/frag_light_lambert.glsl')
include(`fragment shader components/frag_light_phong.glsl')

// light model
include(`fragment shader light model/frag_light_model_lambert_phong.glsl')

其實(shí)我只用到了m4的include功能杈湾,我們將這個(gè)文件和frag_lambert_blinn對比一下。

// defines
include(`fragment shader components/frag_base_header.glsl')
include(`fragment shader components/frag_structs.glsl')
include(`fragment shader components/frag_in_vars.glsl')
include(`fragment shader components/frag_uniform_vars.glsl')

// functions
include(`fragment shader components/frag_normal.glsl')
include(`fragment shader components/frag_light_base.glsl')
include(`fragment shader components/frag_light_lambert.glsl')
include(`fragment shader components/frag_light_blinn.glsl')

// light model
include(`fragment shader light model/frag_light_model_lambert_blinn.glsl')

只有最后兩個(gè)include不一樣攘须,很好的滿足了我復(fù)用GLSL的需求漆撞。最后我寫了一個(gè)簡單的腳本批量處理targets下的文件。

#!env python

import os
import subprocess

target_files = os.listdir("./targets")

for file in target_files:
    print("building " + file + "...")
    command = str.format("m4 ./targets/{0} > ../{0}", file)
    subprocess.call(command, shell=True)
    print(file + " build finish.")

將這個(gè)腳本集成到你的編譯系統(tǒng)中,就可以做到完全自動(dòng)化復(fù)用和預(yù)處理GLSL了浮驳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悍汛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子至会,更是在濱河造成了極大的恐慌员凝,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奋献,死亡現(xiàn)場離奇詭異健霹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瓶蚂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門糖埋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窃这,你說我怎么就攤上這事瞳别。” “怎么了杭攻?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵祟敛,是天一觀的道長。 經(jīng)常有香客問我兆解,道長馆铁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任锅睛,我火速辦了婚禮埠巨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘现拒。我一直安慰自己辣垒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布印蔬。 她就那樣靜靜地躺著勋桶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侥猬。 梳的紋絲不亂的頭發(fā)上例驹,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機(jī)與錄音陵究,去河邊找鬼眠饮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛铜邮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼松蒜,長吁一口氣:“原來是場噩夢啊……” “哼扔茅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起秸苗,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤召娜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后惊楼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體玖瘸,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年檀咙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狈茉,死狀恐怖蒿往,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棕诵,我是刑警寧澤裁良,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站校套,受9級特大地震影響价脾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜笛匙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一彼棍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膳算,春花似錦座硕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至机隙,卻和暖如春蜘拉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背有鹿。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工旭旭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人葱跋。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓持寄,卻偏偏與公主長得像源梭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子稍味,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容