2015-07-02 127 views
0

我畫一個三角形在OpenGL,如:在OpenGL在繪圖時轉換像素座標到標準化的座標3.0

  MyGLRenderer() 
      { 
       fSampleVertices = ByteBuffer.allocateDirect(fSampleVerticesData.length * 4) 
         .order (ByteOrder.nativeOrder()).asFloatBuffer(); 

       fSampleVertices.put(fSampleVerticesData).position (0); 

       Log.d(TAG, "MyGLRender()"); 
      } 

      private FloatBuffer fSampleVertices; 

      private final float[] fSampleVerticesData = 
        { .8f, .8f, 0.0f, -.8f, .8f, 0.0f, -.8f, -.8f, 0.0f }; 

      public void onDrawFrame(GL10 unused) 
      { 
       GLES30.glViewport (0, 0, mWidth, mHeight); 

       GLES30.glClear (GLES30.GL_COLOR_BUFFER_BIT); 

       GLES30.glUseProgram (dProgramObject1); 

       GLES30.glVertexAttribPointer (0, 3, GLES30.GL_FLOAT, false, 0, fSampleVertices); 

       GLES30.glEnableVertexAttribArray (0); 

       GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3); 

       //Log.d(TAG, "onDrawFrame()"); 
      } 

所以,因爲我已經與座標不採取試驗很長時間才發現屏幕 的可見區域介於-1,1之間。那麼三角形佔據了屏幕的80%。以及我已經確定,我的 GLSurfaceView的像素尺寸寬度爲2560,高度爲1600。

因此再給予這些基於像素座標(fBoardOuter)三角形:

1112.0f 
    800.0f 
    0.0f 
    -1280.0f 
    800.0f 
    0.0f 
    -1280.0f 
    -800.0f 
    0.0f 

我不得不要麼轉換的像素座標的東西-1,1之間或找到一種方法來gl在繪製時將這些座標變換爲 ?由於我對OpenGL很新,所以我正在尋找一些指導來做到這一點?

我的頂點着色器是這樣的:

String sVertexShader1 = 
       "#version 300 es    \n" 
      + "in vec4 vPosition;   \n" 
      + "void main()     \n" 
      + "{       \n" 
      + " gl_Position = vPosition; \n" 
      + "}       \n"; 

我會正確的,那麼在說,基於系統的像素將被稱爲世界座標?我現在想要做的只是棋盤遊戲的2D繪圖。


我發現Android有這樣的功能:

orthoM(float[] m, int mOffset, float left, float right, float bottom, float top, float near, float far) 

但是沒有什麼到目前爲止我讀過的文檔中解釋的矩陣的使用如何浮動[]可以將像素座標轉換爲GLES30中的矩陣的歸一化座標。

我還發現這裏的文檔:

http://developer.android.com/guide/topics/graphics/opengl.html

基於關我試圖創建一個實例文檔:

http://pastebin.com/5PTsfSdz

在引擎收錄例子fSampleVertices我想會更小,並且在屏幕的中心,但它不是它仍然幾乎是整個屏幕,如果我嘗試將它放入gl,fBoardOuter只會向我顯示一個黑屏DrawArray。

回答

1

您可能需要找一本書或一些好的教程來深入瞭解其中的一些概念。但是因爲你的問題中有一些特定的項目,我會盡量在這個格式中解釋它們。

您發現的座標系統,其中x和y座標方向的範圍爲[-1.0,1.0],正式名稱爲Normalized Device Coordinates,通常縮寫爲NDC。這與您提出的名稱非常相似,因此一些OpenGL術語實際上非常合乎邏輯。 :)

至少只要你處理2D座標,這就是你的頂點着色器需要產生的座標範圍。即您分配給內置gl_Position變量的座標需要在此範圍內才能在輸出中可見。如果您正在處理3D座標並應用透視投影,事情會變得稍微複雜一些,但現在我們將跳過該部分。

現在,你已經猜到了,你有兩個主要選擇,如果你想在不同的座標系來指定座標:

  1. 您將它們轉換到NDC在你的代碼,你將它們傳遞到OpenGL的面前。
  2. 你有OpenGL應用轉換到你的輸入座標。

選項2顯然是更好的選擇,因爲GPU在執行這項工作時非常高效。

在一個非常簡單的層面上,這意味着您可以修改頂點着色器中的座標。如果你看看你的非常簡單的第一個頂點着色器:

in vec4 vPosition; 
void main() 
{ 
    gl_Position = vPosition; 
} 

你通過你的應用程序代碼在vPosition輸入變量提供的座標,和您分配正是他同坐標的頂點着色器輸出gl_Position

如果您想使用不同的座標系,則需要在頂點着色器代碼中處理輸入座標,並將處理後的座標分配給輸出。

現代版本的OpenGL並沒有真正爲這些座標系統命名。當這些東西仍然硬連接到固定管道時,曾經有「模型座標」和「世界座標」。既然這是用可編程着色器代碼完成的,那麼從OpenGL的角度來看,這些概念就不再相關。它所關心的是來自頂點着色器的座標。在此之前發生的一切都是你自己的事情。

應用線性變換的規範方式,包括您需要的翻譯和縮放,以便將其用於預期的用途,方法是將座標乘以變換矩陣。如果您不想自己編寫(簡單)代碼,您已經發現了包含一些用於構建轉換矩陣的實用函數的android.opengl.Matrix程序包。

一旦你有了一個變換矩陣,你將它作爲一個統一的變量傳遞給頂點着色器,並將該矩陣應用到着色器代碼中。這看起來與着色器代碼的方式是例如:

in vec4 vPosition; 
uniform mat4 TransformMat; 
void main() 
{ 
    gl_Position = TransformMat * vPosition; 
} 

要設置這個矩陣的值,你需要得到統一變量的位置鏈接着色器一次後,用prog您的着色器程序:

GLint transformLoc = GLES20.glGetUniformLocation(prog, "TransformMat"); 

然後,至少一次,你想改變矩陣中的每個時刻,您撥打:

GLES20.glUniformMatrix4fv(transformLoc, 1, GL_FALSE, mat, 0); 

其中mat是您自己構建的矩陣,也可以是android.opengl.Matrix中的一個實用函數。請注意,在之後,您通過glUseProgram()使程序處於最新狀態,此調用需要爲