1.小球旋转
知识点:1.光照、视角、材质、矩阵变换的基本用法
2.计算FPS
#include "stdafx.h"
#include
#include
#include
#include
#include
#define WIDTH 400
#define HEIGHT 400
//#define ColoredVertex(c,v) do{glColor3fv(c);glVertex3fv(v);}while(0)
GLfloat angle=0.0f;
static int day =200;
double CalFrequency()
{
static int count;
static double save;
static clock_t last,current;
double timegap;
++count;
if(count<=50)
return save;
count = 0;
last = current;
current = clock();
timegap = (current-last)/(double)CLK_TCK;
save = 50.0/timegap;
return save;
}
void myDisplay(void)
{
double FPS=CalFrequency();
printf("FPS=%f\n",FPS);
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,5.0,-10.0,0,0,0,0,1,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);
glLightfv(GL_LIGHT0,GL_AMBIENT,sun_light_ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sun_light_diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,sun_light_specular);
glEnable(GL_LIGHT0);
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);
glMaterialfv(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);
glMaterialfv(GL_FRONT,GL_SHININESS,&earth_mat_shininess);
glRotatef(angle,0.0f,1.0f,0.0f);
glTranslatef(5.0f,0.0f,0.0f);
glutSolidSphere(2.0,40,32);
}
//glFlush();
glutSwapBuffers();
}
void myIdle(void)
{
angle+=1.0f;
if(angle>=360.0f)
angle=0.0f;
myDisplay();
}
int _tmain(int argc, char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowPosition(200,200);
glutInitWindowSize(WIDTH,HEIGHT);
glutCreateWindow("tanrunj");
glutDisplayFunc(myDisplay);
glutIdleFunc(myIdle);
glutMainLoop();
return 0;
}
知识点:1.BMP文件的正确读入
2.glReadPixels的正确
#define BMP_Header_Length 54
void grab(void)
{
FILE* pDummyFile;
FILE* pWritingFile;
GLubyte* pPixelData;
GLubyte BMP_Header[BMP_Header_Length];
GLint i,j;
GLint PixelDataLength;
i=WindowWidth*3;
while(i%4!=0)
i++;
PixelDataLength=i*WindowHeight;
//分配内存,打开流
pPixelData=(GLubyte*)malloc(PixelDataLength);
if(pPixelData==0)
exit(0);
fopen_s(&pDummyFile,"dummy.bmp","rb");
if(pDummyFile==0)
exit(0);
fopen_s(&pWritingFile ,"grab.bmp","wb");
if(pWritingFile==0)
exit(0);
//读取像素
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
glReadPixels(0,0,WindowWidth,WindowHeight,
GL_BGR_EXT,GL_UNSIGNED_BYTE,pPixelData);
//把dummy.bmp的文件头复制为新文件头
//pDummy->bmp_header
fread(BMP_Header,sizeof(BMP_Header),1,pDummyFile);
//bmp_header->pwriting
fwrite(BMP_Header,sizeof(BMP_Header),1,pWritingFile);
fseek(pWritingFile,0x0012,SEEK_SET);
i=WindowWidth;
j=WindowHeight;
//修改宽高参数
fwrite(&i,sizeof(i),1,pWritingFile);
fwrite(&j,sizeof(j),1,pWritingFile);
//写入像素
fseek(pWritingFile,0,SEEK_END);
fwrite(pPixelData,PixelDataLength,1,pWritingFile);
//释放内存,关闭流
fclose(pDummyFile);
fclose(pWritingFile);
free(pPixelData);
}
知识点:1.纹理的载入
2.贴图的用法
// ConsoleApplication1.cpp : ¶¨Òå¿ØÖÆ̨ӦÓóÌÐòµÄÈë¿Úµã¡£
//
#include "stdafx.h"
#include
#include
#include
#include
#include
#define WIDTH 400
#define HEIGHT 400
#define WindowWidth 400
#define WindowHeight 400
//grab 窗口的像素
#define BMP_Header_Length 54
void grab(void)
{
FILE* pDummyFile;
FILE* pWritingFile;
GLubyte* pPixelData;
GLubyte BMP_Header[BMP_Header_Length];
GLint i,j;
GLint PixelDataLength;
i=WindowWidth*3;
while(i%4!=0)
i++;
PixelDataLength=i*WindowHeight;
//分配内存,打开流
pPixelData=(GLubyte*)malloc(PixelDataLength);
if(pPixelData==0)
exit(0);
fopen_s(&pDummyFile,"dummy.bmp","rb");
if(pDummyFile==0)
exit(0);
fopen_s(&pWritingFile ,"grab.bmp","wb");
if(pWritingFile==0)
exit(0);
//读取像素
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
glReadPixels(0,0,WindowWidth,WindowHeight,
GL_BGR_EXT,GL_UNSIGNED_BYTE,pPixelData);
//把dummy.bmp的文件头复制为新文件头
//pDummy->bmp_header
fread(BMP_Header,sizeof(BMP_Header),1,pDummyFile);
//bmp_header->pwriting
fwrite(BMP_Header,sizeof(BMP_Header),1,pWritingFile);
fseek(pWritingFile,0x0012,SEEK_SET);
i=WindowWidth;
j=WindowHeight;
//修改宽高参数
fwrite(&i,sizeof(i),1,pWritingFile);
fwrite(&j,sizeof(j),1,pWritingFile);
//写入像素
fseek(pWritingFile,0,SEEK_END);
fwrite(pPixelData,PixelDataLength,1,pWritingFile);
//释放内存,关闭流
fclose(pDummyFile);
fclose(pWritingFile);
free(pPixelData);
}
//判断是否2的幂次
int power_of_two(int n)
{
if(n<=0)
return 0;
return (n&(n-1))==0;
}
GLfloat angle=0.0f;
GLuint load_texture(const char* file_name)
{
GLint width,height,total_bytes;
GLubyte* pixels = 0;
GLint last_texture_ID;
GLuint texture_ID = 0;
//打开文件
FILE* pFile ;
fopen_s(&pFile,file_name,"rb");
if(pFile==0)
return 0;
//读取宽高
fseek(pFile,0x0012,SEEK_SET);
fread(&width,4,1,pFile);
fread(&height,4,1,pFile);
fseek(pFile,BMP_Header_Length,SEEK_SET);
//计算像素总大小字节
{
GLint line_bytes = width*3;
while (line_bytes%4!=0)
++line_bytes;
total_bytes = line_bytes*height;
}
pixels = (GLubyte*)malloc(total_bytes);
if(pixels==0)
{
fclose(pFile);
return 0;
}
if(fread(pixels,total_bytes,1,pFile)<=0)
{
free(pixels);
fclose(pFile);
return 0;
}
//旧版中,纹理宽高不是整数次方或太大需缩放
{
GLint max;
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max);
if(!power_of_two(width)||
!power_of_two(height)||
width>max||height>>max)
{
const GLint new_width = 256;
const GLint new_height = 256;
GLint new_line_bytes,new_total_bytes;
GLubyte* new_pixels = 0;
//计算字节
new_line_bytes =new_width*3;
while (new_line_bytes%4!=0)
++new_line_bytes;
new_total_bytes=new_line_bytes*new_height;
//分配内存
new_pixels=(GLubyte*)malloc(new_total_bytes);
//分配失败
if(new_pixels==0)
{
free(pixels);
fclose(pFile);
return 0;
}
//像素缩放
gluScaleImage(GL_RGB,width,height,GL_UNSIGNED_BYTE,pixels,
new_width,new_height,GL_UNSIGNED_BYTE,new_pixels);
//释放,指向新数据,重设宽高
free(pixels);
pixels = new_pixels;
width = new_width;
height = new_height;
}
}
//分配纹理编号
glGenTextures(1,&texture_ID);
if(texture_ID ==0)
{
free(pixels);
fclose(pFile);
return 0;
}
//创建自定义的纹理
//绑定纹理,载入设参
//绑定前,获得纹理编号,最后恢复
glGetIntegerv(GL_TEXTURE_BINDING_2D,&last_texture_ID);
glBindTexture(GL_TEXTURE_2D,texture_ID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,
GL_BGR_EXT,GL_UNSIGNED_BYTE,pixels);
glBindTexture(GL_TEXTURE_2D,last_texture_ID);
//pixels内存在glteximage2d后可以释放,已被存到专门图形硬件
free(pixels);
return texture_ID;
}
//计算FPS
double CalFrequency()
{
static int count;
static double save;
static clock_t last,current;
double timegap;
++count;
if(count<=50)
return save;
count = 0;
last = current;
current = clock();
timegap = (current-last)/(double)CLK_TCK;
save = 50.0/timegap;
return save;
}
//纹理编号
GLuint texGround;
GLuint texWall;
void myDisplay(void)
{
double FPS=CalFrequency();
printf("FPS=%f\n",FPS);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//视角
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75,1,1,21);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1,5,5,0,0,0,0,0,1);
//贴土地
glBindTexture(GL_TEXTURE_2D,texGround);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-8,-8,0);
glTexCoord2f(0,5); glVertex3f(-8,8,0);
glTexCoord2f(5,5); glVertex3f(8,8,0);
glTexCoord2f(5,0); glVertex3f(8,-8,0);
glEnd();
//贴墙
glBindTexture(GL_TEXTURE_2D,texWall);
glBegin(GL_QUADS);
glTexCoord2d(0,0); glVertex3f(-6,-3,0);
glTexCoord2d(0,1); glVertex3f(-6,-3,1.5);
glTexCoord2f(5,1); glVertex3f(6,-3,1.5);
glTexCoord2f(5,0); glVertex3f(6,-3,0);
glEnd();
//旋转再绘制墙
glRotatef(-90,0,0,1);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-6,-3,0);
glTexCoord2f(0,1); glVertex3f(-6,-3,1.5);
glTexCoord2f(5,1); glVertex3f(6,-3,1.5);
glTexCoord2f(5,0); glVertex3f(6,-3,0);
glEnd();
glutSwapBuffers();
grab();
}
//转动调整
void myIdle(void)
{
angle+=1.0f;
if(angle>=360.0f)
angle=0.0f;
myDisplay();
}
int _tmain(int argc, char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowPosition(200,200);
glutInitWindowSize(WIDTH,HEIGHT);
glutCreateWindow("tanrunj");
glutDisplayFunc(myDisplay);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
texGround = load_texture("ground.bmp");
texWall = load_texture("wall.bmp");
glutIdleFunc(myIdle);
glutMainLoop();
return 0;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
setLight();
//ÒÔ£¨0,0£¬0.5£©ÎªÖÐÐÄ£¬»æÖÆÒ»¸ö°ë¾¶Îª.3µÄ²»Í¸Ã÷ºìÇò£¬¾àÀë×îÔ¶
setMatirial(red_color,30.0);
glPushMatrix();
glTranslatef(0,0,0.5);
//°ë¾¶£¬¾Î³¶ÎÊý
glutSolidSphere(0.3,30,30);
glPopMatrix();
//»æÖÆ°ë͸Ã÷£¬Éî¶È»º³åΪֻ¶Á
//glDepthMask(GL_FALSE);
//ÒÔ(0.2,0,-0.5)ΪÖÐÐÄ£¬»æÖÆ.2µÄ°ë͸Ã÷À¶Çò£¨×î½ü£©
setMatirial(blue_color,30);
glPushMatrix();
glTranslatef(0.2,0,-0.5);
glutSolidSphere(0.2,30,30);
glPopMatrix();
//ÒÔ(0.1,0,0)ΪÖÐÐÄ£¬»æÖÆ.15°ë͸Ã÷ÂÌÇò£¨Öм䣩
setMatirial(green_color,30);
glPushMatrix();
glTranslatef(0.1,0,0);
glutSolidSphere(0.15,30,30);
glPopMatrix();
//Íê³É°ë͸Ã÷£¬Éî¶È»Ö¸´¿É¶Á¿Éд
glDepthMask(GL_TRUE);
void display(void)
{
static int initialized = 0;
static GLuint texWindow = 0;
static GLuint texPicture = 0;
// 执行初始化操作,包括:读取相片,读取相框,将相框由BGR颜色转换为BGRA,启用二维纹理
if( !initialized )
{
texPicture = load_texture("pic.bmp");
texWindow = load_texture("window.bmp");
glBindTexture(GL_TEXTURE_2D, texWindow);
texture_colorkey(255, 255, 255, 10);
glEnable(GL_TEXTURE_2D);
initialized = 1;
}
// 清除屏幕
glClear(GL_COLOR_BUFFER_BIT);
// 绘制相片,此时不需要进行Alpha测试,所有的像素都进行绘制
glBindTexture(GL_TEXTURE_2D, texPicture);
glDisable(GL_ALPHA_TEST);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(0, 1); glVertex2f(-1.0f, 1.0f);
glTexCoord2f(1, 1); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(1, 0); glVertex2f( 1.0f, -1.0f);
glEnd();
// 绘制相框,此时进行Alpha测试,只绘制不透明部分的像素
glBindTexture(GL_TEXTURE_2D, texWindow);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(0, 1); glVertex2f(-1.0f, 1.0f);
glTexCoord2f(1, 1); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(1, 0); glVertex2f( 1.0f, -1.0f);
glEnd();
// 交换缓冲
glutSwapBuffers();
}
void display(void)
{
// 清除屏幕
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 设置观察点
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1, 5, 25);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5, 0, 6.5, 0, 0, 0, 0, 1, 0);
glEnable(GL_DEPTH_TEST);
// 绘制球体
glDisable(GL_STENCIL_TEST);
draw_sphere();
// 绘制一个平面镜。在绘制的同时注意设置模板缓冲。
// 另外,为了保证平面镜之后的镜像能够正确绘制,在绘制平面镜时需要将深度缓冲区设置为只读的。
// 在绘制时暂时关闭光照效果
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glEnable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING);
glColor3f(0.5f, 0.5f, 0.5f);
glDepthMask(GL_FALSE);
glRectf(-1.5f, -1.5f, 1.5f, 1.5f);
glDepthMask(GL_TRUE);
// 绘制一个与先前球体关于平面镜对称的球体,注意光源的位置也要发生对称改变
// 因为平面镜是在X轴和Y轴所确定的平面,所以只要Z坐标取反即可实现对称
// 为了保证球体的绘制范围被限制在平面镜内部,使用模板测试
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glScalef(1.0f, 1.0f, -1.0f);
draw_sphere();
// 交换缓冲
glutSwapBuffers();
// 截图
grab();
}