glPixelStorei 详解 包括像素传输

3.glPixelStore

像glPixelStorei(GL_PACK_ALIGNMENT, 1)这样的调用,通常会用于像素传输(PACK/UNPACK)的场合。尤其是导入纹理(glTexImage2D)的时候:

C++代码
  1. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);  
  2. glTexImage2D(,,,, &pixelData);
  3.   
  4. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);  

很明显地,它是在改变某个状态量,然后再Restore回来。——为什么是状态?你难道8知道OpenGL就是以状态机不?——什么状态?其实名字已经很直白了,glPixelStore这组函数要改变的是像素的存储格式。

涉及到像素在CPU和GPU上的传输,那就有个存储格式的概念。在本地内存中端像素集合是什么格式?传输到GPU时又是什么格式?格式会是一样么?在glTexImage2D这个函数中,包含两个关于颜色格式的参数,一个是纹理(GPU端,也可以说server端)的,一个是像素数据(程序内存上,也就是client端)的,两者是不一定一样的,哪怕一样也无法代表GPU会像内存那样去存储。或者想象一下,从一张硬盘上的图片提取到内存的像素数据,上传给GPU成为一张纹理,这个“纹理”还会是原来的那种RGBARGBA的一个序列完事么?显然不是的。作为一张纹理,有其纹理ID、WRAP模式、插值模式,指定maipmap时还会有一串各个Level下的map,等等。就纹理的数据来说,本质纹理是边长要满足2的n次方(power of two)的数据集合,这样首先大小上就有可能不一样,另外排列方式也未必就是RGBA的形式。在OpenGL的“解释”中,纹理就是一个“可以被采样的复杂的数据集合”,无论外面世界千变万化,GPU只认纹理作为自己“图像数据结构”,这体现着“规范化”这条世界纽带的伟大之处。

姑且把GPU里面的像素存储格式看做一个未知数,把该存储空间内那批像素看做一堆X。不要深究一堆X究竟是什么样子的,嘛,反正就想象成一堆软绵绵的,或者模糊不清的,打满马赛克的,(哔——)的一样的东西就可以了。与此相比,内存中的像素数据实在太规则规范了!可能源文件各种图片格式,什么bmp、jpg、png甚至dds,但只要你按该格式的算法结构来提取(类似[Bmp文件的结构与基本操作(逐像素印屏版)] ),总可以提取出一列整齐的RGBARGBA(或者RGBRGB什么的,反正很整齐就行了管他呢)的数据堆出来,是可以在程序中实测的东西。

涉及到像素在CPU和GPU上的传输,那就有个传输方向的概念。那就是大家耳濡目染的PACK和UNPACK。嘛,装载和卸载也可以,打包和解压也可以,随你怎么译了。结合上述存储格式的概念:

  • PACK —— 把像素从一堆X的状态转变到规则的状态(把一堆泥土装载进一个花盆,把散散的货物装上货柜,或者把一堆各样的文件打包成一个rar压缩包,等等);
  • UNPACK —— 把像素从规则的状态转变到一堆X的状态(把花盆里的泥倒出来,把货柜中的货物卸载到盐田港,或者解压压缩包,等等)。

我认为这两个概念还是很容易混淆的,所以形象化一点总好点嘛。从本地内存向GPU的传输(UNPACK),包括各种glTexImage、glDrawPixel;从GPU到本地内存的传输(PACK),包括glGetTexImage、glReadPixel等。也正因如此,PBO也有PACK和UNPACK模式的区别。

好像说了好多不相关的事情。嘛,适当也当做延伸。回头来真正看一下glPixelStore吧。它的第一个参数,譬如ALIGNMENT、ROW_LENGTH、IMAGE_HEIGHT等等,都有PACK和UNPACK的两种版本,所以对应的也是上述关于PACH和UNPACK的两类函数。所以对于glTexImage2D,才使用GL_UNPACK_ALIGNMENT的版本。但要说明的是,无论是哪种传输方式,它都是针对本地内存端(client端)上的像素数据的。在上述例子中,它起着补充glTexImage2D中关于传输起点——本地像素集合的格式,的作用。

一般来说,这些本地的数据集合,只要知道其起始位置、大小(width*height)和颜色格式(譬如GL_RGBA等等)、值格式(GL_UNSIGNED_CHAR、GL_FLOAT等等),就能准确地传输。而这些都是需要向glTexImage2D函数(或者上述的其他传输型函数)提供的。但是,这里头也一些细节,其实是需要glPixelStore这个函数来进行设置的。

3.1 GL_UNPACK_ALIGNMENT / GL_PACK_ALIGNMENT

通常,提取一张图像的时候,我们怎么知道一行的数据量呢?这个一行的数据量应该是:width * sizeof(Pixel) ,应对最一般RGBA、各通道各占一个字节的像素结构,width * sizeof(Pixel) = width * 4 * sizeof(byte),是4的整数倍。但是也有时候,我们的像素数据中一行的数据量不一定是4的整数倍(譬如一张RGB的图像、宽度150、各通道各占一个字节的像素结构,一行的数据量就是450个字节)。

另一方面,跟编译器一样,GPU传输时也喜欢4字节对齐,也即是说喜欢对像素数据按4字节存取。所以它更偏向于喜欢每一行的数据量是4的整数倍(按上述,这恰好是比较常见的)。所以为了更高的存取效率,OpenGL默认让像素数据按4字节4字节的方式传输向GPU——但是问题在于,对于行非4字节对齐的像素数据,第一行的最后一次存取的4字节将部分包括第一行的数据部分包括第二行的数据,当然致命的不是在这里,而是在最后一行:存取将很可能会越界。为了防止这样的情况,一是硬性把像素数据延展成4字节对齐的(就像BMP文件的存储方式一样,[Bmp文件的结构与基本操作(逐像素印屏版)] );二是选择绝对会造成4字节对齐的颜色格式或值格式(GL_RGBA啦,或者GL_INT、GL_FLOAT之类);三是以牺牲一些存取效率为代价,去更改OpenGL的字节对齐方式——这就是glPixelStore结合GL_UNPACK_ALIGNMENT / GL_PACK_ALIGNMENT。

C++代码
  1. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);    
  2.    
  3. glTexImage2D(,,,, &pixelData);  
  4.     
  5. glPixelStorei(GL_UNPACK_ALIGNMENT, 4);    

再次看回这段代码,这时候就明白了:让字节对齐从默认的4字节对齐改成1字节对齐(选择1的话,无论图片本身是怎样都是绝对不会出问题的,嘛,以效率的牺牲为代价),UNPACK像素数据,再把字节对齐方式设置回默认的4字节对齐。至于哪种方式更适合,就看你依据硬件环境限制、麻烦程度等,去选择了。

3.2 GL_UNPACK_ROW_LENGTH/ GL_PACK_ROW_LENGTH 和 GL_UNPACK_SKIP_ROWS / GL_PACK_SKIP_ROWS 、 GL_UNPACK_SKIP_PIXELS/GL_PACK_SKIP_PIXELS

有的时候,我们把一些小图片拼凑进一张大图片内,这样使用大图片生成的纹理,一来可以使多个原本使用不同的图片作为纹理的同质物件如今能够在同一个Batch内,节省了一些状态切换的开销,二来也容易综合地降低了显存中纹理的总大小。但是,也有些时候,我们需要从原本一张大的图片中,截取图片当中的某一部分作为纹理。要能够做到这样,可以通过预先对图片进行裁剪或者在获得像素数据后,把其中需要的那一部分另外存储到一个Buffer内再交给glTexImage2D之类的函数。而上述这些参数下glPixelStore的使用将帮助我们更好地完成这个目的:

C++代码
  1.   //原图中需要单独提取出来制成纹理的区域
  2. RECT subRect = {{100, 80}, {500, 400}}; //origin.x, origin.y, size.width, size.height
  3. //假设原图的宽度为BaseWidth, 高度为BaseHeight
  4. glPixelStorei(GL_UNPACK_ROW_LENGTH,  BaseWidth);    //指定像素数据中原图的宽度
  5. glPixelStorei(GL_UNPACK_SKIP_ROWS,      subRect. origin.y.); //指定纹理起点偏离原点的高度值
  6. glPixelStorei(GL_UNPACK_SKIP_PIXELS,     subRect. origin.x); //指定纹理起点偏离原点的宽度值
  7. glTexImage2D(..., subRect.size.width, ubRect.size.height,.. &pixelData);  //使用区域的宽高
  8.   
  9. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);  
  10. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);  
  11. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);  

这段代码本身,即使没有注释也很清楚了。注意的是GL_UNPACK_ROW_LENGTH的必要性,因为为了确认区域起点的Offset,就需要把线性数据pixelData上标记起点的“游标”从0移动到OffsetToData = subRect. origin.y * BaseWidth + subRect. origin.x的位置。有了区域纹理原点的在原图数据的位置,以及区域的尺寸,glTexImage2D就可以确定区域纹理生成所需要的信息了。通过glPixelStore的使用,避免了新建Buffer和自己处理图像数据的开销和麻烦了。

说到这里,到底为什么要这样做来提取区域纹理呢?尤其是原图若其他部分都是程序所需要的,那是不是就可以直接通过纹理坐标去切割更好呢?我想到的是一种情况(也可以说我是因为这种情况才注意到glPixelStore的这种用法):如果这块区域纹理需要作重复铺设(wrap mode选择GL_REPEAT)呢?这时候纹理坐标的方法就没用了,因为REPEAT所依据的也是纹理坐标(使用纹理坐标的小数部分进行采样)。这时候就需要上述做法了。(事实上3DSMAX等软件纹理导入的类似区域纹理平铺的功能就能如此实现。)

4.glScissor

我想这个函数也应该很常见才对。裁剪测试啊,当年跟Alpha测试、Depth测试、Stencil测试可以并列哦,而今更是不掉时髦值啊。因为我实在很难想象在Shader里能容易地实现它的功能:裁剪。当然这只是矩形裁剪,但是对于discard掉渲染中不需要的像素真是颇简单粗暴。我使用它最多的是一些二维图片缩略图栏——有时候我们只需要把这些缩略图的显示限制在一个区域里,但又要支持滑动。

C++代码 (OpenGL)
  1.         glEnable(GL_SCISSOR_TEST);  
  2.         glScissor(GLint(m_rtThumbRegion.x), GLint(m_rtThumbRegion.y), GLint(m_rtThumbRegion.width), GLint(m_rtThumbRegion.height));  
  3.   
  4.        //.....  Render
  5.   
  6.         glDisable(GL_SCISSOR_TEST);  

其中,除了启用GL_SCISSOR_TEST外,只要给glScissor指出需要保留显示的区域就可以了。在此区域外的像素依然会被渲染(不会怎么省流水线操作,所以也别指望它附带什么提高效率之类的功能),在下图中,其实左右两侧还是继续渲染其他的图片(或者说,其实这个缩略图栏横跨整个屏幕),但是就在fragment shader之后,它们会被检测到不在该区域内而被discard掉罢

分享:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include "stdafx.h" #include <GL/glut.h> #include <stdlib.h> #include <stdio.h> #define stripeImageWidth 32 GLubyte stripeImage[4 * stripeImageWidth]; #ifdef GL_VERSION_1_1 static GLuint texName; #endif void makeStripeImage(void) { int j; for (j = 0; j < stripeImageWidth; j++) { stripeImage[4 * j] = (GLubyte)((j <= 4) ? 255 : 0); stripeImage[4 * j + 1] = (GLubyte)((j>4) ? 255 : 0); stripeImage[4 * j + 2] = (GLubyte)0; stripeImage[4 * j + 3] = (GLubyte)255; } } /* planes for texture coordinate generation */ static GLfloat xequalzero[] = { 1.0, 0.0, 0.0, 0.0 }; static GLfloat slanted[] = { 1.0, 1.0, 1.0, 0.0 }; static GLfloat *currentCoeff; static GLenum currentPlane; static GLint currentGenMode; static float roangles; static float roangles1; float roangles2 = -2; float roangles3 = -3; void SpecialKeys(int key, int x, int y) { if (key == GLUT_KEY_F1) roangles += 2.0f; roangles2 += 0.05; roangles3 += 1; if (key == GLUT_KEY_F2) roangles1 += 2.0f; if (roangles2 >= 3) roangles2 = -3; // 使用新的坐标重新绘制场景 glutPostRedisplay(); } void init(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); makeStripeImage(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef GL_VERSION_1_1 glGenTextures(1, &texName;); glBindTexture(GL_TEXTURE_1D, texName); #endif glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifdef GL_VERSION_1_1 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, stripeImageWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, stripeImage); #else glTexImage1D(GL_TEXTURE_1D, 0, 4, stripeImageWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, stripeImage); #endif glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); currentCoeff = xequalzero; currentGenMode = GL_OBJECT_LINEAR; currentPlane = GL_OBJECT_PLANE; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, currentGenMode); glTexGenfv(GL_S, currentPlane, currentCoeff); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_1D); //glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glFrontFace(GL_CW); //glCullFace(GL_BACK); glMaterialf(GL_FRONT, GL_SHININESS, 64.0); roangles = 45.0f; roangles1 = 362.0f; } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glBegin(GL_QUADS); glColor3f(1, 0, 1); glVertex3f(-1, -1, 0); glColor3f(1, 0, 1); glVertex3f(-3, -1, 0); glColor3f(1, 0, 1); glVertex3f(1, -1, 0); glColor3f(1, 0, 1); glVertex3f(-1, -2, 0); glEnd(); glPopMatrix(); glPushMatrix(); glTranslated(roangles2, 2, -3); glRotatef(roangles, 0.0, 1.0, 0.0); #ifdef GL_VERSION_1_1 glBindTexture(GL_TEXTURE_1D, texName); #endif //glutSolidTeapot(2.0); glutSolidSphere(0.8, 32, 32); glPopMatrix(); glFlush(); glPushMatrix(); glTranslated(1, 2, -3); glRotatef(roangles1, 1.0, 0.0, 0.0); glRotatef(roangles3, 0.0, 1.0, 0.0); #ifdef GL_VERSION_1_1 glBindTexture(GL_TEXTURE_1D, texName); #endif //glutSolidTeapot(2.0); glTranslated(-1, -3, -0); glRotatef(90, 1.0f, 0.0f, 0.0f); glRotatef(180, 0.0f, 1.0f, 0.0f); glRotatef(-30, 0.0f, 0.0f, 1.0f); glutSolidCone(1, 2, 32, 32); glPopMatrix(); glFlush(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-3.5, 3.5, -3.5*(GLfloat)h / (GLfloat)w, 3.5*(GLfloat)h / (GLfloat)w, -3.5, 3.5); else glOrtho(-3.5*(GLfloat)w / (GLfloat)h, 3.5*(GLfloat)w / (GLfloat)h, -3.5, 3.5, -3.5, 3.5); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void idle() { roangles += 0.1f; glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc;, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(600, 600); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); //glutIdleFunc(idle); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutSpecialFunc(SpecialKeys); glutMainLoop(); return 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 原理
#include<stdio.h> #include<stdlib.h> #include<gl/glaux.h> #include<GL/glut.h> #include"../../wgGameLib03/dms/FileImage.h" #include"../../wgGraphLib/GraphElemenfs.h" GLint iWidth, iHeight, iGomponents.h; GLenum eFormat; GLfloat xRot,yRot; GLfloat noLight[4]={0.0f,0.0f,0.0f,1.0f}; GLfloat ambientLight[4]={0.3f,0.3f,0.3f,0.2f}; GLfloat brightLight[4]={1.0f,1.0f,1.0f,0.3f}; static GLfloat lightPos[]={5.0f,5.0f,5.0f,1.0f}; void Init() { glClearColor(0.0f,0.0f,0.0f,1.0f); glCullFace(GL_BACK); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glLigntModelfv(GL_LIGHT_MODEL_AMBIENT,noLight); glLightfv(GL_LIGHTO,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHTO,GL_DIFFUSE,diffuseLight); glLightfv(GL_LIGHTO,GL_SPECULAR,brightLight); glLightfv(GL_LIGHTO,GL_POSITION,lightPos); glEnable(GL_COLOR_MATERIAL); glColorMateriali(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); glMaterialfv(GL_FRONT,GL_SPECULAR,brightLight); glMateriali(GL_FRONT,GL_SHININESS,30); glPixelStorei(GL_UNPACK_ALIGHMENT,1); dms::FileImage image("stone.jpg"); if(image.data()) { glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,image.width(),image.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,image.data()); //glTexImage2D(GL_TEXTURE_2D,0,iComponents,iWidth,iHeight,0,eFormat,GL_UNSIGNED_BYTE,pImage); free(image.data()); } float colorl[4]={1.0,0.1,0.1,1.0}; 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_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_BLEND); glEnable(GL_TEXTURE_2D); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); float vertices[5][3]={{0.0f,0.8f,0.0f}, {-0.50f,0.0f,-0.50f}, {0.5f,0.0f,-0.5f}, {0.50f,0.0f,0.50f}}; float normal[3]; glPushMatrix(); glTranslatef(0.0f,-0.3f,-4.0f); if(xRot>360.5f) { xRot=0.0f; } if(yRot>360.5f) { yRot=0.0f; } glBotatef(xROt,1.0f,0.0f,0.0f); glRotatef(yRot,0.0f,1.0f,0.0f); xRot+=0.5f; yRot+=0.5f; glBegin(GL_TRIANGLES); glColor3f(1.0f,0.0f,0.0f); glNormal3f(0.0f,-1.0f,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[2]); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[4]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.0f,1.0f); glVertex3fv(vertices[1]); glColor3f(0.0f,0.0f,1.0f); wgGetNormal(vertices[1],vertices[3],vertices[0],normal); glNormal3f(normal); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glColor3f(0.0f,1.0f,1.0f); wgGetNormal(vertices[0],vertices[4],vertices[2],normal); glNormal3f(normal); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[2]); glColor3f(1.0f,0.0f,1.0f); wgGetNormal(vertices[0],vertices[2],vertices[1],normal); glNormal3f(normal); glTexCoord2f(0.5f,0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f,0.0f); glVertex3fv(vertices[2]); glTexCoord2f(1.0f,0.0f); glVertex3fv(vertices[1]); glEnd(); glPopMatrix(); glutSwapBuffers(); } voidReshape(GLsizei w,GLsizei h) { if(h==0) h=1; glViewport(0,0,w,h); float fAspect=(GLfloat)w/(GLfloat)h; glMatrixMade(GL_PROJECTION); glLoadIdentity(); glutPostRedisplay(); } void TimerFunc(int value) { glutPostRedisplay(); glutTimerFunc(60,TimerFunc,1); } int main(int args,char *argv[]) { glutInit(&args,argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(512,512); glutCreatWindow("example"); glutDisplayFunc(display); glutReshapeFunc(Reshape); Init(); glutTimerFunc(50,TimerFunc,1); //tTexture glutMainLoop(); return 0; }
视点变换,旋转,加速减速,星空背景 太阳,光晕 各行星纹理 #include #include #include #include #include #include #include #pragma comment(lib, "winmm.lib") #pragma comment(lib,"wininet") // 纹理图像结构 typedef struct { int imgWidth; // 纹理宽度 int imgHeight; // 纹理高度 unsigned char byteCount; // 每个象素对应的字节数,3:24位图,4:带alpha通道的24位图 unsigned char *data; // 纹理数据 }TEXTUREIMAGE; // BMP文件头 #pragma pack(2) typedef struct { unsigned short bfType; // 文件类型 unsigned long bfSize; // 文件大小 unsigned short bfReserved1; // 保留位 unsigned short bfReserved2; // 保留位 unsigned long bfOffBits; // 数据偏移位置 }BMPFILEHEADER; #pragma pack() // BMP信息头 typedef struct { unsigned long biSize; // 此结构大小 long biWidth; // 图像宽度 long biHeight; // 图像高度 unsigned short biPlanes; // 调色板数量 unsigned short biBitCount; // 每个象素对应的位数,24:24位图,32:带alpha通道的24位图 unsigned long biCompression; // 压缩 unsigned long biSizeImage; // 图像大小 long biXPelsPerMeter;// 横向分辨率 long biYPelsPerMeter;// 纵向分辨率 unsigned long biClrUsed; // 颜色使用数 unsigned long biClrImportant; // 重要颜色数 }BMPINFOHEADER; // 定义窗口的标题、宽度、高度、全屏布尔变量 #define WIN_TITLE "模拟太阳系各星球的转动" const int WIN_WIDTH = 800; const int WIN_HEIGHT = 600; BOOL isFullScreen = FALSE; // 初始不为全屏 #define DEG_TO_RAD 0.017453 float angle=0.0; static GLdouble viewer[]= {0,0,0,0,0}; // 初始化视角 GLUquadricObj *quadric; // 建立二次曲面对象 GLfloat angle_Z; // 星空旋转角度 bool g_bOrbitOn = true; // 控制转动暂停 float g_fSpeedmodifier = 1.0f; // 时间控制 float g_fElpasedTime; double g_dCurrentTime; double g_dLastTime; GLfloat LightAmbient[] = { 1.0f, 1.0f, 1.0f, 0.0f }; // 环境光参数 GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 0.0f }; // 漫射光参数 GLfloat LightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 光源的位置 // 纹理图象 TEXTUREIMAGE skyImg; TEXTUREIMAGE sunImg; TEXTUREIMAGE rayImg; TEXTUREIMAGE mercuImg; TEXTUREIMAGE venusImg; TEXTUREIMAGE earthImg; TEXTUREIMAGE marsImg; TEXTUREIMAGE jupiterImg; TEXTUREIMAGE saturnImg; TEXTUREIMAGE uranusImg; TEXTUREIMAGE neptuneImg; TEXTUREIMAGE moonImg; GLuint texture[12]; // 纹理数组 // 星球速度定义 static float fSunSpin = 0.0f; // 太阳自转速度 static float fMercuSpin = 0.0f; // 水星自转速度 static float fMercuOrbit = 0.0f; // 水星公转速度 static float fVenusSpin = 0.0f; // 金星自转速度 static float fVenusOrbit = 0.0f; // 金星公转速度 static float fEarthSpin = 0.0f; // 地球自转速度 static float fEarthOrbit = 0.0f; // 地球公转速度 static float fMarsSpin = 0.0f; // 火星自转速度 static float fMarsOrbit = 0.0f; // 火星公转速度 static float fJupiterSpin = 0.0f; // 木星自转速度 static float fJupiterOrbit = 0.0f; // 木星公转速度 static float fSaturnSpin = 0.0f; // 土星自转速度 static float fSaturnOrbit = 0.0f; // 土星公转速度 static float fUranusSpin = 0.0f; // 天王星自转速度 static float fUranusOrbit = 0.0f; // 天王星公转速度 static float fNeptuneSpin = 0.0f; // 海王星自转速度 static float fNeptuneOrbit = 0.0f; // 海王星公转速度 static float fMoonSpin = 0.0f; // 月亮自转速度 static float fMoonOrbit = 0.0f; // 月亮公转速度 void MakeTexture(TEXTUREIMAGE textureImg, GLuint * texName) //转换为纹理 { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //对齐像素字节函数 glGenTextures(1,texName); //第一个参数指定表明获取多少个连续的纹理标识符 glBindTexture(GL_TEXTURE_2D , *texName); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureImg.imgWidth,textureImg.imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImg.data); } // 初始化OpenGL void InitGL(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //设置黑色背景 glClearDepth(2.0f); // 设置深度缓存 glEnable(GL_DEPTH_TEST); //启动深度测试 glDepthFunc(GL_LEQUAL); //深度小或相等的时候渲染 glShadeModel(GL_SMOOTH); //启动阴影平滑 glEnable(GL_CULL_FACE); //开启剔除操作效果 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //使用质量最好的模式指定颜色和纹理坐标的插值质量 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // 设置环境光 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // 设置漫反射光 glEnable(GL_LIGHTING); // 打开光照 glEnable(GL_LIGHT1); // 打开光源1 // 载入纹理 glEnable(GL_TEXTURE_2D); // 开启2D纹理映射 MakeTexture(skyImg, &texture;[0]); MakeTexture(sunImg, &texture;[1]); MakeTexture(rayImg, &texture;[2]); MakeTexture(mercuImg, &texture;[3]); MakeTexture(venusImg, &texture;[4]); MakeTexture(earthImg, &texture;[5]); MakeTexture(marsImg, &texture;[6]); MakeTexture(jupiterImg, &texture;[7]); MakeTexture(saturnImg, &texture;[8]); MakeTexture(uranusImg, &texture;[9]); MakeTexture(neptuneImg, &texture;[10]); MakeTexture(moonImg, &texture;[11]); quadric = gluNewQuadric(); // 建立一个曲面对象指针 gluQuadricTexture(quadric, GLU_TRUE); // 建立纹理坐标 gluQuadricDrawStyle(quadric, GLU_FILL); // 面填充 } void Display(void) { glLoadIdentity(); // 设置观察点的位置和观察的方向 gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0); //摄像机x,摄像机y,摄像机z, 目标点x,目标点y,目标点z, 摄像机顶朝向x,摄像机顶朝向y,摄像机顶朝向z // 获得系统时间使太阳系有动态效果 g_dCurrentTime = timeGetTime(); g_fElpasedTime = (float)((g_dCurrentTime - g_dLastTime) * 0.0005); g_dLastTime = g_dCurrentTime; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode( GL_MODELVIEW ); //指定GL_MODELVIEW是下一个矩阵操作的目标 glTranslatef(0.0f, 0.0f, -5.0f); // 将坐标系移入屏幕5.0f glRotatef(10, 1.0f ,0.0f, 0.0f); // 将坐标系绕x轴旋转10度 glEnable(GL_LIGHT0); // 打开光源0 /**********************************绘制背景星空********************************************/ glPushMatrix (); // 当前模型矩阵入栈 glTranslatef(-10.0f, 3.0f, 0.0f); glRotatef(angle_Z, 0.0f, 0.0f, 1.0f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); // 星空纹理 glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f, 50.0f, -50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, -1.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f, 50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f( 50.0f, -50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f( 50.0f, -50.0f, -50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 0.0f, -1.0f, 0.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 50.0f, 50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f( 50.0f, 50.0f, -50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( 1.0f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-50.0f, -50.0f, -50.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(-50.0f, 50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(-50.0f, -50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(-50.0f, 50.0f, -50.0f); glEnd(); glBegin(GL_QUADS); glNormal3f( -1.0f, 0.0f, 0.0f); glTexCoord2f(6.0f, 6.0f); glVertex3f(50.0f, -50.0f, -50.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(50.0f, 50.0f, 50.0f); glTexCoord2f(6.0f, 0.0f); glVertex3f(50.0f, -50.0f, 50.0f); glTexCoord2f(0.0f, 6.0f); glVertex3f(50.0f, 50.0f, -50.0f); glEnd(); glPopMatrix (); // 当前模型矩阵出栈 /**********************************绘制太阳************************************************/ glBindTexture(GL_TEXTURE_2D, texture[2]); // 光晕纹理 glEnable(GL_BLEND); // 开启混合 glDisable(GL_DEPTH_TEST); // 关闭深度测试 // 绘制太阳光晕 glDisable(GL_LIGHTING); // 关闭光照 glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 半透明混合函数 glColor4f(1.0f, 0.5f, 0.0f, 0.5f); // 设置RGBA值 glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glEnd(); glDisable(GL_BLEND); // 关闭混合 glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); // 开启光照 glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // 设置光源1位置 glBindTexture(GL_TEXTURE_2D, texture[1]); // 太阳纹理 // 将坐标系绕Y轴旋转fSunSpin角度,控制太阳自转 glRotatef(fSunSpin,0.0,1.0,0.0); gluSphere(quadric, 0.3f, 32, 32); // 绘制太阳球体 /**********************************绘制水星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fMercuOrbit角度,控制水星公转 glRotatef(fMercuOrbit, 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(0.5f, 0.0f, 0.0f); // 将坐标系右移0.5f glBindTexture(GL_TEXTURE_2D, texture[3]); // 水星纹理 // 将坐标系绕Z轴旋转fMercuSpin角度 控制水星自转 glRotatef(fMercuSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.04f, 32, 32); // 水星球体 glPopMatrix (); // 当前模型视图矩阵出栈 // 绘制轨道 glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(0.5f*sin(DEG_TO_RAD*angle),0,0.5f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制金星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fVenusOrbit角度,控制金星公转 glRotatef(fVenusOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);// 将坐标系绕X轴旋转-90度 glTranslatef(0.8f, 0.0f, 0.0f); // 将坐标系右移0.8f glBindTexture(GL_TEXTURE_2D, texture[4]); // 金星纹理 // 将坐标系绕Z轴旋转fVenusSpin角度,控制金星自转 glRotatef(fVenusSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.06f, 32, 32); // 金星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(0.8f*sin(DEG_TO_RAD*angle),0,0.8f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制地球************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fEarthOrbit角度,控制地球公转 glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);// 将坐标系绕X轴旋转-90度 glTranslatef(1.1f, 0.0f, 0.0f); // 将坐标系右移1.1f glBindTexture(GL_TEXTURE_2D, texture[5]); // 地球纹理 // 将坐标系绕Z轴旋转fEarthSpin角度,控制地球自转 glRotatef(fEarthSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.08f, 32, 32); // 地球球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.1f*sin(DEG_TO_RAD*angle),0,1.1f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制火星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fMarsOrbit角度,控制火星公转 glRotatef(fMarsOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.4f, 0.0f, 0.0f); // 将坐标系右移1.4f glBindTexture(GL_TEXTURE_2D, texture[6]); // 火星纹理 // 将坐标系绕Z轴旋转fMarsSpin角度,控制火星自转 glRotatef(fMarsSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.04f, 32, 32); // 火星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.4f*sin(DEG_TO_RAD*angle),0,1.4f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制木星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fJupiterOrbit角度,控制木星公转 glRotatef(fJupiterOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.7f, 0.0f, 0.0f); // 将坐标系右移1.7f glBindTexture(GL_TEXTURE_2D, texture[7]); // 木星纹理 // 将坐标系绕Z轴旋转fJupiterSpin角度,控制木星自转 glRotatef(fJupiterSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.13f, 32, 32); // 木星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.7f*sin(DEG_TO_RAD*angle),0,1.7f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制土星************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fSaturnOrbit角度,控制土星公转 glRotatef(fSaturnOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(1.9f, 0.0f, 0.0f); // 将坐标系右移1.9f glBindTexture(GL_TEXTURE_2D, texture[8]); // 土星纹理 // 将坐标系绕Z轴旋转fSaturnSpin角度,控制土星自转 glRotatef(fSaturnSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.1f, 32, 32); // 土星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(1.9f*sin(DEG_TO_RAD*angle),0,1.9f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制天王星**********************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fUranusOrbit角度,控制天王星公转 glRotatef(fUranusOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(2.1f, 0.0f, 0.0f); // 将坐标系右移2.1f glBindTexture(GL_TEXTURE_2D, texture[9]); // 天王星纹理 // 将坐标系绕Z轴旋转fUranusSpin角度,控制天王星自转 glRotatef(fUranusSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.1f, 32, 32); // 天王星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(2.1f*sin(DEG_TO_RAD*angle),0,2.1f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制海王星**********************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // 开启纹理 glPushMatrix (); // 当前模型视图矩阵入栈 // 将坐标系绕Y轴旋转fNeptuneOrbit角度,控制海王星公转 glRotatef(fNeptuneOrbit , 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); // 将坐标系绕X轴旋转-90度 glTranslatef(2.3f, 0.0f, 0.0f); // 将坐标系右移2.3f glBindTexture(GL_TEXTURE_2D, texture[10]); // 海王星纹理 // 将坐标系绕Z轴旋转fNeptuneSpin角度,控制海王星自转 glRotatef(fNeptuneSpin , 0.0f, 0.0f, 1.0f); gluSphere(quadric, 0.08f, 32, 32); // 海王星球体 glPopMatrix (); glBegin(GL_LINE_LOOP); for(angle=0;angle<=360;angle++) glVertex3f(2.3f*sin(DEG_TO_RAD*angle),0,2.3f*cos(DEG_TO_RAD*angle)); glEnd(); /**********************************绘制月亮************************************************/ glDisable(GL_LIGHT0); glEnable(GL_TEXTURE_2D ); // glBindTexture(GL_TEXTURE_2D, texture[11]); // 月亮纹理 glPushMatrix (); // 将坐标系绕Y轴旋转fEarthOrbit角度,控制月亮跟随地球 glRotatef(fEarthOrbit , 0.0f, 1.0f, 0.0f); glTranslatef(1.1f, 0.0f, 0.0f); // 将坐标系右移1.1f // 将坐标系绕Y轴旋转fMoonOrbit角度,控制月亮公转 glRotatef(fMoonOrbit , 0.0f, 1.0f, 0.0f); glTranslatef(0.15f, 0.0f, 0.0f); // 将坐标系绕Y轴旋转fMoonSpin角度,控制月亮自转 glBindTexture(GL_TEXTURE_2D, texture[11]); glRotatef(fMoonSpin , 0.0f, 1.0f, 0.0f); gluSphere(quadric, 0.02, 32, 32); // 月亮球体 glPopMatrix (); // 控制各星球转动的速度 if( g_bOrbitOn == true ) { fSunSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f); fMercuSpin -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f); fMercuOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f); fVenusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 10.0f); fVenusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f); fEarthSpin -= g_fSpeedmodifier * (g_fElpasedTime * 100.0f); fEarthOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 20.0f); fMarsSpin -= g_fSpeedmodifier * (g_fElpasedTime * 30.0f); fMarsOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f); fJupiterSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f); fJupiterOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 35.0f); fSaturnSpin -= g_fSpeedmodifier * (g_fElpasedTime * 90.0f); fSaturnOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 25.0f); fUranusSpin -= g_fSpeedmodifier * (g_fElpasedTime * 70.0f); fUranusOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 15.0f); fNeptuneSpin -= g_fSpeedmodifier * (g_fElpasedTime * 40.0f); fNeptuneOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 5.0f); fMoonSpin -= g_fSpeedmodifier * (g_fElpasedTime * 50.0f); fMoonOrbit -= g_fSpeedmodifier * (g_fElpasedTime * 200.0f); } angle_Z += 0.01f; // 星空旋转 glutSwapBuffers(); // 交换双缓存 glFlush(); } void Reshape(int width, int height) { if (height==0) height=1; // 改变窗口 glViewport(0,0,width,height); // 设置视口 // 设置投影矩阵 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(viewer[0],viewer[1],viewer[2],viewer[3],viewer[4],-5,0,1,0); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 'r': case 'R': // 视点上下左右移动 if(viewer[0]=-6.0) viewer[0]-=0.5; break; case 'u': case 'U': if(viewer[1]=-6.0) viewer[1]-=0.1; break; case'+': case '=': // 加速,减速,暂停 g_fSpeedmodifier+=1.0f; glutPostRedisplay(); break; case ' ': g_bOrbitOn = !g_bOrbitOn; glutPostRedisplay(); break; case'-': //按'-'减小运行速度 g_fSpeedmodifier-=1.0f; glutPostRedisplay(); break; case VK_ESCAPE: // 按ESC键时退出 exit(0); break; default: break; } } void special_keys(int s_keys, int x, int y) { switch(s_keys) { case GLUT_KEY_F1: // 按F1键时切换窗口/全屏模式 if(isFullScreen) { glutReshapeWindow(WIN_WIDTH, WIN_HEIGHT); glutPositionWindow(30, 30); isFullScreen = FALSE; } else { glutFullScreen(); isFullScreen = TRUE; } break; case GLUT_KEY_RIGHT: // 视角上下左右旋转 if(viewer[3]=-3.0) viewer[3]-=0.1; break; case GLUT_KEY_UP: if(viewer[4]=-4.5) viewer[4]-=0.1; break; default: break; } } void mouse(int btn, int state, int x, int y) // 远近视角 { if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) viewer[2]+=0.3; if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN&&viewer;[2]>=-3.9) viewer[2]-=0.3; } void LoadBmp(char *filename, TEXTUREIMAGE *textureImg) // 载入图片 { int i, j; FILE *file; BMPFILEHEADER bmpFile; BMPINFOHEADER bmpInfo; int pixel_size; // 初始化纹理数据 textureImg->imgWidth = 0; textureImg->imgHeight = 0; if (textureImg->data != NULL) { delete []textureImg->data; } // 打开文件 file = fopen(filename, "rb"); if (file == NULL) { return; } // 获取文件头 rewind(file); fread(&bmpFile;, sizeof(BMPFILEHEADER), 1, file); fread(&bmpInfo;, sizeof(BMPINFOHEADER), 1, file); // 验证文件类型 if (bmpFile.bfType != 0x4D42) { return; } // 获取图像色彩数 pixel_size = bmpInfo.biBitCount >> 3; // 读取文件数据 textureImg->data = new unsigned char[bmpInfo.biWidth * bmpInfo.biHeight * pixel_size]; for(i = 0 ; i < bmpInfo.biHeight; i++) { fseek(file, bmpFile.bfOffBits + (bmpInfo.biHeight - i - 1) * bmpInfo.biWidth * pixel_size, SEEK_SET); for (j = 0; j data + (i * bmpInfo.biWidth + j) * pixel_size + 2, sizeof(unsigned char), 1, file); // 绿色分量 fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 1, sizeof(unsigned char), 1, file); // 蓝色分量 fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 0, sizeof(unsigned char), 1, file); // Alpha分量 if (pixel_size == 4) { fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 3, sizeof(unsigned char), 1, file); } } } // 记录图像相关参数 textureImg->imgWidth = bmpInfo.biWidth; textureImg->imgHeight = bmpInfo.biHeight; textureImg->byteCount = pixel_size; fclose(file); } // 程序主函数 void main(int argc, char** argv) { //读图片 LoadBmp("Picture//Sky.bmp" , &skyImg;); LoadBmp("Picture//Sun.bmp" , &sunImg;); LoadBmp("Picture//Ray.bmp" , &rayImg;); LoadBmp("Picture//Mercu.bmp" , &mercuImg;); LoadBmp("Picture//Venus.bmp" , &venusImg;); //金星 LoadBmp("Picture//Earth.bmp" , &earthImg;); LoadBmp("Picture//Mars.bmp" , &marsImg;); //火星 LoadBmp("Picture//Jupiter.bmp" , &jupiterImg;); //木星 LoadBmp("Picture//Saturn.bmp" , &saturnImg;); //土星 LoadBmp("Picture//Uranus.bmp" , &uranusImg;); //天王星 LoadBmp("Picture//Neptune.bmp" , &neptuneImg;); //海王星 LoadBmp("Picture//Moon.bmp" , &moonImg;); glutInit(&argc;, argv); // 初始化GLUT库 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); // 初始化显示模式 glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT); // 初始化窗口大小 glutInitWindowPosition(20,20); // 初始化窗口位置 GLuint window = glutCreateWindow(WIN_TITLE); // 建立窗口 InitGL(); // 初始化OpenGL glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(special_keys); glutMouseFunc(mouse); glutIdleFunc(Display); // 设置窗口空闲时的处理函数 glutMainLoop(); // 进入事件处理循环 }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值