公開課“3D勳章”實現方案

公開課“3D勳章”實現方案

------ opengl es 2.0中加載.obj 與 .mtl

先上一個效果圖
在這裏插入圖片描述

看到這個需求,直接反應是用OpenGLES加載一個.obj(頂點數據)與.mtl(顏色材質信息)文件 就搞定了( .obj與.mtl文件由設計師用3dmax、Maya等工具導出)。
本以爲是一個簡單需求,但做起來發現困難點並不少:

  • OpenGLES如何加載.obj與.mtl文件?
  • 勳章的進入和退出動畫效果?
  • 勳章進入和退出過程中的實時光照效果該怎麼做?

解決這三個問題,是需求實現的關鍵。
爲此,我設計了以下架構實現方式,先看架構圖:

架構實現:
在這裏插入圖片描述

我們從下向上說:

  • 最下邊運行在Android系統上,這個不用細說
  • .obj 3D文件解析引擎:
    自己手動解析的,並不是網上開源框架(大都泛泛而談,只能做demo) 。如果開源,那我的這個工程應該就是第一個開源的比較完善的.obj3D文件.mtl材質文件的Java解析庫
  • 光照系統:
    shader 主要用於模擬 環境光、散射光、鏡面光(高光)。上線產品,爲了效果,必須有光照;
  • 動畫引擎:
    雖然看起來簡單,但設計確是按照一個動畫引擎標準設計的;
    整個動畫引擎可以劃分爲:場景、層、動畫精靈。引擎的架構借鑑了遊戲引擎Cocos2d;
    這樣設計的優點是:
    a、若底層不依賴Opengl ES 底層依賴的是View 或者SurfaceView 可直接移植爲一個2D動畫引擎;
    b、繼續擴展還可以發展做成骨骼動畫;

下面我們對這個架構實現進行詳細說明。

一、OpenGLES如何加載.obj與.mtl文件?

本來以爲網上應該有兼容性較好的obj與mtl的java解析庫,但在網上找了好多代碼,發現其在加載obj與mtl中,基本都存在較大問題。

網上代碼主要分爲了以下幾個部分:

  • mind3d 2011年就已停止維護(爲opengl es1.0),並且在加載多圖形上存在很大的不兼容(主要解析了obj,mtl沒有解析)。
  • 其他一些obj解析代碼,基本都是解析了obj,不管mtl文件
    或者簡單解析了mtl,卻沒有把對應的材質信息應用到opengl 繪製的圖形上
  • 《Android 3D遊戲開發技術寶典——OpenGL ES 2.0》(2012年我和幾個同學寫的書) 第九章 3D模型加載。 當時寫這本書時,也只是簡單解析了obj文件,而且對mtl文件並未做解析(網上很多的例子是把這一章的案例直接照搬了)

mind3d官方地址與源碼
https://code.google.com/archive/p/min3d/
https://github.com/deadmoose/min3d

1.1 Obj 與mtl文件簡單舉例

obj文件是3D模型文件格式。由Alias|Wavefront公司爲3D建模和動畫軟件”Advanced Visualizer”開發的一種標準,適合用於3D軟件模型之間的互導,也可以通過Maya讀寫。

  • 只支持模型三角面數據和材質信息,無動畫功能支持;
  • 其中幾何信息由.obj文件提供,材質信息由.mtl文件定義;
  • 文件以行爲單位表示一條數據,可以根據行開頭的字符判斷後續的內容;
  • 其中 # 字符表示註釋行

1.1.1 obj文件中主要存放的以下幾何信息

  • 三維空間中頂點座標信息
  • 頂點的紋理座標(貼圖座標)信息
  • 頂點的法向量信息(計算光照用)

這裏我手寫了一份triangle.obj文件:

triangle.obj

# mtl材質文件
# mtllib testvt.mtl

# o 對象名稱(Object name)
o adfaf

# 組名稱
g default

# 頂點
v 0 0.5 0
v -0.5 -0.5 0
v 0.5 -0.5 0

# 紋理座標
vt 0.0 1.0
vt 0.0 0.0
vt 1.0 1.0

# 頂點法線
vn 0 0 1

# 當前圖元所用材質
usemtl Default

# s Smooth shading across polygons is enabled by smoothing groups.
# Smooth shading can be disabled as well.
s off

# v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3(索引起始於1)
f 1/1/1 2/2/1 3/3/1

triangle.obj 增加了詳細的註釋;

  • triangle.obj 中規定了模型頂點、紋理、法向量等信息,確定了模型的頂點數據;

1.1.2 mtl文件

這裏我手寫了一份triangle.mtl文件:
mtl中主要規定了幾何圖形的貼圖信息,對環境光、散射光、鏡面光的反射情況、透明度等

triangle.mtl

# 定義一個名爲 'Default'的材質
newmtl Default

# 材質的環境光
Ka 0 0 0
# 散射光
Kd 0.784314 0.784314 0.784314
# 鏡面光
Ks 0 0 0

# 透明度
d 1

# 爲漫反射指定顏色紋理文件
map_Kd test_vt.png

triangle.mtl 增加了詳細的註釋;

  • triangle.mtl 中規定了模型材質相關的信息,包括紋理貼圖、環境光、鏡面光、散射光等相關配置都來自這個文件;

1.1.3 triangle.obj與triangle.mtl加載到OpenGL後的運行效果

這裏寫圖片描述

  • 加載triangle.obj與triangle.mtl 模型後的運行效果圖如上圖所示;
  • 這裏爲了方便理解,所以僅僅加載的是一個最簡單的普通三角形;

這裏寫圖片描述

  • 加載的triangle.obj與triangle.mtl 三角形,在三維空間中的位置如上圖所示。
  • 三維空間中頂點的位置信息來源於triangle.obj文件中。

關於關照與材質相關,詳細信息,可參考我的另一篇文章:
http://blog.csdn.net/xiaxl/article/details/76826812

二、動畫引擎實現

在這裏插入圖片描述

說動畫實現之前,先要說一下動畫引擎架構的設計。
動畫引擎實現,參考了Cocos2d遊戲引擎的設計思想,整個動畫引擎分爲了三層:

2.1、動畫引擎架構實現

前邊說了,這個設計實際參考了Cocos2d遊戲引擎的設計思想,所以實現上與Cocos2d有很多的相似之處:
在這裏插入圖片描述

  • 場景:場景負責繪製其所包含的全部層;
  • 層:層負責管理、繪製其中的精靈;
    層亦可以攜帶精靈做出一些旋轉、平移、縮放 等簡單的動畫效果;
  • 精靈:精靈是遊戲實體,精靈是活潑的,可以做很多的動畫效果;
    精靈應該是活潑的、好動的!!!
    而動畫引擎中的 SpriteAnima ,則是我賦予精靈的動畫實現,也是精靈活潑起來的根本。

2.2、具體的代碼實現

在具體分層代碼實現上:

在這裏插入圖片描述

  • 場景:場景繼承自GLSurfaceView 管理者衆多的層,負責頁面繪製;
  • 層: 層管理者衆多的精靈,並且繼承自SpriteAnima
    層亦被賦予了動畫屬性,可以攜帶衆多的精靈完成動畫,而不影像精靈的動畫;
    同時也賦予了層活潑好動的天性
  • 精靈:當然亦繼承自SpriteAnima,天然活潑好動。

2.3、SpriteAnima 動畫實現

具體動畫類的實現,則參考了Android屬性動畫的實現方案:

Opengl ES中的屬性動畫

在這裏插入圖片描述

以上代碼截圖,就是我自定義實現的Opengl ES中的屬性動畫

參考Android屬性動畫:

  • 通過反射調用,不斷更改精靈的AngleY屬性值來完成精靈屬性的變更。
  • 這裏我還加入了Android的動畫差值器 OvershootInterpolator ,使得勳章動畫在運行時,具備動畫越過便邊界後,回彈的效果。我們的勳章精靈變得更加活潑。

讓精靈活潑起來

在這裏插入圖片描述
如以上代碼截圖所示:只要動畫尚未結束,則不斷請求GLThread的場景重繪,來完成精靈的活潑運動效果

三、3D空間對光的模擬

當光照射到一個物體表面上時,會出現三種情形。

  • 首先,光可以通過物體表面向空間反射, 產生反射光。
  • 其次,對於透明體,光可以穿透該物體並從另一端射出,產生透射光。
  • 最後,部分光將被物體表面吸收而轉換成熱。

在上述三部分光中,僅僅是透射光和反射光能夠進入人眼產生視覺效果。這裏只考慮被照明物體表面的反射光影響,假定物體表面光滑不透明且由理想材料構成,環境假設爲由白光照明。
一般來說,反射光可以分成三個分量,即環境反射、漫反射和鏡面反射

在這裏插入圖片描述

  • 鏡面光:上圖中,最亮部分爲鏡面光
  • 散射光(漫反射光):上圖中,比鏡面光稍暗部分爲散射光
  • 環境光:上圖中,最暗部分爲環境光

三維場景中,只要能模擬出以上三種光照效果,則成功模擬了虛擬世界中的光照。完成產品經理、設計是要求,成功上線則不成問題。

3.1、環境光 模擬

從四面八方照射向物體的光,這種光是非發光物體反射的其他光;
因此,環境光可以選擇一個較暗的顏色值進行模擬

在這裏插入圖片描述

shader代碼實現

shader 代碼實現如下:選擇一個較暗的顏色值模擬環境光

在這裏插入圖片描述

3.2、散射光(漫反射光) 模擬

光源照射到物體的表面,經過物體表面的漫反射,四面八方反射出去的光。

在這裏插入圖片描述

如上圖所示,一個光源照直射到一個球面,半個球面會有相應的反射光,這裏要模擬的就是這樣的光:
半球面中心點最亮,一直到球面邊緣逐漸變暗

公式來計算

我們可以用如下公式來計算散射光:

在這裏插入圖片描述

  • 光照的中心點最亮
  • 入射角越大,最終的散射光強度就越小;從中心到邊緣慢慢變暗

shader代碼實現

在這裏插入圖片描述

newNormal 點的法向量、vp 點到光源的向量 均爲單位向量,因此,向量點乘即爲入射角的cos值;

在這裏插入圖片描述

3.3、鏡面光 模擬

相比散射光,高光的亮度區域進一步縮小,是光照射到物體中最亮的一塊

在這裏插入圖片描述

  • V點到攝像機的向量
  • L點到光源的向量
  • H V與L的半向量

模擬公式

我們可以用以下公式來模擬:

在這裏插入圖片描述

shader代碼實現

在這裏插入圖片描述

四、最終效果

  • OpenGLES如何加載.obj與.mtl文件?
  • 勳章的進入和退出動畫效果?
  • 勳章進入和退出過程中的實時光照效果該怎麼做?

以上三個問題解決完成,我們來瞅瞅最終效果(炫耀一下):

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

五、開源

最後,兩個字:代碼開源...

文檔地址:
http://blog.csdn.net/xiaxl/article/details/77048507
案例實現代碼:
https://github.com/xiaxveliang/GLES2_Anima_LoadFrom_Obj

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章