OpenGLES進(jìn)階教程7-天空盒效果

教程

OpenGLES入門(mén)教程1-Tutorial01-GLKit
OpenGLES入門(mén)教程2-Tutorial02-shader入門(mén)
OpenGLES入門(mén)教程3-Tutorial03-三維變換
OpenGLES入門(mén)教程4-Tutorial04-GLKit進(jìn)階
OpenGLES進(jìn)階教程1-Tutorial05-地球月亮
OpenGLES進(jìn)階教程2-Tutorial06-光線(xiàn)
OpenGLES進(jìn)階教程3-Tutorial07-粒子效果
OpenGLES進(jìn)階教程4-Tutorial08-幀緩存
OpenGLES進(jìn)階教程5-Tutorial09-碰碰車(chē)
OpenGLES進(jìn)階教程6-Tutorial10-平截體優(yōu)化
這一次的內(nèi)容是精心準(zhǔn)備的天空盒特效拒秘,為了節(jié)約大家時(shí)間,這次在教程里面不貼代碼,demo部分的內(nèi)容都是干貨
寫(xiě)這個(gè)demo的過(guò)程中遇到了一些坎,最后會(huì)提到召川。
特別留意天空盒紋理坐標(biāo)推導(dǎo)頂點(diǎn)數(shù)據(jù)對(duì)象切換

概念準(zhǔn)備

天空盒特效:OpenGL ES提供了一個(gè)立方體貼圖(cube mapping)的專(zhuān)門(mén)用于產(chǎn)生天空盒效果的紋理貼圖模式。
舉例:一個(gè)人掖桦,站在立方體的中間,上下左右前后看到的都是立方體的圖片供汛。

效果展示

為節(jié)省流量枪汪,gif比較模糊,清晰效果可以看demo怔昨。


核心思路

天空盒的核心就是通過(guò)方向來(lái)取樣紋理雀久,紋理坐標(biāo)被當(dāng)作方向向量,建立適合的正方體后趁舀,位置坐標(biāo)就是紋理坐標(biāo)赖捌。

具體細(xì)節(jié)

1、尺寸大小

天空盒的尺寸可以隨意矮烹,但是需要足夠大以容納渲染的場(chǎng)景越庇。
同時(shí)天空盒的中心要盡可能貼近視點(diǎn)的眼睛位置罩锐,避免太近產(chǎn)生紋理拉伸。

2卤唉、紋理坐標(biāo)到紋素推導(dǎo)(核心)

紋理坐標(biāo)(s, t, r)被當(dāng)作方向向量看待涩惑,每個(gè)紋理單元都表示從原點(diǎn)所看到的紋理立方體上的圖像。
如果是texture2D的情況桑驱,紋理坐標(biāo)(s, t)會(huì)直接返回相應(yīng)位置的紋素竭恬;
textureCube的情況,首先讀取cube紋理熬的,然后以正方體中心為原點(diǎn)痊硕,(s,t,r)為方向,求出正方體和方向向量的交點(diǎn)位置(a, b)悦析,按照位置(a, b)在紋理上面選擇相對(duì)應(yīng)的紋素寿桨。
舉個(gè)例子:
對(duì)于(s, t, r) , 假設(shè) S=fabs(s) ,同理有T R强戴。
如果S > T 并且 S > R亭螟。 那么可以確定交點(diǎn)在面+x 和 -x
根據(jù)s的±可以確定±x面。
直線(xiàn)過(guò)原點(diǎn)和點(diǎn)(s, t, r) 骑歹,那么也會(huì)過(guò)點(diǎn)(1, t/s, r/s)预烙。
(t/s) 和(r/s)就是對(duì)應(yīng)的紋素位置。
考慮到立方體的面為[-1, 1]道媚,那么可以把 (t/s + 1) / 2扁掸,這樣就得到真正的紋素坐標(biāo)( (t/s + 1) / 2, (r/s + 1) / 2)

3、頂點(diǎn)數(shù)據(jù)對(duì)象切換(核心)

  • glBindVertexArrayOES
    很多應(yīng)用會(huì)在同一個(gè)渲染幀調(diào)用多次glBindBuffer()最域、glEnableVertexAttribArray()和glVertexAttribPointer()函數(shù)(用不同的頂點(diǎn)屬性來(lái)渲染多個(gè)對(duì)象)
    新的頂點(diǎn)數(shù)據(jù)對(duì)象(VAO) 擴(kuò)展會(huì)幾率當(dāng)前上下文中的與頂點(diǎn)屬性相關(guān)的狀態(tài)谴分,并存儲(chǔ)這些信息到一個(gè)小的緩存中。之后可以通過(guò)單次調(diào)用glBindVertexArrayOES() 函數(shù)來(lái)恢復(fù)镀脂,不需要在調(diào)用glBindBuffer()牺蹄、glEnableVertexAttribArray()和glVertexAttribPointer()。

  • VAO和VBO
    VBO:頂點(diǎn)緩沖區(qū)對(duì)象(buffer-object)薄翅,用于存儲(chǔ)頂點(diǎn)坐標(biāo)沙兰、紋理坐標(biāo)、頂點(diǎn)法線(xiàn)翘魄、頂點(diǎn)顏色等鼎天。
    VAO:頂點(diǎn)數(shù)據(jù)對(duì)象,記錄頂點(diǎn)數(shù)據(jù)存儲(chǔ)狀態(tài)信息的狀態(tài)對(duì)象(status-object)暑竟。

This extension introduces vertex array objects which encapsulate vertex array states on the server side (vertex buffer objects).
These objects aim to keep pointers to vertex data and to provide
names for different sets of vertex data. Therefore applications are
allowed to rapidly switch between different sets of vertex array
state, and to easily return to the default vertex array state.
Q:Should vertex array objects be sharable across multiple OpenGL ES
contexts?
A: No.

總結(jié)

demo實(shí)現(xiàn)過(guò)程遇到最大的一個(gè)坑斋射,如下:


bug.gif

暫停的適合,天空盒的效果會(huì)消失!
然后開(kāi)始尋找問(wèn)題所在绩鸣,最后發(fā)現(xiàn)問(wèn)題代碼出現(xiàn)在這里

        // 增加角度
        if (!self.mPauseSwitch.on) {
            self.angle += 0.01;
        }

實(shí)在無(wú)法理解為什么角度的改變會(huì)影響天空盒的顯示怀大。
回顧了一下OpenGL ES的繪制過(guò)程,從頂點(diǎn)緩存到變換呀闻、著色到幀緩存,發(fā)現(xiàn)天空盒的繪制都沒(méi)有問(wèn)題潜慎。
接著開(kāi)始思考捡多,會(huì)不會(huì)是飛機(jī)的繪制影響了天空盒的繪制?因?yàn)檫@是兩個(gè)著色器铐炫,存在不同的頂點(diǎn)數(shù)據(jù)和紋理垒手。
于是嘗試在繪制完天空盒后調(diào)用下面,防止天空盒綁定的數(shù)據(jù)緩存被飛機(jī)的影響倒信。

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

在繪制完飛機(jī)后調(diào)用下面科贬,防止飛機(jī)的頂點(diǎn)數(shù)據(jù)去影響到天空盒。

    glDisableVertexAttribArray(GLKVertexAttribPosition);
    glDisableVertexAttribArray(GLKVertexAttribNormal);
    glBindTexture(GL_TEXTURE_2D, 0);

然而并沒(méi)有什么用 ==鳖悠!

問(wèn)題擱在心頭好幾天榜掌,每天都會(huì)嘗試,也在google查GLKSkyboxEffect相關(guān)的問(wèn)題乘综,可惜GLKSkyboxEffect是蘋(píng)果官方自己實(shí)現(xiàn)憎账。
本來(lái)天空盒是上周就已經(jīng)實(shí)現(xiàn)好,為了寫(xiě)這篇文章實(shí)現(xiàn)了一個(gè)暫停的功能卡辰,就出現(xiàn)這個(gè)bug胞皱。雖然去掉暫停功能很正常,但是這個(gè)表明demo確實(shí)有缺陷九妈,無(wú)法棄之不顧反砌。
經(jīng)過(guò)很多天嘗試后,已經(jīng)可以確定的是萌朱,是飛機(jī)的繪制影響了天空盒的位置宴树,角度的旋轉(zhuǎn)只是隱藏了bug。
開(kāi)始尋找非OpenGL ES的文章嚷兔,看看OpenGL的天空盒實(shí)現(xiàn)森渐,同時(shí)查看蘋(píng)果官方的文檔。
最后偶然在蘋(píng)果的文檔中看到一個(gè)關(guān)鍵詞OES冒晰,我似乎明白了什么同衣。
OES是OpenGL ES的一個(gè)非標(biāo)準(zhǔn)擴(kuò)展,天空盒里面有用到壶运,而我并沒(méi)有處理耐齐。
嘗試用OES來(lái)管理飛機(jī)的頂點(diǎn)模型。

//    glGenVertexArraysOES(1, &_mPositionBuffer);
//    glBindVertexArrayOES(_mPositionBuffer);

問(wèn)題果然迎仍而解:暫停的時(shí)候天空盒是正常的。
接下來(lái)開(kāi)始嘗試不用OES埠况,尋找問(wèn)題的根源耸携。
最后的結(jié)論:天空盒的繪制調(diào)用了glBindVertexArrayOES(),可是在繪制結(jié)束后沒(méi)有glBindVertexArrayOES(0);導(dǎo)致飛機(jī)的頂點(diǎn)數(shù)據(jù)影響了天空盒的頂點(diǎn)數(shù)據(jù)辕翰。
解決方案:在繪制完天空盒后調(diào)用glBindVertexArrayOES(0);夺衍,問(wèn)題完美解決。

Tips

天空盒還有兩部分內(nèi)容:一個(gè)是切圖喜命,這個(gè)比較簡(jiǎn)單沟沙,用CoreGraphics即可;另一個(gè)是用Shader來(lái)實(shí)現(xiàn)天空盒壁榕,而非GLKSkyboxEffect矛紫,這部分加進(jìn)來(lái)篇幅就過(guò)長(zhǎng)了。這兩部分都在github上面放了源碼牌里,都已經(jīng)編譯調(diào)試沒(méi)問(wèn)題颊咬,下載完可以直接運(yùn)行。
附上代碼

思考題

  • 為什么視點(diǎn)距離天空盒太近會(huì)產(chǎn)生紋理拉伸牡辽?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喳篇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子催享,更是在濱河造成了極大的恐慌杭隙,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件因妙,死亡現(xiàn)場(chǎng)離奇詭異痰憎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)攀涵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)铣耘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人以故,你說(shuō)我怎么就攤上這事蜗细。” “怎么了怒详?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵炉媒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我昆烁,道長(zhǎng)吊骤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任静尼,我火速辦了婚禮白粉,結(jié)果婚禮上传泊,老公的妹妹穿的比我還像新娘。我一直安慰自己鸭巴,他們只是感情好眷细,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著鹃祖,像睡著了一般溪椎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惯豆,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天池磁,我揣著相機(jī)與錄音,去河邊找鬼楷兽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛华临,可吹牛的內(nèi)容都是我干的芯杀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼雅潭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼揭厚!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起扶供,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤筛圆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后椿浓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體太援,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年扳碍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了提岔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笋敞,死狀恐怖碱蒙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情夯巷,我是刑警寧澤赛惩,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站趁餐,受9級(jí)特大地震影響喷兼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜澎怒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一褒搔、第九天 我趴在偏房一處隱蔽的房頂上張望阶牍。 院中可真熱鬧,春花似錦星瘾、人聲如沸走孽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)磕瓷。三九已至,卻和暖如春念逞,著一層夾襖步出監(jiān)牢的瞬間困食,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工翎承, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留硕盹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓叨咖,卻偏偏與公主長(zhǎng)得像瘩例,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子甸各,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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

  • 一垛贤、紋理基礎(chǔ) 3D圖形渲染中最基本的操作就是對(duì)一個(gè)表面應(yīng)用紋理。紋理可以表現(xiàn)只從網(wǎng)格的幾何形狀無(wú)法得到的附加細(xì)節(jié)趣倾。...
    cain_huang閱讀 8,806評(píng)論 0 7
  • 目錄結(jié)構(gòu): 第一步聘惦,明確要干嘛 第二步,怎么去畫(huà)(純理論) 第三步儒恋,怎么去畫(huà)(實(shí)戰(zhàn)) 第四步善绎,練練手 第一步,明確...
    半紙淵閱讀 8,081評(píng)論 18 57
  • 摘自:Cocos2d-x 高級(jí)開(kāi)發(fā)教程-第10章OpenGL基礎(chǔ) OpenGL簡(jiǎn)介(1) OpenGL是一個(gè)基于C...
    資深小夏閱讀 1,605評(píng)論 0 0
  • 十年寒窗碧浊,一朝高考 考完之后猛然的放松涂邀,莘莘學(xué)子們是否會(huì)感到了一絲的茫然與無(wú)措呢? 接下來(lái)箱锐,該如何安排長(zhǎng)達(dá)3個(gè)月的...
    五道口科技閱讀 226評(píng)論 0 0