OpenGL/JOGL使用模板测试(Stencil test)

在OpenGL中,往往需要对鼠标选中的对象进行突出显示,此时就需要给物体增加一个光环;

部分核心代码如下所示:

float haloScale = 1.1;

static GLfloat blueMaterial[] = {0.0, 0.0, 1.0, 1.0},
        redMaterial[] = {1.0, 0.0, 0.0, 1.0},
        purpleMaterial[] = {0.3, 0.0, 0.3, 1.0},
        greenMaterial[] = {0.0, 1.0, 0.0, 1.0},
        grayMaterial[] = {0.1, 0.1, 0.1, 1.0};

static GLfloat lightPosition0[4],lightPosition1[4];
static float lightAngle = 0.0, lightHeight = 20;
static GLfloat lightColor[] = {1.f, 1.f, 1.f, 1.0}; /* green-tinted */


//--------------------------------【Display( )函数】--------------------------------------------
//		描述:绘图回调函数
//----------------------------------------------------------------------------------------------
void Display()
{
    glStencilMask(0xffffffff);
    glClearStencil(0x4);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    if(haloScale>1.0){
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_ALWAYS, 1, 0xFF);
        glStencilMask(0xFF);
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    }

    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
    glPushMatrix();
    glTranslatef(0, 8.0, 10);
    glColor3f(0.f,0.f,1.f);
    glutSolidSphere(5, 12, 12);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(0, 20.0, 0);
    glColor3f(1.f,0.f,0.f);
    glutSolidSphere(5, 12, 12);
    glPopMatrix();

    if(haloScale>1.0){
        glEnable(GL_STENCIL_TEST);
        glColor3f(1.f, 1.f, 0.f);
        glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
        glStencilMask(0xFF);
        glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);

        glPushMatrix();
        glTranslatef(0, 8.0, 10);
        glScalef(haloScale, haloScale, haloScale);
        glutSolidSphere(5, 12, 12);
        glPopMatrix();

        glPushMatrix();
        glTranslatef(0, 20.0, 0);
        glScalef(haloScale, haloScale, haloScale);
        glutSolidSphere(5, 12, 12);
        glPopMatrix();
        
        glDisable(GL_STENCIL_TEST);
    }

    glEnable(GL_NORMALIZE);
    glDisable(GL_COLOR_MATERIAL);
    //画栅格
//    glMaterialfv(GL_FRONT, GL_DIFFUSE, grayMaterial);
    glColor3f(0.1f, 0.1f, 0.1f); //设置栅格线条的颜色
    glLineWidth(0.1f);
    glBegin(GL_LINES);
    for (int i = -100; i <= 100; i += 10)
    {
        glVertex3f(i, 0, -100);
        glVertex3f(i, 0, 100);
        glVertex3f(100, 0, i);
        glVertex3f(-100, 0, i);
    }
    glEnd();

    DrawCoordinate(50, 50, 50); //坐标轴线的长度

    glDisable(GL_NORMALIZE);

    glLoadIdentity();
    gluLookAt(_eye.x,_eye.y,_eye.z, _target.x,_target.y,_target.z, _up.x,_up.y,_up.z);

    glutSwapBuffers();
}

//--------------------------------【main( )函数】--------------------------------------------
//		描述:主函数
//----------------------------------------------------------------------------------------------
int main(int argc, char **argv)
{
    glutInit(&argc, argv); //对Glut进行初始化

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL | GLUT_MULTISAMPLE); //设置显示方式,GLUT_DOUBLE表示使用双缓冲,GLUT_RGBA表示使用RGBA颜色,R值(红色分量)、G值(绿色分量)、B值(蓝色分量)和A值(alpha分量)

    glutInitWindowSize(win_width, win_height); //设置窗口大小

    glutInitWindowPosition(0, 0); //设置窗口位置

    glutCreateWindow("光环"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口。

    glutDisplayFunc(&Display);

    glutReshapeFunc(Reshape);

    glutMouseFunc(Mouse);

    glutMouseWheelFunc(mouseWheel);

    glutMotionFunc(Motion); //glutMotionFunc是响应鼠标键按下去后,移到鼠标的情形!

    glutKeyboardFunc(Keyboard);

    Init();

    glutMainLoop();

    return 0;
}

最终结果如下图所示:

 

附上国外介绍如何生成光环的链接:

https://www.opengl.org/archives/resources/code/samples/mjktips/StenciledHaloEffect.html

在C++中利用OpenGL实现了给物体添加光环功能,但是在JOGL中实现该功能时,Stencil test功能一直不起作用,翻阅了网上许多关于JOGL的资料,其中有效的链接如下:

https://chrisingradschool.wordpress.com/2010/02/19/enabling-the-stencil-buffer-in-jogl-opengl-java/?unapproved=225&moderation-hash=2e9983b80e7bbcc5e661a3557979e751#comment-225

https://stackoverflow.com/questions/19038015/whats-wrong-with-this-simple-opengl-jogl-stencil-test

这两个链接中都提到了需要通过glcapabilities来设置StencilBit,类比于C++中使用glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL )来清除模板缓冲

所以,在JOGL中创建GlPanel的时候,需要加上glcapabilities.setStencilBits(8);

private GLJPanel createGlPanel() throws AWTException {

   GLProfile glprofile = GLProfile.getDefault();
   GLCapabilities glcapabilities = new GLCapabilities(glprofile);
   glcapabilities.setStencilBits(8);
   panel = new GLJPanel(glcapabilities);

   return panel;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值