(此节内容对应NEHE教程第23课)
把环境纹理包裹在你的3D模型上,让它看起来象反射了周围的场景一样。
球体环境映射是一个创建快速金属反射效果的方法
首先,你需要一幅球体环境映射图,用来把它映射到球体上。在Photoshop中打开一幅图并选择所有的像素,创建它的一个复制。
接着,我们把图像变为2的幂次方大小,一般为128x128或256x256。
最后使用扭曲(distort)滤镜,并应用球体效果。然后把它保存为Reflect.bmp文件。
如右图上面的为背景的图片,下面为经过球面滤镜处理过的,用于进行球面贴图的纹理
对于球面映射往往我们希望背景图片是不变的,前面球面是可以转动的,因此适当的PUSH 与POP 视图模型 可以带到效果
原始图片 处理后图片 合成后效果
#include "header.h" int part1; int part2; int p1=0; int p2=1; GLfloat xrot; GLfloat yrot; GLfloat xspeed; GLfloat yspeed; GLfloat z=-10.0f; GLUquadricObj *quadratic; GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f }; GLuint filter; GLuint texture[6]; GLuint object=1; AUX_RGBImageRec *LoadBMP(char *Filename) { FILE *File=NULL; if (!Filename) { return NULL; } File=fopen(Filename,"r"); if (File) { fclose(File); return auxDIBImageLoad(Filename); } return NULL; } int loop=0; int LoadGLTextures() { int Status=FALSE; AUX_RGBImageRec *TextureImage[2]; memset(TextureImage,0,sizeof(void *)*2); if ((TextureImage[0]=LoadBMP("Data/BG.bmp")) && (TextureImage[1]=LoadBMP("Data/Reflect.bmp"))) { Status=TRUE; glGenTextures(6, &texture[0]); for ( loop=0; loop<2; loop++) { // Create Nearest Filtered Texture glBindTexture(GL_TEXTURE_2D, texture[loop]); // Gen Tex 0 and 1 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data); // Create Linear Filtered Texture glBindTexture(GL_TEXTURE_2D, texture[loop+2]); // Gen Tex 2 and 3 4 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data); // Create MipMapped Texture glBindTexture(GL_TEXTURE_2D, texture[loop+4]); // Gen Tex 4 and 5 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data); } for (loop=0; loop<2; loop++) { if (TextureImage[loop]) { if (TextureImage[loop]->data) { free(TextureImage[loop]->data); } free(TextureImage[loop]); } } } return Status; } GLvoid ReSizeGLScene(GLsizei width, GLsizei height) { if (height==0) { height=1; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Calculate The Aspect Ratio Of The Window gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int InitGL(void) { if (!LoadGLTextures()) { return FALSE; } glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); glEnable(GL_LIGHT1); quadratic=gluNewQuadric(); gluQuadricNormals(quadratic, GLU_SMOOTH); gluQuadricTexture(quadratic, GL_TRUE); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); return TRUE; } void glDrawCube() { glBegin(GL_QUADS); // Front Face glNormal3f( 0.0f, 0.0f, 0.5f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Back Face glNormal3f( 0.0f, 0.0f,-0.5f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Face glNormal3f( 0.0f, 0.5f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Bottom Face glNormal3f( 0.0f,-0.5f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Right Face glNormal3f( 0.5f, 0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Left Face glNormal3f(-0.5f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); } void DrawGLScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,z); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glBindTexture(GL_TEXTURE_2D, texture[filter+(filter+1)]); glPushMatrix(); glRotatef(xrot,1.0f,0.0f,0.0f); glRotatef(yrot,0.0f,1.0f,0.0f); switch(object) { case 0: glDrawCube(); break; case 1: glTranslatef(0.0f,0.0f,-1.5f); gluCylinder(quadratic,1.0f,1.0f,3.0f,32,32); break; case 2: gluSphere(quadratic,1.3f,32,32); break; case 3: glTranslatef(0.0f,0.0f,-1.5f); gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32); break; }; glPopMatrix(); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glBindTexture(GL_TEXTURE_2D, texture[filter*2]); glPushMatrix(); glTranslatef(0.0f, 0.0f, -24.0f); glBegin(GL_QUADS); glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-13.3f, -10.0f, 10.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 13.3f, -10.0f, 10.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 13.3f, 10.0f, 10.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-13.3f, 10.0f, 10.0f); glEnd(); glPopMatrix(); xrot+=xspeed; yrot+=yspeed; glFlush(); } void rotate() { glutPostRedisplay(); } void keyboard(unsigned char key,int x,int y) { switch (key) { case 'L': glEnable(GL_LIGHTING); glutPostRedisplay(); break; case 'l': glDisable(GL_LIGHTING); glutPostRedisplay(); break; case ' ': object++; if(object>5) object=0; glutPostRedisplay(); break; case 'F': filter+=1; if (filter>2) { filter=0; } glutPostRedisplay(); break; case 'W': yspeed+=0.01f; glutIdleFunc(rotate); break; case 'S': yspeed-=0.01f; glutIdleFunc(rotate); break; case 'A': xspeed+=0.01f; glutIdleFunc(rotate); break; case 'D': xspeed-=0.01f; glutIdleFunc(rotate); break; case 'Z': z-=0.01f; glutIdleFunc(rotate); break; case 'X': z+=0.01f; glutIdleFunc(rotate); break; case 'R': glutIdleFunc(NULL); break; } } int main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(800,600); glutInitWindowPosition(100,100); glutCreateWindow("球面映射"); InitGL(); glutDisplayFunc(DrawGLScene); glutKeyboardFunc(keyboard); glutReshapeFunc(ReSizeGLScene); glutMainLoop(); }
相关推荐
OpenGL球面映射是一种在3D图形编程中广泛使用的纹理映射技术,它允许我们将二维纹理贴在三维模型,特别是球体表面,创造出逼真的视觉效果。这种技术在虚拟现实、天文学模拟、地球仪渲染等领域有着广泛应用。下面将...
18:二次几何体 19:粒子系统 20:蒙板 21:线的游戏 22:凹凸映射 23:球面映射 24:扩展 25:变形 26:反射 27:影子 28:贝塞尔曲面 29:Blt函数 30:碰撞检测 31:模型加载 32:拾取游戏 33:TGA文件 34:地形 ...
OpenGL是计算机图形学中的一种广泛应用的编程接口,用于在各种操作系统和硬件上生成二维和三维图像。本主题主要探讨如何使用OpenGL进行球体的绘制以及如何应用贴图技术为球体添加纹理,使得渲染出的球体更加真实。 ...
球面等距模型就是一种常用的校正方法,它通过将图像投影到一个理想的球面上,然后将球面上的点映射回平面上,从而减少或消除畸变。 在实现鱼眼矫正的过程中,有几个关键点需要考虑: 1. **坐标转换**:首先,我们...
总之,OpenGL球面倒影贴图是利用纹理映射技术模拟真实世界反射的一种方法,通过精心设计的着色器和预处理的环境纹理,可以在3D场景中创造出逼真的反射效果。学习和实践这个技术对于提升3D图形编程能力非常有帮助。
支持如下: (1)opengl es绘制三角形拼成球体 (2)图片作为纹理映射到整个球面上 (3)双点触控缩放球体 (4)拖动旋转球体
- **曲面绘制**:学习如何在OpenGL中绘制经过球面映射的曲面。 #### 二十七、令牌、扩展、剪切测试及TGA加载 本章节涵盖令牌、扩展、剪切测试及TGA文件加载等内容。 **主要内容**: - **令牌技术**:了解令牌的...
OpenGL中的纹理映射是计算机图形学中的一个重要概念,它用于增强3D模型的表面细节,模拟现实世界中的光照效果。纹理映射通过将纹理图案应用到物体表面,使得原本简单的几何形状看起来更加真实和丰富。 纹理映射的...
OpenGL是一种强大的图形库,用于在各种操作系统和硬件平台上创建2D和3D图形。这个"OpenGL.rar"压缩包包含了关于如何使用OpenGL实现...通过学习和理解这段代码,开发者可以深入理解OpenGL如何进行3D图形绘制和交互操作。
OpenGL是一种强大的图形编程接口,广泛用于创建复杂的3D图形和应用程序。C#是.NET框架下常用的编程语言,而CSGL(C# OpenGL)库则为C#开发者提供了一...深入学习OpenGL和CSGL,你可以创建更加丰富和动态的3D应用程序。
综上所述,基于OpenGL和GLSL的鱼眼全景图实现涉及到图像处理、3D图形编程和着色器技术等多个方面,通过精心设计的顶点和片段着色器,以及合理的纹理映射,我们可以成功地将二维的全景图转化为具有鱼眼视觉效果的三维...
3. 纹理映射:使用`glTexImage2D`加载和应用2D纹理,提升3D模型的视觉效果。 4. OpenGL的矩阵操作:通过变换矩阵实现球体的自动旋转,涉及`glRotatef`等函数。 5. Pascal封装的OpenGL接口:`gl.pas`文件提供了Pascal...
### OpenGL下三维模型的显示与自由旋转关键技术解析 #### 一、三维模型数据的读取 在本研究中,为了实现在OpenGL环境下显示并自由旋转三维模型的目标,首先需要解决的问题是如何有效地读取三维模型数据。DXF...
在地球模型中,片段着色器可能使用球面映射或者立方体贴图技术来应用地球纹理,模拟海洋、陆地、云层等不同的地理特征。 4. **纹理映射**:为了使地球看起来真实,通常需要一个地球纹理图像,这可以是一个高分辨率...
首先,Trackball算法的核心是将屏幕坐标映射到一个球面上,然后计算鼠标点击和释放时的两个点在球面上的对应位置。这两个点确定了一个球面三角形,通过这个三角形我们可以找到旋转轴和旋转角度。旋转轴是球心与...
3. **绘制球体**: 要绘制球体,可以使用球面坐标系统,将球体上的每个点映射到笛卡尔坐标系统。这通常涉及到三角网格的生成,将球体表面划分为多个三角形面片。每个面片的顶点坐标可以通过球体半径、经度和纬度计算...