我正在学习如何使用模板缓冲区,但到目前为止还没有成功地获得一个简单的例子。实际上,尽管尝试了glStencilOp
和glStencilFunc
的各种参数组合,但我还没有看到任何证据表明模板缓冲区正在工作。我开始怀疑我的图形驱动程序(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);
}
}
答案 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);
强>
答案 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是在运行时更改像素格式比创建和销毁渲染上下文(“画布”)更好的方法。