计算机图形学——OpenGL之光照

    xiaoxiao2021-04-14  41

    计算机图形学——OpenGL之光照

    1、光照系统

           光照系统可以分为三部分:

    光源就是光的来源,可以是太阳或者电灯等。

    材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。

    光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。

           相关概念:

    镜面反射:光线入射理想的光滑平面,反射后的光线是很规则的 漫反射:光线入射粗糙的、不光滑的平面,反射后的光线是杂乱的

    2、设置光源

              在OpenGL中,仅仅支持有限数量的光源。 使用GL_LIGHT0表示第0号光源,GL_LIGHT1表示第1号光源,依次类推。 OpenGL至多会支持8个光源,即GL_LIGHT0到GL_LIGHT7。 使用glEnable函数可以开启它们。例如,glEnable(GL_LIGHT0);可以开启第0号光源。 使用glDisable函数则可以关闭光源。

              每一个光源都可以设置其属性,这一动作是通过glLight*函数完成的。glLight*函数具有三个参数,第一个参数指明是设置哪一个光源的属性,第二个参数指明是设置该光源的哪一个属性,第三个参数则是指明把该属性值设置成多少。光源的属性:

    GL_AMBIENT表示该光源所发出的光,经过非常多次的反射后,最终遗留在整个光照环境中的强度

    GL_DIFFUSE表示该光源所发出的光,照射到粗糙表面时经过漫反射,所得到的光的强度

    GL_SPECULAR表示该光源所发出的光,照射到光滑表面时经过镜面反射,所得到的光的强度。             其中每个属性由四个值表示,分别代表了颜色的R, G, B, A值。

    GL_POSITION属性。表示光源所在的位置。由四个值(X, Y, Z, W)表示。如果第四个值W为零,则表示该光源位于无限远处,前三个值表示了它所在的方向。这种光源称为方向性光源,通常,太阳可以近似的被认为是方向性光源。

    如果第四个值W不为零,则X/W, Y/W, Z/W表示了光源的位置。这种光源称为位置性光源。对于位置性光源,设置其位置与设置多边形顶点的方式相似,各种矩阵变换函数例如:glTranslate*、glRotate*等在这里也同样有效。

    方向性光源在计算时比位置性光源快了不少,因此,在视觉效果允许的情况下,应该尽可能的使用方向性光源。

    GL_SPOT_DIRECTION、GL_SPOT_EXPONENT、GL_SPOT_CUTOFF属性。表示将光源作为聚光灯使用(这些属性只对位置性光源有效)。

    GL_CONSTANT_ATTENUATION、GL_LINEAR_ATTENUATION、GL_QUADRATIC_ATTENUATION属性。这三个属性表示了光源所发出的光线的直线传播特性(这些属性只对位置性光源有效)

    3、设置材质

             光源是通过glLight*函数来设置的,而材质则是通过glMaterial*函数来设置的。glMaterial*函数有三个参数。第一个参数表示指定哪一面的属性。可以是GL_FRONT、GL_BACK或者GL_FRONT_AND_BACK。分别表示设置“正面”“背面”的材质,或者两面同时设置

    下面分别说明glMaterial*函数可以指定的材质属性。

    GL_AMBIENT表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度。

    GL_DIFFUSE表示光线照射到该材质上,经过漫反射后形成的光线强度。

    GL_SPECULAR表示光线照射到该材质上,经过镜面反射后形成的光线强度。

    通常,GL_AMBIENT和GL_DIFFUSE都取相同的值,可以达到比较真实的效果。

    使用GL_AMBIENT_AND_DIFFUSE可以同时设置GL_AMBIENT和GL_DIFFUSE属性。

    GL_SHININESS属性。该属性只有一个值,称为“镜面指数”,取值范围是0到128。

    该值越小,表示材质越粗糙,点光源发射的光线照射到上面,也可以产生较大的亮点。该值越大,表示材质越类似于镜面,光源照射到上面后,产生较小的亮点。

    GL_EMISSION属性。该属性由四个值组成,表示一种颜色。OpenGL认为该材质本身就微微的向外发射光线,以至于眼睛感觉到它有这样的颜色,但这光线又比较微弱,以至于不会影响到其它物体的颜色。

    4、光照模型

            在OpenGL中,光照模型包括四个部分的内容:

    全局环境光线:那些充分散射,无法分清究竟来自哪个光源的光线的强度 观察点位置是在较近位置还是在无限远处 物体正面与背面是否分别计算光照 镜面颜色(即GL_SPECULAR属性所指定的颜色)的计算是否从其它光照计算中分离出来,并在纹理操作以后在进行应用

            可以通过函数glLightModel*来进行设置。该函数有两个参数,第一个表示要设置的项目,第二个参数表示要设置成的值。

    GL_LIGHT_MODEL_AMBIENT表示全局环境光线强度,由四个值组成。

    GL_LIGHT_MODEL_LOCAL_VIEWER表示是否在近处观看,若是则设置为GL_TRUE,否则(即在无限远处观看)设置为GL_FALSE。

    GL_LIGHT_MODEL_COLOR_CONTROL表示颜色计算方式。

    GL_LIGHT_MODEL_TWO_SIDE表示是否执行双面光照计算。如果设置为GL_TRUE,则OpenGL不仅将根据法线向量计算正面的光照,也会将法线向量反转并计算背面的光照。

           OpenGL默认是关闭光照处理的。要打开光照处理功能,使用下面的语句:

    glEnable(GL_LIGHTING);

           同样要关闭光照处理功能,使用glDisable(GL_LIGHTING)。

    5、实例演示:

    源码: #include <GL/glut.h> void GL_display(); void GL_reshape(GLsizei w, GLsizei h); void GL_myInitial(); void main(void) { glutCreateWindow("Gouraud光照模型"); GL_myInitial(); glutDisplayFunc(GL_display); glutReshapeFunc(GL_reshape); glutMainLoop(); } void GL_myInitial() { GLfloat light_position[] = {1.0,1.0,1.0,0.0}; 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 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_AMBIENT , light_ambient ); glLightfv(GL_LIGHT0, GL_DIFFUSE , light_diffuse ); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); } void GL_display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSolidTeapot(0.5); glFlush(); } void GL_reshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glOrtho (-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }
    转载请注明原文地址: https://ju.6miu.com/read-669667.html

    最新回复(0)