1
2
3#include <assert.h>
4#include <stdio.h>
5#include <stddef.h>
6#include <stdlib.h>
7#include <string.h>
8#include <GL/glew.h>
9#include "readtex.h"
10#include "skybox.h"
11
12
13static int
14load(GLenum target, const char *filename,
15     GLboolean flipTB, GLboolean flipLR)
16{
17   GLint w, h;
18   GLenum format;
19   GLubyte *img = LoadRGBImage( filename, &w, &h, &format );
20   if (!img) {
21      printf("Error: couldn't load texture image %s\n", filename);
22      return 0;
23   }
24   assert(format == GL_RGB);
25
26   printf("Load cube face 0x%x: %s %d x %d\n", target, filename, w, h);
27
28   /* <sigh> the way the texture cube mapping works, we have to flip
29    * images to make things look right.
30    */
31   if (flipTB) {
32      const int stride = 3 * w;
33      GLubyte temp[3*1024];
34      int i;
35      for (i = 0; i < h / 2; i++) {
36         memcpy(temp, img + i * stride, stride);
37         memcpy(img + i * stride, img + (h - i - 1) * stride, stride);
38         memcpy(img + (h - i - 1) * stride, temp, stride);
39      }
40   }
41   if (flipLR) {
42      const int stride = 3 * w;
43      GLubyte temp[3];
44      GLubyte *row;
45      int i, j;
46      for (i = 0; i < h; i++) {
47         row = img + i * stride;
48         for (j = 0; j < w / 2; j++) {
49            int k = w - j - 1;
50            temp[0] = row[j*3+0];
51            temp[1] = row[j*3+1];
52            temp[2] = row[j*3+2];
53            row[j*3+0] = row[k*3+0];
54            row[j*3+1] = row[k*3+1];
55            row[j*3+2] = row[k*3+2];
56            row[k*3+0] = temp[0];
57            row[k*3+1] = temp[1];
58            row[k*3+2] = temp[2];
59         }
60      }
61   }
62
63   gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img);
64   free(img);
65   return 1;
66}
67
68
69GLuint
70LoadSkyBoxCubeTexture(const char *filePosX,
71                      const char *fileNegX,
72                      const char *filePosY,
73                      const char *fileNegY,
74                      const char *filePosZ,
75                      const char *fileNegZ)
76{
77   GLuint tex;
78
79   glGenTextures(1, &tex);
80   glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
81
82   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
83   glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
84                   GL_LINEAR_MIPMAP_NEAREST);
85
86   if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_X, filePosX, GL_TRUE, GL_TRUE))
87      return 0;
88   if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
89      return 0;
90   if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, GL_TRUE, GL_TRUE))
91      return 0;
92   if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, GL_TRUE, GL_TRUE))
93      return 0;
94   if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
95      return 0;
96   if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, fileNegZ, GL_TRUE, GL_TRUE))
97      return 0;
98
99   return tex;
100}
101
102
103#define eps1 0.99
104#define br   20.0  /* box radius */
105
106void
107DrawSkyBoxCubeTexture(GLuint tex)
108{
109   struct vertex {
110      float x, y, z, s, t, r;
111   };
112
113   static const struct vertex verts[24] = {
114      /* +X side */
115      { br, -br, -br,  1.0, -eps1, -eps1 },
116      { br, -br,  br,  1.0, -eps1,  eps1 },
117      { br,  br,  br,  1.0,  eps1,  eps1 },
118      { br,  br, -br,  1.0,  eps1, -eps1 },
119
120      /* -X side */
121      { -br,  br, -br,  -1.0,  eps1, -eps1 },
122      { -br,  br,  br,  -1.0,  eps1,  eps1 },
123      { -br, -br,  br,  -1.0, -eps1,  eps1 },
124      { -br, -br, -br,  -1.0, -eps1, -eps1 },
125
126      /* +Y side */
127      {  br,  br, -br,   eps1, 1.0, -eps1 },
128      {  br,  br,  br,   eps1, 1.0,  eps1 },
129      { -br,  br,  br,  -eps1, 1.0,  eps1 },
130      { -br,  br, -br,  -eps1, 1.0, -eps1 },
131
132      /* -Y side */
133      { -br, -br, -br,  -eps1, -1.0, -eps1 },
134      { -br, -br,  br,  -eps1, -1.0,  eps1 },
135      {  br, -br,  br,   eps1, -1.0,  eps1 },
136      {  br, -br, -br,   eps1, -1.0, -eps1 },
137
138      /* +Z side */
139      {  br, -br, br,   eps1, -eps1, 1.0 },
140      { -br, -br, br,  -eps1, -eps1, 1.0 },
141      { -br,  br, br,  -eps1,  eps1, 1.0 },
142      {  br,  br, br,   eps1,  eps1, 1.0 },
143
144      /* -Z side */
145      {  br,  br, -br,   eps1,  eps1, -1.0 },
146      { -br,  br, -br,  -eps1,  eps1, -1.0 },
147      { -br, -br, -br,  -eps1, -eps1, -1.0 },
148      {  br, -br, -br,   eps1, -eps1, -1.0 },
149   };
150
151   static GLuint vbo = 0;
152
153   if (!vbo ) {
154      glGenBuffersARB(1, &vbo);
155      glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
156      glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
157                      GL_STATIC_DRAW_ARB);
158   }
159   else {
160      glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
161   }
162
163   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
164
165   glVertexPointer(3, GL_FLOAT, sizeof(struct vertex),
166                   (void *) offsetof(struct vertex, x));
167   glTexCoordPointer(3, GL_FLOAT, sizeof(struct vertex),
168                     (void *) offsetof(struct vertex, s));
169   glEnableClientState(GL_VERTEX_ARRAY);
170   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
171
172   glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
173   glEnable(GL_TEXTURE_CUBE_MAP);
174
175   glDisable(GL_BLEND);
176
177   glDrawArrays(GL_QUADS, 0, 24);
178
179   glDisable(GL_TEXTURE_CUBE_MAP);
180
181   glDisableClientState(GL_VERTEX_ARRAY);
182   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
183
184   glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
185}
186
187