首页 > 代码库 > OpenGL部分知识小总结

OpenGL部分知识小总结

OpenGL部分知识小总结



光照:

glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);

创建光源:
glLightf(GLenum light, GLenum pname, GLfloat param);
pname参数:
    GL_AMBIENT——环境光
    GL_DIFFUSE——散射光强度,LIGHT0默认为白色,其他为黑色
    GL_SPECULAR——镜面强度,LIGHT0默认为白色,其他为黑色
    GL_POSITION——光源位置
    GL_SPOT_DIRECTION——聚光灯方向
    GL_SPOT_EXPONENT——聚光指数
    GL_SPOT_CUTOFF——聚光灯切角
    GL_CONSTANT_ATTENUATION——常数衰减因子
    GL_LINEAR_ATTENUATION——线性衰减因子
    GL_QUADRATIC_ATTENUATION——二次衰减因子

光照模型:
glLightModel*()描述了光照模型的参数.
pname参数:
    GL_LIGHT_MODEL_AMBIENT: 整个场景的环境光的RGBA参数
    GL_LIGHT_MODEL_LOCAL_VIEWER: 镜面反射角度如何计算,GL_FALSE把观察点放到无限远处
    GL_LIGHT_MODEL_TWO_SIDE: 单面还是双面光照
    GL_LIGHT_MODEL_COLOR_CONTROL: 镜面颜色的计算是否从环境和散射颜色中分离出来

材质属性:
glMaterialf(GLenum face, GLenum pname, GLfloat param);
pname参数:
    GL_AMBIENT: 材料的环境颜色
    GL_DIFFUSE: 材料的散射颜色
    GL_AMBIENT_AND_DIFFUSE
    GL_SPECULAR: 材料的镜面颜色
    GL_SHININESS: 镜面指数  [0.0, 128.0],值越大,亮点越小、越亮
    GL_EMISSION: 材料的发射颜色, eg:模拟台灯
    GL_COLOR_INDEXES: 环境、散射和镜面颜色索引

为了减少材料属性所带来的开销,可以使用glColorMaterial(GLenum face, GLenum mode);
face: GL_FRONT,GL_BACK,GL_FRONT_AND_BACK. mode: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR
然后使用glColor3f()指定颜色

如果想更改单个材料参数的值,可以使用glColorMaterial(),如果想更改多个材料参数的值,可以使用glMaterial*().


混合:

glEnable(GL_BLEND);
glBlendFunc(GLenum sfactor, GLenum dfactor);
混合因子:
    GL_ZERO
    GL_ONE
    GL_SRC_COLOR
    GL_ONE_MINUS_SRC_COLOR
    GL_DST_COLOR
    GL_ONE_MINUS_DST_COLOR
    GL_SRC_ALPHA
    GL_ONE_MINUS_SRC_ALPHA
    GL_DST_ALPHA
    GL_ONE_MINUS_DST_ALPHA
    GL_CONSTANT_COLOR
    GL_ONE_MINUS_CONSTANT_COLOR
    GL_CONSTANT_ALPHA
    GL_ONE_MINUS_CONSTANT_ALPHA
    GL_SRC_ALPHA_SATURATE
如果使用了GL_*CONSTANT*混合,就需要使用glBlendColor(r,g,b,a)指定一种常量颜色

抗锯齿:

glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);  //最好的透视修正
对点和直线进行抗锯齿处理:
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_SMOOTH);
RGB模式下抗锯齿需要启用混合功能glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

使用多重采用对几何图元进行抗锯齿处理:
    多重采样特别适合对多边形的边缘进行抗锯齿处理,因为此时不需要进行排序,如果使用alpha值对多边形进行抗锯齿处理,
半透明的物体的绘图顺序将会影响最终的颜色。
在应用程序中增加多重采样功能:
1)、获取一个支持多重采样的窗口: glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_MULTISAMPLE);;
2)、打开窗口之后,需要验证一下多重采样功能是否可用,如果查询状态变量GL_SAMPLE_BUFFERS返回的值是1,并且GL_SMAPLES
返回的值大于1,就可以采用多重采样功能:
    GLint bufs, smaples;
    glGetIntegerv(GL_SAMPLE_BUFFERS, &bufs);
    glGetIntegerv(GL_SAMPLES, &samples);
3)、启用多重采样功能:
    glEnable(GL_MULTISAMPLE);


雾:
glFogi(GL_FOG_MODE, GL_EXP2);   //设定雾的模式
glFogfv(GL_FOG_COLOR, fogColor);  //设定雾的颜色
glFogf(GL_FOG_DENSITY, 0.35);   //设定雾的密度
glHint(GL_FOG_HINT,GL_DONT_CARE);  //设定雾的渲染方式
glFogf(GL_FOG_START, 1.0);  //设定雾的开始位置
glFogf(GL_FOG_END, 5.0);   //设定雾的结束位置

点参数:
    有时,我们相对那些看上去像圆或球体的物体进行渲染,但是又不想使用效率较低的多边形近似模拟。例如,飞机靠近跑道上的
路灯时,路灯变得越来越大、越来越亮,或者想模拟液滴。可以使用微粒系统模拟这些现象。
    点参数根据点和观察者的距离,对点的大小和亮度进行衰减。使用glPointParameterf*()指定衰减方程式的参数和alpha.
    glPointParameterf(GLenum pname, Glfloat param);
    glPointParameterf(GLenum pname, const TYPE* param);
pname: GL_POINT_DISTANCE_ATTENUATION, param:(a,b,c)数组-常数、线性、二次衰减系数
       GL_POINT_SIZE_MIN OR GL_POINT_SIZE_MAX, param表示最小值or最大值
       ...
为了使用点参数得到圆点而不是方块点,需要启用点抗锯齿功能:
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


多边形偏移:
    如果想着重显示实心物体的边缘,需要使用多边形偏移
启用多边形偏移:
    glEnable(GL_POLYGON_OFFSET_FILL); //GL_POLYGON_OFFSET_LINE , GL_POLYGON_OFFSET_POINT
还需要使用glPolygonMode()设置当前的多边形光栅化方法
eg:

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef GL_VERSION_1_1
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);
    (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_MIDDLE_BUTTON:
	    switch (state) {
		case GLUT_DOWN:
		    spiny = (spiny + 5) % 360; 
                    glutPostRedisplay();
		    break;
		default:
		    break;
            }
            break;
	case GLUT_RIGHT_BUTTON:
	    switch (state) {
		case GLUT_UP:
		    exit(0);
		    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;
}
#else
int main(int argc, char** argv)
{
    fprintf (stderr, "This program demonstrates a feature which is not in OpenGL Version 1.0.\n");
    fprintf (stderr, "If your implementation of OpenGL Version 1.0 has the right extensions,\n");
    fprintf (stderr, "you may be able to modify this program to make it run.\n");
    return 0;
}
#endif

    


显示列表:
    glGenLists(GLsizei range);  //产生若干个未使用的索引值,用作glNewList的第一个参数
    glNewList(GLuint list, GLenum mode);  //mode一般用GL_COMPILE,只编译,不执行,相反GL_COMPILE_AND_EXECUTE
    glEndList();
    glCallList(GLuint list); //调用显示列表
    创建显示列表时,只有表达式的值存储在显示列表中,如果数组中的值发生了变化,显示列表中的值不会发生变化。
    并不是所有的OpenGL函数都可以存储在显示列表中并执行,例如设置状态的函数和提取状态值的函数就无法存储在显示列表中,当在创建
显示列表时调用了这些函数时, 它们会立即执行。
    显示列表可嵌套.
执行多个显示列表:
    可以连续执行多个显示列表,但必须把显示列表索引放在一个数组中并调用glCallLists(),glListBase(GLuint base)指定初始偏移量,
它将与glCallLists()中的显示列表索引相加,显示列表基址对glCallList()和glNewList()没有效果。
    glCallLists(GLsizei n, GLenum type, const GLvoid *lists);



OpenGL部分知识小总结