2011-05-08 86 views
0

我一直在努力想辦法解決這個問題,並且在淘汰Stack Overflow和Web之後,我一直在抨擊我的頭,我沒有找到任何示例已經爲我工作。我終於看到了很接近的代碼,所以也許你們(和加爾斯?)可以幫我弄清楚這一點。繪製在OpenGL ES 2D Orthographic(Ortho)模式中的問題

我的第一個問題是,我試圖通過將屏幕抓取作爲紋理來實現運動模糊,然後使用透明度在下一幀中繪製紋理 - 或者使用更多的幀以獲得更多模糊。 (如果任何人有興趣,這是我遵循的指南:http://www.codeproject.com/KB/openGL/MotionBlur.aspx

我已經將屏幕保存爲紋理工作正常。我遇到的問題是在屏幕頂部的Ortho模式下繪製。經過很多次敲打之後,我終於得到了一張基本的方形圖,但是我對OpenGL ES理解的缺乏和一個容易遵循的例子現在讓我難以忍受。我需要採取我保存的紋理,並將其繪製到我繪製的方格中。我一直沒有做的事情似乎有效。

另外,我的第二個問題是,將更復雜的3D模型繪製成Ortho模式。我似乎無法得到任何模型繪製。我正在使用(稍微定製的)min3d框架(http://code.google.com/p/min3d/),並且我試圖在Ortho模式下繪製Object3d,就像我在透視模式下繪製它們一樣。據我瞭解,他們應該畫相同的,他們應該沒有深度。但我似乎根本看不到他們。

這是我正在使用的代碼。我嘗試了很多不同的東西,這是我得到的最接近的東西(實際上是在屏幕上繪製可以看到的東西)。我仍然不知道如何在正視圖中獲得正確的3D模型圖。我確信我正在做一些可怕的錯誤,可能完全誤解了OpenGL繪圖的一些基本方面。讓我知道是否有任何其他代碼需要發佈。

// Gets called once, before all drawing occurs 
// 
private void reset() 
{ 
    // Reset TextureManager 
    Shared.textureManager().reset(); 

    // Do OpenGL settings which we are using as defaults, or which we will not be changing on-draw 

    // Explicit depth settings 
    _gl.glEnable(GL10.GL_DEPTH_TEST);         
    _gl.glClearDepthf(1.0f); 
    _gl.glDepthFunc(GL10.GL_LESS);          
    _gl.glDepthRangef(0,1f);            
    _gl.glDepthMask(true);            

    // Alpha enabled 
    _gl.glEnable(GL10.GL_BLEND);           
    _gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);  

    // "Transparency is best implemented using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
    // with primitives sorted from farthest to nearest." 

    // Texture 
    _gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); // (OpenGL default is GL_NEAREST_MIPMAP) 
    _gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); // (is OpenGL default) 

    // CCW frontfaces only, by default 
    _gl.glFrontFace(GL10.GL_CCW); 
    _gl.glCullFace(GL10.GL_BACK); 
    _gl.glEnable(GL10.GL_CULL_FACE); 

    // Disable lights by default 
    for (int i = GL10.GL_LIGHT0; i < GL10.GL_LIGHT0 + NUM_GLLIGHTS; i++) { 
     _gl.glDisable(i); 
    } 

    // 
    // Scene object init only happens here, when we get GL for the first time 
    // 
} 

// Called every frame 
// 
protected void drawScene() 
{ 
    if(_scene.fogEnabled() == true) { 
     _gl.glFogf(GL10.GL_FOG_MODE, _scene.fogType().glValue()); 
     _gl.glFogf(GL10.GL_FOG_START, _scene.fogNear()); 
     _gl.glFogf(GL10.GL_FOG_END, _scene.fogFar()); 
     _gl.glFogfv(GL10.GL_FOG_COLOR, _scene.fogColor().toFloatBuffer()); 
     _gl.glEnable(GL10.GL_FOG); 
    } else { 
     _gl.glDisable(GL10.GL_FOG); 
    } 

    // Sync all of the object drawing so that updates in the mover 
    // thread can be synced if necessary 
    synchronized(Renderer.SYNC) 
    { 
     for (int i = 0; i < _scene.children().size(); i++) 
     { 
      Object3d o = _scene.children().get(i); 
      if(o.animationEnabled()) 
      { 
       ((AnimationObject3d)o).update(); 
      } 
      drawObject(o); 
     } 
    } 

    // 
    // 
    // 
    // Draw the blur 

    // Set Up An Ortho View 
    _switchToOrtho(); 

    _drawMotionBlur(); 

    // Switch back to the previous view 
    _switchToPerspective(); 

    _saveScreenToTexture("blur", 512); 
} 

private void _switchToOrtho() 
{ 
    // Set Up An Ortho View 
    _gl.glDisable(GL10.GL_DEPTH_TEST); 
    _gl.glMatrixMode(GL10.GL_PROJECTION); // Select Projection 
    _gl.glPushMatrix(); // Push The Matrix 
    _gl.glLoadIdentity(); // Reset The Matrix 
    _gl.glOrthof(0f, 480f, 0f, 800f, -1f, 1f); 
    //_gl.glOrthof(0f, 480f, 0f, 800f, -100f, 100f); 
    _gl.glMatrixMode(GL10.GL_MODELVIEW); // Select Modelview Matrix 
    _gl.glPushMatrix(); // Push The Matrix 
    _gl.glLoadIdentity(); // Reset The Matrix 
} 

private void _switchToPerspective() 
{ 
    // Switch back to the previous view 
    _gl.glEnable(GL10.GL_DEPTH_TEST); 
    _gl.glMatrixMode(GL10.GL_PROJECTION); 
    _gl.glPopMatrix(); 
    _gl.glMatrixMode(GL10.GL_MODELVIEW); 
    _gl.glPopMatrix(); // Pop The Matrix 
} 

private void _saveScreenToTexture(String $textureId, int $size) 
{ 
    // Save the screen as a texture 
    _gl.glViewport(0, 0, $size, $size); 
    _gl.glBindTexture(GL10.GL_TEXTURE_2D, _textureManager.getGlTextureId($textureId)); 
    _gl.glCopyTexImage2D(GL10.GL_TEXTURE_2D,0,GL10.GL_RGB,0,0,512,512,0); 
    _gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 
    _gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
    _gl.glViewport(0, 0, 480, 800); 
} 

private void _drawMotionBlur() 
{ 
    // Vertices 
    float squareVertices[] = { 
     -3f, 0f,  // Bottom Left 
     475f, 0f,  // Bottom Right 
     475f, 800f, // Top Right 
     -3f, 800f // Top Left 
    }; 

    ByteBuffer vbb = ByteBuffer.allocateDirect(squareVertices.length * 4); 
    vbb.order(ByteOrder.nativeOrder()); 
    FloatBuffer vertexBuffer = vbb.asFloatBuffer(); 
    vertexBuffer.put(squareVertices); 
    vertexBuffer.position(0); 

    // 
    // 
    // Textures 
    FloatBuffer textureBuffer; // buffer holding the texture coordinates 
    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) 
    }; 
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(squareVertices.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    byteBuffer = ByteBuffer.allocateDirect(texture.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    textureBuffer = byteBuffer.asFloatBuffer(); 
    textureBuffer.put(texture); 
    textureBuffer.position(0); 
    // 
    // 
    // 

    _gl.glLineWidth(3.0f); 
    _gl.glTranslatef(5.0f, 0.0f, 0.0f); 
    _gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer); 
    _gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 

    _gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4); 
    //_gl.glTranslatef(100.0f, 0.0f, 0.0f); 
    //_gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4); 
    //_gl.glTranslatef(100.0f, 0.0f, 0.0f); 
    //_gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4); 


    _gl.glEnable(GL10.GL_TEXTURE_2D); 
    _gl.glEnable(GL10.GL_BLEND); 
    _gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    _gl.glLoadIdentity(); 

    // 
    // 
    // 
    _gl.glBindTexture(GL10.GL_TEXTURE_2D, _textureManager.getGlTextureId("blur")); 
    _gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
    _gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); 
    // 
    // 
    // 

    _gl.glDisable(GL10.GL_BLEND); 
    _gl.glDisable(GL10.GL_TEXTURE_2D); 
    _gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
} 

編輯:這裏有一個簡單的例子,這一切都在一個功能,不包括任何的屏幕保存到質感的東西。這只是繪製一個3D場景,切換到Ortho,繪製帶有紋理的正方形,然後切換回透視。

// Called every frame 
// 
protected void drawScene() 
{ 
    // Draw the 3d models in perspective mode 
    // This part works (uses min3d) and draws a 3d scene 
    // 
    for (int i = 0; i < _scene.children().size(); i++) 
    { 
     Object3d o = _scene.children().get(i); 
     if(o.animationEnabled()) 
     { 
      ((AnimationObject3d)o).update(); 
     } 
     drawObject(o); 
    } 

    // Set Up The Ortho View to draw a square with a texture 
    // over the 3d scene 
    // 
    _gl.glDisable(GL10.GL_DEPTH_TEST); 
    _gl.glMatrixMode(GL10.GL_PROJECTION); // Select Projection 
    _gl.glPushMatrix(); // Push The Matrix 
    _gl.glLoadIdentity(); // Reset The Matrix 
    _gl.glOrthof(0f, 480f, 0f, 800f, -1f, 1f); 
    _gl.glMatrixMode(GL10.GL_MODELVIEW); // Select Modelview Matrix 
    _gl.glPushMatrix(); // Push The Matrix 
    _gl.glLoadIdentity(); // Reset The Matrix 


    // Draw A Square With A Texture 
    // (Assume that the texture "blur" is already created properly -- 
    // it is as I can use it when drawing my 3d scene if I apply it 
    // to one of the min3d objects) 
    // 
    float squareVertices[] = { 
     -3f, 0f,  // Bottom Left 
     475f, 0f,  // Bottom Right 
     475f, 800f, // Top Right 
     -3f, 800f // Top Left 
    }; 

    ByteBuffer vbb = ByteBuffer.allocateDirect(squareVertices.length * 4); 
    vbb.order(ByteOrder.nativeOrder()); 
    FloatBuffer vertexBuffer = vbb.asFloatBuffer(); 
    vertexBuffer.put(squareVertices); 
    vertexBuffer.position(0); 

    FloatBuffer textureBuffer; // buffer holding the texture coordinates 
    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) 
    }; 
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(squareVertices.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    byteBuffer = ByteBuffer.allocateDirect(texture.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    textureBuffer = byteBuffer.asFloatBuffer(); 
    textureBuffer.put(texture); 
    textureBuffer.position(0); 

    _gl.glLineWidth(3.0f); 
    _gl.glTranslatef(5.0f, 0.0f, 0.0f); 
    _gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer); 
    _gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 

    _gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4); 

    _gl.glEnable(GL10.GL_TEXTURE_2D); 
    _gl.glEnable(GL10.GL_BLEND); 
    _gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    _gl.glLoadIdentity(); 

    _gl.glBindTexture(GL10.GL_TEXTURE_2D, _textureManager.getGlTextureId("blur")); 
    _gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
    _gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); 

    _gl.glDisable(GL10.GL_BLEND); 
    _gl.glDisable(GL10.GL_TEXTURE_2D); 
    _gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

    // Switch Back To The Perspective Mode 
    // 
    _gl.glEnable(GL10.GL_DEPTH_TEST); 
    _gl.glMatrixMode(GL10.GL_PROJECTION); 
    _gl.glPopMatrix(); 
    _gl.glMatrixMode(GL10.GL_MODELVIEW); 
    _gl.glPopMatrix(); // Pop The Matrix 
} 

EDIT2:感謝Christian的回答,我刪除了第二glVertexPointer_gl.glBlendFunc (GL10.GL_ONE, GL10.GL_ONE);(我刪除了他們從上面的示例代碼,以及這樣就不會混淆的問題)。我現在有一個紋理渲染,但只在組成方形的一個三角形中。所以我在屏幕的左側看到一個三角形,它應用了紋理。爲什麼它不適用於廣場的兩半?我認爲這是因爲我只有一個這樣的電話:gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);,所以我實際上只畫一個三角形。

+0

如果您在使用正交投影時遇到問題,您是否更容易閱讀代碼示例?所有這些運動模糊相關的方法在這裏都很混亂。如果您可以提供更多關於正交投影及其用法的更短代碼示例,那麼嘗試幫助會更容易。 – harism 2011-05-08 21:46:30

+0

添加了更簡單的代碼版本。 – 2011-05-08 22:41:07

回答

2

首先,您將混合函數設置爲(GL_ONE,GL_ONE),它將剛剛添加模糊紋理到幀緩衝區並使整個場景過亮。你probalby想要使用(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA),但你必須確保你的模糊紋理有正確的阿爾法,通過配置紋理環境使用alpha(而不是紋理)的常量值或使用GL_MODULATE (1,1,1,0.5)彩色方塊。或者使用片段着色器。

其次,您在第二次調用glVertexPointer時指定了大小3,但是您的數據是2d向量(第一次調用是正確的)。

glOrtho並不一定是2D,它只是一個沒有透視失真的相機(更遠的物體不會變小)。 glOrtho的參數在視圖座標中指定屏幕平面大小。因此,如果您的場景覆蓋單位立方體中的世界,則480x800的鄰位太大(如果您繪製其他對象而不是透視圖,則不會出現問題,因爲您的正方形或UI元素,但是當您想繪製相同的3d天平必須匹配)。另一件事情是,在遠近距離依然重要的情況下,掉落的所有東西都會被剪掉。因此,如果您的相機位於(0,0,0)處,並且您沿着-z方向觀看glOrtho(0,480,0,800,-1,1),則只會看到與(0,0,-1)相交的對象) - (480,800,1)-box。所以請記住,glOrtho和glFrustum(或gluPerspective)都定義了一個3d觀看音量。在它的一個盒子裏,在它的平截頭體中,猜測一個平截頭體(加蓋的金字塔)。如果不夠清楚,請參閱一些關於轉換和查看的介紹性文章。

+0

感謝您的回覆。它實際上已經被設置爲(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA),我認爲(GL_ONE,GL_ONE)粘貼了我昨晚試用的其他一些示例代碼。我會擺脫這一點。我已將ortho模式設置爲480x800,因爲那是屏幕的大小。正如你解釋它,我應該使用更小的座標,紋理仍然會正確顯示?另外,我知道Ortho不是2d,我的意思是我試圖在ortho模式(一個正方形)中顯示2d的東西。我的第二項任務是以正交模式顯示3D對象。 – 2011-05-08 22:42:36

+0

我會嘗試改變這些座標,並且我會去掉第二個glVertexPointer調用,但是我最大的問題是要渲染紋理。我可以看到盒子,所以這是工作,我不能讓紋理顯示。 – 2011-05-08 22:46:57

+1

@ einsteinx2對於你的方塊來說,選擇的正方形是完美的,當渲染ui-stuff或其他東西時,通常將屏幕尺寸設置爲ortho,但它不適用於正常的3d對象(至於第二個你的問題的一部分)。另一個方法是使用ortho(0,1,0,1)並繪製一個單位平方(所以你的屏幕尺寸可以改變並且不寫入平方座標),但是你必須調整平移(不是以像素爲單位)。請記住。你的方形垂直和平移(模糊)​​必須與鄰位匹配。 – 2011-05-08 22:49:58