iOS開發(fā)-OpenGLES進(jìn)階教程3

教程

OpenGLES入門教程1-Tutorial01-GLKit
OpenGLES入門教程2-Tutorial02-shader入門
OpenGLES入門教程3-Tutorial03-三維變換
OpenGLES入門教程4-Tutorial04-GLKit進(jìn)階
OpenGLES進(jìn)階教程1-Tutorial05-地球月亮
OpenGLES進(jìn)階教程2-Tutorial06-光線
這次的內(nèi)容是粒子效果。

效果展示

粒子效果.gif

核心思路

  • 自定義shader著色器
    通過(guò)glCreateProgram()創(chuàng)建shader。

  • 圖形變換
    GLKMatrix4MakeLookAt實(shí)現(xiàn)模型變換
    GLKMatrix4MakePerspective實(shí)現(xiàn)透視變換

  • 粒子效果
    glDrawArrays的GL_POINTS參數(shù)可以用來(lái)畫粒子
    glsl的頂點(diǎn)著色有內(nèi)建變量gl_PointSize,可以用來(lái)設(shè)置粒子大小

  • 物理
    通過(guò)a = f/m算加速度
    v = v0 + at 算速度
    s = s0 + 0.5 * (v0 + v) * t 算距離

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

  • AGLKPointParticleEffect類
    AGLKPointParticleEffect類管理并且繪制所有的粒子。
- (void)addParticleAtPosition:(GLKVector3)aPosition
   velocity:(GLKVector3)aVelocity
   force:(GLKVector3)aForce
   size:(float)aSize
   lifeSpanSeconds:(NSTimeInterval)aSpan
   fadeDurationSeconds:(NSTimeInterval)aDuration;

添加一個(gè)粒子的方法,參數(shù)包括初始速度、受力、大小、持續(xù)時(shí)間、漸隱時(shí)間,** 注意 ** 粒子會(huì)根據(jù)生命周期進(jìn)行復(fù)用。
loadShaders 方法是加載shader
prepareToDraw方法緩存頂點(diǎn)數(shù)據(jù)、為頂點(diǎn)著色器的變量賦值

  • AGLKPointParticleShader類
    代碼注釋非常詳細(xì)
attribute vec3 a_emissionPosition; //位置
attribute vec3 a_emissionVelocity; //速度
attribute vec3 a_emissionForce; //受力
attribute vec2 a_size;  //大小 和 Fade持續(xù)時(shí)間  size = GLKVector2Make(aSize, aDuration);
attribute vec2 a_emissionAndDeathTimes; //發(fā)射時(shí)間 和 消失時(shí)間

// UNIFORMS
uniform highp mat4      u_mvpMatrix; //變換矩陣
uniform sampler2D       u_samplers2D[1]; //紋理
uniform highp vec3      u_gravity; //重力
uniform highp float     u_elapsedSeconds; //當(dāng)前時(shí)間

// Varyings
varying lowp float      v_particleOpacity; //粒子 不透明度

void main()
{
    highp float elapsedTime = u_elapsedSeconds - a_emissionAndDeathTimes.x; //流逝時(shí)間
    
    // 質(zhì)量假設(shè)是1.0 加速度 = 力 (a = f/m)
    // v = v0 + at : v 是當(dāng)前速度; v0 是初速度;
    //               a 是加速度; t 是時(shí)間
    highp vec3 velocity = a_emissionVelocity +
    ((a_emissionForce + u_gravity) * elapsedTime);
    
    // s = s0 + 0.5 * (v0 + v) * t : s 當(dāng)前位置
    //                              s0 初始位置
    //                              v0 初始速度
    //                              v 當(dāng)前速度
    //                              t 是時(shí)間
    // 運(yùn)算是對(duì)向量運(yùn)算,相當(dāng)于分別求出x、y、z的位置,再綜合
    highp vec3 untransformedPosition = a_emissionPosition +
    0.5 * (a_emissionVelocity + velocity) * elapsedTime;
    
    //得出點(diǎn)的位置
    gl_Position = u_mvpMatrix * vec4(untransformedPosition, 1.0);
    gl_PointSize = a_size.x / gl_Position.w;    
    
    
    // 消失時(shí)間減去當(dāng)前時(shí)間,得到當(dāng)前的壽命; 除以Fade持續(xù)時(shí)間,當(dāng)剩余時(shí)間小于Fade時(shí)間后,得到一個(gè)從1到0變化的值
    // 如果這個(gè)值小于0,則取0
    v_particleOpacity = max(0.0, min(1.0,
                                     (a_emissionAndDeathTimes.y - u_elapsedSeconds) /
                                     max(a_size.y, 0.00001)));
}

shader編譯流程圖

Paste_Image.png

總結(jié)

OpenGL ES的學(xué)習(xí)需要多嘗試,同時(shí)有規(guī)范的代碼習(xí)慣,還要對(duì)功能進(jìn)行抽象和封裝。
附上源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容