附錄(四)繪制紋理

繪制紋理

精度限定符用于指定任何基于浮點(diǎn)或者整數(shù)變量的精度轰胁,關(guān)鍵字有高谒主、中朝扼、低赃阀。

highp vec4        position;
varying lowp vec4 color;
mediump float     specularExp;

精度限定符,還有默認(rèn)精度的概念擎颖,如果沒有設(shè)置榛斯,就設(shè)置默認(rèn)的,默認(rèn)精度限定符使用以下語法在頂點(diǎn)或片段著色器的頂部指定:

precision highp float;
precision mediump int;

為浮點(diǎn)指定的精度將用作基于浮點(diǎn)值的所有變量的默認(rèn)精度搂捧。同樣驮俗,為int指定的精度將用作所有基于整數(shù)的變量的默認(rèn)精度。在頂點(diǎn)著色器中允跑,如果沒有指定默認(rèn)精度王凑,則int和float的默認(rèn)精度都很高搪柑。

精度選擇:

  • 對于通常在頂點(diǎn)著色器中執(zhí)行的操作,最可能需要的精度限定符是高精度限定符索烹。
  • 用矩陣變換位置工碾,變換法線和紋理坐標(biāo),或者生成紋理坐標(biāo)的操作需要高精度地完成百姓。
  • 顏色計(jì)算和光照方程很可能以中等精度完成渊额。

這將取決于正在執(zhí)行的顏色計(jì)算的種類以及正在執(zhí)行的操作所需的范圍和精度。我們相信highp很可能是頂點(diǎn)著色器中大多數(shù)操作使用的默認(rèn)精度垒拢,因此在下面的示例中使用highp作為默認(rèn)精度限定符旬迹。

Open gl es的著色器限制

這些限制應(yīng)該會有所幫助開發(fā)人員編寫了一個(gè)便攜式頂點(diǎn)著色器,可以在大多數(shù)OpenGL ES 2.0實(shí)現(xiàn)上編譯和運(yùn)行求类。

頂點(diǎn)著色器的長度

指令計(jì)數(shù)超過頂點(diǎn) 著色器允許的最大指令奔垦,頂點(diǎn)著色器源將無法編譯。所以出現(xiàn)了一些限制尸疆,來保證可以正常運(yùn)行宴倍。

臨時(shí)變量

臨時(shí)變量是指在函數(shù)內(nèi)部聲明的變量或存儲中間值的變量。
因?yàn)镺penGL ES著色語言是高級語言仓技,所以沒有辦法指定所有OpenGL ES 2.0實(shí)現(xiàn)必須支持的最小臨時(shí)變量數(shù)鸵贬。
因此,頂點(diǎn)著色器可能會遇到這個(gè)問題脖捻,并且不會在所有ES 2.0實(shí)現(xiàn)上編譯阔逼。

流量控制

OpenGL ES 2.0要求實(shí)現(xiàn)支持頂點(diǎn)著色器中的循環(huán),而不要求它們必須展開地沮。例如嗜浮,您可以有一個(gè)For循環(huán),循環(huán)索引從0到1023摩疑。這通常不會被著色器編譯器展開危融,因?yàn)檎归_的著色器的代碼大小對于大多數(shù)ES 2.0實(shí)現(xiàn)來說可能太大。以下限制適用于頂點(diǎn)著色器中使用的循環(huán):
【循環(huán)可以減小程序的大小】

  • 在for循環(huán)中只能使用一個(gè)循環(huán)索引雷袋。
  • 循環(huán)索引必須初始化為常數(shù)整數(shù)表達(dá)式吉殃。
  • for循環(huán)中聲明的條件表達(dá)式必須是下列之一:
    loop_indx < constant_expression
    loop_indx <= constant_expression
    loop_indx > constant_expression
    loop_indx >= constant_expression
    loop_indx != constant_expression
    loop_indx == constant_expression
    
  • 只能使用以下表達(dá)式之一在for循環(huán)語句中修改循環(huán)索引:
    loop_index--
    loop_index++
    loop_index -= constant_expression
    loop_index += constant_expression
    
  • 循環(huán)索引可以作為只讀參數(shù)傳遞給for循環(huán)中的函數(shù)(即循環(huán)索引可以與使用in參數(shù)限定符聲明的參數(shù)一起使用)。
Examples of valid for loop constructs are shown here.
const int numLights = 4;
int i, j;
for (i=0; i<numLights; i++)
{
   …
}
for (j=4; j>0; j--)
{
   …
   foo(j);  // argument to function foo that takes j
            // is declared with the in qualifier.
}
Examples of invalid for loop constructs are shown here.
uniform int numLights;
int i;
for (i=0; i<numLights; i++)  // conditional expression is 
                             // not constant
{
   …
}
for (i=0; i<8; i++)
{
   i = foo();   // return value of foo() cannot be 
                // assigned to loop index i
}
for (j=4; j>0;)
{
   …
   j--;   // loop index j cannot be modified 
          // inside for loop
}

雖然OpenGL ES 2.0著色語言規(guī)范指定了while和do-while循環(huán)楷怒,但這并不是必需的蛋勺,因此可能不被所有OpenGL ES 2.0實(shí)現(xiàn)所支持。

條件語句

完全支持以下條件語句鸠删,沒有任何限制抱完。

if(bool_expression)
{
   …
}
if(bool_expression)
{
   …
}
else
{
   …
}

圖形處理器通常并行執(zhí)行具有多個(gè)頂點(diǎn)的頂點(diǎn)著色器或具有多個(gè)片段的片段著色器。
并行執(zhí)行的頂點(diǎn)或片段的數(shù)量將取決于GPU的性能目標(biāo)刃泡。
if和if-else條件語句中的bool_expression對于并行執(zhí)行的頂點(diǎn)或片段可以有不同的值巧娱。
由于GPU并行執(zhí)行的頂點(diǎn)或片段數(shù)量減少碉怔,這可能會影響性能。
我們建議禁添,為了獲得最佳性能眨层,條件語句應(yīng)該與bool_expression值一起使用,這些值對于并行執(zhí)行的頂點(diǎn)或片段是相同的上荡。如果使用統(tǒng)一的表達(dá)式趴樱,就會出現(xiàn)這種情況.

數(shù)組索引

完全支持制服(不包括采樣器)的數(shù)組索引。數(shù)組索引可以是常量酪捡、統(tǒng)一值或計(jì)算值叁征。采樣器只能使用常數(shù)積分表達(dá)式進(jìn)行索引。常數(shù)積分表達(dá)式是文字值(如4)逛薇,常數(shù)整數(shù)變量(如const int sampler _ indx = 3捺疼;),或者常量表達(dá)式(例如3 + sampler_indx)永罚。
屬性矩陣和向量可以使用常數(shù)積分表達(dá)式進(jìn)行索引啤呼。不強(qiáng)制使用非常數(shù)積分表達(dá)式對屬性矩陣和向量進(jìn)行索引。然而呢袱,這是一個(gè)非常有用的特性官扣。下面的代碼顯示了一個(gè)執(zhí)行頂點(diǎn)蒙皮的頂點(diǎn)著色器。a_matrixweights是一個(gè)存儲矩陣權(quán)重的頂點(diǎn)屬性羞福,最多可存儲四個(gè)矩陣惕蹄。

attribute vec4 a_matrixweights; // matrix weights 
attribute vec4 a_matrixindices;  // matrix palette indices
int i;
for (i=0; i<=3; i++)
{
   float   m_wt = a_matrixweights[i];
   int     m_indx = int(a_matrixindices[i]) * 3;
   …
}

以粗體突出顯示的代碼a_matrixweights[i]和a_matrixindices[i]不需要支持,因此可能無法編譯治专。

注意:索引常數(shù)矩陣和向量卖陵、變量和變量或變量和變量數(shù)組的規(guī)則與已經(jīng)描述的屬性的規(guī)則相同

計(jì)算頂點(diǎn)著色器中使用的制服數(shù)量

gl _ MaxVertexUniformVectors描述頂點(diǎn)著色器中可以使用的最大制服數(shù)量。任何兼容的OpenGL ES 2.0實(shí)現(xiàn)都必須支持的gl _ MaxVertexUniformVectors的最小值是128個(gè)vec4條目张峰。統(tǒng)一存儲用于存儲以下變量:

  • 用統(tǒng)一限定符聲明的變量泪蔫。
  • 常量變量。
  • ? Literal values.
  • 特定于實(shí)現(xiàn)的常數(shù)

頂點(diǎn)著色器中使用的統(tǒng)一變量的數(shù)量以及用常量限定符喘批、文字值和特定于實(shí)現(xiàn)的常量聲明的變量必須符合第5章中描述的打包規(guī)則撩荣。如果這些不適合,那么頂點(diǎn)著色器將無法編譯谤祖。開發(fā)人員可以應(yīng)用打包規(guī)則婿滓,并確定存儲統(tǒng)一變量老速、常量變量和文字值所需的統(tǒng)一存儲量粥喜。無法確定特定于實(shí)現(xiàn)的常量的數(shù)量,因?yàn)樵撝挡粌H會因?qū)崿F(xiàn)而異橘券,還會根據(jù)頂點(diǎn)著色器使用的內(nèi)置著色語言函數(shù)而變化额湘。通常卿吐,當(dāng)使用內(nèi)置超越函數(shù)時(shí),需要特定于實(shí)現(xiàn)的常數(shù)锋华。

就文字值而言嗡官,OpenGL ES 2.0著色語言規(guī)范聲明不假設(shè)常數(shù)傳播。這意味著同一文字值的多個(gè)實(shí)例將被多次計(jì)數(shù)毯焕⊙苄龋可以理解,在頂點(diǎn)著色器中使用文字值(如0.0或1.0)更容易纳猫,但我們建議盡可能避免這種情況婆咸。應(yīng)該聲明適當(dāng)?shù)某A孔兞浚皇鞘褂梦淖种滴咴_@避免了多次使用相同的文字值計(jì)數(shù)尚骄,如果頂點(diǎn)統(tǒng)一存儲要求超過實(shí)現(xiàn)支持的范圍,這可能導(dǎo)致頂點(diǎn)著色器無法編譯侵续。

考慮下面的例子倔丈,它描述了頂點(diǎn)著色器代碼的一個(gè)片段,該代碼為每個(gè)頂點(diǎn)變換兩個(gè)紋理坐標(biāo):

#define NUM_TEXTURES   2
uniform mat4  tex_matrix[NUM_TEXTURES];        // texture matrices
uniform bool  enable_tex[NUM_TEXTURES];        // texture enables
uniform bool  enable_tex_matrix[NUM_TEXTURES]; // texture matrix 
                                               // enables
attribute vec4  a_texcoord0;  // available if enable_tex[0] is true
attribute vec4  a_texcoord1;  // available if enable_tex[1] is true
varying vec4    v_texcoord[NUM_TEXTURES];
v_texcoord[0] = vec4(0.0, 0.0, 0.0, 1.0);
// is texture 0 enabled
if (enable_tex[0])
{
   // is texture matrix 0 enabled
   if(enable_tex_matrix[0])
      v_texcoord[0] = tex_matrix[0] * a_texcoord0;
   else
      v_texcoord[0] = a_texcoord0;
}
v_texcoord[1] = vec4(0.0, 0.0, 0.0, 1.0);
// is texture 1 enabled
if (enable_tex[1])
{
   // is texture matrix 1 enabled
   if(enable_tex_matrix[1])
      v_texcoord[1] = tex_matrix[1] * a_texcoord1;
   else
      v_texcoord[1] = a_texcoord1;
}

剛才描述的代碼可能導(dǎo)致對文字值0状蜗、1需五、0.0、1.0的每個(gè)引用都按照統(tǒng)一存儲進(jìn)行計(jì)數(shù)轧坎。為了保證這些文字值在統(tǒng)一存儲中只計(jì)數(shù)一次警儒,頂點(diǎn)著色器代碼段應(yīng)該編寫如下

#define NUM_TEXTURES   2
const int  c_zero = 0;
const int  c_one  = 1;
uniform mat4  tex_matrix[NUM_TEXTURES];        // texture matrices
uniform bool  enable_tex[NUM_TEXTURES];        // texture enables
uniform bool  enable_tex_matrix[NUM_TEXTURES]; // texture matrix 
                                               // enables   
attribute vec4  a_texcoord0;  // available if enable_tex[0] is true
attribute vec4  a_texcoord1;  // available if enable_tex[1] is true
varying vec4    v_texcoord[NUM_TEXTURES];
v_texcoord[c_zero] = vec4(float(c_zero), float(c_zero), 
                          float(c_zero), float(c_one));
// is texture 0 enabled
if(enable_tex[c_zero])
{
   // is texture matrix 0 enabled
   if(enable_tex_matrix[c_zero])
      v_texcoord[c_zero] = tex_matrix[c_zero] * a_texcoord0;
   else
      v_texcoord[c_zero] = a_texcoord0;
}
v_texcoord[c_one] = vec4(float(c_zero), float(c_zero), 
                         float(c_zero), float(c_one));
// is texture 1 enabled
if(enable_tex[c_one])
{
   // is texture matrix 1 enabled
   if(enable_tex_matrix[c_one])
      v_texcoord[c_one] = tex_matrix[c_one] * a_texcoord1;
   else
      v_texcoord[c_one] = a_texcoord1;
}

希望這一節(jié)有助于很好地理解OpenGL ES 2.0著色語言的局限性,以及如何編寫應(yīng)該在大多數(shù)OpenGL ES 2.0實(shí)現(xiàn)上編譯和運(yùn)行的頂點(diǎn)著色器眶根。

一個(gè)簡單的頂點(diǎn)著色器

頂點(diǎn)著色器將位置及其相關(guān)的顏色數(shù)據(jù)作為輸入或?qū)傩允癫ㄟ^4 × 4矩陣轉(zhuǎn)換位置,并輸出轉(zhuǎn)換后的位置和顏色属百。

Example 8-1 A Simple Vertex Shader 
// uniforms used by the vertex shader
uniform mat4    u_mvp_matrix; // matrix to convert P from 
                              // model space to clip space.
// attributes input to the vertex shader
attribute vec4  a_position;   // input position value
attribute vec4  a_color;      // input vertex color
// varying variables – input to the fragment shader
varying vec4    v_color;      // output vertex color
void
main()
{
   v_color = a_color;
   gl_Position = u_mvp_matrix * a_position;
}

然后记劝,設(shè)置和光柵化階段使用變換的頂點(diǎn)位置和圖元類型將圖元光柵化成片段。對于每個(gè)片段族扰,插值的v_color將被計(jì)算并作為輸入傳遞給片段著色器厌丑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市渔呵,隨后出現(xiàn)的幾起案子怒竿,更是在濱河造成了極大的恐慌,老刑警劉巖扩氢,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耕驰,死亡現(xiàn)場離奇詭異,居然都是意外死亡录豺,警方通過查閱死者的電腦和手機(jī)朦肘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門饭弓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人媒抠,你說我怎么就攤上這事弟断。” “怎么了趴生?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵阀趴,是天一觀的道長。 經(jīng)常有香客問我苍匆,道長舍咖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任锉桑,我火速辦了婚禮排霉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘民轴。我一直安慰自己攻柠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布后裸。 她就那樣靜靜地躺著瑰钮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪微驶。 梳的紋絲不亂的頭發(fā)上浪谴,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機(jī)與錄音因苹,去河邊找鬼苟耻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛扶檐,可吹牛的內(nèi)容都是我干的凶杖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼款筑,長吁一口氣:“原來是場噩夢啊……” “哼智蝠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起奈梳,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤杈湾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后攘须,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漆撞,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了叫挟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艰匙。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡限煞,死狀恐怖抹恳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情署驻,我是刑警寧澤奋献,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站旺上,受9級特大地震影響瓶蚂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宣吱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一窃这、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧征候,春花似錦杭攻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至跑揉,卻和暖如春锅睛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背历谍。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工现拒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人望侈。 一個(gè)月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓具练,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甜无。 傳聞我的和親對象是個(gè)殘疾皇子扛点,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

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