golang.org/x/mobile/exp/gl/glutil/glimage.go 源碼分析

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

看這篇之前,建議先看之前幾篇,這幾篇是基礎。

Go Mobile 例子 basic 源碼分析
http://www.cnblogs.com/ghj1976/p/5183199.html

OpenGL ES 著色語言
http://www.cnblogs.com/ghj1976/p/5180895.html

仿射變換矩陣(這是glimage包最核心的矩陣演算法變換邏輯基礎知識)
http://www.cnblogs.com/ghj1976/p/5199086.html 

 

glutil 包中重要的類是 Image 類, 它實現了 *image.RGBA 和 OpenGL紋理圖形之間的橋樑,而Image類中最關鍵的就是完成繪圖,我們重點也是分析這個函數。

 

繪圖用的顏色著色器

 

precision用來確定預設精度修飾符,precision mediump float; 基本相當於中等精度。

varying 標示是從頂點著色器傳遞過來的變數。 vec2  2個浮點的向量  UV

uniform 唯讀變數  sampler2D

sampler2D是個啥?其實在CG中,sampler2D就是和texture所綁定的一個資料容器介面。這個說法還是太複雜了,簡單理解的話,所謂載入以後的texture(貼圖)說白了不過是一塊記憶體儲存的,使用了RGB(也許還有A)通道,且每個通道8bits的資料。而具體地想知道像素與座標的對應關係,以及擷取這些資料,我們總不能一次一次去自己計算記憶體位址或者位移,因此可以通過sampler2D來對貼圖進行操作。更簡單地理解,sampler2D就是GLSL中的2D貼圖的類型,相應的,還有sampler1D,sampler3D,samplerCube等等格式。

texture2D(textureSample, UV) 通過texture2D函數我們可以得到一個紋素(texel),這是一個紋理圖片中的像素。函數參數分別為simpler2D以及紋理座標。

參考: http://blog.csdn.net/racehorse/article/details/6664717

 

繪圖用的頂點著色器

參數類型說明:

  • uniform 唯讀變數
  • mat3  3*3 的浮點矩陣。
  • attribute 專用於頂點著色器的唯讀變數
  • vec3 三個浮點的向量、 vec2 2個浮點的向量。
  • varying 標示是要從頂點著色器傳遞的變數,具體變數名字是UV, 後面有UV的計算公式。

gl_Position 相關計算

gl_Position 變數是一個四維 (vec4) 變數,包含頂點的 x、y、z 和 w 值。上面代碼中 w 值恒定為 1,其他值為 mvp * p 計算出來。

mvp 是座標轉換的矩陣,具體計算邏輯請看後面。

p是 Z 軸恒定為1 的 三維變數, 其他兩維 由 pos 參數傳入。

pos 是由 quadXYCoords 傳入的,它是 OpenGl 座標系的四個頂點座標。

 

UV 頂點對應顏色計算

在顏色著色器中, 顏色和位置的對應關係由UV傳入。 UV 的計算在頂點著色器中完成計算。

UV 由 uvp 轉換矩陣 * 具體座標 inUV 計算而來。

inUV 傳遞的值是由 quadUVCoords 傳入的,它是 手機螢幕座標系的座標四個頂點。

 

繪圖函數參數分析


繪製具體圖我們用的下面封裝的函數
golang.org/x/mobile/exp/gl/glutil/glimage.go

// Draw draws the srcBounds part of the image onto a parallelogram, defined by
// three of its corners, in the current GL framebuffer.
func (img *Image) Draw(sz size.Event, topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle) {

這個函數通過給定的三個點(左上方、右上方、左下角)來畫出一個平行四邊形。

  • img  要繪製的圖片類。
  • 這個函數的第一個參數 sz size.Event 是遊戲螢幕的大小。
  • topLeft, topRight, bottomLeft geom.Point  是確定平行四邊形的三個點。
  • srcBounds image.Rectangle 是要繪圖的位置邊界值,即在哪裡繪製這個圖。 通過兩個點 Min, Max Point 來定位。

這個函數輸出參數的座標系是手機螢幕的座標系,如:

在 golang.org/x/mobile/geom 包中有 pixel 和 pt 的轉換函式。

px是像素,螢幕中最小元素單位。
pt是磅數,1英寸為72磅。字型大小的單位一般用磅數。

 

傳遞給OpenGL的 mvp 矩陣值的計算

We are drawing a parallelogram PQRS, defined by three of its corners, onto the entire GL framebuffer ABCD.
我們在整個OpenGL幀緩衝ABCD中畫一個由三個角確定的平行四邊形 PQRS。

The two quads may actually be equal, but in the general case, PQRS can be smaller, and PQRS is not necessarily axis-aligned.
這兩個四邊形實際上是相等的,但一般情況下PQRS會更小,而且PQRS跟座標軸並不對齊。

 

There are two co-ordinate spaces: geom space and framebuffer space.
這裡我們會用到2個座標系, geom座標系和 Framebuffer 座標系。

In geom space, the ABCD rectangle is:
在 geom 座標系中, ABCD的矩形座標如下:

    (0, 0)                               (geom.Width, 0)
    (0, geom.Height)       (geom.Width, geom.Height)

and the PQRS quad is:  PQRS 的座標是:

    (topLeft.X,    topLeft.Y)                         (topRight.X, topRight.Y)
    (bottomLeft.X, bottomLeft.Y)           (implicit,   implicit)

In framebuffer space, the ABCD rectangle is:
在 framebuffer 座標系下,ABCD 矩形座標是

    (-1, +1) (+1, +1)
    (-1, -1)  (+1, -1)

First of all, convert from geom space to framebuffer space.
首先,我們需要從 geom 座標系轉變成 framebuffer 座標系
For later convenience, we divide everything by 2 here: px2 is half of the P.X co-ordinate (in framebuffer space).
為了後面方便起見,我們這裡2分一切,px2是PX座標系實際座標的一半(framebuffer座標系)

px2 := -0.5 + float32(topLeft.X/sz.WidthPt)
py2 := +0.5 - float32(topLeft.Y/sz.HeightPt)
qx2 := -0.5 + float32(topRight.X/sz.WidthPt)
qy2 := +0.5 - float32(topRight.Y/sz.HeightPt)
sx2 := -0.5 + float32(bottomLeft.X/sz.WidthPt)
sy2 := +0.5 - float32(bottomLeft.Y/sz.HeightPt)

這個座標轉換請看:

Next, solve for the affine transformation matrix
下一步,解決 仿射變換矩陣 (仿射變換(Affine Transformation))

有關 仿射變換矩陣 的知識請參看: http://www.cnblogs.com/ghj1976/p/5199086.html 

我們現在要通過計算 A點通過一個矩陣轉換成 P 點座標, B點轉換成 Q點座標, D點轉換成 S點座標,如:

這個轉換肯定是一個 仿射變換 。 

A點的座標是 (-1,+1)   P 的座標是 (2*PX2, 2*PY2)  ,這個轉換可以用下面公式表示。

同理有 B –> Q , D->S 的 公式。

從公式中提取6個運算式如下:

-a00 + a01 + a02 = 2*px2
-a10 + a11 + a12 = 2*py2
+a00 + a01 + a02 = 2*qx2
+a10 + a11 + a12 = 2*qy2
-a00 - a01 + a02 = 2*sx2
-a10 - a11 + a12 = 2*sy2

通過合并運算,可以推理得到

a00 = qx2 - px2
a01 = px2 - sx2
a02 = qx2 + sx2
a10 = qy2 - py2
a11 = py2 - sy2
a12 = qy2 + sy2       

即mvp這個轉換矩陣應該是

 

傳遞給OpenGL的uvp 的矩陣值的計算

這個的計算邏輯過程跟 mvp的過程一樣, 不過是 螢幕座標系 跟

貼圖紋理的座標是類似的, 不過在紋理座標系中, ABCD 的座標是:

        //    (0,0) (1,0)
        //    (0,1) (1,1)

PQRS 四個軸跟座標系是對齊的。如效果所示:

由於是軸對齊的, 所以存在:

px=sx     qy=py

跟上面一樣做 A到P的轉換  和  B到Q的轉換。 矩陣運算如下:

最後可以得到這個轉換矩陣為,這也是 uvp 傳入的值。

 

 

給 OpenGL 傳遞頂點資料

 

下面這三行代碼經常一起出現,含義解釋如下:

    glctx.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY)
    glctx.EnableVertexAttribArray(glimage.pos)
    glctx.VertexAttribPointer(glimage.pos, 2, gl.FLOAT, false, 0, 0)

BindBuffer(target Enum, b Buffer)
的第一個參數是表明buffer的類型,gl.ARRAY_BUFFER表明儲存vertex data。
綁定了buffer後,我們需要為buffer傳值,傳值在之前完成 BufferData 這裡完成。
 
EnableVertexAttribArray(a Attrib)

啟用該屬性

 

VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int)

  • dst: 需要綁定的屬性的索引值。
  • size: 表示buffer中幾個值代表一個vertex。
  • ty: 表示buffer中資料的類型,一般有FIXED, BYTE, UNSIGNED_BYTE, FLOAT, SHORT, UNSIGNED_SHORT。
  • normalized: 這個參數可以設為true或者false,它涉及到資料轉換。一般我們都將它設為false。
  • stride: 如果為0,表示buffer中的資料是按順序儲存。
  • offset: buffer的位移值,如果設定了則會從Offset的位置開始。

整個這個過程可以用表示,圖來自:  https://github.com/fem-d/webGL/blob/master/blog/WebGL%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AF%87%EF%BC%88Lesson%202%EF%BC%89.md

 

https://github.com/fem-d/webGL/tree/master/blog

 

 

資料流程圖

頂點資料傳遞流程圖

 

 

顏色渲染資料傳遞流程圖

 

 

參考:

OpenGL ES 2 封裝庫說明
https://godoc.org/golang.org/x/mobile/gl

glutil 包說明文檔
https://godoc.org/golang.org/x/mobile/exp/gl/glutil

WebGL基礎學習篇
https://github.com/fem-d/webGL/blob/master/blog/WebGL%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0%E7%AF%87%EF%BC%88Lesson%202%EF%BC%89.md

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.