这个简单的 OpenGL/JOGL 模板测试有啥问题?
Posted
技术标签:
【中文标题】这个简单的 OpenGL/JOGL 模板测试有啥问题?【英文标题】:What's wrong with this simple OpenGL/JOGL stencil test?这个简单的 OpenGL/JOGL 模板测试有什么问题? 【发布时间】:2013-09-26 20:25:09 【问题描述】:我正在学习如何使用模板缓冲区,但到目前为止,即使是一个简单的示例也未能成功。事实上,尽管尝试了 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);
【问题讨论】:
我认为你错过了一个调用 glStencilMask() 的调用。 en.wikibooks.org/wiki/OpenGL_Programming/Stencil_buffer @zero298 我尝试了使用和不使用glStencilMask
。我将它添加到上面的示例中,它仍然会产生相同的图像。
试试我的新编辑。复制并粘贴代码后,更改功能就起作用了。
【参考方案1】:
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 是一种在运行时更改像素格式的好方法,而不是创建和销毁渲染上下文(“画布”)。
【讨论】:
+1 感谢您指出这一点。 @zero298 的回答让我摸不着头脑,因为事实上,我的 init 方法中确实有glcapabilities.setStencilBits(8)
。
啊,谢谢,我没有注意到 glCapabilities 已经在代码中了。我只是看到它不是并且知道这是一个问题。下次我一定会解释为什么会起作用。【参考方案2】:
您需要致电glStencilMask()
,它可以控制写入或不写入的内容。将其设置为写或不写,绘制模板(在您的情况下为菱形),再次设置glStencilMask()
,然后绘制您想要剪裁的内容。
这有一个很好的样本:Stencil Buffer explanation
编辑:
好的,我想我找到了问题所在。您需要在程序的顶部设置您的功能。
final GLCapabilities glcapabilities = new GLCapabilities(glprofile);
glcapabilities.setStencilBits(8);
final GLCanvas glcanvas = new GLCanvas(glcapabilities);
重要的部分是:
glcapabilities.setStencilBits(8);
感谢:enabling stencil in jogl
【讨论】:
如果这是解决方案,我会非常高兴,但我已经尝试过了,但没有成功。请参阅我上面编辑的示例。我得到了同样的结果。 @whiskeyspider:仅仅因为您在代码中添加了该行并不意味着您做得正确。您需要在创建渲染上下文之前设置功能。换句话说,在final GLCanvas glcanvas = new GLCanvas(glcapabilities);
之前。以上是关于这个简单的 OpenGL/JOGL 模板测试有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章
win系统可以连网,但是Ubuntu系统不能连。电脑装的双系统,不知道啥问