立方体环境贴图(Cube Mapping)之OpenGL原理
2016-03-19 21:56
666 查看
立方体纹理是一种特殊的纹理技术,它用6幅二维纹理图像构成一个以原点为中心的纹理立方体。对于每个片段,纹理坐标(s, t, r)被当作方向向量看待,每个纹理单元都表示从原点所看到的纹理立方体上的图像。
一个典型的立方环境贴图如下:
图1
其中,前、后、左、右、上、下为环境图的各个方位截图。X, Y, Z为设置OpenGL中设置Cubemap贴图的方位。
里面有点奇怪,是为什么上和下的方向是反的?那个因为OpenGL最开始支持贴图的方式是倒过来的,也就是
图2
为了使得前图能够正向,因此我们对图2进行旋转,从而得到图1。
下面是实例代码:
main.cpp //里面有采用自己写一个TexutreManager类来解析.png图片,这里不贴这个类的代码了。
vert文件
运行效果:
各个纹理
front
back
left
right
top
bottom
一个典型的立方环境贴图如下:
图1
其中,前、后、左、右、上、下为环境图的各个方位截图。X, Y, Z为设置OpenGL中设置Cubemap贴图的方位。
里面有点奇怪,是为什么上和下的方向是反的?那个因为OpenGL最开始支持贴图的方式是倒过来的,也就是
图2
为了使得前图能够正向,因此我们对图2进行旋转,从而得到图1。
下面是实例代码:
main.cpp //里面有采用自己写一个TexutreManager类来解析.png图片,这里不贴这个类的代码了。
#pragma comment(lib, "glew32.lib") #include <GL/glew.h> #include "textfile.h" #include <GL/glut.h> #include <iostream> #include "TextureManager.h" using namespace std; GLuint vShader, fShader; //顶点着色器对象 TextureManager gTM; GLuint textureID; GLuint programHandle; float rotateAngle = 0.0f; float rotateStep = 0.03f; float positionData[] = { -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f }; unsigned int indexData[] = { 0, 1, 2, 3, 6, 7, 4, 5, 1, 3, 5, 7, 0, 2, 4, 6, 3, 5, 4, 2, 1, 7, 6, 0 }; void initCubeMap() { glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); /* GLBITMAP* pos_x_img = gTM.GetTextureData("img/NEG_X.jpg"); GLBITMAP* neg_x_img = gTM.GetTextureData("img/POS_X.jpg"); GLBITMAP* pos_y_img = gTM.GetTextureData("img/NEG_Y.jpg"); GLBITMAP* neg_y_img = gTM.GetTextureData("img/POS_Y.jpg"); GLBITMAP* pos_z_img = gTM.GetTextureData("img/POS_Z.jpg"); GLBITMAP* neg_z_img = gTM.GetTextureData("img/NEG_Z.jpg"); */ GLBITMAP* pos_x_img = gTM.GetTextureData("img1/right.jpg"); GLBITMAP* neg_x_img = gTM.GetTextureData("img1/left.jpg"); GLBITMAP* pos_y_img = gTM.GetTextureData("img1/bottom.jpg"); GLBITMAP* neg_y_img = gTM.GetTextureData("img1/top.jpg"); GLBITMAP* pos_z_img = gTM.GetTextureData("img1/front.jpg"); GLBITMAP* neg_z_img = gTM.GetTextureData("img1/back.jpg"); if (pos_x_img == NULL || neg_x_img == NULL || pos_y_img == NULL || neg_y_img == NULL || pos_z_img == NULL || neg_z_img == NULL) { cerr << "Error: Loading images for the cube map" << endl; exit(-1); } glEnable(GL_TEXTURE_CUBE_MAP); glActiveTexture(GL_TEXTURE0); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, pos_x_img->rgb_mode, pos_x_img->w, pos_x_img->h, 0, pos_x_img->rgb_mode, GL_UNSIGNED_BYTE, pos_x_img->buf); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, neg_x_img->rgb_mode, neg_x_img->w, neg_x_img->h, 0, neg_x_img->rgb_mode, GL_UNSIGNED_BYTE, neg_x_img->buf); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, pos_y_img->rgb_mode, pos_y_img->w, pos_y_img->h, 0, pos_y_img->rgb_mode, GL_UNSIGNED_BYTE, pos_y_img->buf); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, neg_y_img->rgb_mode, neg_y_img->w, neg_y_img->h, 0, neg_y_img->rgb_mode, GL_UNSIGNED_BYTE, neg_y_img->buf); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, pos_z_img->rgb_mode, pos_z_img->w, pos_z_img->h, 0, pos_z_img->rgb_mode, GL_UNSIGNED_BYTE, pos_z_img->buf); glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, neg_z_img->rgb_mode, neg_z_img->w, neg_z_img->h, 0, neg_z_img->rgb_mode, GL_UNSIGNED_BYTE, neg_z_img->buf); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } void initShader(const char* VShaderFile, const char* FShaderFile) { const GLubyte* renderer = glGetString(GL_RENDERER); const GLubyte* vendor = glGetString(GL_VENDOR); const GLubyte* version = glGetString(GL_VERSION); const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION); GLint major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); cout << "GL Vendor: " << vendor << endl; cout << "GL Renderer: " << renderer << endl; cout << "GL Version(string): " << version << endl; cout << "GL Version (integer): " << major << "." << minor << endl; cout << "GLSL Version: " << glslVersion << endl; vShader = glCreateShader(GL_VERTEX_SHADER); if (0 == vShader) { cerr << "ERROR: Create vertex shader failed" << endl; exit(1); } const GLchar* vShaderCode = textFileRead(VShaderFile); cout << "vShaderCode: " << vShaderCode << endl; const GLchar* vCodeArray[1] = {vShaderCode}; glShaderSource(vShader, 1, vCodeArray, NULL); glCompileShader(vShader); GLint compileResult; glGetShaderiv(vShader, GL_COMPILE_STATUS, &compileResult); if (GL_FALSE == compileResult) { GLint logLen; glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 0) { char* log = (char*)malloc(logLen); GLsizei written; glGetShaderInfoLog(vShader, logLen, &written, log); cerr << "vertex shader compile log: " << endl; cerr << log << endl; free(log); } } fShader = glCreateShader(GL_FRAGMENT_SHADER); if (0 == fShader) { cerr << "ERROR: Create fragment shader failed" << endl; exit(1); } const GLchar* fShaderCode = textFileRead(FShaderFile); cout << "fShaderCode: " << fShaderCode << endl; const GLchar* fCodeArray[1] = {fShaderCode}; glShaderSource(fShader, 1, fCodeArray, NULL); glCompileShader(fShader); glGetShaderiv(fShader, GL_COMPILE_STATUS, &compileResult); if (GL_FALSE == compileResult) { GLint logLen; glGetShaderiv(fShader, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 0) { char* log = (char*)malloc(logLen); GLsizei written; glGetShaderInfoLog(fShader, logLen, &written, log); cerr << "fragment shader compile log: " << endl; cerr << log << endl; free(log); } } programHandle = glCreateProgram(); if (!programHandle) { cerr << "Error: create program fialed" << endl; exit(1); } glAttachShader(programHandle, vShader); glAttachShader(programHandle, fShader); glBindAttribLocation(programHandle, 0, "VertexPosition"); glBindAttribLocation(programHandle, 1, "VertexColor"); glLinkProgram(programHandle); GLint linkStatus; glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus); if (GL_FALSE == linkStatus) { cerr << "ERROR: link shader program failed" << endl; GLint logLen; glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 0) { char* log = (char*)malloc(logLen); GLsizei written; glGetProgramInfoLog(programHandle, logLen, &written, log); cerr << "Program log: " << endl; cerr << log << endl; } } else { glUseProgram(programHandle); } } void init() { GLenum err = glewInit(); if (GLEW_OK != err) { cout << "Error initializing GLEW: " << glewGetErrorString(err) << endl; } initShader("basic.vert", "basic.frag"); initCubeMap(); } void resize(int width, int height) // Resize And Initialize The GL Window { if (height==0) // Prevent A Divide By Zero By { height=1; // Making Height Equal One } glViewport(0,0,width,height); // Reset The Current Viewport glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix // Calculate The Aspect Ratio Of The Window gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix glLoadIdentity(); // Reset The Modelview Matrix glTranslatef(0.0f, 0.0f, -3.0f); //glRotatef(-180, 0.0, 0.0, 1.0); } void setUniforms() { int textureLoc = glGetUniformLocation(programHandle, "cubemap1"); glUniform1i(textureLoc, 0); int eyeposLoc = glGetUniformLocation(programHandle, "eyepos"); glUniform3f(eyeposLoc, 0, 0.0, 1.0f); } void display() { setUniforms(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glRotatef(rotateAngle, 0, 1, 0); glEnable(GL_TEXTURE_CUBE_MAP); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); //glutSolidTeapot(1.0); glutSolidSphere(1.0, 60, 60); //glutSolidCube(1.0); /* glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 3*sizeof(GL_FLOAT), positionData); glEnableClientState(GL_INDEX_ARRAY); glVertexPointer(1, GL_INT, sizeof(GL_INT), indexData); glDrawArrays(GL_QUADS, 0, 8); */ glutSwapBuffers(); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: glDeleteShader(vShader); glUseProgram(0); break; } } void onTimer(int value) { rotateAngle = rotateAngle + rotateStep; if (rotateAngle >= 360) { rotateAngle = 0; } display(); glutTimerFunc(100, onTimer, 0); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GL_DOUBLE | GLUT_RGB); glutInitWindowSize(600, 600); glutInitWindowPosition(100, 100); glutCreateWindow("GLSL Test: Draw a triangle"); init(); glutDisplayFunc(display); glutTimerFunc(100, onTimer, 0); glutKeyboardFunc(keyboard); glutReshapeFunc(resize); glutMainLoop(); return 0; }
vert文件
uniform vec4 eyepos; varying vec3 reflectvec; void main(void) { //vec4 pos = normalize(gl_ModelViewMatrix * gl_Vertex); //pos = pos / pos.w; vec4 pos = gl_ModelViewMatrix * gl_Vertex; vec3 eyevec = normalize(eyepos.xyz - pos.xyz); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); reflectvec = reflect(-eyevec, norm); gl_Position = ftransform(); }frag文件
uniform samplerCube cubemap1; varying vec3 reflectvec; void main(void) { vec4 texcolor = textureCube(cubemap1, reflectvec.stp); gl_FragColor = texcolor; }
运行效果:
各个纹理
front
back
left
right
top
bottom
相关文章推荐
- 【Android开发1-1】手动创建第一个APP:HelloWorld
- android 屏幕适配
- Material Design (四),AppBarLayout的使用
- iOS:实现图片的无限轮播(二)---之使用第三方库SDCycleScrollView
- IOS 公共类-MyMBProgressUtil Progress显示
- Android手机屏幕分辨率适配方案
- unity c# LINQ查询
- unity c# Lambda表达式
- unity c# 泛型委托
- unity c# 标准事件模式
- unity c# 事件
- Android图像处理之Paint
- unity c# 接口
- Android中异步加载方案
- Android中使用Post带参数请求的方法
- [android] 采用GET方式提交数据到服务器
- IOS 使用XIB 自定义View
- Android中创建触摸点使之随点击移动
- Swift中的switch 和 do while
- Android中实现点击变换图片