| |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <GL/glew.h> |
| #include <GL/glu.h> |
| #include "readtex.h" |
| #include "skybox.h" |
| |
| |
| static int |
| load(GLenum target, const char *filename, |
| GLboolean flipTB, GLboolean flipLR) |
| { |
| GLint w, h; |
| GLenum format; |
| GLubyte *img = LoadRGBImage( filename, &w, &h, &format ); |
| if (!img) { |
| printf("Error: couldn't load texture image %s\n", filename); |
| return 0; |
| } |
| assert(format == GL_RGB); |
| |
| printf("Load cube face 0x%x: %s %d x %d\n", target, filename, w, h); |
| |
| /* <sigh> the way the texture cube mapping works, we have to flip |
| * images to make things look right. |
| */ |
| if (flipTB) { |
| const int stride = 3 * w; |
| GLubyte temp[3*1024]; |
| int i; |
| for (i = 0; i < h / 2; i++) { |
| memcpy(temp, img + i * stride, stride); |
| memcpy(img + i * stride, img + (h - i - 1) * stride, stride); |
| memcpy(img + (h - i - 1) * stride, temp, stride); |
| } |
| } |
| if (flipLR) { |
| const int stride = 3 * w; |
| GLubyte temp[3]; |
| GLubyte *row; |
| int i, j; |
| for (i = 0; i < h; i++) { |
| row = img + i * stride; |
| for (j = 0; j < w / 2; j++) { |
| int k = w - j - 1; |
| temp[0] = row[j*3+0]; |
| temp[1] = row[j*3+1]; |
| temp[2] = row[j*3+2]; |
| row[j*3+0] = row[k*3+0]; |
| row[j*3+1] = row[k*3+1]; |
| row[j*3+2] = row[k*3+2]; |
| row[k*3+0] = temp[0]; |
| row[k*3+1] = temp[1]; |
| row[k*3+2] = temp[2]; |
| } |
| } |
| } |
| |
| gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img); |
| free(img); |
| return 1; |
| } |
| |
| |
| GLuint |
| LoadSkyBoxCubeTexture(const char *filePosX, |
| const char *fileNegX, |
| const char *filePosY, |
| const char *fileNegY, |
| const char *filePosZ, |
| const char *fileNegZ) |
| { |
| GLuint tex; |
| |
| glGenTextures(1, &tex); |
| glBindTexture(GL_TEXTURE_CUBE_MAP, tex); |
| |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, |
| GL_LINEAR_MIPMAP_NEAREST); |
| |
| if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_X, filePosX, GL_TRUE, GL_TRUE)) |
| return 0; |
| if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE)) |
| return 0; |
| if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, 1+GL_FALSE, GL_TRUE)) |
| return 0; |
| if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, 1+GL_FALSE, GL_TRUE)) |
| return 0; |
| if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE)) |
| return 0; |
| if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, fileNegZ, GL_TRUE, GL_TRUE)) |
| return 0; |
| |
| return tex; |
| } |
| |
| |
| #define eps1 0.99 |
| #define br 20.0 /* box radius */ |
| |
| void |
| DrawSkyBoxCubeTexture(GLuint tex) |
| { |
| struct vertex { |
| float x, y, z, s, t, r; |
| }; |
| |
| static const struct vertex verts[24] = { |
| /* +X side */ |
| { br, -br, -br, 1.0, -eps1, -eps1 }, |
| { br, -br, br, 1.0, -eps1, eps1 }, |
| { br, br, br, 1.0, eps1, eps1 }, |
| { br, br, -br, 1.0, eps1, -eps1 }, |
| |
| /* -X side */ |
| { -br, br, -br, -1.0, eps1, -eps1 }, |
| { -br, br, br, -1.0, eps1, eps1 }, |
| { -br, -br, br, -1.0, -eps1, eps1 }, |
| { -br, -br, -br, -1.0, -eps1, -eps1 }, |
| |
| /* +Y side */ |
| { br, br, -br, eps1, 1.0, -eps1 }, |
| { br, br, br, eps1, 1.0, eps1 }, |
| { -br, br, br, -eps1, 1.0, eps1 }, |
| { -br, br, -br, -eps1, 1.0, -eps1 }, |
| |
| /* -Y side */ |
| { -br, -br, -br, -eps1, -1.0, -eps1 }, |
| { -br, -br, br, -eps1, -1.0, eps1 }, |
| { br, -br, br, eps1, -1.0, eps1 }, |
| { br, -br, -br, eps1, -1.0, -eps1 }, |
| |
| /* +Z side */ |
| { br, -br, br, eps1, -eps1, 1.0 }, |
| { -br, -br, br, -eps1, -eps1, 1.0 }, |
| { -br, br, br, -eps1, eps1, 1.0 }, |
| { br, br, br, eps1, eps1, 1.0 }, |
| |
| /* -Z side */ |
| { br, br, -br, eps1, eps1, -1.0 }, |
| { -br, br, -br, -eps1, eps1, -1.0 }, |
| { -br, -br, -br, -eps1, -eps1, -1.0 }, |
| { br, -br, -br, eps1, -eps1, -1.0 }, |
| }; |
| |
| static GLuint vbo = 0; |
| |
| if (!vbo ) { |
| glGenBuffersARB(1, &vbo); |
| glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo); |
| glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, |
| GL_STATIC_DRAW_ARB); |
| } |
| else { |
| glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo); |
| } |
| |
| glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); |
| |
| glVertexPointer(3, GL_FLOAT, sizeof(struct vertex), |
| (void *) offsetof(struct vertex, x)); |
| glTexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), |
| (void *) offsetof(struct vertex, s)); |
| glEnableClientState(GL_VERTEX_ARRAY); |
| glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
| |
| glBindTexture(GL_TEXTURE_CUBE_MAP, tex); |
| glEnable(GL_TEXTURE_CUBE_MAP); |
| |
| glDisable(GL_BLEND); |
| |
| glDrawArrays(GL_QUADS, 0, 24); |
| |
| glDisable(GL_TEXTURE_CUBE_MAP); |
| |
| glDisableClientState(GL_VERTEX_ARRAY); |
| glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
| |
| glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); |
| } |
| |