OpenGL中启用光照前的准备——指定法线

我们在使用光源时,除了强度和颜色之外,还需要指定光源的位置和方向,并且这些光源的位置和方向将会极大地影响场景的外观。

OpenGL至少支持8种独立的光源。当我们指定一个光源时,便要告诉OpenGL这个光源的位置以及它的照射方向。光源经常向四周照射,但也可以向一个方向照射。无论在哪种情况下,对于我们所绘制的任何物体,来自任何光源的光线(除了纯粹的环境光源之外)都将根据一个角度撞击组成这个物体的多边形的表面。为了计算围绕多边形表面的着色效果,OpenGL必须能够计算光线与多边形表面之间的角度。

设想一下,一个多边形被一束来自某个光源的光线所照射,当这束光线照射到多边形的表面时,它与平面会形成一个角度(A);然后,光线按照一个角度(B)向观察者反射(观察者不一定能够看到它)。通过这些角度,再加上我们之前所讨论的光照参数和材料属性,就可以计算这个位置的外观颜色了,如图所示

由于OpenGL根据每个顶点计算外观颜色,那么当这每个顶点从某个角度被一束光线所照射时,我们该如何计算顶点和光线之间的角度呢?当然,我们无法用几何的方法找到3D空间中一个点和一条直线的角度,因为它存在无穷的可能性。为了解决这个问题,我们必须将每个顶点与一些信息相关联,这就是我们接下来要说的,表示每个顶点垂直向上的向量——法线。

表面法线

在一个假想的平面(或多边形)上,一条垂直向上的向量称为法线向量。实际上,它就是一条指向某个方向的直线(向量),它与多边形的表面呈90度角。

指定法线

在OpenGL中,下面这段代码指定了一条法线向量:

glBegin(GL_TRIANGLES);

glNormal3f(0.0f, -1.0f, 0.0f);

glVertex3f(0.0f, 0.0f, 60.0f);

glVertex3f(-15.0f, 0.0f, 30.0f);

glVertex3f(15.0f, 0.0f, 30.0f);

glEnd();

glNormal3f函数接受3个表示坐标的值(X,Y,Z),它指定了一条垂直于这个三角形表面的法线向量。在这里,所有三个顶点的法线具有相同的方向,都是沿Y轴的负方向向下。这是一个简单的示例,因为这个三角形平平地躺在X-Z平面上。

当我们开始绘图时,为每个顶点或多边形指定一条法线的任务几乎是不可能的,尤其是在只有很少一部分表面是平行于三个主平面的情况下。当然,我们会有解决的办法,可以通过调用一个glTools函数库中的方法,来生成我们所需要的法线。

生成法线

我们可以通过取多边形平面上的3个点来计算它的法线向量。如图所示,平面上的3个点P1、P2、P3,我们可以定义两个向量,从P1至p2的向量V1以及从P1至P3的向量V2。从数学的角度而言,三维空间中的两个向量定义了一个平面。我们对这两个向量求叉积(V1×V2),其结果所产生的向量与这个平面垂直,也就是我们所需的法线向量,如图中的向量V3所示:

glTool函数库包含了一个函数,专门用于根据一个多边形上的3个点计算一条法线向量:

void m3dFindNormal(M3DVector3f vNormal,

const M3DVector3f vP1,

const M3DVector3f vP2,

const M3DVector3f vP3);

该方法的第一个参数用于存储求得的法线向量,还要另外向它传递3个向量,表示取自多边形或三角形上的点(以逆时针环绕方向指定)。注意,该方法返回的法线向量并不一定是单位长度的。

单位法线

所谓单位法线,就是长度为1的法线。将法线转换为单位法线的过程称为法线的规范化。在OpenGL的实现中,对于光照计算,所有的法线向量都必须先进行规范化,然后再参与计算。

    本文出自杜晓萌的博客,请勿用于任何商业用途,转载请保持完整性并标明出处:                    http://blog.csdn.net/haohan_meng

时间: 2024-11-08 20:18:58

OpenGL中启用光照前的准备——指定法线的相关文章

OpenGL中设置光照的镜面反射效果

在上一篇笔记中,我们记述了光线的方向与多边形表面的角度计算关系,除此之外,我们还有光源的位置需要指定.我们在ChangeSize函数的内部指定光源的位置: // 指定光源的位置 GLfloat lightPos[] = {-50.0f, 50.0f, 100.0f, 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, lightPos); 在此,lightPos数组包含了光源的坐标位置.这个数组的最后一个值是1.0,表示指定的坐标是光源的位置:如果这个数组的最后一个

OpenGL中的光照与材料

在OpenGL光照模型中,除非一个物体自己会发光,否则它将受到3种不同类型的光的照射,这3种不同类型的光分别是:环境光(ambient).散射光(diffuse)和镜面光(specular).作为现实世界中光照的抽象,这3种类型的光允许我们模拟和控制光照在物体表面上所产生的效果. 环境光(ambient) 环境光并不来自任何特定的方向.由环境光所照射的物体在所有方向的表面都是均匀照亮的.在OpenGL中,这种光照类型实际上模拟了环境中源自所有光源的散光. 散射光(diffuse) OpenGL中

在OpenGL中给场景添加光照

为了在OpenGL中使用光照计算,我们需要调用glEnable方法,并用GL_LIGHTING作为参数.这个调用告诉OpenGL在确定场景中每个顶点的颜色时使用光照参数和材料属性.当然,如果我们没有指定任何光照参数和材料属性,那么物体仍将会保持为黑暗的无光照状态. // 启用光照 glEnable(GL_LIGHTING); 一.设置环境光 OpenGL提供了一个全局光源,它只发射环境光.这种光源很有用,它可以照射没有被其它光源直接照射的物体的背面,并且如果场景看上去太暗,可以调节这种全局环境光

OpenGL学习(五) 光照与材质

OpenGL中的光照     环境光:在环境中进行了充分的散射,无法分辨其方向的光. 散射光:来自某个方向. 镜面光:来自一个特定的方向,并且倾向于从表面某个特定的方向反射. 除了以上三种光外,材料可能具有一种发射颜色,它模拟那些源自某个物体的光. 为了实现明暗效果,必须启用光照计算,而且每种光源也必须被启用.对于单个光源,我们可以这样做: glEnable(GL_LIGHTING); glEnable(GL_LIGHT0) 注:一旦光照被启用,glColor*()指定的颜色值将不再使用. 指定

Opengl场景中加光照包含几个步骤

http://zuoye.baidu.com/question/44e2a82d7ad5c0e1d33ddb9a40e0bf86.html  Opengl场景中加光照包含几个步骤,各个步骤实现用的函数是什么?这两个问题回答清楚就行了,不用说别的.粘贴的一律无视. 小白小菜0026 2014-10-10 优质解答下载作业帮App,拍照秒答 主要分三步:设置光源参数 .开启光照.设置法线信息. 1.设置光源参数.通过多次调用带有不同参数的glLightfv()函数来实现.一般会设置环境光(Ambie

OpenGL中的颜色混合功能(一)

我们知道,材料属性和光照参数可以极大地增加图形的逼真度,但除此之外,我们在对现实世界进行建模时,有许多效果是通过混合颜色的方式实现的.透明的物体,像是玻璃水杯,在它后面发射过来的光会与透明物体的颜色混合在一起.这种透明在OpenGL中的实现方式,是通过首先绘制背景物体,然后把前景物体(比如水杯)与颜色缓冲区中已经存在的颜色进行混合而实现的.在这一过程中,颜色的alpha值成分发挥了重要作用. 颜色的混合功能 在一般情况下,OpenGL在渲染时把颜色值存放在颜色缓冲区中,把每个片段(像素)的深度值

OpenGL中创建聚光灯的效果

现在,我们使用如下的数组来指定一个光源的位置: // 指定光源位置的数组 GLfloat lightPos[] = {0.0f, 0.0f, 75.0f, 1.0f}; // 设置光源0的位置 glLightfv(GL_LIGHT0,GL_POSITION,lightPos); lightPos数组的最后一个值在此为1.0,它表示光源的实际位置就在(X,Y,Z)所表示的位置.在默认情况下,光线从这个位置均匀地向四周发射.如果我们把lightPos数组的最后一个值设为0.0,可以使光源看上去像是来

GLSL 在OpenGL中向shader传递信息【转】

http://blog.csdn.net/hgl868/article/details/7872219 引言 一个OpenGL程序可以用多种方式和shader通信.注意这种通信是单向的,因为shader的输出只能是渲染到某些目标,比如颜色和深度缓存. OpenGL的部分状态可以被shader访问,因此程序改变OpenGL某些状态就可以与shader进行通信了.例如一个程序想把光的颜色传给shader,可以直接调用OpenGL接口,就像使用固定功能流水线时做的那样. 不过,使用OpenGL状态并不

OpenGL中的帧缓存

OpenGL中的帧缓存 在OpenGL窗口中, 左下角的像素为(0, 0). 一般而言, 像素(x, y)占据的矩形区域左下角为(x, y), 右上角为(x+1, y+1). 1. 缓存及其用途 [1]颜色缓存,  左前,右前,左后,右后和任意数量的辅助颜色缓存; [2]深度缓存 [3]模板缓存 [4]累积缓存 2.颜色缓存 1) 颜色缓存存储了颜色索引或RGB颜色数据, 还可能存储了alpha值. 2) 支持立体观察(stereoscopic viewing)的OpenGL实现有左颜色缓存和右