在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://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;
}