OPENGL的光影效果(转)
为什么3D作图常常能产生另人震惊的效果?因为利用3D作图,你可以生成一些 现实中难得实现的真实的感受。特别是一些特殊的光影效果。
其实光源前面已经讲的很全面了,只是缺少一些专门的例子。这里我们来稍微 加深一下认识,我们将在例子中看到一个地方的光源对不同物体发出不同的光
这在现实中是少见的吧?
1.双面光照:
void glLightModeli(LIGHT_MODEL_TWO_SIDE,GL_TRUE);
光照计算通常是对多边形进行的。一般设置光照的条件总是对正面的多边形,而不考虑背面,但是如果考虑一个物体被劈开,光源的个数又会影响可见性,那么有必要对多边形双面都进行计算,这就是上面函数的功能;取消这一功能只须把第三个参数改为GL_FALSE。
2.聚光源
定义聚光源的函数仍是利用glLightfv(),需要设定的参数包括:光源位置、光源发散半角和光源聚光方向。
具体实现可以看下面例子:
//
//sample.cpp
#include "glos.h"
#include
#include
#include "windows.h"
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);
void initlights(void)
{
//定义物体材质特性的数值
GLfloat mat_ambient[]={0.2,0.2,0.2,1.0};
GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};
GLfloat mat_specular[]={1.0,1.0,1.0,1.0};
GLfloat mat_shininess[]={80.0};
//定义第0个光源的属性(这是平行的环境光,没有聚光效果)
GLfloat light0_diffuse[]={0.0,0.0,1.0,1.0};
GLfloat light0_position[]={1.0,1.0,1.0,0.0};
//定义第一个光源的属性(聚光灯一)
GLfloat light1_ambient[]={0.2,0.2,0.2,1.0};
GLfloat light1_diffuse[]={1.0,0.0,0.0,1.0};
GLfloat light1_specular[]={1.0,0.6,0.6,1.0};
GLfloat light1_position[]={-3.0,-3.0,3.0,1.0};
GLfloat spot_direction[]={1.0,1.0,-1.0};
//定义第二个光源的属性(聚光灯二)
GLfloat light2_ambient[]={0.2,0.6,0.2,1.0};
GLfloat light2_diffuse[]={0.0,1.0,0.0,1.0};
GLfloat light2_specular[]={0.0,1.0,0.0,1.0};
GLfloat light2_position[]={-3.0,-3.0,3.0,1.0};
GLfloat spot2_direction[]={1.0,1.0,-1.0};
//!!!我们看到第一和第二个聚光源除了在颜色的定义上一个偏红,一个偏绿
//其他没有任何不同,所以如果象我们后面作的,对一个物体开启一个光源,对
//另一个物体开启另一个光源,就会产生一个点光源对不同物体发出不同光的效果
//将前面的属性定义加以应用
glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);
glLightfv(GL_LIGHT0,GL_POSITION,light0_position);
glLightfv(GL_LIGHT1,GL_AMBIENT,light1_ambient);
glLightfv(GL_LIGHT1,GL_DIFFUSE,light1_diffuse);
glLightfv(GL_LIGHT1,GL_SPECULAR,light1_specular);
glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
//定义聚光灯发散角
glLightf(GL_LIGHT1,GL_SPOT_CUTOFF,30.0);
//定义聚光灯发射方向的向量
glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION,spot_direction);
glLightfv(GL_LIGHT2,GL_AMBIENT,light2_ambient);
glLightfv(GL_LIGHT2,GL_DIFFUSE,light2_diffuse);
glLightfv(GL_LIGHT2,GL_SPECULAR,light2_specular);
glLightfv(GL_LIGHT2,GL_POSITION,light2_position);
glLightf(GL_LIGHT2,GL_SPOT_CUTOFF,30.0);
glLightfv(GL_LIGHT2,GL_SPOT_DIRECTION,spot2_direction);
glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
}
void myinit(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("sample1");
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
initlights();
// glShadeModel(GL_FLAT);
}
void CALLBACK reshape(GLsizei w,GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0);
else
glOrtho(-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void CALLBACK display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//首先标出聚光源一、二的位置(同一位置)
glPushMatrix();
glTranslated(-3.0,-3.0,3.0);
glDisable(GL_LIGHTING);
glColor3f(1.0,0.0,0.0);
auxWireCube(0.1);
glEnable(GL_LIGHTING);
glPopMatrix();
//关掉第二个光源,只启用第一个光源(红),绘制球体一
glPushMatrix();
glDisable(GL_LIGHT2);
glTranslated(0.0,2.0,0.0);
auxSolidSphere(2.0);
glPopMatrix();
//关掉第一个光源,只启用第二个光源(绿),绘制球体二
glPushMatrix();
glDisable(GL_LIGHT1);
glEnable(GL_LIGHT2);
glTranslated(0.0,-2.0,0.0);
auxSolidSphere(2.0);
glPopMatrix();
glFlush();
}
void main(void)
{
myinit();
auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
///
一个现实中难以见到的情景出现了。还不快试试?
结束光源之前,再给出一个光源移动的例子,其中用到了鼠标消息的响应,实现非常简单,以OPENGL的辅助库提供的方式调用一个CALLBACK函数即可,和以前讲的响应键盘输入的方法完全一样。
//
//sample.cpp
#include "glos.h"
#include
#include
#include "windows.h"
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);
//控制光源移动的变量
static int step=0;
//鼠标响应的CALLBACK函数
void CALLBACK movelight(AUX_EVENTREC *event)
{
step=(step+15)%360;
}
void initlights(void)
{
GLfloat mat_ambient[]={0.2,0.2,0.2,1.0};
GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};
GLfloat mat_specular[]={1.0,1.0,1.0,1.0};
GLfloat mat_shininess[]={80.0};
GLfloat light0_diffuse[]={0.0,0.0,1.0,1.0};
GLfloat light0_ambient[]={0.2,0.5,0.5,1.0};
glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);
glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient);
glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void myinit(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("sample1");
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
initlights();
// glShadeModel(GL_FLAT);
}
void CALLBACK reshape(GLsizei w,GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0);
else
glOrtho(-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void CALLBACK display(void)
{
GLfloat position[]={0.0,0.0,1.5,1.0};
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0,0.0,-5.0);
glPushMatrix();
//光源的位置只由旋转变量step决定,每按下鼠标左键一下,step的值便会改变
//导致光源位置的改变
glRotated((GLdouble)step,-1.0,1.0,1.0);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glTranslated(0.0,0.0,1.5);
glDisable(GL_LIGHTING);
glColor3f(1.0,1.0,0.0);
auxWireSphere(0.25);
glEnable(GL_LIGHTING);
glPopMatrix();
auxSolidTorus(0.5,2.5);
glPopMatrix();
glFlush();
}
void main(void)
{
myinit();
auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSEDOWN,movelight);
auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
/
在例子中,黄色的小球表示当前光源的位置,它的旋转导致了环状体表面受光照部分的光影的变化,每按下鼠标左键一下,光源就会作响应的旋转。
OPENGL的光影效果(转)相关推荐
- opengl地球贴纹理_一文看懂材质/纹理 Material, Texture, Shading, Shader 的区别
在计算机图形学和三维设计中,有几个容易混淆的概念.今天我们来一举拿下. 概念整理 可以这么总结: Material 是表现 Shading 的数据集.其他几个概念都是生成这一数据集的资源或者工具. 这 ...
- (转)OpenGL与DirectX 比较
Linux易用性差的一个重要表现是对游戏的支持性差.当然,linux也有为数众多的游戏,如纸牌,企鹅滑雪,泡泡龙,这些小游戏的可玩性绝对的windows的纸牌,扫雷之类高. 不过,我们所说的游戏是指& ...
- 图形世界分裂的两派——理清Direct3D和OpenGL的脉络
计算机三维图形是指将用数据描述的三维空间通过计算转换成二维图像并显示或打印出来的技术,API(Application Programming Interface)即"应用程序接口" ...
- 图形世界分裂的两派 理清Direct3D和OpenGL的脉络
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 计算机三 ...
- 比较DirectX和OpenGL的区别
OpenGL是个专业的3D程序接口,是一个功能强大,调用方便的底层3D图形库.OpenGL的前身是SGI公司为其图形工作站开发的IRIS GL.IRIS GL是一个工业标准的3D图形软件接口,功能虽然 ...
- OpenGL: 基础篇
本人水平有限,如有问题请以文章形式提出,大家可以讨论吗... [OPENGL怎么用] OPENGL编程类似C编程,实际接口就是C,所以熟悉C是必要的 一般编程可用到的函数库包括: OPENGL实用库: ...
- OpenGL与DirectX 比较
Linux易用性差的一个重要表现是对游戏的支持性差.当然,linux也有为数众多的游戏,如纸牌,企鹅滑雪,泡泡龙,这些小游戏的可玩性绝对的windows的纸牌,扫雷之类高. 不过,我们所说的游戏是指& ...
- 图形世界分裂的两派——理清D3D和OpenGL的脉络
转载自:http://www.iieeg.com/newscon.php?id=8388 计算机三维图形是指将用数据描述的三维空间通过计算转换成二维图像并显示或打印出来的技术,API(Applicat ...
- OpenCL,OpenGL编译
OpenCL,OpenGL编译 TVM已经支持多个硬件后端:CPU,GPU,移动设备等-添加了另一个后端:OpenGL / WebGL. OpenGL / WebGL能够在没有安装CUDA的环境中利用 ...
最新文章
- 为什么阿里巴巴要禁用Executors创建线程池?
- vivado中如何导入ise工程
- python在线工具-6 种 Python 数据可视化工具
- pandas内置绘图_使用Pandas内置功能探索数据集
- .NET Core ResponseCache【缓存篇(一)】
- 结构损伤检测与智能诊断 陈长征_宿迁厂房安全检测多少钱介绍说明
- hdu 1018 Big Number(n!求位数)
- weblogic调整多个服务启动顺序方法
- tomcat的url-pattern的源码分析
- 网页如何转pdf并实现下载
- golang GC机制
- 十五、Spring cloud 消息总线(Bus)
- 高级Java程序员技术栈
- 风控系统就该这么设计(万能通用),那是相当稳定
- 液晶显示屏的C语言编码,AT89C51单片机驱动液晶显示汉字C语言
- Zoho 企业邮箱不可用修复方案
- Java中excel的导出导入
- 角位移/倾角/角度传感器如何安装
- 篮球比赛计时计分系统
- AST抽象语法树的基本思想
热门文章
- 计算机组成原理logiasim入门:关于Logisim自定义封装
- 计算机基本框图英语作业,计算机专业英语单词作业.doc
- SpringBoot项目启动报错,java.lang.IllegalStateException: Ambiguous mapping.访问路径模棱两可,无法映射的问题!!!
- Spring Boot中使用Swagger3.0.0版本构建RESTful APIs
- FS4412-点亮LED
- php 数组从小到大排序,PHP 数组排序-php数组的排序函数
- Windows设置本地DNS域名解析hosts文件配置
- android MP3播放器(支持歌词滚动等功能)
- LeetCode 93. 复原 IP 地址【字符串,回溯算法】
- Ableton Live 11 Suite for Mac新版本升级