这个简单的OpenGL / JOGL模板测试有什么问题?

时间:2013-09-26 20:25:10

标签: opengl jogl stencil-buffer

我正在学习如何使用模板缓冲区,但到目前为止还没有成功地获得一个简单的例子。实际上,尽管尝试了glStencilOpglStencilFunc的各种参数组合,但我还没有看到任何证据表明模板缓冲区正在工作。我开始怀疑我的图形驱动程序(Mac Pro,Mac OS X 10.8.5)或JOGL(2.0.2)不支持它......或者我缺少一些非常基本的东西。

这就是我所看到的:

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);
    }
}

2 个答案:

答案 0 :(得分:3)

您需要拨打glStencilMask()来控制写入与否的内容。将其设置为执行或不执行,绘制模板(在您的情况下为钻石),再次设置glStencilMask(),然后绘制要剪切的内容。

这样有一个很好的样本:Stencil Buffer explanation

修改

好的,我想我发现了问题。您需要在程序的顶部设置您的功能。

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

答案 1 :(得分:3)

Zero298有正确的想法,但无法解释为什么你在代码中尝试的东西不起作用。当您了解帧缓冲像素格式如何在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      ();

重要的是你在创建渲染上下文(“canvas”)之前这样做。模板缓冲区不是您可以在需要时启用或禁用的 - 您首先必须选择为其保留存储空间的像素格式。由于像素格式在您创建渲染上下文之前是固定的,因此您需要在new GLCanvas (...)之前执行此操作。

您实际上可以使用FBO在没有模板缓冲区的渲染上下文中进行模板操作,但这比您现在应该考虑的要先进得多。如果您想要进行MSAA,可以考虑一些事情,FBO是在运行时更改像素格式比创建和销毁渲染上下文(“画布”)更好的方法。