2015-12-26 65 views
0

所以我有一個程序。我試圖模擬大量具有錯綜複雜時刻邏輯的運動粒子,因爲很多原因我不想參加CGP。當然,我將在GPU上繪製這一切。我應該從結構和類切換到數組嗎?

現在我原本以爲當模擬GPU延遲粒子的TONS將是一個問題,而不是CPU。不幸的是,我以高達6fps的速度運行500個粒子:(我已經跟蹤瞭如何將頂點發送到粒子模擬器的等待時間,甚至沒有創建緩衝區,簡單地說我是如何構建數組的。有陣列,我清除每一幀,然後通過粒子數組中的每個粒子,併爲它們中的每一個創建數組,然後導致大約17500個附加調用(500個粒子),所以我需要一種不同的方式來做到這一點因爲如果不構建這些數組,它將以60fps的速度運行,而不會產生cpu延遲,這些append調用中的大多數都會調用一個結構的成員

當前每個粒子都是基於一個類對象創建的,被存儲在結構中。我會不時地切換s結構到陣列?或者,也許我應該切換到數組?顯然,做任何這些都會使編程變得更加困難。但是它值得嗎?

一個大問題是我需要將每個粒子繪製爲膠囊。我會用兩個點和一條粗線來表示。不幸的是,OpenGL ES 2.0不支持粗線,所以我必須用兩個點和兩個三角形來繪製:(你可以看到函數「calculateSquare」使得這兩個三角形基於兩點,這也非常滯後但它不是唯一的問題,我會嘗試用不同的方式以後找到

你有什麼想法

注:?根據Xcode的內存佔用僅在10 MB然而,CPU框架。時間是141毫秒

這裏是BTW代碼:

func buildParticleArrays() 
    { 
     lineStrip = [] 
     lineStripColors = [] 
     lineStripsize = [] 
     s_vertes = [] 
     s_color = [] 
     s_size = [] 
     for cparticle in particles 
     { 
      let pp = cparticle.lastPosition 
      let np = cparticle.position 
      if (cparticle.frozen == true) 
      { 
       addPoint(cparticle.position, color: cparticle.color, size: cparticle.size) 
      } 
      else 
      { 
       let s = cparticle.size/2.0 

       //Add point merely adds the data in array format 
       addPoint(cparticle.position, color: cparticle.color, size: cparticle.size) 
       addPoint(cparticle.lastPosition, color: cparticle.color, size: cparticle.size) 

       lineStrip += calculateSquare(pp, pp2: np, size: s) 


       for var i = 0; i < 6; i++ 
       { 
        let rgb = hsvtorgb(cparticle.color) 
        lineStripColors.append(GLfloat(rgb.r)) 
        lineStripColors.append(GLfloat(rgb.g)) 
        lineStripColors.append(GLfloat(rgb.b)) 
        lineStripColors.append(GLfloat(rgb.a)) 
        lineStripsize.append(GLfloat(cparticle.size)) 
       } 
      } 



     } 
    } 
func addPoint(theObject: point, color: colorhsv, size: CGFloat) 
    { 

     let rgb = hsvtorgb(color) 
     s_vertes += [GLfloat(theObject.x), GLfloat(theObject.y), GLfloat(theObject.z)] 
     s_color += [GLfloat(rgb.r), GLfloat(rgb.g), GLfloat(rgb.b), GLfloat(rgb.a)] 
     s_size.append(GLfloat(size)) 
    } 

func calculateSquare(pp1: point, pp2: point, size: CGFloat) -> [GLfloat] 
{ 

    let p1 = pp1 
    var p2 = pp2 
    var s1 = point() 
    var s2 = point() 
    let center = CGPointMake((p1.x + p2.x)/2.0, (p1.y + p2.y)/2.0) 


    var angle:CGFloat = 0 
    if ((p1.x == p2.x) && (p1.y == p2.y)) 
    { 
     //They are ontop of eachother 
     angle = CGFloat(M_PI)/2.0 
     p2.x += 0.0001 
     p2.y += 0.0001 
    } 
    else 
    { 
     if(p1.x == p2.x) 
     { 
      //UH OH x axis is equal 
      if (p1.y < p2.y) 
      { 
       //RESULT: p1 is lower so should be first 
       s1 = p1 
       s2 = p2 
      } 
      else 
      { 
       //RESULT: p2 is lower and should be first 
       s1 = p2 
       s2 = p1 
      } 
     } 
     else 
     { 
      //We could be all good 
      if (p1.y == p2.y) 
      { 
       //Uh oh y axis is equal 
       if (p1.x < p2.x) 
       { 
        //RESULT: p1 is left so should be first 
        s1 = p1 
        s2 = p2 
       } 
       else 
       { 
        //RESULT: p2 is to the right so should be first 
        s1 = p2 
        s2 = p1 
       } 
      } 
      else 
      { 
       //Feuf everything is ok 
       if ((p1.x < p2.x) && (p1.y < p2.y)) //First point is left and below 
       { 
        //P1 should be first 
        s1 = p1 
        s2 = p2 
       } 
       else //First point is right and top 
       { 
        //P2 should be first 
        s1 = p2 
        s2 = p1 
       } 
      } 

     } 
     angle = angle2p(s1, p2: s2) 
    } 


    if (angle < 0) 
    { 
     angle += CGFloat(M_PI) * 2.0 
    } 

    let yh = size/2.0 
    let distance = dist(p1, p2: p2) 
    let xh = distance/2.0 

    let tl = rotateVector(CGPointMake(-xh, yh), angle: angle) + center 
    let tr = rotateVector(CGPointMake(xh, yh), angle: angle) + center 
    let bl = rotateVector(CGPointMake(-xh, -yh), angle: angle) + center 
    let br = rotateVector(CGPointMake(xh, -yh), angle: angle) + center 

    let c1:[GLfloat] = [GLfloat(bl.x), GLfloat(bl.y), 0] 
    let c2:[GLfloat] = [GLfloat(tl.x), GLfloat(tl.y), 0] 
    let c3:[GLfloat] = [GLfloat(br.x), GLfloat(br.y), 0] 
    let c4:[GLfloat] = [GLfloat(tr.x), GLfloat(tr.y), 0] 
    let part1 = c1 + c2 + c3 
    let part2 = c2 + c3 + c4 
    return part1 + part2 
} 
+1

內存使用率是10mbps ??你的意思是10 MB? –

+0

我的不好。如果我只有10 mbps,我會有一個高效的程序。將編輯 –

+1

你可以爲自己節省很多痛苦計算角度與atan2(我認爲Darwin.atan2將工作,但我不是Swift專家)。你可以通過簡單的矢量操作節省更多的痛苦,從而完全避免觸發。你可以從(y,-x)與(x,y)成直角的觀察開始。 –

回答

0

你真的需要系統RAM中的所有粒子嗎?例如對於場景中其他物體的某些物理碰撞計算?否則,您可以創建一個粒子,將其發送到GPU並在GPU着色器中進行計算。

+0

你在暗示我通過着色器在GPU中進行了計算? 但是我不知道如何將數據從gpu發送回cpu。此外,我的問題並不完全是我的計算,大部分問題是每幀建立如此龐大的陣列。 –

+0

這是我的問題:你需要系統RAM中的粒子嗎?你爲什麼需要將它發送回CPU?你只需要渲染500次。 – Darko

+0

因爲粒子的運動非常多樣化,所以我需要撞擊粒子。它依賴於大量的全局變量,手指觸摸以及其內部的隨機值。它們不會通過簡單的物理移動,它們的移動代碼至少有幾百行(基於全局變量運行的部分)。 –

0

好吧,經過幾個小時的效率調整後,我就以每秒28幀的速度運行500個粒子,看起來非常流暢!我仍然有一些方法可以去。最好的建議是分配內存,而不是追加內存。這節省了大量的問題。

特別感謝@Darko,@Marcelo_Cantos提出最終優化我的代碼的想法!

相關問題