2013-09-26 30 views
0

我正在學習如何使用模板緩衝區,但到目前爲止還沒有成功獲得一個簡單的例子來工作。事實上,儘管嘗試了各種glStencilOpglStencilFunc的參數組合,但我還是沒有看到任何證據表明模板緩衝區正在工作。我開始懷疑我的圖形驅動程序(Mac Pro,Mac OS X 10.8.5)或JOGL(2.0.2)不支持它......或者我錯過了一些非常基本的東西。這個簡單的OpenGL/JOGL模板測試有什麼問題?

這裏是我所看到的:

enter image description here

我期待看到紅鑽由綠鑽裁剪。我究竟做錯了什麼?

public class Test { 

    public static void main(String[] args) { 
     GLProfile glprofile = GLProfile.getDefault(); 
     final GLCapabilities glcapabilities = new GLCapabilities(glprofile); 
     final GLCanvas glcanvas = new GLCanvas(glcapabilities); 
     final GLU glu = new GLU(); 

     glcanvas.addGLEventListener(new GLEventListener() { 

      @Override 
      public void reshape(GLAutoDrawable glautodrawable, int x, int y, int width, int height) {} 



      @Override 
      public void init(GLAutoDrawable glautodrawable) { 
       GL2 gl = glautodrawable.getGL().getGL2(); 

       glcapabilities.setStencilBits(8); 

       gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); 
       gl.glLoadIdentity(); 

       glu.gluPerspective(45, 1, 1, 10000); 
       glu.gluLookAt(0, 0, 100, 0, 0, 0, 0, 1, 0); 

       gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); 
       gl.glLoadIdentity(); 
      } 



      @Override 
      public void dispose(GLAutoDrawable glautodrawable) {} 



      @Override 
      public void display(GLAutoDrawable glautodrawable) { 
       GL2 gl = glautodrawable.getGL().getGL2(); 

       gl.glEnable(GL.GL_STENCIL_TEST); 

       gl.glClearStencil(0x0); 
       gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); 

       gl.glStencilFunc(GL.GL_ALWAYS, 1, 1); 
       gl.glStencilOp(GL.GL_REPLACE, GL.GL_REPLACE, GL.GL_REPLACE); 
      gl.glStencilMask(0xFF); 
       //gl.glColorMask(false, false, false, false); 
       //gl.glDepthMask(false); 

       gl.glColor3f(0, 1, 0); 
       gl.glBegin(GL2.GL_QUADS); 
       gl.glVertex2f(-25.0f, 0.0f); 
       gl.glVertex2f(0.0f, 15.0f); 
       gl.glVertex2f(25.0f, 0.0f); 
       gl.glVertex2f(0.0f, -15.0f); 
       gl.glEnd(); 

      gl.glStencilMask(0); 
       gl.glStencilFunc(GL2.GL_EQUAL, 1, 1); 
       gl.glStencilOp(GL2.GL_KEEP, GL2.GL_KEEP, GL2.GL_KEEP); 
       //gl.glColorMask(true, true, true, true); 
       //gl.glDepthMask(true); 

       gl.glColor3f(1, 0, 0); 
       gl.glBegin(GL2.GL_QUADS); 
       gl.glVertex2f(-20.0f, 0.0f); 
       gl.glVertex2f(0.0f, 20.0f); 
       gl.glVertex2f(20.0f, 0.0f); 
       gl.glVertex2f(0.0f, -20.0f); 
       gl.glEnd(); 
      } 
     }); 

     final JFrame jframe = new JFrame("One Triangle Swing GLCanvas"); 
     jframe.addWindowListener(new WindowAdapter() { 

      @Override 
      public void windowClosing(WindowEvent windowevent) { 
       jframe.dispose(); 
       System.exit(0); 
      } 
     }); 

     jframe.getContentPane().add(glcanvas, BorderLayout.CENTER); 
     jframe.setSize(640, 480); 
     jframe.setVisible(true); 
    } 
} 
+0

我想你錯過了一個調用glStencilMask()來做模版。 http://en.wikibooks.org/wiki/OpenGL_Programming/Stencil_buffer – zero298

+0

@ zero298我試過,沒有'glStencilMask'。我將它添加到上面的示例中,它仍然會生成相同的圖像。 – whiskeyspider

+0

嘗試我的新編輯。在複製並粘貼代碼之後,更改功能起作用。 – zero298

回答

2

您需要致電glStencilMask()這是控制什麼被寫或不是。設置它做或不寫,繪製模具(在你的情況下,鑽石),再次設置glStencilMask(),然後繪製你想要剪裁的東西。

這有一個很好的例子:Stencil Buffer explanation

編輯:

OK,我想我找到了問題。您需要在程序的頂部設置您的功能。

final GLCapabilities glcapabilities = new GLCapabilities(glprofile); 
glcapabilities.setStencilBits(8); 
final GLCanvas glcanvas = new GLCanvas(glcapabilities); 

最重要的部分是: glcapabilities.setStencilBits(8);

My clipped output

感謝:enabling stencil in jogl

+0

如果這是解決方案,我會很高興,但我已經嘗試過,沒有運氣。看我上面編輯的例子。我得到相同的結果。 – whiskeyspider

+0

@whiskeyspider:僅僅因爲您將該行添加到您的代碼並不意味着您做得很好。您需要設置能力_before_創建渲染上下文。換句話說,在最後的GLCanvas glcanvas =新的GLCanvas(glcapabilities)之前;'。 –

3

Zero298看法是正確的,但不能解釋爲什麼你在你的代碼試圖不起作用。當你瞭解framebuffer像素格式如何在OpenGL中工作時,這會變得更加明顯;我將在下面摸一點點這一點,但最初只是重新哈希妥善解決:

public static void main(String[] args) { 
    GLProfile  glprofile  = GLProfile.getDefault(); 
    GLCapabilities glcapabilities = new GLCapabilities (glprofile); 

    // You must do this _BEFORE_ creating a render context 
    glcapabilities.setStencilBits (8); 

    final GLCanvas glcanvas = new GLCanvas (glcapabilities); 
    final GLU  glu  = new GLU  (); 

重要的是,你創建的呈現上下文(「畫布」)之前做到這一點。模板緩衝區不是您可以在需要時啓用或禁用的功能 - 您首先必須選擇一個爲其保留存儲空間的像素格式。由於像素格式從創建渲染上下文開始就是固定的,因此您需要在new GLCanvas (...)之前執行此操作。

實際上,您可以使用FBO在沒有模板緩衝區的渲染上下文中執行模板操作,但這比您目前應該考慮的要先進得多。有些事情要考慮,如果你想要做MSAA,FBO在運行時改變像素格式比創建和銷燬渲染上下文(「canvas」)要好得多。

+0

+1感謝您指出這一點。我在@ zero298的回答中搔着頭,因爲實際上,我的init方法中已經有'glcapabilities.setStencilBits(8)'。 – whiskeyspider

+0

啊,謝謝,我沒有注意到glCapabilities已經在代碼中。我只是看到它不是,並且知道這是一個問題。下次我一定會解釋爲什麼有些東西可行。 – zero298

相關問題