0

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

这是我所看到的:

在此处输入图像描述

我期待看到红色钻石被绿色钻石夹住。我究竟做错了什么?

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

2 回答 2

4

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

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

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

于 2013-09-27T00:58:56.003 回答
3

您需要调用glStencilMask()它来控制写入或不写入的内容。将其设置为写或不写,绘制模板(在您的情况下为菱形),glStencilMask()再次设置,然后绘制您想要剪裁的内容。

这有一个很好的示例:模板缓冲区解释

编辑:

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

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

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

我的剪辑输出

感谢:在 jogl 中启用模板

于 2013-09-26T20:49:13.183 回答