您的位置:首页 > 运维架构

OpenGL--多边形偏移

2015-04-13 17:48 211 查看
理论基础

多边形偏移:有时候我们需要着重显示多边形的边缘,一般做法是先绘制实心的再在同一位置绘制空心的,这样就可以突出边缘。但是,由于直线与多边形的光栅化并不完全相同,即使在同一位置绘制它们的深度值也不一定相同,这样绘制的直线可能忽浓忽淡。这时我们就可以激活多边形偏移来解决这个问题,其原理就是给实体或线框的深度加上一个偏移值。即把实体推向远处或把线框拉近,具体偏移值多少是通过设置glPolygonOffset(factor,units)算出的,其底层公式是这样:offset = m * factor + r * units.

实例代码

#include "GLTools.h"
#include "GLShaderManager.h"

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

GLuint list;
GLint spinx = 0;
GLint spiny = 0;
GLfloat tdist = 0.0;
GLfloat polyfactor = 1.0;
GLfloat polyunits = 1.0;

void display (void)
{
    GLfloat gray[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };

    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix ();
    glTranslatef (0.0, 0.0, tdist);
    glRotatef ((GLfloat) spinx, 1.0, 0.0, 0.0);
    glRotatef ((GLfloat) spiny, 0.0, 1.0, 0.0);

    //在开启光照与多边形偏移下,绘制一个实心球体
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gray);
    glMaterialfv(GL_FRONT, GL_SPECULAR, black);
    glMaterialf(GL_FRONT, GL_SHININESS, 0.0);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_POLYGON_OFFSET_FILL);//激活多边形偏移
    glPolygonOffset(polyfactor, polyunits);//计算出一个偏移值,以后每个片段的深度值都加上这个值
    glCallList (list);
    //在关闭光照与多边形偏移下,同一位置绘制一个线框球体
    glDisable(GL_POLYGON_OFFSET_FILL);//关闭多边形偏移
    glDisable(GL_LIGHTING);
    glDisable(GL_LIGHT0);
    glColor3f (1.0, 1.0, 1.0);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glCallList (list);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glPopMatrix ();
    glFlush ();
}

void gfxinit (void)
{
    GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

    GLfloat global_ambient[] = { 0.2, 0.2, 0.2, 1.0 };

    glClearColor (0.0, 0.0, 0.0, 1.0);

    list = glGenLists(1);
    glNewList (list, GL_COMPILE);
    glutSolidSphere(1.0, 20, 12);
    glEndList ();

    glEnable(GL_DEPTH_TEST);

    glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
    glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
    glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
    glLightfv (GL_LIGHT0, GL_POSITION, light_position);
    glLightModelfv (GL_LIGHT_MODEL_AMBIENT, global_ambient);
}

void reshape(int width, int height)
{
    glViewport (0, 0, width, height);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective(45.0, (GLdouble)width/(GLdouble)height,
                   1.0, 10.0);
    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();
    gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void mouse(int button, int state, int x, int y) {
    switch (button) {
        case GLUT_LEFT_BUTTON:
            switch (state) {
                case GLUT_DOWN:
                    spinx = (spinx + 5) % 360;
                    glutPostRedisplay();
                    break;
                default:
                    break;
            }
            break;
        case GLUT_RIGHT_BUTTON:
            switch (state) {
                case GLUT_DOWN:
                    spiny = (spiny + 5) % 360;
                    glutPostRedisplay();
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }
}

void keyboard (unsigned char key, int x, int y)
{
    switch (key) {
        //调节观察点距离
        case 't':
            if (tdist < 4.0) {
                tdist = (tdist + 0.5);
                glutPostRedisplay();
            }
            break;
        case 'T':
            if (tdist > -5.0) {
                tdist = (tdist - 0.5);
                glutPostRedisplay();
            }
            break;
         //调节计算偏移值的两个参数
        case 'F':
            polyfactor = polyfactor + 0.1;
            printf ("polyfactor is %f\n", polyfactor);
            glutPostRedisplay();
            break;
        case 'f':
            polyfactor = polyfactor - 0.1;
            printf ("polyfactor is %f\n", polyfactor);
            glutPostRedisplay();
            break;
        case 'U':
            polyunits = polyunits + 1.0;
            printf ("polyunits is %f\n", polyunits);
            glutPostRedisplay();
            break;
        case 'u':
            polyunits = polyunits - 1.0;
            printf ("polyunits is %f\n", polyunits);
            glutPostRedisplay();
            break;
        default:
            break;
    }
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow(argv[0]);
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutKeyboardFunc(keyboard);
    gfxinit();
    glutMainLoop();
    return 0;
}


下面是没有开启多边形偏移与开启了多边形偏移下的表现:




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: