OpenGL学习笔记(三):颜色与光照

作者:yurunsun@gmail.com 新浪微博@孙雨润 新浪博客 CSDN博客

日期: 2013-6-13

本章内容:

  1. RGBA颜色模式
  2. 指定物体绘图颜色
  3. 平滑着色模式
  4. 定义光源、材料、光照模型属性
  5. 控制光源位置
  6. 颜色混合
  7. 抗锯齿

1. 颜色

  1. RGBA颜色模式

    硬件为R G B A成分保留一定数量的位平面。如果RGB的位数少而无法表达需要的颜色,可以使用抖动(GL_DITHER)实现:即使用两种颜色交替对一个像素着色。这一选项默认是打开的。

  2. RGBA下指定颜色

    void glColor4f(float r, float g, float b, float a);
    
  3. 指定着色模型

    用多种颜色绘制直线或填充多边形时可以使用glShadeModel()来指定着色模型。参数可以是GL_SMOOTHGL_FLAT

    FLAT模式先整个图元的颜色就是它任何一个顶点的颜色,SMOOTH模式下每个顶点单独处理,使用Gouraud算法均匀插值。

2. 光照

2.1 隐藏面消除

GL_FILL填充的实心物体应该遮挡后面的物体,因此需要开启GL_DEPTH_TEST使得OpenGL能够进行深度测试。

2.2 四种光

  1. 环境光(ambient):在环境中进行了充分的散射,无法分辨方向的光
  2. 散射光(diffuse):来自某个方向,如果从正面照射表面会看起来显得更亮一些。当撞击表面时会均匀向所有方向发散
  3. 镜面光(specular):来自特定方向,并倾向于从表面向某个特定的方向反射
  4. 发射光(emissive):模拟源自某个物体的光。表面的发射颜色可以增加物体强度,但是不受任何光源影响,也不作为额外光照

2.3 材料颜色

材料也有上述123的属性,但是是表示对rgb分量的反射比例。最终效果是分量与光照值相乘的结果。

float green[] = {0.0f, 1.0f, 0.0f, 1.0f};
glMaterial4f(GL_FRONT, GL_AMBIENT, green);

2.4 为顶点定义法线

物体的法线决定了相对光源的方向,OpenGL根据法线计算这个顶点从每个光源接收的光线数量。表面法线必须是单位长度,还必须保证对物体进行的模视变换没有对法线进行缩放、最终法线仍然保持单位长度。参见:

GL_NORMALIZE
GL_RESCALE_NORMALE

2.5 创建光源

OpenGL至少支持8个光源:

GL_LIGHT0, ... GL_LIGHT7    

使用glLight来设置位置、方向、四种光的颜色、聚光灯、消减等光源参数:

GL_AMBIENT (0.0, 0.0, 0.0, 1.0)
GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) 
GL_SPECULAR (1.0, 1.0, 1.0, 1.0)
GL_POSITION (0.0, 0.0, 1.0, 0.0) 
GL_SPOT_DIRECTION (0.0, 0.0,1.0) 
GL_SPOT_EXPONENT 0.0 
GL_SPOT_CUTOFF 180.0 
GL_CONSTANT_ATTENUATION 1.0
GL_LINEAR_ATTENUATION 0.0 
GL_QUADRATIC_ATTENUATION 0.0 

2.6 光照模型

void glLightModelf(GLenum pname, TYPE param);

GL_LIGHT_MODEL_AMBIENT (0.2, 0.2, 0.2, 1.0) // 整个场景的环境光RGBA
GL_LIGHT_MODEL_LOCAL_VIEWER 0.0 or GL_FALSE // 局部观察点还是无限远处观察点
GL_LIGHT_MODEL_TWO_SIDE 0.0 or GL_FALSE     // 单面光照还是双面光照
GL_LIGHT_MODEL_COLOR_CONTROL GL_SINGLE_COLOR // 镜面颜色计算是否从环境和散射颜色中分离

3. alpha值混合

glEnable(GL_BLEND);

3.1 src因子与dst因子

首先需要指定如何计算src和dst混合因子,这两个因子都是RGBA四元组,分别与src颜色和dst颜色的RGBA相乘;然后src与dst的对应成分再进行组合。例如

混合因子:

(Sr, Sg, Sb, Sa) 与 (Dr, Dg, Db,Da)

混合结果:

(RsSr+RdDr, GsSg+GdDg, BsSb+BdDb, AsSa+AdDa)

使用下面函数来设置因子

void glBlendFunc(GLenum srcfactor, GLenum destfactor);

3.2 混合算术组合方式

void glBlendEquation(GLenummode);

GL_FUNC_ADD                 CsS + CdD
GL_FUNC_SUBTRACT            CsS - CdD
GL_FUNC_REVERSE_SUBTRACT    CdD - CsS
GL_MIN                      min(CsS, CdD)
GL_MAX                      max(CsS, CdD)
GL_LOGIC_OP                 CS op CD

4. 抗锯齿

void glHint(GLenum target, GLenum hint);

hint的取值为:

GL_FASTEST
GL_NICEST
GL_DONT_CARE

target取值为:

GL_POINT_SMOOTH_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT   //点线多边形
GL_FOG_HINT                                                         // 雾计算
GL_PERSPECTIVE_CORRECTION_HINT                                      // 颜色和纹理坐标插值质量
GL_GENERATE_MIPMAP_HINT                                             
GL_TEXTURE_COMPRESSION_HINT
GL_FRAGMENT_SHADER_DERIVATIVE_HINT

5. 雾

雾是通用的术语,描述类似大气的效果,用于模拟模糊、薄雾、烟、污染等。

glEnable(GL_FOG);
glFogi(GL_FOG_MODE, GL_EXP);
glFogfv(GL_FOG_COLOR, fogColorArr);
glFogf(GL_FOG_DENSITY, o.35);
glFogf(GL_FOG_START, 1.0);
glFogf(GL_FOG_END, 5.0);

6. 点参数

有时候可能需要渲染球体,但又不想使用效率较低的多边形近似模拟,例如对飞行模拟器中的路灯建模,或者雨滴。这些都可以渲染成点图元,并对点进行修改使其具有适当的大小和亮度。可以使用glPointSize()和glEnable(GLPOINTSMOOTH)创建较大的圆点,并使用雾来提示距离。但glPointSize()不能出现在glBegin()/glEnd()`之间,因此难以改变点的大小。

点参数能够根据点和观察点的距离,对点的大小和亮度进行衰减:

void glPointParameterf(GLenumpname, GLfloat param);
void glPointParameterfv(GLenumpname, const float* param);

GL_POINT_DISTANCE_ATTENUATION           // 衰减系数
GL_POINT_SIZE_MIN or GL_POINT_SIZE_MAX  // 点大小的绝对限制
GL_POINT_FADE_THRESHOLD_SIZE            // 
GL_POINT_SPRITE_COORD_ORIGIN            // 迭代纹理的起始点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
opengl 期末复习资料 第一、二章: 1、 OpenGL中能渲染的基本元素是什么?GLU 可以渲染哪些基本元素? 第三章 2、 用框图说明OpenGL的渲染流程,并简要说明每个坐标系。 第四、五章 3、 写出OpenGL中局部光照的方程,要包含的系数有光源参数、材料参数、聚光灯的参数、衰减参数等,方程要表示是多个光源的。 4、 分析程序并计算 请看下面的一段程序,并计算三个顶点○1、○2和○3处的光照颜色值。 void init(void) { GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); //glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); //glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); } void display(void) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBegin(GL_TRIANGLES); glNormal3f(..); ○1glVertex3f(1.0, 0.0, 0.0); ○2glVertex3f(0.0, 1.0, 0.0); ○3glVertex3f(0.0, 0.0, 1.0); glEnd(); glFlush (); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) 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(); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } 第9章 在OpenGL中,使用纹理的步骤是什么?纹理坐标和纹理都可以通过程序计算出来,自动生成纹理的原理是什么? 第10章 帧缓存有几种,什么叫片元,片元的测试和操作有哪些? 明白stencilbuffer的使用。 用stencilbuffer编程实现一个功能。 5、 采用GPU编程,请说明Vertex Shader 和 Fragment Shader 的输入输出坐标系是什么? 输入输出的主要参数是什么? 如何实现Multi-Pass 渲染? 6、 在一个坐标系W中,光源的位置为 (0, 0, 200, 1.0),设模型为一个以(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)为三个点的三角形,另一个模型是以(0, 0, 10)为中心,长度为2的一个正方体,如何实现该正方体在三角形平面上的阴影?如何使用OpenGL函数来实现?要求在照相机改变时,该程序应该仍然有效。 7、 如何实现纹理的反走样?说明其原理。 8、 写出场景的反走样算法,并说明其原理。 9、 如何实现采用立方体映射实现的环境映射,写出立方体映射的生成算法和把其作为环境映射时显示的程序。 10、 请列举出3种以上的三维模型常见的表示格式,已知一个立方体环境映射对应的六个面上的图片,分别假定为X_POSITVIE_PIC, X_NEGATIVE_PIC, Y_POSITIVE_PIC, Y_NEGATIVE_PIC, Z_POSITIVE_PIC, Z_NEGATIVE_PIC,请用OBJ格式表示一个长度为1的立方体,并把每个面分别贴上给定的六个图片。 11、 分析下面的程序并计算 在下面的例子中,计算对应○1○2○3○4四个顶点所对应的四边形上的一个点(-1.0, 0.5, 0.0)对应的纹理坐标是多少?按照最近邻域滤波方法,该点对应的颜色是什么? /* Create checkerboard texture */ #define checkImageWidth 64 #define checkImageHeight 64 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; #ifdef GL_VERSION_1_1 static GLuint texName; #endif void makeCheckImage(void) { int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i&0x8)==0)^((j&0x8))==0))*255; checkImage[i][j][0] = (GLubyte) c; checkImage[i][j][1] = (GLubyte) c; checkImage[i][j][2] = (GLubyte) c; checkImage[i][j][3] = (GLubyte) 255; } } } void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); makeCheckImage(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef GL_VERSION_1_1 glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #ifdef GL_VERSION_1_1 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); #else glTexImage2D(GL_TEXTURE_2D, 0, 4, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); #endif } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); #ifdef GL_VERSION_1_1 glBindTexture(GL_TEXTURE_2D, texName); #endif glBegin(GL_QUADS); ○1glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); ○2glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 1.0, 0.0); ○3glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 0.0); ○4glTexCoord2f(1.0, 0.0); glVertex3f(0.0, -1.0, 0.0); glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(2.41421, 1.0, -1.41421); glTexCoord2f(1.0, 0.0); glVertex3f(2.41421, -1.0, -1.41421); glEnd(); glFlush(); glDisable(GL_TEXTURE_2D); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -3.6); } void keyboard (unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; default: break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; } Deferred shading 原理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值