说明
- 使用图形学的两个最常用的阴影技术之一,Shadow Mapping方法(另一种是Shadow Volumes方法)。
- 使用多重纹理。
- 使用双缓冲。
参考网址
实现大概过程
第一次绘制:关闭光照效果,普通,阴影;将视角放在光源处,绘制物体(记得剔除正面),获得深度。
恢复矩阵,初始化纹理自动生成坐标。清空缓冲区。
第二次绘制:
1、打开光照效果,关闭光源(相当于只使用环境光),打开普通贴图,关闭阴影纹理,绘制物体,获得环境光下物体的颜色。
2、将环境光置为0(即关闭环境光),打开光源(打开光照效果),打开普通贴图和阴影纹理,绘制物体(当深度和纹理相等时绘制)。
恢复环境光,渲染物体。
代码
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include <windows.h>
#define PI 3.14159265359
/********************全局变量及函数的预定义**********************************/
float day=0;//地球自转角度
float month=0;//月亮自转和公转角度
float year=0;//地球公转角度
float sun=0;//太阳自转角度
GLuint tex_walls[3], tex_shadow;
GLuint frame_buffer_s;
int shadow_w=1366, shadow_h=768;
GLfloat lightPos[] = {
0.0, 0.0, 0.0 };//点光源位置
GLfloat lookat[] = {
1.0, 0.0, 0.0 };//向前方向
GLfloat up[] = {
0.0, 1.0, 0.0 };//向上方向
GLfloat texData[1366*768];
/****函数的预定义****/
void tex_init(void);
/******************glut回调函数**********************************************/
void Keyboard(unsigned char key, int x, int y){
if(key==27)//按下Esc键退出
exit(0);
}
void Timer(int millis){
// float dday = 6,speed = 4;
float dday = 18,speed = 12;
float dmonth = speed*dday/29.5;//月亮自转和公转角度的增量
float dyear = speed*dday/365.2475;//地球公转角度的增量
float dsun = speed*dday/27.5;//太阳自转角度的增量
day = fmod(day+dday,360);//计算地球自转角度
month = fmod(month+dmonth,360);//计算月亮自转和公转角度
year = fmod(year+dyear,360);//计算地球公转角度
sun = fmod(sun+dsun,360);//计算太阳自转角度
glutPostRedisplay();//调用场景绘制函数
glutTimerFunc(millis,Timer,millis);//指定定时器函数,参数为间隔毫秒数,函数名,函数参数值
}
void Reshape(int w,int h){
//窗口变化回调函数
glViewport(0,0,w,h);//视口的位置和大小
glMatrixMode(GL_PROJECTION);//当前变换类型为投影变换
glLoadIdentity();//当前矩阵为单位矩阵
//定义投影变换,参数为:y向张角;x/y;近平面;远平面
gluPerspective(30,(float) w/h,1,1000);
glTranslatef(0,0,-8);//适当远移
glRotatef(30,1,0,0);//调整观察角度
glMatrixMode(GL_MODELVIEW);//当前变换类型为视图造型变换
glLoadIdentity();
}
/******************非功能函数************************************************/
void transposeMatrix( GLfloat m[16] )//置换矩阵
{
GLfloat tmp;
#define Swap( a, b ) tmp = a; a = b; b = tmp
Swap( m[1], m[4] );
Swap( m[2], m[8] );
Swap( m[3], m[12] );
Swap( m[6], m[9] );
Swap( m[7], m[13] );
Swap( m[11], m[14] );
#undef Swap
}
/******************纹理及阴影************************************************/
void init(){
glEnable(GL_DEPTH_TEST);//打开深度测试,用于比较远近
float gac[4] = {
0.4f, 0.4f, 0.4f, 1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, gac);//设置环境光亮度
tex_init();//初始化普通贴图,阴影纹理,缓冲
}
//普通贴图,阴影纹理,缓冲
void tex_init()
{
glActiveTexture(GL_TEXTURE0); // 普通贴图
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );//设置纹理自动产生坐标,GL_OBJECT_LINEAR
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
{
//读取文件,获取图片数据,太阳纹理
FILE *file = fopen("C:/Users/Administrator/Desktop/QTProjects/Planetary/1sun.bmp", "rb"); // 打开文件
fseek(file, sizeof(BITMAPFILEHEADER), SEEK_SET); // 跳过文件头
BITMAPINFOHEADER info; // 位图信息头
fread