2012-07-21 19 views
1

我已經成功地完成迄今:的Android/openGL的:填一個2D視口的方形

  • 初始化的GLSurfaceView /渲染器
  • 在屏幕上畫一個三角形
  • 渲染屏幕
  • 在正方形/長方形添加一個位圖紋理屏幕
  • 確保PNG透明度榮幸渲染
  • 時自動調整三角形,所以它們顯示正確的所有屏幕尺寸

但是,固定縮放的三角形後,背景矩形(帶紋理)不再填滿屏幕。

The background no longer fills up the screen

我一直停留在這個有一段時間了,絕對莫名其妙給我在毛巾扔點。

我不確定的主要部分是使用glFrustumf()和gluLookAt()。

@Override 
public void onSurfaceChanged(GL10 gl, int width, int height) { 
    gl.glViewport(0, 0, width, height); 

    ratio = (float) width/height; 
    gl.glMatrixMode(GL10.GL_PROJECTION);  // set matrix to projection mode 
    gl.glLoadIdentity();      // reset the matrix to its default state 
    gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // apply the projection matrix 
} 

@Override 
public void onDrawFrame(GL10 gl) { 
    // Clear the screen 
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 

    // Set GL_MODELVIEW transformation mode 
    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    gl.glLoadIdentity(); // reset the matrix to its default state 

    // When using GL_MODELVIEW, you must set the camera view 
    GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f); 

    bg.draw(gl); 
    // ... 
} 

如果有人有時間來看看這個問題,我已經上傳的文件https://bitbucket.org/koonkii/test_opengl/src,所以你不必重新創建的複製粘貼代碼。

+1

你總是可以自由編輯你的原始文章來添加/更改額外的源代碼,這是最好的添加他們的評論。您也歡迎您發佈自己的問題的答案,但這不合適,除非它真的回答您的問題。 – Tim 2012-07-21 22:33:04

+0

謝謝你的提姆! – twig 2012-07-22 05:21:51

回答

3
GLU.gluLookAt(gl, 0, 0, -5f, 0f, 0f, 0f, 0.0f, 1.0f, 0.0f); 

嘗試-5F更改爲0,你的意思這裏是取代攝像機5臺背部,因此除非你做一正投影(我想你沒有,請嘗試檢查出this)OpenGL正在做的是根據您的透視圖縮放您的背景多邊形,並將其視爲「較小」。

如果您進行正交投影,無論您在z軸上移動相機多少,都會看到相同的尺寸。這對基於2D OpenGL的遊戲非常有用,因此請檢查上面的鏈接。

編輯:gluPerspective和glOrtho

gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); 

gluPerspective有一個名爲 'fovy' 參數,這基本上是 '在Y軸視場'。視野表示攝像機可以看到的空間量,基本上是「擴大」或「收縮」任何頂點。一個典型的人眼有45ºFOV。

zNear和zFar表示近,遠平截頭體限制,平截頭體是一個不可見的「框」,它確定哪些頂點位於可視區域之外。

長寬比確定相機的寬度和高度之間的比例。

glOrtho是gluPerspective的在這個意義上的特殊情況,該FOV始終爲0。

gl.glOrthof(0.0f, (float) width, (float) height, 0.0f, 1.0f, -1.0f); 

前四個參數指定的剪取平面(屏幕的正常大小)的大小,另一兩個值指定了近處和遠處的平截頭體(除非要通過將對象置於「遠處」來隱藏對象,否則不需要這些對象。

我希望這清除它一點你。

+0

你好RedOrav。我一直在關注多個指南(我已經失去了多少,目前只有很多標籤打開),我不確定我正在使用哪個投影。這究竟意味着什麼? (編輯:對不起,我只是做了谷歌搜索這個詞的意思,它似乎就是我需要的!) – twig 2012-07-21 17:39:15

+1

投影是如何轉換3D座標以顯示在2D屏幕上。這就像'壓扁'它們,以便它們可以根據一些參數正確顯示。通常,3D應用程序使用模仿眼睛的45度角「鏡頭」,但您可以使用任何想要使圖像變形的角度(例如在相機中使用凸面或凹面鏡頭) 即,正交投影是其中相機的z軸始終垂直於3D中的一個座標。因此,您只會看到兩個座標,「完全展平」您的圖像。 – RedOrav 2012-07-21 17:47:42

+0

啊,謝謝你。說得通。那麼,我試着將-5.0f減小到0,現在它顯示了一個空白的紅色屏幕(紅色是清晰的顏色)。我也試過更換glFrustum()與glOrthof()和相同的結果(對於-5F和0F)gluLookAt() – twig 2012-07-21 18:03:03

3

好了,經過良好的睡眠和應用有關正交投影RedOrav的意見,我沒有更多的瀏覽到它,得到它的工作!

通過RedOrav給出的代碼片段做實際工作,但是切換到正交投影我仍然繪製正方形和三角形小寬度0.15f後。幾乎不可見,因爲它的寬度小於1個像素!

改變背景/平方米/三角形代碼的東西更合理(30.0f)後,他們發現了!

與碼多一點玩耍了,並得到了妥善安置工作。我已經將代碼提交給bitbucket供那些想查看項目工作副本的人使用。

爲什麼我需要G.getYPos原因()是因爲底部座標= 0,並且頂部是屏幕高度。無法找到一種更好的方式來顛倒它,而不會顛倒所有的紋理。

重要的初始化部分是:

全球幫手

public class G { 
    public static float ratio; 
    public static int width, height; 

    /** The texture pointer */ 
    public static int[] textures = new int[3]; 

    final static int TEXTURE_DEFAULT = 0; 
    final static int TEXTURE_BG = 1; 
    final static int TEXTURE_ANDROID = 2; 
    final static int TEXTURE_TURTLE = 3; 

    /** 
    * Since (bottom = 0, top = height), we need to invert the values so they make sense logically. 
    */ 
    public static int getYPos(int top) { 
     return G.height - top; 
    } 
} 

渲染器類

@Override 
public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
    this.loadGLTextures(gl); 

    gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); //Red Background 
} 

@Override 
public void onSurfaceChanged(GL10 gl, int width, int height) { 
    gl.glViewport(0, 0, width, height); 


    // Save these for global use. 
    G.width = width; 
    G.height = height; 
    G.ratio = (float) width/height; 


    // Set up orthogonal viewport and make adjustments for screen ratio 
    gl.glViewport(0, 0, width, height); 
    gl.glMatrixMode(GL10.GL_PROJECTION); 
    gl.glLoadIdentity(); 
    GLU.gluOrtho2D(gl, 0, width, 0, height); // The parameters are weird but bottom = 0 so we need an inverter function G. 

    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    gl.glLoadIdentity(); 


    // Start setting up the constructs we need 
    bg = new Background(); 

    squares = new ArrayList<Square>(); 
    squares.add(new Square(width/2, G.getYPos(0))); // middle/top of the screen 
    squares.add(new Square(width/2, G.height /2)); // center of the screen 

    triangles = new ArrayList<Triangle>(); 
    triangles.add(new Triangle(0, G.getYPos(0))); // top left 
    triangles.add(new Triangle(width, G.getYPos(height))); // bottom right 
    triangles.add(new Triangle(width /2, height /2)); // middle 
} 

@Override 
public void onDrawFrame(GL10 gl) { 
    // Clear the screen 
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 

    bg.draw(gl); 

    for (Square s : squares) { 
     s.draw(gl); 
    } 

    // Draw correctly scaled triangles 
    for (Triangle t : triangles) { 
     t.draw(gl); 
    } 

    try { 
     Thread.sleep(400); 
    } 
    catch (InterruptedException e) { 
    } 
} 


/** 
* Loads the textures up. 
*/ 
public void loadGLTextures(GL10 gl) { 
    int[] texture_map = new int[] { R.drawable.bg_game, R.drawable.ic_launcher }; 
    Bitmap bitmap; 

    // generate one texture pointer, keep 0 as blank/default 
    gl.glGenTextures(texture_map.length, G.textures, 0); 

    for (int i = 0; i < texture_map.length; i++) { 
     // loading texture 
     bitmap = BitmapFactory.decodeResource(context.getResources(), texture_map[i]); 

     // ...and bind it to our array 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[i +1]); 

     // create nearest filtered texture 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 
     gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 

     // Use Android GLUtils to specify a two-dimensional texture image from our bitmap 
     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 

     // Clean up 
     bitmap.recycle(); 
    } 
} 

背景類 p

ublic class Background { 
    private FloatBuffer vertexBuffer; // buffer holding the vertices 
    private float vertices[] = { 
      -1.0f, -1.0f, 0.0f,  // V1 - bottom left 
      -1.0f, 1.0f, 0.0f,  // V2 - top left 
      1.0f, -1.0f, 0.0f,  // V3 - bottom right 
      1.0f, 1.0f, 0.0f   // V4 - top right 
    }; 

    private FloatBuffer textureBuffer; // buffer holding the texture coordinates 
    private float texture[] = { 
      // Mapping coordinates for the vertices 
      0.0f, 1.0f,  // top left  (V2) 
      0.0f, 0.0f,  // bottom left (V1) 
      1.0f, 1.0f,  // top right (V4) 
      1.0f, 0.0f  // bottom right (V3) 
    }; 


    public Background() { 
     // Recalculate the vertices so they fit the screen 
     vertices[0] = 0;  // v1 left 
     vertices[1] = G.height; // v1 bottom 

     vertices[3] = 0;  // v2 left 
     vertices[4] = 0;  // v2 top 

     vertices[6] = G.width; // v3 right 
     vertices[7] = G.height; // v3 bottom 

     vertices[9] = G.width; // v4 right 
     vertices[10] = 0;  // v4 top 


     // a float has 4 bytes so we allocate for each coordinate 4 bytes 
     ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 

     // allocates the memory from the byte buffer 
     vertexBuffer = byteBuffer.asFloatBuffer(); 

     // fill the vertexBuffer with the vertices 
     vertexBuffer.put(vertices); 

     // set the cursor position to the beginning of the buffer 
     vertexBuffer.position(0); 


     byteBuffer = ByteBuffer.allocateDirect(texture.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 
     textureBuffer = byteBuffer.asFloatBuffer(); 
     textureBuffer.put(texture); 
     textureBuffer.position(0); 
    } 


    public void draw(GL10 gl) { 
     gl.glEnable(GL10.GL_TEXTURE_2D); // Twig; 

     // Bind the previously generated texture 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_BG]); 

     // Point to our buffers 
     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

     // Point to our vertex buffer 
     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 

     // Draw the vertices as triangle strip 
     gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length/3); 

     //Disable the client state before leaving 
     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

     gl.glDisable(GL10.GL_TEXTURE_2D); // twig; 
    } 
} 

Square類 非常類似於背景除了它具有位置和適用alpha透明度。

public class Square { 
    private FloatBuffer vertexBuffer; // buffer holding the vertices 
    private float vertices[] = { 
      -1.0f, -1.0f, 0.0f,  // V1 - bottom left 
      -1.0f, 1.0f, 0.0f,  // V2 - top left 
      1.0f, -1.0f, 0.0f,  // V3 - bottom right 
      1.0f, 1.0f, 0.0f   // V4 - top right 
    }; 

    private FloatBuffer textureBuffer; // buffer holding the texture coordinates 
    private float texture[] = { 
      // Mapping coordinates for the vertices 
      0.0f, 1.0f,  // top left  (V2) 
      0.0f, 0.0f,  // bottom left (V1) 
      1.0f, 1.0f,  // top right (V4) 
      1.0f, 0.0f  // bottom right (V3) 
    }; 


    public Square(float posX, float posY) { 
     float w = 30f; 
     float h = w; 

     vertices[0] = posX - w; // left 
     vertices[3] = posX - w; 
     vertices[6] = posX + w; // right 
     vertices[9] = posX + w; 

     vertices[1] = posY - h; // top 
     vertices[4] = posY + h; 
     vertices[7] = posY - h; // bottom 
     vertices[10] = posY + h; 

     // a float has 4 bytes so we allocate for each coordinate 4 bytes 
     ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 

     // allocates the memory from the byte buffer 
     vertexBuffer = byteBuffer.asFloatBuffer(); 

     // fill the vertexBuffer with the vertices 
     vertexBuffer.put(vertices); 

     // set the cursor position to the beginning of the buffer 
     vertexBuffer.position(0); 



     byteBuffer = ByteBuffer.allocateDirect(texture.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 
     textureBuffer = byteBuffer.asFloatBuffer(); 
     textureBuffer.put(texture); 
     textureBuffer.position(0); 
    } 


    /** The draw method for the square with the GL context */ 
    public void draw(GL10 gl) { 
     // Enable alpha transparency 
     gl.glEnable(GL10.GL_BLEND); 
     gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA); 

     // bind the previously generated texture 
     gl.glEnable(GL10.GL_TEXTURE_2D); // Twig; 

     gl.glBindTexture(GL10.GL_TEXTURE_2D, G.textures[G.TEXTURE_ANDROID]); 

     // Point to our buffers 
     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

     // reset the colour for the square 
     gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 

     // Point to our vertex buffer 
     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 

     // Draw the vertices as triangle strip 
     gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length/3); 

     //Disable the client state before leaving 
     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

     // Disable alpha transparency 
     gl.glDisable(GL10.GL_BLEND); 
     gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ZERO); 

     gl.glDisable(GL10.GL_TEXTURE_2D); // twig; 
    } 
} 

三角類

public class Triangle { 
    private FloatBuffer vertexBuffer; // buffer holding the vertices 

    private float vertices[] = { 
      -0.5f, -0.5f, 0.0f,  // V1 - first vertex (x,y,z) 
      0.5f, -0.5f, 0.0f,  // V2 - second vertex 
      0.0f, 0.5f, 0.0f   // V3 - third vertex 
    }; 

    public Triangle(float posX, float posY) { 
     int w = 30; 
     int h = w; 

     vertices[0] = posX - (w/2); // left 
     vertices[3] = posX + (w/2); // right 
     vertices[6] = posX;   // middle 

     vertices[1] = posY - (h/2); // bottom 
     vertices[4] = posY - (h/2); // bottom 
     vertices[7] = posY + (h/2); // top 

     // a float has 4 bytes so we allocate for each coordinate 4 bytes 
     ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); 
     vertexByteBuffer.order(ByteOrder.nativeOrder()); 

     // allocates the memory from the byte buffer 
     vertexBuffer = vertexByteBuffer.asFloatBuffer(); 

     // fill the vertexBuffer with the vertices 
     vertexBuffer.put(vertices); 

     // set the cursor position to the beginning of the buffer 
     vertexBuffer.position(0); 
    } 

    public void draw(GL10 gl) { 
     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 

     // set the colour for the triangle 
     gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f); 

     // Point to our vertex buffer 
     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 

     // Draw the vertices as triangle strip 
     gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length/3); 

     // Reset the colour 
     gl.glColor4f(1.0f, 1.0f, 1.0f, 0.0f); 

     //Disable the client state before leaving 
     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
    } 
} 

希望這有助於任何人有與OpenGL的開始類似的問題。