OpenGL从1.0开始--光照和表面绘制函数
来源:互联网 发布:wap淘宝流量是什么意思 编辑:程序博客网 时间:2024/05/29 11:40
对场景的对象进行透视投影,然后再可见面上产生自然光照效果,可以实现场景的真实感显示。多说无益,看一个示例是最直接的方法(示例代码来源于http://blog.csdn.net/timidsmile/article/details/7017197)。
#include <gl/glut.h> #define WIDTH 400 #define HEIGHT 400 static GLfloat angle = 0.0f;void myDisplay(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.0f, 1.0f, 1.0f, 20.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 5.0, -10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // 定义太阳光源,它是一种白色的光源 { GLfloat sun_light_position[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat sun_light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat sun_light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat sun_light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); //指定第0号光源的位置 glLightfv(GL_LIGHT0, GL_AMBIENT, sun_light_ambient); //GL_AMBIENT表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度(颜色) glLightfv(GL_LIGHT0, GL_DIFFUSE, sun_light_diffuse); //漫反射后~~ glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular);//镜面反射后~~~ glEnable(GL_LIGHT0); //使用第0号光照 glEnable(GL_LIGHTING); //在后面的渲染中使用光照 glEnable(GL_DEPTH_TEST); //这句是启用深度测试,这样,在后面的物体会被挡着,例如房子后面有棵树,如果不启用深度测试,你先画了房子再画树,树会覆盖房子的;但启用深度测试后无论你怎么画,树一定在房子后面(被房子挡着) } // 定义太阳的材质并绘制太阳 { GLfloat sun_mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat sun_mat_diffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat sun_mat_specular[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat sun_mat_emission[] = { 0.5f, 0.0f, 0.0f, 1.0f }; GLfloat sun_mat_shininess = 0.0f; glMaterialfv(GL_FRONT, GL_AMBIENT, sun_mat_ambient); //定义材料的前面采用 "多次反射" glMaterialfv(GL_FRONT, GL_DIFFUSE, sun_mat_diffuse); //材料的前面为 漫反射 glMaterialfv(GL_FRONT, GL_SPECULAR, sun_mat_specular); //定义材料的前面为 镜面反射 glMaterialfv(GL_FRONT, GL_EMISSION, sun_mat_emission); //定义材料的前面为 镜面指数 glMaterialf(GL_FRONT, GL_SHININESS, sun_mat_shininess); //材料的前面 采用 的颜色 glutSolidSphere(2.0, 40, 32); } // 定义地球的材质并绘制地球 { GLfloat earth_mat_ambient[] = { 0.0f, 0.0f, 0.5f, 1.0f }; GLfloat earth_mat_diffuse[] = { 0.0f, 0.0f, 0.5f, 1.0f }; GLfloat earth_mat_specular[] = { 0.0f, 0.0f, 1.0f, 1.0f }; GLfloat earth_mat_emission[] = { 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat earth_mat_shininess = 30.0f; glMaterialfv(GL_FRONT, GL_AMBIENT, earth_mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, earth_mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, earth_mat_specular); glMaterialfv(GL_FRONT, GL_EMISSION, earth_mat_emission); glMaterialf(GL_FRONT, GL_SHININESS, earth_mat_shininess); glRotatef(angle, 0.0f, -1.0f, 0.0f); glTranslatef(5.0f, 0.0f, 0.0f); //如果使用glutSolidSphere函数来绘制球体,则该函数会自动的指定这些法线向量, //不必再手工指出。如果是自己指定若干的顶点来绘制一个球体,则需要自己指定法线向量。 glutSolidSphere(2.0, 40, 32); } glutSwapBuffers(); //交换缓冲区 }void myIdle(void){ angle += 1.0f; if (angle >= 360.0f) angle = 0.0f; myDisplay();}int main(int argc, char* argv[]){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutInitWindowPosition(200, 200); glutInitWindowSize(WIDTH, HEIGHT); glutCreateWindow("OpenGL光照演示"); glutDisplayFunc(&myDisplay); glutIdleFunc(&myIdle); glutMainLoop(); return 0;}
这个示例模拟的是地球绕太阳旋转的场景,红色的太阳发射出白光照亮了蓝色的地球。我们来详解里面的函数。
太阳是一种点光源。我们使用glLightfv设置光源的各种属性,包括光源位置GL_POSITION,光源颜色(环境光GL_AMBIENT, 漫反射光GL_DIFFUSE, 镜面反射光GL_SPECULAR),辐射强度衰减系数等。
glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position);//第一个参数为光源名,第二个参数指定属性,第三个参数为属性值
除了点光源外我们还可以设置方向光源(投射光源),即模拟台灯光照,中心光线最强,边缘光线强度最低。
glLightfv(GL_LIGHT0, GL_SPOT_POSITION, sun_light_position);//圆锥轴方向glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, 30.0);//光源到圆锥轴的夹角被限制在30度的范围内glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, 2.5);//从中心到边缘的衰减系数
可在全局级指定若干个OpenGL光照参数。
glLightModel*(paramName,paramValve);//两个参数分别指定参数名和参数值
光照效果除了和光源颜色有关外,也和对象表面反射特性密不可分。表面的反射系数和其他可选特性用下列函数来设定:
glMaterialf(surfFace,surfProperty,propertyValue);
surfFace赋予符号常量GL_FRONT,GL_BACK,GL_FRONT_AND_BACK之一,指定需要描述的面,surfProperty指定属性名(散射颜色gL_EMISSION、GL_SHININESS等)。
在应用光源前,需要激活光源并点亮光源。
glEnable(lightName);//点亮光源glEnable(GL_LIGHTING);//激活光源
我们还可以使用雾气效果来模拟真实环境。
glEnable(GL_FOG);//激活雾气glFogf(atmoParameter,paramValue);//设置雾气属性,例如颜色GL_FOG_COLOR,雾气衰减GL_FOG_DENSITY等等
为了更好地处理图元表面的明暗变化,可以指定相应的表面绘制方法来进行插值处理。
glShadeModel(surfRenderingMethod);
参数指定表面绘制方法,如果是GL_FLAT指定常数强度表面绘制方法,即不进行任何处理。GL_SMOOTH指定Gouraud表面绘制方法,在这种模式下,需要对每个平面指定一个法向量。
glBegin(GL_TRIANGLES):glNormal3fv(normalVector1);glVertex3fv(vertex1);glNormal3fv(normalVector2);glVertex3fv(vertex2);glNormal3fv(normalVector3);glVertex3fv(vertex3);
我们可以将法向量单位化来加速OpenGL效率
glEnable(GL_NORMALIZE);
和顶点数组。颜色数组一样,我们也可以指定一个法向量数组:
glEnableClientState(GL_NORMAL_ARRAY);glNormalPointer(dataType,offset,normalArray);
- OpenGL从1.0开始--光照和表面绘制函数
- OpenGL从1.0开始--纹理与表面细节
- OpenGL从1.0开始--绘制常用统计图
- OpenGL从1.0开始--绘制规则多面体
- OpenGL从1.0开始--绘制二次曲面
- opengl--重新开始--05 颜色和光照
- OpenGL从1.0开始--交互式输入设备函数
- OpenGL光照和材质
- OpenGL 光照和材质
- android openGL ES2 一切从绘制纹理开始
- android openGL ES2 一切从绘制纹理开始
- OpenGL从1.0开始--点和线的属性
- OpenGL分格化和二次方程表面
- OpenGL材质和光照(转)
- OpenGL中的光照和颜色
- OpenGL从1.0开始--输出图元
- OpenGL从1.0开始--曲线图形
- OpenGL从1.0开始--颜色调和
- Android Studio导入Eclipse项目的两种方法
- js正则表达式
- LRU算法
- Java程序设计学习知识点总结
- 382. 三角形计数 [LintCode]
- OpenGL从1.0开始--光照和表面绘制函数
- 单例模式的升级之路
- Windows安装Python虚拟环境
- Qt移植到ARM Linux教程
- PHP GD2库的简单使用
- 算法时间复杂度和空间复杂度
- RBAC从零开始--登录及登录拦截器
- webSocket初认识和使用
- hive的内置函数