OpenGL中的光照系列之二[光照计算]

  • 光照设置

在OpenGL中当我们需要使用光照时,我们需要做如下的设置:

  1. 开启场景中的光照计算
  2. 设置场景中光源的参数
  3. 开启设置好的光源

下面我们就依次进行:

  • 开启和关闭光照计算

在OpenGL中使用glEnable和glDisable来开启和关闭光照计算:

// 开启光照计算
glEnable(GL_LIGHTING);

//关闭光照计算
glDisable(GL_LIGHTING)
  • 设置光源参数

OpenGL的实现默认最少支持8个光源,这些光源的编号从0-7,依次是GL_LIGHT0、GL_LIGHT1 .... GL_LIGHT7,当我们使用是可以调用glLight来设置它们的参数,具体参数包括:

  • GL_AMBIENT

设置光源中的环境光成分,调用如下:

//设置0号光源的环境光为
float ambient[] = {0.4, 0.4, 0.4, 1.0}
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient)
散射光默认的取值是(0, 0, 0, 1)
  • GL_DIFFUSE

设置光源中的散射光成分,默认的取值 GL_LIGHT0是(1,1,1,1), 其他光源的取值是(0,0,0,1),调用方式:

//设置0号光源的环境光为
float diffuse[] = {0.4, 0.4, 0.4, 1.0}
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse)
  • GL_SPECULAR

设置光源中的平行光成分,默认的取值与GL_DIFFUSE中一样,GL_LIGHT0默认是(1,1,1,1),其他光源是(0,0,0,1)

  • GL_POSITION

设置光源的位置,GL_POSITON中指定的位置在调用glLight之后会通过当前的模型视图矩阵转换到相机坐标系中,GL_POSITION中的位置是一个齐次坐标,最后一个参数w如果为0,代表该光源是一个平行光,平行光中衰减参数是无效的。初始OpenGL中的光源位置在(0,0,1,0),也就是该光源是一个平行光,并且方向指向Z轴负方向。

  • GL_SPOT_DIRECTION

这个参数和以下两个参数都是用来设置聚光灯效果的光源的,GL_SPOT_DIRECTION简单来说就是设置聚光灯的方向,当聚光灯的开口角度不是360度的时候(类似于点光源),设置GL_SPOT_DIRECTION是有效的(也就是当GL_SPOT_CUTOFF是180度的时候设置GL_SPOT_DIRECTION并没有任何作用),默认的GL_SPOT_DIRECTION的取值是z轴负方向,也就是(0, 0, -1),在指定GL_SPORT_DIRECTION之后它会经过模型视图矩阵的变化变化到相机坐标系中。

  • GL_SPOT_EXPONENT

这个参数主要用来设置聚光灯的光线集中度,聚光灯的光的强度在光锥中心最高,越靠近边缘光的强度就越弱,这个参数设置的越大,聚光灯的聚光效果越强,这个参数的初始取值是0,它的取值范围限定在【0,128】

  • GL_SPOT_CUTOFF

这个参数主要用来设置聚光灯的辐射范围,默认值是180(类似与点光源),可以选择的取值范围是【0,90】以及180这个特殊值,可以参考下图:

OpenGL中的光照系列之二[光照计算]_第1张图片

  • GL_CONSTANT_ATTENUATION  GL_LINEAR_ATTENUATION  GL_QUADRATIC_ATTENUATION

这三个参数主要用来设置光的衰减参数,分别是常量衰减部分+线性部分+二次部分,具体衰减公式可以继续阅读下文。默认的取值是(1,0,0),也就是没有衰减。需要注意的是:这三个参数只对有位置的光源有用,对平行光源来说没有意义。

  • 光照的应用示例

下文中主要列举了光源通过不同的参数设置所显现的不同效果:

  • 1.  仅使用环境光,默认的材质,开启光照计算后的效果:

    glClearColor(0, 0, 0, 1)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    ambient = [0.8, 0.8, 0.8]
    glLightfv(GL_LIGHT1, GL_AMBIENT, ambient)
    glEnable(GL_LIGHT1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glTranslatef(0, 0, -10)
    glRotatef(xRot, 1, 0, 0)
    glRotatef(yRot, 0, 1, 0)
    glutSolidSphere(2, 32, 18)
    glutSwapBuffers()
运行效果:

OpenGL中的光照系列之二[光照计算]_第2张图片

  • 2. 仅使用散射光,默认材质的效果

    glClearColor(0, 0, 0, 1)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    diffuse = [0.8, 0.8, 0.8]
    glLightfv(GL_LIGHT0, GL_AMBIENT, diffuse)
    glEnable(GL_LIGHT0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glTranslatef(0, 0, -10)
    glRotatef(xRot, 1, 0, 0)
    glRotatef(yRot, 0, 1, 0)
    glutSolidSphere(2, 32, 18)
    glutSwapBuffers()
运行效果:

OpenGL中的光照系列之二[光照计算]_第3张图片

  • 3. 仅包含平行光,代码如下:

    glClearColor(0, 0, 0, 1)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    specular = [0.8, 0.8, 0.8]
    glLightfv(GL_LIGHT1, GL_SPECULAR, specular)
    glEnable(GL_LIGHT1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glTranslatef(0, 0, -10)
    glRotatef(xRot, 1, 0, 0)
    glRotatef(yRot, 0, 1, 0)
    glutSolidSphere(2, 32, 18)
    glutSwapBuffers()
运行效果:什么场景都看不见,主要是因为平行光依赖于视点与光线之间的角度关系
  • 4. 修改光源的位置,当我们修改光源的位置时,以2中的示例为例,修改光源的位置:

    glClearColor(0, 0, 0, 1)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    diffuse = [0.8, 0.8, 0.8]
    position = [-1, 0, 0, 0]
    glLightfv(GL_LIGHT0, GL_POSITION, position)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse)
    glEnable(GL_LIGHT0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glTranslatef(0, 0, -10)
    glRotatef(xRot, 1, 0, 0)
    glRotatef(yRot, 0, 1, 0)
    glutSolidSphere(2, 32, 18)
    glutSwapBuffers()
运行效果:

OpenGL中的光照系列之二[光照计算]_第4张图片

可以看到光源的位置确实由正前方转到左方了

  • 5. 修改平行光源为点光源

将4中的平行光修改为点光源

    glClearColor(0, 0, 0, 1)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    diffuse = [0.8, 0.8, 0.8]
    position = [-1, 0, 0, 1]
    glLightfv(GL_LIGHT0, GL_POSITION, position)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse)
    glEnable(GL_LIGHT0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glTranslatef(0, 0, -10)
    glRotatef(xRot, 1, 0, 0)
    glRotatef(yRot, 0, 1, 0)
    glutSolidSphere(2, 32, 18)
    glutSwapBuffers()
  • 6. 使用聚光源

我们将5中的点光源设置为聚光灯的模式,让它限定在一定范围内,代码如下:

    glClearColor(0, 0, 0, 1)
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    diffuse = [0.8, 0.8, 0.8]
    position = [0, 0, -1, 1]
    glLightfv(GL_LIGHT0, GL_POSITION, position)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse)
    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 20.0)
    glEnable(GL_LIGHT0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glTranslatef(0, 0, -10)
    glRotatef(xRot, 1, 0, 0)
    glRotatef(yRot, 0, 1, 0)
    glutSolidSphere(2, 32, 18)
    glutSwapBuffers()

以上就是光源的使用,下文接着讲述材质部分的内容

你可能感兴趣的:(OpenGL,Basic)