OpenGL天空贴图以及反射纹理映射即镜面反射
编程中一个好的天空贴图会给玩家带来舒适的感觉,还有那对周围物体的反射光映射到球、等物体上或许是一个特别愉悦的事件,然而这在opengl里实现又不太难,
请看下面的代码:
#include <GL\glew.h>
#include <GL\GLAUX.H>
#define GLUT_DISABLE_ATEXIT_HACK
#include <gl\glut.h>
#include <stdio.h>
#include <stdlib.h>// 摄像机参数
static float cameraTheta = 0, cameraPhi = 0;
static int mouseX = 0, mouseY = 0, mouseDownX = 0, mouseDownY = 0;//天空渲染模式
static int cubeMapAvailable = 0;//纹理
static UINT textureObjectCubeMap;
static UINT textureObjects2d[6];//接收反射光物体参数static int rotateObject = 1;
static int objectAngle = 0;//渲染函数
static void drawSkybox(void);
static void drawSkyboxCubeEnvironment(void);//初始化函数
static BOOL initSkybox(void);
static void shutdownSkybox(void);//加载bmp图片
//swap_bytes用于翻转倒* BMP文件BOOL loadImage(GLenum target, const char *fileName);
#define SWAP_BYTES(b1,b2) (b1)=(b1)^(b2);(b2)=(b1)^(b2);(b1)=(b1)^(b2);static void onTimer(int value);
static void onDisplay(void);
static void onMouseMoveButtonDown(int x, int y);
static void onMouseDown(int b, int s, int x, int y);
static void onSpecialKey(int key, int x, int y);
static void onKey(unsigned char key, int x, int y);//用立方体环境映射绘制天空盒 Skybox的立方体绘制两三角扇形
//以立方体的相对角为中心
void drawSkyboxCubeEnvironment(void)
{drawSkybox();//绘制天空盒//设置对象矩阵glMatrixMode(GL_MODELVIEW);glPushMatrix();glLoadIdentity();glTranslatef(0, 0, -8);glRotatef(cameraPhi, 1, 0, 0);glRotatef(cameraTheta, 0, 1, 0);//旋转glRotatef((float)objectAngle, 1, 0, 0);glRotatef((float)2 * objectAngle, 0, 1, 0);//旋转纹理矩阵匹配摄像机矩阵//mode 指定哪一个矩阵堆栈是下一个矩阵操作的目标,//可选值: GL_MODELVIEW、GL_PROJECTION、GL_TEXTURE.glMatrixMode(GL_TEXTURE);glPushMatrix();glLoadIdentity();glRotatef(-cameraTheta, 0, 1, 0);glRotatef(-cameraPhi, 1, 0, 0);//绘制映射物体if (cubeMapAvailable){glDisable(GL_TEXTURE_2D);glEnable(GL_DEPTH_TEST);//开启深度测试glEnable(GL_TEXTURE_CUBE_MAP_ARB);//开启映射glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, textureObjectCubeMap);//绑定映射纹理//绘制反光物体//建立映射坐标生成glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);glEnable(GL_TEXTURE_GEN_S);glEnable(GL_TEXTURE_GEN_T);glEnable(GL_TEXTURE_GEN_R);glutSolidSphere(3, 16, 16);//禁用反射映射glDisable(GL_TEXTURE_GEN_S);glDisable(GL_TEXTURE_GEN_T);glDisable(GL_TEXTURE_GEN_R);glDisable(GL_DEPTH_TEST);//关闭深度测试}glPopMatrix();//恢复模型矩阵glMatrixMode(GL_MODELVIEW);glPopMatrix();//恢复矩阵}//采用六面和六2D纹理绘制天空盒
void drawSkybox(void)
{//禁用映射glDisable(GL_TEXTURE_CUBE_MAP_ARB);glEnable(GL_TEXTURE_2D);float skyHei = 20; //天空的高度float skyLen = 40; //天空的长度float skyWid = 40; //天空的宽度//后面glBindTexture(GL_TEXTURE_2D, textureObjects2d[0]);glBegin(GL_TRIANGLE_FAN);glTexCoord2f(1, 0);glVertex3f(skyLen, skyHei, skyWid);glTexCoord2f(1, 1);glVertex3f(skyLen, -skyHei, skyWid);glTexCoord2f(0, 1);glVertex3f(-skyLen, -skyHei, skyWid);glTexCoord2f(0, 0);glVertex3f(-skyLen, skyHei, skyWid);glEnd();//前面glBindTexture(GL_TEXTURE_2D, textureObjects2d[1]);glBegin(GL_TRIANGLE_FAN);glTexCoord2f(1, 0);glVertex3f(-skyLen, skyHei, -skyWid);glTexCoord2f(1, 1);glVertex3f(-skyLen, -skyHei, -skyWid);glTexCoord2f(0, 1);glVertex3f(skyLen, -skyHei, -skyWid);glTexCoord2f(0, 0);glVertex3f(skyLen, skyHei, -skyWid);glEnd();//右面glBindTexture(GL_TEXTURE_2D, textureObjects2d[2]);glBegin(GL_TRIANGLE_FAN);glTexCoord2f(1, 0);glVertex3f(skyLen, skyHei, -skyWid);glTexCoord2f(1, 1);glVertex3f(skyLen, -skyHei, -skyWid);glTexCoord2f(0, 1);glVertex3f(skyLen, -skyHei, skyWid);glTexCoord2f(0, 0);glVertex3f(skyLen, skyHei, skyWid);glEnd();//左面glBindTexture(GL_TEXTURE_2D, textureObjects2d[3]);glBegin(GL_TRIANGLE_FAN);glTexCoord2f(1, 0);glVertex3f(-skyLen, skyHei, skyWid);glTexCoord2f(1, 1);glVertex3f(-skyLen, -skyHei, skyWid);glTexCoord2f(0, 1);glVertex3f(-skyLen, -skyHei, -skyWid);glTexCoord2f(0, 0);glVertex3f(-skyLen, skyHei, -skyWid);glEnd();//顶面glBindTexture(GL_TEXTURE_2D, textureObjects2d[4]);glBegin(GL_TRIANGLE_FAN);glTexCoord2f(0, 1);glVertex3f(-skyLen, skyHei, skyWid);glTexCoord2f(0, 0);glVertex3f(-skyLen, skyHei, -skyWid);glTexCoord2f(1, 0);glVertex3f(skyLen, skyHei, -skyWid);glTexCoord2f(1, 1);glVertex3f(skyLen, skyHei, skyWid);glEnd();//底面glBindTexture(GL_TEXTURE_2D, textureObjects2d[5]);glBegin(GL_TRIANGLE_FAN);glTexCoord2f(0, 1);glVertex3f(-skyLen, -skyHei, -skyWid);glTexCoord2f(0, 0);glVertex3f(-skyLen, -skyHei, skyWid);glTexCoord2f(1, 0);glVertex3f(skyLen, -skyHei, skyWid);glTexCoord2f(1, 1);glVertex3f(skyLen, -skyHei, -skyWid);glEnd();glDisable(GL_TEXTURE_2D);//关闭纹理
}void onDisplay(void)
{float w = (float)glutGet(GLUT_WINDOW_WIDTH), h = (float)glutGet(GLUT_WINDOW_HEIGHT);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(100.0, w / h, 1, 100);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glRotatef(cameraPhi, 1, 0, 0);glRotatef(cameraTheta, 0, 1, 0);glClear(GL_DEPTH_BUFFER_BIT);drawSkyboxCubeEnvironment();glutSwapBuffers();glutPostRedisplay();
}//定时器
void onTimer(int value)
{if (rotateObject){objectAngle = (objectAngle + 1) % 360;}glutTimerFunc(10, onTimer, 0);
}//鼠标事件
void onMouseMoveButtonDown(int x, int y)
{cameraTheta += (float)(x - mouseDownX);cameraPhi += (float)(y - mouseDownY);cameraPhi = max(-90, min(cameraPhi, 90));mouseDownX = x;mouseDownY = y;
}void onMouseDown(int b, int s, int x, int y)
{if (s == GLUT_DOWN){mouseDownX = x;mouseDownY = y;glutMotionFunc(onMouseMoveButtonDown);}else{glutMotionFunc(0);}
}void onSpecialKey(int key, int x, int y)
{switch (key){case GLUT_KEY_RIGHT:cameraTheta = cameraTheta + 5;while (cameraTheta > 360) cameraTheta -= 360;break;case GLUT_KEY_LEFT:cameraTheta = cameraTheta - 5;while (cameraTheta < 0) cameraTheta += 360;break;case GLUT_KEY_UP:cameraPhi = cameraPhi + 5;if (cameraPhi > 90) cameraPhi = 90;break;case GLUT_KEY_DOWN:cameraPhi = cameraPhi - 5;if (cameraPhi < -90) cameraPhi = -90;break;};
}void onKey(unsigned char key, int x, int y)
{switch (key){case VK_ESCAPE:exit(0); break;case 'r':case 'R':rotateObject = !rotateObject;break;};
}//加载bmp图片
BOOL loadImage(GLenum target, const char *fileName)
{int i, topRow, bottomRow;AUX_RGBImageRec *image = auxDIBImageLoad(fileName);if (image != 0){topRow = 0;bottomRow = 3 * image->sizeX*(image->sizeY - 1);while (topRow < bottomRow){for (i = 0; i<3 * image->sizeX; i++){SWAP_BYTES(image->data[bottomRow + i], image->data[topRow + i]);}bottomRow -= 3 * image->sizeX;topRow += 3 * image->sizeX;}glTexImage2D(target, 0, 3, image->sizeX, image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data);free(image->data);free(image);return TRUE;}else{return FALSE;}
}//初始化
BOOL initSkybox(void)
{int i;int clampMode;BOOL succeeded = GL_TRUE;char *imageFiles[] = { "data/image1.bmp", "data/image2.bmp", "data/image3.bmp", "data/image4.bmp", "data/image5.bmp", "data/image6.bmp" };glGenTextures(6, textureObjects2d);glGenTextures(1, &textureObjectCubeMap);//单位化glEnable(GL_NORMALIZE);//如果我们能用gl_clamp_to_edge//判定是否支持特定的OpenGL扩展//extension是指定要测试的OpenGL扩展的名称if (glutExtensionSupported("GL_EXT_texture_edge_clamp")){clampMode = GL_CLAMP_TO_EDGE;//去除接缝间的空隙边框是否处理?(不处理)}else{clampMode = GL_CLAMP;}//生成 2d texturesfor (i = 0; i<6; i++){glBindTexture(GL_TEXTURE_2D, textureObjects2d[i]);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);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, clampMode);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampMode);//去除接缝间的空隙边框是否处理?(不处理)succeeded = succeeded && loadImage(GL_TEXTURE_2D, imageFiles[i]);}//生成多维数据集映射,如果支持if (glutExtensionSupported("GL_ARB_texture_cube_map")){cubeMapAvailable = 1;glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, textureObjectCubeMap);glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);succeeded = succeeded && loadImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, imageFiles[0]);succeeded = succeeded && loadImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, imageFiles[1]);succeeded = succeeded && loadImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, imageFiles[2]);succeeded = succeeded && loadImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, imageFiles[3]);succeeded = succeeded && loadImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, imageFiles[4]);succeeded = succeeded && loadImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, imageFiles[5]);}else{cubeMapAvailable = 0;}return succeeded;}// 删除内存
void shutdownSkybox(void)
{glDeleteTextures(6, textureObjects2d);glDeleteTextures(1, &textureObjectCubeMap);
}int main(int argc, char **argv)
{glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);glutCreateWindow("天空盒及照在物体上的反射光");glutReshapeWindow(1366, 768);glutDisplayFunc(onDisplay);glutMouseFunc(onMouseDown);glutSpecialFunc(onSpecialKey);glutKeyboardFunc(onKey);glutTimerFunc(10, onTimer, 0);if (!initSkybox()){shutdownSkybox();return 0;}glutMainLoop();shutdownSkybox();return 0;
}
实验结果截图:
OpenGL天空贴图以及反射纹理映射即镜面反射相关推荐
- OpenGL立方体贴图
OpenGL 立方贴图 Copyright NVIDIA Corporation, 1999. Commercial publication in written, electronic, or ot ...
- OpenGL 立方贴图
OpenGL 立方贴图 Copyright NVIDIA Corporation, 1999. Commercial publication in written, electronic, or ot ...
- OpenGL 立方体贴图Cubemaps
OpenGL立方体贴图Cubemaps 立方体贴图Cubemaps简介 创建立方体贴图 天空盒 加载天空盒 显示天空盒 优化 环境映射 反射 折射 动态环境贴图 立方体贴图Cubemaps简介 我们已 ...
- openGL环境贴图
openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.代码 1.主程序 二.着色器程序 1.顶点着色器 2.片元着色器 运行效果 总结 源码下载 前言 在照明和材质章节中,我们考虑了 ...
- 使用OpenGL 立方体贴图
openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.OpenGL 立方体贴图 二.使用步骤 1.代码 2.着色器程序 运行结果 注意 源码下载 参考 前言 对于室外3D 场景,通常 ...
- OpenGL 位移贴图实例
OpenGL 位移贴图 先上图,再解答. 按下D键 完整主要的源代码 源代码剖析 先上图,再解答. 按下D键 完整主要的源代码 #include <vmath.h> #include &l ...
- OpenGL渲染纹理和平面反射
OpenGL渲染纹理和平面反射 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <stdio.h> #include "GL ...
- OpenGL阴影贴图
OpenGL阴影贴图 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <stdio.h> #include "GL/glus ...
- OpenGL天空游戏
OpenGL天空游戏 OpenGL天空游戏简介 源代码剖析 主要源代码 OpenGL天空游戏简介 天空游戏是一种在视觉上放大场景的方法,通过在环绕摄像机 360 度的观众周围创建纹理来使其更具表现力. ...
最新文章
- 有了这款可视化工具,Java 应用性能调优 so easy。。。
- ubunu16.04 TensorFlow object detection API 应用配置
- 工作107:插入请求头
- 最全面的Android Studio使用教程【申明:来源于网络】
- apache是干嘛用的_同学,其实用免费版的IDEA来创建SpringBoot项目挺方便的...
- 实操教程|Pytorch - 弹性训练极简实现( 附源码)
- win10 联想键盘快捷键关闭_如何关闭联想台式机电脑USB键盘的FN功能
- Linux内核编译 —— 配置文件
- java线程同步机制,实现同步锁
- 返利网app android版
- 【stm32CubeMX】STM32F103c8t6串口通信
- e4e反演框架:Designing an Encoder for StyleGAN Image Manipulation
- Python —对象的浅拷贝和深拷贝
- 钉钉走出国门,火遍全球离不开它的支持
- Beats:为 Filebeat 配置 inputs
- 成功中标 荣联为中国检科院打造一站式生信服务平台
- Windows系统怎么使用TeamViewer打印
- 美国知名科技博客简介
- Anaconda画图中文和负号乱码问题
- cloc JAVA文件_Cloc简介
热门文章
- suite No.1 , BWV 1007, In G:Prelude
- linux触摸屏信息,如何使用Linux获取触摸屏原始数据的坐标
- 启发主义——深入神经网络(Inceptionism: Going Deeper into Neural Networks)
- Python教程大全之如何绘制3D曲面图 3D Surface plot
- 今天最有成就感的事:教会一个60多岁的美国工程师说hehe
- 如何找到你喜欢的Premiere的动态图形模板
- Linux内文件编辑
- python自然语言处理安装NLRK(自然语言工具包)
- 【建议收藏】超详细ArcGIS中制作剖面图讲解(附练习数据)
- NetApp Ontap初始化配置详解