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