2012-06-29 38 views
1

我正在爲iOS創建一個ios繪畫應用程序,並且在最困難的時間在特定點處旋轉繪畫紋理以使其面對筆畫的方向。繪製GL_POINTS(指定2個座標)時,是否可以在頂點處旋轉紋理?

我在用戶的每次觸摸之間分開幾個像素來繪製紋理。頂點被表示爲具有x和y座標的2d點到頂點緩衝區,然後被渲染到屏幕。下面是我使用的繪製代碼:

count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y))/kBrushPixelStep), 1); 
GLfloat *vBuffer = malloc(2 * sizeof(GLfloat)); 
for(i = 0; i < count; i++) { 

    vBuffer[0] = start.x + (end.x - start.x) * ((GLfloat)i/(GLfloat)count); 
    vBuffer[1] = start.y + (end.y - start.y) * ((GLfloat)i/(GLfloat)count); 
    CGFloat degrees = atan2(end.y - start.y, end.x - start.x) * 180/M_PI; 

    glMatrixMode(GL_TEXTURE); 
    glPushMatrix(); 
    glVertexPointer(2, GL_FLOAT, 0, vBuffer); 
    glDrawArrays(GL_POINTS, 0, count); 
    glRotatef(degrees, 0, 0, 1); 
    glPopMatrix(); 
} 

// render to screen 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, renderbuffer); 
[context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

這並沒有給我想要的效果,這是紋理在由代表兩個點之間的偏差角度每個頂點的旋轉。

問題我有是:

  • 我如何在每一個點旋轉只是紋理?
  • 只用x,y座標來表示每個頂點還是必須是3點或更多?
  • 我是否需要啓用紋理映射?那是什麼阻止我獨立旋轉每個頂點的紋理?如果是這樣,我如何表示如上所示的頂點數組的紋理座標數組?我一直沒能弄清楚這一部分。

非常感謝您的幫助!

UPDATE:

我能想出解決辦法,並張貼在這裏我的答案:https://stackoverflow.com/a/11298219/111856

回答

1

,你需要使用一些其他的方式,就像你不能當你畫作爲GL_POINTS旋轉點繪製紋理爲GL_TRIANGLES

+0

這很有道理。我使用POINT sprites將紋理渲染到不同的點,然後意識到點sprite不能旋轉。感謝您的迴應 – kajham

2

我已經能夠通過從頂點着色器傳遞旋轉值來旋轉片段着色器中的紋理。給定一個頂點着色器與以下情況:

attribute float aRotation; 
varying float vRotation; 

的屬性是從您的應用程序傳遞而變化的信息傳遞給片段着色器。沒有什麼需要計算,所以你可以把這個在頂點着色器的main()函數,直接拷貝過來的值:

vRotation = aRotation; 

在片段着色器,你需要有另一種不同的說法:

varying highp float vRotation; 

值gl_PointCoord是一個值在0.0到1.0之間的vec2,其中(0.0,0.0)是左下角,(1.0,1.0)是右上角,所以幾乎沒有翻譯要做這項工作。在您的片段着色器的主要加:

// Set a center position. 
highp vec2 center = vec2(0.5, 0.5); 

// Translate the center of the point the origin. 
highp vec2 centeredPoint = gl_PointCoord - center; 

// Create a rotation matrix using the provided angle 
highp mat2 rotation = mat2(cos(vRotation), sin(vRotation), 
          -sin(vRotation), cos(vRotation)); 

// Perform the rotation. 
centeredPoint = rotation * centeredPoint; 

// Translate the point back to its original position and use that point 
// to get your texture color. 
gl_FragColor = texture2D(uTexture, centeredPoint + center); 

注意:實際點精靈仍然是由發動機得出相同的正方形。如果使用此方法,則需要確保紋理每邊大約有15%的填充(例如,如果圖像是128x128,則需要使用56像素邊距填充圖像)。

3

如果您已經從谷歌搜索(幾乎所有人都可以)到達此頁面,您可能想知道如何旋轉使用gl_PointCoord呈現的精靈。 SteveL接受的答案錯誤地說這是不可能的,但Joel Murphy指出瞭如何做到這一點。

如果您使用喬爾的建議,以下是一些可能與您有關的附加信息。 (在我的書附加,繳費信息是儘可能接近實際的答案,因爲沒有什麼區別!)

  1. 的圖像需要以root原來的2倍大小,即1.414 X,做大不是15%
  2. 在頂點着色器中執行三角函數的效率明顯更高。所以,我有:

    precision mediump float; 
    
    attribute vec3 vertex; 
    attribute vec3 normal; 
    
    uniform mat4 modelviewmatrix[2]; 
    uniform vec3 unib[4]; 
    
    varying float dist; 
    varying mat2 rotn; 
    
    void main(void) { 
        gl_Position = modelviewmatrix[1] * vec4(vertex,1.0); 
        dist = vertex[2]; 
        rotn = mat2(cos(normal[0]), sin(normal[0]), 
          -sin(normal[0]), cos(normal[0])); 
        gl_PointSize = unib[2][2]/dist; 
    } 
    

    片段着色器:

    precision mediump float; 
    
    uniform sampler2D tex0; 
    uniform vec3 unib[4]; 
    
    varying float dist; 
    varying mat2 rotn; 
    
    void main(void) { 
        vec2 centre = vec2(0.5, 0.5); 
        vec2 rot_coord = rotn * (gl_PointCoord - centre) + centre; 
        vec4 texc = texture2D(tex0, rot_coord); 
        if (dist < 1.0 || texc.a < unib[0][2]) discard; 
        gl_FragColor = texc; 
    } 
    

PS我使用highp變量切換,因爲一些在SOC板如beaglebone和cubitruck使用手機GPU的不支持它。

PPS作爲這種方法的延伸,我已經將該着色器的一個版本添加到pi3d中,該版本也使用偏移量將texture2D()用作精靈圖集。 vertexfragment